Bug 1168992 - Part 3: Change PNK_SUPERPROP to PNK_DOT and fix reflection of super.prop. (r=Waldo)

This commit is contained in:
Eric Faust 2015-09-02 15:09:04 -07:00
parent f2c68805f1
commit 177ac7002d
12 changed files with 179 additions and 225 deletions

View File

@ -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:

View File

@ -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:

View File

@ -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);

View File

@ -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:

View File

@ -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) {

View File

@ -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

View File

@ -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;

View File

@ -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)

View File

@ -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();
}

View File

@ -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) {}

View File

@ -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")

View File

@ -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);