Bug 1405760 - Remove ParseHandler::newBinary from the interface. Don't set the op field of assignment nodes. r=Waldo
authorJason Orendorff <jorendorff@mozilla.com>
Wed, 04 Oct 2017 11:51:14 -0500
changeset 385572 5b75a80f5310d4cb43c9f556200025f654705471
parent 385571 2dd2420c096323dc7ece727c26e750a7e5b7a09a
child 385573 a2bc0214fbcaf6104fe2ae8d2f4843997ea283de
push id32662
push userryanvm@gmail.com
push dateWed, 11 Oct 2017 21:53:47 +0000
treeherdermozilla-central@3d918ff5d634 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersWaldo
bugs1405760
milestone58.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1405760 - Remove ParseHandler::newBinary from the interface. Don't set the op field of assignment nodes. r=Waldo FullParseHandler::newBinary remains as a private method.
js/src/builtin/ReflectParse.cpp
js/src/frontend/BytecodeEmitter.cpp
js/src/frontend/BytecodeEmitter.h
js/src/frontend/FullParseHandler.h
js/src/frontend/Parser.cpp
js/src/frontend/SyntaxParseHandler.h
--- a/js/src/builtin/ReflectParse.cpp
+++ b/js/src/builtin/ReflectParse.cpp
@@ -1731,17 +1731,17 @@ class ASTSerializer
     DebugOnly<uint32_t> lineno;
 
     Value unrootedAtomContents(JSAtom* atom) {
         return StringValue(atom ? atom : cx->names().empty);
     }
 
     BinaryOperator binop(ParseNodeKind kind);
     UnaryOperator unop(ParseNodeKind kind);
-    AssignmentOperator aop(JSOp op);
+    AssignmentOperator aop(ParseNodeKind kind);
 
     bool statements(ParseNode* pn, NodeVector& elts);
     bool expressions(ParseNode* pn, NodeVector& elts);
     bool leftAssociate(ParseNode* pn, MutableHandleValue dst);
     bool rightAssociate(ParseNode* pn, MutableHandleValue dst);
     bool functionArgs(ParseNode* pn, ParseNode* pnargs,
                       NodeVector& args, NodeVector& defaults, MutableHandleValue rest);
 
@@ -1838,44 +1838,44 @@ class ASTSerializer
     }
 
     bool program(ParseNode* pn, MutableHandleValue dst);
 };
 
 } /* anonymous namespace */
 
 AssignmentOperator
-ASTSerializer::aop(JSOp op)
+ASTSerializer::aop(ParseNodeKind kind)
 {
-    switch (op) {
-      case JSOP_NOP:
+    switch (kind) {
+      case PNK_ASSIGN:
         return AOP_ASSIGN;
-      case JSOP_ADD:
+      case PNK_ADDASSIGN:
         return AOP_PLUS;
-      case JSOP_SUB:
+      case PNK_SUBASSIGN:
         return AOP_MINUS;
-      case JSOP_MUL:
+      case PNK_MULASSIGN:
         return AOP_STAR;
-      case JSOP_DIV:
+      case PNK_DIVASSIGN:
         return AOP_DIV;
-      case JSOP_MOD:
+      case PNK_MODASSIGN:
         return AOP_MOD;
-      case JSOP_POW:
+      case PNK_POWASSIGN:
         return AOP_POW;
-      case JSOP_LSH:
+      case PNK_LSHASSIGN:
         return AOP_LSH;
-      case JSOP_RSH:
+      case PNK_RSHASSIGN:
         return AOP_RSH;
-      case JSOP_URSH:
+      case PNK_URSHASSIGN:
         return AOP_URSH;
-      case JSOP_BITOR:
+      case PNK_BITORASSIGN:
         return AOP_BITOR;
-      case JSOP_BITXOR:
+      case PNK_BITXORASSIGN:
         return AOP_BITXOR;
-      case JSOP_BITAND:
+      case PNK_BITANDASSIGN:
         return AOP_BITAND;
       default:
         return AOP_ERR;
     }
 }
 
 UnaryOperator
 ASTSerializer::unop(ParseNodeKind kind)
@@ -2881,17 +2881,17 @@ ASTSerializer::expression(ParseNode* pn,
       case PNK_MULASSIGN:
       case PNK_DIVASSIGN:
       case PNK_MODASSIGN:
       case PNK_POWASSIGN:
       {
         MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_left->pn_pos));
         MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_right->pn_pos));
 
-        AssignmentOperator op = aop(pn->getOp());
+        AssignmentOperator op = aop(pn->getKind());
         LOCAL_ASSERT(op > AOP_ERR && op < AOP_LIMIT);
 
         RootedValue lhs(cx), rhs(cx);
         return pattern(pn->pn_left, &lhs) &&
                expression(pn->pn_right, &rhs) &&
                builder.assignmentExpression(op, lhs, rhs, &pn->pn_pos, dst);
       }
 
--- a/js/src/frontend/BytecodeEmitter.cpp
+++ b/js/src/frontend/BytecodeEmitter.cpp
@@ -6222,19 +6222,42 @@ EmitAssignmentRhs(BytecodeEmitter* bce, 
     // many other values have been pushed on the stack, we need to get the
     // already-pushed RHS value.
     if (offset != 1 && !bce->emit2(JSOP_PICK, offset - 1))
         return false;
 
     return true;
 }
 
-bool
-BytecodeEmitter::emitAssignment(ParseNode* lhs, JSOp op, ParseNode* rhs)
-{
+static inline JSOp
+CompoundAssignmentParseNodeKindToJSOp(ParseNodeKind pnk)
+{
+    switch (pnk) {
+      case PNK_ASSIGN:       return JSOP_NOP;
+      case PNK_ADDASSIGN:    return JSOP_ADD;
+      case PNK_SUBASSIGN:    return JSOP_SUB;
+      case PNK_BITORASSIGN:  return JSOP_BITOR;
+      case PNK_BITXORASSIGN: return JSOP_BITXOR;
+      case PNK_BITANDASSIGN: return JSOP_BITAND;
+      case PNK_LSHASSIGN:    return JSOP_LSH;
+      case PNK_RSHASSIGN:    return JSOP_RSH;
+      case PNK_URSHASSIGN:   return JSOP_URSH;
+      case PNK_MULASSIGN:    return JSOP_MUL;
+      case PNK_DIVASSIGN:    return JSOP_DIV;
+      case PNK_MODASSIGN:    return JSOP_MOD;
+      case PNK_POWASSIGN:    return JSOP_POW;
+      default: MOZ_CRASH("unexpected compound assignment op");
+    }
+}
+
+bool
+BytecodeEmitter::emitAssignment(ParseNode* lhs, ParseNodeKind pnk, ParseNode* rhs)
+{
+    JSOp op = CompoundAssignmentParseNodeKindToJSOp(pnk);
+
     // Name assignments are handled separately because choosing ops and when
     // to emit BINDNAME is involved and should avoid duplication.
     if (lhs->isKind(PNK_NAME)) {
         auto emitRhs = [op, lhs, rhs](BytecodeEmitter* bce, const NameLocation& lhsLoc,
                                       bool emittedBindOp)
         {
             // For compound assignments, first get the LHS value, then emit
             // the RHS and the op.
@@ -6250,18 +6273,20 @@ BytecodeEmitter::emitAssignment(ParseNod
 
             if (!lhs->isInParens() && op == JSOP_NOP && rhs && rhs->isDirectRHSAnonFunction()) {
                 RootedAtom name(bce->cx, lhs->name());
                 if (!bce->setOrEmitSetFunName(rhs, name, FunctionPrefixKind::None))
                     return false;
             }
 
             // Emit the compound assignment op if there is one.
-            if (op != JSOP_NOP && !bce->emit1(op))
-                return false;
+            if (op != JSOP_NOP) {
+                if (!bce->emit1(op))
+                    return false;
+            }
 
             return true;
         };
 
         return emitSetName(lhs, emitRhs);
     }
 
     // Deal with non-name assignments.
@@ -7133,17 +7158,17 @@ BytecodeEmitter::emitInitializeForInOrOf
 
     ParseNode* target = forHead->pn_kid1;
     MOZ_ASSERT(!forHead->pn_kid2);
 
     // If the for-in/of loop didn't have a variable declaration, per-loop
     // initialization is just assigning the iteration value to a target
     // expression.
     if (!parser.isDeclarationList(target))
-        return emitAssignment(target, JSOP_NOP, nullptr); // ... ITERVAL
+        return emitAssignment(target, PNK_ASSIGN, nullptr); // ... ITERVAL
 
     // Otherwise, per-loop initialization is (possibly) declaration
     // initialization.  If the declaration is a lexical declaration, it must be
     // initialized.  If the declaration is a variable declaration, an
     // assignment to that name (which does *not* necessarily assign to the
     // variable!) must be generated.
 
     if (!updateSourceCoordNotes(target->pn_pos.begin))
@@ -7858,17 +7883,17 @@ BytecodeEmitter::emitComprehensionForOf(
         return false;
 
     // Emit code to assign result.value to the iteration variable.
     if (!emitAtomOp(cx->names().value, JSOP_GETPROP))     // ITER VALUE
         return false;
 
     // Notice: Comprehension for-of doesn't perform IteratorClose, since it's
     // not in the spec.
-    if (!emitAssignment(loopVariableName, JSOP_NOP, nullptr)) // ITER VALUE
+    if (!emitAssignment(loopVariableName, PNK_ASSIGN, nullptr)) // ITER VALUE
         return false;
 
     // Remove VALUE from the stack to release it.
     if (!emit1(JSOP_POP))                                 // ITER
         return false;
     if (!emit1(JSOP_UNDEFINED))                           // ITER UNDEF
         return false;
 
@@ -7982,17 +8007,17 @@ BytecodeEmitter::emitComprehensionForIn(
         return false;
 
 #ifdef DEBUG
     int loopDepth = this->stackDepth;
 #endif
 
     // Emit code to assign the enumeration value to the left hand side, but
     // also leave it on the stack.
-    if (!emitAssignment(forHead->pn_kid2, JSOP_NOP, nullptr))
+    if (!emitAssignment(forHead->pn_kid2, PNK_ASSIGN, nullptr))
         return false;
 
     /* The stack should be balanced around the assignment opcode sequence. */
     MOZ_ASSERT(this->stackDepth == loopDepth);
 
     /* Emit code for the loop body. */
     if (!emitTree(forBody))
         return false;
@@ -11013,17 +11038,17 @@ BytecodeEmitter::emitTree(ParseNode* pn,
       case PNK_BITANDASSIGN:
       case PNK_LSHASSIGN:
       case PNK_RSHASSIGN:
       case PNK_URSHASSIGN:
       case PNK_MULASSIGN:
       case PNK_DIVASSIGN:
       case PNK_MODASSIGN:
       case PNK_POWASSIGN:
-        if (!emitAssignment(pn->pn_left, pn->getOp(), pn->pn_right))
+        if (!emitAssignment(pn->pn_left, pn->getKind(), pn->pn_right))
             return false;
         break;
 
       case PNK_CONDITIONAL:
         if (!emitConditionalExpression(pn->as<ConditionalExpression>(), valueUsage))
             return false;
         break;
 
--- a/js/src/frontend/BytecodeEmitter.h
+++ b/js/src/frontend/BytecodeEmitter.h
@@ -754,17 +754,17 @@ struct MOZ_STACK_CLASS BytecodeEmitter
     MOZ_MUST_USE bool setOrEmitSetFunName(ParseNode* maybeFun, HandleAtom name,
                                           FunctionPrefixKind prefixKind);
 
     MOZ_MUST_USE bool emitInitializer(ParseNode* initializer, ParseNode* pattern);
     MOZ_MUST_USE bool emitInitializerInBranch(ParseNode* initializer, ParseNode* pattern);
 
     MOZ_MUST_USE bool emitCallSiteObject(ParseNode* pn);
     MOZ_MUST_USE bool emitTemplateString(ParseNode* pn);
-    MOZ_MUST_USE bool emitAssignment(ParseNode* lhs, JSOp op, ParseNode* rhs);
+    MOZ_MUST_USE bool emitAssignment(ParseNode* lhs, ParseNodeKind pnk, ParseNode* rhs);
 
     MOZ_MUST_USE bool emitReturn(ParseNode* pn);
     MOZ_MUST_USE bool emitStatement(ParseNode* pn);
     MOZ_MUST_USE bool emitStatementList(ParseNode* pn);
 
     MOZ_MUST_USE bool emitDeleteName(ParseNode* pn);
     MOZ_MUST_USE bool emitDeleteProperty(ParseNode* pn);
     MOZ_MUST_USE bool emitDeleteElement(ParseNode* pn);
--- a/js/src/frontend/FullParseHandler.h
+++ b/js/src/frontend/FullParseHandler.h
@@ -212,22 +212,25 @@ class FullParseHandler
         return new_<UnaryNode>(PNK_SPREAD, pos, kid);
     }
 
     ParseNode* newArrayPush(uint32_t begin, ParseNode* kid) {
         TokenPos pos(begin, kid->pn_pos.end);
         return new_<UnaryNode>(PNK_ARRAYPUSH, pos, kid);
     }
 
+  private:
     ParseNode* newBinary(ParseNodeKind kind, ParseNode* left, ParseNode* right,
                          JSOp op = JSOP_NOP)
     {
         TokenPos pos(left->pn_pos.begin, right->pn_pos.end);
         return new_<BinaryNode>(kind, op, pos, left, right);
     }
+
+  public:
     ParseNode* appendOrCreateList(ParseNodeKind kind, ParseNode* left, ParseNode* right,
                                   ParseContext* pc)
     {
         return ParseNode::appendOrCreateList(kind, left, right, this, pc);
     }
 
     // Expressions
 
@@ -509,16 +512,20 @@ class FullParseHandler
     {
         ParseNode* pn = new_<BinaryNode>(PNK_IMPORT, JSOP_NOP, pos,
                                          importSpecSet, moduleSpec);
         if (!pn)
             return null();
         return pn;
     }
 
+    ParseNode* newImportSpec(ParseNode* importNameNode, ParseNode* bindingName) {
+        return newBinary(PNK_IMPORT_SPEC, importNameNode, bindingName);
+    }
+
     ParseNode* newExportDeclaration(ParseNode* kid, const TokenPos& pos) {
         return new_<UnaryNode>(PNK_EXPORT, pos, kid);
     }
 
     ParseNode* newExportFromDeclaration(uint32_t begin, ParseNode* exportSpecSet,
                                         ParseNode* moduleSpec)
     {
         ParseNode* pn = new_<BinaryNode>(PNK_EXPORT_FROM, JSOP_NOP, exportSpecSet, moduleSpec);
@@ -528,16 +535,20 @@ class FullParseHandler
         return pn;
     }
 
     ParseNode* newExportDefaultDeclaration(ParseNode* kid, ParseNode* maybeBinding,
                                            const TokenPos& pos) {
         return new_<BinaryNode>(PNK_EXPORT_DEFAULT, JSOP_NOP, pos, kid, maybeBinding);
     }
 
+    ParseNode* newExportSpec(ParseNode* bindingName, ParseNode* exportName) {
+        return newBinary(PNK_EXPORT_SPEC, bindingName, exportName);
+    }
+
     ParseNode* newExportBatchSpec(const TokenPos& pos) {
         return new_<NullaryNode>(PNK_EXPORT_BATCH_SPEC, JSOP_NOP, pos);
     }
 
     ParseNode* newExprStatement(ParseNode* expr, uint32_t end) {
         MOZ_ASSERT(expr->pn_pos.end <= end);
         return new_<UnaryNode>(PNK_SEMI, TokenPos(expr->pn_pos.begin, end), expr);
     }
@@ -725,20 +736,18 @@ class FullParseHandler
         ParseNode* newExpr = new_<ListNode>(PNK_NEW, JSOP_NEW, TokenPos(begin, begin + 1));
         if (!newExpr)
             return nullptr;
 
         addList(newExpr, ctor);
         return newExpr;
     }
 
-    ParseNode* newAssignment(ParseNodeKind kind, ParseNode* lhs, ParseNode* rhs,
-                             JSOp op)
-    {
-        return newBinary(kind, lhs, rhs, op);
+    ParseNode* newAssignment(ParseNodeKind kind, ParseNode* lhs, ParseNode* rhs) {
+        return newBinary(kind, lhs, rhs);
     }
 
     bool isUnparenthesizedYieldExpression(ParseNode* node) {
         return node->isKind(PNK_YIELD) && !node->isInParens();
     }
 
     bool isUnparenthesizedCommaExpression(ParseNode* node) {
         return node->isKind(PNK_COMMA) && !node->isInParens();
--- a/js/src/frontend/Parser.cpp
+++ b/js/src/frontend/Parser.cpp
@@ -4434,17 +4434,17 @@ Parser<ParseHandler, CharT>::bindingInit
         pc->functionBox()->hasParameterExprs = true;
 
     Node rhs = assignExpr(InAllowed, yieldHandling, TripledotProhibited);
     if (!rhs)
         return null();
 
     handler.checkAndSetIsDirectRHSAnonFunction(rhs);
 
-    Node assign = handler.newAssignment(PNK_ASSIGN, lhs, rhs, JSOP_NOP);
+    Node assign = handler.newAssignment(PNK_ASSIGN, lhs, rhs);
     if (!assign)
         return null();
 
     if (foldConstants && !FoldConstants(context, &assign, this))
         return null();
 
     return assign;
 }
@@ -4829,17 +4829,17 @@ Parser<ParseHandler, CharT>::declaration
         // peek at the next token when assignExpr() is a lazily parsed arrow
         // function.
         TokenKind ignored;
         if (!tokenStream.peekToken(&ignored))
             return null();
         tokenStream.addModifierException(TokenStream::OperandIsNone);
     }
 
-    return handler.newBinary(PNK_ASSIGN, pattern, init);
+    return handler.newAssignment(PNK_ASSIGN, pattern, init);
 }
 
 template <class ParseHandler, typename CharT>
 bool
 Parser<ParseHandler, CharT>::initializerInNameDeclaration(Node decl, Node binding,
                                                           Handle<PropertyName*> name,
                                                           DeclarationKind declKind,
                                                           bool initialDeclaration,
@@ -5147,17 +5147,17 @@ Parser<FullParseHandler, char16_t>::name
                 return false;
             if (!noteDeclaredName(bindingAtom, DeclarationKind::Import, pos()))
                 return false;
 
             Node importNameNode = newName(importName, importNamePos);
             if (!importNameNode)
                 return false;
 
-            Node importSpec = handler.newBinary(PNK_IMPORT_SPEC, importNameNode, bindingName);
+            Node importSpec = handler.newImportSpec(importNameNode, bindingName);
             if (!importSpec)
                 return false;
 
             handler.addList(importSpecSet, importSpec);
 
             TokenKind next;
             if (!tokenStream.getToken(&next))
                 return false;
@@ -5193,17 +5193,17 @@ Parser<FullParseHandler, char16_t>::name
             return false;
         if (!noteDeclaredName(bindingName, DeclarationKind::Const, pos()))
             return false;
 
         // The namespace import name is currently required to live on the
         // environment.
         pc->varScope().lookupDeclaredName(bindingName)->value()->setClosedOver();
 
-        Node importSpec = handler.newBinary(PNK_IMPORT_SPEC, importName, bindingNameNode);
+        Node importSpec = handler.newImportSpec(importName, bindingNameNode);
         if (!importSpec)
             return false;
 
         handler.addList(importSpecSet, importSpec);
     }
 
     return true;
 }
@@ -5260,17 +5260,17 @@ Parser<FullParseHandler, char16_t>::impo
 
             Node bindingName = newName(bindingAtom);
             if (!bindingName)
                 return null();
 
             if (!noteDeclaredName(bindingAtom, DeclarationKind::Import, pos()))
                 return null();
 
-            Node importSpec = handler.newBinary(PNK_IMPORT_SPEC, importName, bindingName);
+            Node importSpec = handler.newImportSpec(importName, bindingName);
             if (!importSpec)
                 return null();
 
             handler.addList(importSpecSet, importSpec);
 
             if (!tokenStream.peekToken(&tt))
                 return null();
 
@@ -5566,17 +5566,17 @@ Parser<ParseHandler, CharT>::exportClaus
 
         Node exportName = newName(tokenStream.currentName());
         if (!exportName)
             return null();
 
         if (!checkExportedNameForClause(exportName))
             return null();
 
-        Node exportSpec = handler.newBinary(PNK_EXPORT_SPEC, bindingName, exportName);
+        Node exportSpec = handler.newExportSpec(bindingName, exportName);
         if (!exportSpec)
             return null();
 
         handler.addList(kid, exportSpec);
 
         TokenKind next;
         if (!tokenStream.getToken(&next))
             return null();
@@ -8245,31 +8245,30 @@ Parser<ParseHandler, CharT>::assignExpr(
     } else {
         lhs = condExpr1(inHandling, yieldHandling, tripledotHandling, &possibleErrorInner, invoked);
         if (!lhs) {
             return null();
         }
     }
 
     ParseNodeKind kind;
-    JSOp op;
     switch (tokenStream.currentToken().type) {
-      case TOK_ASSIGN:       kind = PNK_ASSIGN;       op = JSOP_NOP;    break;
-      case TOK_ADDASSIGN:    kind = PNK_ADDASSIGN;    op = JSOP_ADD;    break;
-      case TOK_SUBASSIGN:    kind = PNK_SUBASSIGN;    op = JSOP_SUB;    break;
-      case TOK_BITORASSIGN:  kind = PNK_BITORASSIGN;  op = JSOP_BITOR;  break;
-      case TOK_BITXORASSIGN: kind = PNK_BITXORASSIGN; op = JSOP_BITXOR; break;
-      case TOK_BITANDASSIGN: kind = PNK_BITANDASSIGN; op = JSOP_BITAND; break;
-      case TOK_LSHASSIGN:    kind = PNK_LSHASSIGN;    op = JSOP_LSH;    break;
-      case TOK_RSHASSIGN:    kind = PNK_RSHASSIGN;    op = JSOP_RSH;    break;
-      case TOK_URSHASSIGN:   kind = PNK_URSHASSIGN;   op = JSOP_URSH;   break;
-      case TOK_MULASSIGN:    kind = PNK_MULASSIGN;    op = JSOP_MUL;    break;
-      case TOK_DIVASSIGN:    kind = PNK_DIVASSIGN;    op = JSOP_DIV;    break;
-      case TOK_MODASSIGN:    kind = PNK_MODASSIGN;    op = JSOP_MOD;    break;
-      case TOK_POWASSIGN:    kind = PNK_POWASSIGN;    op = JSOP_POW;    break;
+      case TOK_ASSIGN:       kind = PNK_ASSIGN;       break;
+      case TOK_ADDASSIGN:    kind = PNK_ADDASSIGN;    break;
+      case TOK_SUBASSIGN:    kind = PNK_SUBASSIGN;    break;
+      case TOK_BITORASSIGN:  kind = PNK_BITORASSIGN;  break;
+      case TOK_BITXORASSIGN: kind = PNK_BITXORASSIGN; break;
+      case TOK_BITANDASSIGN: kind = PNK_BITANDASSIGN; break;
+      case TOK_LSHASSIGN:    kind = PNK_LSHASSIGN;    break;
+      case TOK_RSHASSIGN:    kind = PNK_RSHASSIGN;    break;
+      case TOK_URSHASSIGN:   kind = PNK_URSHASSIGN;   break;
+      case TOK_MULASSIGN:    kind = PNK_MULASSIGN;    break;
+      case TOK_DIVASSIGN:    kind = PNK_DIVASSIGN;    break;
+      case TOK_MODASSIGN:    kind = PNK_MODASSIGN;    break;
+      case TOK_POWASSIGN:    kind = PNK_POWASSIGN;    break;
 
       case TOK_ARROW: {
 
         // A line terminator between ArrowParameters and the => should trigger a SyntaxError.
         tokenStream.ungetToken();
         TokenKind next;
         if (!tokenStream.peekTokenSameLine(&next))
             return null();
@@ -8401,17 +8400,17 @@ Parser<ParseHandler, CharT>::assignExpr(
 
     Node rhs = assignExpr(inHandling, yieldHandling, TripledotProhibited);
     if (!rhs)
         return null();
 
     if (kind == PNK_ASSIGN)
         handler.checkAndSetIsDirectRHSAnonFunction(rhs);
 
-    return handler.newAssignment(kind, lhs, rhs, op);
+    return handler.newAssignment(kind, lhs, rhs);
 }
 
 template <class ParseHandler, typename CharT>
 bool
 Parser<ParseHandler, CharT>::isValidSimpleAssignmentTarget(Node node,
                                                            FunctionCallBehavior behavior /* = ForbidAssignmentToFunctionCalls */)
 {
     // Note that this method implements *only* a boolean test.  Reporting an
@@ -10048,17 +10047,17 @@ Parser<ParseHandler, CharT>::objectLiter
                 }
 
                 Node rhs = assignExpr(InAllowed, yieldHandling, TripledotProhibited);
                 if (!rhs)
                     return null();
 
                 handler.checkAndSetIsDirectRHSAnonFunction(rhs);
 
-                Node propExpr = handler.newAssignment(PNK_ASSIGN, lhs, rhs, JSOP_NOP);
+                Node propExpr = handler.newAssignment(PNK_ASSIGN, lhs, rhs);
                 if (!propExpr)
                     return null();
 
                 if (!handler.addPropertyDefinition(literal, propName, propExpr))
                     return null();
             } else {
                 RootedAtom funName(context);
                 if (!tokenStream.isCurrentTokenType(TOK_RB)) {
--- a/js/src/frontend/SyntaxParseHandler.h
+++ b/js/src/frontend/SyntaxParseHandler.h
@@ -248,19 +248,16 @@ class SyntaxParseHandler
     Node newSpread(uint32_t begin, Node kid) {
         return NodeGeneric;
     }
 
     Node newArrayPush(uint32_t begin, Node kid) {
         return NodeGeneric;
     }
 
-    Node newBinary(ParseNodeKind kind, Node left, Node right) {
-        return NodeGeneric;
-    }
     Node appendOrCreateList(ParseNodeKind kind, Node left, Node right, ParseContext* pc) {
         return NodeGeneric;
     }
 
     // Expressions
 
     Node newGeneratorComprehension(Node genfn, const TokenPos& pos) { return NodeGeneric; }
     Node newArrayComprehension(Node body, const TokenPos& pos) { return NodeGeneric; }
@@ -305,16 +302,19 @@ class SyntaxParseHandler
         return NodeGeneric;
     }
     Node newExportFromDeclaration(uint32_t begin, Node exportSpecSet, Node moduleSpec) {
         return NodeGeneric;
     }
     Node newExportDefaultDeclaration(Node kid, Node maybeBinding, const TokenPos& pos) {
         return NodeGeneric;
     }
+    Node newExportSpec(Node bindingName, Node exportName) {
+        return NodeGeneric;
+    }
     Node newExportBatchSpec(const TokenPos& pos) {
         return NodeGeneric;
     }
 
     Node newSetThis(Node thisName, Node value) { return value; }
 
     Node newExprStatement(Node expr, uint32_t end) {
         return expr == NodeUnparenthesizedString ? NodeStringExprStatement : NodeGeneric;
@@ -465,20 +465,18 @@ class SyntaxParseHandler
                    list == NodeLexicalDeclaration ||
                    list == NodeFunctionCall);
     }
 
     Node newNewExpression(uint32_t begin, Node ctor) {
         return NodeGeneric;
     }
 
-    Node newAssignment(ParseNodeKind kind, Node lhs, Node rhs, JSOp op) {
-        if (kind == PNK_ASSIGN)
-            return NodeUnparenthesizedAssignment;
-        return newBinary(kind, lhs, rhs);
+    Node newAssignment(ParseNodeKind kind, Node lhs, Node rhs) {
+        return kind == PNK_ASSIGN ? NodeUnparenthesizedAssignment : NodeGeneric;
     }
 
     bool isUnparenthesizedCommaExpression(Node node) {
         return node == NodeUnparenthesizedCommaExpr;
     }
 
     bool isUnparenthesizedAssignment(Node node) {
         return node == NodeUnparenthesizedAssignment;