mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-04 23:08:39 +09:00
Issue #2173 - Add accessors to LexicalScopeNode
Based-on: m-c 1479659/7
This commit is contained in:
parent
a49f4d0483
commit
3bd300e263
12 changed files with 180 additions and 171 deletions
|
|
@ -2380,8 +2380,8 @@ ASTSerializer::tryStatement(TernaryNode* tryNode, MutableHandleValue dst)
|
|||
if (!guarded.reserve(catchList->count()))
|
||||
return false;
|
||||
|
||||
for (ParseNode* catchScope : catchList->contents()) {
|
||||
MOZ_ASSERT(catchScope->isKind(PNK_LEXICALSCOPE));
|
||||
for (ParseNode* catchNode : catchList->contents()) {
|
||||
LexicalScopeNode* catchScope = &catchNode->as<LexicalScopeNode>();
|
||||
RootedValue clause(cx);
|
||||
bool isGuarded;
|
||||
if (!catchClause(&catchScope->scopeBody()->as<TernaryNode>(), &isGuarded, &clause))
|
||||
|
|
@ -2480,7 +2480,7 @@ ASTSerializer::statement(ParseNode* pn, MutableHandleValue dst)
|
|||
return builder.emptyStatement(&pn->pn_pos, dst);
|
||||
|
||||
case PNK_LEXICALSCOPE:
|
||||
pn = pn->scopeBody();
|
||||
pn = pn->as<LexicalScopeNode>().scopeBody();
|
||||
if (!pn->isKind(PNK_STATEMENTLIST))
|
||||
return statement(pn, dst);
|
||||
MOZ_FALLTHROUGH;
|
||||
|
|
@ -2578,8 +2578,9 @@ ASTSerializer::statement(ParseNode* pn, MutableHandleValue dst)
|
|||
|
||||
if (head->isKind(PNK_FORIN) || head->isKind(PNK_FOROF)) {
|
||||
RootedValue var(cx);
|
||||
if (initNode->isKind(PNK_LEXICALSCOPE)) {
|
||||
if (!variableDeclaration(&initNode->scopeBody()->as<ListNode>(), true, &var))
|
||||
if (initNode->is<LexicalScopeNode>()) {
|
||||
LexicalScopeNode* scopeNode = &initNode->as<LexicalScopeNode>();
|
||||
if (!variableDeclaration(&scopeNode->scopeBody()->as<ListNode>(), true, &var))
|
||||
return false;
|
||||
} else if (!initNode->isKind(PNK_VAR) &&
|
||||
!initNode->isKind(PNK_LET) &&
|
||||
|
|
@ -2810,8 +2811,8 @@ ASTSerializer::comprehensionBlock(ForNode* forNode, MutableHandleValue dst)
|
|||
bool isForOf = in->isKind(PNK_FOROF);
|
||||
|
||||
ListNode* decl;
|
||||
if (in->kid1()->isKind(PNK_LEXICALSCOPE))
|
||||
decl = &in->kid1()->scopeBody()->as<ListNode>();
|
||||
if (in->kid1()->is<LexicalScopeNode>())
|
||||
decl = &in->kid1()->as<LexicalScopeNode>().scopeBody()->as<ListNode>();
|
||||
else
|
||||
decl = &in->kid1()->as<ListNode>();
|
||||
MOZ_ASSERT(decl->count() == 1);
|
||||
|
|
@ -2840,8 +2841,8 @@ ASTSerializer::comprehension(ParseNode* pn, MutableHandleValue dst)
|
|||
// 1. The kind that was in ES4 for a while: [z for (x in y)]
|
||||
// 2. The kind that was in ES6 for a while: [for (x of y) z]
|
||||
// They have slightly different parse trees and scoping.
|
||||
bool isLegacy = pn->isKind(PNK_LEXICALSCOPE);
|
||||
ParseNode* next = isLegacy ? pn->scopeBody() : pn;
|
||||
bool isLegacy = pn->is<LexicalScopeNode>();
|
||||
ParseNode* next = isLegacy ? pn->as<LexicalScopeNode>().scopeBody() : pn;
|
||||
LOCAL_ASSERT(next->isKind(PNK_COMPREHENSIONFOR));
|
||||
|
||||
NodeVector blocks(cx);
|
||||
|
|
@ -2886,8 +2887,8 @@ ASTSerializer::generatorExpression(ParseNode* pn, MutableHandleValue dst)
|
|||
// Just as there are two kinds of array comprehension (see
|
||||
// ASTSerializer::comprehension), there are legacy and modern generator
|
||||
// expression.
|
||||
bool isLegacy = pn->isKind(PNK_LEXICALSCOPE);
|
||||
ParseNode* next = isLegacy ? pn->scopeBody() : pn;
|
||||
bool isLegacy = pn->is<LexicalScopeNode>();
|
||||
ParseNode* next = isLegacy ? pn->as<LexicalScopeNode>().scopeBody() : pn;
|
||||
LOCAL_ASSERT(next->isKind(PNK_COMPREHENSIONFOR));
|
||||
|
||||
NodeVector blocks(cx);
|
||||
|
|
@ -3653,29 +3654,29 @@ ASTSerializer::functionArgsAndBody(ParseNode* pn, NodeVector& args, NodeVector&
|
|||
MutableHandleValue body, MutableHandleValue rest)
|
||||
{
|
||||
ListNode* argsList;
|
||||
ParseNode* pnbody;
|
||||
ParseNode* bodyNode;
|
||||
|
||||
/* Extract the args and body separately. */
|
||||
if (pn->isKind(PNK_PARAMSBODY)) {
|
||||
argsList = &pn->as<ListNode>();
|
||||
pnbody = argsList->last();
|
||||
bodyNode = argsList->last();
|
||||
} else {
|
||||
argsList = nullptr;
|
||||
pnbody = pn;
|
||||
bodyNode = pn;
|
||||
}
|
||||
|
||||
if (pnbody->isKind(PNK_LEXICALSCOPE))
|
||||
pnbody = pnbody->scopeBody();
|
||||
if (bodyNode->is<LexicalScopeNode>())
|
||||
bodyNode = bodyNode->as<LexicalScopeNode>().scopeBody();
|
||||
|
||||
/* Serialize the arguments and body. */
|
||||
switch (pnbody->getKind()) {
|
||||
switch (bodyNode->getKind()) {
|
||||
case PNK_RETURN: /* expression closure, no destructured args */
|
||||
return functionArgs(pn, argsList, args, defaults, rest) &&
|
||||
expression(pnbody->as<UnaryNode>().kid(), body);
|
||||
expression(bodyNode->as<UnaryNode>().kid(), body);
|
||||
|
||||
case PNK_STATEMENTLIST: /* statement closure */
|
||||
{
|
||||
ParseNode* firstNode = pnbody->as<ListNode>().head();
|
||||
ParseNode* firstNode = bodyNode->as<ListNode>().head();
|
||||
|
||||
// Skip over initial yield in generator.
|
||||
if (firstNode && firstNode->isKind(PNK_INITIALYIELD)) {
|
||||
|
|
@ -3692,7 +3693,7 @@ ASTSerializer::functionArgsAndBody(ParseNode* pn, NodeVector& args, NodeVector&
|
|||
}
|
||||
|
||||
return functionArgs(pn, argsList, args, defaults, rest) &&
|
||||
functionBody(firstNode, &pnbody->pn_pos, body);
|
||||
functionBody(firstNode, &bodyNode->pn_pos, body);
|
||||
}
|
||||
|
||||
default:
|
||||
|
|
|
|||
|
|
@ -592,8 +592,8 @@ BytecodeEmitter::emitLoopHead(ParseNode* nextpn, JumpTarget* top)
|
|||
* instruction. nextpn is often a block, in which case the next
|
||||
* instruction typically comes from the first statement inside.
|
||||
*/
|
||||
if (nextpn->isKind(PNK_LEXICALSCOPE))
|
||||
nextpn = nextpn->scopeBody();
|
||||
if (nextpn->is<LexicalScopeNode>())
|
||||
nextpn = nextpn->as<LexicalScopeNode>().scopeBody();
|
||||
if (nextpn->isKind(PNK_STATEMENTLIST)) {
|
||||
if (ParseNode* firstStatement = nextpn->as<ListNode>().head()) {
|
||||
nextpn = firstStatement;
|
||||
|
|
@ -612,8 +612,8 @@ BytecodeEmitter::emitLoopEntry(ParseNode* nextpn, JumpList entryJump)
|
|||
{
|
||||
if (nextpn) {
|
||||
/* Update the line number, as for LOOPHEAD. */
|
||||
if (nextpn->isKind(PNK_LEXICALSCOPE))
|
||||
nextpn = nextpn->scopeBody();
|
||||
if (nextpn->is<LexicalScopeNode>())
|
||||
nextpn = nextpn->as<LexicalScopeNode>().scopeBody();
|
||||
if (nextpn->isKind(PNK_STATEMENTLIST)) {
|
||||
if (ParseNode* firstStatement = nextpn->as<ListNode>().head()) {
|
||||
nextpn = firstStatement;
|
||||
|
|
@ -1487,7 +1487,7 @@ BytecodeEmitter::checkSideEffects(ParseNode* pn, bool* answer)
|
|||
|
||||
case PNK_LEXICALSCOPE:
|
||||
MOZ_ASSERT(pn->isArity(PN_SCOPE));
|
||||
return checkSideEffects(pn->scopeBody(), answer);
|
||||
return checkSideEffects(pn->as<LexicalScopeNode>().scopeBody(), answer);
|
||||
|
||||
// We could methodically check every interpolated expression, but it's
|
||||
// probably not worth the trouble. Treat template strings as effect-free
|
||||
|
|
@ -2080,8 +2080,7 @@ BytecodeEmitter::emitNumberOp(double dval)
|
|||
MOZ_NEVER_INLINE bool
|
||||
BytecodeEmitter::emitSwitch(SwitchStatement* switchStmt)
|
||||
{
|
||||
ParseNode& lexical = switchStmt->lexicalForCaseList();
|
||||
MOZ_ASSERT(lexical.isKind(PNK_LEXICALSCOPE));
|
||||
LexicalScopeNode& lexical = switchStmt->lexicalForCaseList();
|
||||
ListNode* cases = &lexical.scopeBody()->as<ListNode>();
|
||||
MOZ_ASSERT(cases->isKind(PNK_STATEMENTLIST));
|
||||
|
||||
|
|
@ -2343,20 +2342,21 @@ BytecodeEmitter::emitScript(ParseNode* body)
|
|||
setFunctionBodyEndPos(body->pn_pos);
|
||||
|
||||
if (sc->isEvalContext() && !sc->strict() &&
|
||||
body->isKind(PNK_LEXICALSCOPE) && !body->isEmptyScope())
|
||||
body->is<LexicalScopeNode>() && !body->as<LexicalScopeNode>().isEmptyScope())
|
||||
{
|
||||
// Sloppy eval scripts may need to emit DEFFUNs in the prologue. If there is
|
||||
// an immediately enclosed lexical scope, we need to enter the lexical
|
||||
// scope in the prologue for the DEFFUNs to pick up the right
|
||||
// environment chain.
|
||||
EmitterScope lexicalEmitterScope(this);
|
||||
LexicalScopeNode* scope = &body->as<LexicalScopeNode>();
|
||||
|
||||
switchToPrologue();
|
||||
if (!lexicalEmitterScope.enterLexical(this, ScopeKind::Lexical, body->scopeBindings()))
|
||||
if (!lexicalEmitterScope.enterLexical(this, ScopeKind::Lexical, scope->scopeBindings()))
|
||||
return false;
|
||||
switchToMain();
|
||||
|
||||
if (!emitLexicalScopeBody(body->scopeBody()))
|
||||
if (!emitLexicalScopeBody(scope->scopeBody()))
|
||||
return false;
|
||||
|
||||
if (!lexicalEmitterScope.leave(this))
|
||||
|
|
@ -4272,13 +4272,13 @@ BytecodeEmitter::emitTry(TernaryNode* tryNode)
|
|||
// code if appropriate, and is also used for the catch-all trynote for
|
||||
// capturing exceptions thrown from catch{} blocks.
|
||||
//
|
||||
for (ParseNode* lexicalScope : catchList->as<ListNode>().contents()) {
|
||||
for (ParseNode* scopeNode : catchList->as<ListNode>().contents()) {
|
||||
LexicalScopeNode* catchScope = &scopeNode->as<LexicalScopeNode>();
|
||||
if (!tryCatch.emitCatch())
|
||||
return false;
|
||||
|
||||
// Emit the lexical scope and catch body.
|
||||
MOZ_ASSERT(lexicalScope->isKind(PNK_LEXICALSCOPE));
|
||||
if (!emitTree(lexicalScope))
|
||||
if (!emitTree(catchScope))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -4387,14 +4387,12 @@ BytecodeEmitter::emitLexicalScopeBody(ParseNode* body, EmitLineNumberNote emitLi
|
|||
// Using MOZ_NEVER_INLINE in here is a workaround for llvm.org/pr14047. See
|
||||
// the comment on emitSwitch.
|
||||
MOZ_NEVER_INLINE bool
|
||||
BytecodeEmitter::emitLexicalScope(ParseNode* pn)
|
||||
BytecodeEmitter::emitLexicalScope(LexicalScopeNode* lexicalScope)
|
||||
{
|
||||
MOZ_ASSERT(pn->isKind(PNK_LEXICALSCOPE));
|
||||
|
||||
TDZCheckCache tdzCache(this);
|
||||
|
||||
ParseNode* body = pn->scopeBody();
|
||||
if (pn->isEmptyScope())
|
||||
ParseNode* body = lexicalScope->scopeBody();
|
||||
if (lexicalScope->isEmptyScope())
|
||||
return emitLexicalScopeBody(body);
|
||||
|
||||
// Update line number notes before emitting TDZ poison in
|
||||
|
|
@ -4431,7 +4429,7 @@ BytecodeEmitter::emitLexicalScope(ParseNode* pn)
|
|||
} else
|
||||
kind = ScopeKind::Lexical;
|
||||
|
||||
if (!emitterScope.enterLexical(this, kind, pn->scopeBindings()))
|
||||
if (!emitterScope.enterLexical(this, kind, lexicalScope->scopeBindings()))
|
||||
return false;
|
||||
|
||||
if (body->isKind(PNK_FOR)) {
|
||||
|
|
@ -5310,7 +5308,7 @@ BytecodeEmitter::emitComprehensionForInOrOfVariables(ParseNode* pn, bool* lexica
|
|||
// for-in/of loops, and we haven't extended these requirements to
|
||||
// comprehension syntax.
|
||||
|
||||
*lexicalScope = pn->isKind(PNK_LEXICALSCOPE);
|
||||
*lexicalScope = pn->is<LexicalScopeNode>();
|
||||
if (*lexicalScope) {
|
||||
// This is initially-ES7-tracked syntax, now with considerably murkier
|
||||
// outlook. The scope work is done by the caller by instantiating an
|
||||
|
|
@ -5369,9 +5367,10 @@ BytecodeEmitter::emitComprehensionForOf(ForNode* forNode)
|
|||
Maybe<EmitterScope> emitterScope;
|
||||
ParseNode* loopVariableName;
|
||||
if (lexicalScope) {
|
||||
loopVariableName = parser->handler.singleBindingFromDeclaration(&loopDecl->scopeBody()->as<ListNode>());
|
||||
LexicalScopeNode* scopeNode = &loopDecl->as<LexicalScopeNode>();
|
||||
loopVariableName = parser->handler.singleBindingFromDeclaration(&scopeNode->scopeBody()->as<ListNode>());
|
||||
emitterScope.emplace(this);
|
||||
if (!emitterScope->enterComprehensionFor(this, loopDecl->scopeBindings()))
|
||||
if (!emitterScope->enterComprehensionFor(this, scopeNode->scopeBindings()))
|
||||
return false;
|
||||
} else {
|
||||
loopVariableName = parser->handler.singleBindingFromDeclaration(&loopDecl->as<ListNode>());
|
||||
|
|
@ -5515,7 +5514,8 @@ BytecodeEmitter::emitComprehensionForIn(ForNode* forNode)
|
|||
Maybe<EmitterScope> emitterScope;
|
||||
if (lexicalScope) {
|
||||
emitterScope.emplace(this);
|
||||
if (!emitterScope->enterComprehensionFor(this, loopDecl->scopeBindings()))
|
||||
LexicalScopeNode* scopeNode = &loopDecl->as<LexicalScopeNode>();
|
||||
if (!emitterScope->enterComprehensionFor(this, scopeNode->scopeBindings()))
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -8945,7 +8945,7 @@ BytecodeEmitter::emitTree(ParseNode* pn, ValueUsage valueUsage /* = ValueUsage::
|
|||
break;
|
||||
|
||||
case PNK_LEXICALSCOPE:
|
||||
if (!emitLexicalScope(pn))
|
||||
if (!emitLexicalScope(&pn->as<LexicalScopeNode>()))
|
||||
return false;
|
||||
break;
|
||||
|
||||
|
|
|
|||
|
|
@ -588,7 +588,7 @@ struct MOZ_STACK_CLASS BytecodeEmitter
|
|||
MOZ_MUST_USE bool emitWith(BinaryNode* withNode);
|
||||
|
||||
MOZ_NEVER_INLINE MOZ_MUST_USE bool emitLabeledStatement(const LabeledStatement* pn);
|
||||
MOZ_NEVER_INLINE MOZ_MUST_USE bool emitLexicalScope(ParseNode* pn);
|
||||
MOZ_NEVER_INLINE MOZ_MUST_USE bool emitLexicalScope(LexicalScopeNode* lexicalScope);
|
||||
MOZ_MUST_USE bool emitLexicalScopeBody(ParseNode* body,
|
||||
EmitLineNumberNote emitLineNote = EMIT_LINENOTE);
|
||||
MOZ_NEVER_INLINE MOZ_MUST_USE bool emitSwitch(SwitchStatement* switchStmt);
|
||||
|
|
|
|||
|
|
@ -207,8 +207,8 @@ ContainsHoistedDeclaration(ExclusiveContext* cx, ParseNode* node, bool* result)
|
|||
|
||||
if (tryNode->kid2()) {
|
||||
if (ListNode* catchList = &tryNode->kid2()->as<ListNode>()) {
|
||||
for (ParseNode* lexicalScope : catchList->contents()) {
|
||||
MOZ_ASSERT(lexicalScope->isKind(PNK_LEXICALSCOPE));
|
||||
for (ParseNode* scopeNode : catchList->contents()) {
|
||||
LexicalScopeNode* lexicalScope = &scopeNode->as<LexicalScopeNode>();
|
||||
|
||||
TernaryNode* catchNode = &lexicalScope->scopeBody()->as<TernaryNode>();
|
||||
MOZ_ASSERT(catchNode->isKind(PNK_CATCH));
|
||||
|
|
@ -286,14 +286,14 @@ ContainsHoistedDeclaration(ExclusiveContext* cx, ParseNode* node, bool* result)
|
|||
}
|
||||
|
||||
case PNK_LEXICALSCOPE: {
|
||||
MOZ_ASSERT(node->isArity(PN_SCOPE));
|
||||
ParseNode* expr = node->scopeBody();
|
||||
LexicalScopeNode* scope = &node->as<LexicalScopeNode>();
|
||||
ParseNode* expr = scope->scopeBody();
|
||||
|
||||
if (expr->isKind(PNK_FOR) || expr->isKind(PNK_FUNCTION))
|
||||
return ContainsHoistedDeclaration(cx, expr, result);
|
||||
|
||||
MOZ_ASSERT(expr->isKind(PNK_STATEMENTLIST));
|
||||
return ListContainsHoistedDeclaration(cx, &node->scopeBody()->as<ListNode>(), result);
|
||||
return ListContainsHoistedDeclaration(cx, &scope->scopeBody()->as<ListNode>(), result);
|
||||
}
|
||||
|
||||
// List nodes with all non-null children.
|
||||
|
|
@ -1966,11 +1966,12 @@ Fold(ExclusiveContext* cx, ParseNode** pnp, Parser<FullParseHandler>& parser, bo
|
|||
case PNK_DOT:
|
||||
return FoldDottedProperty(cx, &pn->as<PropertyAccessBase>(), parser, inGenexpLambda);
|
||||
|
||||
case PNK_LEXICALSCOPE:
|
||||
MOZ_ASSERT(pn->isArity(PN_SCOPE));
|
||||
if (!pn->scopeBody())
|
||||
case PNK_LEXICALSCOPE: {
|
||||
LexicalScopeNode* node = &pn->as<LexicalScopeNode>();
|
||||
if (!node->scopeBody())
|
||||
return true;
|
||||
return Fold(cx, &pn->pn_u.scope.body, parser, inGenexpLambda);
|
||||
return Fold(cx, node->unsafeScopeBodyReference(), parser, inGenexpLambda);
|
||||
}
|
||||
|
||||
case PNK_NAME:
|
||||
return FoldName(cx, &pn->as<NameNode>(), parser, inGenexpLambda);
|
||||
|
|
|
|||
|
|
@ -648,7 +648,7 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS)
|
|||
}
|
||||
|
||||
SwitchStatementType newSwitchStatement(uint32_t begin, Node discriminant,
|
||||
Node lexicalForCaseList, bool hasDefault)
|
||||
LexicalScopeNodeType lexicalForCaseList, bool hasDefault)
|
||||
{
|
||||
return new_<SwitchStatement>(begin, discriminant, lexicalForCaseList, hasDefault);
|
||||
}
|
||||
|
|
@ -714,7 +714,7 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS)
|
|||
return new_<OptionalPropertyByValue>(lhs, index, lhs->pn_pos.begin, end);
|
||||
}
|
||||
|
||||
inline MOZ_MUST_USE bool addCatchBlock(ListNodeType catchList, ParseNode* lexicalScope,
|
||||
inline MOZ_MUST_USE bool addCatchBlock(ListNodeType catchList, LexicalScopeNodeType lexicalScope,
|
||||
ParseNode* catchBinding, ParseNode* catchGuard,
|
||||
ParseNode* catchBody);
|
||||
|
||||
|
|
@ -759,7 +759,7 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS)
|
|||
void addFunctionFormalParameter(CodeNodeType funNode, Node argpn) {
|
||||
addList(/* list = */ funNode->body(), /* child = */ argpn);
|
||||
}
|
||||
void setFunctionBody(CodeNodeType funNode, Node body) {
|
||||
void setFunctionBody(CodeNodeType funNode, LexicalScopeNodeType body) {
|
||||
MOZ_ASSERT(funNode->body()->isKind(PNK_PARAMSBODY));
|
||||
addList(/* list = */ funNode->body(), /* child = */ body);
|
||||
}
|
||||
|
|
@ -772,7 +772,7 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS)
|
|||
return new_<BinaryNode>(PNK_NEW, JSOP_NEW, TokenPos(begin, args->pn_pos.end), ctor, args);
|
||||
}
|
||||
|
||||
ParseNode* newLexicalScope(LexicalScope::Data* bindings, ParseNode* body) {
|
||||
LexicalScopeNodeType newLexicalScope(LexicalScope::Data* bindings, Node body) {
|
||||
return new_<LexicalScopeNode>(bindings, body);
|
||||
}
|
||||
|
||||
|
|
@ -1002,7 +1002,7 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS)
|
|||
};
|
||||
|
||||
inline bool
|
||||
FullParseHandler::addCatchBlock(ListNodeType catchList, ParseNode* lexicalScope,
|
||||
FullParseHandler::addCatchBlock(ListNodeType catchList, LexicalScopeNodeType lexicalScope,
|
||||
ParseNode* catchBinding, ParseNode* catchGuard, ParseNode* catchBody)
|
||||
{
|
||||
ParseNode* catchpn = newTernary(PNK_CATCH, catchBinding, catchGuard, catchBody);
|
||||
|
|
|
|||
|
|
@ -828,10 +828,10 @@ class NameResolver
|
|||
case PNK_CATCHLIST: {
|
||||
ListNode* catchList = &cur->as<ListNode>();
|
||||
for (ParseNode* catchNode : catchList->contents()) {
|
||||
MOZ_ASSERT(catchNode->isKind(PNK_LEXICALSCOPE));
|
||||
MOZ_ASSERT(catchNode->scopeBody()->isKind(PNK_CATCH));
|
||||
MOZ_ASSERT(catchNode->scopeBody()->isArity(PN_TERNARY));
|
||||
if (!resolve(catchNode->scopeBody(), prefix))
|
||||
LexicalScopeNode* catchScope = &catchNode->as<LexicalScopeNode>();
|
||||
MOZ_ASSERT(catchScope->scopeBody()->isKind(PNK_CATCH));
|
||||
MOZ_ASSERT(catchScope->scopeBody()->isArity(PN_TERNARY));
|
||||
if (!resolve(catchScope->scopeBody(), prefix))
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
|
@ -862,8 +862,7 @@ class NameResolver
|
|||
break;
|
||||
|
||||
case PNK_LEXICALSCOPE:
|
||||
MOZ_ASSERT(cur->isArity(PN_SCOPE));
|
||||
if (!resolve(cur->scopeBody(), prefix))
|
||||
if (!resolve(cur->as<LexicalScopeNode>().scopeBody(), prefix))
|
||||
return false;
|
||||
break;
|
||||
|
||||
|
|
|
|||
|
|
@ -96,8 +96,6 @@ enum class PushResult { Recyclable, CleanUpLater };
|
|||
static PushResult
|
||||
PushCodeNodeChildren(CodeNode* node, NodeStack* stack)
|
||||
{
|
||||
MOZ_ASSERT(node->isArity(PN_CODE));
|
||||
|
||||
/*
|
||||
* Function nodes are linked into the function box tree, and may appear
|
||||
* on method lists. Both of those lists are singly-linked, so trying to
|
||||
|
|
@ -133,10 +131,8 @@ PushNameNodeChildren(NameNode* node, NodeStack* stack)
|
|||
}
|
||||
|
||||
static PushResult
|
||||
PushScopeNodeChildren(ParseNode* node, NodeStack* stack)
|
||||
PushScopeNodeChildren(LexicalScopeNode* node, NodeStack* stack)
|
||||
{
|
||||
MOZ_ASSERT(node->isArity(PN_SCOPE));
|
||||
|
||||
if (node->scopeBody())
|
||||
stack->push(node->scopeBody());
|
||||
node->setScopeBody(nullptr);
|
||||
|
|
@ -146,7 +142,6 @@ PushScopeNodeChildren(ParseNode* node, NodeStack* stack)
|
|||
static PushResult
|
||||
PushListNodeChildren(ListNode* node, NodeStack* stack)
|
||||
{
|
||||
MOZ_ASSERT(node->isArity(PN_LIST));
|
||||
node->checkConsistency();
|
||||
|
||||
stack->pushList(node);
|
||||
|
|
@ -508,7 +503,7 @@ PushNodeChildren(ParseNode* pn, NodeStack* stack)
|
|||
return PushNameNodeChildren(&pn->as<NameNode>(), stack);
|
||||
|
||||
case PNK_LEXICALSCOPE:
|
||||
return PushScopeNodeChildren(pn, stack);
|
||||
return PushScopeNodeChildren(&pn->as<LexicalScopeNode>(), stack);
|
||||
|
||||
case PNK_FUNCTION:
|
||||
case PNK_MODULE:
|
||||
|
|
@ -701,7 +696,7 @@ ParseNode::dump(int indent)
|
|||
as<LoopControlStatement>().dump(indent);
|
||||
return;
|
||||
case PN_SCOPE:
|
||||
((LexicalScopeNode*) this)->dump(indent);
|
||||
as<LexicalScopeNode>().dump(indent);
|
||||
return;
|
||||
}
|
||||
fprintf(stderr, "#<BAD NODE %p, kind=%u, arity=%u>",
|
||||
|
|
|
|||
|
|
@ -312,9 +312,9 @@ IsTypeofKind(ParseNodeKind kind)
|
|||
* kid1: try block
|
||||
* kid2: null or PNK_CATCHLIST list
|
||||
* kid3: null or finally block
|
||||
* PNK_CATCHLIST list pn_head: list of PNK_LEXICALSCOPE nodes, one per
|
||||
* catch-block, each with scopeBody pointing
|
||||
* to a PNK_CATCH node
|
||||
* PNK_CATCHLIST (ListNode)
|
||||
* head: list of PNK_LEXICALSCOPE nodes, one per catch-block,
|
||||
* each with scopeBody pointing to a PNK_CATCH node
|
||||
* PNK_CATCH (TernaryNode)
|
||||
* kid1: PNK_NAME, PNK_ARRAY, or PNK_OBJECT catch binding node (PNK_ARRAY or PNK_OBJECT if destructuring)
|
||||
or null if optional catch binding
|
||||
|
|
@ -524,8 +524,9 @@ IsTypeofKind(ParseNodeKind kind)
|
|||
* PNK_SETTHIS (BinaryNode)
|
||||
* left: '.this' Name
|
||||
* right: SuperCall
|
||||
* PNK_LEXICALSCOPE scope pn_u.scope.bindings: scope bindings
|
||||
* pn_u.scope.body: scope body
|
||||
* PNK_LEXICALSCOPE (LexicalScopeNode)
|
||||
* scopeBindings: scope bindings
|
||||
* scopeBody: scope body
|
||||
* PNK_GENERATOR (NullaryNode)
|
||||
* PNK_INITIALYIELD (UnaryNode)
|
||||
* kid: generator object
|
||||
|
|
@ -567,6 +568,8 @@ enum ParseNodeArity
|
|||
\
|
||||
macro(CodeNode, CodeNodeType, asCode) \
|
||||
\
|
||||
macro(LexicalScopeNode, LexicalScopeNodeType, asLexicalScope) \
|
||||
\
|
||||
macro(ListNode, ListNodeType, asList) \
|
||||
macro(CallSiteNode, CallSiteNodeType, asCallSite) \
|
||||
\
|
||||
|
|
@ -732,6 +735,8 @@ class ParseNode
|
|||
ParseNode* body; /* module or function body */
|
||||
} code;
|
||||
struct {
|
||||
private:
|
||||
friend class LexicalScopeNode;
|
||||
LexicalScope::Data* bindings;
|
||||
ParseNode* body;
|
||||
} scope;
|
||||
|
|
@ -759,28 +764,6 @@ class ParseNode
|
|||
|
||||
inline PropertyName* name() const;
|
||||
|
||||
bool isEmptyScope() const {
|
||||
MOZ_ASSERT(pn_arity == PN_SCOPE);
|
||||
return !pn_u.scope.bindings;
|
||||
}
|
||||
|
||||
Handle<LexicalScope::Data*> scopeBindings() const {
|
||||
MOZ_ASSERT(!isEmptyScope());
|
||||
// Bindings' GC safety depend on the presence of an AutoKeepAtoms that
|
||||
// the rest of the frontend also depends on.
|
||||
return Handle<LexicalScope::Data*>::fromMarkedLocation(&pn_u.scope.bindings);
|
||||
}
|
||||
|
||||
ParseNode* scopeBody() const {
|
||||
MOZ_ASSERT(pn_arity == PN_SCOPE);
|
||||
return pn_u.scope.body;
|
||||
}
|
||||
|
||||
void setScopeBody(ParseNode* body) {
|
||||
MOZ_ASSERT(pn_arity == PN_SCOPE);
|
||||
pn_u.scope.body = body;
|
||||
}
|
||||
|
||||
/* True if pn is a parsenode representing a literal constant. */
|
||||
bool isLiteral() const {
|
||||
return isKind(PNK_NUMBER) ||
|
||||
|
|
@ -1523,8 +1506,9 @@ class NumericLiteral : public ParseNode
|
|||
}
|
||||
};
|
||||
|
||||
struct LexicalScopeNode : public ParseNode
|
||||
class LexicalScopeNode : public ParseNode
|
||||
{
|
||||
public:
|
||||
LexicalScopeNode(LexicalScope::Data* bindings, ParseNode* body)
|
||||
: ParseNode(PNK_LEXICALSCOPE, JSOP_NOP, PN_SCOPE, body->pn_pos)
|
||||
{
|
||||
|
|
@ -1533,12 +1517,37 @@ struct LexicalScopeNode : public ParseNode
|
|||
}
|
||||
|
||||
static bool test(const ParseNode& node) {
|
||||
return node.isKind(PNK_LEXICALSCOPE);
|
||||
bool match = node.isKind(PNK_LEXICALSCOPE);
|
||||
MOZ_ASSERT_IF(match, node.isArity(PN_SCOPE));
|
||||
return match;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
void dump(int indent);
|
||||
#endif
|
||||
|
||||
Handle<LexicalScope::Data*> scopeBindings() const {
|
||||
MOZ_ASSERT(!isEmptyScope());
|
||||
// Bindings' GC safety depend on the presence of an AutoKeepAtoms that
|
||||
// the rest of the frontend also depends on.
|
||||
return Handle<LexicalScope::Data*>::fromMarkedLocation(&pn_u.scope.bindings);
|
||||
}
|
||||
|
||||
ParseNode* scopeBody() const {
|
||||
return pn_u.scope.body;
|
||||
}
|
||||
|
||||
void setScopeBody(ParseNode* body) {
|
||||
pn_u.scope.body = body;
|
||||
}
|
||||
|
||||
bool isEmptyScope() const {
|
||||
return !pn_u.scope.bindings;
|
||||
}
|
||||
|
||||
ParseNode** unsafeScopeBodyReference() {
|
||||
return &pn_u.scope.body;
|
||||
}
|
||||
};
|
||||
|
||||
class LabeledStatement : public NameNode
|
||||
|
|
@ -1983,14 +1992,13 @@ class ClassMethod : public BinaryNode
|
|||
class SwitchStatement : public BinaryNode
|
||||
{
|
||||
public:
|
||||
SwitchStatement(uint32_t begin, ParseNode* discriminant, ParseNode* lexicalForCaseList,
|
||||
SwitchStatement(uint32_t begin, ParseNode* discriminant, LexicalScopeNode* lexicalForCaseList,
|
||||
bool hasDefault)
|
||||
: BinaryNode(PNK_SWITCH, JSOP_NOP,
|
||||
TokenPos(begin, lexicalForCaseList->pn_pos.end),
|
||||
discriminant, lexicalForCaseList)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
MOZ_ASSERT(lexicalForCaseList->isKind(PNK_LEXICALSCOPE));
|
||||
ListNode* cases = &lexicalForCaseList->scopeBody()->as<ListNode>();
|
||||
MOZ_ASSERT(cases->isKind(PNK_STATEMENTLIST));
|
||||
bool found = false;
|
||||
|
|
@ -2016,8 +2024,8 @@ class SwitchStatement : public BinaryNode
|
|||
ParseNode& discriminant() const {
|
||||
return *left();
|
||||
}
|
||||
ParseNode& lexicalForCaseList() const {;
|
||||
return *right();
|
||||
LexicalScopeNode& lexicalForCaseList() const {
|
||||
return right()->as<LexicalScopeNode>();
|
||||
}
|
||||
bool hasDefault() const {
|
||||
return pn_u.binary.hasDefault;
|
||||
|
|
@ -2090,15 +2098,13 @@ class ClassNode : public TernaryNode
|
|||
if (methodsOrBlock->isKind(PNK_CLASSMETHODLIST))
|
||||
return &methodsOrBlock->as<ListNode>();
|
||||
|
||||
MOZ_ASSERT(methodsOrBlock->is<LexicalScopeNode>());
|
||||
ListNode* list = &methodsOrBlock->scopeBody()->as<ListNode>();
|
||||
ListNode* list = &methodsOrBlock->as<LexicalScopeNode>().scopeBody()->as<ListNode>();
|
||||
MOZ_ASSERT(list->isKind(PNK_CLASSMETHODLIST));
|
||||
return list;
|
||||
}
|
||||
Handle<LexicalScope::Data*> scopeBindings() const {
|
||||
ParseNode* scope = kid3();
|
||||
MOZ_ASSERT(scope->is<LexicalScopeNode>());
|
||||
return scope->scopeBindings();
|
||||
return scope->as<LexicalScopeNode>().scopeBindings();
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -2221,8 +2227,8 @@ FunctionFormalParametersList(ParseNode* fn, unsigned* numFormals)
|
|||
MOZ_ASSERT(argsBody->isKind(PNK_PARAMSBODY));
|
||||
*numFormals = argsBody->count();
|
||||
if (*numFormals > 0 &&
|
||||
argsBody->last()->isKind(PNK_LEXICALSCOPE) &&
|
||||
argsBody->last()->scopeBody()->isKind(PNK_STATEMENTLIST))
|
||||
argsBody->last()->is<LexicalScopeNode>() &&
|
||||
argsBody->last()->as<LexicalScopeNode>().scopeBody()->isKind(PNK_STATEMENTLIST))
|
||||
{
|
||||
(*numFormals)--;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2066,16 +2066,16 @@ Parser<FullParseHandler>::newLexicalScopeData(ParseContext::Scope& scope)
|
|||
}
|
||||
|
||||
template <>
|
||||
SyntaxParseHandler::Node
|
||||
SyntaxParseHandler::LexicalScopeNodeType
|
||||
Parser<SyntaxParseHandler>::finishLexicalScope(ParseContext::Scope& scope, Node body)
|
||||
{
|
||||
if (!propagateFreeNamesAndMarkClosedOverBindings(scope))
|
||||
return null();
|
||||
return body;
|
||||
return handler.newLexicalScope(body);
|
||||
}
|
||||
|
||||
template <>
|
||||
ParseNode*
|
||||
LexicalScopeNode*
|
||||
Parser<FullParseHandler>::finishLexicalScope(ParseContext::Scope& scope, ParseNode* body)
|
||||
{
|
||||
if (!propagateFreeNamesAndMarkClosedOverBindings(scope))
|
||||
|
|
@ -2108,7 +2108,7 @@ IsArgumentsUsedInLegacyGenerator(ExclusiveContext* cx, Scope* scope)
|
|||
}
|
||||
|
||||
template <>
|
||||
ParseNode*
|
||||
LexicalScopeNode*
|
||||
Parser<FullParseHandler>::evalBody(EvalSharedContext* evalsc)
|
||||
{
|
||||
ParseContext evalpc(this, evalsc, /* newDirectives = */ nullptr);
|
||||
|
|
@ -2119,21 +2119,24 @@ Parser<FullParseHandler>::evalBody(EvalSharedContext* evalsc)
|
|||
if (!varScope.init(pc))
|
||||
return nullptr;
|
||||
|
||||
// All evals have an implicit non-extensible lexical scope.
|
||||
ParseContext::Scope lexicalScope(this);
|
||||
if (!lexicalScope.init(pc))
|
||||
return nullptr;
|
||||
LexicalScopeNode* body;
|
||||
{
|
||||
// All evals have an implicit non-extensible lexical scope.
|
||||
ParseContext::Scope lexicalScope(this);
|
||||
if (!lexicalScope.init(pc))
|
||||
return nullptr;
|
||||
|
||||
ParseNode* body = statementList(YieldIsName);
|
||||
if (!body)
|
||||
return nullptr;
|
||||
ParseNode* list = statementList(YieldIsName);
|
||||
if (!list)
|
||||
return nullptr;
|
||||
|
||||
if (!checkStatementsEOF())
|
||||
return nullptr;
|
||||
if (!checkStatementsEOF())
|
||||
return nullptr;
|
||||
|
||||
body = finishLexicalScope(lexicalScope, body);
|
||||
if (!body)
|
||||
return nullptr;
|
||||
body = finishLexicalScope(lexicalScope, list);
|
||||
if (!body)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// It's an error to use 'arguments' in a legacy generator expression.
|
||||
//
|
||||
|
|
@ -2170,8 +2173,10 @@ Parser<FullParseHandler>::evalBody(EvalSharedContext* evalsc)
|
|||
}
|
||||
#endif
|
||||
|
||||
if (!FoldConstants(context, &body, this))
|
||||
ParseNode* node = body;
|
||||
if (!FoldConstants(context, &node, this))
|
||||
return nullptr;
|
||||
body = handler.asLexicalScope(node);
|
||||
|
||||
Maybe<EvalScope::Data*> bindings = newEvalScopeData(pc->varScope());
|
||||
if (!bindings)
|
||||
|
|
@ -2663,7 +2668,7 @@ Parser<ParseHandler>::declareFunctionArgumentsObject()
|
|||
}
|
||||
|
||||
template <typename ParseHandler>
|
||||
typename ParseHandler::Node
|
||||
typename ParseHandler::LexicalScopeNodeType
|
||||
Parser<ParseHandler>::functionBody(InHandling inHandling, YieldHandling yieldHandling,
|
||||
FunctionSyntaxKind kind, FunctionBodyType type)
|
||||
{
|
||||
|
|
@ -3721,7 +3726,7 @@ Parser<ParseHandler>::functionFormalParametersAndBody(InHandling inHandling,
|
|||
// Whereas the |yield| in the function body is always parsed as a name.
|
||||
// The same goes when parsing |await| in arrow functions.
|
||||
YieldHandling bodyYieldHandling = GetYieldHandling(pc->generatorKind());
|
||||
Node body;
|
||||
LexicalScopeNodeType body;
|
||||
{
|
||||
AutoAwaitIsKeyword<ParseHandler> awaitIsKeyword(this, funbox->isAsync());
|
||||
body = functionBody(inHandling, bodyYieldHandling, kind, bodyType);
|
||||
|
|
@ -4620,7 +4625,7 @@ Parser<ParseHandler>::destructuringDeclarationWithoutYieldOrAwait(DeclarationKin
|
|||
}
|
||||
|
||||
template <typename ParseHandler>
|
||||
typename ParseHandler::Node
|
||||
typename ParseHandler::LexicalScopeNodeType
|
||||
Parser<ParseHandler>::blockStatement(YieldHandling yieldHandling, unsigned errorNumber)
|
||||
{
|
||||
MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_LC));
|
||||
|
|
@ -6532,7 +6537,7 @@ Parser<ParseHandler>::switchStatement(YieldHandling yieldHandling)
|
|||
handler.addCaseStatementToList(caseList, caseClause);
|
||||
}
|
||||
|
||||
Node lexicalForCaseList = finishLexicalScope(scope, caseList);
|
||||
LexicalScopeNodeType lexicalForCaseList = finishLexicalScope(scope, caseList);
|
||||
if (!lexicalForCaseList)
|
||||
return null();
|
||||
|
||||
|
|
@ -6983,7 +6988,7 @@ Parser<ParseHandler>::tryStatement(YieldHandling yieldHandling)
|
|||
* finally nodes are TOK_LC statement lists.
|
||||
*/
|
||||
|
||||
Node innerBlock;
|
||||
LexicalScopeNodeType innerBlock;
|
||||
{
|
||||
MUST_MATCH_TOKEN(TOK_LC, JSMSG_CURLY_BEFORE_TRY);
|
||||
|
||||
|
|
@ -6994,11 +6999,11 @@ Parser<ParseHandler>::tryStatement(YieldHandling yieldHandling)
|
|||
if (!scope.init(pc))
|
||||
return null();
|
||||
|
||||
innerBlock = statementList(yieldHandling);
|
||||
if (!innerBlock)
|
||||
ListNodeType list = statementList(yieldHandling);
|
||||
if (!list)
|
||||
return null();
|
||||
|
||||
innerBlock = finishLexicalScope(scope, innerBlock);
|
||||
innerBlock = finishLexicalScope(scope, list);
|
||||
if (!innerBlock)
|
||||
return null();
|
||||
|
||||
|
|
@ -7018,8 +7023,6 @@ Parser<ParseHandler>::tryStatement(YieldHandling yieldHandling)
|
|||
return null();
|
||||
|
||||
do {
|
||||
Node pnblock;
|
||||
|
||||
/* Check for another catch after unconditional catch. */
|
||||
if (hasUnconditionalCatch) {
|
||||
error(JSMSG_CATCH_AFTER_GENERAL);
|
||||
|
|
@ -7100,28 +7103,28 @@ Parser<ParseHandler>::tryStatement(YieldHandling yieldHandling)
|
|||
MUST_MATCH_TOKEN(TOK_LC, JSMSG_CURLY_BEFORE_CATCH);
|
||||
}
|
||||
|
||||
Node catchBody = catchBlockStatement(yieldHandling, scope);
|
||||
LexicalScopeNodeType catchBody = catchBlockStatement(yieldHandling, scope);
|
||||
if (!catchBody)
|
||||
return null();
|
||||
|
||||
if (!catchGuard)
|
||||
hasUnconditionalCatch = true;
|
||||
|
||||
pnblock = finishLexicalScope(scope, catchBody);
|
||||
if (!pnblock)
|
||||
LexicalScopeNodeType catchScope = finishLexicalScope(scope, catchBody);
|
||||
if (!catchScope)
|
||||
return null();
|
||||
|
||||
if (!handler.addCatchBlock(catchList, pnblock, catchName, catchGuard, catchBody))
|
||||
if (!handler.addCatchBlock(catchList, catchScope, catchName, catchGuard, catchBody))
|
||||
return null();
|
||||
handler.setEndPosition(catchList, pos().end);
|
||||
handler.setEndPosition(pnblock, pos().end);
|
||||
handler.setEndPosition(catchScope, pos().end);
|
||||
|
||||
if (!tokenStream.getToken(&tt, TokenStream::Operand))
|
||||
return null();
|
||||
} while (tt == TOK_CATCH);
|
||||
}
|
||||
|
||||
Node finallyBlock = null();
|
||||
LexicalScopeNodeType finallyBlock = null();
|
||||
|
||||
if (tt == TOK_FINALLY) {
|
||||
MUST_MATCH_TOKEN(TOK_LC, JSMSG_CURLY_BEFORE_FINALLY);
|
||||
|
|
@ -7133,11 +7136,11 @@ Parser<ParseHandler>::tryStatement(YieldHandling yieldHandling)
|
|||
if (!scope.init(pc))
|
||||
return null();
|
||||
|
||||
finallyBlock = statementList(yieldHandling);
|
||||
if (!finallyBlock)
|
||||
ListNodeType list = statementList(yieldHandling);
|
||||
if (!list)
|
||||
return null();
|
||||
|
||||
finallyBlock = finishLexicalScope(scope, finallyBlock);
|
||||
finallyBlock = finishLexicalScope(scope, list);
|
||||
if (!finallyBlock)
|
||||
return null();
|
||||
|
||||
|
|
@ -7156,7 +7159,7 @@ Parser<ParseHandler>::tryStatement(YieldHandling yieldHandling)
|
|||
}
|
||||
|
||||
template <typename ParseHandler>
|
||||
typename ParseHandler::Node
|
||||
typename ParseHandler::LexicalScopeNodeType
|
||||
Parser<ParseHandler>::catchBlockStatement(YieldHandling yieldHandling,
|
||||
ParseContext::Scope& catchParamScope)
|
||||
{
|
||||
|
|
@ -7427,7 +7430,7 @@ Parser<ParseHandler>::classDefinition(YieldHandling yieldHandling,
|
|||
if (!innerName)
|
||||
return null();
|
||||
|
||||
Node classBlock = finishLexicalScope(*innerScope, classMethods);
|
||||
LexicalScopeNodeType classBlock = finishLexicalScope(*innerScope, classMethods);
|
||||
if (!classBlock)
|
||||
return null();
|
||||
|
||||
|
|
@ -8937,7 +8940,7 @@ Parser<ParseHandler>::comprehensionFor(GeneratorKind comprehensionKind)
|
|||
return null();
|
||||
|
||||
// Finish the lexical scope after parsing the tail.
|
||||
Node lexicalScope = finishLexicalScope(scope, decls);
|
||||
LexicalScopeNodeType lexicalScope = finishLexicalScope(scope, decls);
|
||||
if (!lexicalScope)
|
||||
return null();
|
||||
|
||||
|
|
|
|||
|
|
@ -1132,7 +1132,7 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_TYPE)
|
|||
// Eval scripts are distinguished from global scripts in that in ES6, per
|
||||
// 18.2.1.1 steps 9 and 10, all eval scripts are executed under a fresh
|
||||
// lexical scope.
|
||||
Node evalBody(EvalSharedContext* evalsc);
|
||||
LexicalScopeNodeType evalBody(EvalSharedContext* evalsc);
|
||||
|
||||
// Parse the body of a global script.
|
||||
ListNodeType globalBody(GlobalSharedContext* globalsc);
|
||||
|
|
@ -1196,8 +1196,8 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_TYPE)
|
|||
|
||||
ListNodeType statementList(YieldHandling yieldHandling);
|
||||
|
||||
Node blockStatement(YieldHandling yieldHandling,
|
||||
unsigned errorNumber = JSMSG_CURLY_IN_COMPOUND);
|
||||
LexicalScopeNodeType blockStatement(YieldHandling yieldHandling,
|
||||
unsigned errorNumber = JSMSG_CURLY_IN_COMPOUND);
|
||||
BinaryNodeType doWhileStatement(YieldHandling yieldHandling);
|
||||
BinaryNodeType whileStatement(YieldHandling yieldHandling);
|
||||
|
||||
|
|
@ -1217,7 +1217,7 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_TYPE)
|
|||
BinaryNodeType withStatement(YieldHandling yieldHandling);
|
||||
UnaryNodeType throwStatement(YieldHandling yieldHandling);
|
||||
TernaryNodeType tryStatement(YieldHandling yieldHandling);
|
||||
Node catchBlockStatement(YieldHandling yieldHandling, ParseContext::Scope& catchParamScope);
|
||||
LexicalScopeNodeType catchBlockStatement(YieldHandling yieldHandling, ParseContext::Scope& catchParamScope);
|
||||
DebuggerStatementType debuggerStatement();
|
||||
|
||||
Node variableStatement(YieldHandling yieldHandling);
|
||||
|
|
@ -1363,8 +1363,8 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_TYPE)
|
|||
// Parse a function body. Pass StatementListBody if the body is a list of
|
||||
// statements; pass ExpressionBody if the body is a single expression.
|
||||
enum FunctionBodyType { StatementListBody, ExpressionBody };
|
||||
Node functionBody(InHandling inHandling, YieldHandling yieldHandling, FunctionSyntaxKind kind,
|
||||
FunctionBodyType type);
|
||||
LexicalScopeNodeType functionBody(InHandling inHandling, YieldHandling yieldHandling,
|
||||
FunctionSyntaxKind kind, FunctionBodyType type);
|
||||
|
||||
UnaryNodeType unaryOpExpr(YieldHandling yieldHandling, ParseNodeKind kind, JSOp op, uint32_t begin);
|
||||
|
||||
|
|
@ -1514,7 +1514,7 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_TYPE)
|
|||
bool hasParameterExprs);
|
||||
mozilla::Maybe<VarScope::Data*> newVarScopeData(ParseContext::Scope& scope);
|
||||
mozilla::Maybe<LexicalScope::Data*> newLexicalScopeData(ParseContext::Scope& scope);
|
||||
Node finishLexicalScope(ParseContext::Scope& scope, Node body);
|
||||
LexicalScopeNodeType finishLexicalScope(ParseContext::Scope& scope, Node body);
|
||||
|
||||
Node propertyName(YieldHandling yieldHandling,
|
||||
const mozilla::Maybe<DeclarationKind>& maybeDecl, ListNodeType propList,
|
||||
|
|
|
|||
|
|
@ -316,6 +316,10 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS)
|
|||
ClassNamesType newClassNames(Node outer, Node inner, const TokenPos& pos) { return NodeGeneric; }
|
||||
ClassNodeType newClass(Node name, Node heritage, Node methodBlock, const TokenPos& pos) { return NodeGeneric; }
|
||||
|
||||
LexicalScopeNodeType newLexicalScope(Node body) {
|
||||
return NodeLexicalDeclaration;
|
||||
}
|
||||
|
||||
BinaryNodeType newNewTarget(NullaryNodeType newHolder, NullaryNodeType targetHolder) {
|
||||
return NodeGeneric;
|
||||
}
|
||||
|
|
@ -362,7 +366,8 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS)
|
|||
}
|
||||
BinaryNodeType newDoWhileStatement(Node body, Node cond, const TokenPos& pos) { return NodeGeneric; }
|
||||
BinaryNodeType newWhileStatement(uint32_t begin, Node cond, Node body) { return NodeGeneric; }
|
||||
SwitchStatementType newSwitchStatement(uint32_t begin, Node discriminant, Node lexicalForCaseList, bool hasDefault)
|
||||
SwitchStatementType newSwitchStatement(uint32_t begin, Node discriminant,
|
||||
LexicalScopeNodeType lexicalForCaseList, bool hasDefault)
|
||||
{
|
||||
return NodeGeneric;
|
||||
}
|
||||
|
|
@ -399,8 +404,8 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS)
|
|||
|
||||
Node newOptionalPropertyByValue(Node pn, Node kid, uint32_t end) { return NodeOptionalElement; }
|
||||
|
||||
MOZ_MUST_USE bool addCatchBlock(ListNodeType catchList, Node letBlock, Node catchBinding,
|
||||
Node catchGuard, Node catchBody) { return true; }
|
||||
MOZ_MUST_USE bool addCatchBlock(ListNodeType catchList, LexicalScopeNodeType lexicalScope,
|
||||
Node catchBinding, Node catchGuard, Node catchBody) { return true; }
|
||||
|
||||
MOZ_MUST_USE bool setLastFunctionFormalParameterDefault(CodeNodeType funNode, Node pn) { return true; }
|
||||
|
||||
|
|
@ -412,7 +417,7 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS)
|
|||
|
||||
bool setComprehensionLambdaBody(CodeNodeType funNode, ListNodeType body) { return true; }
|
||||
void setFunctionFormalParametersAndBody(CodeNodeType funNode, ListNodeType paramsBody) {}
|
||||
void setFunctionBody(CodeNodeType funNode, Node body) {}
|
||||
void setFunctionBody(CodeNodeType funNode, LexicalScopeNodeType body) {}
|
||||
void setFunctionBox(CodeNodeType funNode, FunctionBox* funbox) {}
|
||||
void addFunctionFormalParameter(CodeNodeType funNode, Node argpn) {}
|
||||
|
||||
|
|
|
|||
|
|
@ -668,8 +668,7 @@ static inline ParseNode*
|
|||
FunctionStatementList(CodeNode* funNode)
|
||||
{
|
||||
MOZ_ASSERT(funNode->body()->isKind(PNK_PARAMSBODY));
|
||||
ParseNode* last = funNode->body()->as<ListNode>().last();
|
||||
MOZ_ASSERT(last->isKind(PNK_LEXICALSCOPE));
|
||||
LexicalScopeNode* last = &funNode->body()->as<ListNode>().last()->as<LexicalScopeNode>();
|
||||
MOZ_ASSERT(last->isEmptyScope());
|
||||
ParseNode* body = last->scopeBody();
|
||||
MOZ_ASSERT(body->isKind(PNK_STATEMENTLIST));
|
||||
|
|
@ -6807,10 +6806,11 @@ CheckSwitch(FunctionValidator& f, ParseNode* switchStmt)
|
|||
ParseNode* switchExpr = BinaryLeft(switchStmt);
|
||||
ParseNode* switchBody = BinaryRight(switchStmt);
|
||||
|
||||
if (switchBody->isKind(PNK_LEXICALSCOPE)) {
|
||||
if (!switchBody->isEmptyScope())
|
||||
return f.fail(switchBody, "switch body may not contain lexical declarations");
|
||||
switchBody = switchBody->scopeBody();
|
||||
if (switchBody->is<LexicalScopeNode>()) {
|
||||
LexicalScopeNode* scope = &switchBody->as<LexicalScopeNode>();
|
||||
if (!scope->isEmptyScope())
|
||||
return f.fail(scope, "switch body may not contain lexical declarations");
|
||||
switchBody = scope->scopeBody();
|
||||
}
|
||||
|
||||
ParseNode* stmt = ListHead(switchBody);
|
||||
|
|
@ -6984,10 +6984,9 @@ CheckStatementList(FunctionValidator& f, ParseNode* stmtList, const NameVector*
|
|||
}
|
||||
|
||||
static bool
|
||||
CheckLexicalScope(FunctionValidator& f, ParseNode* lexicalScope)
|
||||
CheckLexicalScope(FunctionValidator& f, ParseNode* node)
|
||||
{
|
||||
MOZ_ASSERT(lexicalScope->isKind(PNK_LEXICALSCOPE));
|
||||
|
||||
LexicalScopeNode* lexicalScope = &node->as<LexicalScopeNode>();
|
||||
if (!lexicalScope->isEmptyScope())
|
||||
return f.fail(lexicalScope, "cannot have 'let' or 'const' declarations");
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue