author | Nigel Babu <nigelbabu@gmail.com> |
Thu, 03 Sep 2015 08:56:51 +0530 | |
changeset 260646 | 857b2baa431251cd402b7ffba6ef5f5035a74a8a |
parent 260645 | 26951c3aa2671ccdc8e78d21c00c2a0501fd2bb5 |
child 260647 | 5e73247011308429810e8bd2fbafa3c1bb898f39 |
push id | 29318 |
push user | cbook@mozilla.com |
push date | Thu, 03 Sep 2015 11:15:07 +0000 |
treeherder | mozilla-central@74fbd245369c [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
bugs | 1168992 |
milestone | 43.0a1 |
backs out | 4f7c8a5677070cfd021dd205c90d60cebc449ee2 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/js/src/builtin/ReflectParse.cpp +++ b/js/src/builtin/ReflectParse.cpp @@ -753,18 +753,16 @@ class NodeBuilder bool comprehensionExpression(HandleValue body, NodeVector& blocks, HandleValue filter, bool isLegacy, TokenPos* pos, MutableHandleValue dst); bool generatorExpression(HandleValue body, NodeVector& blocks, HandleValue filter, bool isLegacy, TokenPos* pos, MutableHandleValue dst); bool metaProperty(HandleValue meta, HandleValue property, TokenPos* pos, MutableHandleValue dst); - bool super(TokenPos* pos, MutableHandleValue dst); - /* * declarations */ bool variableDeclaration(NodeVector& elts, VarDeclKind kind, TokenPos* pos, MutableHandleValue dst); /* @@ -1835,26 +1833,16 @@ NodeBuilder::metaProperty(HandleValue me return callback(cb, meta, property, pos, dst); return newNode(AST_METAPROPERTY, pos, "meta", meta, "property", property, 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 { /* * Serialization of parse nodes to JavaScript objects. * * All serialization methods take a non-nullable ParseNode pointer. */ class ASTSerializer @@ -3076,16 +3064,17 @@ ASTSerializer::expression(ParseNode* pn, case PNK_INSTANCEOF: return leftAssociate(pn, dst); case PNK_POW: return rightAssociate(pn, dst); case PNK_DELETENAME: case PNK_DELETEPROP: + case PNK_DELETESUPERPROP: case PNK_DELETEELEM: case PNK_DELETESUPERELEM: case PNK_DELETEEXPR: case PNK_TYPEOFNAME: case PNK_TYPEOFEXPR: case PNK_VOID: case PNK_NOT: case PNK_BITNOT: @@ -3138,30 +3127,31 @@ ASTSerializer::expression(ParseNode* pn, : builder.callExpression(callee, args, &pn->pn_pos, dst); } case PNK_DOT: { MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_expr->pn_pos)); - RootedValue expr(cx); - RootedValue propname(cx); + RootedValue expr(cx), id(cx); RootedAtom pnAtom(cx, pn->pn_atom); - - 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); + 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); } case PNK_ELEM: { MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_left->pn_pos)); MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_right->pn_pos)); RootedValue left(cx), right(cx);
--- a/js/src/frontend/BytecodeEmitter.cpp +++ b/js/src/frontend/BytecodeEmitter.cpp @@ -1942,16 +1942,22 @@ BytecodeEmitter::checkSideEffects(ParseN case PNK_BREAK: case PNK_CONTINUE: case PNK_DEBUGGER: MOZ_ASSERT(pn->isArity(PN_NULLARY)); *answer = true; 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; return true; // Unary cases with side effects only if the child has them. case PNK_TYPEOFEXPR: case PNK_VOID: @@ -2007,16 +2013,17 @@ BytecodeEmitter::checkSideEffects(ParseN case PNK_YIELD: MOZ_ASSERT(pn->isArity(PN_BINARY)); *answer = true; return true; // 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)); *answer = true; return true; // Deletion of a non-Reference expression has side effects only through // evaluating the expression. @@ -2548,36 +2555,33 @@ BytecodeEmitter::emitNameOp(ParseNode* p } bool 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 * bottom up (reversing again as we go), to avoid excessive recursion. */ if (pn2->isKind(PNK_DOT)) { ParseNode* pndot = pn2; ParseNode* pnup = nullptr; ParseNode* pndown; ptrdiff_t top = offset(); for (;;) { /* Reverse pndot->pn_expr to point up, not down. */ pndot->pn_offset = top; MOZ_ASSERT(!pndot->isUsed()); pndown = pndot->pn_expr; pndot->pn_expr = pnup; - if (!pndown->isKind(PNK_DOT) || pndown->as<PropertyAccess>().isSuper()) + if (!pndown->isKind(PNK_DOT)) break; pnup = pndot; pndot = pndown; } /* pndown is a primary expression, not a dotted property reference. */ if (!emitTree(pndown)) return false; @@ -2647,65 +2651,94 @@ BytecodeEmitter::emitSuperPropOp(ParseNo } bool 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 (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 + 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 return false; if (!emit1(JSOP_POS)) // OBJ N return false; if (post && !emit1(JSOP_DUP)) // OBJ N? N return false; if (!emit1(JSOP_ONE)) // OBJ N? N 1 return false; if (!emit1(binop)) // OBJ N? N+1 return false; if (post) { - if (!emit2(JSOP_PICK, 2 + isSuper)) // N? N+1 OBJ - return false; - 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 = isSuper ? sc->strict() ? JSOP_STRICTSETPROP_SUPER : JSOP_SETPROP_SUPER - : sc->strict() ? JSOP_STRICTSETPROP : JSOP_SETPROP; + if (!emit2(JSOP_PICK, 2)) // N? N+1 OBJ + return false; + if (!emit1(JSOP_SWAP)) // N? OBJ N+1 + return false; + } + + JSOp setOp = sc->strict() ? JSOP_STRICTSETPROP : JSOP_SETPROP; if (!emitAtomOp(pn->pn_kid, setOp)) // N? N+1 return false; if (post && !emit1(JSOP_POP)) // RESULT return false; 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) { const JSCodeSpec* cs = &js_CodeSpec[pn->pn_kid->getOp()]; bool global = (cs->format & JOF_GNAME); bool post; JSOp binop = GetIncDecInfo(pn->getKind(), &post); @@ -3753,30 +3786,34 @@ BytecodeEmitter::emitDestructuringLHS(Pa // See the (PNK_NAME, JSOP_SETNAME) case above. // // In `a.x = b`, `a` is evaluated first, then `b`, then a // JSOP_SETPROP instruction. // // 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. - 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 (!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; if (!emitAtomOp(target, setOp)) return false; break; } case PNK_ELEM: { // See the comment at `case PNK_DOT:` above. This case, @@ -4414,25 +4451,26 @@ BytecodeEmitter::emitAssignment(ParseNod bindOp = JSOP_BINDINTRINSIC; if (!emitIndex32(bindOp, atomIndex)) return false; offset++; } } break; case PNK_DOT: - if (lhs->as<PropertyAccess>().isSuper()) { - if (!emitSuperPropLHS()) - return false; - offset += 2; - } else { - if (!emitTree(lhs->expr())) - return false; - offset += 1; - } + 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 (!makeAtomIndex(lhs->pn_atom, &atomIndex)) return false; break; case PNK_ELEM: MOZ_ASSERT(lhs->isArity(PN_BINARY)); if (!emitTree(lhs->pn_left)) return false; if (!emitTree(lhs->pn_right)) @@ -4495,31 +4533,29 @@ BytecodeEmitter::emitAssignment(ParseNod case JSOP_SETALIASEDVAR: op = JSOP_GETALIASEDVAR; break; default: MOZ_CRASH("Bad op"); } if (!emitVarOp(lhs, op)) return false; } break; case PNK_DOT: { - 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)) + if (!emit1(JSOP_DUP)) + return false; + bool isLength = (lhs->pn_atom == cx->names().length); + if (!emitIndex32(isLength ? JSOP_LENGTH : JSOP_GETPROP, 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; if (!emitElemOpBase(JSOP_GETELEM)) return false; break; case PNK_SUPERELEM: if (!emitDupAt(2)) @@ -4584,19 +4620,24 @@ BytecodeEmitter::emitAssignment(ParseNod return false; } else { if (!emitIndexOp(lhs->getOp(), atomIndex)) return false; } break; case PNK_DOT: { - JSOp setOp = lhs->as<PropertyAccess>().isSuper() ? - (sc->strict() ? JSOP_STRICTSETPROP_SUPER : JSOP_SETPROP_SUPER) : - (sc->strict() ? JSOP_STRICTSETPROP : JSOP_SETPROP); + 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; if (!emitIndexOp(setOp, atomIndex)) return false; break; } case PNK_CALL: /* Do nothing. The JSOP_SETCALL we emitted will always throw. */ MOZ_ASSERT(lhs->pn_xflags & PNX_SETCALL); break; @@ -6480,31 +6521,37 @@ bool BytecodeEmitter::emitDeleteProperty(ParseNode* node) { MOZ_ASSERT(node->isKind(PNK_DELETEPROP)); MOZ_ASSERT(node->isArity(PN_UNARY)); 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) { MOZ_ASSERT(node->isKind(PNK_DELETEELEM)); MOZ_ASSERT(node->isArity(PN_UNARY)); ParseNode* elemExpr = node->pn_kid; MOZ_ASSERT(elemExpr->isKind(PNK_ELEM)); @@ -6690,23 +6737,22 @@ BytecodeEmitter::emitCallOrNew(ParseNode if (pn2->name() == cx->names().forceInterpreter) return emitSelfHostedForceInterpreter(pn); // Fall through. } if (!emitNameOp(pn2, callop)) return false; break; case PNK_DOT: - 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; - } + if (!emitPropOp(pn2, callop ? JSOP_CALLPROP : JSOP_GETPROP)) + return false; + break; + case PNK_SUPERPROP: + if (!emitSuperPropOp(pn2, JSOP_GETPROP_SUPER, /* isCall = */ callop)) + return false; break; case PNK_ELEM: if (!emitElemOp(pn2, callop ? JSOP_CALLELEM : JSOP_GETELEM)) return false; if (callop) { if (!emit1(JSOP_SWAP)) return false; } @@ -6866,16 +6912,20 @@ BytecodeEmitter::emitIncOrDec(ParseNode* { /* Emit lvalue-specialized code for ++/-- operators. */ ParseNode* pn2 = pn->pn_kid; switch (pn2->getKind()) { case PNK_DOT: if (!emitPropIncDec(pn)) return false; break; + case PNK_SUPERPROP: + if (!emitSuperPropIncDec(pn)) + return false; + break; case PNK_ELEM: if (!emitElemIncDec(pn)) return false; break; case PNK_SUPERELEM: if (!emitSuperElemIncDec(pn)) return false; break; @@ -7837,36 +7887,39 @@ BytecodeEmitter::emitTree(ParseNode* pn) case PNK_DELETENAME: ok = emitDeleteName(pn); break; case PNK_DELETEPROP: ok = emitDeleteProperty(pn); break; + case PNK_DELETESUPERPROP: + ok = emitDeleteSuperProperty(pn); + break; + case PNK_DELETEELEM: ok = emitDeleteElement(pn); break; case PNK_DELETESUPERELEM: ok = emitDeleteSuperElement(pn); break; case PNK_DELETEEXPR: ok = emitDeleteExpression(pn); break; case PNK_DOT: - if (pn->as<PropertyAccess>().isSuper()) { - if (!emitSuperPropOp(pn, JSOP_GETPROP_SUPER)) - return false; - } else { - if (!emitPropOp(pn, JSOP_GETPROP)) - return false; - } + ok = emitPropOp(pn, JSOP_GETPROP); + break; + + case PNK_SUPERPROP: + if (!emitSuperPropOp(pn, JSOP_GETPROP_SUPER)) + return false; break; case PNK_ELEM: ok = emitElemOp(pn, JSOP_GETELEM); break; case PNK_SUPERELEM: if (!emitSuperElemOp(pn, JSOP_GETELEM_SUPER))
--- a/js/src/frontend/BytecodeEmitter.h +++ b/js/src/frontend/BytecodeEmitter.h @@ -549,16 +549,17 @@ struct BytecodeEmitter bool emitAssignment(ParseNode* lhs, JSOp op, ParseNode* rhs); bool emitReturn(ParseNode* pn); bool emitStatement(ParseNode* pn); bool emitStatementList(ParseNode* pn, ptrdiff_t top); bool emitDeleteName(ParseNode* pn); bool emitDeleteProperty(ParseNode* pn); + bool emitDeleteSuperProperty(ParseNode* pn); bool emitDeleteElement(ParseNode* pn); bool emitDeleteSuperElement(ParseNode* pn); bool emitDeleteExpression(ParseNode* pn); // |op| must be JSOP_TYPEOF or JSOP_TYPEOFEXPR. bool emitTypeof(ParseNode* node, JSOp op); bool emitLogical(ParseNode* pn); @@ -605,16 +606,17 @@ struct BytecodeEmitter // // Please refer the comment above emitSpread for additional information about // stack convention. bool emitForOf(StmtType type, ParseNode* pn, ptrdiff_t top); 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); bool emitSuperElemIncDec(ParseNode* pn); }; } /* namespace frontend */ } /* namespace js */
--- a/js/src/frontend/FoldConstants.cpp +++ b/js/src/frontend/FoldConstants.cpp @@ -329,16 +329,17 @@ ContainsHoistedDeclaration(ExclusiveCont case PNK_CONDITIONAL: case PNK_TYPEOFNAME: case PNK_TYPEOFEXPR: case PNK_VOID: case PNK_NOT: case PNK_BITNOT: case PNK_DELETENAME: case PNK_DELETEPROP: + case PNK_DELETESUPERPROP: case PNK_DELETEELEM: case PNK_DELETESUPERELEM: case PNK_DELETEEXPR: case PNK_POS: case PNK_NEG: case PNK_PREINCREMENT: case PNK_POSTINCREMENT: case PNK_PREDECREMENT: @@ -408,16 +409,17 @@ ContainsHoistedDeclaration(ExclusiveCont case PNK_CATCH: case PNK_FORIN: case PNK_FOROF: case PNK_FORHEAD: case PNK_FRESHENBLOCK: case PNK_CLASSMETHOD: case PNK_CLASSMETHODLIST: case PNK_CLASSNAMES: + case PNK_SUPERPROP: case PNK_SUPERELEM: case PNK_NEWTARGET: case PNK_POSHOLDER: MOZ_CRASH("ContainsHoistedDeclaration should have indicated false on " "some parent node without recurring to test this node"); case PNK_GLOBALCONST: MOZ_CRASH("ContainsHoistedDeclaration is only called on nested nodes where " @@ -653,19 +655,19 @@ FoldDeleteElement(ExclusiveContext* cx, return true; } static bool FoldDeleteProperty(ExclusiveContext* cx, ParseNode* node, Parser<FullParseHandler>& parser, bool inGenexpLambda) { - MOZ_ASSERT(node->isKind(PNK_DELETEPROP)); + MOZ_ASSERT(node->isKind(PNK_DELETEPROP) || node->isKind(PNK_DELETESUPERPROP)); MOZ_ASSERT(node->isArity(PN_UNARY)); - MOZ_ASSERT(node->pn_kid->isKind(PNK_DOT)); + MOZ_ASSERT(node->pn_kid->isKind(PNK_DOT) || node->pn_kid->isKind(PNK_SUPERPROP)); ParseNode*& expr = node->pn_kid; #ifdef DEBUG ParseNodeKind oldKind = expr->getKind(); #endif if (!Fold(cx, &expr, parser, inGenexpLambda)) return false; @@ -1719,16 +1721,17 @@ Fold(ExclusiveContext* cx, ParseNode** p case PNK_DEBUGGER: case PNK_BREAK: case PNK_CONTINUE: case PNK_TEMPLATE_STRING: case PNK_THIS: 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)); return true; case PNK_TYPEOFNAME: MOZ_ASSERT(pn->isArity(PN_UNARY)); MOZ_ASSERT(pn->pn_kid->isKind(PNK_NAME)); @@ -1747,16 +1750,17 @@ Fold(ExclusiveContext* cx, ParseNode** p case PNK_DELETEEXPR: return FoldDeleteExpr(cx, pn, parser, inGenexpLambda); case PNK_DELETEELEM: case PNK_DELETESUPERELEM: return FoldDeleteElement(cx, pn, parser, inGenexpLambda); case PNK_DELETEPROP: + case PNK_DELETESUPERPROP: return FoldDeleteProperty(cx, pn, parser, inGenexpLambda); case PNK_CONDITIONAL: return FoldConditional(cx, pnp, parser, inGenexpLambda); case PNK_IF: return FoldIf(cx, pnp, parser, inGenexpLambda);
--- a/js/src/frontend/FullParseHandler.h +++ b/js/src/frontend/FullParseHandler.h @@ -70,17 +70,17 @@ class FullParseHandler JS_DECLARE_NEW_METHODS(new_, allocParseNode, inline) typedef ParseNode* Node; typedef Definition* DefinitionNode; bool isPropertyAccess(ParseNode* node) { if (node->isKind(PNK_DOT) || node->isKind(PNK_ELEM)) return true; - return node->isKind(PNK_SUPERELEM); + return node->isKind(PNK_SUPERPROP) || node->isKind(PNK_SUPERELEM); } bool isFunctionCall(ParseNode* node) { // Note: super() is a special form, *not* a function call. return node->isKind(PNK_CALL); } static bool isUnparenthesizedDestructuringPattern(ParseNode* node) { @@ -220,16 +220,18 @@ class FullParseHandler if (expr->isKind(PNK_NAME)) { expr->pn_dflags |= PND_DEOPTIMIZED; expr->setOp(JSOP_DELNAME); return newUnary(PNK_DELETENAME, JSOP_NOP, begin, expr); } 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); if (expr->isKind(PNK_SUPERELEM)) return newUnary(PNK_DELETESUPERELEM, JSOP_NOP, begin, expr); return newUnary(PNK_DELETEEXPR, JSOP_NOP, begin, expr); } @@ -339,34 +341,28 @@ class FullParseHandler return new_<ClassNode>(name, heritage, methodBlock); } ParseNode* newClassMethodList(uint32_t begin) { return new_<ListNode>(PNK_CLASSMETHODLIST, TokenPos(begin, begin + 1)); } 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); } ParseNode* newNewTarget(ParseNode* newHolder, ParseNode* targetHolder) { return new_<BinaryNode>(PNK_NEWTARGET, JSOP_NOP, newHolder, targetHolder); } 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 // singleton objects will have Object.prototype as their [[Prototype]]. setListFlag(literal, PNX_NONCONST); ParseNode* mutation = newUnary(PNK_MUTATEPROTO, JSOP_NOP, begin, expr); if (!mutation) @@ -713,21 +709,16 @@ class FullParseHandler } bool isStatementPermittedAfterReturnStatement(ParseNode *node) { ParseNodeKind kind = node->getKind(); return kind == PNK_FUNCTION || kind == PNK_VAR || kind == PNK_BREAK || kind == PNK_THROW || (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) { setBeginPosition(pn, oth->pn_pos.begin); } void setBeginPosition(ParseNode* pn, uint32_t begin) { pn->pn_pos.begin = begin; MOZ_ASSERT(pn->pn_pos.begin <= pn->pn_pos.end);
--- a/js/src/frontend/NameFunctions.cpp +++ b/js/src/frontend/NameFunctions.cpp @@ -370,16 +370,17 @@ class NameResolver case PNK_ELISION: case PNK_GENERATOR: case PNK_NUMBER: case PNK_BREAK: case PNK_CONTINUE: 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; case PNK_TYPEOFNAME: MOZ_ASSERT(cur->isArity(PN_UNARY)); MOZ_ASSERT(cur->pn_kid->isKind(PNK_NAME)); MOZ_ASSERT(!cur->pn_kid->maybeExpr()); @@ -394,16 +395,17 @@ class NameResolver // Nodes with a single non-null child requiring name resolution. case PNK_TYPEOFEXPR: case PNK_VOID: case PNK_NOT: case PNK_BITNOT: case PNK_THROW: case PNK_DELETENAME: case PNK_DELETEPROP: + case PNK_DELETESUPERPROP: case PNK_DELETEELEM: case PNK_DELETESUPERELEM: case PNK_DELETEEXPR: case PNK_NEG: case PNK_POS: case PNK_PREINCREMENT: case PNK_POSTINCREMENT: case PNK_PREDECREMENT: @@ -750,28 +752,19 @@ class NameResolver MOZ_ASSERT(catchNode->expr()->isKind(PNK_CATCH)); MOZ_ASSERT(catchNode->expr()->isArity(PN_TERNARY)); if (!resolve(catchNode->expr(), prefix)) return false; } 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; case PNK_LEXICALSCOPE: case PNK_NAME: MOZ_ASSERT(cur->isArity(PN_NAME)); if (!resolve(cur->maybeExpr(), prefix)) @@ -786,17 +779,17 @@ class NameResolver break; // Kinds that should be handled by parent node resolution. case PNK_IMPORT_SPEC: // by PNK_IMPORT_SPEC_LIST 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, PNK_DOT + case PNK_POSHOLDER: // by PNK_NEWTARGET MOZ_CRASH("should have been handled by a parent node"); case PNK_LIMIT: // invalid sentinel value MOZ_CRASH("invalid node kind"); } nparents--; return true;
--- a/js/src/frontend/ParseNode.cpp +++ b/js/src/frontend/ParseNode.cpp @@ -209,31 +209,33 @@ PushNodeChildren(ParseNode* pn, NodeStac case PNK_GENERATOR: case PNK_NUMBER: case PNK_BREAK: case PNK_CONTINUE: case PNK_DEBUGGER: 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"); MOZ_ASSERT(!pn->isDefn(), "handle non-trivial cases separately"); return PushResult::Recyclable; // Nodes with a single non-null child. case PNK_TYPEOFNAME: case PNK_TYPEOFEXPR: case PNK_VOID: case PNK_NOT: case PNK_BITNOT: case PNK_THROW: case PNK_DELETENAME: case PNK_DELETEPROP: + case PNK_DELETESUPERPROP: case PNK_DELETEELEM: case PNK_DELETESUPERELEM: case PNK_DELETEEXPR: case PNK_POS: case PNK_NEG: case PNK_PREINCREMENT: case PNK_POSTINCREMENT: case PNK_PREDECREMENT: @@ -1100,20 +1102,17 @@ NameNode::dump(int indent) if (pn_atom->hasLatin1Chars()) DumpName(pn_atom->latin1Chars(nogc), pn_atom->length()); else 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); + DumpParseTree(expr(), indent + 2); fputc(')', stderr); } return; } MOZ_ASSERT(!isUsed()); const char* name = parseNodeNames[getKind()]; if (isUsed())
--- a/js/src/frontend/ParseNode.h +++ b/js/src/frontend/ParseNode.h @@ -133,16 +133,17 @@ class PackedScopeCoordinate F(CONST) \ F(GLOBALCONST) \ F(WITH) \ F(RETURN) \ F(NEW) \ /* Delete operations. These must be sequential. */ \ F(DELETENAME) \ F(DELETEPROP) \ + F(DELETESUPERPROP) \ F(DELETEELEM) \ F(DELETESUPERELEM) \ F(DELETEEXPR) \ F(TRY) \ F(CATCH) \ F(CATCHLIST) \ F(THROW) \ F(DEBUGGER) \ @@ -170,16 +171,17 @@ class PackedScopeCoordinate F(FRESHENBLOCK) \ F(ARGSBODY) \ F(SPREAD) \ F(MUTATEPROTO) \ F(CLASS) \ F(CLASSMETHOD) \ F(CLASSMETHODLIST) \ F(CLASSNAMES) \ + F(SUPERPROP) \ F(SUPERELEM) \ F(NEWTARGET) \ F(POSHOLDER) \ \ /* Unary operators. */ \ F(TYPEOFNAME) \ F(TYPEOFEXPR) \ F(VOID) \ @@ -426,16 +428,17 @@ IsDeleteKind(ParseNodeKind kind) * PNK_POSTINCREMENT, * PNK_PREDECREMENT, * PNK_POSTDECREMENT * PNK_NEW list pn_head: list of ctor, arg1, arg2, ... argN * pn_count: 1 + N (where N is number of args) * 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 * overall delete evaluates to true; can't be a kind * for a more-specific PNK_DELETE* unless constant * folding (or a similar parse tree manipulation) has * occurred * PNK_DOT name pn_expr: MEMBER expr to left of . @@ -1316,21 +1319,16 @@ class PropertyAccess : public ParseNode ParseNode& expression() const { return *pn_u.name.expr; } 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 { public: PropertyByValue(ParseNode* lhs, ParseNode* propExpr, uint32_t begin, uint32_t end) : ParseNode(PNK_ELEM, JSOP_NOP, PN_BINARY, TokenPos(begin, end)) { @@ -1444,16 +1442,32 @@ struct ClassNode : public TernaryNode { return list; } ObjectBox* scopeObject() const { MOZ_ASSERT(pn_kid3->is<LexicalScopeNode>()); return pn_kid3->pn_objbox; } }; +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) { } static bool test(const ParseNode& node) { bool match = node.isKind(PNK_SUPERELEM); MOZ_ASSERT_IF(match, node.isArity(PN_UNARY));
--- a/js/src/frontend/Parser.cpp +++ b/js/src/frontend/Parser.cpp @@ -4960,16 +4960,17 @@ Parser<FullParseHandler>::isValidForStat { if (isForDecl) return pn1->pn_count < 2 && !pn1->isKind(PNK_CONST); switch (pn1->getKind()) { case PNK_ARRAY: case PNK_CALL: case PNK_DOT: + case PNK_SUPERPROP: case PNK_ELEM: case PNK_SUPERELEM: case PNK_NAME: case PNK_OBJECT: return true; default: return false; @@ -8244,16 +8245,17 @@ Parser<ParseHandler>::memberExpr(YieldHa InvokedPrediction invoked) { MOZ_ASSERT(tokenStream.isCurrentTokenType(tt)); Node lhs; JS_CHECK_RECURSION(context, return null()); + bool isSuper = false; uint32_t superBegin = pos().begin; /* Check for new expression first. */ if (tt == TOK_NEW) { uint32_t newBegin = pos().begin; // Make sure this wasn't a |new.target| in disguise. Node newTarget; if (!tryNewTarget(newTarget)) @@ -8280,73 +8282,76 @@ Parser<ParseHandler>::memberExpr(YieldHa bool isSpread = false; if (!argumentList(yieldHandling, lhs, &isSpread)) return null(); if (isSpread) handler.setOp(lhs, JSOP_SPREADNEW); } } } else if (tt == TOK_SUPER) { - lhs = handler.newSuperBase(pos(), context); - if (!lhs) - return null(); + lhs = null(); + isSuper = true; } 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(); if (tt == TOK_EOF) break; Node nextMember; if (tt == TOK_DOT) { if (!tokenStream.getToken(&tt, TokenStream::KeywordIsName)) return null(); if (tt == TOK_NAME) { PropertyName* field = tokenStream.currentName(); - if (handler.isSuperBase(lhs, context) && !checkAndMarkSuperScope()) { - report(ParseError, false, null(), JSMSG_BAD_SUPERPROP, "property"); - return null(); + 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); } - nextMember = handler.newPropertyAccess(lhs, field, pos().end); if (!nextMember) return null(); } else { report(ParseError, false, null(), JSMSG_NAME_AFTER_DOT); return null(); } } else if (tt == TOK_LB) { Node propExpr = expr(InAllowed, yieldHandling); if (!propExpr) return null(); MUST_MATCH_TOKEN(TOK_RB, JSMSG_BRACKET_IN_INDEX); - if (handler.isSuperBase(lhs, context)) { + if (isSuper) { + isSuper = false; if (!checkAndMarkSuperScope()) { report(ParseError, false, null(), JSMSG_BAD_SUPERPROP, "member"); return null(); } nextMember = handler.newSuperElement(propExpr, TokenPos(superBegin, pos().end)); } else { nextMember = handler.newPropertyByValue(lhs, propExpr, pos().end); } if (!nextMember) return null(); } else if ((allowCallSyntax && tt == TOK_LP) || tt == TOK_TEMPLATE_HEAD || tt == TOK_NO_SUBS_TEMPLATE) { - if (handler.isSuperBase(lhs, context)) { + if (isSuper) { // For now... report(ParseError, false, null(), JSMSG_BAD_SUPER); return null(); } nextMember = tt == TOK_LP ? handler.newCall() : handler.newTaggedTemplate(); if (!nextMember) return null(); @@ -8400,26 +8405,28 @@ Parser<ParseHandler>::memberExpr(YieldHa op = JSOP_SPREADCALL; } } else { if (!taggedTemplate(yieldHandling, nextMember, tt)) return null(); } 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 (handler.isSuperBase(lhs, context)) { + if (isSuper) { report(ParseError, false, null(), JSMSG_BAD_SUPER); return null(); } return lhs; } template <typename ParseHandler>
--- a/js/src/frontend/SyntaxParseHandler.h +++ b/js/src/frontend/SyntaxParseHandler.h @@ -42,16 +42,17 @@ class SyntaxParseHandler NodeGetProp, NodeStringExprStatement, NodeReturn, NodeHoistableDeclaration, NodeBreak, NodeThrow, NodeEmptyStatement, + NodeSuperProperty, NodeSuperElement, // This is needed for proper assignment-target handling. ES6 formally // requires function calls *not* pass IsValidSimpleAssignmentTarget, // but at last check there were still sites with |f() = 5| and similar // in code not actually executed (or at least not executed enough to be // noticed). NodeFunctionCall, @@ -126,27 +127,23 @@ class SyntaxParseHandler // equality checks. (Think |if (x = y)| versus |if (x == y)|.) Thus // we need this to treat |if (x = y)| as a possible typo and // |if ((x = y))| as a deliberate assignment within a condition. // // (Technically this isn't needed, as these are *only* extraWarnings // 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, - - // This node is necessary to determine if the LHS of a property access is - // super related. - NodeSuperBase + NodeUnparenthesizedAssignment }; typedef Definition::Kind DefinitionNode; bool isPropertyAccess(Node node) { return node == NodeDottedProperty || node == NodeElement || - node == NodeSuperElement; + node == NodeSuperProperty || node == NodeSuperElement; } bool isFunctionCall(Node node) { // Note: super() is a special form, *not* a function call. return node == NodeFunctionCall; } static bool isUnparenthesizedDestructuringPattern(Node node) { @@ -272,22 +269,25 @@ class SyntaxParseHandler void addArrayElement(Node literal, Node element) { } Node newCall() { return NodeFunctionCall; } Node newTaggedTemplate() { return NodeGeneric; } 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; } bool addShorthand(Node literal, Node name, Node expr) { return true; } bool addObjectMethodDefinition(Node literal, Node name, Node fn, JSOp op) { return true; } bool addClassMethodDefinition(Node literal, Node name, Node fn, JSOp op, bool isStatic) { return true; } Node newYieldExpression(uint32_t begin, Node value, Node gen) { return NodeUnparenthesizedYieldExpr; } Node newYieldStarExpression(uint32_t begin, Node value, Node gen) { return NodeGeneric; } @@ -432,22 +432,16 @@ class SyntaxParseHandler return node == NodeReturn; } bool isStatementPermittedAfterReturnStatement(Node pn) { return pn == NodeHoistableDeclaration || pn == NodeBreak || pn == NodeThrow || 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) {} void setListFlag(Node pn, unsigned flag) {} MOZ_WARN_UNUSED_RESULT Node parenthesize(Node node) { // A number of nodes have different behavior upon parenthesization, but // only in some circumstances. Convert these nodes to special // parenthesized forms.
--- a/js/src/jsast.tbl +++ b/js/src/jsast.tbl @@ -34,17 +34,16 @@ ASTDEF(AST_ARRAY_EXPR, "Array ASTDEF(AST_SPREAD_EXPR, "SpreadExpression", "spreadExpression") ASTDEF(AST_OBJECT_EXPR, "ObjectExpression", "objectExpression") ASTDEF(AST_THIS_EXPR, "ThisExpression", "thisExpression") ASTDEF(AST_COMP_EXPR, "ComprehensionExpression", "comprehensionExpression") ASTDEF(AST_GENERATOR_EXPR, "GeneratorExpression", "generatorExpression") 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") ASTDEF(AST_EXPR_STMT, "ExpressionStatement", "expressionStatement") ASTDEF(AST_LAB_STMT, "LabeledStatement", "labeledStatement") ASTDEF(AST_IF_STMT, "IfStatement", "ifStatement") ASTDEF(AST_SWITCH_STMT, "SwitchStatement", "switchStatement") ASTDEF(AST_WHILE_STMT, "WhileStatement", "whileStatement")
--- a/js/src/tests/js1_8_5/reflect-parse/PatternBuilders.js +++ b/js/src/tests/js1_8_5/reflect-parse/PatternBuilders.js @@ -119,17 +119,17 @@ function catchClause(id, guard, body) { function tryStmt(body, guarded, unguarded, fin) { return Pattern({ type: "TryStatement", block: body, guardedHandlers: guarded, handler: unguarded, finalizer: fin }); } function letStmt(head, body) { return Pattern({ type: "LetStatement", head: head, body: body }); } function superProp(id) { - return dotExpr(Pattern({ type: "Super" }), id); + return dotExpr(ident("super"), id); } function superElem(id) { return memExpr(ident("super"), id); } function classStmt(id, heritage, body) { return Pattern({ type: "ClassStatement", id: id,