diff options
-rw-r--r-- | js/src/frontend/Parser.cpp | 28 | ||||
-rw-r--r-- | js/src/frontend/Parser.h | 5 | ||||
-rw-r--r-- | js/src/jit-test/tests/modules/export-declaration.js | 46 |
3 files changed, 77 insertions, 2 deletions
diff --git a/js/src/frontend/Parser.cpp b/js/src/frontend/Parser.cpp index f382ec5e9..ffece5721 100644 --- a/js/src/frontend/Parser.cpp +++ b/js/src/frontend/Parser.cpp @@ -5124,6 +5124,31 @@ Parser<ParseHandler>::exportBatch(uint32_t begin) return exportFrom(begin, kid); } +template<> +bool +Parser<FullParseHandler>::checkLocalExportNames(ParseNode* node) +{ + // ES 2017 draft 15.2.3.1. + for (ParseNode* next = node->pn_head; next; next = next->pn_next) { + ParseNode* name = next->pn_left; + MOZ_ASSERT(name->isKind(PNK_NAME)); + + RootedPropertyName ident(context, name->pn_atom->asPropertyName()); + if (!checkLocalExportName(ident, name->pn_pos.begin)) + return false; + } + + return true; +} + +template<> +bool +Parser<SyntaxParseHandler>::checkLocalExportNames(Node node) +{ + MOZ_ALWAYS_FALSE(abortIfSyntaxParser()); + return false; +} + template <typename ParseHandler> typename ParseHandler::Node Parser<ParseHandler>::exportClause(uint32_t begin) @@ -5211,6 +5236,9 @@ Parser<ParseHandler>::exportClause(uint32_t begin) if (!matchOrInsertSemicolonAfterNonExpression()) return null(); + if (!checkLocalExportNames(kid)) + return null(); + Node node = handler.newExportDeclaration(kid, TokenPos(begin, pos().end)); if (!node) return null(); diff --git a/js/src/frontend/Parser.h b/js/src/frontend/Parser.h index e322a4b26..824dddb58 100644 --- a/js/src/frontend/Parser.h +++ b/js/src/frontend/Parser.h @@ -1202,6 +1202,7 @@ class Parser final : public ParserBase, private JS::AutoGCRooter Node exportFrom(uint32_t begin, Node specList); Node exportBatch(uint32_t begin); + bool checkLocalExportNames(Node node); Node exportClause(uint32_t begin); Node exportFunctionDeclaration(uint32_t begin); Node exportVariableStatement(uint32_t begin); @@ -1356,6 +1357,10 @@ class Parser final : public ParserBase, private JS::AutoGCRooter uint32_t offset, YieldHandling yieldHandling); + bool checkLocalExportName(HandlePropertyName ident, uint32_t offset) { + return checkLabelOrIdentifierReference(ident, offset, YieldIsName); + } + bool checkBindingIdentifier(HandlePropertyName ident, uint32_t offset, YieldHandling yieldHandling); diff --git a/js/src/jit-test/tests/modules/export-declaration.js b/js/src/jit-test/tests/modules/export-declaration.js index 48d1072bf..9925f2c68 100644 --- a/js/src/jit-test/tests/modules/export-declaration.js +++ b/js/src/jit-test/tests/modules/export-declaration.js @@ -403,10 +403,52 @@ assertThrowsInstanceOf(function() { parseAsModule("export {,} from 'a'"); }, SyntaxError); -parseAsModule("export { true as a } from 'b'"); +program([ + exportDeclaration( + null, + [ + exportSpecifier( + ident("true"), + ident("true") + ), + ], + lit("b"), + false + ) +]).assert(parseAsModule("export { true } from 'b'")); + +program([ + exportDeclaration( + null, + [ + exportSpecifier( + ident("true"), + ident("name") + ), + ], + lit("b"), + false + ) +]).assert(parseAsModule("export { true as name } from 'b'")); + +assertThrowsInstanceOf(function() { + parseAsModule("export { true }"); +}, SyntaxError); + +assertThrowsInstanceOf(function() { + parseAsModule("export { true as name }"); +}, SyntaxError); + +assertThrowsInstanceOf(function() { + parseAsModule("export { static }"); +}, SyntaxError); + +assertThrowsInstanceOf(function() { + parseAsModule("export { static as name }"); +}, SyntaxError); assertThrowsInstanceOf(function () { - parseAsModule("export { a } from 'b' f();"); + parseAsModule("export { name } from 'b' f();"); }, SyntaxError); assertThrowsInstanceOf(function () { |