summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--js/src/frontend/Parser.cpp28
-rw-r--r--js/src/frontend/Parser.h5
-rw-r--r--js/src/jit-test/tests/modules/export-declaration.js46
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 () {