Skip to content

Commit

Permalink
Fix "sourceType: unambiguous" with TLA
Browse files Browse the repository at this point in the history
  • Loading branch information
nicolo-ribaudo committed Oct 18, 2019
1 parent 9a16a3e commit c9112da
Show file tree
Hide file tree
Showing 12 changed files with 321 additions and 5 deletions.
26 changes: 21 additions & 5 deletions packages/babel-parser/src/index.js
Expand Up @@ -25,15 +25,31 @@ export function parse(input: string, options?: Options): File {
const parser = getParser(options, input);
const ast = parser.parse();

// Rather than try to parse as a script first, we opt to parse as a module and convert back
// to a script where possible to avoid having to do a full re-parse of the input content.
if (!parser.sawUnambiguousESM) ast.program.sourceType = "script";
return ast;
if (parser.sawUnambiguousESM) {
return ast;
}

if (!parser.ambiguousScriptDifferentAst) {
ast.program.sourceType = "script";
return ast;
}

// Top level await introduces code which can be both a valid script and
// a valid module, but which produces different ASTs:
// await
// 0
// can be parser either as an AwaitExpression, or as two ExpressionStatements.
try {
options.sourceType = "script";
return getParser(options, input).parse();
} catch {
return ast;
}
} catch (moduleError) {
try {
options.sourceType = "script";
return getParser(options, input).parse();
} catch (scriptError) {}
} catch {}

throw moduleError;
}
Expand Down
1 change: 1 addition & 0 deletions packages/babel-parser/src/parser/base.js
Expand Up @@ -13,6 +13,7 @@ export default class BaseParser {
plugins: PluginsMap;
filename: ?string;
sawUnambiguousESM: boolean = false;
ambiguousScriptDifferentAst: boolean = false;

// Initialized by Tokenizer
state: State;
Expand Down
10 changes: 10 additions & 0 deletions packages/babel-parser/src/parser/expression.js
Expand Up @@ -141,6 +141,7 @@ export default class ExpressionParser extends LValParser {
this.toReferencedList(node.expressions);
return this.finishNode(node, "SequenceExpression");
}

return expr;
}

Expand Down Expand Up @@ -2235,9 +2236,18 @@ export default class ExpressionParser extends LValParser {
);
}

if (!this.scope.inFunction && !this.options.allowAwaitOutsideFunction) {
if (this.hasPrecedingLineBreak()) {
this.ambiguousScriptDifferentAst = true;
} else {
this.sawUnambiguousESM = true;
}
}

if (!this.state.soloAwait) {
node.argument = this.parseMaybeUnary();
}

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

Expand Down
@@ -0,0 +1 @@
await 0
@@ -0,0 +1,5 @@
{
"plugins": ["topLevelAwait"],
"sourceType": "unambiguous",
"allowAwaitOutsideFunction": true
}
@@ -0,0 +1,85 @@
{
"type": "File",
"start": 0,
"end": 7,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 7
}
},
"program": {
"type": "Program",
"start": 0,
"end": 7,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 7
}
},
"sourceType": "script",
"interpreter": null,
"body": [
{
"type": "ExpressionStatement",
"start": 0,
"end": 7,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 7
}
},
"expression": {
"type": "AwaitExpression",
"start": 0,
"end": 7,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 7
}
},
"argument": {
"type": "NumericLiteral",
"start": 6,
"end": 7,
"loc": {
"start": {
"line": 1,
"column": 6
},
"end": {
"line": 1,
"column": 7
}
},
"extra": {
"rawValue": 0,
"raw": "0"
},
"value": 0
}
}
}
],
"directives": []
}
}
@@ -0,0 +1,2 @@
await
0
@@ -0,0 +1,4 @@
{
"plugins": ["topLevelAwait"],
"sourceType": "unambiguous"
}
@@ -0,0 +1,102 @@
{
"type": "File",
"start": 0,
"end": 7,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 2,
"column": 1
}
},
"program": {
"type": "Program",
"start": 0,
"end": 7,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 2,
"column": 1
}
},
"sourceType": "script",
"interpreter": null,
"body": [
{
"type": "ExpressionStatement",
"start": 0,
"end": 5,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 5
}
},
"expression": {
"type": "Identifier",
"start": 0,
"end": 5,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 5
},
"identifierName": "await"
},
"name": "await"
}
},
{
"type": "ExpressionStatement",
"start": 6,
"end": 7,
"loc": {
"start": {
"line": 2,
"column": 0
},
"end": {
"line": 2,
"column": 1
}
},
"expression": {
"type": "NumericLiteral",
"start": 6,
"end": 7,
"loc": {
"start": {
"line": 2,
"column": 0
},
"end": {
"line": 2,
"column": 1
}
},
"extra": {
"rawValue": 0,
"raw": "0"
},
"value": 0
}
}
],
"directives": []
}
}
@@ -0,0 +1 @@
await 0
@@ -0,0 +1,4 @@
{
"plugins": ["topLevelAwait"],
"sourceType": "unambiguous"
}
@@ -0,0 +1,85 @@
{
"type": "File",
"start": 0,
"end": 7,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 7
}
},
"program": {
"type": "Program",
"start": 0,
"end": 7,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 7
}
},
"sourceType": "module",
"interpreter": null,
"body": [
{
"type": "ExpressionStatement",
"start": 0,
"end": 7,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 7
}
},
"expression": {
"type": "AwaitExpression",
"start": 0,
"end": 7,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 7
}
},
"argument": {
"type": "NumericLiteral",
"start": 6,
"end": 7,
"loc": {
"start": {
"line": 1,
"column": 6
},
"end": {
"line": 1,
"column": 7
}
},
"extra": {
"rawValue": 0,
"raw": "0"
},
"value": 0
}
}
}
],
"directives": []
}
}

0 comments on commit c9112da

Please sign in to comment.