Skip to content
This repository was archived by the owner on May 19, 2018. It is now read-only.
/ babylon Public archive
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -117,3 +117,4 @@ require("babylon").parse("code", {
- `asyncGenerators`
- `functionBind`
- `functionSent`
- `dynamicImport`
13 changes: 12 additions & 1 deletion ast/spec.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ These are the core Babylon AST node types.
- [DirectiveLiteral](#directiveliteral)
- [Expressions](#expressions)
- [Super](#super)
- [Import](#import)
- [ThisExpression](#thisexpression)
- [ArrowFunctionExpression](#arrowfunctionexpression)
- [YieldExpression](#yieldexpression)
Expand Down Expand Up @@ -568,6 +569,16 @@ interface Super <: Node {

A `super` pseudo-expression.

## Import

```js
interface Import <: Node {
type: "Import";
}
```

A `import` pseudo-expression.

## ThisExpression

```js
Expand Down Expand Up @@ -870,7 +881,7 @@ A conditional expression, i.e., a ternary `?`/`:` expression.
```js
interface CallExpression <: Expression {
type: "CallExpression";
callee: Expression | Super;
callee: Expression | Super | Import;
arguments: [ Expression | SpreadElement ];
}
```
Expand Down
13 changes: 13 additions & 0 deletions src/parser/expression.js
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,9 @@ pp.parseSubscripts = function (base, startPos, startLoc, noCalls) {
let node = this.startNodeAt(startPos, startLoc);
node.callee = base;
node.arguments = this.parseCallExpressionArguments(tt.parenR, possibleAsync);
if (node.callee.type === "Import" && node.arguments.length !== 1) {
this.raise(node.start, "import() requires exactly one argument");
}
base = this.finishNode(node, "CallExpression");

if (possibleAsync && this.shouldParseAsyncArrow()) {
Expand Down Expand Up @@ -385,6 +388,16 @@ pp.parseExprAtom = function (refShorthandDefaultPos) {
}
return this.finishNode(node, "Super");

case tt._import:
if (!this.hasPlugin("dynamicImport")) this.unexpected();

node = this.startNode();
this.next();
if (!this.match(tt.parenL)) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like this case can never be hit, because the parser runs through statements first, and would throw unexpected trying to parse the import function.

Should I remove it knowing that, or keep it for safety?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wondered that too, good question, curious to see what others think.

Copy link
Member

@danez danez Oct 10, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also codecoverage says we never hit this block, but as we do the same for super maybe be consistent and leave it here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I figured out that this can be hit if you do something that parses as an expression first. For example, inside of a function return import.fails() hits this case.

I've added a test for this case to prevent any regressions and to bump the code coverage.

this.unexpected();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we can do a

this.unexpected(null, `Unexpected token, expected (`);

https://github.com/babel/babylon/pull/150/files#diff-51a873a9697282bed0c15722a6ccf4e6R77

not sure if you can just use this.expect instead

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually we can use #172

to do this.unexpected(null, tt.parenL);

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we add this to #172 after this lands?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in #177.

}
return this.finishNode(node, "Import");

case tt._this:
node = this.startNode();
this.next();
Expand Down
2 changes: 2 additions & 0 deletions src/parser/statement.js
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,8 @@ pp.parseStatement = function (declaration, topLevel) {
case tt.semi: return this.parseEmptyStatement(node);
case tt._export:
case tt._import:
if (this.hasPlugin("dynamicImport") && this.lookahead().type === tt.parenL) break;

if (!this.options.allowImportExportEverywhere) {
if (!topLevel) {
this.raise(this.state.start, "'import' and 'export' may only appear at the top level");
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
function failsParse() {
return import.then();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"throws": "Unexpected token (2:15)"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
function loadImport(file) {
return import(`test/${file}.js`);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,229 @@
{
"type": "File",
"start": 0,
"end": 65,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 3,
"column": 1
}
},
"program": {
"type": "Program",
"start": 0,
"end": 65,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 3,
"column": 1
}
},
"sourceType": "script",
"body": [
{
"type": "FunctionDeclaration",
"start": 0,
"end": 65,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 3,
"column": 1
}
},
"id": {
"type": "Identifier",
"start": 9,
"end": 19,
"loc": {
"start": {
"line": 1,
"column": 9
},
"end": {
"line": 1,
"column": 19
},
"identifierName": "loadImport"
},
"name": "loadImport"
},
"generator": false,
"expression": false,
"async": false,
"params": [
{
"type": "Identifier",
"start": 20,
"end": 24,
"loc": {
"start": {
"line": 1,
"column": 20
},
"end": {
"line": 1,
"column": 24
},
"identifierName": "file"
},
"name": "file"
}
],
"body": {
"type": "BlockStatement",
"start": 26,
"end": 65,
"loc": {
"start": {
"line": 1,
"column": 26
},
"end": {
"line": 3,
"column": 1
}
},
"body": [
{
"type": "ReturnStatement",
"start": 30,
"end": 63,
"loc": {
"start": {
"line": 2,
"column": 2
},
"end": {
"line": 2,
"column": 35
}
},
"argument": {
"type": "CallExpression",
"start": 37,
"end": 62,
"loc": {
"start": {
"line": 2,
"column": 9
},
"end": {
"line": 2,
"column": 34
}
},
"callee": {
"type": "Import",
"start": 37,
"end": 43,
"loc": {
"start": {
"line": 2,
"column": 9
},
"end": {
"line": 2,
"column": 15
}
}
},
"arguments": [
{
"type": "TemplateLiteral",
"start": 44,
"end": 61,
"loc": {
"start": {
"line": 2,
"column": 16
},
"end": {
"line": 2,
"column": 33
}
},
"expressions": [
{
"type": "Identifier",
"start": 52,
"end": 56,
"loc": {
"start": {
"line": 2,
"column": 24
},
"end": {
"line": 2,
"column": 28
},
"identifierName": "file"
},
"name": "file"
}
],
"quasis": [
{
"type": "TemplateElement",
"start": 45,
"end": 50,
"loc": {
"start": {
"line": 2,
"column": 17
},
"end": {
"line": 2,
"column": 22
}
},
"value": {
"raw": "test/",
"cooked": "test/"
},
"tail": false
},
{
"type": "TemplateElement",
"start": 57,
"end": 60,
"loc": {
"start": {
"line": 2,
"column": 29
},
"end": {
"line": 2,
"column": 32
}
},
"value": {
"raw": ".js",
"cooked": ".js"
},
"tail": true
}
]
}
]
}
}
],
"directives": []
}
}
],
"directives": []
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
import('hello', 'world');
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"throws": "import() requires exactly one argument (1:0)"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
import();
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"throws": "import() requires exactly one argument (1:0)"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
import('test.js');
Loading