Bug 1296814 - Move the Parser::checkFunctionDefinition call, out of Parser::functionDefinition, into its few Statement-related callers. r=anba

--HG--
extra : rebase_source : cfcaa227d7e1d9ae8e4c00313a986a40547f1771
This commit is contained in:
Jeff Walden 2016-11-13 00:05:10 -08:00
parent e383cddaf8
commit 2fdbf4afb3
6 changed files with 118 additions and 96 deletions

View File

@ -667,9 +667,18 @@ class FullParseHandler
ParseNode* pn); ParseNode* pn);
inline void setLastFunctionFormalParameterDestructuring(ParseNode* funcpn, ParseNode* pn); inline void setLastFunctionFormalParameterDestructuring(ParseNode* funcpn, ParseNode* pn);
ParseNode* newFunctionDefinition() { ParseNode* newFunctionStatement() {
return new_<CodeNode>(PNK_FUNCTION, pos()); 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) { bool setComprehensionLambdaBody(ParseNode* pn, ParseNode* body) {
MOZ_ASSERT(body->isKind(PNK_STATEMENTLIST)); MOZ_ASSERT(body->isKind(PNK_STATEMENTLIST));
ParseNode* paramsBody = newList(PNK_PARAMSBODY, body); ParseNode* paramsBody = newList(PNK_PARAMSBODY, body);
@ -696,7 +705,7 @@ class FullParseHandler
} }
ParseNode* newModule() { ParseNode* newModule() {
return new_<CodeNode>(PNK_MODULE, pos()); return new_<CodeNode>(PNK_MODULE, JSOP_NOP, pos());
} }
ParseNode* newLexicalScope(LexicalScope::Data* bindings, ParseNode* body) { ParseNode* newLexicalScope(LexicalScope::Data* bindings, ParseNode* body) {

View File

@ -916,10 +916,14 @@ struct ListNode : public ParseNode
struct CodeNode : public ParseNode struct CodeNode : public ParseNode
{ {
CodeNode(ParseNodeKind kind, const TokenPos& pos) CodeNode(ParseNodeKind kind, JSOp op, const TokenPos& pos)
: ParseNode(kind, JSOP_NOP, PN_CODE, pos) : ParseNode(kind, op, PN_CODE, pos)
{ {
MOZ_ASSERT(kind == PNK_FUNCTION || kind == PNK_MODULE); 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_body);
MOZ_ASSERT(!pn_objbox); MOZ_ASSERT(!pn_objbox);
} }

View File

@ -2293,7 +2293,7 @@ Parser<FullParseHandler>::standaloneFunctionBody(HandleFunction fun,
{ {
MOZ_ASSERT(checkOptionsCalled); MOZ_ASSERT(checkOptionsCalled);
Node fn = handler.newFunctionDefinition(); Node fn = handler.newFunctionStatement();
if (!fn) if (!fn)
return null(); return null();
@ -2971,60 +2971,54 @@ Parser<ParseHandler>::functionArguments(YieldHandling yieldHandling, FunctionSyn
template <typename ParseHandler> template <typename ParseHandler>
bool bool
Parser<ParseHandler>::checkFunctionDefinition(HandleAtom funAtom, Node pn, FunctionSyntaxKind kind, Parser<ParseHandler>::checkFunctionDefinition(HandlePropertyName funName, Node pn,
GeneratorKind generatorKind, bool* tryAnnexB) GeneratorKind generatorKind, bool* tryAnnexB)
{ {
if (kind == Statement) { TokenPos pos = handler.getPosition(pn);
TokenPos pos = handler.getPosition(pn);
RootedPropertyName funName(context, funAtom->asPropertyName());
// In sloppy mode, Annex B.3.2 allows labelled function // In sloppy mode, Annex B.3.2 allows labelled function
// declarations. Otherwise it is a parse error. // declarations. Otherwise it is a parse error.
ParseContext::Statement* declaredInStmt = pc->innermostStatement(); ParseContext::Statement* declaredInStmt = pc->innermostStatement();
if (declaredInStmt && declaredInStmt->kind() == StatementKind::Label) { if (declaredInStmt && declaredInStmt->kind() == StatementKind::Label) {
MOZ_ASSERT(!pc->sc()->strict(), MOZ_ASSERT(!pc->sc()->strict(),
"labeled functions shouldn't be parsed in strict mode"); "labeled functions shouldn't be parsed in strict mode");
// Find the innermost non-label statement. Report an error if it's // Find the innermost non-label statement. Report an error if it's
// unbraced: functions can't appear in it. Otherwise the statement // unbraced: functions can't appear in it. Otherwise the statement
// (or its absence) determines the scope the function's bound in. // (or its absence) determines the scope the function's bound in.
while (declaredInStmt && declaredInStmt->kind() == StatementKind::Label) while (declaredInStmt && declaredInStmt->kind() == StatementKind::Label)
declaredInStmt = declaredInStmt->enclosing(); declaredInStmt = declaredInStmt->enclosing();
if (declaredInStmt && !StatementKindIsBraced(declaredInStmt->kind())) { if (declaredInStmt && !StatementKindIsBraced(declaredInStmt->kind())) {
reportWithOffset(ParseError, false, pos.begin, JSMSG_SLOPPY_FUNCTION_LABEL); reportWithOffset(ParseError, false, pos.begin, JSMSG_SLOPPY_FUNCTION_LABEL);
return false;
}
}
if (declaredInStmt) {
MOZ_ASSERT(declaredInStmt->kind() != StatementKind::Label);
MOZ_ASSERT(StatementKindIsBraced(declaredInStmt->kind()));
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.
if (!tryDeclareVarForAnnexBLexicalFunction(funName, tryAnnexB))
return false; return false;
}
} }
if (declaredInStmt) { if (!noteDeclaredName(funName, DeclarationKind::LexicalFunction, pos))
MOZ_ASSERT(declaredInStmt->kind() != StatementKind::Label); return false;
MOZ_ASSERT(StatementKindIsBraced(declaredInStmt->kind()));
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.
if (!tryDeclareVarForAnnexBLexicalFunction(funName, tryAnnexB))
return false;
}
if (!noteDeclaredName(funName, DeclarationKind::LexicalFunction, pos))
return false;
} else {
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();
}
} else { } else {
// A function expression does not introduce any binding. if (!noteDeclaredName(funName, DeclarationKind::BodyLevelFunction, pos))
handler.setOp(pn, kind == Arrow ? JSOP_LAMBDA_ARROW : JSOP_LAMBDA); return false;
// Body-level functions in modules are always closed over.
if (pc->atModuleLevel())
pc->varScope().lookupDeclaredName(funName)->value()->setClosedOver();
} }
return true; return true;
@ -3152,16 +3146,12 @@ typename ParseHandler::Node
Parser<ParseHandler>::functionDefinition(Node pn, InHandling inHandling, Parser<ParseHandler>::functionDefinition(Node pn, InHandling inHandling,
YieldHandling yieldHandling, HandleAtom funName, YieldHandling yieldHandling, HandleAtom funName,
FunctionSyntaxKind kind, FunctionSyntaxKind kind,
GeneratorKind generatorKind, FunctionAsyncKind asyncKind) GeneratorKind generatorKind, FunctionAsyncKind asyncKind,
bool tryAnnexB /* = false */)
{ {
MOZ_ASSERT_IF(kind == Statement, funName); MOZ_ASSERT_IF(kind == Statement, funName);
MOZ_ASSERT_IF(asyncKind == AsyncFunction, generatorKind == StarGenerator); 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 // When fully parsing a LazyScript, we do not fully reparse its inner
// functions, which are also lazy. Instead, their free variables and // functions, which are also lazy. Instead, their free variables and
// source extents are recorded and may be skipped. // source extents are recorded and may be skipped.
@ -3388,7 +3378,7 @@ Parser<FullParseHandler>::standaloneLazyFunction(HandleFunction fun, bool strict
{ {
MOZ_ASSERT(checkOptionsCalled); MOZ_ASSERT(checkOptionsCalled);
Node pn = handler.newFunctionDefinition(); Node pn = handler.newFunctionStatement();
if (!pn) if (!pn)
return null(); return null();
@ -3590,13 +3580,18 @@ Parser<ParseHandler>::functionStmt(YieldHandling yieldHandling, DefaultHandling
return null(); return null();
} }
Node pn = handler.newFunctionDefinition(); Node pn = handler.newFunctionStatement();
if (!pn) if (!pn)
return null(); 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); YieldHandling newYieldHandling = GetYieldHandling(generatorKind, asyncKind);
return functionDefinition(pn, InAllowed, newYieldHandling, name, Statement, generatorKind, return functionDefinition(pn, InAllowed, newYieldHandling, name, Statement, generatorKind,
asyncKind); asyncKind, tryAnnexB);
} }
template <typename ParseHandler> template <typename ParseHandler>
@ -3632,7 +3627,7 @@ Parser<ParseHandler>::functionExpr(InvokedPrediction invoked, FunctionAsyncKind
tokenStream.ungetToken(); tokenStream.ungetToken();
} }
Node pn = handler.newFunctionDefinition(); Node pn = handler.newFunctionExpression();
if (!pn) if (!pn)
return null(); return null();
@ -6523,31 +6518,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 static GeneratorKind
GeneratorKindFromPropertyType(PropertyType propType) GeneratorKindFromPropertyType(PropertyType propType)
{ {
@ -7726,7 +7696,7 @@ Parser<ParseHandler>::assignExpr(InHandling inHandling, YieldHandling yieldHandl
} }
} }
Node pn = handler.newFunctionDefinition(); Node pn = handler.newArrowFunction();
if (!pn) if (!pn)
return null(); return null();
@ -8069,10 +8039,9 @@ template <typename ParseHandler>
typename ParseHandler::Node typename ParseHandler::Node
Parser<ParseHandler>::generatorComprehensionLambda(unsigned begin) Parser<ParseHandler>::generatorComprehensionLambda(unsigned begin)
{ {
Node genfn = handler.newFunctionDefinition(); Node genfn = handler.newFunctionExpression();
if (!genfn) if (!genfn)
return null(); return null();
handler.setOp(genfn, JSOP_LAMBDA);
ParseContext* outerpc = pc; ParseContext* outerpc = pc;
@ -9356,12 +9325,47 @@ template <typename ParseHandler>
typename ParseHandler::Node typename ParseHandler::Node
Parser<ParseHandler>::methodDefinition(PropertyType propType, HandleAtom funName) Parser<ParseHandler>::methodDefinition(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("unexpected property type");
}
GeneratorKind generatorKind = GeneratorKindFromPropertyType(propType); GeneratorKind generatorKind = GeneratorKindFromPropertyType(propType);
FunctionAsyncKind asyncKind = AsyncKindFromPropertyType(propType); FunctionAsyncKind asyncKind = AsyncKindFromPropertyType(propType);
YieldHandling yieldHandling = GetYieldHandling(generatorKind, asyncKind); YieldHandling yieldHandling = GetYieldHandling(generatorKind, asyncKind);
Node pn = handler.newFunctionDefinition(); Node pn = handler.newFunctionExpression();
if (!pn) if (!pn)
return null(); return null();

View File

@ -1256,7 +1256,8 @@ class Parser final : private JS::AutoGCRooter, public StrictModeGetter
Node functionDefinition(Node func, InHandling inHandling, YieldHandling yieldHandling, Node functionDefinition(Node func, InHandling inHandling, YieldHandling yieldHandling,
HandleAtom name, FunctionSyntaxKind kind, 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 // Parse a function body. Pass StatementListBody if the body is a list of
// statements; pass ExpressionBody if the body is a single expression. // statements; pass ExpressionBody if the body is a single expression.
@ -1342,8 +1343,8 @@ class Parser final : private JS::AutoGCRooter, public StrictModeGetter
Node newDotGeneratorName(); Node newDotGeneratorName();
bool declareDotGeneratorName(); bool declareDotGeneratorName();
bool checkFunctionDefinition(HandleAtom funAtom, Node pn, FunctionSyntaxKind kind, bool checkFunctionDefinition(HandlePropertyName funName, Node pn, GeneratorKind generatorKind,
GeneratorKind generatorKind, bool* tryAnnexB); bool* tryAnnexB);
bool skipLazyInnerFunction(Node pn, FunctionSyntaxKind kind, bool tryAnnexB); bool skipLazyInnerFunction(Node pn, FunctionSyntaxKind kind, bool tryAnnexB);
bool innerFunction(Node pn, ParseContext* outerpc, HandleFunction fun, bool innerFunction(Node pn, ParseContext* outerpc, HandleFunction fun,
InHandling inHandling, YieldHandling yieldHandling, InHandling inHandling, YieldHandling yieldHandling,

View File

@ -344,7 +344,11 @@ class SyntaxParseHandler
Node catchGuard, Node catchBody) { return true; } Node catchGuard, Node catchBody) { return true; }
MOZ_MUST_USE bool setLastFunctionFormalParameterDefault(Node funcpn, Node pn) { return true; } MOZ_MUST_USE bool setLastFunctionFormalParameterDefault(Node funcpn, Node pn) { return true; }
Node newFunctionDefinition() { return NodeFunctionDefinition; }
Node newFunctionStatement() { return NodeFunctionDefinition; }
Node newFunctionExpression() { return NodeFunctionDefinition; }
Node newArrowFunction() { return NodeFunctionDefinition; }
bool setComprehensionLambdaBody(Node pn, Node body) { return true; } bool setComprehensionLambdaBody(Node pn, Node body) { return true; }
void setFunctionFormalParametersAndBody(Node pn, Node kid) {} void setFunctionFormalParametersAndBody(Node pn, Node kid) {}
void setFunctionBody(Node pn, Node kid) {} void setFunctionBody(Node pn, Node kid) {}

View File

@ -7060,7 +7060,7 @@ ParseFunction(ModuleValidator& m, ParseNode** fnOut, unsigned* line)
if (!name) if (!name)
return false; return false;
ParseNode* fn = m.parser().handler.newFunctionDefinition(); ParseNode* fn = m.parser().handler.newFunctionStatement();
if (!fn) if (!fn)
return false; return false;