Bug 1611777 - Part 4: super can't occur on the left-hand side of an optional chain. r=yulia

Moves the `isSuper()` method from the base class to the (non-optional) derived
classes, because `super?.x` isn't valid syntax, so it's confusing to be able to
ask if an optional property access is applied on `super`.

The next part will further simplify `BytecodeEmitter::emitDelete{Element,Property}InOptChain()`.

Differential Revision: https://phabricator.services.mozilla.com/D61151

--HG--
extra : moz-landing-system : lando
This commit is contained in:
André Bargull 2020-01-29 16:24:12 +00:00
parent f06ccdae60
commit 15e84c1e7a
4 changed files with 36 additions and 24 deletions

View File

@ -2883,11 +2883,14 @@ bool ASTSerializer::expression(ParseNode* pn, MutableHandleValue dst) {
PropertyAccessBase* prop = &pn->as<PropertyAccessBase>();
MOZ_ASSERT(prop->pn_pos.encloses(prop->expression().pn_pos));
bool isSuper =
prop->is<PropertyAccess>() && prop->as<PropertyAccess>().isSuper();
RootedValue expr(cx);
RootedValue propname(cx);
RootedAtom pnAtom(cx, prop->key().atom());
if (prop->isSuper()) {
if (isSuper) {
if (!builder.super(&prop->expression().pn_pos, &expr)) {
return false;
}
@ -2910,9 +2913,12 @@ bool ASTSerializer::expression(ParseNode* pn, MutableHandleValue dst) {
MOZ_ASSERT(elem->pn_pos.encloses(elem->expression().pn_pos));
MOZ_ASSERT(elem->pn_pos.encloses(elem->key().pn_pos));
bool isSuper =
elem->is<PropertyByValue>() && elem->as<PropertyByValue>().isSuper();
RootedValue expr(cx), key(cx);
if (elem->isSuper()) {
if (isSuper) {
if (!builder.super(&elem->expression().pn_pos, &expr)) {
return false;
}

View File

@ -6806,11 +6806,13 @@ bool BytecodeEmitter::emitDeleteOptionalChain(UnaryNode* deleteNode) {
bool BytecodeEmitter::emitDeletePropertyInOptChain(PropertyAccessBase* propExpr,
OptionalEmitter& oe) {
PropOpEmitter poe(this, PropOpEmitter::Kind::Delete,
propExpr->isSuper() ? PropOpEmitter::ObjKind::Super
: PropOpEmitter::ObjKind::Other);
bool isSuper = propExpr->is<PropertyAccess>() &&
propExpr->as<PropertyAccess>().isSuper();
PropOpEmitter poe(
this, PropOpEmitter::Kind::Delete,
isSuper ? PropOpEmitter::ObjKind::Super : PropOpEmitter::ObjKind::Other);
if (propExpr->isSuper()) {
if (isSuper) {
// The expression |delete super.foo;| has to evaluate |super.foo|,
// which could throw if |this| hasn't yet been set by a |super(...)|
// call or the super-base is not an object, before throwing a
@ -6853,9 +6855,11 @@ bool BytecodeEmitter::emitDeletePropertyInOptChain(PropertyAccessBase* propExpr,
bool BytecodeEmitter::emitDeleteElementInOptChain(PropertyByValueBase* elemExpr,
OptionalEmitter& oe) {
ElemOpEmitter eoe(this, ElemOpEmitter::Kind::Delete,
elemExpr->isSuper() ? ElemOpEmitter::ObjKind::Super
: ElemOpEmitter::ObjKind::Other);
bool isSuper = elemExpr->is<PropertyByValue>() &&
elemExpr->as<PropertyByValue>().isSuper();
ElemOpEmitter eoe(
this, ElemOpEmitter::Kind::Delete,
isSuper ? ElemOpEmitter::ObjKind::Super : ElemOpEmitter::ObjKind::Other);
if (!eoe.prepareForObj()) {
// [stack]
@ -7205,7 +7209,7 @@ bool BytecodeEmitter::emitOptionalCalleeAndThis(ParseNode* callee,
case ParseNodeKind::OptionalDotExpr: {
MOZ_ASSERT(emitterMode != BytecodeEmitter::SelfHosting);
OptionalPropertyAccess* prop = &callee->as<OptionalPropertyAccess>();
bool isSuper = prop->isSuper();
bool isSuper = false;
PropOpEmitter& poe = cone.prepareForPropCallee(isSuper);
if (!emitOptionalDotExpression(prop, poe, isSuper, oe)) {
@ -7229,7 +7233,8 @@ bool BytecodeEmitter::emitOptionalCalleeAndThis(ParseNode* callee,
case ParseNodeKind::OptionalElemExpr: {
OptionalPropertyByValue* elem = &callee->as<OptionalPropertyByValue>();
bool isSuper = elem->isSuper();
bool isSuper = false;
ElemOpEmitter& eoe = cone.prepareForElemCallee(isSuper);
if (!emitOptionalElemExpression(elem, eoe, isSuper, oe)) {
// [stack] CALLEE THIS
@ -7240,6 +7245,7 @@ bool BytecodeEmitter::emitOptionalCalleeAndThis(ParseNode* callee,
case ParseNodeKind::ElemExpr: {
PropertyByValue* elem = &callee->as<PropertyByValue>();
bool isSuper = elem->isSuper();
ElemOpEmitter& eoe = cone.prepareForElemCallee(isSuper);
if (!emitOptionalElemExpression(elem, eoe, isSuper, oe)) {
// [stack] CALLEE THIS
@ -7722,10 +7728,9 @@ bool BytecodeEmitter::emitOptionalTree(ParseNode* pn, OptionalEmitter& oe) {
switch (kind) {
case ParseNodeKind::OptionalDotExpr: {
OptionalPropertyAccess* prop = &pn->as<OptionalPropertyAccess>();
bool isSuper = prop->isSuper();
bool isSuper = false;
PropOpEmitter poe(this, PropOpEmitter::Kind::Get,
isSuper ? PropOpEmitter::ObjKind::Super
: PropOpEmitter::ObjKind::Other);
PropOpEmitter::ObjKind::Other);
if (!emitOptionalDotExpression(prop, poe, isSuper, oe)) {
return false;
}
@ -7745,10 +7750,9 @@ bool BytecodeEmitter::emitOptionalTree(ParseNode* pn, OptionalEmitter& oe) {
case ParseNodeKind::OptionalElemExpr: {
OptionalPropertyByValue* elem = &pn->as<OptionalPropertyByValue>();
bool isSuper = elem->isSuper();
bool isSuper = false;
ElemOpEmitter eoe(this, ElemOpEmitter::Kind::Get,
isSuper ? ElemOpEmitter::ObjKind::Super
: ElemOpEmitter::ObjKind::Other);
ElemOpEmitter::ObjKind::Other);
if (!emitOptionalElemExpression(elem, eoe, isSuper, oe)) {
return false;

View File

@ -1944,11 +1944,6 @@ class PropertyAccessBase : public BinaryNode {
PropertyName& name() const {
return *right()->as<NameNode>().atom()->asPropertyName();
}
bool isSuper() const {
// ParseNodeKind::SuperBase cannot result from any expression syntax.
return expression().isKind(ParseNodeKind::SuperBase);
}
};
class PropertyAccess : public PropertyAccessBase {
@ -1964,6 +1959,11 @@ class PropertyAccess : public PropertyAccessBase {
MOZ_ASSERT_IF(match, node.is<PropertyAccessBase>());
return match;
}
bool isSuper() const {
// ParseNodeKind::SuperBase cannot result from any expression syntax.
return expression().isKind(ParseNodeKind::SuperBase);
}
};
class OptionalPropertyAccess : public PropertyAccessBase {
@ -1999,8 +1999,6 @@ class PropertyByValueBase : public BinaryNode {
ParseNode& expression() const { return *left(); }
ParseNode& key() const { return *right(); }
bool isSuper() const { return left()->isKind(ParseNodeKind::SuperBase); }
};
class PropertyByValue : public PropertyByValueBase {
@ -2015,6 +2013,8 @@ class PropertyByValue : public PropertyByValueBase {
MOZ_ASSERT_IF(match, node.is<PropertyByValueBase>());
return match;
}
bool isSuper() const { return left()->isKind(ParseNodeKind::SuperBase); }
};
class OptionalPropertyByValue : public PropertyByValueBase {

View File

@ -9445,6 +9445,7 @@ GeneralParser<ParseHandler, Unit>::memberPropertyAccess(
}
if (optionalKind == OptionalKind::Optional) {
MOZ_ASSERT(!handler_.isSuperBase(lhs));
return handler_.newOptionalPropertyAccess(lhs, name);
}
return handler_.newPropertyAccess(lhs, name);
@ -9469,6 +9470,7 @@ typename ParseHandler::Node GeneralParser<ParseHandler, Unit>::memberElemAccess(
return null();
}
if (optionalKind == OptionalKind::Optional) {
MOZ_ASSERT(!handler_.isSuperBase(lhs));
return handler_.newOptionalPropertyByValue(lhs, propExpr, pos().end);
}
return handler_.newPropertyByValue(lhs, propExpr, pos().end);