diff options
-rw-r--r-- | js/src/frontend/FullParseHandler.h | 15 | ||||
-rw-r--r-- | js/src/frontend/ParseNode.h | 8 | ||||
-rw-r--r-- | js/src/frontend/Parser.cpp | 176 | ||||
-rw-r--r-- | js/src/frontend/Parser.h | 5 | ||||
-rw-r--r-- | js/src/frontend/SyntaxParseHandler.h | 5 | ||||
-rw-r--r-- | js/src/wasm/AsmJS.cpp | 2 |
6 files changed, 116 insertions, 95 deletions
diff --git a/js/src/frontend/FullParseHandler.h b/js/src/frontend/FullParseHandler.h index da068e5af..b619cf24c 100644 --- a/js/src/frontend/FullParseHandler.h +++ b/js/src/frontend/FullParseHandler.h @@ -670,9 +670,18 @@ class FullParseHandler pn->setDirectRHSAnonFunction(true); } - ParseNode* newFunctionDefinition() { - return new_<CodeNode>(PNK_FUNCTION, pos()); + ParseNode* newFunctionStatement() { + return new_<CodeNode>(PNK_FUNCTION, JSOP_NOP, pos()); } + + ParseNode* newFunctionExpression() { + return new_<CodeNode>(PNK_FUNCTION, JSOP_LAMBDA, pos()); + } + + ParseNode* newArrowFunction() { + return new_<CodeNode>(PNK_FUNCTION, JSOP_LAMBDA_ARROW, pos()); + } + bool setComprehensionLambdaBody(ParseNode* pn, ParseNode* body) { MOZ_ASSERT(body->isKind(PNK_STATEMENTLIST)); ParseNode* paramsBody = newList(PNK_PARAMSBODY, body); @@ -699,7 +708,7 @@ class FullParseHandler } ParseNode* newModule() { - return new_<CodeNode>(PNK_MODULE, pos()); + return new_<CodeNode>(PNK_MODULE, JSOP_NOP, pos()); } ParseNode* newLexicalScope(LexicalScope::Data* bindings, ParseNode* body) { diff --git a/js/src/frontend/ParseNode.h b/js/src/frontend/ParseNode.h index c58dab431..c3523afe4 100644 --- a/js/src/frontend/ParseNode.h +++ b/js/src/frontend/ParseNode.h @@ -926,10 +926,14 @@ struct ListNode : public ParseNode struct CodeNode : public ParseNode { - CodeNode(ParseNodeKind kind, const TokenPos& pos) - : ParseNode(kind, JSOP_NOP, PN_CODE, pos) + CodeNode(ParseNodeKind kind, JSOp op, const TokenPos& pos) + : ParseNode(kind, op, PN_CODE, pos) { MOZ_ASSERT(kind == PNK_FUNCTION || kind == PNK_MODULE); + MOZ_ASSERT_IF(kind == PNK_MODULE, op == JSOP_NOP); + MOZ_ASSERT(op == JSOP_NOP || // statement, module + op == JSOP_LAMBDA_ARROW || // arrow function + op == JSOP_LAMBDA); // expression, method, comprehension, accessor, &c. MOZ_ASSERT(!pn_body); MOZ_ASSERT(!pn_objbox); } diff --git a/js/src/frontend/Parser.cpp b/js/src/frontend/Parser.cpp index 8466d7c1c..c34e4d563 100644 --- a/js/src/frontend/Parser.cpp +++ b/js/src/frontend/Parser.cpp @@ -2352,7 +2352,7 @@ Parser<FullParseHandler>::standaloneFunction(HandleFunction fun, tokenStream.ungetToken(); } - Node fn = handler.newFunctionDefinition(); + Node fn = handler.newFunctionStatement(); if (!fn) return null(); @@ -3010,60 +3010,54 @@ Parser<ParseHandler>::functionArguments(YieldHandling yieldHandling, FunctionSyn template <typename ParseHandler> bool -Parser<ParseHandler>::checkFunctionDefinition(HandleAtom funAtom, Node pn, FunctionSyntaxKind kind, +Parser<ParseHandler>::checkFunctionDefinition(HandlePropertyName funName, Node pn, GeneratorKind generatorKind, bool* tryAnnexB) { - if (kind == Statement) { - TokenPos pos = handler.getPosition(pn); - RootedPropertyName funName(context, funAtom->asPropertyName()); - - // In sloppy mode, Annex B.3.2 allows labelled function - // declarations. Otherwise it is a parse error. - ParseContext::Statement* declaredInStmt = pc->innermostStatement(); - if (declaredInStmt && declaredInStmt->kind() == StatementKind::Label) { - MOZ_ASSERT(!pc->sc()->strict(), - "labeled functions shouldn't be parsed in strict mode"); - - // Find the innermost non-label statement. Report an error if it's - // unbraced: functions can't appear in it. Otherwise the statement - // (or its absence) determines the scope the function's bound in. - while (declaredInStmt && declaredInStmt->kind() == StatementKind::Label) - declaredInStmt = declaredInStmt->enclosing(); - - if (declaredInStmt && !StatementKindIsBraced(declaredInStmt->kind())) { - reportWithOffset(ParseError, false, pos.begin, JSMSG_SLOPPY_FUNCTION_LABEL); - return false; - } - } + TokenPos pos = handler.getPosition(pn); - if (declaredInStmt) { - MOZ_ASSERT(declaredInStmt->kind() != StatementKind::Label); - MOZ_ASSERT(StatementKindIsBraced(declaredInStmt->kind())); + // In sloppy mode, Annex B.3.2 allows labelled function + // declarations. Otherwise it is a parse error. + ParseContext::Statement* declaredInStmt = pc->innermostStatement(); + if (declaredInStmt && declaredInStmt->kind() == StatementKind::Label) { + MOZ_ASSERT(!pc->sc()->strict(), + "labeled functions shouldn't be parsed in strict mode"); - if (!pc->sc()->strict() && generatorKind == NotGenerator) { - // Under sloppy mode, try Annex B.3.3 semantics. If making an - // additional 'var' binding of the same name does not throw an - // early error, do so. This 'var' binding would be assigned - // the function object when its declaration is reached, not at - // the start of the block. + // Find the innermost non-label statement. Report an error if it's + // unbraced: functions can't appear in it. Otherwise the statement + // (or its absence) determines the scope the function's bound in. + while (declaredInStmt && declaredInStmt->kind() == StatementKind::Label) + declaredInStmt = declaredInStmt->enclosing(); - if (!tryDeclareVarForAnnexBLexicalFunction(funName, tryAnnexB)) - return false; - } + if (declaredInStmt && !StatementKindIsBraced(declaredInStmt->kind())) { + reportWithOffset(ParseError, false, pos.begin, JSMSG_SLOPPY_FUNCTION_LABEL); + return false; + } + } - if (!noteDeclaredName(funName, DeclarationKind::LexicalFunction, pos)) - return false; - } else { - if (!noteDeclaredName(funName, DeclarationKind::BodyLevelFunction, pos)) - return false; + if (declaredInStmt) { + MOZ_ASSERT(declaredInStmt->kind() != StatementKind::Label); + MOZ_ASSERT(StatementKindIsBraced(declaredInStmt->kind())); - // Body-level functions in modules are always closed over. - if (pc->atModuleLevel()) - pc->varScope().lookupDeclaredName(funName)->value()->setClosedOver(); + if (!pc->sc()->strict() && generatorKind == NotGenerator) { + // In sloppy mode, try Annex B.3.3 semantics. If making an + // additional 'var' binding of the same name does not throw an + // early error, do so. This 'var' binding would be assigned + // the function object when its declaration is reached, not at + // the start of the block. + + if (!tryDeclareVarForAnnexBLexicalFunction(funName, tryAnnexB)) + return false; } + + if (!noteDeclaredName(funName, DeclarationKind::LexicalFunction, pos)) + return false; } else { - // A function expression does not introduce any binding. - handler.setOp(pn, kind == Arrow ? JSOP_LAMBDA_ARROW : JSOP_LAMBDA); + if (!noteDeclaredName(funName, DeclarationKind::BodyLevelFunction, pos)) + return false; + + // Body-level functions in modules are always closed over. + if (pc->atModuleLevel()) + pc->varScope().lookupDeclaredName(funName)->value()->setClosedOver(); } return true; @@ -3191,16 +3185,12 @@ typename ParseHandler::Node Parser<ParseHandler>::functionDefinition(uint32_t preludeStart, Node pn, InHandling inHandling, YieldHandling yieldHandling, HandleAtom funName, FunctionSyntaxKind kind, - GeneratorKind generatorKind, FunctionAsyncKind asyncKind) + GeneratorKind generatorKind, FunctionAsyncKind asyncKind, + bool tryAnnexB /* = false */) { MOZ_ASSERT_IF(kind == Statement, funName); MOZ_ASSERT_IF(asyncKind == AsyncFunction, generatorKind == StarGenerator); - // Note the declared name and check for early errors. - bool tryAnnexB = false; - if (!checkFunctionDefinition(funName, pn, kind, generatorKind, &tryAnnexB)) - return null(); - // When fully parsing a LazyScript, we do not fully reparse its inner // functions, which are also lazy. Instead, their free variables and // source extents are recorded and may be skipped. @@ -3433,7 +3423,7 @@ Parser<FullParseHandler>::standaloneLazyFunction(HandleFunction fun, bool strict { MOZ_ASSERT(checkOptionsCalled); - Node pn = handler.newFunctionDefinition(); + Node pn = handler.newFunctionStatement(); if (!pn) return null(); @@ -3657,13 +3647,18 @@ Parser<ParseHandler>::functionStmt(uint32_t preludeStart, YieldHandling yieldHan return null(); } - Node pn = handler.newFunctionDefinition(); + Node pn = handler.newFunctionStatement(); if (!pn) return null(); + // Note the declared name and check for early errors. + bool tryAnnexB = false; + if (!checkFunctionDefinition(name, pn, generatorKind, &tryAnnexB)) + return null(); + YieldHandling newYieldHandling = GetYieldHandling(generatorKind, asyncKind); Node fun = functionDefinition(preludeStart, pn, InAllowed, newYieldHandling, - name, Statement, generatorKind, asyncKind); + name, Statement, generatorKind, asyncKind, tryAnnexB); if (!fun) return null(); @@ -3712,7 +3707,7 @@ Parser<ParseHandler>::functionExpr(uint32_t preludeStart, InvokedPrediction invo tokenStream.ungetToken(); } - Node pn = handler.newFunctionDefinition(); + Node pn = handler.newFunctionExpression(); if (!pn) return null(); @@ -6583,31 +6578,6 @@ JSOpFromPropertyType(PropertyType propType) } } -static FunctionSyntaxKind -FunctionSyntaxKindFromPropertyType(PropertyType propType) -{ - switch (propType) { - case PropertyType::Getter: - return Getter; - case PropertyType::GetterNoExpressionClosure: - return GetterNoExpressionClosure; - case PropertyType::Setter: - return Setter; - case PropertyType::SetterNoExpressionClosure: - return SetterNoExpressionClosure; - case PropertyType::Method: - case PropertyType::GeneratorMethod: - case PropertyType::AsyncMethod: - return Method; - case PropertyType::Constructor: - return ClassConstructor; - case PropertyType::DerivedConstructor: - return DerivedClassConstructor; - default: - MOZ_CRASH("unexpected property type"); - } -} - static GeneratorKind GeneratorKindFromPropertyType(PropertyType propType) { @@ -7786,7 +7756,7 @@ Parser<ParseHandler>::assignExpr(InHandling inHandling, YieldHandling yieldHandl } } - Node pn = handler.newFunctionDefinition(); + Node pn = handler.newArrowFunction(); if (!pn) return null(); @@ -8125,10 +8095,9 @@ template <typename ParseHandler> typename ParseHandler::Node Parser<ParseHandler>::generatorComprehensionLambda(unsigned begin) { - Node genfn = handler.newFunctionDefinition(); + Node genfn = handler.newFunctionExpression(); if (!genfn) return null(); - handler.setOp(genfn, JSOP_LAMBDA); ParseContext* outerpc = pc; @@ -9432,12 +9401,47 @@ typename ParseHandler::Node Parser<ParseHandler>::methodDefinition(uint32_t preludeStart, PropertyType propType, HandleAtom funName) { - FunctionSyntaxKind kind = FunctionSyntaxKindFromPropertyType(propType); + FunctionSyntaxKind kind; + switch (propType) { + case PropertyType::Getter: + kind = Getter; + break; + + case PropertyType::GetterNoExpressionClosure: + kind = GetterNoExpressionClosure; + break; + + case PropertyType::Setter: + kind = Setter; + break; + + case PropertyType::SetterNoExpressionClosure: + kind = SetterNoExpressionClosure; + break; + + case PropertyType::Method: + case PropertyType::GeneratorMethod: + case PropertyType::AsyncMethod: + kind = Method; + break; + + case PropertyType::Constructor: + kind = ClassConstructor; + break; + + case PropertyType::DerivedConstructor: + kind = DerivedClassConstructor; + break; + + default: + MOZ_CRASH("Parser: methodDefinition: unexpected property type"); + } + GeneratorKind generatorKind = GeneratorKindFromPropertyType(propType); FunctionAsyncKind asyncKind = AsyncKindFromPropertyType(propType); YieldHandling yieldHandling = GetYieldHandling(generatorKind, asyncKind); - Node pn = handler.newFunctionDefinition(); + Node pn = handler.newFunctionExpression(); if (!pn) return null(); diff --git a/js/src/frontend/Parser.h b/js/src/frontend/Parser.h index 3bfb4ae31..dc9c16adb 100644 --- a/js/src/frontend/Parser.h +++ b/js/src/frontend/Parser.h @@ -1262,7 +1262,8 @@ class Parser final : private JS::AutoGCRooter, public StrictModeGetter Node functionDefinition(uint32_t preludeStart, Node pn, InHandling inHandling, YieldHandling yieldHandling, HandleAtom name, FunctionSyntaxKind kind, - GeneratorKind generatorKind, FunctionAsyncKind asyncKind); + GeneratorKind generatorKind, FunctionAsyncKind asyncKind, + bool tryAnnexB = false); // Parse a function body. Pass StatementListBody if the body is a list of // statements; pass ExpressionBody if the body is a single expression. @@ -1348,7 +1349,7 @@ class Parser final : private JS::AutoGCRooter, public StrictModeGetter Node newDotGeneratorName(); bool declareDotGeneratorName(); - bool checkFunctionDefinition(HandleAtom funAtom, Node pn, FunctionSyntaxKind kind, + bool checkFunctionDefinition(HandlePropertyName funName, Node pn, GeneratorKind generatorKind, bool* tryAnnexB); bool skipLazyInnerFunction(Node pn, uint32_t preludeStart, FunctionSyntaxKind kind, bool tryAnnexB); diff --git a/js/src/frontend/SyntaxParseHandler.h b/js/src/frontend/SyntaxParseHandler.h index 85695ba9c..00ea9d35d 100644 --- a/js/src/frontend/SyntaxParseHandler.h +++ b/js/src/frontend/SyntaxParseHandler.h @@ -342,7 +342,10 @@ class SyntaxParseHandler void checkAndSetIsDirectRHSAnonFunction(Node pn) {} - Node newFunctionDefinition() { return NodeFunctionDefinition; } + Node newFunctionStatement() { return NodeFunctionDefinition; } + Node newFunctionExpression() { return NodeFunctionDefinition; } + Node newArrowFunction() { return NodeFunctionDefinition; } + bool setComprehensionLambdaBody(Node pn, Node body) { return true; } void setFunctionFormalParametersAndBody(Node pn, Node kid) {} void setFunctionBody(Node pn, Node kid) {} diff --git a/js/src/wasm/AsmJS.cpp b/js/src/wasm/AsmJS.cpp index 2b6690363..a318d67a9 100644 --- a/js/src/wasm/AsmJS.cpp +++ b/js/src/wasm/AsmJS.cpp @@ -7064,7 +7064,7 @@ ParseFunction(ModuleValidator& m, ParseNode** fnOut, unsigned* line) if (!name) return false; - ParseNode* fn = m.parser().handler.newFunctionDefinition(); + ParseNode* fn = m.parser().handler.newFunctionStatement(); if (!fn) return false; |