зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1529448 - Move {hasUsedName,hasUsedNamedeclareFunctionThis,declareFunctionThis,declareFunctionArgumentsObject,declareDotGeneratorName} to ParseContext. r=jorendorff
Differential Revision: https://phabricator.services.mozilla.com/D20779 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
54d153b42a
Коммит
ab3eee7b52
|
@ -2514,8 +2514,8 @@ BinASTParser<Tok>::parseInterfaceEagerFunctionDeclaration(
|
|||
BINJS_TRY_DECL(lexicalScopeData,
|
||||
NewLexicalScopeData(cx_, lexicalScope, alloc_, pc_));
|
||||
BINJS_TRY_DECL(bodyScope, handler_.newLexicalScope(*lexicalScopeData, body));
|
||||
BINJS_MOZ_TRY_DECL(
|
||||
result, buildFunction(start, kind, name, params, bodyScope, funbox));
|
||||
BINJS_MOZ_TRY_DECL(result,
|
||||
buildFunction(start, kind, name, params, bodyScope));
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -2577,8 +2577,8 @@ JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceEagerFunctionExpression(
|
|||
BINJS_TRY_DECL(lexicalScopeData,
|
||||
NewLexicalScopeData(cx_, lexicalScope, alloc_, pc_));
|
||||
BINJS_TRY_DECL(bodyScope, handler_.newLexicalScope(*lexicalScopeData, body));
|
||||
BINJS_MOZ_TRY_DECL(
|
||||
result, buildFunction(start, kind, name, params, bodyScope, funbox));
|
||||
BINJS_MOZ_TRY_DECL(result,
|
||||
buildFunction(start, kind, name, params, bodyScope));
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -2629,8 +2629,7 @@ JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceEagerGetter(
|
|||
ListNode* body;
|
||||
MOZ_TRY(parseGetterContents(length, ¶ms, &body));
|
||||
MOZ_TRY(prependDirectivesToBody(body, directives));
|
||||
BINJS_MOZ_TRY_DECL(method,
|
||||
buildFunction(start, kind, name, params, body, funbox));
|
||||
BINJS_MOZ_TRY_DECL(method, buildFunction(start, kind, name, params, body));
|
||||
BINJS_TRY_DECL(result, handler_.newObjectMethodOrPropertyDefinition(
|
||||
name, method, accessorType));
|
||||
return result;
|
||||
|
@ -2692,8 +2691,7 @@ JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceEagerMethod(
|
|||
ListNode* body;
|
||||
MOZ_TRY(parseFunctionOrMethodContents(length, ¶ms, &body));
|
||||
MOZ_TRY(prependDirectivesToBody(body, directives));
|
||||
BINJS_MOZ_TRY_DECL(method,
|
||||
buildFunction(start, kind, name, params, body, funbox));
|
||||
BINJS_MOZ_TRY_DECL(method, buildFunction(start, kind, name, params, body));
|
||||
BINJS_TRY_DECL(result, handler_.newObjectMethodOrPropertyDefinition(
|
||||
name, method, accessorType));
|
||||
return result;
|
||||
|
@ -2748,8 +2746,7 @@ JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceEagerSetter(
|
|||
ListNode* body;
|
||||
MOZ_TRY(parseSetterContents(length, ¶ms, &body));
|
||||
MOZ_TRY(prependDirectivesToBody(body, directives));
|
||||
BINJS_MOZ_TRY_DECL(method,
|
||||
buildFunction(start, kind, name, params, body, funbox));
|
||||
BINJS_MOZ_TRY_DECL(method, buildFunction(start, kind, name, params, body));
|
||||
BINJS_TRY_DECL(result, handler_.newObjectMethodOrPropertyDefinition(
|
||||
name, method, accessorType));
|
||||
return result;
|
||||
|
|
|
@ -198,7 +198,7 @@ JS::Result<FunctionNode*> BinASTParserPerTokenizer<Tok>::parseLazyFunction(
|
|||
|
||||
auto binKind = isExpr ? BinKind::LazyFunctionExpression
|
||||
: BinKind::LazyFunctionDeclaration;
|
||||
return buildFunction(firstOffset, binKind, nullptr, params, body, funbox);
|
||||
return buildFunction(firstOffset, binKind, nullptr, params, body);
|
||||
}
|
||||
|
||||
template <typename Tok>
|
||||
|
@ -316,7 +316,9 @@ JS::Result<FunctionNode*> BinASTParserPerTokenizer<Tok>::makeEmptyFunctionNode(
|
|||
template <typename Tok>
|
||||
JS::Result<FunctionNode*> BinASTParserPerTokenizer<Tok>::buildFunction(
|
||||
const size_t start, const BinKind kind, ParseNode* name, ListNode* params,
|
||||
ParseNode* body, FunctionBox* funbox) {
|
||||
ParseNode* body) {
|
||||
FunctionBox* funbox = pc_->functionBox();
|
||||
|
||||
// Set the argument count for building argument packets. Function.length is
|
||||
// handled by setting the appropriate funbox field during argument parsing.
|
||||
if (!lazyScript_ ||
|
||||
|
@ -331,63 +333,10 @@ JS::Result<FunctionNode*> BinASTParserPerTokenizer<Tok>::buildFunction(
|
|||
|
||||
handler_.setFunctionFormalParametersAndBody(result, params);
|
||||
|
||||
HandlePropertyName dotThis = cx_->names().dotThis;
|
||||
const bool declareThis = hasUsedName(dotThis) ||
|
||||
funbox->bindingsAccessedDynamically() ||
|
||||
funbox->isDerivedClassConstructor();
|
||||
|
||||
if (declareThis) {
|
||||
ParseContext::Scope& funScope = pc_->functionScope();
|
||||
ParseContext::Scope::AddDeclaredNamePtr p =
|
||||
funScope.lookupDeclaredNameForAdd(dotThis);
|
||||
MOZ_ASSERT(!p);
|
||||
BINJS_TRY(funScope.addDeclaredName(pc_, p, dotThis, DeclarationKind::Var,
|
||||
DeclaredNameInfo::npos));
|
||||
funbox->setHasThisBinding();
|
||||
|
||||
// TODO (efaust): This capture will have to come from encoder side for arrow
|
||||
// functions.
|
||||
}
|
||||
|
||||
// This models PerHandlerParser::declaeFunctionArgumentsObject, with some
|
||||
// subtleties removed, as they don't yet apply to us.
|
||||
HandlePropertyName arguments = cx_->names().arguments;
|
||||
if (hasUsedName(arguments) ||
|
||||
pc_->functionBox()->bindingsAccessedDynamically()) {
|
||||
funbox->usesArguments = true;
|
||||
|
||||
ParseContext::Scope& funScope = pc_->functionScope();
|
||||
ParseContext::Scope::AddDeclaredNamePtr p =
|
||||
funScope.lookupDeclaredNameForAdd(arguments);
|
||||
if (!p) {
|
||||
BINJS_TRY(funScope.addDeclaredName(
|
||||
pc_, p, arguments, DeclarationKind::Var, DeclaredNameInfo::npos));
|
||||
funbox->declaredArguments = true;
|
||||
} else if (p->value()->kind() != DeclarationKind::Var) {
|
||||
// Lexicals, formal parameters, and body level functions shadow.
|
||||
funbox->usesArguments = false;
|
||||
}
|
||||
|
||||
if (funbox->usesArguments) {
|
||||
funbox->setArgumentsHasLocalBinding();
|
||||
|
||||
if (pc_->sc()->bindingsAccessedDynamically() ||
|
||||
pc_->sc()->hasDebuggerStatement()) {
|
||||
funbox->setDefinitelyNeedsArgsObj();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (funbox->needsDotGeneratorName()) {
|
||||
ParseContext::Scope& funScope = pc_->functionScope();
|
||||
HandlePropertyName dotGenerator = cx_->names().dotGenerator;
|
||||
ParseContext::Scope::AddDeclaredNamePtr p =
|
||||
funScope.lookupDeclaredNameForAdd(dotGenerator);
|
||||
if (!p) {
|
||||
BINJS_TRY(funScope.addDeclaredName(
|
||||
pc_, p, dotGenerator, DeclarationKind::Var, DeclaredNameInfo::npos));
|
||||
}
|
||||
BINJS_TRY(pc_->declareDotGeneratorName());
|
||||
|
||||
HandlePropertyName dotGenerator = cx_->names().dotGenerator;
|
||||
BINJS_TRY(usedNames_.noteUse(cx_, dotGenerator, pc_->scriptId(),
|
||||
pc_->innermostScope()->id()));
|
||||
|
||||
|
@ -400,6 +349,12 @@ JS::Result<FunctionNode*> BinASTParserPerTokenizer<Tok>::buildFunction(
|
|||
BINJS_TRY(handler_.prependInitialYield(stmtList, dotGen));
|
||||
}
|
||||
|
||||
const bool canSkipLazyClosedOverBindings = false;
|
||||
BINJS_TRY(pc_->declareFunctionArgumentsObject(usedNames_,
|
||||
canSkipLazyClosedOverBindings));
|
||||
BINJS_TRY(
|
||||
pc_->declareFunctionThis(usedNames_, canSkipLazyClosedOverBindings));
|
||||
|
||||
// Check all our bindings after maybe adding function metavars.
|
||||
MOZ_TRY(checkFunctionClosedVars());
|
||||
|
||||
|
|
|
@ -138,10 +138,10 @@ class BinASTParserPerTokenizer : public BinASTParserBase,
|
|||
JS::Result<FunctionNode*> makeEmptyFunctionNode(const size_t start,
|
||||
const BinKind kind,
|
||||
FunctionBox* funbox);
|
||||
|
||||
JS::Result<FunctionNode*> buildFunction(const size_t start,
|
||||
const BinKind kind, ParseNode* name,
|
||||
ListNode* params, ParseNode* body,
|
||||
FunctionBox* funbox);
|
||||
ListNode* params, ParseNode* body);
|
||||
JS::Result<FunctionBox*> buildFunctionBox(GeneratorKind generatorKind,
|
||||
FunctionAsyncKind functionAsyncKind,
|
||||
FunctionSyntaxKind syntax,
|
||||
|
|
|
@ -940,8 +940,7 @@ EagerFunctionExpression:
|
|||
BINJS_TRY_DECL(bodyScope,
|
||||
handler_.newLexicalScope(*lexicalScopeData, body));
|
||||
BINJS_MOZ_TRY_DECL(result,
|
||||
buildFunction(start, kind, name, params, bodyScope,
|
||||
funbox));
|
||||
buildFunction(start, kind, name, params, bodyScope));
|
||||
|
||||
LazyFunctionExpression:
|
||||
init: |
|
||||
|
@ -1008,7 +1007,7 @@ EagerMethod:
|
|||
inherits: EagerFunctionExpression
|
||||
build: |
|
||||
BINJS_MOZ_TRY_DECL(method,
|
||||
buildFunction(start, kind, name, params, body, funbox));
|
||||
buildFunction(start, kind, name, params, body));
|
||||
BINJS_TRY_DECL(result,
|
||||
handler_.newObjectMethodOrPropertyDefinition(name, method,
|
||||
accessorType));
|
||||
|
|
|
@ -15,6 +15,7 @@ namespace js {
|
|||
namespace frontend {
|
||||
|
||||
using AddDeclaredNamePtr = ParseContext::Scope::AddDeclaredNamePtr;
|
||||
using DeclaredNamePtr = ParseContext::Scope::DeclaredNamePtr;
|
||||
|
||||
const char* DeclarationKindString(DeclarationKind kind) {
|
||||
switch (kind) {
|
||||
|
@ -472,6 +473,149 @@ bool ParseContext::tryDeclareVarHelper(HandlePropertyName name,
|
|||
return true;
|
||||
}
|
||||
|
||||
bool ParseContext::hasUsedName(const UsedNameTracker& usedNames,
|
||||
HandlePropertyName name) {
|
||||
if (auto p = usedNames.lookup(name)) {
|
||||
return p->value().isUsedInScript(scriptId());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ParseContext::hasUsedFunctionSpecialName(const UsedNameTracker& usedNames,
|
||||
HandlePropertyName name) {
|
||||
MOZ_ASSERT(name == sc()->cx_->names().arguments ||
|
||||
name == sc()->cx_->names().dotThis);
|
||||
return hasUsedName(usedNames, name) ||
|
||||
functionBox()->bindingsAccessedDynamically();
|
||||
}
|
||||
|
||||
bool ParseContext::declareFunctionThis(const UsedNameTracker& usedNames,
|
||||
bool canSkipLazyClosedOverBindings) {
|
||||
// The asm.js validator does all its own symbol-table management so, as an
|
||||
// optimization, avoid doing any work here.
|
||||
if (useAsmOrInsideUseAsm()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Derived class constructors emit JSOP_CHECKRETURN, which requires
|
||||
// '.this' to be bound.
|
||||
FunctionBox* funbox = functionBox();
|
||||
HandlePropertyName dotThis = sc()->cx_->names().dotThis;
|
||||
|
||||
bool declareThis;
|
||||
if (canSkipLazyClosedOverBindings) {
|
||||
declareThis = funbox->function()->lazyScript()->hasThisBinding();
|
||||
} else {
|
||||
declareThis = hasUsedFunctionSpecialName(usedNames, dotThis) ||
|
||||
funbox->isDerivedClassConstructor();
|
||||
}
|
||||
|
||||
if (declareThis) {
|
||||
ParseContext::Scope& funScope = functionScope();
|
||||
AddDeclaredNamePtr p = funScope.lookupDeclaredNameForAdd(dotThis);
|
||||
MOZ_ASSERT(!p);
|
||||
if (!funScope.addDeclaredName(this, p, dotThis, DeclarationKind::Var,
|
||||
DeclaredNameInfo::npos)) {
|
||||
return false;
|
||||
}
|
||||
funbox->setHasThisBinding();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ParseContext::declareFunctionArgumentsObject(
|
||||
const UsedNameTracker& usedNames, bool canSkipLazyClosedOverBindings) {
|
||||
FunctionBox* funbox = functionBox();
|
||||
ParseContext::Scope& funScope = functionScope();
|
||||
ParseContext::Scope& _varScope = varScope();
|
||||
|
||||
bool hasExtraBodyVarScope = &funScope != &_varScope;
|
||||
|
||||
// Time to implement the odd semantics of 'arguments'.
|
||||
HandlePropertyName argumentsName = sc()->cx_->names().arguments;
|
||||
|
||||
bool tryDeclareArguments;
|
||||
if (canSkipLazyClosedOverBindings) {
|
||||
tryDeclareArguments =
|
||||
funbox->function()->lazyScript()->shouldDeclareArguments();
|
||||
} else {
|
||||
tryDeclareArguments = hasUsedFunctionSpecialName(usedNames, argumentsName);
|
||||
}
|
||||
|
||||
// ES 9.2.12 steps 19 and 20 say formal parameters, lexical bindings,
|
||||
// and body-level functions named 'arguments' shadow the arguments
|
||||
// object.
|
||||
//
|
||||
// So even if there wasn't a free use of 'arguments' but there is a var
|
||||
// binding of 'arguments', we still might need the arguments object.
|
||||
//
|
||||
// If we have an extra var scope due to parameter expressions and the body
|
||||
// declared 'var arguments', we still need to declare 'arguments' in the
|
||||
// function scope.
|
||||
DeclaredNamePtr p = _varScope.lookupDeclaredName(argumentsName);
|
||||
if (p && p->value()->kind() == DeclarationKind::Var) {
|
||||
if (hasExtraBodyVarScope) {
|
||||
tryDeclareArguments = true;
|
||||
} else {
|
||||
funbox->usesArguments = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (tryDeclareArguments) {
|
||||
AddDeclaredNamePtr p = funScope.lookupDeclaredNameForAdd(argumentsName);
|
||||
if (!p) {
|
||||
if (!funScope.addDeclaredName(this, p, argumentsName,
|
||||
DeclarationKind::Var,
|
||||
DeclaredNameInfo::npos)) {
|
||||
return false;
|
||||
}
|
||||
funbox->declaredArguments = true;
|
||||
funbox->usesArguments = true;
|
||||
} else if (hasExtraBodyVarScope) {
|
||||
// Formal parameters shadow the arguments object.
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Compute if we need an arguments object.
|
||||
if (funbox->usesArguments) {
|
||||
// There is an 'arguments' binding. Is the arguments object definitely
|
||||
// needed?
|
||||
//
|
||||
// Also see the flags' comments in ContextFlags.
|
||||
funbox->setArgumentsHasLocalBinding();
|
||||
|
||||
// Dynamic scope access destroys all hope of optimization.
|
||||
if (sc()->bindingsAccessedDynamically()) {
|
||||
funbox->setDefinitelyNeedsArgsObj();
|
||||
}
|
||||
|
||||
// If a script contains the debugger statement either directly or
|
||||
// within an inner function, the arguments object should be created
|
||||
// eagerly so the Debugger API may observe bindings.
|
||||
if (sc()->hasDebuggerStatement()) {
|
||||
funbox->setDefinitelyNeedsArgsObj();
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ParseContext::declareDotGeneratorName() {
|
||||
// The special '.generator' binding must be on the function scope, as
|
||||
// generators expect to find it on the CallObject.
|
||||
ParseContext::Scope& funScope = functionScope();
|
||||
HandlePropertyName dotGenerator = sc()->cx_->names().dotGenerator;
|
||||
AddDeclaredNamePtr p = funScope.lookupDeclaredNameForAdd(dotGenerator);
|
||||
if (!p &&
|
||||
!funScope.addDeclaredName(this, p, dotGenerator, DeclarationKind::Var,
|
||||
DeclaredNameInfo::npos)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace frontend
|
||||
|
||||
} // namespace js
|
||||
|
|
|
@ -621,6 +621,16 @@ class ParseContext : public Nestable<ParseContext> {
|
|||
mozilla::Maybe<DeclarationKind>* redeclaredKind,
|
||||
uint32_t* prevPos);
|
||||
|
||||
bool hasUsedName(const UsedNameTracker& usedNames, HandlePropertyName name);
|
||||
bool hasUsedFunctionSpecialName(const UsedNameTracker& usedNames,
|
||||
HandlePropertyName name);
|
||||
|
||||
bool declareFunctionThis(const UsedNameTracker& usedNames,
|
||||
bool canSkipLazyClosedOverBindings);
|
||||
bool declareFunctionArgumentsObject(const UsedNameTracker& usedNames,
|
||||
bool canSkipLazyClosedOverBindings);
|
||||
bool declareDotGeneratorName();
|
||||
|
||||
private:
|
||||
mozilla::Maybe<DeclarationKind> isVarRedeclaredInInnermostScope(
|
||||
HandlePropertyName name, DeclarationKind kind);
|
||||
|
|
|
@ -806,13 +806,6 @@ bool ParserBase::noteUsedNameInternal(HandlePropertyName name) {
|
|||
return usedNames_.noteUse(cx_, name, pc_->scriptId(), scope->id());
|
||||
}
|
||||
|
||||
bool ParserSharedBase::hasUsedName(HandlePropertyName name) {
|
||||
if (UsedNamePtr p = usedNames_.lookup(name)) {
|
||||
return p->value().isUsedInScript(pc_->scriptId());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template <class ParseHandler>
|
||||
bool PerHandlerParser<ParseHandler>::
|
||||
propagateFreeNamesAndMarkClosedOverBindings(ParseContext::Scope& scope) {
|
||||
|
@ -1559,46 +1552,6 @@ SyntaxParseHandler::ModuleNodeType Parser<SyntaxParseHandler, Unit>::moduleBody(
|
|||
return SyntaxParseHandler::NodeFailure;
|
||||
}
|
||||
|
||||
bool ParserBase::hasUsedFunctionSpecialName(HandlePropertyName name) {
|
||||
MOZ_ASSERT(name == cx_->names().arguments || name == cx_->names().dotThis);
|
||||
return hasUsedName(name) || pc_->functionBox()->bindingsAccessedDynamically();
|
||||
}
|
||||
|
||||
template <class ParseHandler>
|
||||
bool PerHandlerParser<ParseHandler>::declareFunctionThis() {
|
||||
// The asm.js validator does all its own symbol-table management so, as an
|
||||
// optimization, avoid doing any work here.
|
||||
if (pc_->useAsmOrInsideUseAsm()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Derived class constructors emit JSOP_CHECKRETURN, which requires
|
||||
// '.this' to be bound.
|
||||
FunctionBox* funbox = pc_->functionBox();
|
||||
HandlePropertyName dotThis = cx_->names().dotThis;
|
||||
|
||||
bool declareThis;
|
||||
if (handler_.canSkipLazyClosedOverBindings()) {
|
||||
declareThis = funbox->function()->lazyScript()->hasThisBinding();
|
||||
} else {
|
||||
declareThis = hasUsedFunctionSpecialName(dotThis) ||
|
||||
funbox->isDerivedClassConstructor();
|
||||
}
|
||||
|
||||
if (declareThis) {
|
||||
ParseContext::Scope& funScope = pc_->functionScope();
|
||||
AddDeclaredNamePtr p = funScope.lookupDeclaredNameForAdd(dotThis);
|
||||
MOZ_ASSERT(!p);
|
||||
if (!funScope.addDeclaredName(pc_, p, dotThis, DeclarationKind::Var,
|
||||
DeclaredNameInfo::npos)) {
|
||||
return false;
|
||||
}
|
||||
funbox->setHasThisBinding();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class ParseHandler>
|
||||
typename ParseHandler::NameNodeType
|
||||
PerHandlerParser<ParseHandler>::newInternalDotName(HandlePropertyName name) {
|
||||
|
@ -1624,20 +1577,6 @@ PerHandlerParser<ParseHandler>::newDotGeneratorName() {
|
|||
return newInternalDotName(cx_->names().dotGenerator);
|
||||
}
|
||||
|
||||
bool ParserBase::declareDotGeneratorName() {
|
||||
// The special '.generator' binding must be on the function scope, as
|
||||
// generators expect to find it on the CallObject.
|
||||
ParseContext::Scope& funScope = pc_->functionScope();
|
||||
HandlePropertyName dotGenerator = cx_->names().dotGenerator;
|
||||
AddDeclaredNamePtr p = funScope.lookupDeclaredNameForAdd(dotGenerator);
|
||||
if (!p &&
|
||||
!funScope.addDeclaredName(pc_, p, dotGenerator, DeclarationKind::Var,
|
||||
DeclaredNameInfo::npos)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class ParseHandler>
|
||||
bool PerHandlerParser<ParseHandler>::finishFunctionScopes(
|
||||
bool isStandaloneFunction) {
|
||||
|
@ -1878,83 +1817,6 @@ FunctionNode* Parser<FullParseHandler, Unit>::standaloneFunction(
|
|||
return funNode;
|
||||
}
|
||||
|
||||
template <class ParseHandler>
|
||||
bool PerHandlerParser<ParseHandler>::declareFunctionArgumentsObject() {
|
||||
FunctionBox* funbox = pc_->functionBox();
|
||||
ParseContext::Scope& funScope = pc_->functionScope();
|
||||
ParseContext::Scope& varScope = pc_->varScope();
|
||||
|
||||
bool hasExtraBodyVarScope = &funScope != &varScope;
|
||||
|
||||
// Time to implement the odd semantics of 'arguments'.
|
||||
HandlePropertyName argumentsName = cx_->names().arguments;
|
||||
|
||||
bool tryDeclareArguments;
|
||||
if (handler_.canSkipLazyClosedOverBindings()) {
|
||||
tryDeclareArguments =
|
||||
funbox->function()->lazyScript()->shouldDeclareArguments();
|
||||
} else {
|
||||
tryDeclareArguments = hasUsedFunctionSpecialName(argumentsName);
|
||||
}
|
||||
|
||||
// ES 9.2.12 steps 19 and 20 say formal parameters, lexical bindings,
|
||||
// and body-level functions named 'arguments' shadow the arguments
|
||||
// object.
|
||||
//
|
||||
// So even if there wasn't a free use of 'arguments' but there is a var
|
||||
// binding of 'arguments', we still might need the arguments object.
|
||||
//
|
||||
// If we have an extra var scope due to parameter expressions and the body
|
||||
// declared 'var arguments', we still need to declare 'arguments' in the
|
||||
// function scope.
|
||||
DeclaredNamePtr p = varScope.lookupDeclaredName(argumentsName);
|
||||
if (p && p->value()->kind() == DeclarationKind::Var) {
|
||||
if (hasExtraBodyVarScope) {
|
||||
tryDeclareArguments = true;
|
||||
} else {
|
||||
funbox->usesArguments = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (tryDeclareArguments) {
|
||||
AddDeclaredNamePtr p = funScope.lookupDeclaredNameForAdd(argumentsName);
|
||||
if (!p) {
|
||||
if (!funScope.addDeclaredName(pc_, p, argumentsName, DeclarationKind::Var,
|
||||
DeclaredNameInfo::npos)) {
|
||||
return false;
|
||||
}
|
||||
funbox->declaredArguments = true;
|
||||
funbox->usesArguments = true;
|
||||
} else if (hasExtraBodyVarScope) {
|
||||
// Formal parameters shadow the arguments object.
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Compute if we need an arguments object.
|
||||
if (funbox->usesArguments) {
|
||||
// There is an 'arguments' binding. Is the arguments object definitely
|
||||
// needed?
|
||||
//
|
||||
// Also see the flags' comments in ContextFlags.
|
||||
funbox->setArgumentsHasLocalBinding();
|
||||
|
||||
// Dynamic scope access destroys all hope of optimization.
|
||||
if (pc_->sc()->bindingsAccessedDynamically()) {
|
||||
funbox->setDefinitelyNeedsArgsObj();
|
||||
}
|
||||
|
||||
// If a script contains the debugger statement either directly or
|
||||
// within an inner function, the arguments object should be created
|
||||
// eagerly so the Debugger API may observe bindings.
|
||||
if (pc_->sc()->hasDebuggerStatement()) {
|
||||
funbox->setDefinitelyNeedsArgsObj();
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class ParseHandler, typename Unit>
|
||||
typename ParseHandler::LexicalScopeNodeType
|
||||
GeneralParser<ParseHandler, Unit>::functionBody(InHandling inHandling,
|
||||
|
@ -2024,7 +1886,7 @@ GeneralParser<ParseHandler, Unit>::functionBody(InHandling inHandling,
|
|||
|
||||
if (pc_->needsDotGeneratorName()) {
|
||||
MOZ_ASSERT_IF(!pc_->isAsync(), type == StatementListBody);
|
||||
if (!declareDotGeneratorName()) {
|
||||
if (!pc_->declareDotGeneratorName()) {
|
||||
return null();
|
||||
}
|
||||
NameNodeType generator = newDotGeneratorName();
|
||||
|
@ -2040,10 +1902,13 @@ GeneralParser<ParseHandler, Unit>::functionBody(InHandling inHandling,
|
|||
// finishing up the scope so these special bindings get marked as closed
|
||||
// over if necessary. Arrow functions don't have these bindings.
|
||||
if (kind != FunctionSyntaxKind::Arrow) {
|
||||
if (!declareFunctionArgumentsObject()) {
|
||||
bool canSkipLazyClosedOverBindings =
|
||||
handler_.canSkipLazyClosedOverBindings();
|
||||
if (!pc_->declareFunctionArgumentsObject(usedNames_,
|
||||
canSkipLazyClosedOverBindings)) {
|
||||
return null();
|
||||
}
|
||||
if (!declareFunctionThis()) {
|
||||
if (!pc_->declareFunctionThis(usedNames_, canSkipLazyClosedOverBindings)) {
|
||||
return null();
|
||||
}
|
||||
}
|
||||
|
@ -7266,7 +7131,8 @@ GeneralParser<ParseHandler, Unit>::synthesizeConstructor(
|
|||
return null();
|
||||
}
|
||||
|
||||
if (!declareFunctionThis()) {
|
||||
bool canSkipLazyClosedOverBindings = handler_.canSkipLazyClosedOverBindings();
|
||||
if (!pc_->declareFunctionThis(usedNames_, canSkipLazyClosedOverBindings)) {
|
||||
return null();
|
||||
}
|
||||
|
||||
|
@ -7395,7 +7261,8 @@ GeneralParser<ParseHandler, Unit>::fieldInitializer(YieldHandling yieldHandling,
|
|||
handler_.setBeginPosition(initializerAssignment, initializerExpr);
|
||||
handler_.setEndPosition(initializerAssignment, initializerExpr);
|
||||
|
||||
if (!declareFunctionThis()) {
|
||||
bool canSkipLazyClosedOverBindings = handler_.canSkipLazyClosedOverBindings();
|
||||
if (!pc_->declareFunctionThis(usedNames_, canSkipLazyClosedOverBindings)) {
|
||||
return null();
|
||||
}
|
||||
|
||||
|
|
|
@ -272,9 +272,6 @@ class MOZ_STACK_CLASS ParserSharedBase : private JS::AutoGCRooter {
|
|||
friend void js::frontend::TraceBinParser(JSTracer* trc,
|
||||
JS::AutoGCRooter* parser);
|
||||
|
||||
protected:
|
||||
bool hasUsedName(HandlePropertyName name);
|
||||
|
||||
private:
|
||||
// Create a new traceable node and store it into the trace list.
|
||||
template <typename BoxT, typename ArgT>
|
||||
|
@ -446,12 +443,9 @@ class MOZ_STACK_CLASS ParserBase : public ParserSharedBase,
|
|||
bool nextTokenContinuesLetDeclaration(TokenKind next);
|
||||
|
||||
bool noteUsedNameInternal(HandlePropertyName name);
|
||||
bool hasUsedFunctionSpecialName(HandlePropertyName name);
|
||||
|
||||
bool checkAndMarkSuperScope();
|
||||
|
||||
bool declareDotGeneratorName();
|
||||
|
||||
bool leaveInnerFunction(ParseContext* outerpc);
|
||||
|
||||
JSAtom* prefixAccessorName(PropertyType propType, HandleAtom propAtom);
|
||||
|
@ -553,9 +547,6 @@ class MOZ_STACK_CLASS PerHandlerParser : public ParserBase {
|
|||
Node body);
|
||||
bool finishFunction(bool isStandaloneFunction = false);
|
||||
|
||||
bool declareFunctionThis();
|
||||
bool declareFunctionArgumentsObject();
|
||||
|
||||
inline NameNodeType newName(PropertyName* name);
|
||||
inline NameNodeType newName(PropertyName* name, TokenPos pos);
|
||||
|
||||
|
@ -750,7 +741,6 @@ class MOZ_STACK_CLASS GeneralParser : public PerHandlerParser<ParseHandler> {
|
|||
using Base::finishLexicalScope;
|
||||
using Base::foldConstants_;
|
||||
using Base::getFilename;
|
||||
using Base::hasUsedFunctionSpecialName;
|
||||
using Base::hasValidSimpleStrictParameterNames;
|
||||
using Base::isUnexpectedEOF_;
|
||||
using Base::keepAtoms_;
|
||||
|
@ -813,11 +803,7 @@ class MOZ_STACK_CLASS GeneralParser : public PerHandlerParser<ParseHandler> {
|
|||
|
||||
private:
|
||||
using Base::checkAndMarkSuperScope;
|
||||
using Base::declareDotGeneratorName;
|
||||
using Base::declareFunctionArgumentsObject;
|
||||
using Base::declareFunctionThis;
|
||||
using Base::finishFunction;
|
||||
using Base::hasUsedName;
|
||||
using Base::identifierReference;
|
||||
using Base::leaveInnerFunction;
|
||||
using Base::newDotGeneratorName;
|
||||
|
|
Загрузка…
Ссылка в новой задаче