Bug 1493870 - Remove ParseNode::name. r=jorendorff
authorTooru Fujisawa <arai_a@mac.com>
Tue, 16 Oct 2018 15:01:15 +0900
changeset 489716 847c7c6af1db86f0edcae2986a9a9582160f4f4b
parent 489715 4700f0a79ebd4ec48932225cc7c124c999656938
child 489717 0ece655d6f5b5ff673e1d12b7b8979b5ff0089da
push id247
push userfmarier@mozilla.com
push dateSat, 27 Oct 2018 01:06:44 +0000
reviewersjorendorff
bugs1493870
milestone64.0a1
Bug 1493870 - Remove ParseNode::name. r=jorendorff
js/src/builtin/ReflectParse.cpp
js/src/frontend/BinSource-auto.cpp
js/src/frontend/BinSource.cpp
js/src/frontend/BinSource.yaml
js/src/frontend/BytecodeEmitter.cpp
js/src/frontend/BytecodeEmitter.h
js/src/frontend/ParseNode-inl.h
js/src/frontend/ParseNode.cpp
js/src/frontend/ParseNode.h
js/src/frontend/Parser.cpp
js/src/wasm/AsmJS.cpp
--- a/js/src/builtin/ReflectParse.cpp
+++ b/js/src/builtin/ReflectParse.cpp
@@ -11,25 +11,25 @@
 #include "mozilla/Move.h"
 
 #include <stdlib.h>
 
 #include "jspubtd.h"
 
 #include "builtin/Array.h"
 #include "builtin/Reflect.h"
+#include "frontend/ParseNode.h"
 #include "frontend/Parser.h"
 #include "frontend/TokenStream.h"
 #include "js/CharacterEncoding.h"
 #include "js/StableStringChars.h"
 #include "vm/JSAtom.h"
 #include "vm/JSObject.h"
 #include "vm/RegExpObject.h"
 
-#include "frontend/ParseNode-inl.h"
 #include "vm/JSObject-inl.h"
 
 using namespace js;
 using namespace js::frontend;
 
 using JS::AutoStableStringChars;
 using JS::AutoValueArray;
 using JS::CompileOptions;
--- a/js/src/frontend/BinSource-auto.cpp
+++ b/js/src/frontend/BinSource-auto.cpp
@@ -15,23 +15,23 @@
 #include "mozilla/Move.h"
 #include "mozilla/PodOperations.h"
 #include "mozilla/Vector.h"
 
 #include "frontend/BinSource-macros.h"
 #include "frontend/BinSource.h"
 #include "frontend/BinTokenReaderTester.h"
 #include "frontend/FullParseHandler.h"
+#include "frontend/ParseNode.h"
 #include "frontend/Parser.h"
 #include "frontend/SharedContext.h"
 
 #include "vm/RegExpObject.h"
 
 #include "frontend/ParseContext-inl.h"
-#include "frontend/ParseNode-inl.h"
 
 namespace js {
 namespace frontend {
 
 // Compare a bunch of `uint8_t` values (as returned by the tokenizer_) with
 // a string literal (and ONLY a string literal).
 template<typename Tok, size_t N>
 bool operator==(const typename Tok::Chars& left, const char (&right)[N]) {
@@ -2838,18 +2838,19 @@ BinASTParser<Tok>::parseInterfaceCallExp
                 parseContext_->functionBox()->usesApply = true;
         } else if (prop == cx_->names().call) {
             op = JSOP_FUNCALL;
         }
     }
 
     // Check for direct calls to `eval`.
     if (factory_.isEvalName(callee, cx_)) {
-        if (!parseContext_->varScope().lookupDeclaredNameForAdd(callee->name())
-         && !parseContext_->innermostScope()->lookupDeclaredNameForAdd(callee->name())) {
+        if (!parseContext_->varScope().lookupDeclaredNameForAdd(cx_->names().eval)
+         && !parseContext_->innermostScope()->lookupDeclaredNameForAdd(cx_->names().eval))
+        {
             // This is a direct call to `eval`.
             if (!parseContext_->sc()->hasDirectEval()) {
                 return raiseMissingDirectEvalInAssertedScope();
             }
 
             op = parseContext_->sc()->strict() ? JSOP_STRICTEVAL : JSOP_EVAL;
         }
     }
@@ -4540,17 +4541,17 @@ BinASTParser<Tok>::parseInterfaceShortha
     const BinField expected_fields[1] = { BinField::Name };
     MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif // defined(DEBUG)
 
     BINJS_MOZ_TRY_DECL(name, parseIdentifierExpression());
 
     MOZ_ASSERT(name->isKind(ParseNodeKind::Name));
     MOZ_ASSERT(!factory_.isUsableAsObjectPropertyName(name));
-    BINJS_TRY_DECL(propName, factory_.newObjectLiteralPropertyName(name->name(), tokenizer_->pos(start)));
+    BINJS_TRY_DECL(propName, factory_.newObjectLiteralPropertyName(name->template as<NameNode>().name(), tokenizer_->pos(start)));
 
     BINJS_TRY_DECL(result, factory_.newObjectMethodOrPropertyDefinition(propName, name, AccessorType::None));
     result->setKind(ParseNodeKind::Shorthand);
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceSpreadElement(const size_t start, const BinKind kind, const BinFields& fields)
--- a/js/src/frontend/BinSource.cpp
+++ b/js/src/frontend/BinSource.cpp
@@ -12,24 +12,24 @@
 #include "mozilla/Move.h"
 #include "mozilla/PodOperations.h"
 #include "mozilla/ScopeExit.h"
 #include "mozilla/Vector.h"
 
 #include "frontend/BinSource-macros.h"
 #include "frontend/BinTokenReaderTester.h"
 #include "frontend/FullParseHandler.h"
+#include "frontend/ParseNode.h"
 #include "frontend/Parser.h"
 #include "frontend/SharedContext.h"
 
 #include "js/Result.h"
 #include "vm/RegExpObject.h"
 
 #include "frontend/ParseContext-inl.h"
-#include "frontend/ParseNode-inl.h"
 #include "vm/JSContext-inl.h"
 
 // # About compliance with EcmaScript
 //
 // For the moment, this parser implements ES5. Future versions will be extended
 // to ES6 and further on.
 //
 // By design, it does NOT implement Annex B.3.3. If possible, we would like
@@ -553,17 +553,17 @@ BinASTParser<Tok>::checkPositionalParame
 
             JSAtom* name = positionalParams.get()[i];
             if (!name) {
                 // Step 2.a.ii.1.
                 return raiseError("Expected destructuring/rest parameter per AssertedParameterScope.paramNames, got positional parameter");
             }
 
             // Step 2.a.i.
-            if (param->name() != name) {
+            if (param->as<NameNode>().name() != name) {
                 // Step 2.a.ii.1.
                 return raiseError("Name mismatch between AssertedPositionalParameterName in AssertedParameterScope.paramNames and actual parameter");
             }
 
             // Step 2.a.i.1.
             // Implicitly done.
         } else {
             // Destructuring parameter.
--- a/js/src/frontend/BinSource.yaml
+++ b/js/src/frontend/BinSource.yaml
@@ -33,23 +33,23 @@ cpp:
         #include "mozilla/Move.h"
         #include "mozilla/PodOperations.h"
         #include "mozilla/Vector.h"
 
         #include "frontend/BinSource-macros.h"
         #include "frontend/BinSource.h"
         #include "frontend/BinTokenReaderTester.h"
         #include "frontend/FullParseHandler.h"
+        #include "frontend/ParseNode.h"
         #include "frontend/Parser.h"
         #include "frontend/SharedContext.h"
 
         #include "vm/RegExpObject.h"
 
         #include "frontend/ParseContext-inl.h"
-        #include "frontend/ParseNode-inl.h"
 
         namespace js {
         namespace frontend {
 
         // Compare a bunch of `uint8_t` values (as returned by the tokenizer_) with
         // a string literal (and ONLY a string literal).
         template<typename Tok, size_t N>
         bool operator==(const typename Tok::Chars& left, const char (&right)[N]) {
@@ -501,18 +501,19 @@ CallExpression:
                     parseContext_->functionBox()->usesApply = true;
             } else if (prop == cx_->names().call) {
                 op = JSOP_FUNCALL;
             }
         }
 
         // Check for direct calls to `eval`.
         if (factory_.isEvalName(callee, cx_)) {
-            if (!parseContext_->varScope().lookupDeclaredNameForAdd(callee->name())
-             && !parseContext_->innermostScope()->lookupDeclaredNameForAdd(callee->name())) {
+            if (!parseContext_->varScope().lookupDeclaredNameForAdd(cx_->names().eval)
+             && !parseContext_->innermostScope()->lookupDeclaredNameForAdd(cx_->names().eval))
+            {
                 // This is a direct call to `eval`.
                 if (!parseContext_->sc()->hasDirectEval()) {
                     return raiseMissingDirectEvalInAssertedScope();
                 }
 
                 op = parseContext_->sc()->strict() ? JSOP_STRICTEVAL : JSOP_EVAL;
             }
         }
@@ -1108,17 +1109,17 @@ Script:
     build:
         MOZ_TRY(checkClosedVars(parseContext_->varScope()));
         BINJS_MOZ_TRY_DECL(result, appendDirectivesToBody(/* body = */ statements, /* directives = */ directives));
 
 ShorthandProperty:
     build: |
         MOZ_ASSERT(name->isKind(ParseNodeKind::Name));
         MOZ_ASSERT(!factory_.isUsableAsObjectPropertyName(name));
-        BINJS_TRY_DECL(propName, factory_.newObjectLiteralPropertyName(name->name(), tokenizer_->pos(start)));
+        BINJS_TRY_DECL(propName, factory_.newObjectLiteralPropertyName(name->template as<NameNode>().name(), tokenizer_->pos(start)));
 
         BINJS_TRY_DECL(result, factory_.newObjectMethodOrPropertyDefinition(propName, name, AccessorType::None));
         result->setKind(ParseNodeKind::Shorthand);
 
 SwitchCase:
     type-ok:
         CaseClause*
     build: |
--- a/js/src/frontend/BytecodeEmitter.cpp
+++ b/js/src/frontend/BytecodeEmitter.cpp
@@ -31,16 +31,17 @@
 #include "frontend/ElemOpEmitter.h"
 #include "frontend/EmitterScope.h"
 #include "frontend/ExpressionStatementEmitter.h"
 #include "frontend/ForInEmitter.h"
 #include "frontend/ForOfEmitter.h"
 #include "frontend/ForOfLoopControl.h"
 #include "frontend/IfEmitter.h"
 #include "frontend/NameOpEmitter.h"
+#include "frontend/ParseNode.h"
 #include "frontend/Parser.h"
 #include "frontend/PropOpEmitter.h"
 #include "frontend/SwitchEmitter.h"
 #include "frontend/TDZCheckCache.h"
 #include "frontend/TryEmitter.h"
 #include "frontend/WhileEmitter.h"
 #include "js/CompileOptions.h"
 #include "vm/BytecodeUtil.h"
@@ -48,17 +49,16 @@
 #include "vm/GeneratorObject.h"
 #include "vm/JSAtom.h"
 #include "vm/JSContext.h"
 #include "vm/JSFunction.h"
 #include "vm/JSScript.h"
 #include "vm/Stack.h"
 #include "wasm/AsmJS.h"
 
-#include "frontend/ParseNode-inl.h"
 #include "vm/JSObject-inl.h"
 
 using namespace js;
 using namespace js::frontend;
 
 using mozilla::AssertedCast;
 using mozilla::DebugOnly;
 using mozilla::Maybe;
@@ -1711,19 +1711,19 @@ BytecodeEmitter::emitGetNameAtLocation(J
     if (!noe.emitGet()) {
         return false;
     }
 
     return true;
 }
 
 bool
-BytecodeEmitter::emitGetName(ParseNode* pn)
-{
-    return emitGetName(pn->name());
+BytecodeEmitter::emitGetName(NameNode* name)
+{
+    return emitGetName(name->name());
 }
 
 bool
 BytecodeEmitter::emitTDZCheckIfNeeded(JSAtom* name, const NameLocation& loc)
 {
     // Dynamic accesses have TDZ checks built into their VM code and should
     // never emit explicit TDZ checks.
     MOZ_ASSERT(loc.hasKnownSlot());
@@ -2216,17 +2216,17 @@ bool
 BytecodeEmitter::emitSetThis(BinaryNode* setThisNode)
 {
     // ParseNodeKind::SetThis is used to update |this| after a super() call
     // in a derived class constructor.
 
     MOZ_ASSERT(setThisNode->isKind(ParseNodeKind::SetThis));
     MOZ_ASSERT(setThisNode->left()->isKind(ParseNodeKind::Name));
 
-    RootedAtom name(cx, setThisNode->left()->name());
+    RootedAtom name(cx, setThisNode->left()->as<NameNode>().name());
 
     // The 'this' binding is not lexical, but due to super() semantics this
     // initialization needs to be treated as a lexical one.
     NameLocation loc = lookupName(name);
     NameLocation lexicalLoc;
     if (loc.kind() == NameLocation::Kind::FrameSlot) {
         lexicalLoc = NameLocation::FrameSlot(BindingKind::Let, loc.frameSlot());
     } else if (loc.kind() == NameLocation::Kind::EnvironmentCoordinate) {
@@ -2553,17 +2553,17 @@ BytecodeEmitter::emitSetOrInitializeDest
         // Per its post-condition, emitDestructuringOps has left the
         // to-be-destructured value on top of the stack.
         if (!emit1(JSOP_POP)) {
             return false;
         }
     } else {
         switch (target->getKind()) {
           case ParseNodeKind::Name: {
-            RootedAtom name(cx, target->name());
+            RootedAtom name(cx, target->as<NameNode>().name());
             NameLocation loc;
             NameOpEmitter::Kind kind;
             switch (flav) {
               case DestructuringDeclaration:
                 loc = lookupName(name);
                 kind = NameOpEmitter::Kind::Initialize;
                 break;
               case DestructuringFormalParameterInVarScope: {
@@ -3022,17 +3022,17 @@ bool
 BytecodeEmitter::emitInitializer(ParseNode* initializer, ParseNode* pattern)
 {
     if (!emitTree(initializer)) {
         return false;
     }
 
     if (initializer->isDirectRHSAnonFunction()) {
         MOZ_ASSERT(!pattern->isInParens());
-        RootedAtom name(cx, pattern->name());
+        RootedAtom name(cx, pattern->as<NameNode>().name());
         if (!setOrEmitSetFunName(initializer, name)) {
             return false;
         }
     }
 
     return true;
 }
 
@@ -3764,26 +3764,27 @@ BytecodeEmitter::emitDeclarationList(Lis
             if (!emitDestructuringOps(pattern, DestructuringDeclaration)) {
                 return false;
             }
 
             if (!emit1(JSOP_POP)) {
                 return false;
             }
         } else {
-            if (!emitSingleDeclaration(declList, decl, decl->as<NameNode>().initializer())) {
-                return false;
-            }
-        }
-    }
-    return true;
-}
-
-bool
-BytecodeEmitter::emitSingleDeclaration(ParseNode* declList, ParseNode* decl,
+            NameNode* name = &decl->as<NameNode>();
+            if (!emitSingleDeclaration(declList, name, name->initializer())) {
+                return false;
+            }
+        }
+    }
+    return true;
+}
+
+bool
+BytecodeEmitter::emitSingleDeclaration(ListNode* declList, NameNode* decl,
                                        ParseNode* initializer)
 {
     MOZ_ASSERT(decl->isKind(ParseNodeKind::Name));
 
     // Nothing to do for initializer-less 'var' declarations, as there's no TDZ.
     if (!initializer && declList->isKind(ParseNodeKind::Var)) {
         return true;
     }
@@ -3860,35 +3861,36 @@ CompoundAssignmentParseNodeKindToJSOp(Pa
 bool
 BytecodeEmitter::emitAssignment(ParseNode* lhs, JSOp compoundOp, ParseNode* rhs)
 {
     bool isCompound = compoundOp != JSOP_NOP;
 
     // Name assignments are handled separately because choosing ops and when
     // to emit BINDNAME is involved and should avoid duplication.
     if (lhs->isKind(ParseNodeKind::Name)) {
+        NameNode* nameNode = &lhs->as<NameNode>();
+        RootedAtom name(cx, nameNode->name());
         NameOpEmitter noe(this,
-                          lhs->name(),
+                          name,
                           isCompound
                           ? NameOpEmitter::Kind::CompoundAssignment
                           : NameOpEmitter::Kind::SimpleAssignment);
         if (!noe.prepareForRhs()) {                       // ENV? VAL?
             return false;
         }
 
         // Emit the RHS. If we emitted a BIND[G]NAME, then the scope is on
         // the top of the stack and we need to pick the right RHS value.
         uint8_t offset = noe.emittedBindOp() ? 2 : 1;
         if (!EmitAssignmentRhs(this, rhs, offset)) {      // ENV? VAL? RHS
             return false;
         }
         if (rhs && rhs->isDirectRHSAnonFunction()) {
-            MOZ_ASSERT(!lhs->isInParens());
+            MOZ_ASSERT(!nameNode->isInParens());
             MOZ_ASSERT(!isCompound);
-            RootedAtom name(cx, lhs->name());
             if (!setOrEmitSetFunName(rhs, name)) {         // ENV? VAL? RHS
                 return false;
             }
         }
 
         // Emit the compound assignment op if there is one.
         if (isCompound) {
             if (!emit1(compoundOp)) {                     // ENV? VAL
@@ -4322,17 +4324,17 @@ BytecodeEmitter::emitCatch(BinaryNode* c
                 return false;
             }
             if (!emit1(JSOP_POP)) {
                 return false;
             }
             break;
 
           case ParseNodeKind::Name:
-            if (!emitLexicalInitialization(param)) {
+            if (!emitLexicalInitialization(&param->as<NameNode>())) {
                 return false;
             }
             if (!emit1(JSOP_POP)) {
                 return false;
             }
             break;
 
           default:
@@ -4904,17 +4906,18 @@ BytecodeEmitter::emitInitializeForInOrOf
     if (!updateSourceCoordNotes(target->pn_pos.begin)) {
         return false;
     }
 
     MOZ_ASSERT(target->isForLoopDeclaration());
     target = parser->astGenerator().singleBindingFromDeclaration(&target->as<ListNode>());
 
     if (target->isKind(ParseNodeKind::Name)) {
-        NameOpEmitter noe(this, target->name(), NameOpEmitter::Kind::Initialize);
+        NameNode* nameNode = &target->as<NameNode>();
+        NameOpEmitter noe(this, nameNode->name(), NameOpEmitter::Kind::Initialize);
         if (!noe.prepareForRhs()) {
             return false;
         }
         if (noe.emittedBindOp()) {
             // Per-iteration initialization in for-in/of loops computes the
             // iteration value *before* initializing.  Thus the initializing
             // value may be buried under a bind-specific value on the stack.
             // Swap it to the top of the stack.
@@ -4960,18 +4963,17 @@ BytecodeEmitter::emitForOf(ForNode* forO
 
     ParseNode* forHeadExpr = forOfHead->kid3();
 
     // Certain builtins (e.g. Array.from) are implemented in self-hosting
     // as for-of loops.
     bool allowSelfHostedIter = false;
     if (emitterMode == BytecodeEmitter::SelfHosting &&
         forHeadExpr->isKind(ParseNodeKind::Call) &&
-        forHeadExpr->as<BinaryNode>().left()->name() == cx->names().allowContentIter)
-    {
+        forHeadExpr->as<BinaryNode>().left()->isName(cx->names().allowContentIter)) {
         allowSelfHostedIter = true;
     }
 
     ForOfEmitter forOf(this, headLexicalEmitterScope, allowSelfHostedIter, iterKind);
 
     if (!forOf.emitIterated()) {                          //
         return false;
     }
@@ -5031,17 +5033,18 @@ BytecodeEmitter::emitForIn(ForNode* forI
             if (ParseNode* initializer = decl->as<NameNode>().initializer()) {
                 MOZ_ASSERT(forInTarget->isKind(ParseNodeKind::Var),
                            "for-in initializers are only permitted for |var| declarations");
 
                 if (!updateSourceCoordNotes(decl->pn_pos.begin)) {
                     return false;
                 }
 
-                NameOpEmitter noe(this, decl->name(), NameOpEmitter::Kind::Initialize);
+                NameNode* nameNode = &decl->as<NameNode>();
+                NameOpEmitter noe(this, nameNode->name(), NameOpEmitter::Kind::Initialize);
                 if (!noe.prepareForRhs()) {
                     return false;
                 }
                 if (!emitInitializer(initializer, decl)) {
                     return false;
                 }
                 if (!noe.emitAssignment()) {
                     return false;
@@ -5612,23 +5615,22 @@ BytecodeEmitter::emitContinue(PropertyNa
         }
     } else {
         target = findInnermostNestableControl<LoopControl>();
     }
     return emitGoto(target, &target->continues, SRC_CONTINUE);
 }
 
 bool
-BytecodeEmitter::emitGetFunctionThis(ParseNode* pn)
+BytecodeEmitter::emitGetFunctionThis(NameNode* thisName)
 {
     MOZ_ASSERT(sc->thisBinding() == ThisBinding::Function);
-    MOZ_ASSERT(pn->isKind(ParseNodeKind::Name));
-    MOZ_ASSERT(pn->name() == cx->names().dotThis);
-
-    return emitGetFunctionThis(Some(pn->pn_pos.begin));
+    MOZ_ASSERT(thisName->isName(cx->names().dotThis));
+
+    return emitGetFunctionThis(Some(thisName->pn_pos.begin));
 }
 
 bool
 BytecodeEmitter::emitGetFunctionThis(const mozilla::Maybe<uint32_t>& offset)
 {
     if (offset) {
         if (!updateLineNumberNotes(*offset)) {
             return false;
@@ -5646,23 +5648,25 @@ BytecodeEmitter::emitGetFunctionThis(con
 
     return true;
 }
 
 bool
 BytecodeEmitter::emitGetThisForSuperBase(UnaryNode* superBase)
 {
     MOZ_ASSERT(superBase->isKind(ParseNodeKind::SuperBase));
-    return emitGetFunctionThis(superBase->kid());         // THIS
+    NameNode* nameNode = &superBase->kid()->as<NameNode>();
+    return emitGetFunctionThis(nameNode);                 // THIS
 }
 
 bool
 BytecodeEmitter::emitThisLiteral(ThisLiteral* pn)
 {
-    if (ParseNode* thisName = pn->kid()) {
+    if (ParseNode* kid = pn->kid()) {
+        NameNode* thisName = &kid->as<NameNode>();
         return emitGetFunctionThis(thisName);             // THIS
     }
 
     if (sc->thisBinding() == ThisBinding::Module) {
         return emit1(JSOP_UNDEFINED);                     // UNDEF
     }
 
     MOZ_ASSERT(sc->thisBinding() == ThisBinding::Global);
@@ -6515,17 +6519,17 @@ BytecodeEmitter::emitSelfHostedCallFunct
     // invokes the callee with the correct |this| object and arguments.
     // callFunction(fun, thisArg, arg0, arg1) thus becomes:
     // - emit lookup for fun
     // - emit lookup for thisArg
     // - emit lookups for arg0, arg1
     //
     // argc is set to the amount of actually emitted args and the
     // emitting of args below is disabled by setting emitArgs to false.
-    ParseNode* calleeNode = callNode->left();
+    NameNode* calleeNode = &callNode->left()->as<NameNode>();
     ListNode* argsList = &callNode->right()->as<ListNode>();
 
     const char* errorName = SelfHostedCallFunctionName(calleeNode->name(), cx);
 
     if (argsList->count() < 2) {
         reportError(callNode, JSMSG_MORE_ARGS_NEEDED, errorName, "2", "s");
         return false;
     }
@@ -6535,18 +6539,17 @@ BytecodeEmitter::emitSelfHostedCallFunct
         reportError(callNode, JSMSG_NOT_CONSTRUCTOR, errorName);
         return false;
     }
 
     bool constructing = calleeNode->name() == cx->names().constructContentFunction;
     ParseNode* funNode = argsList->head();
     if (constructing) {
         callOp = JSOP_NEW;
-    } else if (funNode->getKind() == ParseNodeKind::Name &&
-               funNode->name() == cx->names().std_Function_apply) {
+    } else if (funNode->isName(cx->names().std_Function_apply)) {
         callOp = JSOP_FUNAPPLY;
     }
 
     if (!emitTree(funNode)) {
         return false;
     }
 
 #ifdef DEBUG
@@ -6730,42 +6733,42 @@ BytecodeEmitter::emitSelfHostedGetProper
     if (!emitTree(objNode)) {
         return false;
     }
 
     return emitElemOpBase(JSOP_GETELEM_SUPER);
 }
 
 bool
-BytecodeEmitter::isRestParameter(ParseNode* pn)
+BytecodeEmitter::isRestParameter(ParseNode* expr)
 {
     if (!sc->isFunctionBox()) {
         return false;
     }
 
     FunctionBox* funbox = sc->asFunctionBox();
     RootedFunction fun(cx, funbox->function());
     if (!funbox->hasRest()) {
         return false;
     }
 
-    if (!pn->isKind(ParseNodeKind::Name)) {
-        if (emitterMode == BytecodeEmitter::SelfHosting && pn->isKind(ParseNodeKind::Call)) {
-            BinaryNode* callNode = &pn->as<BinaryNode>();
+    if (!expr->isKind(ParseNodeKind::Name)) {
+        if (emitterMode == BytecodeEmitter::SelfHosting &&
+            expr->isKind(ParseNodeKind::Call))
+        {
+            BinaryNode* callNode = &expr->as<BinaryNode>();
             ParseNode* calleeNode = callNode->left();
-            if (calleeNode->getKind() == ParseNodeKind::Name &&
-                calleeNode->name() == cx->names().allowContentIter)
-            {
+            if (calleeNode->isName(cx->names().allowContentIter)) {
                 return isRestParameter(callNode->right()->as<ListNode>().head());
             }
         }
         return false;
     }
 
-    JSAtom* name = pn->name();
+    JSAtom* name = expr->as<NameNode>().name();
     Maybe<NameLocation> paramLoc = locationOfNameBoundInFunctionScope(name);
     if (paramLoc && lookupName(name) == *paramLoc) {
         FunctionScope::Data* bindings = funbox->functionScopeBindings();
         if (bindings->nonPositionalFormalStart > 0) {
             // |paramName| can be nullptr when the rest destructuring syntax is
             // used: `function f(...[]) {}`.
             JSAtom* paramName =
                 bindings->trailingNames[bindings->nonPositionalFormalStart - 1].name();
@@ -6776,18 +6779,18 @@ BytecodeEmitter::isRestParameter(ParseNo
     return false;
 }
 
 bool
 BytecodeEmitter::emitCalleeAndThis(ParseNode* callee, ParseNode* call, CallOrNewEmitter& cone)
 {
     switch (callee->getKind()) {
       case ParseNodeKind::Name:
-        if (!cone.emitNameCallee(callee->name())) {       // CALLEE THIS
-            return false;
+        if (!cone.emitNameCallee(callee->as<NameNode>().name())) {
+            return false;                                 // CALLEE THIS
         }
         break;
       case ParseNodeKind::Dot: {
         MOZ_ASSERT(emitterMode != BytecodeEmitter::SelfHosting);
         PropertyAccess* prop = &callee->as<PropertyAccess>();
         bool isSuper = prop->isSuper();
 
         PropOpEmitter& poe = cone.prepareForPropCallee(isSuper);
@@ -6953,17 +6956,17 @@ BytecodeEmitter::emitCallOrNew(BinaryNod
     ListNode* argsList = &callNode->right()->as<ListNode>();
     bool isSpread = JOF_OPTYPE(callNode->getOp()) == JOF_BYTE;
     if (calleeNode->isKind(ParseNodeKind::Name) && emitterMode == BytecodeEmitter::SelfHosting &&
         !isSpread)
     {
         // Calls to "forceInterpreter", "callFunction",
         // "callContentFunction", or "resumeGenerator" in self-hosted
         // code generate inline bytecode.
-        PropertyName* calleeName = calleeNode->name();
+        PropertyName* calleeName = calleeNode->as<NameNode>().name();
         if (calleeName == cx->names().callFunction ||
             calleeName == cx->names().callContentFunction ||
             calleeName == cx->names().constructContentFunction)
         {
             return emitSelfHostedCallFunction(callNode);
         }
         if (calleeName == cx->names().resumeGenerator) {
             return emitSelfHostedResumeGenerator(callNode);
@@ -7660,18 +7663,17 @@ BytecodeEmitter::emitArray(ParseNode* ar
             }
         } else {
             ParseNode* expr;
             if (elem->isKind(ParseNodeKind::Spread)) {
                 expr = elem->as<UnaryNode>().kid();
 
                 if (emitterMode == BytecodeEmitter::SelfHosting &&
                     expr->isKind(ParseNodeKind::Call) &&
-                    expr->as<BinaryNode>().left()->name() == cx->names().allowContentIter)
-                {
+                    expr->as<BinaryNode>().left()->isName(cx->names().allowContentIter)) {
                     allowSelfHostedIter = true;
                 }
             } else {
                 expr = elem;
             }
             if (!emitTree(expr)) {                                       // ARRAY INDEX? VALUE
                 return false;
             }
@@ -7950,17 +7952,17 @@ BytecodeEmitter::emitFunctionFormalParam
             {
                 return false;
             }
 
             if (!emit1(JSOP_POP)) {
                 return false;
             }
         } else if (hasParameterExprs || isRest) {
-            RootedAtom paramName(cx, bindingElement->name());
+            RootedAtom paramName(cx, bindingElement->as<NameNode>().name());
             NameLocation paramLoc = *locationOfNameBoundInScope(paramName, funScope);
             NameOpEmitter noe(this, paramName, paramLoc, NameOpEmitter::Kind::Initialize);
             if (!noe.prepareForRhs()) {
                 return false;
             }
             if (hasParameterExprs) {
                 // If we had an initializer or a rest parameter, the value is
                 // already on the stack.
@@ -8097,19 +8099,19 @@ BytecodeEmitter::emitFunctionBody(ParseN
             return false;
         }
     }
 
     return true;
 }
 
 bool
-BytecodeEmitter::emitLexicalInitialization(ParseNode* pn)
-{
-    NameOpEmitter noe(this, pn->name(), NameOpEmitter::Kind::Initialize);
+BytecodeEmitter::emitLexicalInitialization(NameNode* name)
+{
+    NameOpEmitter noe(this, name->name(), NameOpEmitter::Kind::Initialize);
     if (!noe.prepareForRhs()) {
         return false;
     }
 
     // The caller has pushed the RHS to the top of the stack. Assert that the
     // name is lexical and no BIND[G]NAME ops were emitted.
     MOZ_ASSERT(noe.loc().isLexical());
     MOZ_ASSERT(!noe.emittedBindOp());
@@ -8321,29 +8323,28 @@ BytecodeEmitter::emitClass(ClassNode* cl
         return false;
     }
 
     if (!emit1(JSOP_POP)) {                                     // ... CONSTRUCTOR
         return false;
     }
 
     if (names) {
-        ParseNode* innerName = names->innerBinding();
+        NameNode* innerName = names->innerBinding();
         if (!emitLexicalInitialization(innerName)) {            // ... CONSTRUCTOR
             return false;
         }
 
         // Pop the inner scope.
         if (!emitterScope->leave(this)) {
             return false;
         }
         emitterScope.reset();
 
-        ParseNode* outerName = names->outerBinding();
-        if (outerName) {
+        if (NameNode* outerName = names->outerBinding()) {
             if (!emitLexicalInitialization(outerName)) {        // ... CONSTRUCTOR
                 return false;
             }
             // Only class statements make outer bindings, and they do not leave
             // themselves on the stack.
             if (!emit1(JSOP_POP)) {                             // ...
                 return false;
             }
@@ -8363,17 +8364,17 @@ BytecodeEmitter::emitExportDefault(Binar
     MOZ_ASSERT(exportNode->isKind(ParseNodeKind::ExportDefault));
 
     ParseNode* nameNode = exportNode->left();
     if (!emitTree(nameNode)) {
         return false;
     }
 
     if (ParseNode* binding = exportNode->right()) {
-        if (!emitLexicalInitialization(binding)) {
+        if (!emitLexicalInitialization(&binding->as<NameNode>())) {
             return false;
         }
 
         if (nameNode->isDirectRHSAnonFunction()) {
             HandlePropertyName name = cx->names().default_;
             if (!setOrEmitSetFunName(nameNode, name)) {
                 return false;
             }
@@ -8799,17 +8800,17 @@ BytecodeEmitter::emitTree(ParseNode* pn,
 
       case ParseNodeKind::Object:
         if (!emitObject(&pn->as<ListNode>())) {
             return false;
         }
         break;
 
       case ParseNodeKind::Name:
-        if (!emitGetName(pn)) {
+        if (!emitGetName(&pn->as<NameNode>())) {
             return false;
         }
         break;
 
       case ParseNodeKind::TemplateStringList:
         if (!emitTemplateString(&pn->as<ListNode>())) {
             return false;
         }
--- a/js/src/frontend/BytecodeEmitter.h
+++ b/js/src/frontend/BytecodeEmitter.h
@@ -12,16 +12,17 @@
 #include "mozilla/Attributes.h"
 #include "mozilla/Span.h"
 
 #include "ds/InlineTable.h"
 #include "frontend/BCEParserHandle.h"
 #include "frontend/EitherParser.h"
 #include "frontend/JumpList.h"
 #include "frontend/NameFunctions.h"
+#include "frontend/ParseNode.h"
 #include "frontend/SharedContext.h"
 #include "frontend/SourceNotes.h"
 #include "frontend/ValueUsage.h"
 #include "vm/BytecodeUtil.h"
 #include "vm/Interpreter.h"
 #include "vm/Iteration.h"
 
 namespace js {
@@ -516,17 +517,17 @@ struct MOZ_STACK_CLASS BytecodeEmitter
     MOZ_MUST_USE bool emitUint32Operand(JSOp op, uint32_t operand);
 
     // Emit (1 + extra) bytecodes, for N bytes of op and its immediate operand.
     MOZ_MUST_USE bool emitN(JSOp op, size_t extra, ptrdiff_t* offset = nullptr);
 
     MOZ_MUST_USE bool emitNumberOp(double dval);
 
     MOZ_MUST_USE bool emitThisLiteral(ThisLiteral* pn);
-    MOZ_MUST_USE bool emitGetFunctionThis(ParseNode* pn);
+    MOZ_MUST_USE bool emitGetFunctionThis(NameNode* thisName);
     MOZ_MUST_USE bool emitGetFunctionThis(const mozilla::Maybe<uint32_t>& offset);
     MOZ_MUST_USE bool emitGetThisForSuperBase(UnaryNode* superBase);
     MOZ_MUST_USE bool emitSetThis(BinaryNode* setThisNode);
     MOZ_MUST_USE bool emitCheckDerivedClassConstructorReturn();
 
     // Handle jump opcodes and jump targets.
     MOZ_MUST_USE bool emitJumpTarget(JumpTarget* target);
     MOZ_MUST_USE bool emitJumpNoFallthrough(JSOp op, JumpList* jump);
@@ -580,24 +581,24 @@ struct MOZ_STACK_CLASS BytecodeEmitter
 
     MOZ_MUST_USE bool emitArgOp(JSOp op, uint16_t slot);
     MOZ_MUST_USE bool emitEnvCoordOp(JSOp op, EnvironmentCoordinate ec);
 
     MOZ_MUST_USE bool emitGetNameAtLocation(JSAtom* name, const NameLocation& loc);
     MOZ_MUST_USE bool emitGetName(JSAtom* name) {
         return emitGetNameAtLocation(name, lookupName(name));
     }
-    MOZ_MUST_USE bool emitGetName(ParseNode* pn);
+    MOZ_MUST_USE bool emitGetName(NameNode* name);
 
     MOZ_MUST_USE bool emitTDZCheckIfNeeded(JSAtom* name, const NameLocation& loc);
 
     MOZ_MUST_USE bool emitNameIncDec(UnaryNode* incDec);
 
     MOZ_MUST_USE bool emitDeclarationList(ListNode* declList);
-    MOZ_MUST_USE bool emitSingleDeclaration(ParseNode* declList, ParseNode* decl,
+    MOZ_MUST_USE bool emitSingleDeclaration(ListNode* declList, NameNode* decl,
                                             ParseNode* initializer);
 
     MOZ_MUST_USE bool emitNewInit();
     MOZ_MUST_USE bool emitSingletonInitialiser(ParseNode* pn);
 
     MOZ_MUST_USE bool emitPrepareIteratorResult();
     MOZ_MUST_USE bool emitFinishIteratorResult(bool done);
     MOZ_MUST_USE bool iteratorResultShape(unsigned* shape);
@@ -756,17 +757,17 @@ struct MOZ_STACK_CLASS BytecodeEmitter
     MOZ_MUST_USE bool emitSequenceExpr(ListNode* node,
                                        ValueUsage valueUsage = ValueUsage::WantValue);
 
     MOZ_NEVER_INLINE MOZ_MUST_USE bool emitIncOrDec(UnaryNode* incDec);
 
     MOZ_MUST_USE bool emitConditionalExpression(ConditionalExpression& conditional,
                                                 ValueUsage valueUsage = ValueUsage::WantValue);
 
-    bool isRestParameter(ParseNode* pn);
+    bool isRestParameter(ParseNode* expr);
 
     MOZ_MUST_USE bool emitArguments(ListNode* argsList, bool isCall, bool isSpread,
                                     CallOrNewEmitter& cone);
     MOZ_MUST_USE bool emitCallOrNew(BinaryNode* callNode,
                                     ValueUsage valueUsage = ValueUsage::WantValue);
     MOZ_MUST_USE bool emitSelfHostedCallFunction(BinaryNode* callNode);
     MOZ_MUST_USE bool emitSelfHostedResumeGenerator(BinaryNode* callNode);
     MOZ_MUST_USE bool emitSelfHostedForceInterpreter();
@@ -788,17 +789,17 @@ struct MOZ_STACK_CLASS BytecodeEmitter
 
     MOZ_MUST_USE bool emitBreak(PropertyName* label);
     MOZ_MUST_USE bool emitContinue(PropertyName* label);
 
     MOZ_MUST_USE bool emitFunctionFormalParametersAndBody(ListNode* paramsBody);
     MOZ_MUST_USE bool emitFunctionFormalParameters(ListNode* paramsBody);
     MOZ_MUST_USE bool emitInitializeFunctionSpecialNames();
     MOZ_MUST_USE bool emitFunctionBody(ParseNode* pn);
-    MOZ_MUST_USE bool emitLexicalInitialization(ParseNode* pn);
+    MOZ_MUST_USE bool emitLexicalInitialization(NameNode* name);
 
     // Emit bytecode for the spread operator.
     //
     // emitSpread expects the current index (I) of the array, the array itself
     // and the iterator to be on the stack in that order (iterator on the bottom).
     // It will pop the iterator and I, then iterate over the iterator by calling
     // |.next()| and put the results into the I-th element of array with
     // incrementing I, then push the result I (it will be original I +
deleted file mode 100644
--- a/js/src/frontend/ParseNode-inl.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
- * vim: set ts=8 sts=4 et sw=4 tw=99:
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef frontend_ParseNode_inl_h
-#define frontend_ParseNode_inl_h
-
-#include "frontend/ParseNode.h"
-
-#include "frontend/SharedContext.h"
-
-namespace js {
-namespace frontend {
-
-inline PropertyName*
-ParseNode::name() const
-{
-    MOZ_ASSERT(isKind(ParseNodeKind::Function) || isKind(ParseNodeKind::Name));
-    JSAtom* atom = isKind(ParseNodeKind::Function)
-                   ? as<CodeNode>().funbox()->function()->explicitName()
-                   : as<NameNode>().atom();
-    return atom->asPropertyName();
-}
-
-} /* namespace frontend */
-} /* namespace js */
-
-#endif /* frontend_ParseNode_inl_h */
--- a/js/src/frontend/ParseNode.cpp
+++ b/js/src/frontend/ParseNode.cpp
@@ -1,15 +1,15 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  * vim: set ts=8 sts=4 et sw=4 tw=99:
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#include "frontend/ParseNode-inl.h"
+#include "frontend/ParseNode.h"
 
 #include "mozilla/ArrayUtils.h"
 #include "mozilla/FloatingPoint.h"
 
 #include "jsnum.h"
 
 #include "frontend/Parser.h"
 
--- a/js/src/frontend/ParseNode.h
+++ b/js/src/frontend/ParseNode.h
@@ -636,16 +636,17 @@ class ParseNode
     ParseNodeArity getArity() const        { return ParseNodeArity(pn_arity); }
     bool isArity(ParseNodeArity a) const   { return getArity() == a; }
     void setArity(ParseNodeArity a)        { pn_arity = a; }
 
     bool isBinaryOperation() const {
         ParseNodeKind kind = getKind();
         return ParseNodeKind::BinOpFirst <= kind && kind <= ParseNodeKind::BinOpLast;
     }
+    inline bool isName(PropertyName* name) const;
 
     /* Boolean attributes. */
     bool isInParens() const                { return pn_parens; }
     bool isLikelyIIFE() const              { return isInParens(); }
     void setInParens(bool enabled)         { pn_parens = enabled; }
 
     bool isDirectRHSAnonFunction() const {
         return pn_rhs_anon_fun;
@@ -735,19 +736,16 @@ class ParseNode
     /*
      * If |left| is a list of the given kind/left-associative op, append
      * |right| to it and return |left|.  Otherwise return a [left, right] list.
      */
     static ParseNode*
     appendOrCreateList(ParseNodeKind kind, ParseNode* left, ParseNode* right,
                        FullParseHandler* handler, ParseContext* pc);
 
-    // include "ParseNode-inl.h" for these methods.
-    inline PropertyName* name() const;
-
     /* True if pn is a parsenode representing a literal constant. */
     bool isLiteral() const {
         return isKind(ParseNodeKind::Number) ||
                isKind(ParseNodeKind::String) ||
                isKind(ParseNodeKind::True) ||
                isKind(ParseNodeKind::False) ||
                isKind(ParseNodeKind::Null) ||
                isKind(ParseNodeKind::RawUndefined);
@@ -836,16 +834,21 @@ class NameNode : public ParseNode
 #ifdef DEBUG
     void dump(GenericPrinter& out, int indent);
 #endif
 
     JSAtom* atom() const {
         return pn_u.name.atom;
     }
 
+    PropertyName* name() const {
+        MOZ_ASSERT(isKind(ParseNodeKind::Name));
+        return atom()->asPropertyName();
+    }
+
     ParseNode* initializer() const {
         return pn_u.name.initOrStmt;
     }
 
     void setAtom(JSAtom* atom) {
         pn_u.name.atom = atom;
     }
 
@@ -854,16 +857,22 @@ class NameNode : public ParseNode
     }
 
     // Methods used by FoldConstants.cpp.
     ParseNode** unsafeInitializerReference() {
         return &pn_u.name.initOrStmt;
     }
 };
 
+inline bool
+ParseNode::isName(PropertyName* name) const
+{
+    return getKind() == ParseNodeKind::Name && as<NameNode>().name() == name;
+}
+
 class UnaryNode : public ParseNode
 {
   public:
     UnaryNode(ParseNodeKind kind, const TokenPos& pos, ParseNode* kid)
       : ParseNode(kind, JSOP_NOP, PN_UNARY, pos)
     {
         pn_u.unary.kid = kid;
     }
--- a/js/src/frontend/Parser.cpp
+++ b/js/src/frontend/Parser.cpp
@@ -30,29 +30,29 @@
 
 #include "jsnum.h"
 #include "jstypes.h"
 
 #include "builtin/ModuleObject.h"
 #include "builtin/SelfHostingDefines.h"
 #include "frontend/BytecodeCompiler.h"
 #include "frontend/FoldConstants.h"
+#include "frontend/ParseNode.h"
 #include "frontend/TokenStream.h"
 #include "irregexp/RegExpParser.h"
 #include "vm/BytecodeUtil.h"
 #include "vm/JSAtom.h"
 #include "vm/JSContext.h"
 #include "vm/JSFunction.h"
 #include "vm/JSScript.h"
 #include "vm/RegExpObject.h"
 #include "vm/StringType.h"
 #include "wasm/AsmJS.h"
 
 #include "frontend/ParseContext-inl.h"
-#include "frontend/ParseNode-inl.h"
 #include "vm/EnvironmentObject-inl.h"
 
 using namespace js;
 
 using mozilla::Maybe;
 using mozilla::Nothing;
 using mozilla::PodCopy;
 using mozilla::PodZero;
--- a/js/src/wasm/AsmJS.cpp
+++ b/js/src/wasm/AsmJS.cpp
@@ -26,16 +26,17 @@
 #include "mozilla/Unused.h"
 
 #include <new>
 
 #include "jsmath.h"
 #include "jsutil.h"
 
 #include "builtin/String.h"
+#include "frontend/ParseNode.h"
 #include "frontend/Parser.h"
 #include "gc/Policy.h"
 #include "js/MemoryMetrics.h"
 #include "js/Printf.h"
 #include "js/SourceBufferHolder.h"
 #include "js/StableStringChars.h"
 #include "js/Wrapper.h"
 #include "util/StringBuffer.h"
@@ -47,17 +48,16 @@
 #include "wasm/WasmCompile.h"
 #include "wasm/WasmGenerator.h"
 #include "wasm/WasmInstance.h"
 #include "wasm/WasmIonCompile.h"
 #include "wasm/WasmJS.h"
 #include "wasm/WasmSerialize.h"
 #include "wasm/WasmValidate.h"
 
-#include "frontend/ParseNode-inl.h"
 #include "vm/ArrayBufferObject-inl.h"
 #include "vm/JSObject-inl.h"
 
 using namespace js;
 using namespace js::frontend;
 using namespace js::jit;
 using namespace js::wasm;
 
@@ -698,17 +698,17 @@ static inline ParseNode*
 MaybeInitializer(ParseNode* pn)
 {
     return pn->as<NameNode>().initializer();
 }
 
 static inline bool
 IsUseOfName(ParseNode* pn, PropertyName* name)
 {
-    return pn->isKind(ParseNodeKind::Name) && pn->name() == name;
+    return pn->isName(name);
 }
 
 static inline bool
 IsIgnoredDirectiveName(JSContext* cx, JSAtom* atom)
 {
     return atom != cx->names().useStrict;
 }
 
@@ -2245,17 +2245,17 @@ IsCallToGlobal(ModuleValidator& m, Parse
         return false;
     }
 
     ParseNode* callee = CallCallee(pn);
     if (!callee->isKind(ParseNodeKind::Name)) {
         return false;
     }
 
-    *global = m.lookupGlobal(callee->name());
+    *global = m.lookupGlobal(callee->as<NameNode>().name());
     return !!*global;
 }
 
 static bool
 IsCoercionCall(ModuleValidator& m, ParseNode* pn, Type* coerceTo, ParseNode** coercedExpr)
 {
     const ModuleValidator::Global* global;
     if (!IsCallToGlobal(m, pn, &global)) {
@@ -2766,21 +2766,22 @@ static bool
 CheckArgument(ModuleValidator& m, ParseNode* arg, PropertyName** name)
 {
     *name = nullptr;
 
     if (!arg->isKind(ParseNodeKind::Name)) {
         return m.fail(arg, "argument is not a plain name");
     }
 
-    if (!CheckIdentifier(m, arg, arg->name())) {
-        return false;
-    }
-
-    *name = arg->name();
+    PropertyName* argName = arg->as<NameNode>().name();;
+    if (!CheckIdentifier(m, arg, argName)) {
+        return false;
+    }
+
+    *name = argName;
     return true;
 }
 
 static bool
 CheckModuleArgument(ModuleValidator& m, ParseNode* arg, PropertyName** name)
 {
     if (!CheckArgument(m, arg, name)) {
         return false;
@@ -3003,17 +3004,17 @@ CheckNewArrayView(ModuleValidator& m, Pr
         if (!IsArrayViewCtorName(m, field, &type)) {
             return m.fail(ctorExpr, "could not match typed array name");
         }
     } else {
         if (!ctorExpr->isKind(ParseNodeKind::Name)) {
             return m.fail(ctorExpr, "expecting name of imported array view constructor");
         }
 
-        PropertyName* globalName = ctorExpr->name();
+        PropertyName* globalName = ctorExpr->as<NameNode>().name();
         const ModuleValidator::Global* global = m.lookupGlobal(globalName);
         if (!global) {
             return m.failName(ctorExpr, "%s not found in module global scope", globalName);
         }
 
         if (global->which() != ModuleValidator::Global::ArrayViewCtor) {
             return m.failName(ctorExpr, "%s must be an imported array view constructor", globalName);
         }
@@ -3078,72 +3079,74 @@ CheckGlobalDotImport(ModuleValidator& m,
         }
         return m.failName(base, "expecting %s.Math", globalName);
     }
 
     if (!base->isKind(ParseNodeKind::Name)) {
         return m.fail(base, "expected name of variable or parameter");
     }
 
-    if (base->name() == m.globalArgumentName()) {
+    auto baseName = base->as<NameNode>().name();
+    if (baseName == m.globalArgumentName()) {
         if (field == m.cx()->names().NaN) {
             return m.addGlobalConstant(varName, GenericNaN(), field);
         }
         if (field == m.cx()->names().Infinity) {
             return m.addGlobalConstant(varName, PositiveInfinity<double>(), field);
         }
 
         Scalar::Type type;
         if (IsArrayViewCtorName(m, field, &type)) {
             return m.addArrayViewCtor(varName, type, field);
         }
 
         return m.failName(initNode, "'%s' is not a standard constant or typed array name", field);
     }
 
-    if (base->name() != m.importArgumentName()) {
+    if (baseName != m.importArgumentName()) {
         return m.fail(base, "expected global or import name");
     }
 
     return m.addFFI(varName, field);
 }
 
 static bool
 CheckModuleGlobal(ModuleValidator& m, ParseNode* var, bool isConst)
 {
     if (!var->isKind(ParseNodeKind::Name)) {
         return m.fail(var, "import variable is not a plain name");
     }
 
-    if (!CheckModuleLevelName(m, var, var->name())) {
+    PropertyName* varName = var->as<NameNode>().name();
+    if (!CheckModuleLevelName(m, var, varName)) {
         return false;
     }
 
     ParseNode* initNode = MaybeInitializer(var);
     if (!initNode) {
         return m.fail(var, "module import needs initializer");
     }
 
     if (IsNumericLiteral(m, initNode)) {
-        return CheckGlobalVariableInitConstant(m, var->name(), initNode, isConst);
+        return CheckGlobalVariableInitConstant(m, varName, initNode, isConst);
     }
 
     if (initNode->isKind(ParseNodeKind::BitOr) ||
         initNode->isKind(ParseNodeKind::Pos) ||
         initNode->isKind(ParseNodeKind::Call))
     {
-        return CheckGlobalVariableInitImport(m, var->name(), initNode, isConst);
+        return CheckGlobalVariableInitImport(m, varName, initNode, isConst);
     }
 
     if (initNode->isKind(ParseNodeKind::New)) {
-        return CheckNewArrayView(m, var->name(), initNode);
+        return CheckNewArrayView(m, varName, initNode);
     }
 
     if (initNode->isKind(ParseNodeKind::Dot)) {
-        return CheckGlobalDotImport(m, var->name(), initNode);
+        return CheckGlobalDotImport(m, varName, initNode);
     }
 
     return m.fail(initNode, "unsupported import expression");
 }
 
 static bool
 CheckModuleProcessingDirectives(ModuleValidator& m)
 {
@@ -3278,17 +3281,17 @@ CheckArguments(FunctionValidator& f, Par
     *stmtIter = stmt;
     return true;
 }
 
 static bool
 IsLiteralOrConst(FunctionValidator& f, ParseNode* pn, NumLit* lit)
 {
     if (pn->isKind(ParseNodeKind::Name)) {
-        const ModuleValidator::Global* global = f.lookupGlobal(pn->name());
+        const ModuleValidator::Global* global = f.lookupGlobal(pn->as<NameNode>().name());
         if (!global || global->which() != ModuleValidator::Global::ConstantLiteral) {
             return false;
         }
 
         *lit = global->constLiteralValue();
         return true;
     }
 
@@ -3321,17 +3324,17 @@ CheckFinalReturn(FunctionValidator& f, P
 
 static bool
 CheckVariable(FunctionValidator& f, ParseNode* var, ValTypeVector* types, Vector<NumLit>* inits)
 {
     if (!var->isKind(ParseNodeKind::Name)) {
         return f.fail(var, "local variable is not a plain name");
     }
 
-    PropertyName* name = var->name();
+    PropertyName* name = var->as<NameNode>().name();
 
     if (!CheckIdentifier(f.m(), var, name)) {
         return false;
     }
 
     ParseNode* initNode = MaybeInitializer(var);
     if (!initNode) {
         return f.failName(var, "var '%s' needs explicit type declaration via an initial value", name);
@@ -3409,17 +3412,17 @@ CheckNumericLiteral(FunctionValidator& f
     }
     *type = Type::lit(lit);
     return f.writeConstExpr(lit);
 }
 
 static bool
 CheckVarRef(FunctionValidator& f, ParseNode* varRef, Type* type)
 {
-    PropertyName* name = varRef->name();
+    PropertyName* name = varRef->as<NameNode>().name();
 
     if (const FunctionValidator::Local* local = f.lookupLocal(name)) {
         if (!f.encoder().writeOp(Op::GetLocal)) {
             return false;
         }
         if (!f.encoder().writeVarU32(local->slot)) {
             return false;
         }
@@ -3468,17 +3471,17 @@ static const int32_t NoMask = -1;
 static bool
 CheckArrayAccess(FunctionValidator& f, ParseNode* viewName, ParseNode* indexExpr,
                  Scalar::Type* viewType)
 {
     if (!viewName->isKind(ParseNodeKind::Name)) {
         return f.fail(viewName, "base of array access must be a typed array view name");
     }
 
-    const ModuleValidator::Global* global = f.lookupGlobal(viewName->name());
+    const ModuleValidator::Global* global = f.lookupGlobal(viewName->as<NameNode>().name());
     if (!global || !global->isAnyArrayView()) {
         return f.fail(viewName, "base of array access must be a typed array view name");
     }
 
     *viewType = global->viewType();
 
     uint32_t index;
     if (IsLiteralOrConstInt(f, indexExpr, &index)) {
@@ -3701,17 +3704,17 @@ CheckStoreArray(FunctionValidator& f, Pa
 
     *type = rhsType;
     return true;
 }
 
 static bool
 CheckAssignName(FunctionValidator& f, ParseNode* lhs, ParseNode* rhs, Type* type)
 {
-    RootedPropertyName name(f.cx(), lhs->name());
+    RootedPropertyName name(f.cx(), lhs->as<NameNode>().name());
 
     if (const FunctionValidator::Local* lhsVar = f.lookupLocal(name)) {
         Type rhsType;
         if (!CheckExpr(f, rhs, &rhsType)) {
             return false;
         }
 
         if (!f.encoder().writeOp(Op::TeeLocal)) {
@@ -4101,17 +4104,17 @@ CheckFuncPtrCall(FunctionValidator& f, P
     ParseNode* callee = CallCallee(callNode);
     ParseNode* tableNode = ElemBase(callee);
     ParseNode* indexExpr = ElemIndex(callee);
 
     if (!tableNode->isKind(ParseNodeKind::Name)) {
         return f.fail(tableNode, "expecting name of function-pointer array");
     }
 
-    PropertyName* name = tableNode->name();
+    PropertyName* name = tableNode->as<NameNode>().name();
     if (const ModuleValidator::Global* existing = f.lookupGlobal(name)) {
         if (existing->which() != ModuleValidator::Global::Table) {
             return f.failName(tableNode, "'%s' is not the name of a function-pointer array", name);
         }
     }
 
     if (!indexExpr->isKind(ParseNodeKind::BitAnd)) {
         return f.fail(indexExpr, "function-pointer table index expression needs & mask");
@@ -4168,17 +4171,17 @@ CheckIsExternType(FunctionValidator& f, 
     return true;
 }
 
 static bool
 CheckFFICall(FunctionValidator& f, ParseNode* callNode, unsigned ffiIndex, Type ret, Type* type)
 {
     MOZ_ASSERT(ret.isCanonical());
 
-    PropertyName* calleeName = CallCallee(callNode)->name();
+    PropertyName* calleeName = CallCallee(callNode)->as<NameNode>().name();
 
     if (ret.isFloat()) {
         return f.fail(callNode, "FFI calls can't return float");
     }
 
     ValTypeVector args;
     if (!CheckCallArgs<CheckIsExternType>(f, callNode, &args)) {
         return false;
@@ -4461,31 +4464,31 @@ CheckCoercedCall(FunctionValidator& f, P
     if (callee->isKind(ParseNodeKind::Elem)) {
         return CheckFuncPtrCall(f, call, ret, type);
     }
 
     if (!callee->isKind(ParseNodeKind::Name)) {
         return f.fail(callee, "unexpected callee expression type");
     }
 
-    PropertyName* calleeName = callee->name();
+    PropertyName* calleeName = callee->as<NameNode>().name();
 
     if (const ModuleValidator::Global* global = f.lookupGlobal(calleeName)) {
         switch (global->which()) {
           case ModuleValidator::Global::FFI:
             return CheckFFICall(f, call, global->ffiIndex(), ret, type);
           case ModuleValidator::Global::MathBuiltinFunction:
             return CheckCoercedMathBuiltinCall(f, call, global->mathBuiltinFunction(), ret, type);
           case ModuleValidator::Global::ConstantLiteral:
           case ModuleValidator::Global::ConstantImport:
           case ModuleValidator::Global::Variable:
           case ModuleValidator::Global::Table:
           case ModuleValidator::Global::ArrayView:
           case ModuleValidator::Global::ArrayViewCtor:
-            return f.failName(callee, "'%s' is not callable function", callee->name());
+            return f.failName(callee, "'%s' is not callable function", calleeName);
           case ModuleValidator::Global::Function:
             break;
         }
     }
 
     return CheckInternalCall(f, call, calleeName, ret, type);
 }
 
@@ -6009,17 +6012,17 @@ CheckFuncPtrTable(ModuleValidator& m, Pa
 
     Uint32Vector elemFuncDefIndices;
     const FuncType* sig = nullptr;
     for (ParseNode* elem = ListHead(arrayLiteral); elem; elem = NextNode(elem)) {
         if (!elem->isKind(ParseNodeKind::Name)) {
             return m.fail(elem, "function-pointer table's elements must be names of functions");
         }
 
-        PropertyName* funcName = elem->name();
+        PropertyName* funcName = elem->as<NameNode>().name();
         const ModuleValidator::Func* func = m.lookupFuncDef(funcName);
         if (!func) {
             return m.fail(elem, "function-pointer table's elements must be names of functions");
         }
 
         const FuncType& funcSig = m.env().types[func->sigIndex()].funcType();
         if (sig) {
             if (*sig != funcSig) {
@@ -6035,17 +6038,17 @@ CheckFuncPtrTable(ModuleValidator& m, Pa
     }
 
     FuncType copy;
     if (!copy.clone(*sig)) {
         return false;
     }
 
     uint32_t tableIndex;
-    if (!CheckFuncPtrTableAgainstExisting(m, var, var->name(), std::move(copy), mask, &tableIndex)) {
+    if (!CheckFuncPtrTableAgainstExisting(m, var, var->as<NameNode>().name(), std::move(copy), mask, &tableIndex)) {
         return false;
     }
 
     if (!m.defineFuncPtrTable(tableIndex, std::move(elemFuncDefIndices))) {
         return m.fail(var, "duplicate function-pointer definition");
     }
 
     return true;
@@ -6083,17 +6086,17 @@ CheckFuncPtrTables(ModuleValidator& m)
 
 static bool
 CheckModuleExportFunction(ModuleValidator& m, ParseNode* pn, PropertyName* maybeFieldName = nullptr)
 {
     if (!pn->isKind(ParseNodeKind::Name)) {
         return m.fail(pn, "expected name of exported function");
     }
 
-    PropertyName* funcName = pn->name();
+    PropertyName* funcName = pn->as<NameNode>().name();
     const ModuleValidator::Func* func = m.lookupFuncDef(funcName);
     if (!func) {
         return m.failName(pn, "function '%s' not found", funcName);
     }
 
     return m.addExportField(*func, maybeFieldName);
 }
 
@@ -6997,17 +7000,17 @@ class ModuleCharsForStore : ModuleChars
         // not present in the source so we must manually explicitly serialize
         // and match the formals as a Vector of PropertyName.
         isFunCtor_ = parser.pc->isStandaloneFunctionBody();
         if (isFunCtor_) {
             unsigned numArgs;
             CodeNode* functionNode = parser.pc->functionBox()->functionNode;
             ParseNode* arg = FunctionFormalParametersList(functionNode, &numArgs);
             for (unsigned i = 0; i < numArgs; i++, arg = arg->pn_next) {
-                UniqueChars name = StringToNewUTF8CharsZ(nullptr, *arg->name());
+                UniqueChars name = StringToNewUTF8CharsZ(nullptr, *arg->as<NameNode>().name());
                 if (!name || !funCtorArgs_.append(std::move(name))) {
                     return false;
                 }
             }
         }
 
         return true;
     }
@@ -7090,17 +7093,17 @@ class ModuleCharsForLookup : ModuleChars
             }
             unsigned numArgs;
             CodeNode* functionNode = parser.pc->functionBox()->functionNode;
             ParseNode* arg = FunctionFormalParametersList(functionNode, &numArgs);
             if (funCtorArgs_.length() != numArgs) {
                 return false;
             }
             for (unsigned i = 0; i < funCtorArgs_.length(); i++, arg = arg->pn_next) {
-                UniqueChars name = StringToNewUTF8CharsZ(nullptr, *arg->name());
+                UniqueChars name = StringToNewUTF8CharsZ(nullptr, *arg->as<NameNode>().name());
                 if (!name || strcmp(funCtorArgs_[i].get(), name.get())) {
                     return false;
                 }
             }
         }
         return true;
     }
 };