summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--js/src/frontend/FullParseHandler.h15
-rw-r--r--js/src/frontend/ParseNode.h8
-rw-r--r--js/src/frontend/Parser.cpp176
-rw-r--r--js/src/frontend/Parser.h5
-rw-r--r--js/src/frontend/SyntaxParseHandler.h5
-rw-r--r--js/src/wasm/AsmJS.cpp2
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;