diff --git a/js/src/builtin/ReflectParse.cpp b/js/src/builtin/ReflectParse.cpp index 30318d9ce8..91bef98884 100644 --- a/js/src/builtin/ReflectParse.cpp +++ b/js/src/builtin/ReflectParse.cpp @@ -34,12 +34,6 @@ using mozilla::ArrayLength; using mozilla::DebugOnly; using mozilla::Forward; -enum class ParseTarget -{ - Script, - Module -}; - enum ASTType { AST_ERROR = -1, #define ASTDEF(ast, str, method) ast, @@ -623,6 +617,9 @@ class NodeBuilder MOZ_MUST_USE bool metaProperty(HandleValue meta, HandleValue property, TokenPos* pos, MutableHandleValue dst); + MOZ_MUST_USE bool callImportExpression(HandleValue ident, HandleValue arg, TokenPos* pos, + MutableHandleValue dst); + MOZ_MUST_USE bool super(TokenPos* pos, MutableHandleValue dst); /* @@ -1758,6 +1755,20 @@ NodeBuilder::metaProperty(HandleValue meta, HandleValue property, TokenPos* pos, dst); } +bool +NodeBuilder::callImportExpression(HandleValue ident, HandleValue arg, TokenPos* pos, + MutableHandleValue dst) +{ + RootedValue cb(cx, callbacks[AST_CALL_IMPORT]); + if (!cb.isNull()) + return callback(cb, arg, pos, dst); + + return newNode(AST_CALL_IMPORT, pos, + "ident", ident, + "arg", arg, + dst); +} + bool NodeBuilder::super(TokenPos* pos, MutableHandleValue dst) { @@ -3360,6 +3371,7 @@ ASTSerializer::expression(ParseNode* pn, MutableHandleValue dst) return classDefinition(&pn->as(), true, dst); case PNK_NEWTARGET: + case PNK_IMPORT_META: { BinaryNode* node = &pn->as(); ParseNode* firstNode = node->left(); @@ -3370,15 +3382,41 @@ ASTSerializer::expression(ParseNode* pn, MutableHandleValue dst) MOZ_ASSERT(secondNode->isKind(PNK_POSHOLDER)); MOZ_ASSERT(node->pn_pos.encloses(secondNode->pn_pos)); - RootedValue newIdent(cx); - RootedValue targetIdent(cx); + RootedValue firstIdent(cx); + RootedValue secondIdent(cx); - RootedAtom newStr(cx, cx->names().new_); - RootedAtom targetStr(cx, cx->names().target); + RootedAtom firstStr(cx); + RootedAtom secondStr(cx); - return identifier(newStr, &firstNode->pn_pos, &newIdent) && - identifier(targetStr, &secondNode->pn_pos, &targetIdent) && - builder.metaProperty(newIdent, targetIdent, &node->pn_pos, dst); + if (pn->getKind() == PNK_NEWTARGET) { + firstStr = cx->names().new_; + secondStr = cx->names().target; + } else { + firstStr = cx->names().import; + secondStr = cx->names().meta; + } + + return identifier(firstStr, &firstNode->pn_pos, &firstIdent) && + identifier(secondStr, &secondNode->pn_pos, &secondIdent) && + builder.metaProperty(firstIdent, secondIdent, &pn->pn_pos, dst); + } + + case PNK_CALL_IMPORT: + { + BinaryNode* node = &pn->as(); + ParseNode* firstNode = node->left(); + MOZ_ASSERT(firstNode->isKind(PNK_POSHOLDER)); + MOZ_ASSERT(pn->pn_pos.encloses(firstNode->pn_pos)); + ParseNode* secondNode = node->right(); + MOZ_ASSERT(pn->pn_pos.encloses(secondNode->pn_pos)); + + RootedValue ident(cx); + RootedValue arg(cx); + + HandlePropertyName name = cx->names().import; + return identifier(name, &firstNode->pn_pos, &ident) && + expression(secondNode, &arg) && + builder.callImportExpression(ident, arg, &pn->pn_pos, dst); } case PNK_SETTHIS: { @@ -3793,7 +3831,7 @@ reflect_parse(JSContext* cx, uint32_t argc, Value* vp) uint32_t lineno = 1; bool loc = true; RootedObject builder(cx); - ParseTarget target = ParseTarget::Script; + ParseGoal target = ParseGoal::Script; RootedValue arg(cx, args.get(1)); @@ -3881,9 +3919,9 @@ reflect_parse(JSContext* cx, uint32_t argc, Value* vp) return false; if (isScript) { - target = ParseTarget::Script; + target = ParseGoal::Script; } else if (isModule) { - target = ParseTarget::Module; + target = ParseGoal::Module; } else { JS_ReportErrorASCII(cx, "Bad target value, expected 'script' or 'module'"); return false; @@ -3912,14 +3950,14 @@ reflect_parse(JSContext* cx, uint32_t argc, Value* vp) return false; Parser parser(cx, cx->tempLifoAlloc(), options, chars.begin().get(), chars.length(), /* foldConstants = */ false, usedNames, - nullptr, nullptr); + nullptr, nullptr, target); if (!parser.checkOptions()) return false; serialize.setParser(&parser); ParseNode* pn; - if (target == ParseTarget::Script) { + if (target == ParseGoal::Script) { pn = parser.parse(); if (!pn) return false; diff --git a/js/src/frontend/BytecodeCompiler.cpp b/js/src/frontend/BytecodeCompiler.cpp index de04d41d60..2a78301262 100644 --- a/js/src/frontend/BytecodeCompiler.cpp +++ b/js/src/frontend/BytecodeCompiler.cpp @@ -74,8 +74,9 @@ class MOZ_STACK_CLASS BytecodeCompiler bool createScriptSource(Maybe parameterListEnd); bool maybeCompressSource(); bool canLazilyParse(); - bool createParser(); - bool createSourceAndParser(Maybe parameterListEnd = Nothing()); + bool createParser(ParseGoal goal); + bool createSourceAndParser(ParseGoal goal, + Maybe parameterListEnd = Nothing()); // If toString{Start,End} are not explicitly passed, assume the script's // offsets in the source used to parse it are the same as what should be @@ -212,7 +213,7 @@ BytecodeCompiler::canLazilyParse() } bool -BytecodeCompiler::createParser() +BytecodeCompiler::createParser(ParseGoal goal) { usedNames.emplace(cx); if (!usedNames->init()) @@ -221,14 +222,14 @@ BytecodeCompiler::createParser() if (canLazilyParse()) { syntaxParser.emplace(cx, alloc, options, sourceBuffer.get(), sourceBuffer.length(), /* foldConstants = */ false, *usedNames, - (Parser*) nullptr, (LazyScript*) nullptr); + (Parser*) nullptr, (LazyScript*) nullptr, goal); if (!syntaxParser->checkOptions()) return false; } parser.emplace(cx, alloc, options, sourceBuffer.get(), sourceBuffer.length(), - /* foldConstants = */ true, *usedNames, syntaxParser.ptrOr(nullptr), nullptr); + /* foldConstants = */ true, *usedNames, syntaxParser.ptrOr(nullptr), nullptr, goal); parser->sct = sourceCompressor; parser->ss = scriptSource; if (!parser->checkOptions()) @@ -239,11 +240,12 @@ BytecodeCompiler::createParser() } bool -BytecodeCompiler::createSourceAndParser(Maybe parameterListEnd /* = Nothing() */) +BytecodeCompiler::createSourceAndParser(ParseGoal goal, + Maybe parameterListEnd /* = Nothing() */) { return createScriptSource(parameterListEnd) && maybeCompressSource() && - createParser(); + createParser(goal); } bool @@ -322,7 +324,7 @@ BytecodeCompiler::maybeCompleteCompressSource() JSScript* BytecodeCompiler::compileScript(HandleObject environment, SharedContext* sc) { - if (!createSourceAndParser()) + if (!createSourceAndParser(ParseGoal::Script)) return nullptr; if (!createScript()) @@ -392,7 +394,7 @@ BytecodeCompiler::compileEvalScript(HandleObject environment, HandleScope enclos ModuleObject* BytecodeCompiler::compileModule() { - if (!createSourceAndParser()) + if (!createSourceAndParser(ParseGoal::Module)) return nullptr; Rooted module(cx, ModuleObject::create(cx)); @@ -449,7 +451,7 @@ BytecodeCompiler::compileStandaloneFunction(MutableHandleFunction fun, MOZ_ASSERT(fun); MOZ_ASSERT(fun->isTenured()); - if (!createSourceAndParser(parameterListEnd)) + if (!createSourceAndParser(ParseGoal::Script, parameterListEnd)) return false; // Speculatively parse using the default directives implied by the context. @@ -649,7 +651,7 @@ frontend::CompileLazyFunction(JSContext* cx, Handle lazy, const cha if (!usedNames.init()) return false; Parser parser(cx, cx->tempLifoAlloc(), options, chars, length, - /* foldConstants = */ true, usedNames, nullptr, lazy); + /* foldConstants = */ true, usedNames, nullptr, lazy, lazy->parseGoal()); if (!parser.checkOptions()) return false; diff --git a/js/src/frontend/BytecodeEmitter.cpp b/js/src/frontend/BytecodeEmitter.cpp index 6e52fbad77..40cf2a85e4 100644 --- a/js/src/frontend/BytecodeEmitter.cpp +++ b/js/src/frontend/BytecodeEmitter.cpp @@ -1090,6 +1090,7 @@ BytecodeEmitter::checkSideEffects(ParseNode* pn, bool* answer) // Trivial binary nodes with more token pos holders. case PNK_NEWTARGET: + case PNK_IMPORT_META: MOZ_ASSERT(pn->as().left()->isKind(PNK_POSHOLDER)); MOZ_ASSERT(pn->as().right()->isKind(PNK_POSHOLDER)); *answer = false; @@ -1319,6 +1320,11 @@ BytecodeEmitter::checkSideEffects(ParseNode* pn, bool* answer) *answer = true; return true; + case PNK_CALL_IMPORT: + MOZ_ASSERT(pn->isArity(PN_BINARY)); + *answer = true; + return true; + // Every part of a loop might be effect-free, but looping infinitely *is* // an effect. (Language lawyer trivia: C++ says threads can be assumed // to exit or have side effects, C++14 [intro.multithread]p27, so a C++ @@ -9076,6 +9082,14 @@ BytecodeEmitter::emitTree(ParseNode* pn, ValueUsage valueUsage /* = ValueUsage:: return false; break; + case PNK_IMPORT_META: + MOZ_CRASH("NYI"); + break; + + case PNK_CALL_IMPORT: + reportError(nullptr, JSMSG_NO_DYNAMIC_IMPORT); + return false; + case PNK_SETTHIS: if (!emitSetThis(&pn->as())) return false; diff --git a/js/src/frontend/FoldConstants.cpp b/js/src/frontend/FoldConstants.cpp index 4b9cf55df4..8bd81faab4 100644 --- a/js/src/frontend/FoldConstants.cpp +++ b/js/src/frontend/FoldConstants.cpp @@ -138,6 +138,7 @@ ContainsHoistedDeclaration(ExclusiveContext* cx, ParseNode* node, bool* result) case PNK_EXPORT_SPEC: case PNK_EXPORT: case PNK_EXPORT_BATCH_SPEC: + case PNK_CALL_IMPORT: *result = false; return true; @@ -403,6 +404,7 @@ ContainsHoistedDeclaration(ExclusiveContext* cx, ParseNode* node, bool* result) case PNK_CLASSMETHODLIST: case PNK_CLASSNAMES: case PNK_NEWTARGET: + case PNK_IMPORT_META: case PNK_POSHOLDER: case PNK_SUPERCALL: case PNK_SUPERBASE: @@ -1900,7 +1902,8 @@ Fold(ExclusiveContext* cx, ParseNode** pnp, Parser& parser, bo Fold(cx, node->unsafeRightReference(), parser, inGenexpLambda); } - case PNK_NEWTARGET:{ + case PNK_NEWTARGET: + case PNK_IMPORT_META:{ #ifdef DEBUG BinaryNode* node = &pn->as(); MOZ_ASSERT(node->left()->isKind(PNK_POSHOLDER)); @@ -1909,6 +1912,13 @@ Fold(ExclusiveContext* cx, ParseNode** pnp, Parser& parser, bo return true; } + case PNK_CALL_IMPORT: { + BinaryNode* node = &pn->as(); + MOZ_ASSERT(pn->isArity(PN_BINARY)); + MOZ_ASSERT(node->left()->isKind(PNK_POSHOLDER)); + return Fold(cx, node->unsafeRightReference(), parser, inGenexpLambda); + } + case PNK_CLASSNAMES: { ClassNames* names = &pn->as(); if (names->outerBinding()) { diff --git a/js/src/frontend/FullParseHandler.h b/js/src/frontend/FullParseHandler.h index ab01fa83ef..75aa618cfd 100644 --- a/js/src/frontend/FullParseHandler.h +++ b/js/src/frontend/FullParseHandler.h @@ -590,6 +590,14 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS) return new_(PNK_EXPORT_DEFAULT, JSOP_NOP, pos, kid, maybeBinding); } + BinaryNodeType newImportMeta(Node importHolder, Node metaHolder) { + return new_(PNK_IMPORT_META, JSOP_NOP, importHolder, metaHolder); + } + + BinaryNodeType newCallImport(Node importHolder, Node singleArg) { + return new_(PNK_CALL_IMPORT, JSOP_NOP, importHolder, singleArg); + } + UnaryNodeType newExprStatement(Node expr, uint32_t end) { MOZ_ASSERT(expr->pn_pos.end <= end); return new_(PNK_SEMI, JSOP_NOP, TokenPos(expr->pn_pos.begin, end), expr); diff --git a/js/src/frontend/NameAnalysisTypes.h b/js/src/frontend/NameAnalysisTypes.h index 40959689df..344c42429f 100644 --- a/js/src/frontend/NameAnalysisTypes.h +++ b/js/src/frontend/NameAnalysisTypes.h @@ -64,6 +64,12 @@ class EnvironmentCoordinate namespace frontend { +enum class ParseGoal : uint8_t +{ + Script, + Module +}; + // A detailed kind used for tracking declarations in the Parser. Used for // specific early error semantics and better error messages. enum class DeclarationKind : uint8_t diff --git a/js/src/frontend/NameFunctions.cpp b/js/src/frontend/NameFunctions.cpp index bb4fd6319a..677337ac88 100644 --- a/js/src/frontend/NameFunctions.cpp +++ b/js/src/frontend/NameFunctions.cpp @@ -424,7 +424,8 @@ class NameResolver MOZ_ASSERT(!cur->as().kid()->as().initializer()); break; - case PNK_NEWTARGET: { + case PNK_NEWTARGET: + case PNK_IMPORT_META: { MOZ_ASSERT(cur->as().left()->isKind(PNK_POSHOLDER)); MOZ_ASSERT(cur->as().right()->isKind(PNK_POSHOLDER)); break; @@ -834,6 +835,14 @@ class NameResolver break; } + case PNK_CALL_IMPORT: { + BinaryNode* node = &cur->as(); + MOZ_ASSERT(cur->isArity(PN_BINARY)); + if (!resolve(node->right(), prefix)) + return false; + break; + } + case PNK_DOT: { // Super prop nodes do not have a meaningful LHS PropertyAccess* prop = &cur->as(); diff --git a/js/src/frontend/ParseNode.h b/js/src/frontend/ParseNode.h index 50fe44074a..f094a3b013 100644 --- a/js/src/frontend/ParseNode.h +++ b/js/src/frontend/ParseNode.h @@ -121,6 +121,8 @@ class ObjectBox; F(SUPERBASE) \ F(SUPERCALL) \ F(SETTHIS) \ + F(IMPORT_META) \ + F(CALL_IMPORT) \ \ /* Unary operators. */ \ F(TYPEOFNAME) \ diff --git a/js/src/frontend/Parser.cpp b/js/src/frontend/Parser.cpp index d5cdd898c2..ad38321bc0 100644 --- a/js/src/frontend/Parser.cpp +++ b/js/src/frontend/Parser.cpp @@ -791,7 +791,8 @@ ParserBase::ParserBase(ExclusiveContext* cx, LifoAlloc& alloc, bool foldConstants, UsedNameTracker& usedNames, Parser* syntaxParser, - LazyScript* lazyOuterFunction) + LazyScript* lazyOuterFunction, + ParseGoal parseGoal) : context(cx), alloc(alloc), tokenStream(cx, options, chars, length, thisForCtor()), @@ -807,7 +808,8 @@ ParserBase::ParserBase(ExclusiveContext* cx, LifoAlloc& alloc, #endif abortedSyntaxParse(false), isUnexpectedEOF_(false), - awaitIsKeyword_(false) + awaitIsKeyword_(false), + parseGoal_(uint8_t(parseGoal)) { cx->perThreadData->frontendCollectionPool.addActiveCompilation(); tempPoolMark = alloc.mark(); @@ -834,9 +836,10 @@ Parser::Parser(ExclusiveContext* cx, LifoAlloc& alloc, bool foldConstants, UsedNameTracker& usedNames, Parser* syntaxParser, - LazyScript* lazyOuterFunction) + LazyScript* lazyOuterFunction, + ParseGoal parseGoal) : ParserBase(cx, alloc, options, chars, length, foldConstants, usedNames, syntaxParser, - lazyOuterFunction), + lazyOuterFunction, parseGoal), AutoGCRooter(cx, PARSER), handler(cx, alloc, tokenStream, syntaxParser, lazyOuterFunction) { @@ -2468,7 +2471,8 @@ Parser::finishFunction(bool isStandaloneFunction /* = false pc->innerFunctionsForLazy, versionNumber(), funbox->bufStart, funbox->bufEnd, funbox->toStringStart, - funbox->startLine, funbox->startColumn); + funbox->startLine, funbox->startColumn, + parseGoal()); if (!lazy) return false; @@ -5212,6 +5216,22 @@ Parser::importDeclaration() return SyntaxParseHandler::NodeFailure; } +template +inline typename ParseHandler::Node +Parser::importDeclarationOrImportExpr(YieldHandling yieldHandling) +{ + MOZ_ASSERT(anyChars.isCurrentTokenType(TOK_IMPORT)); + + TokenKind tt; + if (!tokenStream.peekToken(&tt)) + return null(); + + if (tt == TOK_DOT || tt == TOK_LP) + return expressionStatement(yieldHandling); + + return importDeclaration(); +} + template<> bool Parser::checkExportedName(JSAtom* exportName) @@ -7737,7 +7757,7 @@ Parser::statement(YieldHandling yieldHandling) // ImportDeclaration (only inside modules) case TOK_IMPORT: - return importDeclaration(); + return importDeclarationOrImportExpr(yieldHandling); // ExportDeclaration (only inside modules) case TOK_EXPORT: @@ -7928,7 +7948,7 @@ Parser::statementListItem(YieldHandling yieldHandling, // ImportDeclaration (only inside modules) case TOK_IMPORT: - return importDeclaration(); + return importDeclarationOrImportExpr(yieldHandling); // ExportDeclaration (only inside modules) case TOK_EXPORT: @@ -9284,6 +9304,10 @@ Parser::memberExpr(YieldHandling yieldHandling, TripledotHandling lhs = handler.newSuperBase(thisName, pos()); if (!lhs) return null(); + } else if (tt == TOK_IMPORT) { + lhs = importExpr(yieldHandling); + if (!lhs) + return null(); } else { lhs = primaryExpr(yieldHandling, tripledotHandling, tt, possibleError, invoked); if (!lhs) @@ -10454,6 +10478,52 @@ Parser::tryNewTarget(BinaryNodeType* newTarget) template typename ParseHandler::Node +Parser::importExpr(YieldHandling yieldHandling) +{ + MOZ_ASSERT(anyChars.isCurrentTokenType(TOK_IMPORT)); + + Node importHolder = handler.newPosHolder(pos()); + if (!importHolder) + return null(); + + TokenKind next; + if (!tokenStream.getToken(&next)) + return null(); + + if (next == TOK_DOT) { + if (!tokenStream.getToken(&next)) + return null(); + if (next != TOK_META) { + error(JSMSG_UNEXPECTED_TOKEN, "meta", TokenKindToDesc(next)); + return null(); + } + + if (parseGoal() != ParseGoal::Module) { + errorAt(pos().begin, JSMSG_IMPORT_META_OUTSIDE_MODULE); + return null(); + } + + Node metaHolder = handler.newPosHolder(pos()); + if (!metaHolder) + return null(); + + return handler.newImportMeta(importHolder, metaHolder); + } else if (next == TOK_LP) { + Node arg = assignExpr(InAllowed, yieldHandling, TripledotProhibited); + if (!arg) + return null(); + + MUST_MATCH_TOKEN_MOD(TOK_RP, TokenStream::Operand, JSMSG_PAREN_AFTER_ARGS); + + return handler.newCallImport(importHolder, arg); + } else { + error(JSMSG_UNEXPECTED_TOKEN, TokenKindToDesc(next)); + return null(); + } +} + +template +typename ParseHandler::Node Parser::primaryExpr(YieldHandling yieldHandling, TripledotHandling tripledotHandling, TokenKind tt, PossibleError* possibleError, InvokedPrediction invoked /* = PredictUninvoked */) diff --git a/js/src/frontend/Parser.h b/js/src/frontend/Parser.h index 317b497334..8eb6a2f21b 100644 --- a/js/src/frontend/Parser.h +++ b/js/src/frontend/Parser.h @@ -801,15 +801,21 @@ class ParserBase : public StrictModeGetter bool awaitIsKeyword_:1; + uint8_t parseGoal_:1; + public: bool awaitIsKeyword() const { return awaitIsKeyword_; } + ParseGoal parseGoal() const { + return ParseGoal(parseGoal_); + } + ParserBase(ExclusiveContext* cx, LifoAlloc& alloc, const ReadOnlyCompileOptions& options, const char16_t* chars, size_t length, bool foldConstants, UsedNameTracker& usedNames, Parser* syntaxParser, - LazyScript* lazyOuterFunction); + LazyScript* lazyOuterFunction, ParseGoal parseGoal); ~ParserBase(); const char* getFilename() const { return tokenStream.getFilename(); } @@ -1045,7 +1051,7 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_TYPE) public: Parser(ExclusiveContext* cx, LifoAlloc& alloc, const ReadOnlyCompileOptions& options, const char16_t* chars, size_t length, bool foldConstants, UsedNameTracker& usedNames, - Parser* syntaxParser, LazyScript* lazyOuterFunction); + Parser* syntaxParser, LazyScript* lazyOuterFunction, ParseGoal parseGoal); ~Parser(); friend class AutoAwaitIsKeyword; @@ -1236,6 +1242,7 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_TYPE) ListNodeType lexicalDeclaration(YieldHandling yieldHandling, DeclarationKind kind); inline BinaryNodeType importDeclaration(); + Node importDeclarationOrImportExpr(YieldHandling yieldHandling); bool processExport(Node node); bool processExportFrom(BinaryNodeType node); @@ -1346,6 +1353,8 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_TYPE) bool tryNewTarget(BinaryNodeType* newTarget); bool checkAndMarkSuperScope(); + Node importExpr(YieldHandling yieldHandling); + FunctionNodeType methodDefinition(uint32_t toStringStart, PropertyType propType, HandleAtom funName); /* diff --git a/js/src/frontend/ReservedWords.h b/js/src/frontend/ReservedWords.h index 359ae54074..9d45b6eca3 100644 --- a/js/src/frontend/ReservedWords.h +++ b/js/src/frontend/ReservedWords.h @@ -66,6 +66,7 @@ macro(from, from, TOK_FROM) \ macro(get, get, TOK_GET) \ macro(let, let, TOK_LET) \ + macro(meta, meta, TOK_META) \ macro(of, of, TOK_OF) \ macro(set, set, TOK_SET) \ macro(static, static_, TOK_STATIC) \ diff --git a/js/src/frontend/SyntaxParseHandler.h b/js/src/frontend/SyntaxParseHandler.h index f3591e22ba..e364f9d680 100644 --- a/js/src/frontend/SyntaxParseHandler.h +++ b/js/src/frontend/SyntaxParseHandler.h @@ -354,6 +354,12 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS) BinaryNodeType newExportDefaultDeclaration(Node kid, Node maybeBinding, const TokenPos& pos) { return NodeGeneric; } + Node newImportMeta(Node importHolder, Node metaHolder) { + return NodeGeneric; + } + Node newCallImport(Node importHolder, Node singleArg) { + return NodeGeneric; + } BinaryNodeType newSetThis(Node thisName, Node value) { return value; } diff --git a/js/src/frontend/TokenKind.h b/js/src/frontend/TokenKind.h index f11ceda33e..745e1b6987 100644 --- a/js/src/frontend/TokenKind.h +++ b/js/src/frontend/TokenKind.h @@ -125,6 +125,7 @@ macro(FROM, "'from'") \ macro(GET, "'get'") \ macro(LET, "'let'") \ + macro(META, "'meta'") \ macro(OF, "'of'") \ macro(SET, "'set'") \ macro(STATIC, "'static'") \ diff --git a/js/src/js.msg b/js/src/js.msg index c99eff03a7..218d60f83d 100644 --- a/js/src/js.msg +++ b/js/src/js.msg @@ -265,6 +265,7 @@ MSG_DEF(JSMSG_FROM_AFTER_EXPORT_STAR, 0, JSEXN_SYNTAXERR, "missing keyword 'fro MSG_DEF(JSMSG_GARBAGE_AFTER_INPUT, 2, JSEXN_SYNTAXERR, "unexpected garbage after {0}, starting with {1}") MSG_DEF(JSMSG_IDSTART_AFTER_NUMBER, 0, JSEXN_SYNTAXERR, "identifier starts immediately after numeric literal") MSG_DEF(JSMSG_ILLEGAL_CHARACTER, 0, JSEXN_SYNTAXERR, "illegal character") +MSG_DEF(JSMSG_IMPORT_META_OUTSIDE_MODULE, 0, JSEXN_SYNTAXERR, "import.meta may only appear in a module") MSG_DEF(JSMSG_IMPORT_DECL_AT_TOP_LEVEL, 0, JSEXN_SYNTAXERR, "import declarations may only appear at top level of a module") MSG_DEF(JSMSG_OF_AFTER_FOR_LOOP_DECL, 0, JSEXN_SYNTAXERR, "a declaration in the head of a for-of loop can't have an initializer") MSG_DEF(JSMSG_IN_AFTER_LEXICAL_FOR_DECL,0,JSEXN_SYNTAXERR, "a lexical declaration in the head of a for-in loop can't have an initializer") @@ -590,6 +591,7 @@ MSG_DEF(JSMSG_AMBIGUOUS_IMPORT, 0, JSEXN_SYNTAXERR, "ambiguous import") MSG_DEF(JSMSG_MISSING_NAMESPACE_EXPORT, 0, JSEXN_SYNTAXERR, "export not found for namespace") MSG_DEF(JSMSG_MISSING_EXPORT, 1, JSEXN_SYNTAXERR, "local binding for export '{0}' not found") MSG_DEF(JSMSG_BAD_MODULE_STATUS, 0, JSEXN_INTERNALERR, "module record has unexpected status") +MSG_DEF(JSMSG_NO_DYNAMIC_IMPORT, 0, JSEXN_SYNTAXERR, "dynamic module import is not implemented") // Promise MSG_DEF(JSMSG_CANNOT_RESOLVE_PROMISE_WITH_ITSELF, 0, JSEXN_TYPEERR, "A promise cannot be resolved with itself.") diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index eb9106827d..f9f5b986ea 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -4240,7 +4240,8 @@ JS_BufferIsCompilableUnit(JSContext* cx, HandleObject obj, const char* utf8, siz frontend::Parser parser(cx, cx->tempLifoAlloc(), options, chars, length, /* foldConstants = */ true, - usedNames, nullptr, nullptr); + usedNames, nullptr, nullptr, + frontend::ParseGoal::Script); JS::WarningReporter older = JS::SetWarningReporter(cx, nullptr); if (!parser.checkOptions() || !parser.parse()) { // We ran into an error. If it was because we ran out of source, we diff --git a/js/src/jsast.tbl b/js/src/jsast.tbl index a50e31d7ba..24814c3973 100644 --- a/js/src/jsast.tbl +++ b/js/src/jsast.tbl @@ -44,6 +44,7 @@ ASTDEF(AST_YIELD_EXPR, "YieldExpression", "yieldExpres ASTDEF(AST_CLASS_EXPR, "ClassExpression", "classExpression") ASTDEF(AST_METAPROPERTY, "MetaProperty", "metaProperty") ASTDEF(AST_SUPER, "Super", "super") +ASTDEF(AST_CALL_IMPORT, "CallImport", "callImport") ASTDEF(AST_EMPTY_STMT, "EmptyStatement", "emptyStatement") ASTDEF(AST_BLOCK_STMT, "BlockStatement", "blockStatement") diff --git a/js/src/jsscript.cpp b/js/src/jsscript.cpp index 75d59bef68..fe0be9b5a2 100644 --- a/js/src/jsscript.cpp +++ b/js/src/jsscript.cpp @@ -4089,7 +4089,8 @@ LazyScript::Create(ExclusiveContext* cx, HandleFunction fun, Handle> innerFunctions, JSVersion version, uint32_t begin, uint32_t end, - uint32_t toStringStart, uint32_t lineno, uint32_t column) + uint32_t toStringStart, uint32_t lineno, uint32_t column, + frontend::ParseGoal parseGoal) { union { PackedView p; @@ -4112,6 +4113,7 @@ LazyScript::Create(ExclusiveContext* cx, HandleFunction fun, p.isLikelyConstructorWrapper = false; p.isDerivedClassConstructor = false; p.needsHomeObject = false; + p.parseGoal = uint32_t(parseGoal); LazyScript* res = LazyScript::CreateRaw(cx, fun, packedFields, begin, end, toStringStart, lineno, column); diff --git a/js/src/jsscript.h b/js/src/jsscript.h index fd5c96a16d..1943634b15 100644 --- a/js/src/jsscript.h +++ b/js/src/jsscript.h @@ -2019,6 +2019,7 @@ class LazyScript : public gc::TenuredCell uint32_t isDerivedClassConstructor : 1; uint32_t needsHomeObject : 1; uint32_t hasRest : 1; + uint32_t parseGoal : 1; }; union { @@ -2058,7 +2059,8 @@ class LazyScript : public gc::TenuredCell const frontend::AtomVector& closedOverBindings, Handle> innerFunctions, JSVersion version, uint32_t begin, uint32_t end, - uint32_t toStringStart, uint32_t lineno, uint32_t column); + uint32_t toStringStart, uint32_t lineno, uint32_t column, + frontend::ParseGoal parseGoal); // Create a LazyScript and initialize the closedOverBindings and the // innerFunctions with dummy values to be replaced in a later initialization @@ -2169,6 +2171,10 @@ class LazyScript : public gc::TenuredCell p_.isExprBody = true; } + frontend::ParseGoal parseGoal() const { + return frontend::ParseGoal(p_.parseGoal); + } + bool strict() const { return p_.strict; } diff --git a/js/src/shell/js.cpp b/js/src/shell/js.cpp index 85751d7be1..d0d2dda637 100644 --- a/js/src/shell/js.cpp +++ b/js/src/shell/js.cpp @@ -4146,7 +4146,8 @@ Parse(JSContext* cx, unsigned argc, Value* vp) if (!usedNames.init()) return false; Parser parser(cx, cx->tempLifoAlloc(), options, chars, length, - /* foldConstants = */ true, usedNames, nullptr, nullptr); + /* foldConstants = */ true, usedNames, nullptr, nullptr, + ParseGoal::Script); if (!parser.checkOptions()) return false; @@ -4197,7 +4198,8 @@ SyntaxParse(JSContext* cx, unsigned argc, Value* vp) return false; Parser parser(cx, cx->tempLifoAlloc(), options, chars, length, false, - usedNames, nullptr, nullptr); + usedNames, nullptr, nullptr, + ParseGoal::Script); if (!parser.checkOptions()) return false; diff --git a/js/src/vm/CommonPropertyNames.h b/js/src/vm/CommonPropertyNames.h index 171920447e..82f0ebadaa 100644 --- a/js/src/vm/CommonPropertyNames.h +++ b/js/src/vm/CommonPropertyNames.h @@ -226,6 +226,7 @@ macro(maximumFractionDigits, maximumFractionDigits, "maximumFractionDigits") \ macro(maximumSignificantDigits, maximumSignificantDigits, "maximumSignificantDigits") \ macro(message, message, "message") \ + macro(meta, meta, "meta") \ macro(minDays, minDays, "minDays") \ macro(minimumFractionDigits, minimumFractionDigits, "minimumFractionDigits") \ macro(minimumIntegerDigits, minimumIntegerDigits, "minimumIntegerDigits") \ diff --git a/js/src/vm/Debugger.cpp b/js/src/vm/Debugger.cpp index f844d1d482..5b7af64872 100644 --- a/js/src/vm/Debugger.cpp +++ b/js/src/vm/Debugger.cpp @@ -5084,7 +5084,8 @@ Debugger::isCompilableUnit(JSContext* cx, unsigned argc, Value* vp) frontend::Parser parser(cx, cx->tempLifoAlloc(), options, chars.twoByteChars(), length, /* foldConstants = */ true, - usedNames, nullptr, nullptr); + usedNames, nullptr, nullptr, + frontend::ParseGoal::Script); JS::WarningReporter older = JS::SetWarningReporter(cx, nullptr); if (!parser.checkOptions() || !parser.parse()) { // We ran into an error. If it was because we ran out of memory we report