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] 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