From 84f6abcaa8dcbe8fd3280f3db7c184ea757c0f89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hu=C3=A1ng=20J=C3=B9nli=C3=A0ng?= Date: Thu, 4 Jun 2020 17:17:08 -0400 Subject: [PATCH 1/6] add nextTokenStartSince method --- packages/babel-parser/src/tokenizer/index.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/packages/babel-parser/src/tokenizer/index.js b/packages/babel-parser/src/tokenizer/index.js index a6e44c027d97..55cda33a6ed5 100644 --- a/packages/babel-parser/src/tokenizer/index.js +++ b/packages/babel-parser/src/tokenizer/index.js @@ -190,11 +190,14 @@ export default class Tokenizer extends ParserErrors { } nextTokenStart(): number { - const thisTokEnd = this.state.pos; - skipWhiteSpace.lastIndex = thisTokEnd; + return this.nextTokenStartSince(this.state.pos); + } + + nextTokenStartSince(pos: number): number { + skipWhiteSpace.lastIndex = pos; const skip = skipWhiteSpace.exec(this.input); // $FlowIgnore: The skipWhiteSpace ensures to match any string - return thisTokEnd + skip[0].length; + return pos + skip[0].length; } lookaheadCharCode(): number { From 8d87929a70d5a66a47f934c694901f459d5cb9b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hu=C3=A1ng=20J=C3=B9nli=C3=A0ng?= Date: Thu, 4 Jun 2020 17:18:28 -0400 Subject: [PATCH 2/6] fix: properly parse `export default from` --- packages/babel-parser/src/parser/statement.js | 20 +++++++++-- .../babel-parser/src/plugins/placeholders.js | 15 ++++++++ .../input.js | 1 + .../output.json | 33 +++++++++++++++++ .../input.js | 1 + .../output.json | 36 +++++++++++++++++++ .../input.js | 1 + .../output.json | 22 ++++++++++++ .../export-extensions/default-from/input.js | 1 + .../default-from/options.json | 4 +++ .../default-from/output.json | 22 ++++++++++++ 11 files changed, 153 insertions(+), 3 deletions(-) create mode 100644 packages/babel-parser/test/fixtures/esprima/es2015-export-declaration/export-default-from-as-identifier-2/input.js create mode 100644 packages/babel-parser/test/fixtures/esprima/es2015-export-declaration/export-default-from-as-identifier-2/output.json create mode 100644 packages/babel-parser/test/fixtures/esprima/es2015-export-declaration/export-default-from-as-identifier-3/input.js create mode 100644 packages/babel-parser/test/fixtures/esprima/es2015-export-declaration/export-default-from-as-identifier-3/output.json create mode 100644 packages/babel-parser/test/fixtures/esprima/es2015-export-declaration/export-default-from-as-identifier/input.js create mode 100644 packages/babel-parser/test/fixtures/esprima/es2015-export-declaration/export-default-from-as-identifier/output.json create mode 100644 packages/babel-parser/test/fixtures/experimental/export-extensions/default-from/input.js create mode 100644 packages/babel-parser/test/fixtures/experimental/export-extensions/default-from/options.json create mode 100644 packages/babel-parser/test/fixtures/experimental/export-extensions/default-from/output.json diff --git a/packages/babel-parser/src/parser/statement.js b/packages/babel-parser/src/parser/statement.js index 521d13c9fb63..d99ff88d9cd1 100644 --- a/packages/babel-parser/src/parser/statement.js +++ b/packages/babel-parser/src/parser/statement.js @@ -1857,10 +1857,24 @@ export default class StatementParser extends ExpressionParser { } const next = this.nextTokenStart(); - return ( + const hasFrom = this.isUnparsedContextual(next, "from"); + if ( this.input.charCodeAt(next) === charCodes.comma || - this.isUnparsedContextual(next, "from") - ); + (this.match(tt.name) && hasFrom) + ) { + return true; + } + // lookahead again when `export default from` is seen + if (this.match(tt._default) && hasFrom) { + const nextAfterFrom = this.input.charCodeAt( + this.nextTokenStartSince(next + 4), + ); + return ( + nextAfterFrom === charCodes.quotationMark || + nextAfterFrom === charCodes.apostrophe + ); + } + return false; } parseExportFrom(node: N.ExportNamedDeclaration, expect?: boolean): void { diff --git a/packages/babel-parser/src/plugins/placeholders.js b/packages/babel-parser/src/plugins/placeholders.js index 646494d1c5fe..ae19dc4a057a 100644 --- a/packages/babel-parser/src/plugins/placeholders.js +++ b/packages/babel-parser/src/plugins/placeholders.js @@ -251,6 +251,21 @@ export default (superClass: Class): Class => return super.parseExport(node); } + isExportDefaultSpecifier(): boolean { + if (this.match(tt._default)) { + const next = this.nextTokenStart(); + if (this.isUnparsedContextual(next, "from")) { + if ( + this.input.substr(this.nextTokenStartSince(next + 4), 2) === + tt.placeholder.label + ) { + return true; + } + } + } + return super.isExportDefaultSpecifier(); + } + maybeParseExportDefaultSpecifier(node: N.Node): boolean { if (node.specifiers && node.specifiers.length > 0) { // "export %%NAME%%" has already been parsed by #parseExport. diff --git a/packages/babel-parser/test/fixtures/esprima/es2015-export-declaration/export-default-from-as-identifier-2/input.js b/packages/babel-parser/test/fixtures/esprima/es2015-export-declaration/export-default-from-as-identifier-2/input.js new file mode 100644 index 000000000000..6539d5765f62 --- /dev/null +++ b/packages/babel-parser/test/fixtures/esprima/es2015-export-declaration/export-default-from-as-identifier-2/input.js @@ -0,0 +1 @@ +export default from (bar); diff --git a/packages/babel-parser/test/fixtures/esprima/es2015-export-declaration/export-default-from-as-identifier-2/output.json b/packages/babel-parser/test/fixtures/esprima/es2015-export-declaration/export-default-from-as-identifier-2/output.json new file mode 100644 index 000000000000..e873e886ca8d --- /dev/null +++ b/packages/babel-parser/test/fixtures/esprima/es2015-export-declaration/export-default-from-as-identifier-2/output.json @@ -0,0 +1,33 @@ +{ + "type": "File", + "start":0,"end":26,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":26}}, + "program": { + "type": "Program", + "start":0,"end":26,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":26}}, + "sourceType": "module", + "interpreter": null, + "body": [ + { + "type": "ExportDefaultDeclaration", + "start":0,"end":26,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":26}}, + "declaration": { + "type": "CallExpression", + "start":15,"end":25,"loc":{"start":{"line":1,"column":15},"end":{"line":1,"column":25}}, + "callee": { + "type": "Identifier", + "start":15,"end":19,"loc":{"start":{"line":1,"column":15},"end":{"line":1,"column":19},"identifierName":"from"}, + "name": "from" + }, + "arguments": [ + { + "type": "Identifier", + "start":21,"end":24,"loc":{"start":{"line":1,"column":21},"end":{"line":1,"column":24},"identifierName":"bar"}, + "name": "bar" + } + ] + } + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/esprima/es2015-export-declaration/export-default-from-as-identifier-3/input.js b/packages/babel-parser/test/fixtures/esprima/es2015-export-declaration/export-default-from-as-identifier-3/input.js new file mode 100644 index 000000000000..7690fcc07197 --- /dev/null +++ b/packages/babel-parser/test/fixtures/esprima/es2015-export-declaration/export-default-from-as-identifier-3/input.js @@ -0,0 +1 @@ +export default from ?? 42; diff --git a/packages/babel-parser/test/fixtures/esprima/es2015-export-declaration/export-default-from-as-identifier-3/output.json b/packages/babel-parser/test/fixtures/esprima/es2015-export-declaration/export-default-from-as-identifier-3/output.json new file mode 100644 index 000000000000..6af2532e8508 --- /dev/null +++ b/packages/babel-parser/test/fixtures/esprima/es2015-export-declaration/export-default-from-as-identifier-3/output.json @@ -0,0 +1,36 @@ +{ + "type": "File", + "start":0,"end":26,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":26}}, + "program": { + "type": "Program", + "start":0,"end":26,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":26}}, + "sourceType": "module", + "interpreter": null, + "body": [ + { + "type": "ExportDefaultDeclaration", + "start":0,"end":26,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":26}}, + "declaration": { + "type": "LogicalExpression", + "start":15,"end":25,"loc":{"start":{"line":1,"column":15},"end":{"line":1,"column":25}}, + "left": { + "type": "Identifier", + "start":15,"end":19,"loc":{"start":{"line":1,"column":15},"end":{"line":1,"column":19},"identifierName":"from"}, + "name": "from" + }, + "operator": "??", + "right": { + "type": "NumericLiteral", + "start":23,"end":25,"loc":{"start":{"line":1,"column":23},"end":{"line":1,"column":25}}, + "extra": { + "rawValue": 42, + "raw": "42" + }, + "value": 42 + } + } + } + ], + "directives": [] + } +} diff --git a/packages/babel-parser/test/fixtures/esprima/es2015-export-declaration/export-default-from-as-identifier/input.js b/packages/babel-parser/test/fixtures/esprima/es2015-export-declaration/export-default-from-as-identifier/input.js new file mode 100644 index 000000000000..79719db06e63 --- /dev/null +++ b/packages/babel-parser/test/fixtures/esprima/es2015-export-declaration/export-default-from-as-identifier/input.js @@ -0,0 +1 @@ +export default from; diff --git a/packages/babel-parser/test/fixtures/esprima/es2015-export-declaration/export-default-from-as-identifier/output.json b/packages/babel-parser/test/fixtures/esprima/es2015-export-declaration/export-default-from-as-identifier/output.json new file mode 100644 index 000000000000..efa51a6eeef9 --- /dev/null +++ b/packages/babel-parser/test/fixtures/esprima/es2015-export-declaration/export-default-from-as-identifier/output.json @@ -0,0 +1,22 @@ +{ + "type": "File", + "start":0,"end":20,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":20}}, + "program": { + "type": "Program", + "start":0,"end":20,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":20}}, + "sourceType": "module", + "interpreter": null, + "body": [ + { + "type": "ExportDefaultDeclaration", + "start":0,"end":20,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":20}}, + "declaration": { + "type": "Identifier", + "start":15,"end":19,"loc":{"start":{"line":1,"column":15},"end":{"line":1,"column":19},"identifierName":"from"}, + "name": "from" + } + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/experimental/export-extensions/default-from/input.js b/packages/babel-parser/test/fixtures/experimental/export-extensions/default-from/input.js new file mode 100644 index 000000000000..79719db06e63 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/export-extensions/default-from/input.js @@ -0,0 +1 @@ +export default from; diff --git a/packages/babel-parser/test/fixtures/experimental/export-extensions/default-from/options.json b/packages/babel-parser/test/fixtures/experimental/export-extensions/default-from/options.json new file mode 100644 index 000000000000..fb17f33a28b5 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/export-extensions/default-from/options.json @@ -0,0 +1,4 @@ +{ + "plugins": ["exportDefaultFrom"], + "sourceType": "module" +} diff --git a/packages/babel-parser/test/fixtures/experimental/export-extensions/default-from/output.json b/packages/babel-parser/test/fixtures/experimental/export-extensions/default-from/output.json new file mode 100644 index 000000000000..efa51a6eeef9 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/export-extensions/default-from/output.json @@ -0,0 +1,22 @@ +{ + "type": "File", + "start":0,"end":20,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":20}}, + "program": { + "type": "Program", + "start":0,"end":20,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":20}}, + "sourceType": "module", + "interpreter": null, + "body": [ + { + "type": "ExportDefaultDeclaration", + "start":0,"end":20,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":20}}, + "declaration": { + "type": "Identifier", + "start":15,"end":19,"loc":{"start":{"line":1,"column":15},"end":{"line":1,"column":19},"identifierName":"from"}, + "name": "from" + } + } + ], + "directives": [] + } +} \ No newline at end of file From ce6e6dbace616c7240de908892c6a03531d254b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hu=C3=A1ng=20J=C3=B9nli=C3=A0ng?= Date: Thu, 4 Jun 2020 17:35:13 -0400 Subject: [PATCH 3/6] disallow `from` as identifier after `export default` --- .../babel-parser/src/parser/error-message.js | 2 + packages/babel-parser/src/parser/statement.js | 11 ++++++ .../default-default-asi/input.js | 2 + .../default-default-asi/options.json | 4 ++ .../default-default-asi/output.json | 37 +++++++++++++++++++ .../input.js | 0 .../options.json | 0 .../output.json | 3 ++ 8 files changed, 59 insertions(+) create mode 100644 packages/babel-parser/test/fixtures/experimental/export-extensions/default-default-asi/input.js create mode 100644 packages/babel-parser/test/fixtures/experimental/export-extensions/default-default-asi/options.json create mode 100644 packages/babel-parser/test/fixtures/experimental/export-extensions/default-default-asi/output.json rename packages/babel-parser/test/fixtures/experimental/export-extensions/{default-from => invalid-default-from-identifier}/input.js (100%) rename packages/babel-parser/test/fixtures/experimental/export-extensions/{default-from => invalid-default-from-identifier}/options.json (100%) rename packages/babel-parser/test/fixtures/experimental/export-extensions/{default-from => invalid-default-from-identifier}/output.json (86%) diff --git a/packages/babel-parser/src/parser/error-message.js b/packages/babel-parser/src/parser/error-message.js index 033fe814e87f..430c44289213 100644 --- a/packages/babel-parser/src/parser/error-message.js +++ b/packages/babel-parser/src/parser/error-message.js @@ -42,6 +42,8 @@ export const ErrorMessages = Object.freeze({ DuplicateRegExpFlags: "Duplicate regular expression flag", ElementAfterRest: "Rest element must be last element", EscapedCharNotAnIdentifier: "Invalid Unicode escape", + ExportDefaultFromAsIdentifier: + "'from' is not allowed as an identifier after 'export default'", ForInOfLoopInitializer: "%0 loop variable declaration may not have an initializer", GeneratorInSingleStatementContext: diff --git a/packages/babel-parser/src/parser/statement.js b/packages/babel-parser/src/parser/statement.js index d99ff88d9cd1..8ff7643dd788 100644 --- a/packages/babel-parser/src/parser/statement.js +++ b/packages/babel-parser/src/parser/statement.js @@ -1925,6 +1925,17 @@ export default class StatementParser extends ExpressionParser { if (isDefault) { // Default exports this.checkDuplicateExports(node, "default"); + if (this.hasPlugin("exportDefaultFrom")) { + const declaration = ((node: any): N.ExportDefaultDeclaration) + .declaration; + if ( + declaration.type === "Identifier" && + declaration.name === "from" && + declaration.end - declaration.start === 4 // does not contain escape + ) { + this.raise(declaration.start, Errors.ExportDefaultFromAsIdentifier); + } + } } else if (node.specifiers && node.specifiers.length) { // Named exports for (const specifier of node.specifiers) { diff --git a/packages/babel-parser/test/fixtures/experimental/export-extensions/default-default-asi/input.js b/packages/babel-parser/test/fixtures/experimental/export-extensions/default-default-asi/input.js new file mode 100644 index 000000000000..3b8c1ebc1ca0 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/export-extensions/default-default-asi/input.js @@ -0,0 +1,2 @@ +export default from +"bar"; diff --git a/packages/babel-parser/test/fixtures/experimental/export-extensions/default-default-asi/options.json b/packages/babel-parser/test/fixtures/experimental/export-extensions/default-default-asi/options.json new file mode 100644 index 000000000000..164d90422fb2 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/export-extensions/default-default-asi/options.json @@ -0,0 +1,4 @@ +{ + "sourceType": "module", + "plugins": ["exportDefaultFrom"] +} diff --git a/packages/babel-parser/test/fixtures/experimental/export-extensions/default-default-asi/output.json b/packages/babel-parser/test/fixtures/experimental/export-extensions/default-default-asi/output.json new file mode 100644 index 000000000000..de0d1cce86c4 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/export-extensions/default-default-asi/output.json @@ -0,0 +1,37 @@ +{ + "type": "File", + "start":0,"end":26,"loc":{"start":{"line":1,"column":0},"end":{"line":2,"column":6}}, + "program": { + "type": "Program", + "start":0,"end":26,"loc":{"start":{"line":1,"column":0},"end":{"line":2,"column":6}}, + "sourceType": "module", + "interpreter": null, + "body": [ + { + "type": "ExportNamedDeclaration", + "start":0,"end":26,"loc":{"start":{"line":1,"column":0},"end":{"line":2,"column":6}}, + "specifiers": [ + { + "type": "ExportDefaultSpecifier", + "start":7,"end":14,"loc":{"start":{"line":1,"column":7},"end":{"line":1,"column":14}}, + "exported": { + "type": "Identifier", + "start":7,"end":14,"loc":{"start":{"line":1,"column":7},"end":{"line":1,"column":14},"identifierName":"default"}, + "name": "default" + } + } + ], + "source": { + "type": "StringLiteral", + "start":20,"end":25,"loc":{"start":{"line":2,"column":0},"end":{"line":2,"column":5}}, + "extra": { + "rawValue": "bar", + "raw": "\"bar\"" + }, + "value": "bar" + } + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/experimental/export-extensions/default-from/input.js b/packages/babel-parser/test/fixtures/experimental/export-extensions/invalid-default-from-identifier/input.js similarity index 100% rename from packages/babel-parser/test/fixtures/experimental/export-extensions/default-from/input.js rename to packages/babel-parser/test/fixtures/experimental/export-extensions/invalid-default-from-identifier/input.js diff --git a/packages/babel-parser/test/fixtures/experimental/export-extensions/default-from/options.json b/packages/babel-parser/test/fixtures/experimental/export-extensions/invalid-default-from-identifier/options.json similarity index 100% rename from packages/babel-parser/test/fixtures/experimental/export-extensions/default-from/options.json rename to packages/babel-parser/test/fixtures/experimental/export-extensions/invalid-default-from-identifier/options.json diff --git a/packages/babel-parser/test/fixtures/experimental/export-extensions/default-from/output.json b/packages/babel-parser/test/fixtures/experimental/export-extensions/invalid-default-from-identifier/output.json similarity index 86% rename from packages/babel-parser/test/fixtures/experimental/export-extensions/default-from/output.json rename to packages/babel-parser/test/fixtures/experimental/export-extensions/invalid-default-from-identifier/output.json index efa51a6eeef9..cc0e24e848fe 100644 --- a/packages/babel-parser/test/fixtures/experimental/export-extensions/default-from/output.json +++ b/packages/babel-parser/test/fixtures/experimental/export-extensions/invalid-default-from-identifier/output.json @@ -1,6 +1,9 @@ { "type": "File", "start":0,"end":20,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":20}}, + "errors": [ + "SyntaxError: 'from' is not allowed as an identifier after 'export default' (1:15)" + ], "program": { "type": "Program", "start":0,"end":20,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":20}}, From f452154b660561096a56c362d777e1c363a4f9d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hu=C3=A1ng=20J=C3=B9nli=C3=A0ng?= Date: Thu, 4 Jun 2020 18:14:51 -0400 Subject: [PATCH 4/6] add a new test on valid escaped from as identifier --- .../default-from-identifier-escaped/input.js | 1 + .../options.json | 4 ++++ .../output.json | 22 +++++++++++++++++++ 3 files changed, 27 insertions(+) create mode 100644 packages/babel-parser/test/fixtures/experimental/export-extensions/default-from-identifier-escaped/input.js create mode 100644 packages/babel-parser/test/fixtures/experimental/export-extensions/default-from-identifier-escaped/options.json create mode 100644 packages/babel-parser/test/fixtures/experimental/export-extensions/default-from-identifier-escaped/output.json diff --git a/packages/babel-parser/test/fixtures/experimental/export-extensions/default-from-identifier-escaped/input.js b/packages/babel-parser/test/fixtures/experimental/export-extensions/default-from-identifier-escaped/input.js new file mode 100644 index 000000000000..a202ed0db383 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/export-extensions/default-from-identifier-escaped/input.js @@ -0,0 +1 @@ +export default \u{66}rom; diff --git a/packages/babel-parser/test/fixtures/experimental/export-extensions/default-from-identifier-escaped/options.json b/packages/babel-parser/test/fixtures/experimental/export-extensions/default-from-identifier-escaped/options.json new file mode 100644 index 000000000000..fb17f33a28b5 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/export-extensions/default-from-identifier-escaped/options.json @@ -0,0 +1,4 @@ +{ + "plugins": ["exportDefaultFrom"], + "sourceType": "module" +} diff --git a/packages/babel-parser/test/fixtures/experimental/export-extensions/default-from-identifier-escaped/output.json b/packages/babel-parser/test/fixtures/experimental/export-extensions/default-from-identifier-escaped/output.json new file mode 100644 index 000000000000..622e63e1a1fd --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/export-extensions/default-from-identifier-escaped/output.json @@ -0,0 +1,22 @@ +{ + "type": "File", + "start":0,"end":25,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":25}}, + "program": { + "type": "Program", + "start":0,"end":25,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":25}}, + "sourceType": "module", + "interpreter": null, + "body": [ + { + "type": "ExportDefaultDeclaration", + "start":0,"end":25,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":25}}, + "declaration": { + "type": "Identifier", + "start":15,"end":24,"loc":{"start":{"line":1,"column":15},"end":{"line":1,"column":24},"identifierName":"from"}, + "name": "from" + } + } + ], + "directives": [] + } +} \ No newline at end of file From 44a34863dddced0781ac1665b3802cb2c9b7ba28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hu=C3=A1ng=20J=C3=B9nli=C3=A0ng?= Date: Thu, 4 Jun 2020 18:32:13 -0400 Subject: [PATCH 5/6] address review comments --- packages/babel-parser/src/parser/statement.js | 3 ++- .../input.js | 1 + .../options.json | 4 +++ .../output.json | 26 +++++++++++++++++++ 4 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 packages/babel-parser/test/fixtures/experimental/export-extensions/default-from-identifier-parenthesized/input.js create mode 100644 packages/babel-parser/test/fixtures/experimental/export-extensions/default-from-identifier-parenthesized/options.json create mode 100644 packages/babel-parser/test/fixtures/experimental/export-extensions/default-from-identifier-parenthesized/output.json diff --git a/packages/babel-parser/src/parser/statement.js b/packages/babel-parser/src/parser/statement.js index 8ff7643dd788..e201cfcd36cc 100644 --- a/packages/babel-parser/src/parser/statement.js +++ b/packages/babel-parser/src/parser/statement.js @@ -1931,7 +1931,8 @@ export default class StatementParser extends ExpressionParser { if ( declaration.type === "Identifier" && declaration.name === "from" && - declaration.end - declaration.start === 4 // does not contain escape + declaration.end - declaration.start === 4 && // does not contain escape + !declaration.extra?.parenthesized ) { this.raise(declaration.start, Errors.ExportDefaultFromAsIdentifier); } diff --git a/packages/babel-parser/test/fixtures/experimental/export-extensions/default-from-identifier-parenthesized/input.js b/packages/babel-parser/test/fixtures/experimental/export-extensions/default-from-identifier-parenthesized/input.js new file mode 100644 index 000000000000..74c7cb934c5d --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/export-extensions/default-from-identifier-parenthesized/input.js @@ -0,0 +1 @@ +export default (from); diff --git a/packages/babel-parser/test/fixtures/experimental/export-extensions/default-from-identifier-parenthesized/options.json b/packages/babel-parser/test/fixtures/experimental/export-extensions/default-from-identifier-parenthesized/options.json new file mode 100644 index 000000000000..fb17f33a28b5 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/export-extensions/default-from-identifier-parenthesized/options.json @@ -0,0 +1,4 @@ +{ + "plugins": ["exportDefaultFrom"], + "sourceType": "module" +} diff --git a/packages/babel-parser/test/fixtures/experimental/export-extensions/default-from-identifier-parenthesized/output.json b/packages/babel-parser/test/fixtures/experimental/export-extensions/default-from-identifier-parenthesized/output.json new file mode 100644 index 000000000000..215a4df47bb6 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/export-extensions/default-from-identifier-parenthesized/output.json @@ -0,0 +1,26 @@ +{ + "type": "File", + "start":0,"end":22,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":22}}, + "program": { + "type": "Program", + "start":0,"end":22,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":22}}, + "sourceType": "module", + "interpreter": null, + "body": [ + { + "type": "ExportDefaultDeclaration", + "start":0,"end":22,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":22}}, + "declaration": { + "type": "Identifier", + "start":16,"end":20,"loc":{"start":{"line":1,"column":16},"end":{"line":1,"column":20},"identifierName":"from"}, + "name": "from", + "extra": { + "parenthesized": true, + "parenStart": 15 + } + } + } + ], + "directives": [] + } +} \ No newline at end of file From a6138fbb39e41ab094aeba3dd91745e84734c80a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hu=C3=A1ng=20J=C3=B9nli=C3=A0ng?= Date: Thu, 4 Jun 2020 19:46:29 -0400 Subject: [PATCH 6/6] Update packages/babel-parser/src/plugins/placeholders.js MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Nicolò Ribaudo --- packages/babel-parser/src/plugins/placeholders.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/babel-parser/src/plugins/placeholders.js b/packages/babel-parser/src/plugins/placeholders.js index ae19dc4a057a..69d961e3e6c9 100644 --- a/packages/babel-parser/src/plugins/placeholders.js +++ b/packages/babel-parser/src/plugins/placeholders.js @@ -256,8 +256,10 @@ export default (superClass: Class): Class => const next = this.nextTokenStart(); if (this.isUnparsedContextual(next, "from")) { if ( - this.input.substr(this.nextTokenStartSince(next + 4), 2) === - tt.placeholder.label + this.input.startsWith( + tt.placeholder.label, + this.nextTokenStartSince(next + 4), + ) ) { return true; }