Closed Bug 1168992 Opened 10 years ago Closed 9 years ago

Make meta property lookups (super.prop, super[elem], new.target) compliant with estree spec in Reflect.parse

Categories

(Core :: JavaScript Engine, defect)

defect
Not set
normal

Tracking

()

RESOLVED FIXED
mozilla43
Tracking Status
firefox43 --- fixed

People

(Reporter: efaust, Assigned: efaust)

References

(Blocks 1 open bug)

Details

Attachments

(4 files)

Neither the superprop stuff, nor the newtarget work that is to land in bug 1141865 is Reflect.parse spec compliant. We should follow up on this and fix it.
Blocks: 1141863
Blocks: 1173387
No longer blocks: 1141863
Assignee: nobody → efaustbmo
Status: NEW → ASSIGNED
Attachment #8635573 - Flags: review?(jwalden+bmo)
Attachment #8635574 - Flags: review?(jwalden+bmo)
Attachment #8635575 - Flags: review?(jwalden+bmo)
Both this and part 3 are larger than they strictly "need" to be. They both attempt to remove the PNK_SUPER* Nodes altogether, and integrate that functionality into the existing PNK_DOT and PNK_ELEM. It's just cleaner this way.
Attachment #8635578 - Flags: review?(jwalden+bmo)
Attachment #8635573 - Flags: review?(jwalden+bmo) → review+
Comment on attachment 8635574 [details] [diff] [review] Part 2: Fix new.target reflection Review of attachment 8635574 [details] [diff] [review]: ----------------------------------------------------------------- ::: js/src/frontend/BytecodeEmitter.cpp @@ +7991,5 @@ > return false; > break; > > + case PNK_POSHOLDER: > + MOZ_CRASH("Should never try to emit PNK_POSHOLDER"); MOZ_ASSERT_UNREACHABLE ::: js/src/frontend/Parser.cpp @@ +8759,5 @@ > } > > if (!checkAllowedNestedSyntax(SharedContext::AllowedSyntax::NewTarget)) { > + reportWithOffset(ParseError, false, handler.getPosition(newHolder).begin, > + JSMSG_BAD_NEWTARGET); SyntaxParseHandler::getPosition doesn't work the way you want it to work -- it just returns the current token's position. You want to save the |uint32_t begin| when you create |newHolder| and pass that directly.
Attachment #8635574 - Flags: review?(jwalden+bmo) → review+
Comment on attachment 8635575 [details] [diff] [review] Part 3: Fix super.prop reflection Review of attachment 8635575 [details] [diff] [review]: ----------------------------------------------------------------- ::: js/src/frontend/BytecodeEmitter.cpp @@ +2653,5 @@ > > + if (isSuper) { > + if (!emitSuperPropLHS()) // THIS OBJ > + return false; > + if (!emit1(JSOP_DUP2)) // THIS OJB THIS OBJ OBJ @@ +4345,5 @@ > + offset += 2; > + } else { > + if (!emitTree(lhs->expr())) > + return false; > + offset++; Possibly += 1 for symmetry with above. @@ +4510,5 @@ > case PNK_DOT: > { > + JSOp setOp = lhs->as<PropertyAccess>().isSuper() ? > + sc->strict() ? JSOP_STRICTSETPROP_SUPER : JSOP_SETPROP_SUPER : > + sc->strict() ? JSOP_STRICTSETPROP : JSOP_SETPROP; Uh, this nesting is weird. Parenthesize the two arms of the outermost ternary, or something. ::: js/src/frontend/FullParseHandler.h @@ +353,5 @@ > 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); Add ParseNode* newSuperBase(const TokenPos& pos, ExclusiveContext* cx) { ParseNode* node = new_<NullaryNode>(PNK_POSHOLDER, pos); #ifdef DEBUG // Set the atom so that ParseHandler::isSuperBase can assert its value. if (node) node->pn_atom = cx->names().super; #endif return node; } @@ +706,5 @@ > > + bool isSuperBase(ParseNode* node) { > + // Even though POSHOLDER is used in other places. It's unique enough to > + // answer this question where we care. > + return node->isKind(PNK_POSHOLDER); Make this instead: bool isSuperBase(ParseNode* node, ExclusiveContext* cx) { bool isPosHolder = node->isKind(PNK_POSHOLDER); MOZ_ASSERT_IF(isHolder, node->pn_atom == cx->names().super); return isPosHolder; } with the same comment, but add a bit about verifying the atom as a double-check of that. ::: js/src/frontend/NameFunctions.cpp @@ +755,5 @@ > > + case PNK_DOT: > + // Super prop nodes do not have a meaningful LHS > + if (cur->as<PropertyAccess>().isSuper()) > + break; Don't do fallthrough if these kinds are that different, IMO. case PNK_DOT: MOZ_ASSERT(cur->isArity(PN_NAME)); if (cur->as<PropertyAccess>().hasSuperBase()) break; if (!resolve(cur->expr(), prefix)) return false; break; ::: js/src/frontend/ParseNode.cpp @@ +1092,4 @@ > fputc(' ', stderr); > DumpParseTree(expr(), indent + 2); > fputc(')', stderr); > } Don't you want if (as<PropertyAccess>().hasSuperBase()) fprintf(stderr, "super"); else DumpParseTree(expr(), indent + 2); instead of not printing the "expression" part at all? Looks like right now this would print (. key for super.key: imbalanced and weird. ::: js/src/frontend/ParseNode.h @@ +1301,5 @@ > PropertyName& name() const { > return *pn_u.name.atom->asPropertyName(); > } > + > + bool isSuper() const { hasSuperBase, please. And double-check the pn_atom as well. ::: js/src/frontend/Parser.cpp @@ +8002,5 @@ > handler.setOp(lhs, JSOP_SPREADNEW); > } > } > } else if (tt == TOK_SUPER) { > + lhs = handler.newPosHolder(pos()); newSuperBase ::: js/src/frontend/SyntaxParseHandler.h @@ +135,5 @@ > + > + // Currently used in both property accesses involving super, and new.target > + // This node is necessary to determine if the LHS of a property access is > + // super related. > + NodePosHolder This is only used for super-bases, so rename this to NodeSuperBase. @@ +280,5 @@ > Node newSuperElement(Node expr, const TokenPos& pos) { > return NodeSuperElement; > } > Node newNewTarget(Node newHolder, Node targetHolder) { return NodeGeneric; } > + Node newPosHolder(const TokenPos& pos) { return NodePosHolder; } Use newSuperBase(const TokenPos&, ExclusiveContext* cx) instead of newPosHolder for super. @@ +438,5 @@ > > + bool isSuperBase(Node pn) { > + // While NodePosHolder is used in other places than just as super-base, > + // it is unique enough for our purposes. > + return pn == NodePosHolder; Use |node| instead of |pn|, and add the |ExclusiveContext* cx| argument. And the comment can die at this point, too. ::: js/src/jsreflect.cpp @@ +3017,5 @@ > { > MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_expr->pn_pos)); > > RootedValue expr(cx), id(cx); > RootedAtom pnAtom(cx, pn->pn_atom); Rename this to |key| or |propname| or something, and move the id/key/propname definitions down next to the return statement.
Attachment #8635575 - Flags: review?(jwalden+bmo) → review+
Comment on attachment 8635578 [details] [diff] [review] Part 4: Fix super[elem] reflection Review of attachment 8635578 [details] [diff] [review]: ----------------------------------------------------------------- ::: js/src/frontend/BytecodeEmitter.cpp @@ +2749,5 @@ > > bool > BytecodeEmitter::emitSuperElemOperands(ParseNode* pn, SuperElemOptions opts) > { > + MOZ_ASSERT(pn->isKind(PNK_ELEM) && pn->as<PropertyByValue>().isSuper()); Two separate assertions, so if you hit one/the other you know exactly *which* of these two conditions was wrong. @@ +2888,5 @@ > + return false; > + } > + > + JSOp setOp = isSuper ? sc->strict() ? JSOP_STRICTSETELEM_SUPER : JSOP_SETELEM_SUPER > + : sc->strict() ? JSOP_STRICTSETELEM : JSOP_SETELEM; Parenthesize, and align ?: in the outer thing underneath the "i" in isSuper. @@ +4494,5 @@ > case PNK_ELEM: > { > + JSOp setOp = lhs->as<PropertyByValue>().isSuper() ? > + sc->strict() ? JSOP_STRICTSETELEM_SUPER : JSOP_SETELEM_SUPER : > + sc->strict() ? JSOP_STRICTSETELEM : JSOP_SETELEM; More alignment/parentheses stuff. ::: js/src/frontend/NameFunctions.cpp @@ +458,5 @@ > > + case PNK_ELEM: > + MOZ_ASSERT(cur->isArity(PN_BINARY)); > + if (!cur->as<PropertyByValue>().isSuper() && !resolve(cur->pn_left, prefix)) > + return false; if (!cur...) { if (!resolve(...)) return false; } is the style preferred for when you have a condition guarding whether a fallible thing happens. ::: js/src/frontend/ParseNode.h @@ +1323,5 @@ > + } > + > + bool isSuper() const { > + // Like PropertyAccess above, PNK_POSHOLDER is "good enough". > + return pn_left->isKind(PNK_POSHOLDER); hasSuperBase, with the same sort of changes from the previous patch. ::: js/src/jsreflect.cpp @@ +3035,5 @@ > { > 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); Move right's definition down by the return.
Attachment #8635578 - Flags: review?(jwalden+bmo) → review+
Busted spidermonkey tests. Going to back this out.
Third time seems to have been the charm. Clearing ni?
Flags: needinfo?(efaustbmo)
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: