mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-25 22:01:30 +00:00
Bug 1168992 - Part 3: Change PNK_SUPERPROP to PNK_DOT and fix reflection of super.prop. (r=Waldo)
This commit is contained in:
parent
f2c68805f1
commit
177ac7002d
@ -758,6 +758,8 @@ class NodeBuilder
|
||||
|
||||
bool metaProperty(HandleValue meta, HandleValue property, TokenPos* pos, MutableHandleValue dst);
|
||||
|
||||
bool super(TokenPos* pos, MutableHandleValue dst);
|
||||
|
||||
/*
|
||||
* declarations
|
||||
*/
|
||||
@ -1838,6 +1840,16 @@ NodeBuilder::metaProperty(HandleValue meta, HandleValue property, TokenPos* pos,
|
||||
dst);
|
||||
}
|
||||
|
||||
bool
|
||||
NodeBuilder::super(TokenPos* pos, MutableHandleValue dst)
|
||||
{
|
||||
RootedValue cb(cx, callbacks[AST_SUPER]);
|
||||
if (!cb.isNull())
|
||||
return callback(cb, pos, dst);
|
||||
|
||||
return newNode(AST_SUPER, pos, dst);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
/*
|
||||
@ -3069,7 +3081,6 @@ ASTSerializer::expression(ParseNode* pn, MutableHandleValue dst)
|
||||
|
||||
case PNK_DELETENAME:
|
||||
case PNK_DELETEPROP:
|
||||
case PNK_DELETESUPERPROP:
|
||||
case PNK_DELETEELEM:
|
||||
case PNK_DELETESUPERELEM:
|
||||
case PNK_DELETEEXPR:
|
||||
@ -3132,21 +3143,20 @@ ASTSerializer::expression(ParseNode* pn, MutableHandleValue dst)
|
||||
{
|
||||
MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_expr->pn_pos));
|
||||
|
||||
RootedValue expr(cx), id(cx);
|
||||
RootedValue expr(cx);
|
||||
RootedValue propname(cx);
|
||||
RootedAtom pnAtom(cx, pn->pn_atom);
|
||||
return expression(pn->pn_expr, &expr) &&
|
||||
identifier(pnAtom, nullptr, &id) &&
|
||||
builder.memberExpression(false, expr, id, &pn->pn_pos, dst);
|
||||
}
|
||||
|
||||
case PNK_SUPERPROP:
|
||||
{
|
||||
RootedValue superBase(cx), id(cx);
|
||||
RootedAtom superAtom(cx, cx->names().super);
|
||||
RootedAtom pnAtom(cx, pn->pn_atom);
|
||||
return identifier(superAtom, nullptr, &superBase) &&
|
||||
identifier(pnAtom, nullptr, &id) &&
|
||||
builder.memberExpression(false, superBase, id, &pn->pn_pos, dst);
|
||||
if (pn->as<PropertyAccess>().isSuper()) {
|
||||
if (!builder.super(&pn->pn_expr->pn_pos, &expr))
|
||||
return false;
|
||||
} else {
|
||||
if (!expression(pn->pn_expr, &expr))
|
||||
return false;
|
||||
}
|
||||
|
||||
return identifier(pnAtom, nullptr, &propname) &&
|
||||
builder.memberExpression(false, expr, propname, &pn->pn_pos, dst);
|
||||
}
|
||||
|
||||
case PNK_ELEM:
|
||||
|
@ -1947,12 +1947,6 @@ BytecodeEmitter::checkSideEffects(ParseNode* pn, bool* answer)
|
||||
return true;
|
||||
|
||||
// Watch out for getters!
|
||||
case PNK_SUPERPROP:
|
||||
MOZ_ASSERT(pn->isArity(PN_NULLARY));
|
||||
*answer = true;
|
||||
return true;
|
||||
|
||||
// Again, getters.
|
||||
case PNK_DOT:
|
||||
MOZ_ASSERT(pn->isArity(PN_NAME));
|
||||
*answer = true;
|
||||
@ -2018,7 +2012,6 @@ BytecodeEmitter::checkSideEffects(ParseNode* pn, bool* answer)
|
||||
// Deletion generally has side effects, even if isolated cases have none.
|
||||
case PNK_DELETENAME:
|
||||
case PNK_DELETEPROP:
|
||||
case PNK_DELETESUPERPROP:
|
||||
case PNK_DELETEELEM:
|
||||
case PNK_DELETESUPERELEM:
|
||||
MOZ_ASSERT(pn->isArity(PN_UNARY));
|
||||
@ -2560,6 +2553,9 @@ BytecodeEmitter::emitPropLHS(ParseNode* pn)
|
||||
MOZ_ASSERT(pn->isKind(PNK_DOT));
|
||||
ParseNode* pn2 = pn->maybeExpr();
|
||||
|
||||
// Don't want super sneaking in here.
|
||||
MOZ_ASSERT(!pn2->isKind(PNK_POSHOLDER));
|
||||
|
||||
/*
|
||||
* 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
|
||||
@ -2576,7 +2572,7 @@ BytecodeEmitter::emitPropLHS(ParseNode* pn)
|
||||
MOZ_ASSERT(!pndot->isUsed());
|
||||
pndown = pndot->pn_expr;
|
||||
pndot->pn_expr = pnup;
|
||||
if (!pndown->isKind(PNK_DOT))
|
||||
if (!pndown->isKind(PNK_DOT) || pndown->as<PropertyAccess>().isSuper())
|
||||
break;
|
||||
pnup = pndot;
|
||||
pndot = pndown;
|
||||
@ -2656,13 +2652,21 @@ BytecodeEmitter::emitPropIncDec(ParseNode* pn)
|
||||
MOZ_ASSERT(pn->pn_kid->isKind(PNK_DOT));
|
||||
|
||||
bool post;
|
||||
bool isSuper = pn->pn_kid->as<PropertyAccess>().isSuper();
|
||||
JSOp binop = GetIncDecInfo(pn->getKind(), &post);
|
||||
|
||||
if (!emitPropLHS(pn->pn_kid)) // OBJ
|
||||
return false;
|
||||
if (!emit1(JSOP_DUP)) // OBJ OBJ
|
||||
return false;
|
||||
if (!emitAtomOp(pn->pn_kid, JSOP_GETPROP)) // OBJ V
|
||||
if (isSuper) {
|
||||
if (!emitSuperPropLHS()) // THIS OBJ
|
||||
return false;
|
||||
if (!emit1(JSOP_DUP2)) // THIS OBJ THIS OBJ
|
||||
return false;
|
||||
} else {
|
||||
if (!emitPropLHS(pn->pn_kid)) // OBJ
|
||||
return false;
|
||||
if (!emit1(JSOP_DUP)) // OBJ OBJ
|
||||
return false;
|
||||
}
|
||||
if (!emitAtomOp(pn->pn_kid, isSuper? JSOP_GETPROP_SUPER : JSOP_GETPROP)) // OBJ V
|
||||
return false;
|
||||
if (!emit1(JSOP_POS)) // OBJ N
|
||||
return false;
|
||||
@ -2674,13 +2678,20 @@ BytecodeEmitter::emitPropIncDec(ParseNode* pn)
|
||||
return false;
|
||||
|
||||
if (post) {
|
||||
if (!emit2(JSOP_PICK, 2)) // N? N+1 OBJ
|
||||
if (!emit2(JSOP_PICK, 2 + isSuper)) // N? N+1 OBJ
|
||||
return false;
|
||||
if (!emit1(JSOP_SWAP)) // N? OBJ N+1
|
||||
if (!emit1(JSOP_SWAP)) // N? OBJ N+1
|
||||
return false;
|
||||
if (isSuper) {
|
||||
if (!emit2(JSOP_PICK, 3)) // N THIS N+1 OBJ
|
||||
return false;
|
||||
if (!emit1(JSOP_SWAP)) // N THIS OBJ N+1
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
JSOp setOp = sc->strict() ? JSOP_STRICTSETPROP : JSOP_SETPROP;
|
||||
JSOp setOp = isSuper ? sc->strict() ? JSOP_STRICTSETPROP_SUPER : JSOP_SETPROP_SUPER
|
||||
: sc->strict() ? JSOP_STRICTSETPROP : JSOP_SETPROP;
|
||||
if (!emitAtomOp(pn->pn_kid, setOp)) // N? N+1
|
||||
return false;
|
||||
if (post && !emit1(JSOP_POP)) // RESULT
|
||||
@ -2689,50 +2700,6 @@ BytecodeEmitter::emitPropIncDec(ParseNode* pn)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
BytecodeEmitter::emitSuperPropIncDec(ParseNode* pn)
|
||||
{
|
||||
MOZ_ASSERT(pn->pn_kid->isKind(PNK_SUPERPROP));
|
||||
|
||||
bool post;
|
||||
JSOp binop = GetIncDecInfo(pn->getKind(), &post);
|
||||
|
||||
if (!emitSuperPropLHS()) // THIS OBJ
|
||||
return false;
|
||||
|
||||
if (!emit1(JSOP_DUP2)) // THIS OBJ THIS OBJ
|
||||
return false;
|
||||
if (!emitAtomOp(pn->pn_kid, JSOP_GETPROP_SUPER)) // THIS OBJ V
|
||||
return false;
|
||||
if (!emit1(JSOP_POS)) // THIS OBJ N
|
||||
return false;
|
||||
if (post && !emit1(JSOP_DUP)) // THIS OBJ N? N
|
||||
return false;
|
||||
if (!emit1(JSOP_ONE)) // THIS OBJ N? N 1
|
||||
return false;
|
||||
if (!emit1(binop)) // THIS OBJ N? N+1
|
||||
return false;
|
||||
|
||||
if (post) {
|
||||
if (!emit2(JSOP_PICK, 3)) // OBJ N N+1 THIS
|
||||
return false;
|
||||
if (!emit1(JSOP_SWAP)) // OBJ N THIS N+1
|
||||
return false;
|
||||
if (!emit2(JSOP_PICK, 3)) // N THIS N+1 OBJ
|
||||
return false;
|
||||
if (!emit1(JSOP_SWAP)) // N THIS OBJ N+1
|
||||
return false;
|
||||
}
|
||||
|
||||
JSOp setOp = sc->strict() ? JSOP_STRICTSETPROP_SUPER : JSOP_SETPROP_SUPER;
|
||||
if (!emitAtomOp(pn->pn_kid, setOp)) // N? N+1
|
||||
return false;
|
||||
if (post && !emit1(JSOP_POP)) // RESULT
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
BytecodeEmitter::emitNameIncDec(ParseNode* pn)
|
||||
{
|
||||
@ -3791,24 +3758,20 @@ BytecodeEmitter::emitDestructuringLHS(ParseNode* target, VarEmitOption emitOptio
|
||||
// In `[a.x] = [b]`, per spec, `b` is evaluated before `a`. Then we
|
||||
// need a property set -- but the operands are on the stack in the
|
||||
// wrong order for JSOP_SETPROP, so we have to add a JSOP_SWAP.
|
||||
if (!emitTree(target->pn_expr))
|
||||
return false;
|
||||
if (!emit1(JSOP_SWAP))
|
||||
return false;
|
||||
JSOp setOp = sc->strict() ? JSOP_STRICTSETPROP : JSOP_SETPROP;
|
||||
if (!emitAtomOp(target, setOp))
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
|
||||
case PNK_SUPERPROP:
|
||||
{
|
||||
// See comment above at PNK_DOT. Pick up the pushed value, to fix ordering.
|
||||
if (!emitSuperPropLHS())
|
||||
return false;
|
||||
if (!emit2(JSOP_PICK, 2))
|
||||
return false;
|
||||
JSOp setOp = sc->strict() ? JSOP_STRICTSETPROP_SUPER : JSOP_SETPROP_SUPER;
|
||||
JSOp setOp;
|
||||
if (target->as<PropertyAccess>().isSuper()) {
|
||||
if (!emitSuperPropLHS())
|
||||
return false;
|
||||
if (!emit2(JSOP_PICK, 2))
|
||||
return false;
|
||||
setOp = sc->strict() ? JSOP_STRICTSETPROP_SUPER : JSOP_SETPROP_SUPER;
|
||||
} else {
|
||||
if (!emitTree(target->pn_expr))
|
||||
return false;
|
||||
if (!emit1(JSOP_SWAP))
|
||||
return false;
|
||||
setOp = sc->strict() ? JSOP_STRICTSETPROP : JSOP_SETPROP;
|
||||
}
|
||||
if (!emitAtomOp(target, setOp))
|
||||
return false;
|
||||
break;
|
||||
@ -4456,16 +4419,15 @@ BytecodeEmitter::emitAssignment(ParseNode* lhs, JSOp op, ParseNode* rhs)
|
||||
}
|
||||
break;
|
||||
case PNK_DOT:
|
||||
if (!emitTree(lhs->expr()))
|
||||
return false;
|
||||
offset++;
|
||||
if (!makeAtomIndex(lhs->pn_atom, &atomIndex))
|
||||
return false;
|
||||
break;
|
||||
case PNK_SUPERPROP:
|
||||
if (!emitSuperPropLHS())
|
||||
return false;
|
||||
offset += 2;
|
||||
if (lhs->as<PropertyAccess>().isSuper()) {
|
||||
if (!emitSuperPropLHS())
|
||||
return false;
|
||||
offset += 2;
|
||||
} else {
|
||||
if (!emitTree(lhs->expr()))
|
||||
return false;
|
||||
offset += 1;
|
||||
}
|
||||
if (!makeAtomIndex(lhs->pn_atom, &atomIndex))
|
||||
return false;
|
||||
break;
|
||||
@ -4538,19 +4500,21 @@ BytecodeEmitter::emitAssignment(ParseNode* lhs, JSOp op, ParseNode* rhs)
|
||||
}
|
||||
break;
|
||||
case PNK_DOT: {
|
||||
if (!emit1(JSOP_DUP))
|
||||
return false;
|
||||
bool isLength = (lhs->pn_atom == cx->names().length);
|
||||
if (!emitIndex32(isLength ? JSOP_LENGTH : JSOP_GETPROP, atomIndex))
|
||||
JSOp getOp;
|
||||
if (lhs->as<PropertyAccess>().isSuper()) {
|
||||
if (!emit1(JSOP_DUP2))
|
||||
return false;
|
||||
getOp = JSOP_GETPROP_SUPER;
|
||||
} else {
|
||||
if (!emit1(JSOP_DUP))
|
||||
return false;
|
||||
bool isLength = (lhs->pn_atom == cx->names().length);
|
||||
getOp = isLength ? JSOP_LENGTH : JSOP_GETPROP;
|
||||
}
|
||||
if (!emitIndex32(getOp, atomIndex))
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
case PNK_SUPERPROP:
|
||||
if (!emit1(JSOP_DUP2))
|
||||
return false;
|
||||
if (!emitIndex32(JSOP_GETPROP_SUPER, atomIndex))
|
||||
return false;
|
||||
break;
|
||||
case PNK_ELEM:
|
||||
if (!emit1(JSOP_DUP2))
|
||||
return false;
|
||||
@ -4625,14 +4589,9 @@ BytecodeEmitter::emitAssignment(ParseNode* lhs, JSOp op, ParseNode* rhs)
|
||||
break;
|
||||
case PNK_DOT:
|
||||
{
|
||||
JSOp setOp = sc->strict() ? JSOP_STRICTSETPROP : JSOP_SETPROP;
|
||||
if (!emitIndexOp(setOp, atomIndex))
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
case PNK_SUPERPROP:
|
||||
{
|
||||
JSOp setOp = sc->strict() ? JSOP_STRICTSETPROP_SUPER : JSOP_SETPROP_SUPER;
|
||||
JSOp setOp = lhs->as<PropertyAccess>().isSuper() ?
|
||||
(sc->strict() ? JSOP_STRICTSETPROP_SUPER : JSOP_SETPROP_SUPER) :
|
||||
(sc->strict() ? JSOP_STRICTSETPROP : JSOP_SETPROP);
|
||||
if (!emitIndexOp(setOp, atomIndex))
|
||||
return false;
|
||||
break;
|
||||
@ -6526,26 +6485,20 @@ BytecodeEmitter::emitDeleteProperty(ParseNode* node)
|
||||
ParseNode* propExpr = node->pn_kid;
|
||||
MOZ_ASSERT(propExpr->isKind(PNK_DOT));
|
||||
|
||||
if (propExpr->as<PropertyAccess>().isSuper()) {
|
||||
// Still have to calculate the base, even though we are are going
|
||||
// to throw unconditionally, as calculating the base could also
|
||||
// throw.
|
||||
if (!emit1(JSOP_SUPERBASE))
|
||||
return false;
|
||||
|
||||
return emitUint16Operand(JSOP_THROWMSG, JSMSG_CANT_DELETE_SUPER);
|
||||
}
|
||||
|
||||
JSOp delOp = sc->strict() ? JSOP_STRICTDELPROP : JSOP_DELPROP;
|
||||
return emitPropOp(propExpr, delOp);
|
||||
}
|
||||
|
||||
bool
|
||||
BytecodeEmitter::emitDeleteSuperProperty(ParseNode* node)
|
||||
{
|
||||
MOZ_ASSERT(node->isKind(PNK_DELETESUPERPROP));
|
||||
MOZ_ASSERT(node->isArity(PN_UNARY));
|
||||
MOZ_ASSERT(node->pn_kid->isKind(PNK_SUPERPROP));
|
||||
|
||||
// Still have to calculate the base, even though we are are going
|
||||
// to throw unconditionally, as calculating the base could also
|
||||
// throw.
|
||||
if (!emit1(JSOP_SUPERBASE))
|
||||
return false;
|
||||
|
||||
return emitUint16Operand(JSOP_THROWMSG, JSMSG_CANT_DELETE_SUPER);
|
||||
}
|
||||
|
||||
bool
|
||||
BytecodeEmitter::emitDeleteElement(ParseNode* node)
|
||||
{
|
||||
@ -6742,12 +6695,13 @@ BytecodeEmitter::emitCallOrNew(ParseNode* pn)
|
||||
return false;
|
||||
break;
|
||||
case PNK_DOT:
|
||||
if (!emitPropOp(pn2, callop ? JSOP_CALLPROP : JSOP_GETPROP))
|
||||
return false;
|
||||
break;
|
||||
case PNK_SUPERPROP:
|
||||
if (!emitSuperPropOp(pn2, JSOP_GETPROP_SUPER, /* isCall = */ callop))
|
||||
return false;
|
||||
if (pn2->as<PropertyAccess>().isSuper()) {
|
||||
if (!emitSuperPropOp(pn2, JSOP_GETPROP_SUPER, /* isCall = */ callop))
|
||||
return false;
|
||||
} else {
|
||||
if (!emitPropOp(pn2, callop ? JSOP_CALLPROP : JSOP_GETPROP))
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case PNK_ELEM:
|
||||
if (!emitElemOp(pn2, callop ? JSOP_CALLELEM : JSOP_GETELEM))
|
||||
@ -6917,10 +6871,6 @@ BytecodeEmitter::emitIncOrDec(ParseNode* pn)
|
||||
if (!emitPropIncDec(pn))
|
||||
return false;
|
||||
break;
|
||||
case PNK_SUPERPROP:
|
||||
if (!emitSuperPropIncDec(pn))
|
||||
return false;
|
||||
break;
|
||||
case PNK_ELEM:
|
||||
if (!emitElemIncDec(pn))
|
||||
return false;
|
||||
@ -7892,10 +7842,6 @@ BytecodeEmitter::emitTree(ParseNode* pn)
|
||||
ok = emitDeleteProperty(pn);
|
||||
break;
|
||||
|
||||
case PNK_DELETESUPERPROP:
|
||||
ok = emitDeleteSuperProperty(pn);
|
||||
break;
|
||||
|
||||
case PNK_DELETEELEM:
|
||||
ok = emitDeleteElement(pn);
|
||||
break;
|
||||
@ -7909,12 +7855,13 @@ BytecodeEmitter::emitTree(ParseNode* pn)
|
||||
break;
|
||||
|
||||
case PNK_DOT:
|
||||
ok = emitPropOp(pn, JSOP_GETPROP);
|
||||
break;
|
||||
|
||||
case PNK_SUPERPROP:
|
||||
if (!emitSuperPropOp(pn, JSOP_GETPROP_SUPER))
|
||||
return false;
|
||||
if (pn->as<PropertyAccess>().isSuper()) {
|
||||
if (!emitSuperPropOp(pn, JSOP_GETPROP_SUPER))
|
||||
return false;
|
||||
} else {
|
||||
if (!emitPropOp(pn, JSOP_GETPROP))
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
case PNK_ELEM:
|
||||
|
@ -554,7 +554,6 @@ struct BytecodeEmitter
|
||||
|
||||
bool emitDeleteName(ParseNode* pn);
|
||||
bool emitDeleteProperty(ParseNode* pn);
|
||||
bool emitDeleteSuperProperty(ParseNode* pn);
|
||||
bool emitDeleteElement(ParseNode* pn);
|
||||
bool emitDeleteSuperElement(ParseNode* pn);
|
||||
bool emitDeleteExpression(ParseNode* pn);
|
||||
@ -611,7 +610,6 @@ struct BytecodeEmitter
|
||||
bool emitClass(ParseNode* pn);
|
||||
bool emitSuperPropLHS(bool isCall = false);
|
||||
bool emitSuperPropOp(ParseNode* pn, JSOp op, bool isCall = false);
|
||||
bool emitSuperPropIncDec(ParseNode* pn);
|
||||
enum SuperElemOptions { SuperElem_Get, SuperElem_Set, SuperElem_Call, SuperElem_IncDec };
|
||||
bool emitSuperElemOperands(ParseNode* pn, SuperElemOptions opts = SuperElem_Get);
|
||||
bool emitSuperElemOp(ParseNode* pn, JSOp op, bool isCall = false);
|
||||
|
@ -334,7 +334,6 @@ ContainsHoistedDeclaration(ExclusiveContext* cx, ParseNode* node, bool* result)
|
||||
case PNK_BITNOT:
|
||||
case PNK_DELETENAME:
|
||||
case PNK_DELETEPROP:
|
||||
case PNK_DELETESUPERPROP:
|
||||
case PNK_DELETEELEM:
|
||||
case PNK_DELETESUPERELEM:
|
||||
case PNK_DELETEEXPR:
|
||||
@ -414,7 +413,6 @@ ContainsHoistedDeclaration(ExclusiveContext* cx, ParseNode* node, bool* result)
|
||||
case PNK_CLASSMETHOD:
|
||||
case PNK_CLASSMETHODLIST:
|
||||
case PNK_CLASSNAMES:
|
||||
case PNK_SUPERPROP:
|
||||
case PNK_SUPERELEM:
|
||||
case PNK_NEWTARGET:
|
||||
case PNK_POSHOLDER:
|
||||
@ -660,9 +658,9 @@ static bool
|
||||
FoldDeleteProperty(ExclusiveContext* cx, ParseNode* node, Parser<FullParseHandler>& parser,
|
||||
bool inGenexpLambda)
|
||||
{
|
||||
MOZ_ASSERT(node->isKind(PNK_DELETEPROP) || node->isKind(PNK_DELETESUPERPROP));
|
||||
MOZ_ASSERT(node->isKind(PNK_DELETEPROP));
|
||||
MOZ_ASSERT(node->isArity(PN_UNARY));
|
||||
MOZ_ASSERT(node->pn_kid->isKind(PNK_DOT) || node->pn_kid->isKind(PNK_SUPERPROP));
|
||||
MOZ_ASSERT(node->pn_kid->isKind(PNK_DOT));
|
||||
|
||||
ParseNode*& expr = node->pn_kid;
|
||||
#ifdef DEBUG
|
||||
@ -1726,7 +1724,6 @@ Fold(ExclusiveContext* cx, ParseNode** pnp, Parser<FullParseHandler>& parser, bo
|
||||
case PNK_GENERATOR:
|
||||
case PNK_EXPORT_BATCH_SPEC:
|
||||
case PNK_OBJECT_PROPERTY_NAME:
|
||||
case PNK_SUPERPROP:
|
||||
case PNK_FRESHENBLOCK:
|
||||
case PNK_POSHOLDER:
|
||||
MOZ_ASSERT(pn->isArity(PN_NULLARY));
|
||||
@ -1755,7 +1752,6 @@ Fold(ExclusiveContext* cx, ParseNode** pnp, Parser<FullParseHandler>& parser, bo
|
||||
return FoldDeleteElement(cx, pn, parser, inGenexpLambda);
|
||||
|
||||
case PNK_DELETEPROP:
|
||||
case PNK_DELETESUPERPROP:
|
||||
return FoldDeleteProperty(cx, pn, parser, inGenexpLambda);
|
||||
|
||||
case PNK_CONDITIONAL:
|
||||
|
@ -75,7 +75,7 @@ class FullParseHandler
|
||||
bool isPropertyAccess(ParseNode* node) {
|
||||
if (node->isKind(PNK_DOT) || node->isKind(PNK_ELEM))
|
||||
return true;
|
||||
return node->isKind(PNK_SUPERPROP) || node->isKind(PNK_SUPERELEM);
|
||||
return node->isKind(PNK_SUPERELEM);
|
||||
}
|
||||
|
||||
bool isFunctionCall(ParseNode* node) {
|
||||
@ -225,8 +225,6 @@ class FullParseHandler
|
||||
|
||||
if (expr->isKind(PNK_DOT))
|
||||
return newUnary(PNK_DELETEPROP, JSOP_NOP, begin, expr);
|
||||
if (expr->isKind(PNK_SUPERPROP))
|
||||
return newUnary(PNK_DELETESUPERPROP, JSOP_NOP, begin, expr);
|
||||
|
||||
if (expr->isKind(PNK_ELEM))
|
||||
return newUnary(PNK_DELETEELEM, JSOP_NOP, begin, expr);
|
||||
@ -346,9 +344,6 @@ class FullParseHandler
|
||||
ParseNode* newClassNames(ParseNode* outer, ParseNode* inner, const TokenPos& pos) {
|
||||
return new_<ClassNames>(outer, inner, pos);
|
||||
}
|
||||
ParseNode* newSuperProperty(JSAtom* atom, const TokenPos& pos) {
|
||||
return new_<SuperProperty>(atom, pos);
|
||||
}
|
||||
ParseNode* newSuperElement(ParseNode* expr, const TokenPos& pos) {
|
||||
return new_<SuperElement>(expr, pos);
|
||||
}
|
||||
@ -358,6 +353,15 @@ class FullParseHandler
|
||||
ParseNode* newPosHolder(const TokenPos& pos) {
|
||||
return new_<NullaryNode>(PNK_POSHOLDER, pos);
|
||||
}
|
||||
ParseNode* newSuperBase(const TokenPos& pos, ExclusiveContext* cx) {
|
||||
ParseNode* node = newPosHolder(pos);
|
||||
#ifdef DEBUG
|
||||
// Set the atom for assertion purposes
|
||||
if (node)
|
||||
node->pn_atom = cx->names().super;
|
||||
#endif
|
||||
return node;
|
||||
}
|
||||
|
||||
bool addPrototypeMutation(ParseNode* literal, uint32_t begin, ParseNode* expr) {
|
||||
// Object literals with mutated [[Prototype]] are non-constant so that
|
||||
@ -714,6 +718,11 @@ class FullParseHandler
|
||||
(kind == PNK_SEMI && !node->pn_kid);
|
||||
}
|
||||
|
||||
bool isSuperBase(ParseNode* node, ExclusiveContext* cx) {
|
||||
MOZ_ASSERT_IF(node->isKind(PNK_POSHOLDER), node->pn_atom == cx->names().super);
|
||||
return node->isKind(PNK_POSHOLDER);
|
||||
}
|
||||
|
||||
inline bool finishInitializerAssignment(ParseNode* pn, ParseNode* init, JSOp op);
|
||||
|
||||
void setBeginPosition(ParseNode* pn, ParseNode* oth) {
|
||||
|
@ -375,7 +375,6 @@ class NameResolver
|
||||
case PNK_DEBUGGER:
|
||||
case PNK_EXPORT_BATCH_SPEC:
|
||||
case PNK_FRESHENBLOCK:
|
||||
case PNK_SUPERPROP:
|
||||
case PNK_OBJECT_PROPERTY_NAME:
|
||||
MOZ_ASSERT(cur->isArity(PN_NULLARY));
|
||||
break;
|
||||
@ -400,7 +399,6 @@ class NameResolver
|
||||
case PNK_THROW:
|
||||
case PNK_DELETENAME:
|
||||
case PNK_DELETEPROP:
|
||||
case PNK_DELETESUPERPROP:
|
||||
case PNK_DELETEELEM:
|
||||
case PNK_DELETESUPERELEM:
|
||||
case PNK_DELETEEXPR:
|
||||
@ -757,9 +755,18 @@ class NameResolver
|
||||
break;
|
||||
}
|
||||
|
||||
case PNK_LABEL:
|
||||
case PNK_DOT:
|
||||
MOZ_ASSERT(cur->isArity(PN_NAME));
|
||||
|
||||
// Super prop nodes do not have a meaningful LHS
|
||||
if (cur->as<PropertyAccess>().isSuper())
|
||||
break;
|
||||
if (!resolve(cur->expr(), prefix))
|
||||
return false;
|
||||
break;
|
||||
|
||||
case PNK_LABEL:
|
||||
MOZ_ASSERT(cur->isArity(PN_NAME));
|
||||
if (!resolve(cur->expr(), prefix))
|
||||
return false;
|
||||
break;
|
||||
@ -784,7 +791,7 @@ class NameResolver
|
||||
case PNK_EXPORT_SPEC: // by PNK_EXPORT_SPEC_LIST
|
||||
case PNK_CALLSITEOBJ: // by PNK_TAGGED_TEMPLATE
|
||||
case PNK_CLASSNAMES: // by PNK_CLASS
|
||||
case PNK_POSHOLDER: // by PNK_NEWTARGET
|
||||
case PNK_POSHOLDER: // by PNK_NEWTARGET, PNK_DOT
|
||||
MOZ_CRASH("should have been handled by a parent node");
|
||||
|
||||
case PNK_LIMIT: // invalid sentinel value
|
||||
|
@ -214,7 +214,6 @@ PushNodeChildren(ParseNode* pn, NodeStack* stack)
|
||||
case PNK_EXPORT_BATCH_SPEC:
|
||||
case PNK_OBJECT_PROPERTY_NAME:
|
||||
case PNK_FRESHENBLOCK:
|
||||
case PNK_SUPERPROP:
|
||||
case PNK_POSHOLDER:
|
||||
MOZ_ASSERT(pn->isArity(PN_NULLARY));
|
||||
MOZ_ASSERT(!pn->isUsed(), "handle non-trivial cases separately");
|
||||
@ -230,7 +229,6 @@ PushNodeChildren(ParseNode* pn, NodeStack* stack)
|
||||
case PNK_THROW:
|
||||
case PNK_DELETENAME:
|
||||
case PNK_DELETEPROP:
|
||||
case PNK_DELETESUPERPROP:
|
||||
case PNK_DELETEELEM:
|
||||
case PNK_DELETESUPERELEM:
|
||||
case PNK_DELETEEXPR:
|
||||
@ -1107,7 +1105,10 @@ NameNode::dump(int indent)
|
||||
|
||||
if (isKind(PNK_DOT)) {
|
||||
fputc(' ', stderr);
|
||||
DumpParseTree(expr(), indent + 2);
|
||||
if (as<PropertyAccess>().isSuper())
|
||||
fprintf(stderr, "super");
|
||||
else
|
||||
DumpParseTree(expr(), indent + 2);
|
||||
fputc(')', stderr);
|
||||
}
|
||||
return;
|
||||
|
@ -138,7 +138,6 @@ class PackedScopeCoordinate
|
||||
/* Delete operations. These must be sequential. */ \
|
||||
F(DELETENAME) \
|
||||
F(DELETEPROP) \
|
||||
F(DELETESUPERPROP) \
|
||||
F(DELETEELEM) \
|
||||
F(DELETESUPERELEM) \
|
||||
F(DELETEEXPR) \
|
||||
@ -176,7 +175,6 @@ class PackedScopeCoordinate
|
||||
F(CLASSMETHOD) \
|
||||
F(CLASSMETHODLIST) \
|
||||
F(CLASSNAMES) \
|
||||
F(SUPERPROP) \
|
||||
F(SUPERELEM) \
|
||||
F(NEWTARGET) \
|
||||
F(POSHOLDER) \
|
||||
@ -433,7 +431,6 @@ IsDeleteKind(ParseNodeKind kind)
|
||||
* ctor is a MEMBER expr
|
||||
* PNK_DELETENAME unary pn_kid: PNK_NAME expr
|
||||
* PNK_DELETEPROP unary pn_kid: PNK_DOT expr
|
||||
* PNK_DELETESUPERPROP unary pn_kid: PNK_SUPERPROP expr
|
||||
* PNK_DELETEELEM unary pn_kid: PNK_ELEM expr
|
||||
* PNK_DELETESUPERELEM unary pn_kid: PNK_SUPERELEM expr
|
||||
* PNK_DELETEEXPR unary pn_kid: MEMBER expr that's evaluated, then the
|
||||
@ -1324,6 +1321,11 @@ class PropertyAccess : public ParseNode
|
||||
PropertyName& name() const {
|
||||
return *pn_u.name.atom->asPropertyName();
|
||||
}
|
||||
|
||||
bool isSuper() const {
|
||||
// PNK_POSHOLDER cannot result from any expression syntax.
|
||||
return expression().isKind(PNK_POSHOLDER);
|
||||
}
|
||||
};
|
||||
|
||||
class PropertyByValue : public ParseNode
|
||||
@ -1447,22 +1449,6 @@ struct ClassNode : public TernaryNode {
|
||||
}
|
||||
};
|
||||
|
||||
struct SuperProperty : public NullaryNode {
|
||||
SuperProperty(JSAtom* atom, const TokenPos& pos)
|
||||
: NullaryNode(PNK_SUPERPROP, JSOP_NOP, pos, atom)
|
||||
{ }
|
||||
|
||||
static bool test(const ParseNode& node) {
|
||||
bool match = node.isKind(PNK_SUPERPROP);
|
||||
MOZ_ASSERT_IF(match, node.isArity(PN_NULLARY));
|
||||
return match;
|
||||
}
|
||||
|
||||
JSAtom* propName() const {
|
||||
return pn_atom;
|
||||
}
|
||||
};
|
||||
|
||||
struct SuperElement : public UnaryNode {
|
||||
SuperElement(ParseNode* expr, const TokenPos& pos)
|
||||
: UnaryNode(PNK_SUPERELEM, JSOP_NOP, pos, expr)
|
||||
|
@ -4965,7 +4965,6 @@ Parser<FullParseHandler>::isValidForStatementLHS(ParseNode* pn1, JSVersion versi
|
||||
case PNK_ARRAY:
|
||||
case PNK_CALL:
|
||||
case PNK_DOT:
|
||||
case PNK_SUPERPROP:
|
||||
case PNK_ELEM:
|
||||
case PNK_SUPERELEM:
|
||||
case PNK_NAME:
|
||||
@ -8250,7 +8249,6 @@ Parser<ParseHandler>::memberExpr(YieldHandling yieldHandling, TokenKind tt, bool
|
||||
|
||||
JS_CHECK_RECURSION(context, return null());
|
||||
|
||||
bool isSuper = false;
|
||||
uint32_t superBegin = pos().begin;
|
||||
|
||||
/* Check for new expression first. */
|
||||
@ -8287,14 +8285,17 @@ Parser<ParseHandler>::memberExpr(YieldHandling yieldHandling, TokenKind tt, bool
|
||||
}
|
||||
}
|
||||
} else if (tt == TOK_SUPER) {
|
||||
lhs = null();
|
||||
isSuper = true;
|
||||
lhs = handler.newSuperBase(pos(), context);
|
||||
if (!lhs)
|
||||
return null();
|
||||
} else {
|
||||
lhs = primaryExpr(yieldHandling, tt, invoked);
|
||||
if (!lhs)
|
||||
return null();
|
||||
}
|
||||
|
||||
MOZ_ASSERT_IF(handler.isSuperBase(lhs, context), tokenStream.isCurrentTokenType(TOK_SUPER));
|
||||
|
||||
while (true) {
|
||||
if (!tokenStream.getToken(&tt))
|
||||
return null();
|
||||
@ -8307,16 +8308,11 @@ Parser<ParseHandler>::memberExpr(YieldHandling yieldHandling, TokenKind tt, bool
|
||||
return null();
|
||||
if (tt == TOK_NAME) {
|
||||
PropertyName* field = tokenStream.currentName();
|
||||
if (isSuper) {
|
||||
isSuper = false;
|
||||
if (!checkAndMarkSuperScope()) {
|
||||
report(ParseError, false, null(), JSMSG_BAD_SUPERPROP, "property");
|
||||
return null();
|
||||
}
|
||||
nextMember = handler.newSuperProperty(field, TokenPos(superBegin, pos().end));
|
||||
} else {
|
||||
nextMember = handler.newPropertyAccess(lhs, field, pos().end);
|
||||
if (handler.isSuperBase(lhs, context) && !checkAndMarkSuperScope()) {
|
||||
report(ParseError, false, null(), JSMSG_BAD_SUPERPROP, "property");
|
||||
return null();
|
||||
}
|
||||
nextMember = handler.newPropertyAccess(lhs, field, pos().end);
|
||||
if (!nextMember)
|
||||
return null();
|
||||
} else {
|
||||
@ -8330,8 +8326,7 @@ Parser<ParseHandler>::memberExpr(YieldHandling yieldHandling, TokenKind tt, bool
|
||||
|
||||
MUST_MATCH_TOKEN(TOK_RB, JSMSG_BRACKET_IN_INDEX);
|
||||
|
||||
if (isSuper) {
|
||||
isSuper = false;
|
||||
if (handler.isSuperBase(lhs, context)) {
|
||||
if (!checkAndMarkSuperScope()) {
|
||||
report(ParseError, false, null(), JSMSG_BAD_SUPERPROP, "member");
|
||||
return null();
|
||||
@ -8346,7 +8341,7 @@ Parser<ParseHandler>::memberExpr(YieldHandling yieldHandling, TokenKind tt, bool
|
||||
tt == TOK_TEMPLATE_HEAD ||
|
||||
tt == TOK_NO_SUBS_TEMPLATE)
|
||||
{
|
||||
if (isSuper) {
|
||||
if (handler.isSuperBase(lhs, context)) {
|
||||
// For now...
|
||||
report(ParseError, false, null(), JSMSG_BAD_SUPER);
|
||||
return null();
|
||||
@ -8410,18 +8405,16 @@ Parser<ParseHandler>::memberExpr(YieldHandling yieldHandling, TokenKind tt, bool
|
||||
}
|
||||
handler.setOp(nextMember, op);
|
||||
} else {
|
||||
if (isSuper) {
|
||||
report(ParseError, false, null(), JSMSG_BAD_SUPER);
|
||||
return null();
|
||||
}
|
||||
tokenStream.ungetToken();
|
||||
if (handler.isSuperBase(lhs, context))
|
||||
break;
|
||||
return lhs;
|
||||
}
|
||||
|
||||
lhs = nextMember;
|
||||
}
|
||||
|
||||
if (isSuper) {
|
||||
if (handler.isSuperBase(lhs, context)) {
|
||||
report(ParseError, false, null(), JSMSG_BAD_SUPER);
|
||||
return null();
|
||||
}
|
||||
|
@ -47,7 +47,6 @@ class SyntaxParseHandler
|
||||
NodeThrow,
|
||||
NodeEmptyStatement,
|
||||
|
||||
NodeSuperProperty,
|
||||
NodeSuperElement,
|
||||
|
||||
// This is needed for proper assignment-target handling. ES6 formally
|
||||
@ -132,13 +131,17 @@ class SyntaxParseHandler
|
||||
// warnings, and parsing with that option disables syntax parsing. But
|
||||
// it seems best to be consistent, and perhaps the syntax parser will
|
||||
// eventually enforce extraWarnings and will require this then.)
|
||||
NodeUnparenthesizedAssignment
|
||||
NodeUnparenthesizedAssignment,
|
||||
|
||||
// This node is necessary to determine if the LHS of a property access is
|
||||
// super related.
|
||||
NodeSuperBase
|
||||
};
|
||||
typedef Definition::Kind DefinitionNode;
|
||||
|
||||
bool isPropertyAccess(Node node) {
|
||||
return node == NodeDottedProperty || node == NodeElement ||
|
||||
node == NodeSuperProperty || node == NodeSuperElement;
|
||||
node == NodeSuperElement;
|
||||
}
|
||||
|
||||
bool isFunctionCall(Node node) {
|
||||
@ -274,15 +277,12 @@ class SyntaxParseHandler
|
||||
Node newObjectLiteral(uint32_t begin) { return NodeUnparenthesizedObject; }
|
||||
Node newClassMethodList(uint32_t begin) { return NodeGeneric; }
|
||||
|
||||
Node newSuperProperty(PropertyName* prop, const TokenPos& pos) {
|
||||
return NodeSuperProperty;
|
||||
}
|
||||
|
||||
Node newSuperElement(Node expr, const TokenPos& pos) {
|
||||
return NodeSuperElement;
|
||||
}
|
||||
Node newNewTarget(Node newHolder, Node targetHolder) { return NodeGeneric; }
|
||||
Node newPosHolder(const TokenPos& pos) { return NodeGeneric; }
|
||||
Node newSuperBase(const TokenPos& pos, ExclusiveContext* cx) { return NodeSuperBase; }
|
||||
|
||||
bool addPrototypeMutation(Node literal, uint32_t begin, Node expr) { return true; }
|
||||
bool addPropertyDefinition(Node literal, Node name, Node expr) { return true; }
|
||||
@ -437,6 +437,12 @@ class SyntaxParseHandler
|
||||
pn == NodeEmptyStatement;
|
||||
}
|
||||
|
||||
bool isSuperBase(Node pn, ExclusiveContext* cx) {
|
||||
// While NodePosHolder is used in other places than just as super-base,
|
||||
// it is unique enough for our purposes.
|
||||
return pn == NodeSuperBase;
|
||||
}
|
||||
|
||||
void setOp(Node pn, JSOp op) {}
|
||||
void setBlockId(Node pn, unsigned blockid) {}
|
||||
void setFlag(Node pn, unsigned flag) {}
|
||||
|
@ -39,6 +39,7 @@ ASTDEF(AST_GENERATOR_EXPR, "GeneratorExpression", "generatorEx
|
||||
ASTDEF(AST_YIELD_EXPR, "YieldExpression", "yieldExpression")
|
||||
ASTDEF(AST_CLASS_EXPR, "ClassExpression", "classExpression")
|
||||
ASTDEF(AST_METAPROPERTY, "MetaProperty", "metaProperty")
|
||||
ASTDEF(AST_SUPER, "Super", "super")
|
||||
|
||||
ASTDEF(AST_EMPTY_STMT, "EmptyStatement", "emptyStatement")
|
||||
ASTDEF(AST_BLOCK_STMT, "BlockStatement", "blockStatement")
|
||||
|
@ -124,7 +124,7 @@ function letStmt(head, body) {
|
||||
}
|
||||
|
||||
function superProp(id) {
|
||||
return dotExpr(ident("super"), id);
|
||||
return dotExpr(Pattern({ type: "Super" }), id);
|
||||
}
|
||||
function superElem(id) {
|
||||
return memExpr(ident("super"), id);
|
||||
|
Loading…
Reference in New Issue
Block a user