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)
Core
JavaScript Engine
Tracking
()
RESOLVED
FIXED
mozilla43
Tracking | Status | |
---|---|---|
firefox43 | --- | fixed |
People
(Reporter: efaust, Assigned: efaust)
References
(Blocks 1 open bug)
Details
Attachments
(4 files)
2.65 KB,
patch
|
Waldo
:
review+
|
Details | Diff | Splinter Review |
21.23 KB,
patch
|
Waldo
:
review+
|
Details | Diff | Splinter Review |
46.98 KB,
patch
|
Waldo
:
review+
|
Details | Diff | Splinter Review |
38.30 KB,
patch
|
Waldo
:
review+
|
Details | Diff | Splinter Review |
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.
Updated•9 years ago
|
Assignee | ||
Comment 1•9 years ago
|
||
Assignee: nobody → efaustbmo
Status: NEW → ASSIGNED
Attachment #8635573 -
Flags: review?(jwalden+bmo)
Assignee | ||
Comment 2•9 years ago
|
||
Attachment #8635574 -
Flags: review?(jwalden+bmo)
Assignee | ||
Comment 3•9 years ago
|
||
Attachment #8635575 -
Flags: review?(jwalden+bmo)
Assignee | ||
Comment 4•9 years ago
|
||
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)
Updated•9 years ago
|
Attachment #8635573 -
Flags: review?(jwalden+bmo) → review+
Comment 5•9 years ago
|
||
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 6•9 years ago
|
||
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 7•9 years ago
|
||
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+
I had to back these out in https://hg.mozilla.org/integration/mozilla-inbound/rev/c77c5698e859 for apparently breaking reftests:
https://treeherder.mozilla.org/logviewer.html#?job_id=13628594&repo=mozilla-inbound
Flags: needinfo?(efaustbmo)
Comment 10•9 years ago
|
||
Comment 11•9 years ago
|
||
Busted spidermonkey tests. Going to back this out.
Comment 12•9 years ago
|
||
Comment 13•9 years ago
|
||
Assignee | ||
Comment 14•9 years ago
|
||
Third time seems to have been the charm. Clearing ni?
Flags: needinfo?(efaustbmo)
Comment 15•9 years ago
|
||
https://hg.mozilla.org/mozilla-central/rev/fe5cc04f2339
https://hg.mozilla.org/mozilla-central/rev/7f5f48b58d76
https://hg.mozilla.org/mozilla-central/rev/1ab28f333e8a
https://hg.mozilla.org/mozilla-central/rev/333862eb2aa1
Status: ASSIGNED → RESOLVED
Closed: 9 years ago
status-firefox43:
--- → fixed
Resolution: --- → FIXED
Target Milestone: --- → mozilla43
You need to log in
before you can comment on or make changes to this bug.
Description
•