diff --git a/js/src/builtin/ModuleObject.cpp b/js/src/builtin/ModuleObject.cpp index dcf0e047c59be..9edafafc7dd6f 100644 --- a/js/src/builtin/ModuleObject.cpp +++ b/js/src/builtin/ModuleObject.cpp @@ -1458,7 +1458,7 @@ bool ModuleBuilder::processExportObjectBinding(frontend::ListNode* obj) { for (ParseNode* node : obj->contents()) { MOZ_ASSERT(node->isKind(ParseNodeKind::MutateProto) || - node->isKind(ParseNodeKind::Colon) || + node->isKind(ParseNodeKind::PropertyDefinition) || node->isKind(ParseNodeKind::Shorthand) || node->isKind(ParseNodeKind::Spread)); diff --git a/js/src/builtin/ReflectParse.cpp b/js/src/builtin/ReflectParse.cpp index 435e908552e56..7c71adc813b75 100644 --- a/js/src/builtin/ReflectParse.cpp +++ b/js/src/builtin/ReflectParse.cpp @@ -2500,16 +2500,16 @@ bool ASTSerializer::statement(ParseNode* pn, MutableHandleValue dst) { bool ASTSerializer::classMethod(ClassMethod* classMethod, MutableHandleValue dst) { PropKind kind; - switch (classMethod->getOp()) { - case JSOP_INITPROP: + switch (classMethod->accessorType()) { + case AccessorType::None: kind = PROP_INIT; break; - case JSOP_INITPROP_GETTER: + case AccessorType::Getter: kind = PROP_GETTER; break; - case JSOP_INITPROP_SETTER: + case AccessorType::Setter: kind = PROP_SETTER; break; @@ -3113,21 +3113,26 @@ bool ASTSerializer::property(ParseNode* pn, MutableHandleValue dst) { } PropKind kind; - switch (pn->getOp()) { - case JSOP_INITPROP: - kind = PROP_INIT; - break; + if (pn->is()) { + switch (pn->as().accessorType()) { + case AccessorType::None: + kind = PROP_INIT; + break; - case JSOP_INITPROP_GETTER: - kind = PROP_GETTER; - break; + case AccessorType::Getter: + kind = PROP_GETTER; + break; - case JSOP_INITPROP_SETTER: - kind = PROP_SETTER; - break; + case AccessorType::Setter: + kind = PROP_SETTER; + break; - default: - LOCAL_NOT_REACHED("unexpected object-literal property"); + default: + LOCAL_NOT_REACHED("unexpected object-literal property"); + } + } else { + MOZ_ASSERT(pn->isKind(ParseNodeKind::Shorthand)); + kind = PROP_INIT; } BinaryNode* node = &pn->as(); @@ -3251,8 +3256,10 @@ bool ASTSerializer::objectPattern(ListNode* obj, MutableHandleValue dst) { elts.infallibleAppend(spread); continue; } - LOCAL_ASSERT(propdef->isKind(ParseNodeKind::MutateProto) != - propdef->isOp(JSOP_INITPROP)); + // Patterns can't have getters/setters. + LOCAL_ASSERT(!propdef->is() || + propdef->as().accessorType() == + AccessorType::None); RootedValue key(cx); ParseNode* target; diff --git a/js/src/frontend/BytecodeEmitter.cpp b/js/src/frontend/BytecodeEmitter.cpp index cf9ae5b42bec0..330a0004d8517 100644 --- a/js/src/frontend/BytecodeEmitter.cpp +++ b/js/src/frontend/BytecodeEmitter.cpp @@ -1249,7 +1249,7 @@ bool BytecodeEmitter::checkSideEffects(ParseNode* pn, bool* answer) { *answer = true; return true; - case ParseNodeKind::Colon: + case ParseNodeKind::PropertyDefinition: case ParseNodeKind::Case: { BinaryNode* node = &pn->as(); if (!checkSideEffects(node->left(), answer)) { @@ -3620,7 +3620,7 @@ bool BytecodeEmitter::emitDestructuringOpsObject(ListNode* pattern, member->isKind(ParseNodeKind::Spread)) { subpattern = member->as().kid(); } else { - MOZ_ASSERT(member->isKind(ParseNodeKind::Colon) || + MOZ_ASSERT(member->isKind(ParseNodeKind::PropertyDefinition) || member->isKind(ParseNodeKind::Shorthand)); subpattern = member->as().right(); } @@ -3698,7 +3698,7 @@ bool BytecodeEmitter::emitDestructuringOpsObject(ListNode* pattern, } needsGetElem = false; } else { - MOZ_ASSERT(member->isKind(ParseNodeKind::Colon) || + MOZ_ASSERT(member->isKind(ParseNodeKind::PropertyDefinition) || member->isKind(ParseNodeKind::Shorthand)); ParseNode* key = member->as().left(); @@ -7569,16 +7569,21 @@ bool BytecodeEmitter::emitPropertyList(ListNode* obj, PropertyEmitter& pe, ParseNode* key = prop->left(); ParseNode* propVal = prop->right(); - JSOp op = propdef->getOp(); - MOZ_ASSERT(op == JSOP_INITPROP || op == JSOP_INITPROP_GETTER || - op == JSOP_INITPROP_SETTER); + AccessorType accessorType; + if (prop->is()) { + accessorType = prop->as().accessorType(); + } else if (prop->is()) { + accessorType = prop->as().accessorType(); + } else { + accessorType = AccessorType::None; + } - auto emitValue = [this, &key, &propVal, op, &pe]() { + auto emitValue = [this, &key, &propVal, accessorType, &pe]() { // [stack] CTOR? OBJ CTOR? KEY? if (propVal->isDirectRHSAnonFunction()) { if (key->isKind(ParseNodeKind::NumberExpr)) { - MOZ_ASSERT(op == JSOP_INITPROP); + MOZ_ASSERT(accessorType == AccessorType::None); NumericLiteral* literal = &key->as(); RootedAtom keyAtom(cx, NumberToAtom(cx, literal->value())); @@ -7591,7 +7596,7 @@ bool BytecodeEmitter::emitPropertyList(ListNode* obj, PropertyEmitter& pe, } } else if (key->isKind(ParseNodeKind::ObjectPropertyName) || key->isKind(ParseNodeKind::StringExpr)) { - MOZ_ASSERT(op == JSOP_INITPROP); + MOZ_ASSERT(accessorType == AccessorType::None); RootedAtom keyAtom(cx, key->as().atom()); if (!emitAnonymousFunctionWithName(propVal, keyAtom)) { @@ -7601,9 +7606,9 @@ bool BytecodeEmitter::emitPropertyList(ListNode* obj, PropertyEmitter& pe, } else { MOZ_ASSERT(key->isKind(ParseNodeKind::ComputedName)); - FunctionPrefixKind prefix = op == JSOP_INITPROP + FunctionPrefixKind prefix = accessorType == AccessorType::None ? FunctionPrefixKind::None - : op == JSOP_INITPROP_GETTER + : accessorType == AccessorType::Getter ? FunctionPrefixKind::Get : FunctionPrefixKind::Set; @@ -7657,20 +7662,20 @@ bool BytecodeEmitter::emitPropertyList(ListNode* obj, PropertyEmitter& pe, return false; } - switch (op) { - case JSOP_INITPROP: + switch (accessorType) { + case AccessorType::None: if (!pe.emitInitIndexProp()) { // [stack] CTOR? OBJ return false; } break; - case JSOP_INITPROP_GETTER: + case AccessorType::Getter: if (!pe.emitInitIndexGetter()) { // [stack] CTOR? OBJ return false; } break; - case JSOP_INITPROP_SETTER: + case AccessorType::Setter: if (!pe.emitInitIndexSetter()) { // [stack] CTOR? OBJ return false; @@ -7704,20 +7709,20 @@ bool BytecodeEmitter::emitPropertyList(ListNode* obj, PropertyEmitter& pe, } RootedAtom keyAtom(cx, key->as().atom()); - switch (op) { - case JSOP_INITPROP: + switch (accessorType) { + case AccessorType::None: if (!pe.emitInitProp(keyAtom)) { // [stack] CTOR? OBJ return false; } break; - case JSOP_INITPROP_GETTER: + case AccessorType::Getter: if (!pe.emitInitGetter(keyAtom)) { // [stack] CTOR? OBJ return false; } break; - case JSOP_INITPROP_SETTER: + case AccessorType::Setter: if (!pe.emitInitSetter(keyAtom)) { // [stack] CTOR? OBJ return false; @@ -7751,20 +7756,20 @@ bool BytecodeEmitter::emitPropertyList(ListNode* obj, PropertyEmitter& pe, return false; } - switch (op) { - case JSOP_INITPROP: + switch (accessorType) { + case AccessorType::None: if (!pe.emitInitComputedProp()) { // [stack] CTOR? OBJ return false; } break; - case JSOP_INITPROP_GETTER: + case AccessorType::Getter: if (!pe.emitInitComputedGetter()) { // [stack] CTOR? OBJ return false; } break; - case JSOP_INITPROP_SETTER: + case AccessorType::Setter: if (!pe.emitInitComputedSetter()) { // [stack] CTOR? OBJ return false; diff --git a/js/src/frontend/FoldConstants.cpp b/js/src/frontend/FoldConstants.cpp index 55871d912b752..5836337f4aeb0 100644 --- a/js/src/frontend/FoldConstants.cpp +++ b/js/src/frontend/FoldConstants.cpp @@ -319,7 +319,7 @@ static bool ContainsHoistedDeclaration(JSContext* cx, ParseNode* node, case ParseNodeKind::ComputedName: case ParseNodeKind::Spread: case ParseNodeKind::MutateProto: - case ParseNodeKind::Colon: + case ParseNodeKind::PropertyDefinition: case ParseNodeKind::Shorthand: case ParseNodeKind::ConditionalExpr: case ParseNodeKind::TypeOfNameExpr: @@ -1491,7 +1491,7 @@ class FoldVisitor : public RewritingParseNodeVisitor { ListNode* list = &pn->as(); if (list->hasNonConstInitializer()) { for (ParseNode* node : list->contents()) { - if (node->getKind() != ParseNodeKind::Colon) { + if (node->getKind() != ParseNodeKind::PropertyDefinition) { return true; } BinaryNode* binary = &node->as(); diff --git a/js/src/frontend/FullParseHandler.h b/js/src/frontend/FullParseHandler.h index 70832ea49afae..06846365316c3 100644 --- a/js/src/frontend/FullParseHandler.h +++ b/js/src/frontend/FullParseHandler.h @@ -371,12 +371,12 @@ class FullParseHandler { BinaryNodeType newPropertyDefinition(Node key, Node val) { MOZ_ASSERT(isUsableAsObjectPropertyName(key)); checkAndSetIsDirectRHSAnonFunction(val); - return newBinary(ParseNodeKind::Colon, key, val, JSOP_INITPROP); + return new_(key, val, AccessorType::None); } void addPropertyDefinition(ListNodeType literal, BinaryNodeType propdef) { MOZ_ASSERT(literal->isKind(ParseNodeKind::ObjectExpr)); - MOZ_ASSERT(propdef->isKind(ParseNodeKind::Colon)); + MOZ_ASSERT(propdef->isKind(ParseNodeKind::PropertyDefinition)); if (!propdef->right()->isConstant()) { literal->setHasNonConstInitializer(); @@ -451,8 +451,7 @@ class FullParseHandler { checkAndSetIsDirectRHSAnonFunction(funNode); - ClassMethod* classMethod = - new_(key, funNode, AccessorTypeToJSOp(atype), isStatic); + ClassMethod* classMethod = new_(key, funNode, atype, isStatic); if (!classMethod) { return false; } @@ -780,8 +779,7 @@ class FullParseHandler { AccessorType atype) { MOZ_ASSERT(isUsableAsObjectPropertyName(key)); - return newBinary(ParseNodeKind::Colon, key, value, - AccessorTypeToJSOp(atype)); + return new_(key, value, atype); } BinaryNodeType newShorthandPropertyDefinition(Node key, Node value) { diff --git a/js/src/frontend/NameFunctions.cpp b/js/src/frontend/NameFunctions.cpp index 4c7aaa592b4ad..56ebfd0cfec5e 100644 --- a/js/src/frontend/NameFunctions.cpp +++ b/js/src/frontend/NameFunctions.cpp @@ -193,11 +193,10 @@ class NameResolver : public ParseNodeVisitor { } break; - case ParseNodeKind::Colon: + case ParseNodeKind::PropertyDefinition: case ParseNodeKind::Shorthand: - // Record the ParseNodeKind::Colon/Shorthand but skip the - // ParseNodeKind::Object so we're not flagged as a - // contributor. + // Record the ParseNodeKind::PropertyDefinition/Shorthand but skip the + // ParseNodeKind::Object so we're not flagged as a contributor. pos--; MOZ_FALLTHROUGH; @@ -272,7 +271,7 @@ class NameResolver : public ParseNodeVisitor { for (int pos = size - 1; pos >= 0; pos--) { ParseNode* node = toName[pos]; - if (node->isKind(ParseNodeKind::Colon) || + if (node->isKind(ParseNodeKind::PropertyDefinition) || node->isKind(ParseNodeKind::Shorthand)) { ParseNode* left = node->as().left(); if (left->isKind(ParseNodeKind::ObjectPropertyName) || diff --git a/js/src/frontend/ParseNode.h b/js/src/frontend/ParseNode.h index 6f39e43ce83e9..92e04e960b8d4 100644 --- a/js/src/frontend/ParseNode.h +++ b/js/src/frontend/ParseNode.h @@ -53,7 +53,7 @@ class BigIntBox; F(ExpressionStmt, UnaryNode) \ F(CommaExpr, ListNode) \ F(ConditionalExpr, ConditionalExpression) \ - F(Colon, BinaryNode) \ + F(PropertyDefinition, PropertyDefinition) \ F(Shorthand, BinaryNode) \ F(PosExpr, UnaryNode) \ F(NegExpr, UnaryNode) \ @@ -455,17 +455,17 @@ inline bool IsTypeofKind(ParseNodeKind kind) { * ObjectExpr (ListNode) * head: list of N nodes, each item is one of: * * MutateProto - * * Colon + * * PropertyDefinition * * Shorthand * * Spread * count: N >= 0 - * Colon (BinaryNode) + * PropertyDefinition (PropertyDefinition) * key-value pair in object initializer or destructuring lhs * left: property id * right: value * Shorthand (BinaryNode) - * Same fields as Colon. This is used for object literal properties using - * shorthand ({x}). + * Same fields as PropertyDefinition. This is used for object literal + * properties using shorthand ({x}). * ComputedName (UnaryNode) * ES6 ComputedPropertyName. * kid: the AssignmentExpression inside the square brackets @@ -595,6 +595,8 @@ enum class FunctionSyntaxKind { Setter, }; +enum class AccessorType { None, Getter, Setter }; + static inline bool IsConstructorKind(FunctionSyntaxKind kind) { return kind == FunctionSyntaxKind::ClassConstructor || kind == FunctionSyntaxKind::DerivedClassConstructor; @@ -616,8 +618,8 @@ class ParseNode { bool pn_parens : 1; /* this expr was enclosed in parens */ bool pn_rhs_anon_fun : 1; /* this expr is anonymous function or class that * is a direct RHS of ParseNodeKind::Assign or - * ParseNodeKind::Colon of property, that needs - * SetFunctionName. */ + * ParseNodeKind::PropertyDefinition of property, + * that needs SetFunctionName. */ ParseNode(const ParseNode& other) = delete; void operator=(const ParseNode& other) = delete; @@ -1924,16 +1926,19 @@ class CallSiteNode : public ListNode { class ClassMethod : public BinaryNode { bool isStatic_; + AccessorType accessorType_; public: /* * Method definitions often keep a name and function body that overlap, * so explicitly define the beginning and end here. */ - ClassMethod(ParseNode* name, ParseNode* body, JSOp op, bool isStatic) - : BinaryNode(ParseNodeKind::ClassMethod, op, + ClassMethod(ParseNode* name, ParseNode* body, AccessorType accessorType, + bool isStatic) + : BinaryNode(ParseNodeKind::ClassMethod, JSOP_NOP, TokenPos(name->pn_pos.begin, body->pn_pos.end), name, body), - isStatic_(isStatic) {} + isStatic_(isStatic), + accessorType_(accessorType) {} static bool test(const ParseNode& node) { bool match = node.isKind(ParseNodeKind::ClassMethod); @@ -1946,6 +1951,8 @@ class ClassMethod : public BinaryNode { FunctionNode& method() const { return right()->as(); } bool isStatic() const { return isStatic_; } + + AccessorType accessorType() const { return accessorType_; } }; class ClassField : public BinaryNode { @@ -1970,6 +1977,26 @@ class ClassField : public BinaryNode { } }; +class PropertyDefinition : public BinaryNode { + AccessorType accessorType_; + + public: + PropertyDefinition(ParseNode* name, ParseNode* value, + AccessorType accessorType) + : BinaryNode(ParseNodeKind::PropertyDefinition, JSOP_NOP, + TokenPos(name->pn_pos.begin, value->pn_pos.end), name, + value), + accessorType_(accessorType) {} + + static bool test(const ParseNode& node) { + bool match = node.isKind(ParseNodeKind::PropertyDefinition); + MOZ_ASSERT_IF(match, node.is()); + return match; + } + + AccessorType accessorType() { return accessorType_; } +}; + class SwitchStatement : public BinaryNode { bool hasDefault_; /* only for ParseNodeKind::Switch */ @@ -2166,21 +2193,6 @@ enum ParseReportKind { ParseStrictError }; -enum class AccessorType { None, Getter, Setter }; - -inline JSOp AccessorTypeToJSOp(AccessorType atype) { - switch (atype) { - case AccessorType::None: - return JSOP_INITPROP; - case AccessorType::Getter: - return JSOP_INITPROP_GETTER; - case AccessorType::Setter: - return JSOP_INITPROP_SETTER; - default: - MOZ_CRASH("unexpected accessor type"); - } -} - static inline ParseNode* FunctionFormalParametersList(ParseNode* fn, unsigned* numFormals) { MOZ_ASSERT(fn->isKind(ParseNodeKind::Function)); diff --git a/js/src/frontend/Parser.cpp b/js/src/frontend/Parser.cpp index 9f49903875e5d..9ba1d0bfad2be 100644 --- a/js/src/frontend/Parser.cpp +++ b/js/src/frontend/Parser.cpp @@ -4695,7 +4695,7 @@ bool Parser::checkExportedNamesForObjectBinding( for (ParseNode* node : obj->contents()) { MOZ_ASSERT(node->isKind(ParseNodeKind::MutateProto) || - node->isKind(ParseNodeKind::Colon) || + node->isKind(ParseNodeKind::PropertyDefinition) || node->isKind(ParseNodeKind::Shorthand) || node->isKind(ParseNodeKind::Spread)); diff --git a/js/src/wasm/AsmJS.cpp b/js/src/wasm/AsmJS.cpp index d5bb27193be76..dc37842d41bfe 100644 --- a/js/src/wasm/AsmJS.cpp +++ b/js/src/wasm/AsmJS.cpp @@ -594,7 +594,8 @@ static inline ParseNode* FunctionStatementList(FunctionNode* funNode) { } static inline bool IsNormalObjectField(ParseNode* pn) { - return pn->isKind(ParseNodeKind::Colon) && pn->getOp() == JSOP_INITPROP && + return pn->isKind(ParseNodeKind::PropertyDefinition) && + pn->as().accessorType() == AccessorType::None && BinaryLeft(pn)->isKind(ParseNodeKind::ObjectPropertyName); }