Blob Blame History Raw
#
#  Manuall backport of Mozilla's bug 1378808 and others, mostly
#  to prepare code for backporting of optional chaining support.
#
#      bug 1378808 (part 1-3)
#      bug 1518661 part 3 only (and without all the tests)
#

diff -Nrup mozilla-OLD/js/src/builtin/ReflectParse.cpp mozilla/js/src/builtin/ReflectParse.cpp
--- mozilla-OLD/js/src/builtin/ReflectParse.cpp	2021-12-29 03:47:40.631227104 +0300
+++ mozilla/js/src/builtin/ReflectParse.cpp	2021-12-29 03:37:16.052713992 +0300
@@ -2945,24 +2945,25 @@ ASTSerializer::expression(ParseNode* pn,
       case ParseNodeKind::Call:
       case ParseNodeKind::SuperCall:
       {
-        ParseNode* next = pn->pn_head;
-        MOZ_ASSERT(pn->pn_pos.encloses(next->pn_pos));
+        ParseNode* pn_callee = pn->pn_left;
+        ParseNode* pn_args = pn->pn_right;
+        MOZ_ASSERT(pn->pn_pos.encloses(pn_callee->pn_pos));
 
         RootedValue callee(cx);
         if (pn->isKind(ParseNodeKind::SuperCall)) {
-            MOZ_ASSERT(next->isKind(ParseNodeKind::SuperBase));
-            if (!builder.super(&next->pn_pos, &callee))
+            MOZ_ASSERT(pn_callee->isKind(ParseNodeKind::SuperBase));
+            if (!builder.super(&pn_callee->pn_pos, &callee))
                 return false;
         } else {
-            if (!expression(next, &callee))
+            if (!expression(pn_callee, &callee))
                 return false;
         }
 
         NodeVector args(cx);
-        if (!args.reserve(pn->pn_count - 1))
+        if (!args.reserve(pn_args->pn_count))
             return false;
 
-        for (next = next->pn_next; next; next = next->pn_next) {
+        for (ParseNode* next = pn_args->pn_head; next; next = next->pn_next) {
             MOZ_ASSERT(pn->pn_pos.encloses(next->pn_pos));
 
             RootedValue arg(cx);
@@ -2983,17 +2984,17 @@ ASTSerializer::expression(ParseNode* pn,
 
       case ParseNodeKind::Dot:
       {
-        MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_expr->pn_pos));
+        MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_left->pn_pos));
 
         RootedValue expr(cx);
         RootedValue propname(cx);
-        RootedAtom pnAtom(cx, pn->pn_atom);
+        RootedAtom pnAtom(cx, pn->pn_right->pn_atom);
 
         if (pn->as<PropertyAccess>().isSuper()) {
-            if (!builder.super(&pn->pn_expr->pn_pos, &expr))
+            if (!builder.super(&pn->pn_left->pn_pos, &expr))
                 return false;
         } else {
-            if (!expression(pn->pn_expr, &expr))
+            if (!expression(pn->pn_left, &expr))
                 return false;
         }
 
diff -Nrup mozilla-OLD/js/src/frontend/BytecodeEmitter.cpp mozilla/js/src/frontend/BytecodeEmitter.cpp
--- mozilla-OLD/js/src/frontend/BytecodeEmitter.cpp	2021-12-29 03:47:40.635227075 +0300
+++ mozilla/js/src/frontend/BytecodeEmitter.cpp	2021-12-29 03:47:09.644450104 +0300
@@ -3143,7 +3143,7 @@ BytecodeEmitter::checkSideEffects(ParseN
 
       // Watch out for getters!
       case ParseNodeKind::Dot:
-        MOZ_ASSERT(pn->isArity(PN_NAME));
+        MOZ_ASSERT(pn->isArity(PN_BINARY));
         *answer = true;
         return true;
 
@@ -3388,6 +3388,14 @@ BytecodeEmitter::checkSideEffects(ParseN
       case ParseNodeKind::Call:
       case ParseNodeKind::TaggedTemplate:
       case ParseNodeKind::SuperCall:
+        MOZ_ASSERT(pn->isArity(PN_BINARY));
+        *answer = true;
+        return true;
+
+      // Function arg lists can contain arbitrary expressions. Technically
+      // this only causes side-effects if one of the arguments does, but since
+      // the call being made will always trigger side-effects, it isn't needed.
+      case ParseNodeKind::Arguments:
         MOZ_ASSERT(pn->isArity(PN_LIST));
         *answer = true;
         return true;
@@ -3533,6 +3541,7 @@ BytecodeEmitter::checkSideEffects(ParseN
       case ParseNodeKind::CallSiteObj:      // byParseNodeKind::TaggedTemplate
       case ParseNodeKind::PosHolder:        // byParseNodeKind::NewTarget
       case ParseNodeKind::SuperBase:        // byParseNodeKind::Elem and others
+      case ParseNodeKind::PropertyName:     // by ParseNodeKind::Dot
         MOZ_CRASH("handled by parent nodes");
 
       case ParseNodeKind::Limit: // invalid sentinel value
@@ -4026,11 +4035,11 @@ BytecodeEmitter::emitPropLHS(ParseNode*
     MOZ_ASSERT(pn->isKind(ParseNodeKind::Dot));
     MOZ_ASSERT(!pn->as<PropertyAccess>().isSuper());
 
-    ParseNode* pn2 = pn->pn_expr;
+    ParseNode* pn2 = pn->pn_left;
 
     /*
      * If the object operand is also a dotted property reference, reverse the
-     * list linked via pn_expr temporarily so we can iterate over it from the
+     * list linked via pn_left temporarily so we can iterate over it from the
      * bottom up (reversing again as we go), to avoid excessive recursion.
      */
     if (pn2->isKind(ParseNodeKind::Dot) && !pn2->as<PropertyAccess>().isSuper()) {
@@ -4038,9 +4047,9 @@ BytecodeEmitter::emitPropLHS(ParseNode*
         ParseNode* pnup = nullptr;
         ParseNode* pndown;
         for (;;) {
-            /* Reverse pndot->pn_expr to point up, not down. */
-            pndown = pndot->pn_expr;
-            pndot->pn_expr = pnup;
+            /* Reverse pndot->pn_left to point up, not down. */
+            pndown = pndot->pn_left;
+            pndot->pn_left = pnup;
             if (!pndown->isKind(ParseNodeKind::Dot) || pndown->as<PropertyAccess>().isSuper())
                 break;
             pnup = pndot;
@@ -4053,12 +4062,12 @@ BytecodeEmitter::emitPropLHS(ParseNode*
 
         do {
             /* Walk back up the list, emitting annotated name ops. */
-            if (!emitAtomOp(pndot, JSOP_GETPROP))
+            if (!emitAtomOp(pndot->pn_right, JSOP_GETPROP))
                 return false;
 
-            /* Reverse the pn_expr link again. */
-            pnup = pndot->pn_expr;
-            pndot->pn_expr = pndown;
+            /* Reverse the pn_left link again. */
+            pnup = pndot->pn_left;
+            pndot->pn_left = pndown;
             pndown = pndot;
         } while ((pndot = pnup) != nullptr);
         return true;
@@ -4083,7 +4092,7 @@ BytecodeEmitter::emitSuperPropLHS(ParseN
 bool
 BytecodeEmitter::emitPropOp(ParseNode* pn, JSOp op)
 {
-    MOZ_ASSERT(pn->isArity(PN_NAME));
+    MOZ_ASSERT(pn->isArity(PN_BINARY));
 
     if (!emitPropLHS(pn))
         return false;
@@ -4091,7 +4100,7 @@ BytecodeEmitter::emitPropOp(ParseNode* p
     if (op == JSOP_CALLPROP && !emit1(JSOP_DUP))
         return false;
 
-    if (!emitAtomOp(pn, op))
+    if (!emitAtomOp(pn->pn_right, op))
         return false;
 
     if (op == JSOP_CALLPROP && !emit1(JSOP_SWAP))
@@ -4107,7 +4116,7 @@ BytecodeEmitter::emitSuperPropOp(ParseNo
     if (!emitSuperPropLHS(base, isCall))
         return false;
 
-    if (!emitAtomOp(pn, op))
+    if (!emitAtomOp(pn->pn_right, op))
         return false;
 
     if (isCall && !emit1(JSOP_SWAP))
@@ -4137,7 +4146,7 @@ BytecodeEmitter::emitPropIncDec(ParseNod
         if (!emit1(JSOP_DUP))                       // OBJ OBJ
             return false;
     }
-    if (!emitAtomOp(pn->pn_kid, isSuper? JSOP_GETPROP_SUPER : JSOP_GETPROP)) // OBJ V
+    if (!emitAtomOp(pn->pn_kid->pn_right, isSuper ? JSOP_GETPROP_SUPER : JSOP_GETPROP)) // OBJ V
         return false;
     if (!emit1(JSOP_POS))                           // OBJ N
         return false;
@@ -4163,7 +4172,7 @@ BytecodeEmitter::emitPropIncDec(ParseNod
 
     JSOp setOp = isSuper ? sc->strict() ? JSOP_STRICTSETPROP_SUPER : JSOP_SETPROP_SUPER
                          : sc->strict() ? JSOP_STRICTSETPROP : JSOP_SETPROP;
-    if (!emitAtomOp(pn->pn_kid, setOp))             // N? N+1
+    if (!emitAtomOp(pn->pn_kid->pn_right, setOp))   // N? N+1
         return false;
     if (post && !emit1(JSOP_POP))                   // RESULT
         return false;
@@ -5140,7 +5149,7 @@ BytecodeEmitter::emitDestructuringLHSRef
                 return false;
             *emitted = 2;
         } else {
-            if (!emitTree(target->pn_expr))
+            if (!emitTree(target->pn_left))
                 return false;
             *emitted = 1;
         }
@@ -5258,7 +5267,7 @@ BytecodeEmitter::emitSetOrInitializeDest
                 setOp = sc->strict() ? JSOP_STRICTSETPROP_SUPER : JSOP_SETPROP_SUPER;
             else
                 setOp = sc->strict() ? JSOP_STRICTSETPROP : JSOP_SETPROP;
-            if (!emitAtomOp(target, setOp))
+            if (!emitAtomOp(target->pn_right, setOp))
                 return false;
             break;
           }
@@ -6333,11 +6342,11 @@ BytecodeEmitter::emitAssignment(ParseNod
                 return false;
             offset += 2;
         } else {
-            if (!emitTree(lhs->expr()))
+            if (!emitTree(lhs->pn_left))
                 return false;
             offset += 1;
         }
-        if (!makeAtomIndex(lhs->pn_atom, &atomIndex))
+        if (!makeAtomIndex(lhs->pn_right->pn_atom, &atomIndex))
             return false;
         break;
       case ParseNodeKind::Elem: {
@@ -6386,7 +6395,7 @@ BytecodeEmitter::emitAssignment(ParseNod
             } else {
                 if (!emit1(JSOP_DUP))
                     return false;
-                bool isLength = (lhs->pn_atom == cx->names().length);
+                bool isLength = (lhs->pn_right->pn_atom == cx->names().length);
                 getOp = isLength ? JSOP_LENGTH : JSOP_GETPROP;
             }
             if (!emitIndex32(getOp, atomIndex))
@@ -7211,7 +7220,7 @@ BytecodeEmitter::emitForOf(ParseNode* fo
     bool allowSelfHostedIter = false;
     if (emitterMode == BytecodeEmitter::SelfHosting &&
         forHeadExpr->isKind(ParseNodeKind::Call) &&
-        forHeadExpr->pn_head->name() == cx->names().allowContentIter)
+        forHeadExpr->pn_left->name() == cx->names().allowContentIter)
     {
         allowSelfHostedIter = true;
     }
@@ -9251,10 +9260,12 @@ BytecodeEmitter::emitSelfHostedCallFunct
     //
     // argc is set to the amount of actually emitted args and the
     // emitting of args below is disabled by setting emitArgs to false.
-    ParseNode* pn2 = pn->pn_head;
-    const char* errorName = SelfHostedCallFunctionName(pn2->name(), cx);
+    ParseNode* pn_callee = pn->pn_left;
+    ParseNode* pn_args = pn->pn_right;
+
+    const char* errorName = SelfHostedCallFunctionName(pn_callee->name(), cx);
 
-    if (pn->pn_count < 3) {
+    if (pn_args->pn_count < 2) {
         reportError(pn, JSMSG_MORE_ARGS_NEEDED, errorName, "2", "s");
         return false;
     }
@@ -9265,8 +9276,8 @@ BytecodeEmitter::emitSelfHostedCallFunct
         return false;
     }
 
-    bool constructing = pn2->name() == cx->names().constructContentFunction;
-    ParseNode* funNode = pn2->pn_next;
+    bool constructing = pn_callee->name() == cx->names().constructContentFunction;
+    ParseNode* funNode = pn_args->pn_head;
     if (constructing) {
         callOp = JSOP_NEW;
     } else if (funNode->getKind() == ParseNodeKind::Name &&
@@ -9279,7 +9290,7 @@ BytecodeEmitter::emitSelfHostedCallFunct
 
 #ifdef DEBUG
     if (emitterMode == BytecodeEmitter::SelfHosting &&
-        pn2->name() == cx->names().callFunction)
+        pn_callee->name() == cx->names().callFunction)
     {
         if (!emit1(JSOP_DEBUGCHECKSELFHOSTED))
             return false;
@@ -9308,7 +9319,7 @@ BytecodeEmitter::emitSelfHostedCallFunct
             return false;
     }
 
-    uint32_t argc = pn->pn_count - 3;
+    uint32_t argc = pn_args->pn_count - 2;
     if (!emitCall(callOp, argc))
         return false;
 
@@ -9319,15 +9330,15 @@ BytecodeEmitter::emitSelfHostedCallFunct
 bool
 BytecodeEmitter::emitSelfHostedResumeGenerator(ParseNode* pn)
 {
+    ParseNode* pn_args = pn->pn_right;
+
     // Syntax: resumeGenerator(gen, value, 'next'|'throw'|'close')
-    if (pn->pn_count != 4) {
+    if (pn_args->pn_count != 3) {
         reportError(pn, JSMSG_MORE_ARGS_NEEDED, "resumeGenerator", "1", "s");
         return false;
     }
 
-    ParseNode* funNode = pn->pn_head;  // The resumeGenerator node.
-
-    ParseNode* genNode = funNode->pn_next;
+    ParseNode* genNode = pn_args->pn_head;
     if (!emitTree(genNode))
         return false;
 
@@ -9359,24 +9370,26 @@ BytecodeEmitter::emitSelfHostedForceInte
 bool
 BytecodeEmitter::emitSelfHostedAllowContentIter(ParseNode* pn)
 {
-    if (pn->pn_count != 2) {
+    ParseNode* pn_args = pn->pn_right;
+
+    if (pn_args->pn_count != 1) {
         reportError(pn, JSMSG_MORE_ARGS_NEEDED, "allowContentIter", "1", "");
         return false;
     }
 
     // We're just here as a sentinel. Pass the value through directly.
-    return emitTree(pn->pn_head->pn_next);
+    return emitTree(pn_args->pn_head);
 }
 
 bool
 BytecodeEmitter::emitSelfHostedDefineDataProperty(ParseNode* pn)
 {
-    // Only optimize when 3 arguments are passed (we use 4 to include |this|).
-    MOZ_ASSERT(pn->pn_count == 4);
+    ParseNode* pn_args = pn->pn_right;
 
-    ParseNode* funNode = pn->pn_head;  // The _DefineDataProperty node.
+    // Only optimize when 3 arguments are passed.
+    MOZ_ASSERT(pn_args->pn_count == 3);
 
-    ParseNode* objNode = funNode->pn_next;
+    ParseNode* objNode = pn_args->pn_head;
     if (!emitTree(objNode))
         return false;
 
@@ -9397,14 +9410,14 @@ BytecodeEmitter::emitSelfHostedDefineDat
 bool
 BytecodeEmitter::emitSelfHostedHasOwn(ParseNode* pn)
 {
-    if (pn->pn_count != 3) {
+    ParseNode* pn_args = pn->pn_right;
+
+    if (pn_args->pn_count != 2) {
         reportError(pn, JSMSG_MORE_ARGS_NEEDED, "hasOwn", "2", "");
         return false;
     }
 
-    ParseNode* funNode = pn->pn_head;  // The hasOwn node.
-
-    ParseNode* idNode = funNode->pn_next;
+    ParseNode* idNode = pn_args->pn_head;
     if (!emitTree(idNode))
         return false;
 
@@ -9428,11 +9441,11 @@ BytecodeEmitter::isRestParameter(ParseNo
 
     if (!pn->isKind(ParseNodeKind::Name)) {
         if (emitterMode == BytecodeEmitter::SelfHosting && pn->isKind(ParseNodeKind::Call)) {
-            ParseNode* pn2 = pn->pn_head;
-            if (pn2->getKind() == ParseNodeKind::Name &&
-                pn2->name() == cx->names().allowContentIter)
+            ParseNode* pn_callee = pn->pn_left;
+            if (pn_callee->getKind() == ParseNodeKind::Name &&
+                pn_callee->name() == cx->names().allowContentIter)
             {
-                return isRestParameter(pn2->pn_next);
+                return isRestParameter(pn->pn_right->pn_head);
             }
         }
         return false;
@@ -9561,10 +9574,72 @@ BytecodeEmitter::emitPipeline(ParseNode*
 }
 
 bool
+BytecodeEmitter::emitArguments(ParseNode* pn, bool callop, bool spread)
+{
+    uint32_t argc = pn->pn_count;
+
+    if (argc >= ARGC_LIMIT) {
+        parser.reportError(callop ? JSMSG_TOO_MANY_FUN_ARGS : JSMSG_TOO_MANY_CON_ARGS);
+        return false;
+    }
+
+    if (!spread) {
+        for (ParseNode* pn3 = pn->pn_head; pn3; pn3 = pn3->pn_next) {
+            if (!emitTree(pn3))
+                return false;
+        }
+    } else {
+        ParseNode* args = pn->pn_head;
+        bool emitOptCode = (argc == 1) && isRestParameter(args->pn_kid);
+        IfThenElseEmitter ifNotOptimizable(this);
+
+        if (emitOptCode) {
+            // Emit a preparation code to optimize the spread call with a rest
+            // parameter:
+            //
+            //   function f(...args) {
+            //     g(...args);
+            //   }
+            //
+            // If the spread operand is a rest parameter and it's optimizable
+            // array, skip spread operation and pass it directly to spread call
+            // operation.  See the comment in OptimizeSpreadCall in
+            // Interpreter.cpp for the optimizable conditons.
+
+            if (!emitTree(args->pn_kid))
+                return false;
+
+            if (!emit1(JSOP_OPTIMIZE_SPREADCALL))
+                return false;
+
+            if (!emit1(JSOP_NOT))
+                return false;
+
+            if (!ifNotOptimizable.emitIf())
+                return false;
+
+            if (!emit1(JSOP_POP))
+                return false;
+        }
+
+        if (!emitArray(args, argc))
+            return false;
+
+        if (emitOptCode) {
+            if (!ifNotOptimizable.emitEnd())
+                return false;
+        }
+    }
+
+    return true;
+}
+
+bool
 BytecodeEmitter::emitCallOrNew(ParseNode* pn, ValueUsage valueUsage /* = ValueUsage::WantValue */)
 {
     bool callop =
         pn->isKind(ParseNodeKind::Call) || pn->isKind(ParseNodeKind::TaggedTemplate);
+
     /*
      * Emit callable invocation or operator new (constructor call) code.
      * First, emit code for the left operand to evaluate the callable or
@@ -9580,46 +9655,40 @@ BytecodeEmitter::emitCallOrNew(ParseNode
      * value required for calls (which non-strict mode functions
      * will box into the global object).
      */
-    uint32_t argc = pn->pn_count - 1;
+    ParseNode* pn_callee = pn->pn_left;
+    ParseNode* pn_args = pn->pn_right;
 
-    if (argc >= ARGC_LIMIT) {
-        parser.reportError(callop ? JSMSG_TOO_MANY_FUN_ARGS : JSMSG_TOO_MANY_CON_ARGS);
-        return false;
-    }
-
-    ParseNode* pn2 = pn->pn_head;
     bool spread = JOF_OPTYPE(pn->getOp()) == JOF_BYTE;
 
-    if (pn2->isKind(ParseNodeKind::Name) && emitterMode == BytecodeEmitter::SelfHosting && !spread) {
+    if (pn_callee->isKind(ParseNodeKind::Name) && emitterMode == BytecodeEmitter::SelfHosting && !spread) {
         // Calls to "forceInterpreter", "callFunction",
         // "callContentFunction", or "resumeGenerator" in self-hosted
         // code generate inline bytecode.
-        if (pn2->name() == cx->names().callFunction ||
-            pn2->name() == cx->names().callContentFunction ||
-            pn2->name() == cx->names().constructContentFunction)
+        if (pn_callee->name() == cx->names().callFunction ||
+            pn_callee->name() == cx->names().callContentFunction ||
+            pn_callee->name() == cx->names().constructContentFunction)
         {
             return emitSelfHostedCallFunction(pn);
         }
-        if (pn2->name() == cx->names().resumeGenerator)
+        if (pn_callee->name() == cx->names().resumeGenerator)
             return emitSelfHostedResumeGenerator(pn);
-        if (pn2->name() == cx->names().forceInterpreter)
+        if (pn_callee->name() == cx->names().forceInterpreter)
             return emitSelfHostedForceInterpreter(pn);
-        if (pn2->name() == cx->names().allowContentIter)
+        if (pn_callee->name() == cx->names().allowContentIter)
             return emitSelfHostedAllowContentIter(pn);
-        if (pn2->name() == cx->names().defineDataPropertyIntrinsic && pn->pn_count == 4)
+        if (pn_callee->name() == cx->names().defineDataPropertyIntrinsic && pn_args->pn_count == 3)
             return emitSelfHostedDefineDataProperty(pn);
-        if (pn2->name() == cx->names().hasOwn)
+        if (pn_callee->name() == cx->names().hasOwn)
             return emitSelfHostedHasOwn(pn);
         // Fall through
     }
 
-    if (!emitCallee(pn2, pn, spread, &callop))
+    if (!emitCallee(pn_callee, pn, false, &callop))
         return false;
 
     bool isNewOp = pn->getOp() == JSOP_NEW || pn->getOp() == JSOP_SPREADNEW ||
                    pn->getOp() == JSOP_SUPERCALL || pn->getOp() == JSOP_SPREADSUPERCALL;
 
-
     // Emit room for |this|.
     if (!callop) {
         if (isNewOp) {
@@ -9631,91 +9700,77 @@ BytecodeEmitter::emitCallOrNew(ParseNode
         }
     }
 
+    if (!emitArguments(pn_args, callop, spread))
+        return false;
+
+    uint32_t argc = pn_args->pn_count;
+
     /*
      * Emit code for each argument in order, then emit the JSOP_*CALL or
      * JSOP_NEW bytecode with a two-byte immediate telling how many args
      * were pushed on the operand stack.
      */
-    if (!spread) {
-        for (ParseNode* pn3 = pn2->pn_next; pn3; pn3 = pn3->pn_next) {
-            if (!emitTree(pn3))
-                return false;
-        }
-
-        if (isNewOp) {
-            if (pn->isKind(ParseNodeKind::SuperCall)) {
-                if (!emit1(JSOP_NEWTARGET))
-                    return false;
-            } else {
-                // Repush the callee as new.target
-                if (!emitDupAt(argc + 1))
-                    return false;
-            }
-        }
-    } else {
-        ParseNode* args = pn2->pn_next;
-        bool emitOptCode = (argc == 1) && isRestParameter(args->pn_kid);
-        IfThenElseEmitter ifNotOptimizable(this);
-
-        if (emitOptCode) {
-            // Emit a preparation code to optimize the spread call with a rest
-            // parameter:
-            //
-            //   function f(...args) {
-            //     g(...args);
-            //   }
-            //
-            // If the spread operand is a rest parameter and it's optimizable
-            // array, skip spread operation and pass it directly to spread call
-            // operation.  See the comment in OptimizeSpreadCall in
-            // Interpreter.cpp for the optimizable conditons.
-
-            if (!emitTree(args->pn_kid))
-                return false;
-
-            if (!emit1(JSOP_OPTIMIZE_SPREADCALL))
-                return false;
-
-            if (!emit1(JSOP_NOT))
+    if (isNewOp) {
+        if (pn->isKind(ParseNodeKind::SuperCall)) {
+            if (!emit1(JSOP_NEWTARGET))
                 return false;
-
-            if (!ifNotOptimizable.emitIf())
+        } else if (!spread) {
+            // Repush the callee as new.target
+            if (!emitDupAt(argc + 1))
                 return false;
-
-            if (!emit1(JSOP_POP))
+        } else {
+            if (!emitDupAt(2))
                 return false;
         }
+    }
 
-        if (!emitArray(args, argc))
-            return false;
-
-        if (emitOptCode) {
-            if (!ifNotOptimizable.emitEnd())
-                return false;
-        }
+    ParseNode* coordNode = pn;
+    if (pn->isOp(JSOP_CALL) || pn->isOp(JSOP_SPREADCALL) || pn->isOp(JSOP_FUNCALL) ||
+        pn->isOp(JSOP_FUNAPPLY)) {
+        // Default to using the location of the `(` itself.
+        // obj[expr]() // expression
+        //          ^  // column coord
+        coordNode = pn_args;
 
-        if (isNewOp) {
-            if (pn->isKind(ParseNodeKind::SuperCall)) {
-                if (!emit1(JSOP_NEWTARGET))
-                    return false;
-            } else {
-                if (!emitDupAt(2))
-                    return false;
-            }
+        switch (pn_callee->getKind()) {
+          case ParseNodeKind::Dot:
+            // Use the position of a property access identifier.
+            //
+            // obj().aprop() // expression
+            //       ^       // column coord
+            //
+            // Note: Because of the constant folding logic in FoldElement,
+            // this case also applies for constant string properties.
+            //
+            // obj()['aprop']() // expression
+            //       ^          // column coord
+            coordNode = pn_callee->pn_right;
+            break;
+          case ParseNodeKind::Name:
+            // Use the start of callee names.
+            coordNode = pn_callee;
+            break;
+          default:
+            break;
         }
     }
 
     if (!spread) {
         if (pn->getOp() == JSOP_CALL && valueUsage == ValueUsage::IgnoreValue) {
-            if (!emitCall(JSOP_CALL_IGNORES_RV, argc, pn))
+            if (!emitCall(JSOP_CALL_IGNORES_RV, argc, coordNode))
                 return false;
             checkTypeSet(JSOP_CALL_IGNORES_RV);
         } else {
-            if (!emitCall(pn->getOp(), argc, pn))
+            if (!emitCall(pn->getOp(), argc, coordNode))
                 return false;
             checkTypeSet(pn->getOp());
         }
     } else {
+        if (coordNode) {
+            if (!updateSourceCoordNotes(coordNode->pn_pos.begin))
+                return false;
+        }
+
         if (!emit1(pn->getOp()))
             return false;
         checkTypeSet(pn->getOp());
@@ -10331,7 +10386,7 @@ BytecodeEmitter::emitArray(ParseNode* pn
 
                 if (emitterMode == BytecodeEmitter::SelfHosting &&
                     expr->isKind(ParseNodeKind::Call) &&
-                    expr->pn_head->name() == cx->names().allowContentIter)
+                    expr->pn_left->name() == cx->names().allowContentIter)
                 {
                     allowSelfHostedIter = true;
                 }
@@ -11394,8 +11449,9 @@ BytecodeEmitter::emitTree(ParseNode* pn,
             return false;
         break;
 
+      case ParseNodeKind::PropertyName:
       case ParseNodeKind::PosHolder:
-        MOZ_FALLTHROUGH_ASSERT("Should never try to emitParseNodeKind::PosHolder");
+        MOZ_FALLTHROUGH_ASSERT("Should never try to emit ParseNodeKind::PosHolder or ::Property");
 
       default:
         MOZ_ASSERT(0);
diff -Nrup mozilla-OLD/js/src/frontend/BytecodeEmitter.h mozilla/js/src/frontend/BytecodeEmitter.h
--- mozilla-OLD/js/src/frontend/BytecodeEmitter.h	2021-12-29 03:47:40.636227068 +0300
+++ mozilla/js/src/frontend/BytecodeEmitter.h	2021-12-29 03:47:09.645450097 +0300
@@ -815,6 +815,7 @@ struct MOZ_STACK_CLASS BytecodeEmitter
 
     bool isRestParameter(ParseNode* pn);
 
+    MOZ_MUST_USE bool emitArguments(ParseNode* pn, bool callop, bool spread);
     MOZ_MUST_USE bool emitCallOrNew(ParseNode* pn, ValueUsage valueUsage = ValueUsage::WantValue);
     MOZ_MUST_USE bool emitSelfHostedCallFunction(ParseNode* pn);
     MOZ_MUST_USE bool emitSelfHostedResumeGenerator(ParseNode* pn);
diff -Nrup mozilla-OLD/js/src/frontend/FoldConstants.cpp mozilla/js/src/frontend/FoldConstants.cpp
--- mozilla-OLD/js/src/frontend/FoldConstants.cpp	2021-12-29 03:47:40.636227068 +0300
+++ mozilla/js/src/frontend/FoldConstants.cpp	2021-12-29 03:37:16.058713948 +0300
@@ -363,8 +363,10 @@ ContainsHoistedDeclaration(JSContext* cx
       case ParseNodeKind::Comma:
       case ParseNodeKind::Array:
       case ParseNodeKind::Object:
+      case ParseNodeKind::PropertyName:
       case ParseNodeKind::Dot:
       case ParseNodeKind::Elem:
+      case ParseNodeKind::Arguments:
       case ParseNodeKind::Call:
       case ParseNodeKind::Name:
       case ParseNodeKind::TemplateString:
@@ -1316,7 +1318,10 @@ FoldElement(JSContext* cx, ParseNode** n
 
     // Optimization 3: We have expr["foo"] where foo is not an index.  Convert
     // to a property access (like expr.foo) that optimizes better downstream.
-    ParseNode* dottedAccess = parser.handler.newPropertyAccess(expr, name, node->pn_pos.end);
+    ParseNode* nameNode = parser.handler.newPropertyName(name, key->pn_pos);
+    if (!nameNode)
+        return false;
+    ParseNode* dottedAccess = parser.handler.newPropertyAccess(expr, nameNode);
     if (!dottedAccess)
         return false;
     dottedAccess->setInParens(node->isInParens());
@@ -1474,8 +1479,9 @@ FoldCall(JSContext* cx, ParseNode* node,
 {
     MOZ_ASSERT(node->isKind(ParseNodeKind::Call) ||
                node->isKind(ParseNodeKind::SuperCall) ||
+               node->isKind(ParseNodeKind::New) ||
                node->isKind(ParseNodeKind::TaggedTemplate));
-    MOZ_ASSERT(node->isArity(PN_LIST));
+    MOZ_ASSERT(node->isArity(PN_BINARY));
 
     // Don't fold a parenthesized callable component in an invocation, as this
     // might cause a different |this| value to be used, changing semantics:
@@ -1488,10 +1494,27 @@ FoldCall(JSContext* cx, ParseNode* node,
     //   assertEq(obj.f``, "obj");
     //
     // See bug 537673 and bug 1182373.
-    ParseNode** listp = &node->pn_head;
-    if ((*listp)->isInParens())
-        listp = &(*listp)->pn_next;
+    ParseNode** pn_callee = &node->pn_left;
+    if (node->isKind(ParseNodeKind::New) || !(*pn_callee)->isInParens()) {
+        if (!Fold(cx, pn_callee, parser, inGenexpLambda))
+            return false;
+    }
 
+    ParseNode** pn_args = &node->pn_right;
+    if (!Fold(cx, pn_args, parser, inGenexpLambda))
+        return false;
+
+    return true;
+}
+
+static bool
+FoldArguments(JSContext* cx, ParseNode* node, Parser<FullParseHandler, char16_t>& parser,
+              bool inGenexpLambda)
+{
+    MOZ_ASSERT(node->isKind(ParseNodeKind::Arguments));
+    MOZ_ASSERT(node->isArity(PN_LIST));
+
+    ParseNode** listp = &node->pn_head;
     for (; *listp; listp = &(*listp)->pn_next) {
         if (!Fold(cx, listp, parser, inGenexpLambda))
             return false;
@@ -1550,14 +1573,14 @@ FoldDottedProperty(JSContext* cx, ParseN
                    bool inGenexpLambda)
 {
     MOZ_ASSERT(node->isKind(ParseNodeKind::Dot));
-    MOZ_ASSERT(node->isArity(PN_NAME));
+    MOZ_ASSERT(node->isArity(PN_BINARY));
 
     // Iterate through a long chain of dotted property accesses to find the
     // most-nested non-dotted property node, then fold that.
-    ParseNode** nested = &node->pn_expr;
+    ParseNode** nested = &node->pn_left;
     while ((*nested)->isKind(ParseNodeKind::Dot)) {
-        MOZ_ASSERT((*nested)->isArity(PN_NAME));
-        nested = &(*nested)->pn_expr;
+        MOZ_ASSERT((*nested)->isArity(PN_BINARY));
+        nested = &(*nested)->pn_left;
     }
 
     return Fold(cx, nested, parser, inGenexpLambda);
@@ -1714,7 +1737,6 @@ Fold(JSContext* cx, ParseNode** pnp, Par
       case ParseNodeKind::InstanceOf:
       case ParseNodeKind::In:
       case ParseNodeKind::Comma:
-      case ParseNodeKind::New:
       case ParseNodeKind::Array:
       case ParseNodeKind::Object:
       case ParseNodeKind::ArrayComp:
@@ -1768,10 +1790,14 @@ Fold(JSContext* cx, ParseNode** pnp, Par
         return FoldAdd(cx, pnp, parser, inGenexpLambda);
 
       case ParseNodeKind::Call:
+      case ParseNodeKind::New:
       case ParseNodeKind::SuperCall:
       case ParseNodeKind::TaggedTemplate:
         return FoldCall(cx, pn, parser, inGenexpLambda);
 
+      case ParseNodeKind::Arguments:
+        return FoldArguments(cx, pn, parser, inGenexpLambda);
+
       case ParseNodeKind::Switch:
       case ParseNodeKind::Colon:
       case ParseNodeKind::Assign:
@@ -1851,6 +1877,9 @@ Fold(JSContext* cx, ParseNode** pnp, Par
         MOZ_ASSERT(pn->isArity(PN_NAME));
         return Fold(cx, &pn->pn_expr, parser, inGenexpLambda);
 
+      case ParseNodeKind::PropertyName:
+        MOZ_CRASH("unreachable, handled by ::Dot");
+
       case ParseNodeKind::Dot:
         return FoldDottedProperty(cx, pn, parser, inGenexpLambda);
 
diff -Nrup mozilla-OLD/js/src/frontend/FullParseHandler.h mozilla/js/src/frontend/FullParseHandler.h
--- mozilla-OLD/js/src/frontend/FullParseHandler.h	2021-12-29 03:47:40.637227061 +0300
+++ mozilla/js/src/frontend/FullParseHandler.h	2021-12-29 03:37:16.058713948 +0300
@@ -285,16 +285,20 @@ class FullParseHandler
         literal->append(element);
     }
 
-    ParseNode* newCall(const TokenPos& pos) {
-        return new_<ListNode>(ParseNodeKind::Call, JSOP_CALL, pos);
+    ParseNode* newCall(ParseNode* callee, ParseNode* args) {
+        return new_<BinaryNode>(ParseNodeKind::Call, JSOP_CALL, callee, args);
     }
 
-    ParseNode* newSuperCall(ParseNode* callee) {
-        return new_<ListNode>(ParseNodeKind::SuperCall, JSOP_SUPERCALL, callee);
+    ParseNode* newArguments(const TokenPos& pos) {
+        return new_<ListNode>(ParseNodeKind::Arguments, JSOP_NOP, pos);
     }
 
-    ParseNode* newTaggedTemplate(const TokenPos& pos) {
-        return new_<ListNode>(ParseNodeKind::TaggedTemplate, JSOP_CALL, pos);
+    ParseNode* newSuperCall(ParseNode* callee, ParseNode* args) {
+        return new_<BinaryNode>(ParseNodeKind::SuperCall, JSOP_SUPERCALL, callee, args);
+    }
+
+    ParseNode* newTaggedTemplate(ParseNode* tag, ParseNode* args) {
+        return new_<BinaryNode>(ParseNodeKind::TaggedTemplate, JSOP_CALL, tag, args);
     }
 
     ParseNode* newObjectLiteral(uint32_t begin) {
@@ -669,8 +673,12 @@ class FullParseHandler
         return new_<DebuggerStatement>(pos);
     }
 
-    ParseNode* newPropertyAccess(ParseNode* pn, PropertyName* name, uint32_t end) {
-        return new_<PropertyAccess>(pn, name, pn->pn_pos.begin, end);
+    ParseNode* newPropertyName(PropertyName* name, const TokenPos& pos) {
+        return new_<NameNode>(ParseNodeKind::PropertyName, JSOP_NOP, name, pos);
+    }
+
+    ParseNode* newPropertyAccess(ParseNode* expr, ParseNode* key) {
+        return new_<PropertyAccess>(expr, key, expr->pn_pos.begin, key->pn_pos.end);
     }
 
     ParseNode* newPropertyByValue(ParseNode* lhs, ParseNode* index, uint32_t end) {
@@ -744,13 +752,8 @@ class FullParseHandler
         return new_<LexicalScopeNode>(bindings, body);
     }
 
-    Node newNewExpression(uint32_t begin, ParseNode* ctor) {
-        ParseNode* newExpr = new_<ListNode>(ParseNodeKind::New, JSOP_NEW, TokenPos(begin, begin + 1));
-        if (!newExpr)
-            return nullptr;
-
-        addList(newExpr, ctor);
-        return newExpr;
+    Node newNewExpression(uint32_t begin, ParseNode* ctor, ParseNode* args) {
+        return new_<BinaryNode>(ParseNodeKind::New, JSOP_NEW, TokenPos(begin, args->pn_pos.end), ctor, args);
     }
 
     ParseNode* newAssignment(ParseNodeKind kind, ParseNode* lhs, ParseNode* rhs) {
diff -Nrup mozilla-OLD/js/src/frontend/NameFunctions.cpp mozilla/js/src/frontend/NameFunctions.cpp
--- mozilla-OLD/js/src/frontend/NameFunctions.cpp	2021-12-29 03:47:40.638227054 +0300
+++ mozilla/js/src/frontend/NameFunctions.cpp	2021-12-29 03:37:16.059713941 +0300
@@ -77,11 +77,11 @@ class NameResolver
     bool nameExpression(ParseNode* n, bool* foundName) {
         switch (n->getKind()) {
           case ParseNodeKind::Dot:
-            if (!nameExpression(n->expr(), foundName))
+            if (!nameExpression(n->pn_left, foundName))
                 return false;
             if (!*foundName)
                 return true;
-            return appendPropertyReference(n->pn_atom);
+            return appendPropertyReference(n->pn_right->pn_atom);
 
           case ParseNodeKind::Name:
             *foundName = true;
@@ -313,17 +313,17 @@ class NameResolver
     bool resolveTaggedTemplate(ParseNode* node, HandleAtom prefix) {
         MOZ_ASSERT(node->isKind(ParseNodeKind::TaggedTemplate));
 
-        ParseNode* element = node->pn_head;
+        ParseNode* tag = node->pn_left;
 
-        // The list head is a leading expression, e.g. |tag| in |tag`foo`|,
+        // The leading expression, e.g. |tag| in |tag`foo`|,
         // that might contain functions.
-        if (!resolve(element, prefix))
+        if (!resolve(tag, prefix))
             return false;
 
-        // Next is the callsite object node.  This node only contains
+        // The callsite object node is first.  This node only contains
         // internal strings or undefined and an array -- no user-controlled
         // expressions.
-        element = element->pn_next;
+        ParseNode* element = node->pn_right->pn_head;
 #ifdef DEBUG
         {
             MOZ_ASSERT(element->isKind(ParseNodeKind::CallSiteObj));
@@ -701,9 +701,6 @@ class NameResolver
           case ParseNodeKind::Pow:
           case ParseNodeKind::Pipeline:
           case ParseNodeKind::Comma:
-          case ParseNodeKind::New:
-          case ParseNodeKind::Call:
-          case ParseNodeKind::SuperCall:
           case ParseNodeKind::GenExp:
           case ParseNodeKind::Array:
           case ParseNodeKind::StatementList:
@@ -751,11 +748,32 @@ class NameResolver
             break;
 
           case ParseNodeKind::TaggedTemplate:
-            MOZ_ASSERT(cur->isArity(PN_LIST));
+            MOZ_ASSERT(cur->isArity(PN_BINARY));
             if (!resolveTaggedTemplate(cur, prefix))
                 return false;
             break;
 
+          case ParseNodeKind::New:
+          case ParseNodeKind::Call:
+          case ParseNodeKind::SuperCall:
+            MOZ_ASSERT(cur->isArity(PN_BINARY));
+            if (!resolve(cur->pn_left, prefix))
+                return false;
+            if (!resolve(cur->pn_right, prefix))
+                return false;
+            break;
+
+          // Handles the arguments for new/call/supercall, but does _not_ handle
+          // the Arguments node used by tagged template literals, since that is
+          // special-cased inside of resolveTaggedTemplate.
+          case ParseNodeKind::Arguments:
+            MOZ_ASSERT(cur->isArity(PN_LIST));
+            for (ParseNode* element = cur->pn_head; element; element = element->pn_next) {
+                if (!resolve(element, prefix))
+                    return false;
+            }
+            break;
+
           // Import/export spec lists contain import/export specs containing
           // only pairs of names. Alternatively, an export spec lists may
           // contain a single export batch specifier.
@@ -784,12 +802,12 @@ class NameResolver
           }
 
           case ParseNodeKind::Dot:
-            MOZ_ASSERT(cur->isArity(PN_NAME));
+            MOZ_ASSERT(cur->isArity(PN_BINARY));
 
             // Super prop nodes do not have a meaningful LHS
             if (cur->as<PropertyAccess>().isSuper())
                 break;
-            if (!resolve(cur->expr(), prefix))
+            if (!resolve(cur->pn_left, prefix))
                 return false;
             break;
 
@@ -824,6 +842,7 @@ class NameResolver
           case ParseNodeKind::ExportSpec: // by ParseNodeKind::ExportSpecList
           case ParseNodeKind::CallSiteObj: // by ParseNodeKind::TaggedTemplate
           case ParseNodeKind::ClassNames:  // by ParseNodeKind::Class
+          case ParseNodeKind::PropertyName:  // by ParseNodeKind::Dot
             MOZ_CRASH("should have been handled by a parent node");
 
           case ParseNodeKind::Limit: // invalid sentinel value
diff -Nrup mozilla-OLD/js/src/frontend/ParseNode.cpp mozilla/js/src/frontend/ParseNode.cpp
--- mozilla-OLD/js/src/frontend/ParseNode.cpp	2021-12-29 03:47:40.638227054 +0300
+++ mozilla/js/src/frontend/ParseNode.cpp	2021-12-29 03:37:16.060713934 +0300
@@ -214,6 +214,21 @@ UnaryNode::dump(GenericPrinter& out, int
 void
 BinaryNode::dump(GenericPrinter& out, int indent)
 {
+    if (isKind(ParseNodeKind::Dot)) {
+        out.put("(.");
+
+        DumpParseTree(pn_right, out, indent + 2);
+
+        out.putChar(' ');
+        if (as<PropertyAccess>().isSuper())
+            out.put("super");
+        else
+            DumpParseTree(pn_left, out, indent + 2);
+
+        out.printf(")");
+        return;
+    }
+
     const char* name = parseNodeNames[size_t(getKind())];
     out.printf("(%s ", name);
     indent += strlen(name) + 2;
@@ -286,10 +301,7 @@ DumpName(GenericPrinter& out, const Char
 void
 NameNode::dump(GenericPrinter& out, int indent)
 {
-    if (isKind(ParseNodeKind::Name) || isKind(ParseNodeKind::Dot)) {
-        if (isKind(ParseNodeKind::Dot))
-            out.put("(.");
-
+    if (isKind(ParseNodeKind::Name) || isKind(ParseNodeKind::PropertyName)) {
         if (!pn_atom) {
             out.put("#<null name>");
         } else if (getOp() == JSOP_GETARG && pn_atom->length() == 0) {
@@ -304,15 +316,6 @@ NameNode::dump(GenericPrinter& out, int
             else
                 DumpName(out, pn_atom->twoByteChars(nogc), pn_atom->length());
         }
-
-        if (isKind(ParseNodeKind::Dot)) {
-            out.putChar(' ');
-            if (as<PropertyAccess>().isSuper())
-                out.put("super");
-            else
-                DumpParseTree(expr(), out, indent + 2);
-            out.printf(")");
-        }
         return;
     }
 
diff -Nrup mozilla-OLD/js/src/frontend/ParseNode.h mozilla/js/src/frontend/ParseNode.h
--- mozilla-OLD/js/src/frontend/ParseNode.h	2021-12-29 03:47:40.639227047 +0300
+++ mozilla/js/src/frontend/ParseNode.h	2021-12-29 03:37:16.060713934 +0300
@@ -34,6 +34,7 @@ class ObjectBox;
     F(PostIncrement) \
     F(PreDecrement) \
     F(PostDecrement) \
+    F(PropertyName) \
     F(Dot) \
     F(Elem) \
     F(Array) \
@@ -42,6 +43,7 @@ class ObjectBox;
     F(Label) \
     F(Object) \
     F(Call) \
+    F(Arguments) \
     F(Name) \
     F(ObjectPropertyName) \
     F(ComputedName) \
@@ -366,9 +368,8 @@ IsTypeofKind(ParseNodeKind kind)
  * PostIncrement,
  * PreDecrement,
  * PostDecrement
- * New      list        pn_head: list of ctor, arg1, arg2, ... argN
- *                          pn_count: 1 + N (where N is number of args)
- *                          ctor is a MEMBER expr
+ * New      binary      pn_left: ctor expression on the left of the (
+ *                          pn_right: Arguments
  * DeleteName unary     pn_kid: Name expr
  * DeleteProp unary     pn_kid: Dot expr
  * DeleteElem unary     pn_kid: Elem expr
@@ -377,13 +378,15 @@ IsTypeofKind(ParseNodeKind kind)
  *                          for a more-specific PNK_DELETE* unless constant
  *                          folding (or a similar parse tree manipulation) has
  *                          occurred
- * Dot      name        pn_expr: MEMBER expr to left of .
- *                          pn_atom: name to right of .
+ * PropertyName name    pn_atom: property name being accessed
+ * Dot      binary      pn_left: MEMBER expr to left of .
+ *                          pn_right: PropertyName to right of .
  * Elem     binary      pn_left: MEMBER expr to left of [
  *                          pn_right: expr between [ and ]
- * Call     list        pn_head: list of call, arg1, arg2, ... argN
- *                          pn_count: 1 + N (where N is number of args)
- *                          call is a MEMBER expr naming a callable object
+ * Call     binary      pn_left: callee expression on the left of the (
+ *                          pn_right: Arguments
+ * Arguments list       pn_head: list of arg1, arg2, ... argN
+ *                          pn_count: N (where N is number of args)
  * GenExp   list        Exactly like Call, used for the implicit call
  *                          in the desugaring of a generator-expression.
  * Array    list        pn_head: list of pn_count array element exprs
@@ -405,8 +408,9 @@ IsTypeofKind(ParseNodeKind kind)
  *              list
  * TemplateString      pn_atom: template string atom
                 nullary     pn_op: JSOP_NOP
- * TaggedTemplate      pn_head: list of call, call site object, arg1, arg2, ... argN
- *              list        pn_count: 2 + N (N is the number of substitutions)
+ * TaggedTemplate      pn_left: tag expression
+ *              binary       pn_right: Arguments, with the first being the
+ *                           call site object, then arg1, arg2, ... argN
  * CallSiteObj list     pn_head: a Array node followed by
  *                          list of pn_count - 1 TemplateString nodes
  * RegExp   nullary     pn_objbox: RegExp model object
@@ -418,7 +422,7 @@ IsTypeofKind(ParseNodeKind kind)
  *
  * This,        unary   pn_kid: '.this' Name if function `this`, else nullptr
  * SuperBase    unary   pn_kid: '.this' Name
- *
+ * SuperCall    binary  pn_left: SuperBase pn_right: Arguments
  * SetThis      binary  pn_left: '.this' Name, pn_right: SuperCall
  *
  * LexicalScope scope   pn_u.scope.bindings: scope bindings
@@ -573,8 +577,7 @@ class ParseNode
                 FunctionBox* funbox;    /* function object */
             };
             ParseNode*  expr;           /* module or function body, var
-                                           initializer, argument default, or
-                                           base object of ParseNodeKind::Dot */
+                                           initializer, or argument default */
         } name;
         struct {
             LexicalScope::Data* bindings;
@@ -1194,30 +1197,33 @@ class RegExpLiteral : public NullaryNode
     }
 };
 
-class PropertyAccess : public ParseNode
+class PropertyAccess : public BinaryNode
 {
   public:
-    PropertyAccess(ParseNode* lhs, PropertyName* name, uint32_t begin, uint32_t end)
-      : ParseNode(ParseNodeKind::Dot, JSOP_NOP, PN_NAME, TokenPos(begin, end))
+    /*
+     * PropertyAccess nodes can have any expression/'super' as left-hand
+     * side, but the name must be a ParseNodeKind::PropertyName node.
+     */
+    PropertyAccess(ParseNode* lhs, ParseNode* name, uint32_t begin, uint32_t end)
+      : BinaryNode(ParseNodeKind::Dot, JSOP_NOP, TokenPos(begin, end), lhs, name)
     {
         MOZ_ASSERT(lhs != nullptr);
         MOZ_ASSERT(name != nullptr);
-        pn_u.name.expr = lhs;
-        pn_u.name.atom = name;
     }
 
     static bool test(const ParseNode& node) {
         bool match = node.isKind(ParseNodeKind::Dot);
-        MOZ_ASSERT_IF(match, node.isArity(PN_NAME));
+        MOZ_ASSERT_IF(match, node.isArity(PN_BINARY));
+        MOZ_ASSERT_IF(match, node.pn_right->isKind(ParseNodeKind::PropertyName));
         return match;
     }
 
     ParseNode& expression() const {
-        return *pn_u.name.expr;
+        return *pn_u.binary.left;
     }
 
     PropertyName& name() const {
-        return *pn_u.name.atom->asPropertyName();
+        return *pn_u.binary.right->pn_atom->asPropertyName();
     }
 
     bool isSuper() const {
diff -Nrup mozilla-OLD/js/src/frontend/Parser.cpp mozilla/js/src/frontend/Parser.cpp
--- mozilla-OLD/js/src/frontend/Parser.cpp	2021-12-29 03:47:40.641227032 +0300
+++ mozilla/js/src/frontend/Parser.cpp	2021-12-29 03:37:16.063713912 +0300
@@ -3348,13 +3348,13 @@ Parser<ParseHandler, CharT>::addExprAndG
 
 template <class ParseHandler, typename CharT>
 bool
-Parser<ParseHandler, CharT>::taggedTemplate(YieldHandling yieldHandling, Node nodeList,
+Parser<ParseHandler, CharT>::taggedTemplate(YieldHandling yieldHandling, Node tagArgsList,
                                             TokenKind tt)
 {
     Node callSiteObjNode = handler.newCallSiteObject(pos().begin);
     if (!callSiteObjNode)
         return false;
-    handler.addList(nodeList, callSiteObjNode);
+    handler.addList(tagArgsList, callSiteObjNode);
 
     while (true) {
         if (!appendToCallSiteObj(callSiteObjNode))
@@ -3362,10 +3362,10 @@ Parser<ParseHandler, CharT>::taggedTempl
         if (tt != TOK_TEMPLATE_HEAD)
             break;
 
-        if (!addExprAndGetNextTemplStrToken(yieldHandling, nodeList, &tt))
+        if (!addExprAndGetNextTemplStrToken(yieldHandling, tagArgsList, &tt))
             return false;
     }
-    handler.setEndPosition(nodeList, callSiteObjNode);
+    handler.setEndPosition(tagArgsList, callSiteObjNode);
     return true;
 }
 
@@ -8855,24 +8855,27 @@ Parser<ParseHandler, CharT>::assignExprW
 }
 
 template <class ParseHandler, typename CharT>
-bool
-Parser<ParseHandler, CharT>::argumentList(YieldHandling yieldHandling, Node listNode,
-                                          bool* isSpread,
+typename ParseHandler::Node
+Parser<ParseHandler, CharT>::argumentList(YieldHandling yieldHandling, bool* isSpread,
                                           PossibleError* possibleError /* = nullptr */)
 {
+    Node argsList = handler.newArguments(pos());
+    if (!argsList)
+        return null();
+
     bool matched;
     if (!tokenStream.matchToken(&matched, TOK_RP, TokenStream::Operand))
-        return false;
+        return null();
     if (matched) {
-        handler.setEndPosition(listNode, pos().end);
-        return true;
+        handler.setEndPosition(argsList, pos().end);
+        return argsList;
     }
 
     while (true) {
         bool spread = false;
         uint32_t begin = 0;
         if (!tokenStream.matchToken(&matched, TOK_TRIPLEDOT, TokenStream::Operand))
-            return false;
+            return null();
         if (matched) {
             spread = true;
             begin = pos().begin;
@@ -8881,18 +8884,18 @@ Parser<ParseHandler, CharT>::argumentLis
 
         Node argNode = assignExpr(InAllowed, yieldHandling, TripledotProhibited, possibleError);
         if (!argNode)
-            return false;
+            return null();
         if (spread) {
             argNode = handler.newSpread(begin, argNode);
             if (!argNode)
-                return false;
+                return null();
         }
 
-        handler.addList(listNode, argNode);
+        handler.addList(argsList, argNode);
 
         bool matched;
         if (!tokenStream.matchToken(&matched, TOK_COMMA, TokenStream::Operand))
-            return false;
+            return null();
         if (!matched)
             break;
 
@@ -8905,8 +8908,8 @@ Parser<ParseHandler, CharT>::argumentLis
 
     MUST_MATCH_TOKEN_MOD(TOK_RP, TokenStream::Operand, JSMSG_PAREN_AFTER_ARGS);
 
-    handler.setEndPosition(listNode, pos().end);
-    return true;
+    handler.setEndPosition(argsList, pos().end);
+    return argsList;
 }
 
 template <class ParseHandler, typename CharT>
@@ -8952,20 +8955,27 @@ Parser<ParseHandler, CharT>::memberExpr(
             if (!ctorExpr)
                 return null();
 
-            lhs = handler.newNewExpression(newBegin, ctorExpr);
-            if (!lhs)
-                return null();
-
             bool matched;
             if (!tokenStream.matchToken(&matched, TOK_LP))
                 return null();
+
+            bool isSpread = false;
+            Node args;
             if (matched) {
-                bool isSpread = false;
-                if (!argumentList(yieldHandling, lhs, &isSpread))
-                    return null();
-                if (isSpread)
-                    handler.setOp(lhs, JSOP_SPREADNEW);
+                args = argumentList(yieldHandling, &isSpread);
+            } else {
+                args = handler.newArguments(pos());
             }
+
+            if (!args)
+                return null();
+
+            lhs = handler.newNewExpression(newBegin, ctorExpr, args);
+            if (!lhs)
+                return null();
+
+            if (isSpread)
+                handler.setOp(lhs, JSOP_SPREADNEW);
         }
     } else if (tt == TOK_SUPER) {
         Node thisName = newThisName();
@@ -8998,7 +9008,12 @@ Parser<ParseHandler, CharT>::memberExpr(
                     error(JSMSG_BAD_SUPERPROP, "property");
                     return null();
                 }
-                nextMember = handler.newPropertyAccess(lhs, field, pos().end);
+
+                Node name = handler.newPropertyName(field, pos());
+                if (!name)
+                    return null();
+
+                nextMember = handler.newPropertyAccess(lhs, name);
                 if (!nextMember)
                     return null();
             } else {
@@ -9034,15 +9049,16 @@ Parser<ParseHandler, CharT>::memberExpr(
                     return null();
                 }
 
-                nextMember = handler.newSuperCall(lhs);
-                if (!nextMember)
-                    return null();
-
                 // Despite the fact that it's impossible to have |super()| in a
                 // generator, we still inherit the yieldHandling of the
                 // memberExpression, per spec. Curious.
                 bool isSpread = false;
-                if (!argumentList(yieldHandling, nextMember, &isSpread))
+                Node args = argumentList(yieldHandling, &isSpread);
+                if (!args)
+                    return null();
+
+                nextMember = handler.newSuperCall(lhs, args);
+                if (!nextMember)
                     return null();
 
                 if (isSpread)
@@ -9061,13 +9077,6 @@ Parser<ParseHandler, CharT>::memberExpr(
                     return null();
                 }
 
-                TokenPos nextMemberPos = pos();
-                nextMember = tt == TOK_LP
-                             ? handler.newCall(nextMemberPos)
-                             : handler.newTaggedTemplate(nextMemberPos);
-                if (!nextMember)
-                    return null();
-
                 JSOp op = JSOP_CALL;
                 bool maybeAsyncArrow = false;
                 if (PropertyName* prop = handler.maybeDottedProperty(lhs)) {
@@ -9109,13 +9118,11 @@ Parser<ParseHandler, CharT>::memberExpr(
                     }
                 }
 
-                handler.setBeginPosition(nextMember, lhs);
-                handler.addList(nextMember, lhs);
-
                 if (tt == TOK_LP) {
                     bool isSpread = false;
                     PossibleError* asyncPossibleError = maybeAsyncArrow ? possibleError : nullptr;
-                    if (!argumentList(yieldHandling, nextMember, &isSpread, asyncPossibleError))
+                    Node args = argumentList(yieldHandling, &isSpread, asyncPossibleError);
+                    if (!args)
                         return null();
                     if (isSpread) {
                         if (op == JSOP_EVAL)
@@ -9125,8 +9132,20 @@ Parser<ParseHandler, CharT>::memberExpr(
                         else
                             op = JSOP_SPREADCALL;
                     }
+
+                    nextMember = handler.newCall(lhs, args);
+                    if (!nextMember)
+                        return null();
                 } else {
-                    if (!taggedTemplate(yieldHandling, nextMember, tt))
+                    Node args = handler.newArguments(pos());
+                    if (!args)
+                        return null();
+
+                    if (!taggedTemplate(yieldHandling, args, tt))
+                        return null();
+
+                    nextMember = handler.newTaggedTemplate(lhs, args);
+                    if (!nextMember)
                         return null();
                 }
                 handler.setOp(nextMember, op);
diff -Nrup mozilla-OLD/js/src/frontend/Parser.h mozilla/js/src/frontend/Parser.h
--- mozilla-OLD/js/src/frontend/Parser.h	2021-12-29 03:47:40.642227025 +0300
+++ mozilla/js/src/frontend/Parser.h	2021-12-29 03:37:16.064713905 +0300
@@ -799,7 +799,7 @@ class Parser final
     Node arrayComprehension(uint32_t begin);
     Node generatorComprehension(uint32_t begin);
 
-    bool argumentList(YieldHandling yieldHandling, Node listNode, bool* isSpread,
+    Node argumentList(YieldHandling yieldHandling, bool* isSpread,
                       PossibleError* possibleError = nullptr);
     Node destructuringDeclaration(DeclarationKind kind, YieldHandling yieldHandling,
                                   TokenKind tt);
diff -Nrup mozilla-OLD/js/src/frontend/SyntaxParseHandler.h mozilla/js/src/frontend/SyntaxParseHandler.h
--- mozilla-OLD/js/src/frontend/SyntaxParseHandler.h	2021-12-29 03:47:40.643227018 +0300
+++ mozilla/js/src/frontend/SyntaxParseHandler.h	2021-12-29 03:37:16.064713905 +0300
@@ -241,9 +241,11 @@ class SyntaxParseHandler
     MOZ_MUST_USE bool addSpreadElement(Node literal, uint32_t begin, Node inner) { return true; }
     void addArrayElement(Node literal, Node element) { }
 
-    Node newCall(const TokenPos& pos) { return NodeFunctionCall; }
-    Node newSuperCall(Node callee) { return NodeGeneric; }
-    Node newTaggedTemplate(const TokenPos& pos) { return NodeGeneric; }
+    Node newArguments(const TokenPos& pos) { return NodeGeneric; }
+    Node newCall(Node callee, Node args) { return NodeFunctionCall; }
+
+    Node newSuperCall(Node callee, Node args) { return NodeGeneric; }
+    Node newTaggedTemplate(Node callee, Node args) { return NodeGeneric; }
 
     Node newObjectLiteral(uint32_t begin) { return NodeUnparenthesizedObject; }
     Node newClassMethodList(uint32_t begin) { return NodeGeneric; }
@@ -316,8 +318,12 @@ class SyntaxParseHandler
     }
     Node newDebuggerStatement(const TokenPos& pos) { return NodeGeneric; }
 
-    Node newPropertyAccess(Node pn, PropertyName* name, uint32_t end) {
+    Node newPropertyName(PropertyName* name, const TokenPos& pos) {
         lastAtom = name;
+        return NodeGeneric;
+    }
+
+    Node newPropertyAccess(Node expr, Node key) {
         return NodeDottedProperty;
     }
 
@@ -438,7 +444,7 @@ class SyntaxParseHandler
                    list == NodeFunctionCall);
     }
 
-    Node newNewExpression(uint32_t begin, Node ctor) {
+    Node newNewExpression(uint32_t begin, Node ctor, Node args) {
         return NodeGeneric;
     }
 
diff -Nrup mozilla-OLD/js/src/wasm/AsmJS.cpp mozilla/js/src/wasm/AsmJS.cpp
--- mozilla-OLD/js/src/wasm/AsmJS.cpp	2021-12-29 03:47:40.645227003 +0300
+++ mozilla/js/src/wasm/AsmJS.cpp	2021-12-29 03:37:16.066713891 +0300
@@ -456,22 +456,21 @@ static inline ParseNode*
 CallCallee(ParseNode* pn)
 {
     MOZ_ASSERT(pn->isKind(ParseNodeKind::Call));
-    return ListHead(pn);
+    return BinaryLeft(pn);
 }
 
 static inline unsigned
 CallArgListLength(ParseNode* pn)
 {
     MOZ_ASSERT(pn->isKind(ParseNodeKind::Call));
-    MOZ_ASSERT(ListLength(pn) >= 1);
-    return ListLength(pn) - 1;
+    return ListLength(BinaryRight(pn));
 }
 
 static inline ParseNode*
 CallArgList(ParseNode* pn)
 {
     MOZ_ASSERT(pn->isKind(ParseNodeKind::Call));
-    return NextNode(ListHead(pn));
+    return ListHead(BinaryRight(pn));
 }
 
 static inline ParseNode*
@@ -634,16 +633,16 @@ static ParseNode*
 DotBase(ParseNode* pn)
 {
     MOZ_ASSERT(pn->isKind(ParseNodeKind::Dot));
-    MOZ_ASSERT(pn->isArity(PN_NAME));
-    return pn->expr();
+    MOZ_ASSERT(pn->isArity(PN_BINARY));
+    return pn->pn_left;
 }
 
 static PropertyName*
 DotMember(ParseNode* pn)
 {
     MOZ_ASSERT(pn->isKind(ParseNodeKind::Dot));
-    MOZ_ASSERT(pn->isArity(PN_NAME));
-    return pn->pn_atom->asPropertyName();
+    MOZ_ASSERT(pn->isArity(PN_BINARY));
+    return pn->pn_right->pn_atom->asPropertyName();
 }
 
 static ParseNode*
@@ -3429,9 +3428,11 @@ IsArrayViewCtorName(ModuleValidator& m,
 }
 
 static bool
-CheckNewArrayViewArgs(ModuleValidator& m, ParseNode* ctorExpr, PropertyName* bufferName)
+CheckNewArrayViewArgs(ModuleValidator& m, ParseNode* newExpr, PropertyName* bufferName)
 {
-    ParseNode* bufArg = NextNode(ctorExpr);
+    ParseNode* ctorExpr = BinaryLeft(newExpr);
+    ParseNode* ctorArgs = BinaryRight(newExpr);
+    ParseNode* bufArg = ListHead(ctorArgs);
     if (!bufArg || NextNode(bufArg) != nullptr)
         return m.fail(ctorExpr, "array view constructor takes exactly one argument");
 
@@ -3452,7 +3453,7 @@ CheckNewArrayView(ModuleValidator& m, Pr
     if (!bufferName)
         return m.fail(newExpr, "cannot create array view without an asm.js heap parameter");
 
-    ParseNode* ctorExpr = ListHead(newExpr);
+    ParseNode* ctorExpr = BinaryLeft(newExpr);
 
     PropertyName* field;
     Scalar::Type type;
@@ -3481,7 +3482,7 @@ CheckNewArrayView(ModuleValidator& m, Pr
         type = global->viewType();
     }
 
-    if (!CheckNewArrayViewArgs(m, ctorExpr, bufferName))
+    if (!CheckNewArrayViewArgs(m, newExpr, bufferName))
         return false;
 
     return m.addArrayView(varName, type, field);