From b4bd69bb6d45c268b29e9fc58250449770e665fc Mon Sep 17 00:00:00 2001 From: Jeff Walden Date: Mon, 21 Sep 2015 16:56:25 -0700 Subject: [PATCH] Bug 1206750 - Don't assert when |export ... from 'str'| is followed by a regular expression literal on a new line, with no intervening semicolon. r=arai --- js/src/frontend/Parser.cpp | 36 +++++++++---------- .../keyword-unescaped-requirement-modules.js | 26 ++++++++++++++ 2 files changed, 42 insertions(+), 20 deletions(-) diff --git a/js/src/frontend/Parser.cpp b/js/src/frontend/Parser.cpp index 946288c8ce0..7e88e1cd3e5 100644 --- a/js/src/frontend/Parser.cpp +++ b/js/src/frontend/Parser.cpp @@ -4867,14 +4867,14 @@ Parser::exportDeclaration() if (!moduleSpec) return null(); - if (!MatchOrInsertSemicolon(tokenStream)) + if (!MatchOrInsertSemicolon(tokenStream, TokenStream::Operand)) return null(); return handler.newExportFromDeclaration(begin, kid, moduleSpec); - } else { - tokenStream.ungetToken(); } + tokenStream.ungetToken(); + if (!MatchOrInsertSemicolon(tokenStream, TokenStream::Operand)) return null(); break; @@ -4895,28 +4895,24 @@ Parser::exportDeclaration() if (!tokenStream.getToken(&tt)) return null(); - if (tt == TOK_NAME && tokenStream.currentName() == context->names().from) { - if (!checkUnescapedName()) - return null(); - - MUST_MATCH_TOKEN(TOK_STRING, JSMSG_MODULE_SPEC_AFTER_FROM); - - Node moduleSpec = stringLiteral(); - if (!moduleSpec) - return null(); - - if (!MatchOrInsertSemicolon(tokenStream)) - return null(); - - return handler.newExportFromDeclaration(begin, kid, moduleSpec); - } else { + if (tt != TOK_NAME || tokenStream.currentName() != context->names().from) { report(ParseError, false, null(), JSMSG_FROM_AFTER_EXPORT_STAR); return null(); } - if (!MatchOrInsertSemicolon(tokenStream)) + if (!checkUnescapedName()) return null(); - break; + + MUST_MATCH_TOKEN(TOK_STRING, JSMSG_MODULE_SPEC_AFTER_FROM); + + Node moduleSpec = stringLiteral(); + if (!moduleSpec) + return null(); + + if (!MatchOrInsertSemicolon(tokenStream, TokenStream::Operand)) + return null(); + + return handler.newExportFromDeclaration(begin, kid, moduleSpec); } case TOK_FUNCTION: diff --git a/js/src/tests/ecma_6/extensions/keyword-unescaped-requirement-modules.js b/js/src/tests/ecma_6/extensions/keyword-unescaped-requirement-modules.js index afb19cc50f1..6d10114c13f 100644 --- a/js/src/tests/ecma_6/extensions/keyword-unescaped-requirement-modules.js +++ b/js/src/tests/ecma_6/extensions/keyword-unescaped-requirement-modules.js @@ -61,6 +61,32 @@ if (typeof Reflect.parse === "function") assertEq(oneStatementAST.body.length, 1); assertEq(oneStatementAST.body[0].type, "ExportDeclaration"); + + twoStatementAST = + Reflect.parse(`export { x } from "bar" + /bar/g`, + { target: "module" }); + + statements = twoStatementAST.body; + assertEq(statements.length, 2, + "should have two items in the module, not one ExportDeclaration"); + assertEq(statements[0].type, "ExportDeclaration"); + assertEq(statements[1].type, "ExpressionStatement"); + assertEq(statements[1].expression.type, "Literal"); + assertEq(statements[1].expression.value.toString(), "/bar/g"); + + twoStatementAST = + Reflect.parse(`export * from "bar" + /bar/g`, + { target: "module" }); + + statements = twoStatementAST.body; + assertEq(statements.length, 2, + "should have two items in the module, not one ExportDeclaration"); + assertEq(statements[0].type, "ExportDeclaration"); + assertEq(statements[1].type, "ExpressionStatement"); + assertEq(statements[1].expression.type, "Literal"); + assertEq(statements[1].expression.value.toString(), "/bar/g"); } /******************************************************************************/