mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-10-30 19:17:31 +09:00
Issue #2173 - Add a new PNK_PROPERTYNAME to hold location information about property access name
Based-on: m-c 1378808/2
This commit is contained in:
parent
924140d400
commit
fa1193b8c9
10 changed files with 104 additions and 76 deletions
|
|
@ -3066,20 +3066,20 @@ ASTSerializer::expression(ParseNode* pn, MutableHandleValue dst)
|
||||||
case PNK_OPTDOT:
|
case PNK_OPTDOT:
|
||||||
case PNK_DOT:
|
case PNK_DOT:
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_expr->pn_pos));
|
MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_left->pn_pos));
|
||||||
|
|
||||||
RootedValue expr(cx);
|
RootedValue expr(cx);
|
||||||
RootedValue propname(cx);
|
RootedValue propname(cx);
|
||||||
RootedAtom pnAtom(cx, pn->pn_atom);
|
RootedAtom pnAtom(cx, pn->pn_right->pn_atom);
|
||||||
|
|
||||||
bool isSuper = pn->is<PropertyAccess>() &&
|
bool isSuper = pn->is<PropertyAccess>() &&
|
||||||
pn->as<PropertyAccess>().isSuper();
|
pn->as<PropertyAccess>().isSuper();
|
||||||
|
|
||||||
if (isSuper) {
|
if (isSuper) {
|
||||||
if (!builder.super(&pn->pn_expr->pn_pos, &expr))
|
if (!builder.super(&pn->pn_left->pn_pos, &expr))
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
if (!expression(pn->pn_expr, &expr))
|
if (!expression(pn->pn_left, &expr))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1090,7 +1090,7 @@ BytecodeEmitter::checkSideEffects(ParseNode* pn, bool* answer)
|
||||||
// Watch out for getters!
|
// Watch out for getters!
|
||||||
case PNK_DOT:
|
case PNK_DOT:
|
||||||
case PNK_OPTDOT:
|
case PNK_OPTDOT:
|
||||||
MOZ_ASSERT(pn->isArity(PN_NAME));
|
MOZ_ASSERT(pn->isArity(PN_BINARY));
|
||||||
*answer = true;
|
*answer = true;
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
|
@ -1497,6 +1497,7 @@ BytecodeEmitter::checkSideEffects(ParseNode* pn, bool* answer)
|
||||||
case PNK_CALLSITEOBJ: // by PNK_TAGGED_TEMPLATE
|
case PNK_CALLSITEOBJ: // by PNK_TAGGED_TEMPLATE
|
||||||
case PNK_POSHOLDER: // by PNK_NEWTARGET
|
case PNK_POSHOLDER: // by PNK_NEWTARGET
|
||||||
case PNK_SUPERBASE: // by PNK_ELEM and others
|
case PNK_SUPERBASE: // by PNK_ELEM and others
|
||||||
|
case PNK_PROPERTYNAME: // by PNK_DOT
|
||||||
MOZ_CRASH("handled by parent nodes");
|
MOZ_CRASH("handled by parent nodes");
|
||||||
|
|
||||||
case PNK_LIMIT: // invalid sentinel value
|
case PNK_LIMIT: // invalid sentinel value
|
||||||
|
|
@ -1813,11 +1814,11 @@ BytecodeEmitter::emitPropLHS(ParseNode* pn)
|
||||||
MOZ_ASSERT(pn->isKind(PNK_DOT));
|
MOZ_ASSERT(pn->isKind(PNK_DOT));
|
||||||
MOZ_ASSERT(!pn->as<PropertyAccess>().isSuper());
|
MOZ_ASSERT(!pn->as<PropertyAccess>().isSuper());
|
||||||
|
|
||||||
ParseNode* pn2 = pn->pn_expr;
|
ParseNode* pn2 = pn->pn_left;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the object operand is also a dotted property reference, reverse the
|
* If the object operand is also a dotted property reference, reverse the
|
||||||
* list linked via pn_expr temporarily so we can iterate over it from the
|
* list linked via pn_left temporarily so we can iterate over it from the
|
||||||
* bottom up (reversing again as we go), to avoid excessive recursion.
|
* bottom up (reversing again as we go), to avoid excessive recursion.
|
||||||
*/
|
*/
|
||||||
if (pn2->isKind(PNK_DOT) && !pn2->as<PropertyAccess>().isSuper()) {
|
if (pn2->isKind(PNK_DOT) && !pn2->as<PropertyAccess>().isSuper()) {
|
||||||
|
|
@ -1825,9 +1826,9 @@ BytecodeEmitter::emitPropLHS(ParseNode* pn)
|
||||||
ParseNode* pnup = nullptr;
|
ParseNode* pnup = nullptr;
|
||||||
ParseNode* pndown;
|
ParseNode* pndown;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
/* Reverse pndot->pn_expr to point up, not down. */
|
/* Reverse pndot->pn_left to point up, not down. */
|
||||||
pndown = pndot->pn_expr;
|
pndown = pndot->pn_left;
|
||||||
pndot->pn_expr = pnup;
|
pndot->pn_left = pnup;
|
||||||
if (!pndown->isKind(PNK_DOT) || pndown->as<PropertyAccess>().isSuper())
|
if (!pndown->isKind(PNK_DOT) || pndown->as<PropertyAccess>().isSuper())
|
||||||
break;
|
break;
|
||||||
pnup = pndot;
|
pnup = pndot;
|
||||||
|
|
@ -1840,12 +1841,12 @@ BytecodeEmitter::emitPropLHS(ParseNode* pn)
|
||||||
|
|
||||||
do {
|
do {
|
||||||
/* Walk back up the list, emitting annotated name ops. */
|
/* Walk back up the list, emitting annotated name ops. */
|
||||||
if (!emitAtomOp(pndot->pn_atom, JSOP_GETPROP))
|
if (!emitAtomOp(pndot->pn_right->pn_atom, JSOP_GETPROP))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
/* Reverse the pn_expr link again. */
|
/* Reverse the pn_left link again. */
|
||||||
pnup = pndot->pn_expr;
|
pnup = pndot->pn_left;
|
||||||
pndot->pn_expr = pndown;
|
pndot->pn_left = pndown;
|
||||||
pndown = pndot;
|
pndown = pndot;
|
||||||
} while ((pndot = pnup) != nullptr);
|
} while ((pndot = pnup) != nullptr);
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -2505,7 +2506,7 @@ BytecodeEmitter::emitDestructuringLHSRef(ParseNode* target, size_t* emitted)
|
||||||
// SUPERBASE is pushed onto THIS in poe.prepareForRhs below.
|
// SUPERBASE is pushed onto THIS in poe.prepareForRhs below.
|
||||||
*emitted = 2;
|
*emitted = 2;
|
||||||
} else {
|
} else {
|
||||||
if (!emitTree(target->pn_expr)) // OBJ
|
if (!emitTree(target->pn_left)) // OBJ
|
||||||
return false;
|
return false;
|
||||||
*emitted = 1;
|
*emitted = 1;
|
||||||
}
|
}
|
||||||
|
|
@ -9080,8 +9081,9 @@ BytecodeEmitter::emitTree(ParseNode* pn, ValueUsage valueUsage /* = ValueUsage::
|
||||||
return false;
|
return false;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case PNK_PROPERTYNAME:
|
||||||
case PNK_POSHOLDER:
|
case PNK_POSHOLDER:
|
||||||
MOZ_FALLTHROUGH_ASSERT("Should never try to emit PNK_POSHOLDER");
|
MOZ_FALLTHROUGH_ASSERT("Should never try to emit PNK_POSHOLDER or PNK_PROPERTYNAME");
|
||||||
|
|
||||||
default:
|
default:
|
||||||
MOZ_ASSERT(0);
|
MOZ_ASSERT(0);
|
||||||
|
|
|
||||||
|
|
@ -367,6 +367,7 @@ ContainsHoistedDeclaration(ExclusiveContext* cx, ParseNode* node, bool* result)
|
||||||
case PNK_COMMA:
|
case PNK_COMMA:
|
||||||
case PNK_ARRAY:
|
case PNK_ARRAY:
|
||||||
case PNK_OBJECT:
|
case PNK_OBJECT:
|
||||||
|
case PNK_PROPERTYNAME:
|
||||||
case PNK_DOT:
|
case PNK_DOT:
|
||||||
case PNK_ELEM:
|
case PNK_ELEM:
|
||||||
case PNK_ARGUMENTS:
|
case PNK_ARGUMENTS:
|
||||||
|
|
@ -1367,11 +1368,14 @@ FoldElement(ExclusiveContext* cx, ParseNode** nodePtr, Parser<FullParseHandler>&
|
||||||
|
|
||||||
// Optimization 3: We have expr["foo"] where foo is not an index. Convert
|
// Optimization 3: We have expr["foo"] where foo is not an index. Convert
|
||||||
// to a property access (like expr.foo) that optimizes better downstream.
|
// to a property access (like expr.foo) that optimizes better downstream.
|
||||||
|
ParseNode* nameNode = parser.handler.newPropertyName(name, key->pn_pos);
|
||||||
|
if (!nameNode)
|
||||||
|
return false;
|
||||||
ParseNode* dottedAccess;
|
ParseNode* dottedAccess;
|
||||||
if (node->isKind(PNK_OPTELEM)) {
|
if (node->isKind(PNK_OPTELEM)) {
|
||||||
dottedAccess = parser.handler.newOptionalPropertyAccess(expr, name, node->pn_pos.end);
|
dottedAccess = parser.handler.newOptionalPropertyAccess(expr, nameNode);
|
||||||
} else {
|
} else {
|
||||||
dottedAccess = parser.handler.newPropertyAccess(expr, name, node->pn_pos.end);
|
dottedAccess = parser.handler.newPropertyAccess(expr, nameNode);
|
||||||
}
|
}
|
||||||
if (!dottedAccess) {
|
if (!dottedAccess) {
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -1646,14 +1650,14 @@ FoldDottedProperty(ExclusiveContext* cx, ParseNode* node, Parser<FullParseHandle
|
||||||
bool inGenexpLambda)
|
bool inGenexpLambda)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(node->isKind(PNK_DOT) || node->isKind(PNK_OPTDOT));
|
MOZ_ASSERT(node->isKind(PNK_DOT) || node->isKind(PNK_OPTDOT));
|
||||||
MOZ_ASSERT(node->isArity(PN_NAME));
|
MOZ_ASSERT(node->isArity(PN_BINARY));
|
||||||
|
|
||||||
// Iterate through a long chain of dotted property accesses to find the
|
// Iterate through a long chain of dotted property accesses to find the
|
||||||
// most-nested non-dotted property node, then fold that.
|
// most-nested non-dotted property node, then fold that.
|
||||||
ParseNode** nested = &node->pn_expr;
|
ParseNode** nested = &node->pn_left;
|
||||||
while ((*nested)->isKind(PNK_DOT) || (*nested)->isKind(PNK_OPTDOT)) {
|
while ((*nested)->isKind(PNK_DOT) || (*nested)->isKind(PNK_OPTDOT)) {
|
||||||
MOZ_ASSERT((*nested)->isArity(PN_NAME));
|
MOZ_ASSERT((*nested)->isArity(PN_BINARY));
|
||||||
nested = &(*nested)->pn_expr;
|
nested = &(*nested)->pn_left;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Fold(cx, nested, parser, inGenexpLambda);
|
return Fold(cx, nested, parser, inGenexpLambda);
|
||||||
|
|
@ -1953,6 +1957,9 @@ Fold(ExclusiveContext* cx, ParseNode** pnp, Parser<FullParseHandler>& parser, bo
|
||||||
MOZ_ASSERT(pn->isArity(PN_NAME));
|
MOZ_ASSERT(pn->isArity(PN_NAME));
|
||||||
return Fold(cx, &pn->pn_expr, parser, inGenexpLambda);
|
return Fold(cx, &pn->pn_expr, parser, inGenexpLambda);
|
||||||
|
|
||||||
|
case PNK_PROPERTYNAME:
|
||||||
|
MOZ_CRASH("unreachable, handled by ::Dot");
|
||||||
|
|
||||||
case PNK_OPTDOT:
|
case PNK_OPTDOT:
|
||||||
case PNK_DOT:
|
case PNK_DOT:
|
||||||
return FoldDottedProperty(cx, pn, parser, inGenexpLambda);
|
return FoldDottedProperty(cx, pn, parser, inGenexpLambda);
|
||||||
|
|
|
||||||
|
|
@ -707,16 +707,20 @@ class FullParseHandler
|
||||||
return new_<DebuggerStatement>(pos);
|
return new_<DebuggerStatement>(pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
ParseNode* newPropertyAccess(ParseNode* pn, PropertyName* name, uint32_t end) {
|
ParseNode* newPropertyName(PropertyName* name, const TokenPos& pos) {
|
||||||
return new_<PropertyAccess>(pn, name, pn->pn_pos.begin, end);
|
return new_<NameNode>(PNK_PROPERTYNAME, JSOP_NOP, name, pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
ParseNode* newPropertyAccess(ParseNode* expr, ParseNode* key) {
|
||||||
|
return new_<PropertyAccess>(expr, key, expr->pn_pos.begin, key->pn_pos.end);
|
||||||
}
|
}
|
||||||
|
|
||||||
ParseNode* newPropertyByValue(ParseNode* lhs, ParseNode* index, uint32_t end) {
|
ParseNode* newPropertyByValue(ParseNode* lhs, ParseNode* index, uint32_t end) {
|
||||||
return new_<PropertyByValue>(lhs, index, lhs->pn_pos.begin, end);
|
return new_<PropertyByValue>(lhs, index, lhs->pn_pos.begin, end);
|
||||||
}
|
}
|
||||||
|
|
||||||
ParseNode* newOptionalPropertyAccess(ParseNode* pn, PropertyName* name, uint32_t end) {
|
ParseNode* newOptionalPropertyAccess(ParseNode* expr, ParseNode* key) {
|
||||||
return new_<OptionalPropertyAccess>(pn, name, pn->pn_pos.begin, end);
|
return new_<OptionalPropertyAccess>(expr, key, expr->pn_pos.begin, key->pn_pos.end);
|
||||||
}
|
}
|
||||||
|
|
||||||
ParseNode* newOptionalPropertyByValue(ParseNode* lhs, ParseNode* index, uint32_t end) {
|
ParseNode* newOptionalPropertyByValue(ParseNode* lhs, ParseNode* index, uint32_t end) {
|
||||||
|
|
|
||||||
|
|
@ -74,11 +74,11 @@ class NameResolver
|
||||||
bool nameExpression(ParseNode* n, bool* foundName) {
|
bool nameExpression(ParseNode* n, bool* foundName) {
|
||||||
switch (n->getKind()) {
|
switch (n->getKind()) {
|
||||||
case PNK_DOT:
|
case PNK_DOT:
|
||||||
if (!nameExpression(n->expr(), foundName))
|
if (!nameExpression(n->pn_left, foundName))
|
||||||
return false;
|
return false;
|
||||||
if (!*foundName)
|
if (!*foundName)
|
||||||
return true;
|
return true;
|
||||||
return appendPropertyReference(n->pn_atom);
|
return appendPropertyReference(n->pn_right->pn_atom);
|
||||||
|
|
||||||
case PNK_NAME:
|
case PNK_NAME:
|
||||||
*foundName = true;
|
*foundName = true;
|
||||||
|
|
@ -800,12 +800,12 @@ class NameResolver
|
||||||
}
|
}
|
||||||
|
|
||||||
case PNK_DOT:
|
case PNK_DOT:
|
||||||
MOZ_ASSERT(cur->isArity(PN_NAME));
|
MOZ_ASSERT(cur->isArity(PN_BINARY));
|
||||||
|
|
||||||
// Super prop nodes do not have a meaningful LHS
|
// Super prop nodes do not have a meaningful LHS
|
||||||
if (cur->as<PropertyAccess>().isSuper())
|
if (cur->as<PropertyAccess>().isSuper())
|
||||||
break;
|
break;
|
||||||
if (!resolve(cur->expr(), prefix))
|
if (!resolve(cur->pn_left, prefix))
|
||||||
return false;
|
return false;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
@ -840,6 +840,7 @@ class NameResolver
|
||||||
case PNK_EXPORT_SPEC: // by PNK_EXPORT_SPEC_LIST
|
case PNK_EXPORT_SPEC: // by PNK_EXPORT_SPEC_LIST
|
||||||
case PNK_CALLSITEOBJ: // by PNK_TAGGED_TEMPLATE
|
case PNK_CALLSITEOBJ: // by PNK_TAGGED_TEMPLATE
|
||||||
case PNK_CLASSNAMES: // by PNK_CLASS
|
case PNK_CLASSNAMES: // by PNK_CLASS
|
||||||
|
case PNK_PROPERTYNAME: // by PNK_DOT
|
||||||
MOZ_CRASH("should have been handled by a parent node");
|
MOZ_CRASH("should have been handled by a parent node");
|
||||||
|
|
||||||
case PNK_LIMIT: // invalid sentinel value
|
case PNK_LIMIT: // invalid sentinel value
|
||||||
|
|
|
||||||
|
|
@ -265,6 +265,8 @@ PushNodeChildren(ParseNode* pn, NodeStack* stack)
|
||||||
case PNK_WHILE:
|
case PNK_WHILE:
|
||||||
case PNK_SWITCH:
|
case PNK_SWITCH:
|
||||||
case PNK_NEW:
|
case PNK_NEW:
|
||||||
|
case PNK_OPTDOT:
|
||||||
|
case PNK_DOT:
|
||||||
case PNK_OPTCALL:
|
case PNK_OPTCALL:
|
||||||
case PNK_CALL:
|
case PNK_CALL:
|
||||||
case PNK_SUPERCALL:
|
case PNK_SUPERCALL:
|
||||||
|
|
@ -489,9 +491,8 @@ PushNodeChildren(ParseNode* pn, NodeStack* stack)
|
||||||
}
|
}
|
||||||
|
|
||||||
case PNK_LABEL:
|
case PNK_LABEL:
|
||||||
case PNK_OPTDOT:
|
|
||||||
case PNK_DOT:
|
|
||||||
case PNK_NAME:
|
case PNK_NAME:
|
||||||
|
case PNK_PROPERTYNAME:
|
||||||
return PushNameNodeChildren(pn, stack);
|
return PushNameNodeChildren(pn, stack);
|
||||||
|
|
||||||
case PNK_LEXICALSCOPE:
|
case PNK_LEXICALSCOPE:
|
||||||
|
|
@ -731,6 +732,21 @@ UnaryNode::dump(int indent)
|
||||||
void
|
void
|
||||||
BinaryNode::dump(int indent)
|
BinaryNode::dump(int indent)
|
||||||
{
|
{
|
||||||
|
if (isKind(PNK_DOT)) {
|
||||||
|
fprintf(stderr, "(.");
|
||||||
|
|
||||||
|
DumpParseTree(pn_right, indent + 2);
|
||||||
|
|
||||||
|
fprintf(stderr, " ");
|
||||||
|
if (as<PropertyAccess>().isSuper())
|
||||||
|
fprintf(stderr, "super");
|
||||||
|
else
|
||||||
|
DumpParseTree(pn_left, indent + 2);
|
||||||
|
|
||||||
|
fprintf(stderr, ")");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const char* name = parseNodeNames[getKind()];
|
const char* name = parseNodeNames[getKind()];
|
||||||
fprintf(stderr, "(%s ", name);
|
fprintf(stderr, "(%s ", name);
|
||||||
indent += strlen(name) + 2;
|
indent += strlen(name) + 2;
|
||||||
|
|
@ -803,10 +819,7 @@ DumpName(const CharT* s, size_t len)
|
||||||
void
|
void
|
||||||
NameNode::dump(int indent)
|
NameNode::dump(int indent)
|
||||||
{
|
{
|
||||||
if (isKind(PNK_NAME) || isKind(PNK_DOT)) {
|
if (isKind(PNK_NAME) || isKind(PNK_PROPERTYNAME)) {
|
||||||
if (isKind(PNK_DOT))
|
|
||||||
fprintf(stderr, "(.");
|
|
||||||
|
|
||||||
if (!pn_atom) {
|
if (!pn_atom) {
|
||||||
fprintf(stderr, "#<null name>");
|
fprintf(stderr, "#<null name>");
|
||||||
} else if (getOp() == JSOP_GETARG && pn_atom->length() == 0) {
|
} else if (getOp() == JSOP_GETARG && pn_atom->length() == 0) {
|
||||||
|
|
@ -821,15 +834,6 @@ NameNode::dump(int indent)
|
||||||
else
|
else
|
||||||
DumpName(pn_atom->twoByteChars(nogc), pn_atom->length());
|
DumpName(pn_atom->twoByteChars(nogc), pn_atom->length());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isKind(PNK_DOT)) {
|
|
||||||
fputc(' ', stderr);
|
|
||||||
if (as<PropertyAccess>().isSuper())
|
|
||||||
fprintf(stderr, "super");
|
|
||||||
else
|
|
||||||
DumpParseTree(expr(), indent + 2);
|
|
||||||
fputc(')', stderr);
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,7 @@ class ObjectBox;
|
||||||
F(POSTINCREMENT) \
|
F(POSTINCREMENT) \
|
||||||
F(PREDECREMENT) \
|
F(PREDECREMENT) \
|
||||||
F(POSTDECREMENT) \
|
F(POSTDECREMENT) \
|
||||||
|
F(PROPERTYNAME) \
|
||||||
F(DOT) \
|
F(DOT) \
|
||||||
F(ELEM) \
|
F(ELEM) \
|
||||||
F(OPTDOT) \
|
F(OPTDOT) \
|
||||||
|
|
@ -396,9 +397,9 @@ IsTypeofKind(ParseNodeKind kind)
|
||||||
* contains are nullish. An optional chain can also
|
* contains are nullish. An optional chain can also
|
||||||
* contain nodes such as PNK_DOT, PNK_ELEM, PNK_NAME,
|
* contain nodes such as PNK_DOT, PNK_ELEM, PNK_NAME,
|
||||||
* PNK_CALL, etc. These are evaluated normally.
|
* PNK_CALL, etc. These are evaluated normally.
|
||||||
* PNK_OPTDOT name pn_expr: MEMBER expr to left of .
|
* PNK_OPTDOT binary pn_left: MEMBER expr to left of .
|
||||||
* short circuits back to PNK_OPTCHAIN if nullish.
|
* short circuits back to PNK_OPTCHAIN if nullish.
|
||||||
* pn_atom: name to right of .
|
* pn_right: PropertyName to right of .
|
||||||
* PNK_OPTELEM binary pn_left: MEMBER expr to left of [
|
* PNK_OPTELEM binary pn_left: MEMBER expr to left of [
|
||||||
* short circuits back to PNK_OPTCHAIN if nullish.
|
* short circuits back to PNK_OPTCHAIN if nullish.
|
||||||
* pn_right: expr between [ and ]
|
* pn_right: expr between [ and ]
|
||||||
|
|
@ -406,8 +407,10 @@ IsTypeofKind(ParseNodeKind kind)
|
||||||
* pn_count: 1 + N (where N is number of args)
|
* pn_count: 1 + N (where N is number of args)
|
||||||
* call is a MEMBER expr naming a callable object,
|
* call is a MEMBER expr naming a callable object,
|
||||||
* short circuits back to PNK_OPTCHAIN if nullish.
|
* short circuits back to PNK_OPTCHAIN if nullish.
|
||||||
* PNK_DOT name pn_expr: MEMBER expr to left of .
|
* PNK_PROPERTYNAME pn_atom: property being accessed
|
||||||
* pn_atom: name to right of .
|
* name
|
||||||
|
* PNK_DOT binary pn_left: MEMBER expr to left of .
|
||||||
|
* pn_right: PropertyName to right of .
|
||||||
* PNK_ELEM binary pn_left: MEMBER expr to left of [
|
* PNK_ELEM binary pn_left: MEMBER expr to left of [
|
||||||
* pn_right: expr between [ and ]
|
* pn_right: expr between [ and ]
|
||||||
* PNK_CALL binary pn_left: callee expression on the left of the (
|
* PNK_CALL binary pn_left: callee expression on the left of the (
|
||||||
|
|
@ -600,8 +603,7 @@ class ParseNode
|
||||||
FunctionBox* funbox; /* function object */
|
FunctionBox* funbox; /* function object */
|
||||||
};
|
};
|
||||||
ParseNode* expr; /* module or function body, var
|
ParseNode* expr; /* module or function body, var
|
||||||
initializer, argument default, or
|
initializer, or argument default */
|
||||||
base object of PNK_DOT */
|
|
||||||
} name;
|
} name;
|
||||||
struct {
|
struct {
|
||||||
LexicalScope::Data* bindings;
|
LexicalScope::Data* bindings;
|
||||||
|
|
@ -1223,44 +1225,45 @@ class RegExpLiteral : public NullaryNode
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class PropertyAccessBase : public ParseNode
|
class PropertyAccessBase : public BinaryNode
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
PropertyAccessBase(ParseNodeKind kind, ParseNode* lhs, PropertyName* name,
|
/*
|
||||||
uint32_t begin, uint32_t end)
|
* PropertyAccess nodes can have any expression/'super' as left-hand
|
||||||
: ParseNode(kind, JSOP_NOP, PN_NAME, TokenPos(begin, end))
|
* side, but the name must be a ParseNodeKind::PropertyName node.
|
||||||
|
*/
|
||||||
|
PropertyAccessBase(ParseNodeKind kind, ParseNode* lhs, ParseNode* name, uint32_t begin, uint32_t end)
|
||||||
|
: BinaryNode(kind, JSOP_NOP, TokenPos(begin, end), lhs, name)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(lhs != nullptr);
|
MOZ_ASSERT(lhs != nullptr);
|
||||||
MOZ_ASSERT(name != nullptr);
|
MOZ_ASSERT(name != nullptr);
|
||||||
pn_u.name.expr = lhs;
|
|
||||||
pn_u.name.atom = name;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool test(const ParseNode& node) {
|
static bool test(const ParseNode& node) {
|
||||||
bool match = node.isKind(PNK_DOT) ||
|
bool match = node.isKind(PNK_DOT) ||
|
||||||
node.isKind(PNK_OPTDOT);
|
node.isKind(PNK_OPTDOT);
|
||||||
MOZ_ASSERT_IF(match, node.isArity(PN_NAME));
|
MOZ_ASSERT_IF(match, node.isArity(PN_BINARY));
|
||||||
|
MOZ_ASSERT_IF(match, node.pn_right->isKind(PNK_PROPERTYNAME));
|
||||||
return match;
|
return match;
|
||||||
}
|
}
|
||||||
|
|
||||||
ParseNode& expression() const {
|
ParseNode& expression() const {
|
||||||
return *pn_u.name.expr;
|
return *pn_u.binary.left;
|
||||||
}
|
}
|
||||||
|
|
||||||
PropertyName& name() const {
|
PropertyName& name() const {
|
||||||
return *pn_u.name.atom->asPropertyName();
|
return *pn_u.binary.right->pn_atom->asPropertyName();
|
||||||
}
|
}
|
||||||
|
|
||||||
JSAtom* nameAtom() const {
|
JSAtom* nameAtom() const {
|
||||||
return pn_u.name.atom;
|
return pn_u.binary.right->pn_atom;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class PropertyAccess : public PropertyAccessBase
|
class PropertyAccess : public PropertyAccessBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
PropertyAccess(ParseNode* lhs, PropertyName* name, uint32_t begin,
|
PropertyAccess(ParseNode* lhs, ParseNode* name, uint32_t begin, uint32_t end)
|
||||||
uint32_t end)
|
|
||||||
: PropertyAccessBase(PNK_DOT, lhs, name, begin, end)
|
: PropertyAccessBase(PNK_DOT, lhs, name, begin, end)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(lhs != nullptr);
|
MOZ_ASSERT(lhs != nullptr);
|
||||||
|
|
@ -1269,7 +1272,8 @@ class PropertyAccess : public PropertyAccessBase
|
||||||
|
|
||||||
static bool test(const ParseNode& node) {
|
static bool test(const ParseNode& node) {
|
||||||
bool match = node.isKind(PNK_DOT);
|
bool match = node.isKind(PNK_DOT);
|
||||||
MOZ_ASSERT_IF(match, node.isArity(PN_NAME));
|
MOZ_ASSERT_IF(match, node.isArity(PN_BINARY));
|
||||||
|
MOZ_ASSERT_IF(match, node.pn_right->isKind(PNK_PROPERTYNAME));
|
||||||
return match;
|
return match;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1282,8 +1286,7 @@ class PropertyAccess : public PropertyAccessBase
|
||||||
class OptionalPropertyAccess : public PropertyAccessBase
|
class OptionalPropertyAccess : public PropertyAccessBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
OptionalPropertyAccess(ParseNode* lhs, PropertyName* name, uint32_t begin,
|
OptionalPropertyAccess(ParseNode* lhs, ParseNode* name, uint32_t begin, uint32_t end)
|
||||||
uint32_t end)
|
|
||||||
: PropertyAccessBase(PNK_OPTDOT, lhs, name, begin, end)
|
: PropertyAccessBase(PNK_OPTDOT, lhs, name, begin, end)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(lhs != nullptr);
|
MOZ_ASSERT(lhs != nullptr);
|
||||||
|
|
@ -1292,7 +1295,8 @@ class OptionalPropertyAccess : public PropertyAccessBase
|
||||||
|
|
||||||
static bool test(const ParseNode& node) {
|
static bool test(const ParseNode& node) {
|
||||||
bool match = node.isKind(PNK_OPTDOT);
|
bool match = node.isKind(PNK_OPTDOT);
|
||||||
MOZ_ASSERT_IF(match, node.isArity(PN_NAME));
|
MOZ_ASSERT_IF(match, node.isArity(PN_BINARY));
|
||||||
|
MOZ_ASSERT_IF(match, node.pn_right->isKind(PNK_PROPERTYNAME));
|
||||||
return match;
|
return match;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -9333,11 +9333,14 @@ Parser<ParseHandler>::memberPropertyAccess(
|
||||||
error(JSMSG_BAD_SUPERPROP, "property");
|
error(JSMSG_BAD_SUPERPROP, "property");
|
||||||
return null();
|
return null();
|
||||||
}
|
}
|
||||||
|
Node name = handler.newPropertyName(field, pos());
|
||||||
|
if (!name)
|
||||||
|
return null();
|
||||||
if (optionalKind == OptionalKind::Optional) {
|
if (optionalKind == OptionalKind::Optional) {
|
||||||
MOZ_ASSERT(!handler.isSuperBase(lhs));
|
MOZ_ASSERT(!handler.isSuperBase(lhs));
|
||||||
return handler.newOptionalPropertyAccess(lhs, field, pos().end);
|
return handler.newOptionalPropertyAccess(lhs, name);
|
||||||
}
|
}
|
||||||
return handler.newPropertyAccess(lhs, field, pos().end);
|
return handler.newPropertyAccess(lhs, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class ParseHandler>
|
template <class ParseHandler>
|
||||||
|
|
|
||||||
|
|
@ -360,13 +360,16 @@ class SyntaxParseHandler
|
||||||
}
|
}
|
||||||
Node newDebuggerStatement(const TokenPos& pos) { return NodeGeneric; }
|
Node newDebuggerStatement(const TokenPos& pos) { return NodeGeneric; }
|
||||||
|
|
||||||
Node newPropertyAccess(Node pn, PropertyName* name, uint32_t end) {
|
Node newPropertyName(PropertyName* name, const TokenPos& pos) {
|
||||||
lastAtom = name;
|
lastAtom = name;
|
||||||
|
return NodeGeneric;
|
||||||
|
}
|
||||||
|
|
||||||
|
Node newPropertyAccess(Node expr, Node key) {
|
||||||
return NodeDottedProperty;
|
return NodeDottedProperty;
|
||||||
}
|
}
|
||||||
|
|
||||||
Node newOptionalPropertyAccess(Node pn, PropertyName* name, uint32_t end) {
|
Node newOptionalPropertyAccess(Node expr, Node key) {
|
||||||
lastAtom = name;
|
|
||||||
return NodeOptionalDottedProperty;
|
return NodeOptionalDottedProperty;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -642,16 +642,16 @@ static ParseNode*
|
||||||
DotBase(ParseNode* pn)
|
DotBase(ParseNode* pn)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(pn->isKind(PNK_DOT));
|
MOZ_ASSERT(pn->isKind(PNK_DOT));
|
||||||
MOZ_ASSERT(pn->isArity(PN_NAME));
|
MOZ_ASSERT(pn->isArity(PN_BINARY));
|
||||||
return pn->expr();
|
return pn->pn_left;
|
||||||
}
|
}
|
||||||
|
|
||||||
static PropertyName*
|
static PropertyName*
|
||||||
DotMember(ParseNode* pn)
|
DotMember(ParseNode* pn)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(pn->isKind(PNK_DOT));
|
MOZ_ASSERT(pn->isKind(PNK_DOT));
|
||||||
MOZ_ASSERT(pn->isArity(PN_NAME));
|
MOZ_ASSERT(pn->isArity(PN_BINARY));
|
||||||
return pn->pn_atom->asPropertyName();
|
return pn->pn_right->pn_atom->asPropertyName();
|
||||||
}
|
}
|
||||||
|
|
||||||
static ParseNode*
|
static ParseNode*
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue