mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-10-23 07:37:29 +09:00
Issue #2142 - Use JSOP_INITPROP for field initializers
We don't want to call setters for field initialization. Based-on: m-c 1535471, 1547035
This commit is contained in:
parent
447261cf87
commit
849ab4417c
11 changed files with 89 additions and 40 deletions
|
|
@ -2770,7 +2770,7 @@ ASTSerializer::classField(ClassField* classField, MutableHandleValue dst)
|
||||||
->head()->as<LexicalScopeNode>()
|
->head()->as<LexicalScopeNode>()
|
||||||
.scopeBody()->as<ListNode>()
|
.scopeBody()->as<ListNode>()
|
||||||
.head()->as<UnaryNode>()
|
.head()->as<UnaryNode>()
|
||||||
.kid()->as<AssignmentNode>()
|
.kid()->as<BinaryNode>()
|
||||||
.right();
|
.right();
|
||||||
// RawUndefinedExpr is the node we use for "there is no initializer". If one
|
// RawUndefinedExpr is the node we use for "there is no initializer". If one
|
||||||
// writes, literally, `x = undefined;`, it will not be a RawUndefinedExpr
|
// writes, literally, `x = undefined;`, it will not be a RawUndefinedExpr
|
||||||
|
|
|
||||||
|
|
@ -1214,6 +1214,10 @@ BytecodeEmitter::checkSideEffects(ParseNode* pn, bool* answer)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
// Binary cases with obvious side effects.
|
// Binary cases with obvious side effects.
|
||||||
|
case PNK_INITPROP:
|
||||||
|
*answer = true;
|
||||||
|
return true;
|
||||||
|
|
||||||
case PNK_ASSIGN:
|
case PNK_ASSIGN:
|
||||||
case PNK_ADDASSIGN:
|
case PNK_ADDASSIGN:
|
||||||
case PNK_SUBASSIGN:
|
case PNK_SUBASSIGN:
|
||||||
|
|
@ -3697,9 +3701,14 @@ EmitAssignmentRhs(BytecodeEmitter* bce, ParseNode* rhs, uint8_t offset)
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
BytecodeEmitter::emitAssignment(ParseNode* lhs, JSOp compoundOp, ParseNode* rhs)
|
BytecodeEmitter::emitAssignmentOrInit(ParseNodeKind kind, JSOp compoundOp,
|
||||||
|
ParseNode* lhs, ParseNode* rhs)
|
||||||
{
|
{
|
||||||
bool isCompound = compoundOp != JSOP_NOP;
|
bool isCompound = compoundOp != JSOP_NOP;
|
||||||
|
bool isInit = kind == PNK_INITPROP;
|
||||||
|
|
||||||
|
MOZ_ASSERT_IF(isInit, lhs->isKind(PNK_DOT) ||
|
||||||
|
lhs->isKind(PNK_ELEM));
|
||||||
|
|
||||||
// Name assignments are handled separately because choosing ops and when
|
// Name assignments are handled separately because choosing ops and when
|
||||||
// to emit BINDNAME is involved and should avoid duplication.
|
// to emit BINDNAME is involved and should avoid duplication.
|
||||||
|
|
@ -3754,7 +3763,8 @@ BytecodeEmitter::emitAssignment(ParseNode* lhs, JSOp compoundOp, ParseNode* rhs)
|
||||||
poe.emplace(this,
|
poe.emplace(this,
|
||||||
isCompound
|
isCompound
|
||||||
? PropOpEmitter::Kind::CompoundAssignment
|
? PropOpEmitter::Kind::CompoundAssignment
|
||||||
: PropOpEmitter::Kind::SimpleAssignment,
|
: isInit ? PropOpEmitter::Kind::PropInit
|
||||||
|
: PropOpEmitter::Kind::SimpleAssignment,
|
||||||
isSuper
|
isSuper
|
||||||
? PropOpEmitter::ObjKind::Super
|
? PropOpEmitter::ObjKind::Super
|
||||||
: PropOpEmitter::ObjKind::Other);
|
: PropOpEmitter::ObjKind::Other);
|
||||||
|
|
@ -3781,7 +3791,8 @@ BytecodeEmitter::emitAssignment(ParseNode* lhs, JSOp compoundOp, ParseNode* rhs)
|
||||||
eoe.emplace(this,
|
eoe.emplace(this,
|
||||||
isCompound
|
isCompound
|
||||||
? ElemOpEmitter::Kind::CompoundAssignment
|
? ElemOpEmitter::Kind::CompoundAssignment
|
||||||
: ElemOpEmitter::Kind::SimpleAssignment,
|
: isInit ? ElemOpEmitter::Kind::PropInit
|
||||||
|
: ElemOpEmitter::Kind::SimpleAssignment,
|
||||||
isSuper
|
isSuper
|
||||||
? ElemOpEmitter::ObjKind::Super
|
? ElemOpEmitter::ObjKind::Super
|
||||||
: ElemOpEmitter::ObjKind::Other);
|
: ElemOpEmitter::ObjKind::Other);
|
||||||
|
|
@ -4714,7 +4725,7 @@ BytecodeEmitter::emitInitializeForInOrOfTarget(TernaryNode* forHead)
|
||||||
// initialization is just assigning the iteration value to a target
|
// initialization is just assigning the iteration value to a target
|
||||||
// expression.
|
// expression.
|
||||||
if (!parser->handler.isDeclarationList(target))
|
if (!parser->handler.isDeclarationList(target))
|
||||||
return emitAssignment(target, JSOP_NOP, nullptr); // ... ITERVAL
|
return emitAssignmentOrInit(PNK_ASSIGN, JSOP_NOP, target, nullptr); // ... ITERVAL
|
||||||
|
|
||||||
// Otherwise, per-loop initialization is (possibly) declaration
|
// Otherwise, per-loop initialization is (possibly) declaration
|
||||||
// initialization. If the declaration is a lexical declaration, it must be
|
// initialization. If the declaration is a lexical declaration, it must be
|
||||||
|
|
@ -4728,8 +4739,19 @@ BytecodeEmitter::emitInitializeForInOrOfTarget(TernaryNode* forHead)
|
||||||
MOZ_ASSERT(target->isForLoopDeclaration());
|
MOZ_ASSERT(target->isForLoopDeclaration());
|
||||||
target = parser->handler.singleBindingFromDeclaration(&target->as<ListNode>());
|
target = parser->handler.singleBindingFromDeclaration(&target->as<ListNode>());
|
||||||
|
|
||||||
|
NameNode* nameNode = nullptr;
|
||||||
if (target->isKind(PNK_NAME)) {
|
if (target->isKind(PNK_NAME)) {
|
||||||
NameOpEmitter noe(this, target->name(), NameOpEmitter::Kind::Initialize);
|
nameNode = &target->as<NameNode>();
|
||||||
|
} else if (target->isKind(PNK_ASSIGN) ||
|
||||||
|
target->isKind(PNK_INITPROP)) {
|
||||||
|
BinaryNode* assignNode = &target->as<BinaryNode>();
|
||||||
|
if (assignNode->left()->is<NameNode>()) {
|
||||||
|
nameNode = &assignNode->left()->as<NameNode>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nameNode) {
|
||||||
|
NameOpEmitter noe(this, nameNode->name(), NameOpEmitter::Kind::Initialize);
|
||||||
if (!noe.prepareForRhs()) {
|
if (!noe.prepareForRhs()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -4755,7 +4777,7 @@ BytecodeEmitter::emitInitializeForInOrOfTarget(TernaryNode* forHead)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
MOZ_ASSERT(!target->isKind(PNK_ASSIGN),
|
MOZ_ASSERT(!target->isKind(PNK_ASSIGN) && !target->isKind(PNK_INITPROP),
|
||||||
"for-in/of loop destructuring declarations can't have initializers");
|
"for-in/of loop destructuring declarations can't have initializers");
|
||||||
|
|
||||||
MOZ_ASSERT(target->isKind(PNK_ARRAY) || target->isKind(PNK_OBJECT));
|
MOZ_ASSERT(target->isKind(PNK_ARRAY) || target->isKind(PNK_OBJECT));
|
||||||
|
|
@ -5396,7 +5418,7 @@ BytecodeEmitter::emitComprehensionForOf(ForNode* forNode)
|
||||||
// Notice: Comprehension for-of doesn't perform IteratorClose, since it's
|
// Notice: Comprehension for-of doesn't perform IteratorClose, since it's
|
||||||
// not in the spec.
|
// not in the spec.
|
||||||
|
|
||||||
if (!emitAssignment(loopVariableName, JSOP_NOP, nullptr)) // ITER RESULT VALUE
|
if (!emitAssignmentOrInit(PNK_ASSIGN, JSOP_NOP, loopVariableName, nullptr)) // ITER RESULT VALUE
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Remove VALUE from the stack to release it.
|
// Remove VALUE from the stack to release it.
|
||||||
|
|
@ -5533,7 +5555,7 @@ BytecodeEmitter::emitComprehensionForIn(ForNode* forNode)
|
||||||
|
|
||||||
// Emit code to assign the enumeration value to the left hand side, but
|
// Emit code to assign the enumeration value to the left hand side, but
|
||||||
// also leave it on the stack.
|
// also leave it on the stack.
|
||||||
if (!emitAssignment(forHead->kid2(), JSOP_NOP, nullptr))
|
if (!emitAssignmentOrInit(PNK_ASSIGN, JSOP_NOP, forHead->kid2(), nullptr))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
/* The stack should be balanced around the assignment opcode sequence. */
|
/* The stack should be balanced around the assignment opcode sequence. */
|
||||||
|
|
@ -8384,9 +8406,9 @@ BytecodeEmitter::emitFunctionFormalParameters(ListNode* paramsBody)
|
||||||
for (ParseNode* arg = paramsBody->head(); arg != funBody; arg = arg->pn_next) {
|
for (ParseNode* arg = paramsBody->head(); arg != funBody; arg = arg->pn_next) {
|
||||||
ParseNode* bindingElement = arg;
|
ParseNode* bindingElement = arg;
|
||||||
ParseNode* initializer = nullptr;
|
ParseNode* initializer = nullptr;
|
||||||
if (arg->isKind(PNK_ASSIGN)) {
|
if (arg->isKind(PNK_ASSIGN) || arg->isKind(PNK_INITPROP)) {
|
||||||
bindingElement = arg->as<AssignmentNode>().left();
|
bindingElement = arg->as<BinaryNode>().left();
|
||||||
initializer = arg->as<AssignmentNode>().right();
|
initializer = arg->as<BinaryNode>().right();
|
||||||
}
|
}
|
||||||
bool hasInitializer = !!initializer;
|
bool hasInitializer = !!initializer;
|
||||||
bool isRest = hasRest && arg->pn_next == funBody;
|
bool isRest = hasRest && arg->pn_next == funBody;
|
||||||
|
|
@ -8830,6 +8852,7 @@ BytecodeEmitter::emitTree(ParseNode* pn, ValueUsage valueUsage /* = ValueUsage::
|
||||||
return false;
|
return false;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case PNK_INITPROP:
|
||||||
case PNK_ASSIGN:
|
case PNK_ASSIGN:
|
||||||
case PNK_ADDASSIGN:
|
case PNK_ADDASSIGN:
|
||||||
case PNK_SUBASSIGN:
|
case PNK_SUBASSIGN:
|
||||||
|
|
@ -8843,8 +8866,9 @@ BytecodeEmitter::emitTree(ParseNode* pn, ValueUsage valueUsage /* = ValueUsage::
|
||||||
case PNK_DIVASSIGN:
|
case PNK_DIVASSIGN:
|
||||||
case PNK_MODASSIGN:
|
case PNK_MODASSIGN:
|
||||||
case PNK_POWASSIGN: {
|
case PNK_POWASSIGN: {
|
||||||
AssignmentNode* assignNode = &pn->as<AssignmentNode>();
|
BinaryNode* assignNode = &pn->as<BinaryNode>();
|
||||||
if (!emitAssignment(assignNode->left(), assignNode->getOp(), assignNode->right()))
|
if (!emitAssignmentOrInit(assignNode->getKind(), assignNode->getOp(),
|
||||||
|
assignNode->left(), assignNode->right()))
|
||||||
return false;
|
return false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -696,7 +696,8 @@ struct MOZ_STACK_CLASS BytecodeEmitter
|
||||||
|
|
||||||
MOZ_MUST_USE bool emitCallSiteObject(CallSiteNode* callSiteObj);
|
MOZ_MUST_USE bool emitCallSiteObject(CallSiteNode* callSiteObj);
|
||||||
MOZ_MUST_USE bool emitTemplateString(ListNode* templateString);
|
MOZ_MUST_USE bool emitTemplateString(ListNode* templateString);
|
||||||
MOZ_MUST_USE bool emitAssignment(ParseNode* lhs, JSOp compoundOp, ParseNode* rhs);
|
MOZ_MUST_USE bool emitAssignmentOrInit(ParseNodeKind kind, JSOp compoundOp,
|
||||||
|
ParseNode* lhs, ParseNode* rhs);
|
||||||
|
|
||||||
MOZ_MUST_USE bool emitReturn(UnaryNode* returnNode);
|
MOZ_MUST_USE bool emitReturn(UnaryNode* returnNode);
|
||||||
MOZ_MUST_USE bool emitStatement(UnaryNode* exprStmt);
|
MOZ_MUST_USE bool emitStatement(UnaryNode* exprStmt);
|
||||||
|
|
|
||||||
|
|
@ -132,11 +132,11 @@ ElemOpEmitter::emitGet()
|
||||||
bool
|
bool
|
||||||
ElemOpEmitter::prepareForRhs()
|
ElemOpEmitter::prepareForRhs()
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(isSimpleAssignment() || isCompoundAssignment());
|
MOZ_ASSERT(isSimpleAssignment() || isPropInit()|| isCompoundAssignment());
|
||||||
MOZ_ASSERT_IF(isSimpleAssignment(), state_ == State::Key);
|
MOZ_ASSERT_IF(isSimpleAssignment() || isPropInit(), state_ == State::Key);
|
||||||
MOZ_ASSERT_IF(isCompoundAssignment(), state_ == State::Get);
|
MOZ_ASSERT_IF(isCompoundAssignment(), state_ == State::Get);
|
||||||
|
|
||||||
if (isSimpleAssignment()) {
|
if (isSimpleAssignment() || isPropInit()) {
|
||||||
// For CompoundAssignment, SUPERBASE is already emitted by emitGet.
|
// For CompoundAssignment, SUPERBASE is already emitted by emitGet.
|
||||||
if (isSuper()) {
|
if (isSuper()) {
|
||||||
if (!bce_->emit1(JSOP_SUPERBASE)) { // THIS KEY SUPERBASE
|
if (!bce_->emit1(JSOP_SUPERBASE)) { // THIS KEY SUPERBASE
|
||||||
|
|
@ -155,7 +155,7 @@ bool
|
||||||
ElemOpEmitter::skipObjAndKeyAndRhs()
|
ElemOpEmitter::skipObjAndKeyAndRhs()
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(state_ == State::Start);
|
MOZ_ASSERT(state_ == State::Start);
|
||||||
MOZ_ASSERT(isSimpleAssignment());
|
MOZ_ASSERT(isSimpleAssignment() || isPropInit());
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
state_ = State::Rhs;
|
state_ = State::Rhs;
|
||||||
|
|
@ -203,12 +203,15 @@ ElemOpEmitter::emitDelete()
|
||||||
bool
|
bool
|
||||||
ElemOpEmitter::emitAssignment()
|
ElemOpEmitter::emitAssignment()
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(isSimpleAssignment() || isCompoundAssignment());
|
MOZ_ASSERT(isSimpleAssignment() || isPropInit() || isCompoundAssignment());
|
||||||
MOZ_ASSERT(state_ == State::Rhs);
|
MOZ_ASSERT(state_ == State::Rhs);
|
||||||
|
|
||||||
JSOp setOp = isSuper()
|
MOZ_ASSERT_IF(isPropInit(), !isSuper());
|
||||||
? bce_->sc->strict() ? JSOP_STRICTSETELEM_SUPER : JSOP_SETELEM_SUPER
|
|
||||||
: bce_->sc->strict() ? JSOP_STRICTSETELEM : JSOP_SETELEM;
|
JSOp setOp = isPropInit() ? JSOP_INITELEM
|
||||||
|
: isSuper()
|
||||||
|
? bce_->sc->strict() ? JSOP_STRICTSETELEM_SUPER : JSOP_SETELEM_SUPER
|
||||||
|
: bce_->sc->strict() ? JSOP_STRICTSETELEM : JSOP_SETELEM;
|
||||||
if (!bce_->emitElemOpBase(setOp)) { // ELEM
|
if (!bce_->emitElemOpBase(setOp)) { // ELEM
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -129,6 +129,7 @@ class MOZ_STACK_CLASS ElemOpEmitter
|
||||||
PostDecrement,
|
PostDecrement,
|
||||||
PreDecrement,
|
PreDecrement,
|
||||||
SimpleAssignment,
|
SimpleAssignment,
|
||||||
|
PropInit,
|
||||||
CompoundAssignment
|
CompoundAssignment
|
||||||
};
|
};
|
||||||
enum class ObjKind {
|
enum class ObjKind {
|
||||||
|
|
@ -176,6 +177,7 @@ class MOZ_STACK_CLASS ElemOpEmitter
|
||||||
// | +--------+ |
|
// | +--------+ |
|
||||||
// | +-------------------+
|
// | +-------------------+
|
||||||
// | [SimpleAssignment] |
|
// | [SimpleAssignment] |
|
||||||
|
// | [PropInit] |
|
||||||
// | prepareForRhs v +-----+
|
// | prepareForRhs v +-----+
|
||||||
// +--------------------->+-------------->+->| Rhs |-+
|
// +--------------------->+-------------->+->| Rhs |-+
|
||||||
// | ^ +-----+ |
|
// | ^ +-----+ |
|
||||||
|
|
@ -225,6 +227,10 @@ class MOZ_STACK_CLASS ElemOpEmitter
|
||||||
return kind_ == Kind::SimpleAssignment;
|
return kind_ == Kind::SimpleAssignment;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MOZ_MUST_USE bool isPropInit() const {
|
||||||
|
return kind_ == Kind::PropInit;
|
||||||
|
}
|
||||||
|
|
||||||
MOZ_MUST_USE bool isDelete() const {
|
MOZ_MUST_USE bool isDelete() const {
|
||||||
return kind_ == Kind::Delete;
|
return kind_ == Kind::Delete;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -351,6 +351,7 @@ ContainsHoistedDeclaration(ExclusiveContext* cx, ParseNode* node, bool* result)
|
||||||
case PNK_DIV:
|
case PNK_DIV:
|
||||||
case PNK_MOD:
|
case PNK_MOD:
|
||||||
case PNK_POW:
|
case PNK_POW:
|
||||||
|
case PNK_INITPROP:
|
||||||
case PNK_ASSIGN:
|
case PNK_ASSIGN:
|
||||||
case PNK_ADDASSIGN:
|
case PNK_ADDASSIGN:
|
||||||
case PNK_SUBASSIGN:
|
case PNK_SUBASSIGN:
|
||||||
|
|
@ -1877,6 +1878,7 @@ Fold(ExclusiveContext* cx, ParseNode** pnp, Parser<FullParseHandler>& parser, bo
|
||||||
|
|
||||||
case PNK_SWITCH:
|
case PNK_SWITCH:
|
||||||
case PNK_COLON:
|
case PNK_COLON:
|
||||||
|
case PNK_INITPROP:
|
||||||
case PNK_ASSIGN:
|
case PNK_ASSIGN:
|
||||||
case PNK_ADDASSIGN:
|
case PNK_ADDASSIGN:
|
||||||
case PNK_SUBASSIGN:
|
case PNK_SUBASSIGN:
|
||||||
|
|
|
||||||
|
|
@ -257,6 +257,7 @@ PushNodeChildren(ParseNode* pn, NodeStack* stack)
|
||||||
// Binary nodes with two non-null children.
|
// Binary nodes with two non-null children.
|
||||||
|
|
||||||
// All assignment and compound assignment nodes qualify.
|
// All assignment and compound assignment nodes qualify.
|
||||||
|
case PNK_INITPROP:
|
||||||
case PNK_ASSIGN:
|
case PNK_ASSIGN:
|
||||||
case PNK_ADDASSIGN:
|
case PNK_ADDASSIGN:
|
||||||
case PNK_SUBASSIGN:
|
case PNK_SUBASSIGN:
|
||||||
|
|
|
||||||
|
|
@ -125,6 +125,7 @@ class ObjectBox;
|
||||||
F(SUPERBASE) \
|
F(SUPERBASE) \
|
||||||
F(SUPERCALL) \
|
F(SUPERCALL) \
|
||||||
F(SETTHIS) \
|
F(SETTHIS) \
|
||||||
|
F(INITPROP) \
|
||||||
F(IMPORT_META) \
|
F(IMPORT_META) \
|
||||||
F(CALL_IMPORT) \
|
F(CALL_IMPORT) \
|
||||||
\
|
\
|
||||||
|
|
@ -170,7 +171,7 @@ class ObjectBox;
|
||||||
F(POW) \
|
F(POW) \
|
||||||
\
|
\
|
||||||
/* Assignment operators (= += -= etc.). */ \
|
/* Assignment operators (= += -= etc.). */ \
|
||||||
/* ParseNode::isAssignment assumes all these are consecutive. */ \
|
/* AssignmentNode::test assumes all these are consecutive. */ \
|
||||||
F(ASSIGN) \
|
F(ASSIGN) \
|
||||||
F(ADDASSIGN) \
|
F(ADDASSIGN) \
|
||||||
F(SUBASSIGN) \
|
F(SUBASSIGN) \
|
||||||
|
|
@ -385,7 +386,10 @@ IsTypeofKind(ParseNodeKind kind)
|
||||||
* PNK_COMMA (ListNode)
|
* PNK_COMMA (ListNode)
|
||||||
* head: list of N comma-separated exprs
|
* head: list of N comma-separated exprs
|
||||||
* count: N >= 2
|
* count: N >= 2
|
||||||
* PNK_ASSIGN (BinaryNode)
|
* PNK_INITPROP (BinaryNode)
|
||||||
|
* left: target of assignment, base-class setter will not be invoked
|
||||||
|
* right: value to assign
|
||||||
|
* PNK_ASSIGN (AssignmentNode)
|
||||||
* left: target of assignment
|
* left: target of assignment
|
||||||
* right: value to assign
|
* right: value to assign
|
||||||
* PNK_ADDASSIGN, PNK_SUBASSIGN, PNK_BITORASSIGN, PNK_BITXORASSIGN,
|
* PNK_ADDASSIGN, PNK_SUBASSIGN, PNK_BITORASSIGN, PNK_BITXORASSIGN,
|
||||||
|
|
|
||||||
|
|
@ -8048,18 +8048,18 @@ Parser<ParseHandler>::fieldInitializerOpt(YieldHandling yieldHandling, bool hasH
|
||||||
return null();
|
return null();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Synthesize an assignment expression for the property.
|
// Synthesize a property init.
|
||||||
AssignmentNodeType initializerAssignment = handler.newAssignment(PNK_ASSIGN,
|
AssignmentNodeType initializerPropInit = handler.newAssignment(PNK_INITPROP,
|
||||||
propAssignFieldAccess, initializerExpr,
|
propAssignFieldAccess, initializerExpr,
|
||||||
JSOP_NOP);
|
JSOP_NOP);
|
||||||
if (!initializerAssignment)
|
if (!initializerPropInit)
|
||||||
return null();
|
return null();
|
||||||
|
|
||||||
bool canSkipLazyClosedOverBindings = handler.canSkipLazyClosedOverBindings();
|
bool canSkipLazyClosedOverBindings = handler.canSkipLazyClosedOverBindings();
|
||||||
if (!declareFunctionThis(canSkipLazyClosedOverBindings))
|
if (!declareFunctionThis(canSkipLazyClosedOverBindings))
|
||||||
return null();
|
return null();
|
||||||
|
|
||||||
UnaryNodeType exprStatement = handler.newExprStatement(initializerAssignment, wholeInitializerPos.end);
|
UnaryNodeType exprStatement = handler.newExprStatement(initializerPropInit, wholeInitializerPos.end);
|
||||||
if (!exprStatement)
|
if (!exprStatement)
|
||||||
return null();
|
return null();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -110,11 +110,11 @@ PropOpEmitter::emitGet(JSAtom* prop)
|
||||||
bool
|
bool
|
||||||
PropOpEmitter::prepareForRhs()
|
PropOpEmitter::prepareForRhs()
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(isSimpleAssignment() || isCompoundAssignment());
|
MOZ_ASSERT(isSimpleAssignment() || isPropInit() || isCompoundAssignment());
|
||||||
MOZ_ASSERT_IF(isSimpleAssignment(), state_ == State::Obj);
|
MOZ_ASSERT_IF(isSimpleAssignment() || isPropInit(), state_ == State::Obj);
|
||||||
MOZ_ASSERT_IF(isCompoundAssignment(), state_ == State::Get);
|
MOZ_ASSERT_IF(isCompoundAssignment(), state_ == State::Get);
|
||||||
|
|
||||||
if (isSimpleAssignment()) {
|
if (isSimpleAssignment() || isPropInit()) {
|
||||||
// For CompoundAssignment, SUPERBASE is already emitted by emitGet.
|
// For CompoundAssignment, SUPERBASE is already emitted by emitGet.
|
||||||
if (isSuper()) {
|
if (isSuper()) {
|
||||||
if (!bce_->emit1(JSOP_SUPERBASE)) { // THIS SUPERBASE
|
if (!bce_->emit1(JSOP_SUPERBASE)) { // THIS SUPERBASE
|
||||||
|
|
@ -133,7 +133,7 @@ bool
|
||||||
PropOpEmitter::skipObjAndRhs()
|
PropOpEmitter::skipObjAndRhs()
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(state_ == State::Start);
|
MOZ_ASSERT(state_ == State::Start);
|
||||||
MOZ_ASSERT(isSimpleAssignment());
|
MOZ_ASSERT(isSimpleAssignment() || isPropInit());
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
state_ = State::Rhs;
|
state_ = State::Rhs;
|
||||||
|
|
@ -182,18 +182,20 @@ PropOpEmitter::emitDelete(JSAtom* prop)
|
||||||
bool
|
bool
|
||||||
PropOpEmitter::emitAssignment(JSAtom* prop)
|
PropOpEmitter::emitAssignment(JSAtom* prop)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(isSimpleAssignment() || isCompoundAssignment());
|
MOZ_ASSERT(isSimpleAssignment() || isPropInit() || isCompoundAssignment());
|
||||||
MOZ_ASSERT(state_ == State::Rhs);
|
MOZ_ASSERT(state_ == State::Rhs);
|
||||||
|
|
||||||
if (isSimpleAssignment()) {
|
if (isSimpleAssignment() || isPropInit()) {
|
||||||
if (!prepareAtomIndex(prop)) {
|
if (!prepareAtomIndex(prop)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
JSOp setOp = isSuper()
|
MOZ_ASSERT_IF(isPropInit(), !isSuper());
|
||||||
? bce_->sc->strict() ? JSOP_STRICTSETPROP_SUPER : JSOP_SETPROP_SUPER
|
JSOp setOp = isPropInit() ? JSOP_INITPROP
|
||||||
: bce_->sc->strict() ? JSOP_STRICTSETPROP : JSOP_SETPROP;
|
: isSuper()
|
||||||
|
? bce_->sc->strict() ? JSOP_STRICTSETPROP_SUPER : JSOP_SETPROP_SUPER
|
||||||
|
: bce_->sc->strict() ? JSOP_STRICTSETPROP : JSOP_SETPROP;
|
||||||
if (!bce_->emitAtomOp(propAtomIndex_, setOp)) { // VAL
|
if (!bce_->emitAtomOp(propAtomIndex_, setOp)) { // VAL
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -115,6 +115,7 @@ class MOZ_STACK_CLASS PropOpEmitter
|
||||||
PostDecrement,
|
PostDecrement,
|
||||||
PreDecrement,
|
PreDecrement,
|
||||||
SimpleAssignment,
|
SimpleAssignment,
|
||||||
|
PropInit,
|
||||||
CompoundAssignment
|
CompoundAssignment
|
||||||
};
|
};
|
||||||
enum class ObjKind {
|
enum class ObjKind {
|
||||||
|
|
@ -167,6 +168,7 @@ class MOZ_STACK_CLASS PropOpEmitter
|
||||||
// | +--------+ |
|
// | +--------+ |
|
||||||
// | |
|
// | |
|
||||||
// | [SimpleAssignment] |
|
// | [SimpleAssignment] |
|
||||||
|
// | [PropInit] |
|
||||||
// | prepareForRhs | +-----+
|
// | prepareForRhs | +-----+
|
||||||
// +--------------------->+-------------->+->| Rhs |-+
|
// +--------------------->+-------------->+->| Rhs |-+
|
||||||
// | ^ +-----+ |
|
// | ^ +-----+ |
|
||||||
|
|
@ -217,6 +219,10 @@ class MOZ_STACK_CLASS PropOpEmitter
|
||||||
return kind_ == Kind::SimpleAssignment;
|
return kind_ == Kind::SimpleAssignment;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MOZ_MUST_USE bool isPropInit() const {
|
||||||
|
return kind_ == Kind::PropInit;
|
||||||
|
}
|
||||||
|
|
||||||
MOZ_MUST_USE bool isDelete() const {
|
MOZ_MUST_USE bool isDelete() const {
|
||||||
return kind_ == Kind::Delete;
|
return kind_ == Kind::Delete;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue