Merge inbound to mozilla-central r=merge a=merge
authorCsoregi Natalia <ncsoregi@mozilla.com>
Thu, 21 Dec 2017 12:01:59 +0200
changeset 451389 41084549f30fe029c96f19bcd1fbfd6f209df874
parent 451352 06a19fbe2581a81e6908b4810f8aa302f1516145 (current diff)
parent 451388 c6297aca62a422e4a8988a9a8b186e22d737aa99 (diff)
child 451390 eeb99638dc7a5e635aae2c6c83d8b8dd74364b1a
push id1648
push usermtabara@mozilla.com
push dateThu, 01 Mar 2018 12:45:47 +0000
treeherdermozilla-release@cbb9688c2eeb [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge, merge
milestone59.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge inbound to mozilla-central r=merge a=merge
browser/components/preferences/donottrack.xul
browser/locales/en-US/chrome/browser/preferences/donottrack.dtd
dom/base/Element.cpp
dom/base/Element.h
dom/media/CubebUtils.cpp
dom/webidl/Element.webidl
--- a/accessible/xul/XULListboxAccessible.cpp
+++ b/accessible/xul/XULListboxAccessible.cpp
@@ -151,17 +151,17 @@ XULListboxAccessible::Value(nsString& aV
   }
 }
 
 role
 XULListboxAccessible::NativeRole()
 {
   // A richlistbox is used with the new autocomplete URL bar, and has a parent
   // popup <panel>.
-  if (mContent->GetParent()->IsXULElement(nsGkAtoms::panel))
+  if (mContent->GetParent() && mContent->GetParent()->IsXULElement(nsGkAtoms::panel))
     return roles::COMBOBOX_LIST;
 
   return IsMulticolumn() ? roles::TABLE : roles::LISTBOX;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // XULListboxAccessible: Table
 
--- a/browser/branding/nightly/configure.sh
+++ b/browser/branding/nightly/configure.sh
@@ -1,5 +1,7 @@
 # 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/.
 
 MOZ_APP_DISPLAYNAME=Nightly
+MOZ_MACBUNDLE_ID=nightly
+
deleted file mode 100644
--- a/browser/components/preferences/donottrack.xul
+++ /dev/null
@@ -1,42 +0,0 @@
-<?xml version="1.0"?>
-
-<!-- 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/. -->
-
-<?xml-stylesheet href="chrome://global/skin/"?>
-<?xml-stylesheet href="chrome://browser/skin/preferences/preferences.css"?>
-
-<!DOCTYPE prefwindow [
-<!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd">
-<!ENTITY % doNotTrackDTD SYSTEM "chrome://browser/locale/preferences/donottrack.dtd">
-%brandDTD;
-%doNotTrackDTD;
-]>
-
-<prefwindow id="DoNotTrackDialog" type="child"
-            xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
-            xmlns:html="http://www.w3.org/1999/xhtml"
-            title="&window.title;"
-            style="width: &window.width;; height: &window.height;;"
-            dlgbuttons="accept,cancel">
-  <prefpane>
-    <preferences>
-      <preference id="privacy.donottrackheader.enabled"
-                  name="privacy.donottrackheader.enabled"
-                  type="bool"/>
-    </preferences>
-    <hbox align="center" pack="start">
-      <!-- Work around focus ring not showing properly. -->
-      <spacer style="width: 1em;"/>
-      <checkbox label="&doNotTrackCheckbox2.label;"
-                accesskey="&doNotTrackCheckbox2.accesskey;"
-                preference="privacy.donottrackheader.enabled"/>
-    </hbox>
-    <description flex="1" class="doNotTrackLearnMore">
-      &doNotTrackTPInfo.description;
-      <label class="text-link"
-             href="https://www.mozilla.org/dnt">&doNotTrackLearnMore.label;</label>
-    </description>
-  </prefpane>
-</prefwindow>
--- a/browser/components/preferences/in-content/privacy.js
+++ b/browser/components/preferences/in-content/privacy.js
@@ -619,24 +619,16 @@ var gPrivacyPane = {
       brandShortName: brandName,
       windowTitle: bundlePreferences.getString("blockliststitle"),
       introText: bundlePreferences.getString("blockliststext")
     };
     gSubDialog.open("chrome://browser/content/preferences/blocklists.xul",
       null, params);
   },
 
-  /**
-   * Displays the Do Not Track settings dialog.
-   */
-  showDoNotTrackSettings() {
-    gSubDialog.open("chrome://browser/content/preferences/donottrack.xul",
-      "resizable=no");
-  },
-
   // HISTORY
 
   /*
    * Preferences:
    *
    * places.history.enabled
    * - whether history is enabled or not
    * browser.formfill.enable
--- a/browser/components/preferences/jar.mn
+++ b/browser/components/preferences/jar.mn
@@ -7,17 +7,16 @@ browser.jar:
     content/browser/preferences/applicationManager.js
     content/browser/preferences/blocklists.xul
     content/browser/preferences/blocklists.js
 *   content/browser/preferences/colors.xul
 *   content/browser/preferences/cookies.xul
     content/browser/preferences/cookies.js
 *   content/browser/preferences/connection.xul
     content/browser/preferences/connection.js
-    content/browser/preferences/donottrack.xul
 *   content/browser/preferences/fonts.xul
     content/browser/preferences/fonts.js
     content/browser/preferences/handlers.xml
     content/browser/preferences/handlers.css
 *   content/browser/preferences/languages.xul
     content/browser/preferences/languages.js
     content/browser/preferences/permissions.xul
     content/browser/preferences/sitePermissions.xul
deleted file mode 100644
--- a/browser/locales/en-US/chrome/browser/preferences/donottrack.dtd
+++ /dev/null
@@ -1,13 +0,0 @@
-<!-- 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/. -->
-
-<!ENTITY window.title                 "Do Not Track">
-<!ENTITY window.width                 "50em">
-<!ENTITY window.height                "10em">
-
-<!ENTITY doNotTrackCheckbox2.label    "Always apply Do Not Track">
-<!ENTITY doNotTrackCheckbox2.accesskey "A">
-
-<!ENTITY doNotTrackTPInfo.description "&brandShortName; will send a signal that you don’t want to be tracked whenever Tracking Protection is on.">
-<!ENTITY doNotTrackLearnMore.label    "Learn More">
--- a/browser/locales/jar.mn
+++ b/browser/locales/jar.mn
@@ -67,17 +67,16 @@
     locale/browser/preferences/applications.dtd       (%chrome/browser/preferences/applications.dtd)
     locale/browser/preferences/blocklists.dtd         (%chrome/browser/preferences/blocklists.dtd)
     locale/browser/preferences/colors.dtd             (%chrome/browser/preferences/colors.dtd)
     locale/browser/preferences/connection.dtd         (%chrome/browser/preferences/connection.dtd)
     locale/browser/preferences/containers.dtd         (%chrome/browser/preferences/containers.dtd)
     locale/browser/preferences/containers.properties     (%chrome/browser/preferences/containers.properties)
     locale/browser/preferences/content.dtd            (%chrome/browser/preferences/content.dtd)
     locale/browser/preferences/cookies.dtd            (%chrome/browser/preferences/cookies.dtd)
-    locale/browser/preferences/donottrack.dtd         (%chrome/browser/preferences/donottrack.dtd)
     locale/browser/preferences/fonts.dtd              (%chrome/browser/preferences/fonts.dtd)
     locale/browser/preferences/languages.dtd          (%chrome/browser/preferences/languages.dtd)
     locale/browser/preferences/main.dtd               (%chrome/browser/preferences/main.dtd)
     locale/browser/preferences/permissions.dtd        (%chrome/browser/preferences/permissions.dtd)
     locale/browser/preferences/preferences.dtd        (%chrome/browser/preferences/preferences.dtd)
     locale/browser/preferences/preferences.properties     (%chrome/browser/preferences/preferences.properties)
     locale/browser/preferences/privacy.dtd            (%chrome/browser/preferences/privacy.dtd)
     locale/browser/preferences/search.dtd             (%chrome/browser/preferences/search.dtd)
new file mode 100644
--- /dev/null
+++ b/dom/animation/test/crashtests/1309198-1.html
@@ -0,0 +1,40 @@
+<script>
+function start() {
+  o53=document.createElement('frameset');
+  o254=document.createElement('iframe');
+  o280=document.createElement('audio');
+  o317=document.documentElement;
+  o508=document.createElement('li');
+  o508.appendChild(o317);
+  o590=document.createElement('li');
+  o594=document.createElement('track');
+  o280.appendChild(o594);
+  o647=document.createElement('ol');
+  o654=document.createElement('li');
+  o647.appendChild(o654);
+  o654.insertAdjacentHTML('beforebegin','<iframe>');
+  document.write('<html><body></body></html>');
+  o955=document.documentElement;
+  document.documentElement.appendChild(o647);
+  o590.appendChild(o955);
+  document.close();
+  document.write('<html><body></body></html>');
+  document.documentElement.appendChild(o590);
+  document.documentElement.appendChild(o254);
+  o280.controls^=1;
+  SpecialPowers.forceGC();
+  o317.insertAdjacentHTML('afterend','<iframe>');
+  document.documentElement.appendChild(o280);
+  o2695=document.implementation.createHTMLDocument();
+  o2695.body.appendChild(o254);
+  o53.onerror=f0;
+  document.documentElement.appendChild(o508);
+  o2803=frames[1].document;
+  o2803.getAnimations();
+}
+function f0() {
+  o2803.write('<html><body></body></html>');
+  SpecialPowers.forceCC();
+}
+</script>
+<body onload="start()"></body>
--- a/dom/animation/test/crashtests/crashtests.list
+++ b/dom/animation/test/crashtests/crashtests.list
@@ -9,16 +9,17 @@ pref(dom.animations-api.core.enabled,tru
 pref(dom.animations-api.core.enabled,true) load 1272475-1.html
 pref(dom.animations-api.core.enabled,true) load 1272475-2.html
 pref(dom.animations-api.core.enabled,true) load 1278485-1.html
 pref(dom.animations-api.core.enabled,true) load 1277272-1.html
 pref(dom.animations-api.core.enabled,true) load 1282691-1.html
 pref(dom.animations-api.core.enabled,true) load 1291413-1.html
 pref(dom.animations-api.core.enabled,true) load 1291413-2.html
 pref(dom.animations-api.core.enabled,true) load 1304886-1.html
+pref(dom.animations-api.core.enabled,true) load 1309198-1.html
 pref(dom.animations-api.core.enabled,true) load 1322382-1.html
 pref(dom.animations-api.core.enabled,true) load 1322291-1.html
 pref(dom.animations-api.core.enabled,true) load 1322291-2.html
 pref(dom.animations-api.core.enabled,true) load 1323114-1.html
 pref(dom.animations-api.core.enabled,true) load 1323114-2.html
 pref(dom.animations-api.core.enabled,true) load 1324554-1.html
 pref(dom.animations-api.core.enabled,true) load 1325193-1.html
 pref(dom.animations-api.core.enabled,true) load 1330190-1.html
new file mode 100644
--- /dev/null
+++ b/dom/base/crashtests/1419902.html
@@ -0,0 +1,15 @@
+<html>
+  <head>
+    <script>
+      for (let i = 0; i < 38; i++) {
+        customElements.define("custom-element_0", class extends HTMLElement {
+          constructor() {
+            try { o1 = document.createElement("custom-element_0") } catch (e) {}
+            try { o2 = window.open("data:,") } catch (e) {}
+          }
+        })
+        try { o3 = document.createElement("custom-element_0") } catch (e) {}
+      }
+    </script>
+  </head>
+</html>
--- a/dom/base/crashtests/crashtests.list
+++ b/dom/base/crashtests/crashtests.list
@@ -233,8 +233,9 @@ load 1400701.html
 load 1403377.html
 load 1405771.html
 load 1406109-1.html
 pref(dom.webcomponents.enabled,true) load 1324463.html
 pref(dom.webcomponents.customelements.enabled,true) load 1413815.html
 load 1411473.html
 pref(dom.webcomponents.enabled,false) load 1422931.html
 pref(dom.webcomponents.enabled,true) load 1419799.html
+skip-if(!browserIsRemote) pref(dom.webcomponents.customelements.enabled,true) pref(dom.disable_open_during_load,false) load 1419902.html # skip on non e10s loads, Bug 1419902
--- a/dom/base/nsFrameLoader.cpp
+++ b/dom/base/nsFrameLoader.cpp
@@ -895,18 +895,19 @@ nsFrameLoader::ReallyStartLoadingInterna
     if (!mRemoteBrowser && !TryRemoteBrowser()) {
         NS_WARNING("Couldn't create child process for iframe.");
         return NS_ERROR_FAILURE;
     }
 
     // FIXME get error codes from child
     mRemoteBrowser->LoadURL(mURIToLoad);
 
-    if (!mRemoteBrowserShown && !ShowRemoteFrame(ScreenIntSize(0, 0))) {
-      NS_WARNING("[nsFrameLoader] ReallyStartLoadingInternal tried but couldn't show remote browser.\n");
+    if (!mRemoteBrowserShown) {
+      // This can fail if it's too early to show the frame, we will retry later.
+      Unused << ShowRemoteFrame(ScreenIntSize(0, 0));
     }
 
     return NS_OK;
   }
 
   nsresult rv = MaybeCreateDocShell();
   if (NS_FAILED(rv)) {
     return rv;
--- a/dom/canvas/WebGL2ContextBuffers.cpp
+++ b/dom/canvas/WebGL2ContextBuffers.cpp
@@ -81,16 +81,18 @@ WebGL2Context::CopyBufferSubData(GLenum 
                               (writeType == WebGLBuffer::Kind::OtherData) ? "other"
                                                                           : "element");
         return;
     }
 
     const ScopedLazyBind readBind(gl, readTarget, readBuffer);
     const ScopedLazyBind writeBind(gl, writeTarget, writeBuffer);
     gl->fCopyBufferSubData(readTarget, writeTarget, readOffset, writeOffset, size);
+
+    writeBuffer->ResetLastUpdateFenceId();
 }
 
 void
 WebGL2Context::GetBufferSubData(GLenum target, GLintptr srcByteOffset,
                                 const dom::ArrayBufferView& dstData, GLuint dstElemOffset,
                                 GLuint dstElemCountOverride)
 {
     const char funcName[] = "getBufferSubData";
@@ -127,26 +129,26 @@ WebGL2Context::GetBufferSubData(GLenum t
 
     ////
 
     switch (buffer->mUsage) {
     case LOCAL_GL_STATIC_READ:
     case LOCAL_GL_STREAM_READ:
     case LOCAL_GL_DYNAMIC_READ:
         if (mCompletedFenceId < buffer->mLastUpdateFenceId) {
-            GeneratePerfWarning("%s: Reading from a buffer without checking for previous"
-                                " command completion likely causes pipeline stalls."
-                                " Please use FenceSync.",
-                                funcName);
+            GenerateWarning("%s: Reading from a buffer without checking for previous"
+                            " command completion likely causes pipeline stalls."
+                            " Please use FenceSync.",
+                            funcName);
         }
         break;
     default:
-        GeneratePerfWarning("%s: Reading from a buffer with usage other than *_READ"
-                            " causes pipeline stalls. Copy through a STREAM_READ buffer.",
-                            funcName);
+        GenerateWarning("%s: Reading from a buffer with usage other than *_READ"
+                        " causes pipeline stalls. Copy through a STREAM_READ buffer.",
+                        funcName);
         break;
     }
 
     ////
 
     const ScopedLazyBind readBind(gl, target, buffer);
 
     if (byteLen) {
--- a/dom/canvas/WebGLBuffer.cpp
+++ b/dom/canvas/WebGLBuffer.cpp
@@ -161,16 +161,18 @@ WebGLBuffer::BufferData(GLenum target, s
 
     if (mIndexCache) {
         if (!mIndexRanges.empty()) {
             mContext->GeneratePerfWarning("[%p] Invalidating %u ranges.", this,
                                           uint32_t(mIndexRanges.size()));
             mIndexRanges.clear();
         }
     }
+
+    ResetLastUpdateFenceId();
 }
 
 void
 WebGLBuffer::BufferSubData(GLenum target, size_t dstByteOffset, size_t dataLen,
                            const void* data) const
 {
     const char funcName[] = "bufferSubData";
 
@@ -192,16 +194,18 @@ WebGLBuffer::BufferSubData(GLenum target
     }
 
     ////
 
     const auto& gl = mContext->gl;
     const ScopedLazyBind lazyBind(gl, target, this);
 
     gl->fBufferSubData(target, dstByteOffset, dataLen, uploadData);
+
+    ResetLastUpdateFenceId();
 }
 
 bool
 WebGLBuffer::ValidateRange(const char* funcName, size_t byteOffset, size_t byteLen) const
 {
     auto availLength = mByteLength;
     if (byteOffset > availLength) {
         mContext->ErrorInvalidValue("%s: Offset passes the end of the buffer.", funcName);
@@ -404,16 +408,22 @@ WebGLBuffer::ValidateCanBindToTarget(con
 
     const auto dataType = (mContent == WebGLBuffer::Kind::OtherData) ? "other"
                                                                      : "element";
     mContext->ErrorInvalidOperation("%s: Buffer already contains %s data.", funcName,
                                     dataType);
     return false;
 }
 
+void
+WebGLBuffer::ResetLastUpdateFenceId() const
+{
+    mLastUpdateFenceId = mContext->mNextFenceId;
+}
+
 JSObject*
 WebGLBuffer::WrapObject(JSContext* cx, JS::Handle<JSObject*> givenProto)
 {
     return dom::WebGLBufferBinding::Wrap(cx, this, givenProto);
 }
 
 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_0(WebGLBuffer)
 
--- a/dom/canvas/WebGLBuffer.h
+++ b/dom/canvas/WebGLBuffer.h
@@ -100,17 +100,17 @@ protected:
 
     void InvalidateCacheRange(uint64_t byteOffset, uint64_t byteLength) const;
 
     Kind mContent;
     GLenum mUsage;
     size_t mByteLength;
     size_t mTFBindCount;
     size_t mNonTFBindCount;
-    uint64_t mLastUpdateFenceId = 0;
+    mutable uint64_t mLastUpdateFenceId = 0;
 
     struct IndexRange final {
         GLenum type;
         uint64_t byteOffset;
         uint32_t indexCount;
 
         bool operator<(const IndexRange& x) const {
             if (type != x.type)
@@ -123,13 +123,15 @@ protected:
         }
     };
 
     UniqueBuffer mIndexCache;
     mutable std::map<IndexRange, Maybe<uint32_t>> mIndexRanges;
 
 public:
     CacheMapInvalidator mFetchInvalidator;
+
+    void ResetLastUpdateFenceId() const;
 };
 
 } // namespace mozilla
 
 #endif // WEBGL_BUFFER_H_
--- a/dom/canvas/WebGLContextDraw.cpp
+++ b/dom/canvas/WebGLContextDraw.cpp
@@ -332,16 +332,20 @@ public:
                 if (buffer->IsBoundForNonTF()) {
                     mWebGL->ErrorInvalidOperation("%s: Transform feedback varying %u's"
                                                   " buffer is bound for"
                                                   " non-transform-feedback.",
                                                   funcName, i);
                     *out_error = true;
                     return;
                 }
+
+                // Technically we don't know that this will be updated yet, but we can
+                // speculatively mark it.
+                buffer->ResetLastUpdateFenceId();
             }
         }
 
         ////
 
         const auto& fetchLimits = linkInfo->GetDrawFetchLimits(funcName);
         if (!fetchLimits) {
             *out_error = true;
--- a/dom/canvas/WebGLContextGL.cpp
+++ b/dom/canvas/WebGLContextGL.cpp
@@ -1418,16 +1418,18 @@ WebGLContext::ReadPixels(GLint x, GLint 
     uint32_t bytesAfterOffset = 0;
     if (checkedBytesAfterOffset.isValid()) {
         bytesAfterOffset = checkedBytesAfterOffset.value();
     }
 
     const ScopedLazyBind lazyBind(gl, LOCAL_GL_PIXEL_PACK_BUFFER, buffer);
 
     ReadPixelsImpl(x, y, width, height, format, type, (void*)offset, bytesAfterOffset);
+
+    buffer->ResetLastUpdateFenceId();
 }
 
 static webgl::PackingInfo
 DefaultReadPixelPI(const webgl::FormatUsageInfo* usage)
 {
     MOZ_ASSERT(usage->IsRenderable());
 
     switch (usage->format->componentType) {
--- a/dom/media/CubebUtils.cpp
+++ b/dom/media/CubebUtils.cpp
@@ -45,17 +45,17 @@
 #define MASK_3F1_LFE    (MASK_3F1 | (1 << AudioConfig::CHANNEL_LFE))
 #define MASK_2F2        (MASK_STEREO | (1 << AudioConfig::CHANNEL_LS) | (1 << AudioConfig::CHANNEL_RS))
 #define MASK_2F2_LFE    (MASK_2F2 | (1 << AudioConfig::CHANNEL_LFE))
 #define MASK_3F2        (MASK_3F | (1 << AudioConfig::CHANNEL_LS) | (1 << AudioConfig::CHANNEL_RS))
 #define MASK_3F2_LFE    (MASK_3F2 | (1 << AudioConfig::CHANNEL_LFE))
 #define MASK_3F3R_LFE   (MASK_3F2_LFE | (1 << AudioConfig::CHANNEL_RCENTER))
 #define MASK_3F4_LFE    (MASK_3F2_LFE | (1 << AudioConfig::CHANNEL_RLS) | (1 << AudioConfig::CHANNEL_RRS))
 
-#if defined(XP_LINUX) && !defined(MOZ_WIDGET_ANDROID)
+#if (defined(XP_LINUX) && !defined(MOZ_WIDGET_ANDROID)) || defined(XP_MACOSX)
 #define MOZ_CUBEB_REMOTING
 #endif
 
 extern "C" {
 // These functions are provided by audioipc-server crate
 extern void* audioipc_server_start();
 extern mozilla::ipc::FileDescriptor::PlatformHandleType audioipc_server_new_client(void*);
 extern void audioipc_server_stop(void*);
--- a/dom/workers/ServiceWorkerEvents.cpp
+++ b/dom/workers/ServiceWorkerEvents.cpp
@@ -353,16 +353,18 @@ public:
     }
 
      nsCOMPtr<nsIInputStream> body;
     if (preferredAltDataType.Equals(altDataType)) {
       body = mInternalResponse->TakeAlternativeBody();
     }
     if (!body) {
       mInternalResponse->GetUnfilteredBody(getter_AddRefs(body));
+    } else {
+      Telemetry::ScalarAdd(Telemetry::ScalarID::SW_ALTERNATIVE_BODY_USED_COUNT, 1);
     }
 
     RefPtr<BodyCopyHandle> copyHandle;
     copyHandle = new BodyCopyHandle(Move(mClosure));
 
     rv = mChannel->StartSynthesizedResponse(body, copyHandle, cacheInfoChannel,
                                             mResponseURLSpec,
                                             mInternalResponse->IsRedirected());
--- a/gfx/gl/GLLibraryEGL.h
+++ b/gfx/gl/GLLibraryEGL.h
@@ -13,42 +13,26 @@
 #include "mozilla/StaticMutex.h"
 #include "mozilla/ThreadLocal.h"
 #include "nsIFile.h"
 #include "GeckoProfiler.h"
 
 #include <bitset>
 #include <vector>
 
-#ifdef XP_WIN
-    #ifndef WIN32_LEAN_AND_MEAN
-        #define WIN32_LEAN_AND_MEAN 1
-    #endif
-
-    #include <windows.h>
-
-    typedef HDC EGLNativeDisplayType;
-    typedef HBITMAP EGLNativePixmapType;
-    typedef HWND EGLNativeWindowType;
-#else
-    typedef void* EGLNativeDisplayType;
-    typedef void* EGLNativePixmapType;
-    typedef void* EGLNativeWindowType;
-
-    #ifdef ANDROID
-        // We only need to explicitly dlopen egltrace
-        // on android as we can use LD_PRELOAD or other tricks
-        // on other platforms. We look for it in /data/local
-        // as that's writeable by all users
-        //
-        // This should really go in GLLibraryEGL.cpp but we currently reference
-        // APITRACE_LIB in GLContextProviderEGL.cpp. Further refactoring
-        // will come in subsequent patches on Bug 732865
-        #define APITRACE_LIB "/data/local/tmp/egltrace.so"
-    #endif
+#ifdef ANDROID
+    // We only need to explicitly dlopen egltrace
+    // on android as we can use LD_PRELOAD or other tricks
+    // on other platforms. We look for it in /data/local
+    // as that's writeable by all users
+    //
+    // This should really go in GLLibraryEGL.cpp but we currently reference
+    // APITRACE_LIB in GLContextProviderEGL.cpp. Further refactoring
+    // will come in subsequent patches on Bug 732865
+    #define APITRACE_LIB "/data/local/tmp/egltrace.so"
 #endif
 
 #if defined(MOZ_X11)
 #define EGL_DEFAULT_DISPLAY  ((EGLNativeDisplayType)mozilla::DefaultXDisplay())
 #else
 #define EGL_DEFAULT_DISPLAY  ((EGLNativeDisplayType)0)
 #endif
 
--- a/gfx/gl/GLTypes.h
+++ b/gfx/gl/GLTypes.h
@@ -1,13 +1,13 @@
 /* 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/. */
 
-#if !defined(GLTYPES_H_)
+#ifndef GLTYPES_H_
 #define GLTYPES_H_
 
 #include <stddef.h>
 #include <stdint.h>
 
 #ifndef GLAPIENTRY
 # ifdef WIN32
 #  include <windef.h>
@@ -89,9 +89,26 @@ typedef uint64_t EGLTime;
 
 #define EGL_NO_CONTEXT       ((EGLContext)0)
 #define EGL_NO_DISPLAY       ((EGLDisplay)0)
 #define EGL_NO_SURFACE       ((EGLSurface)0)
 #define EGL_NO_CONFIG        ((EGLConfig)nullptr)
 #define EGL_NO_SYNC          ((EGLSync)0)
 #define EGL_NO_IMAGE         ((EGLImage)0)
 
+
+#ifdef XP_WIN
+    #ifndef WIN32_LEAN_AND_MEAN
+        #define WIN32_LEAN_AND_MEAN 1
+    #endif
+
+    #include <windef.h>
+
+    typedef HDC EGLNativeDisplayType;
+    typedef HBITMAP EGLNativePixmapType;
+    typedef HWND EGLNativeWindowType;
+#else
+    typedef void* EGLNativeDisplayType;
+    typedef void* EGLNativePixmapType;
+    typedef void* EGLNativeWindowType;
 #endif
+
+#endif // GLTYPES_H_
--- a/gfx/gl/SharedSurface.cpp
+++ b/gfx/gl/SharedSurface.cpp
@@ -214,16 +214,18 @@ SharedSurface::SharedSurface(SharedSurfa
     , mGL(gl)
     , mSize(size)
     , mHasAlpha(hasAlpha)
     , mCanRecycle(canRecycle)
     , mIsLocked(false)
     , mIsProducerAcquired(false)
 { }
 
+SharedSurface::~SharedSurface() = default;
+
 layers::TextureFlags
 SharedSurface::GetTextureFlags() const
 {
     return layers::TextureFlags::NO_FLAGS;
 }
 
 void
 SharedSurface::LockProd()
--- a/gfx/gl/SharedSurface.h
+++ b/gfx/gl/SharedSurface.h
@@ -71,18 +71,17 @@ protected:
     SharedSurface(SharedSurfaceType type,
                   AttachmentType attachType,
                   GLContext* gl,
                   const gfx::IntSize& size,
                   bool hasAlpha,
                   bool canRecycle);
 
 public:
-    virtual ~SharedSurface() {
-    }
+    virtual ~SharedSurface();
 
     // Specifies to the TextureClient any flags which
     // are required by the SharedSurface backend.
     virtual layers::TextureFlags GetTextureFlags() const;
 
     bool IsLocked() const { return mIsLocked; }
     bool IsProducerAcquired() const { return mIsProducerAcquired; }
 
--- a/gfx/harfbuzz/NEWS
+++ b/gfx/harfbuzz/NEWS
@@ -1,8 +1,15 @@
+Overview of changes leading to 1.7.4
+Wednesday, December 20, 2017
+====================================
+
+- Fix collect_glyphs() regression caused by hb_set_t changes.
+
+
 Overview of changes leading to 1.7.3
 Monday, December 18, 2017
 ====================================
 
 - hb_set_t performance tuning and optimizations.
 - Speed up collect_glyphs() and reject garbage data.
 - In hb_coretext_font_create() set font point-size (ptem).
 - Misc fixes.
--- a/gfx/harfbuzz/README-mozilla
+++ b/gfx/harfbuzz/README-mozilla
@@ -1,14 +1,14 @@
-gfx/harfbuzz status as of 2017-12-18:
+gfx/harfbuzz status as of 2017-12-20:
 
 This directory contains the HarfBuzz source from the 'master' branch of
 https://github.com/behdad/harfbuzz.
 
-Current version: 1.7.3
+Current version: 1.7.4
 
 UPDATING:
 
 Note that gfx/harfbuzz/src/hb-version.h is not present in the upstream Git
 repository. It is created at build time by the HarfBuzz build system;
 but as we don't use that build system in mozilla, it is necessary to refresh
 this file when updating HarfBuzz, and check it into the mozilla tree.
 
--- a/gfx/harfbuzz/configure.ac
+++ b/gfx/harfbuzz/configure.ac
@@ -1,11 +1,11 @@
 AC_PREREQ([2.64])
 AC_INIT([HarfBuzz],
-        [1.7.3],
+        [1.7.4],
         [https://github.com/harfbuzz/harfbuzz/issues/new],
         [harfbuzz],
         [http://harfbuzz.org/])
 
 AC_CONFIG_MACRO_DIR([m4])
 AC_CONFIG_SRCDIR([src/harfbuzz.pc.in])
 AC_CONFIG_HEADERS([config.h])
 
--- a/gfx/harfbuzz/src/harfbuzz-icu.pc
+++ b/gfx/harfbuzz/src/harfbuzz-icu.pc
@@ -1,13 +1,13 @@
 prefix=/usr/local
 exec_prefix=/usr/local
 libdir=/usr/local/lib
 includedir=/usr/local/include
 
 Name: harfbuzz
 Description: HarfBuzz text shaping library ICU integration
-Version: 1.7.3
+Version: 1.7.4
 
 Requires: harfbuzz
 Requires.private: icu-uc
 Libs: -L${libdir} -lharfbuzz-icu
 Cflags: -I${includedir}/harfbuzz
--- a/gfx/harfbuzz/src/harfbuzz.pc
+++ b/gfx/harfbuzz/src/harfbuzz.pc
@@ -1,13 +1,13 @@
 prefix=/usr/local
 exec_prefix=/usr/local
 libdir=/usr/local/lib
 includedir=/usr/local/include
 
 Name: harfbuzz
 Description: HarfBuzz text shaping library
-Version: 1.7.3
+Version: 1.7.4
 
 Libs: -L${libdir} -lharfbuzz
 Libs.private: -lm    
 Requires.private: glib-2.0 >= 2.19.1 
 Cflags: -I${includedir}/harfbuzz
--- a/gfx/harfbuzz/src/hb-ot-shape-complex-arabic-fallback.hh
+++ b/gfx/harfbuzz/src/hb-ot-shape-complex-arabic-fallback.hh
@@ -72,17 +72,17 @@ arabic_fallback_synthesize_lookup_single
     num_glyphs++;
   }
 
   if (!num_glyphs)
     return nullptr;
 
   /* Bubble-sort or something equally good!
    * May not be good-enough for presidential candidate interviews, but good-enough for us... */
-  hb_stable_sort (&glyphs[0], num_glyphs, OT::GlyphID::cmp, &substitutes[0]);
+  hb_stable_sort (&glyphs[0], num_glyphs, (int(*)(const OT::GlyphID*, const OT::GlyphID *)) OT::GlyphID::cmp, &substitutes[0]);
 
   OT::Supplier<OT::GlyphID> glyphs_supplier      (glyphs, num_glyphs);
   OT::Supplier<OT::GlyphID> substitutes_supplier (substitutes, num_glyphs);
 
   /* Each glyph takes four bytes max, and there's some overhead. */
   char buf[(SHAPING_TABLE_LAST - SHAPING_TABLE_FIRST + 1) * 4 + 128];
   OT::hb_serialize_context_t c (buf, sizeof (buf));
   OT::SubstLookup *lookup = c.start_serialize<OT::SubstLookup> ();
@@ -121,17 +121,17 @@ arabic_fallback_synthesize_lookup_ligatu
     hb_codepoint_t first_glyph;
     if (!hb_font_get_glyph (font, first_u, 0, &first_glyph))
       continue;
     first_glyphs[num_first_glyphs].set (first_glyph);
     ligature_per_first_glyph_count_list[num_first_glyphs] = 0;
     first_glyphs_indirection[num_first_glyphs] = first_glyph_idx;
     num_first_glyphs++;
   }
-  hb_stable_sort (&first_glyphs[0], num_first_glyphs, OT::GlyphID::cmp, &first_glyphs_indirection[0]);
+  hb_stable_sort (&first_glyphs[0], num_first_glyphs, (int(*)(const OT::GlyphID*, const OT::GlyphID *)) OT::GlyphID::cmp, &first_glyphs_indirection[0]);
 
   /* Now that the first-glyphs are sorted, walk again, populate ligatures. */
   for (unsigned int i = 0; i < num_first_glyphs; i++)
   {
     unsigned int first_glyph_idx = first_glyphs_indirection[i];
 
     for (unsigned int second_glyph_idx = 0; second_glyph_idx < ARRAY_LENGTH (ligature_table[0].ligatures); second_glyph_idx++)
     {
--- a/gfx/harfbuzz/src/hb-set-private.hh
+++ b/gfx/harfbuzz/src/hb-set-private.hh
@@ -225,17 +225,18 @@ struct hb_set_t
   {
     if (unlikely (in_error)) return;
     if (unlikely (g == INVALID)) return;
     page_t *page = page_for_insert (g); if (unlikely (!page)) return;
     page->add (g);
   }
   inline bool add_range (hb_codepoint_t a, hb_codepoint_t b)
   {
-    if (unlikely (in_error || a > b || a == INVALID || b == INVALID)) return false;
+    if (unlikely (in_error)) return true; /* https://github.com/harfbuzz/harfbuzz/issues/657 */
+    if (unlikely (a > b || a == INVALID || b == INVALID)) return false;
     unsigned int ma = get_major (a);
     unsigned int mb = get_major (b);
     if (ma == mb)
     {
       page_t *page = page_for_insert (a); if (unlikely (!page)) return false;
       page->add_range (a, b);
     }
     else
@@ -278,17 +279,17 @@ struct hb_set_t
     }
   }
 
   /* Might return false if array looks unsorted.
    * Used for faster rejection of corrupt data. */
   template <typename T>
   inline bool add_sorted_array (const T *array, unsigned int count, unsigned int stride=sizeof(T))
   {
-    if (unlikely (in_error)) return false;
+    if (unlikely (in_error)) return true; /* https://github.com/harfbuzz/harfbuzz/issues/657 */
     if (!count) return true;
     hb_codepoint_t g = *array;
     hb_codepoint_t last_g = g;
     while (count)
     {
       unsigned int m = get_major (g);
       page_t *page = page_for_insert (g); if (unlikely (!page)) return false;
       unsigned int end = major_start (m + 1);
--- a/gfx/harfbuzz/src/hb-version.h
+++ b/gfx/harfbuzz/src/hb-version.h
@@ -33,19 +33,19 @@
 
 #include "hb-common.h"
 
 HB_BEGIN_DECLS
 
 
 #define HB_VERSION_MAJOR 1
 #define HB_VERSION_MINOR 7
-#define HB_VERSION_MICRO 3
+#define HB_VERSION_MICRO 4
 
-#define HB_VERSION_STRING "1.7.3"
+#define HB_VERSION_STRING "1.7.4"
 
 #define HB_VERSION_ATLEAST(major,minor,micro) \
 	((major)*10000+(minor)*100+(micro) <= \
 	 HB_VERSION_MAJOR*10000+HB_VERSION_MINOR*100+HB_VERSION_MICRO)
 
 
 HB_EXTERN void
 hb_version (unsigned int *major,
--- a/gfx/vr/ipc/VRLayerChild.h
+++ b/gfx/vr/ipc/VRLayerChild.h
@@ -6,17 +6,16 @@
 
 #ifndef GFX_VR_LAYERCHILD_H
 #define GFX_VR_LAYERCHILD_H
 
 #include "VRManagerChild.h"
 
 #include "mozilla/RefPtr.h"
 #include "mozilla/gfx/PVRLayerChild.h"
-#include "GLContext.h"
 #include "gfxVR.h"
 
 class nsICanvasRenderingContextInternal;
 
 namespace mozilla {
 class WebGLContext;
 namespace dom {
 class HTMLCanvasElement;
--- a/js/src/builtin/ModuleObject.cpp
+++ b/js/src/builtin/ModuleObject.cpp
@@ -1298,27 +1298,27 @@ ModuleBuilder::initModule()
                                  starExportEntries);
 
     return true;
 }
 
 bool
 ModuleBuilder::processImport(frontend::ParseNode* pn)
 {
-    MOZ_ASSERT(pn->isKind(PNK_IMPORT));
+    MOZ_ASSERT(pn->isKind(ParseNodeKind::PNK_IMPORT));
     MOZ_ASSERT(pn->isArity(PN_BINARY));
-    MOZ_ASSERT(pn->pn_left->isKind(PNK_IMPORT_SPEC_LIST));
-    MOZ_ASSERT(pn->pn_right->isKind(PNK_STRING));
+    MOZ_ASSERT(pn->pn_left->isKind(ParseNodeKind::PNK_IMPORT_SPEC_LIST));
+    MOZ_ASSERT(pn->pn_right->isKind(ParseNodeKind::PNK_STRING));
 
     RootedAtom module(cx_, pn->pn_right->pn_atom);
     if (!maybeAppendRequestedModule(module, pn->pn_right))
         return false;
 
     for (ParseNode* spec = pn->pn_left->pn_head; spec; spec = spec->pn_next) {
-        MOZ_ASSERT(spec->isKind(PNK_IMPORT_SPEC));
+        MOZ_ASSERT(spec->isKind(ParseNodeKind::PNK_IMPORT_SPEC));
         MOZ_ASSERT(spec->pn_left->isArity(PN_NAME));
         MOZ_ASSERT(spec->pn_right->isArity(PN_NAME));
 
         RootedAtom importName(cx_, spec->pn_left->pn_atom);
         RootedAtom localName(cx_, spec->pn_right->pn_atom);
 
         if (!importedBoundNames_.append(localName))
             return false;
@@ -1334,68 +1334,68 @@ ModuleBuilder::processImport(frontend::P
     }
 
     return true;
 }
 
 bool
 ModuleBuilder::processExport(frontend::ParseNode* pn)
 {
-    MOZ_ASSERT(pn->isKind(PNK_EXPORT) || pn->isKind(PNK_EXPORT_DEFAULT));
-    MOZ_ASSERT(pn->getArity() == (pn->isKind(PNK_EXPORT) ? PN_UNARY : PN_BINARY));
+    MOZ_ASSERT(pn->isKind(ParseNodeKind::PNK_EXPORT) || pn->isKind(ParseNodeKind::PNK_EXPORT_DEFAULT));
+    MOZ_ASSERT(pn->getArity() == (pn->isKind(ParseNodeKind::PNK_EXPORT) ? PN_UNARY : PN_BINARY));
 
-    bool isDefault = pn->getKind() == PNK_EXPORT_DEFAULT;
+    bool isDefault = pn->getKind() == ParseNodeKind::PNK_EXPORT_DEFAULT;
     ParseNode* kid = isDefault ? pn->pn_left : pn->pn_kid;
 
     if (isDefault && pn->pn_right) {
         // This is an export default containing an expression.
         HandlePropertyName localName = cx_->names().default_;
         HandlePropertyName exportName = cx_->names().default_;
         return appendExportEntry(exportName, localName);
     }
 
     switch (kid->getKind()) {
-      case PNK_EXPORT_SPEC_LIST:
+      case ParseNodeKind::PNK_EXPORT_SPEC_LIST:
         MOZ_ASSERT(!isDefault);
         for (ParseNode* spec = kid->pn_head; spec; spec = spec->pn_next) {
-            MOZ_ASSERT(spec->isKind(PNK_EXPORT_SPEC));
+            MOZ_ASSERT(spec->isKind(ParseNodeKind::PNK_EXPORT_SPEC));
             RootedAtom localName(cx_, spec->pn_left->pn_atom);
             RootedAtom exportName(cx_, spec->pn_right->pn_atom);
             if (!appendExportEntry(exportName, localName, spec))
                 return false;
         }
         break;
 
-      case PNK_CLASS: {
+      case ParseNodeKind::PNK_CLASS: {
         const ClassNode& cls = kid->as<ClassNode>();
         MOZ_ASSERT(cls.names());
         RootedAtom localName(cx_, cls.names()->innerBinding()->pn_atom);
         RootedAtom exportName(cx_, isDefault ? cx_->names().default_ : localName.get());
         if (!appendExportEntry(exportName, localName))
             return false;
         break;
       }
 
-      case PNK_VAR:
-      case PNK_CONST:
-      case PNK_LET: {
+      case ParseNodeKind::PNK_VAR:
+      case ParseNodeKind::PNK_CONST:
+      case ParseNodeKind::PNK_LET: {
         MOZ_ASSERT(kid->isArity(PN_LIST));
         for (ParseNode* var = kid->pn_head; var; var = var->pn_next) {
-            if (var->isKind(PNK_ASSIGN))
+            if (var->isKind(ParseNodeKind::PNK_ASSIGN))
                 var = var->pn_left;
-            MOZ_ASSERT(var->isKind(PNK_NAME));
+            MOZ_ASSERT(var->isKind(ParseNodeKind::PNK_NAME));
             RootedAtom localName(cx_, var->pn_atom);
             RootedAtom exportName(cx_, isDefault ? cx_->names().default_ : localName.get());
             if (!appendExportEntry(exportName, localName))
                 return false;
         }
         break;
       }
 
-      case PNK_FUNCTION: {
+      case ParseNodeKind::PNK_FUNCTION: {
         RootedFunction func(cx_, kid->pn_funbox->function());
         MOZ_ASSERT(!func->isArrow());
         RootedAtom localName(cx_, func->explicitName());
         RootedAtom exportName(cx_, isDefault ? cx_->names().default_ : localName.get());
         MOZ_ASSERT_IF(isDefault, localName);
         if (!appendExportEntry(exportName, localName))
             return false;
         break;
@@ -1406,33 +1406,33 @@ ModuleBuilder::processExport(frontend::P
     }
 
     return true;
 }
 
 bool
 ModuleBuilder::processExportFrom(frontend::ParseNode* pn)
 {
-    MOZ_ASSERT(pn->isKind(PNK_EXPORT_FROM));
+    MOZ_ASSERT(pn->isKind(ParseNodeKind::PNK_EXPORT_FROM));
     MOZ_ASSERT(pn->isArity(PN_BINARY));
-    MOZ_ASSERT(pn->pn_left->isKind(PNK_EXPORT_SPEC_LIST));
-    MOZ_ASSERT(pn->pn_right->isKind(PNK_STRING));
+    MOZ_ASSERT(pn->pn_left->isKind(ParseNodeKind::PNK_EXPORT_SPEC_LIST));
+    MOZ_ASSERT(pn->pn_right->isKind(ParseNodeKind::PNK_STRING));
 
     RootedAtom module(cx_, pn->pn_right->pn_atom);
     if (!maybeAppendRequestedModule(module, pn->pn_right))
         return false;
 
     for (ParseNode* spec = pn->pn_left->pn_head; spec; spec = spec->pn_next) {
-        if (spec->isKind(PNK_EXPORT_SPEC)) {
+        if (spec->isKind(ParseNodeKind::PNK_EXPORT_SPEC)) {
             RootedAtom bindingName(cx_, spec->pn_left->pn_atom);
             RootedAtom exportName(cx_, spec->pn_right->pn_atom);
             if (!appendExportFromEntry(exportName, module, bindingName, spec->pn_left))
                 return false;
         } else {
-            MOZ_ASSERT(spec->isKind(PNK_EXPORT_BATCH_SPEC));
+            MOZ_ASSERT(spec->isKind(ParseNodeKind::PNK_EXPORT_BATCH_SPEC));
             RootedAtom importName(cx_, cx_->names().star);
             if (!appendExportFromEntry(nullptr, module, importName, spec))
                 return false;
         }
     }
 
     return true;
 }
--- a/js/src/builtin/ReflectParse.cpp
+++ b/js/src/builtin/ReflectParse.cpp
@@ -1744,133 +1744,133 @@ class ASTSerializer
 };
 
 } /* anonymous namespace */
 
 AssignmentOperator
 ASTSerializer::aop(ParseNodeKind kind)
 {
     switch (kind) {
-      case PNK_ASSIGN:
+      case ParseNodeKind::PNK_ASSIGN:
         return AOP_ASSIGN;
-      case PNK_ADDASSIGN:
+      case ParseNodeKind::PNK_ADDASSIGN:
         return AOP_PLUS;
-      case PNK_SUBASSIGN:
+      case ParseNodeKind::PNK_SUBASSIGN:
         return AOP_MINUS;
-      case PNK_MULASSIGN:
+      case ParseNodeKind::PNK_MULASSIGN:
         return AOP_STAR;
-      case PNK_DIVASSIGN:
+      case ParseNodeKind::PNK_DIVASSIGN:
         return AOP_DIV;
-      case PNK_MODASSIGN:
+      case ParseNodeKind::PNK_MODASSIGN:
         return AOP_MOD;
-      case PNK_POWASSIGN:
+      case ParseNodeKind::PNK_POWASSIGN:
         return AOP_POW;
-      case PNK_LSHASSIGN:
+      case ParseNodeKind::PNK_LSHASSIGN:
         return AOP_LSH;
-      case PNK_RSHASSIGN:
+      case ParseNodeKind::PNK_RSHASSIGN:
         return AOP_RSH;
-      case PNK_URSHASSIGN:
+      case ParseNodeKind::PNK_URSHASSIGN:
         return AOP_URSH;
-      case PNK_BITORASSIGN:
+      case ParseNodeKind::PNK_BITORASSIGN:
         return AOP_BITOR;
-      case PNK_BITXORASSIGN:
+      case ParseNodeKind::PNK_BITXORASSIGN:
         return AOP_BITXOR;
-      case PNK_BITANDASSIGN:
+      case ParseNodeKind::PNK_BITANDASSIGN:
         return AOP_BITAND;
       default:
         return AOP_ERR;
     }
 }
 
 UnaryOperator
 ASTSerializer::unop(ParseNodeKind kind)
 {
     if (IsDeleteKind(kind))
         return UNOP_DELETE;
 
     if (IsTypeofKind(kind))
         return UNOP_TYPEOF;
 
     switch (kind) {
-      case PNK_AWAIT:
+      case ParseNodeKind::PNK_AWAIT:
         return UNOP_AWAIT;
-      case PNK_NEG:
+      case ParseNodeKind::PNK_NEG:
         return UNOP_NEG;
-      case PNK_POS:
+      case ParseNodeKind::PNK_POS:
         return UNOP_POS;
-      case PNK_NOT:
+      case ParseNodeKind::PNK_NOT:
         return UNOP_NOT;
-      case PNK_BITNOT:
+      case ParseNodeKind::PNK_BITNOT:
         return UNOP_BITNOT;
-      case PNK_VOID:
+      case ParseNodeKind::PNK_VOID:
         return UNOP_VOID;
       default:
         return UNOP_ERR;
     }
 }
 
 BinaryOperator
 ASTSerializer::binop(ParseNodeKind kind)
 {
     switch (kind) {
-      case PNK_LSH:
+      case ParseNodeKind::PNK_LSH:
         return BINOP_LSH;
-      case PNK_RSH:
+      case ParseNodeKind::PNK_RSH:
         return BINOP_RSH;
-      case PNK_URSH:
+      case ParseNodeKind::PNK_URSH:
         return BINOP_URSH;
-      case PNK_LT:
+      case ParseNodeKind::PNK_LT:
         return BINOP_LT;
-      case PNK_LE:
+      case ParseNodeKind::PNK_LE:
         return BINOP_LE;
-      case PNK_GT:
+      case ParseNodeKind::PNK_GT:
         return BINOP_GT;
-      case PNK_GE:
+      case ParseNodeKind::PNK_GE:
         return BINOP_GE;
-      case PNK_EQ:
+      case ParseNodeKind::PNK_EQ:
         return BINOP_EQ;
-      case PNK_NE:
+      case ParseNodeKind::PNK_NE:
         return BINOP_NE;
-      case PNK_STRICTEQ:
+      case ParseNodeKind::PNK_STRICTEQ:
         return BINOP_STRICTEQ;
-      case PNK_STRICTNE:
+      case ParseNodeKind::PNK_STRICTNE:
         return BINOP_STRICTNE;
-      case PNK_ADD:
+      case ParseNodeKind::PNK_ADD:
         return BINOP_ADD;
-      case PNK_SUB:
+      case ParseNodeKind::PNK_SUB:
         return BINOP_SUB;
-      case PNK_STAR:
+      case ParseNodeKind::PNK_STAR:
         return BINOP_STAR;
-      case PNK_DIV:
+      case ParseNodeKind::PNK_DIV:
         return BINOP_DIV;
-      case PNK_MOD:
+      case ParseNodeKind::PNK_MOD:
         return BINOP_MOD;
-      case PNK_POW:
+      case ParseNodeKind::PNK_POW:
         return BINOP_POW;
-      case PNK_BITOR:
+      case ParseNodeKind::PNK_BITOR:
         return BINOP_BITOR;
-      case PNK_BITXOR:
+      case ParseNodeKind::PNK_BITXOR:
         return BINOP_BITXOR;
-      case PNK_BITAND:
+      case ParseNodeKind::PNK_BITAND:
         return BINOP_BITAND;
-      case PNK_IN:
+      case ParseNodeKind::PNK_IN:
         return BINOP_IN;
-      case PNK_INSTANCEOF:
+      case ParseNodeKind::PNK_INSTANCEOF:
         return BINOP_INSTANCEOF;
-      case PNK_PIPELINE:
+      case ParseNodeKind::PNK_PIPELINE:
         return BINOP_PIPELINE;
       default:
         return BINOP_ERR;
     }
 }
 
 bool
 ASTSerializer::statements(ParseNode* pn, NodeVector& elts)
 {
-    MOZ_ASSERT(pn->isKind(PNK_STATEMENTLIST));
+    MOZ_ASSERT(pn->isKind(ParseNodeKind::PNK_STATEMENTLIST));
     MOZ_ASSERT(pn->isArity(PN_LIST));
 
     if (!elts.reserve(pn->pn_count))
         return false;
 
     for (ParseNode* next = pn->pn_head; next; next = next->pn_next) {
         MOZ_ASSERT(pn->pn_pos.encloses(next->pn_pos));
 
@@ -1899,17 +1899,17 @@ ASTSerializer::expressions(ParseNode* pn
     }
 
     return true;
 }
 
 bool
 ASTSerializer::blockStatement(ParseNode* pn, MutableHandleValue dst)
 {
-    MOZ_ASSERT(pn->isKind(PNK_STATEMENTLIST));
+    MOZ_ASSERT(pn->isKind(ParseNodeKind::PNK_STATEMENTLIST));
 
     NodeVector stmts(cx);
     return statements(pn, stmts) &&
            builder.blockStatement(stmts, &pn->pn_pos, dst);
 }
 
 bool
 ASTSerializer::program(ParseNode* pn, MutableHandleValue dst)
@@ -1926,47 +1926,47 @@ ASTSerializer::sourceElement(ParseNode* 
 {
     /* SpiderMonkey allows declarations even in pure statement contexts. */
     return statement(pn, dst);
 }
 
 bool
 ASTSerializer::declaration(ParseNode* pn, MutableHandleValue dst)
 {
-    MOZ_ASSERT(pn->isKind(PNK_FUNCTION) ||
-               pn->isKind(PNK_VAR) ||
-               pn->isKind(PNK_LET) ||
-               pn->isKind(PNK_CONST));
+    MOZ_ASSERT(pn->isKind(ParseNodeKind::PNK_FUNCTION) ||
+               pn->isKind(ParseNodeKind::PNK_VAR) ||
+               pn->isKind(ParseNodeKind::PNK_LET) ||
+               pn->isKind(ParseNodeKind::PNK_CONST));
 
     switch (pn->getKind()) {
-      case PNK_FUNCTION:
+      case ParseNodeKind::PNK_FUNCTION:
         return function(pn, AST_FUNC_DECL, dst);
 
-      case PNK_VAR:
+      case ParseNodeKind::PNK_VAR:
         return variableDeclaration(pn, false, dst);
 
       default:
-        MOZ_ASSERT(pn->isKind(PNK_LET) || pn->isKind(PNK_CONST));
+        MOZ_ASSERT(pn->isKind(ParseNodeKind::PNK_LET) || pn->isKind(ParseNodeKind::PNK_CONST));
         return variableDeclaration(pn, true, dst);
     }
 }
 
 bool
 ASTSerializer::variableDeclaration(ParseNode* pn, bool lexical, MutableHandleValue dst)
 {
-    MOZ_ASSERT_IF(lexical, pn->isKind(PNK_LET) || pn->isKind(PNK_CONST));
-    MOZ_ASSERT_IF(!lexical, pn->isKind(PNK_VAR));
+    MOZ_ASSERT_IF(lexical, pn->isKind(ParseNodeKind::PNK_LET) || pn->isKind(ParseNodeKind::PNK_CONST));
+    MOZ_ASSERT_IF(!lexical, pn->isKind(ParseNodeKind::PNK_VAR));
 
     VarDeclKind kind = VARDECL_ERR;
     // Treat both the toplevel const binding (secretly var-like) and the lexical const
     // the same way
     if (lexical)
-        kind = pn->isKind(PNK_LET) ? VARDECL_LET : VARDECL_CONST;
+        kind = pn->isKind(ParseNodeKind::PNK_LET) ? VARDECL_LET : VARDECL_CONST;
     else
-        kind = pn->isKind(PNK_VAR) ? VARDECL_VAR : VARDECL_CONST;
+        kind = pn->isKind(ParseNodeKind::PNK_VAR) ? VARDECL_VAR : VARDECL_CONST;
 
     NodeVector dtors(cx);
     if (!dtors.reserve(pn->pn_count))
         return false;
     for (ParseNode* next = pn->pn_head; next; next = next->pn_next) {
         RootedValue child(cx);
         if (!variableDeclarator(next, &child))
             return false;
@@ -1976,21 +1976,21 @@ ASTSerializer::variableDeclaration(Parse
 }
 
 bool
 ASTSerializer::variableDeclarator(ParseNode* pn, MutableHandleValue dst)
 {
     ParseNode* pnleft;
     ParseNode* pnright;
 
-    if (pn->isKind(PNK_NAME)) {
+    if (pn->isKind(ParseNodeKind::PNK_NAME)) {
         pnleft = pn;
         pnright = pn->pn_expr;
         MOZ_ASSERT_IF(pnright, pn->pn_pos.encloses(pnright->pn_pos));
-    } else if (pn->isKind(PNK_ASSIGN)) {
+    } else if (pn->isKind(ParseNodeKind::PNK_ASSIGN)) {
         pnleft = pn->pn_left;
         pnright = pn->pn_right;
         MOZ_ASSERT(pn->pn_pos.encloses(pnleft->pn_pos));
         MOZ_ASSERT(pn->pn_pos.encloses(pnright->pn_pos));
     } else {
         /* This happens for a destructuring declarator in a for-in/of loop. */
         pnleft = pn;
         pnright = nullptr;
@@ -2000,20 +2000,20 @@ ASTSerializer::variableDeclarator(ParseN
     return pattern(pnleft, &left) &&
            optExpression(pnright, &right) &&
            builder.variableDeclarator(left, right, &pn->pn_pos, dst);
 }
 
 bool
 ASTSerializer::importDeclaration(ParseNode* pn, MutableHandleValue dst)
 {
-    MOZ_ASSERT(pn->isKind(PNK_IMPORT));
+    MOZ_ASSERT(pn->isKind(ParseNodeKind::PNK_IMPORT));
     MOZ_ASSERT(pn->isArity(PN_BINARY));
-    MOZ_ASSERT(pn->pn_left->isKind(PNK_IMPORT_SPEC_LIST));
-    MOZ_ASSERT(pn->pn_right->isKind(PNK_STRING));
+    MOZ_ASSERT(pn->pn_left->isKind(ParseNodeKind::PNK_IMPORT_SPEC_LIST));
+    MOZ_ASSERT(pn->pn_right->isKind(ParseNodeKind::PNK_STRING));
 
     NodeVector elts(cx);
     if (!elts.reserve(pn->pn_left->pn_count))
         return false;
 
     for (ParseNode* next = pn->pn_left->pn_head; next; next = next->pn_next) {
         RootedValue elt(cx);
         if (!importSpecifier(next, &elt))
@@ -2024,94 +2024,94 @@ ASTSerializer::importDeclaration(ParseNo
     RootedValue moduleSpec(cx);
     return literal(pn->pn_right, &moduleSpec) &&
            builder.importDeclaration(elts, moduleSpec, &pn->pn_pos, dst);
 }
 
 bool
 ASTSerializer::importSpecifier(ParseNode* pn, MutableHandleValue dst)
 {
-    MOZ_ASSERT(pn->isKind(PNK_IMPORT_SPEC));
+    MOZ_ASSERT(pn->isKind(ParseNodeKind::PNK_IMPORT_SPEC));
 
     RootedValue importName(cx);
     RootedValue bindingName(cx);
     return identifier(pn->pn_left, &importName) &&
            identifier(pn->pn_right, &bindingName) &&
            builder.importSpecifier(importName, bindingName, &pn->pn_pos, dst);
 }
 
 bool
 ASTSerializer::exportDeclaration(ParseNode* pn, MutableHandleValue dst)
 {
-    MOZ_ASSERT(pn->isKind(PNK_EXPORT) ||
-               pn->isKind(PNK_EXPORT_FROM) ||
-               pn->isKind(PNK_EXPORT_DEFAULT));
-    MOZ_ASSERT(pn->getArity() == (pn->isKind(PNK_EXPORT) ? PN_UNARY : PN_BINARY));
-    MOZ_ASSERT_IF(pn->isKind(PNK_EXPORT_FROM), pn->pn_right->isKind(PNK_STRING));
+    MOZ_ASSERT(pn->isKind(ParseNodeKind::PNK_EXPORT) ||
+               pn->isKind(ParseNodeKind::PNK_EXPORT_FROM) ||
+               pn->isKind(ParseNodeKind::PNK_EXPORT_DEFAULT));
+    MOZ_ASSERT(pn->getArity() == (pn->isKind(ParseNodeKind::PNK_EXPORT) ? PN_UNARY : PN_BINARY));
+    MOZ_ASSERT_IF(pn->isKind(ParseNodeKind::PNK_EXPORT_FROM), pn->pn_right->isKind(ParseNodeKind::PNK_STRING));
 
     RootedValue decl(cx, NullValue());
     NodeVector elts(cx);
 
-    ParseNode* kid = pn->isKind(PNK_EXPORT) ? pn->pn_kid : pn->pn_left;
+    ParseNode* kid = pn->isKind(ParseNodeKind::PNK_EXPORT) ? pn->pn_kid : pn->pn_left;
     switch (ParseNodeKind kind = kid->getKind()) {
-      case PNK_EXPORT_SPEC_LIST:
+      case ParseNodeKind::PNK_EXPORT_SPEC_LIST:
         if (!elts.reserve(pn->pn_left->pn_count))
             return false;
 
         for (ParseNode* next = pn->pn_left->pn_head; next; next = next->pn_next) {
             RootedValue elt(cx);
-            if (next->isKind(PNK_EXPORT_SPEC)) {
+            if (next->isKind(ParseNodeKind::PNK_EXPORT_SPEC)) {
                 if (!exportSpecifier(next, &elt))
                     return false;
             } else {
                 if (!builder.exportBatchSpecifier(&pn->pn_pos, &elt))
                     return false;
             }
             elts.infallibleAppend(elt);
         }
         break;
 
-      case PNK_FUNCTION:
+      case ParseNodeKind::PNK_FUNCTION:
         if (!function(kid, AST_FUNC_DECL, &decl))
             return false;
         break;
 
-      case PNK_CLASS:
+      case ParseNodeKind::PNK_CLASS:
         if (!classDefinition(kid, false, &decl))
             return false;
         break;
 
-      case PNK_VAR:
-      case PNK_CONST:
-      case PNK_LET:
-        if (!variableDeclaration(kid, kind != PNK_VAR, &decl))
+      case ParseNodeKind::PNK_VAR:
+      case ParseNodeKind::PNK_CONST:
+      case ParseNodeKind::PNK_LET:
+        if (!variableDeclaration(kid, kind != ParseNodeKind::PNK_VAR, &decl))
             return false;
         break;
 
       default:
           if (!expression(kid, &decl))
               return false;
           break;
     }
 
     RootedValue moduleSpec(cx, NullValue());
-    if (pn->isKind(PNK_EXPORT_FROM) && !literal(pn->pn_right, &moduleSpec))
+    if (pn->isKind(ParseNodeKind::PNK_EXPORT_FROM) && !literal(pn->pn_right, &moduleSpec))
         return false;
 
     RootedValue isDefault(cx, BooleanValue(false));
-    if (pn->isKind(PNK_EXPORT_DEFAULT))
+    if (pn->isKind(ParseNodeKind::PNK_EXPORT_DEFAULT))
         isDefault.setBoolean(true);
 
     return builder.exportDeclaration(decl, elts, moduleSpec, isDefault, &pn->pn_pos, dst);
 }
 
 bool
 ASTSerializer::exportSpecifier(ParseNode* pn, MutableHandleValue dst)
 {
-    MOZ_ASSERT(pn->isKind(PNK_EXPORT_SPEC));
+    MOZ_ASSERT(pn->isKind(ParseNodeKind::PNK_EXPORT_SPEC));
 
     RootedValue bindingName(cx);
     RootedValue exportName(cx);
     return identifier(pn->pn_left, &bindingName) &&
            identifier(pn->pn_right, &exportName) &&
            builder.exportSpecifier(bindingName, exportName, &pn->pn_pos, dst);
 }
 
@@ -2139,17 +2139,17 @@ ASTSerializer::switchStatement(ParseNode
     RootedValue disc(cx);
 
     if (!expression(pn->pn_left, &disc))
         return false;
 
     ParseNode* listNode;
     bool lexical;
 
-    if (pn->pn_right->isKind(PNK_LEXICALSCOPE)) {
+    if (pn->pn_right->isKind(ParseNodeKind::PNK_LEXICALSCOPE)) {
         listNode = pn->pn_right->pn_expr;
         lexical = true;
     } else {
         listNode = pn->pn_right;
         lexical = false;
     }
 
     NodeVector cases(cx);
@@ -2164,17 +2164,17 @@ ASTSerializer::switchStatement(ParseNode
     }
 
     return builder.switchStatement(disc, cases, lexical, &pn->pn_pos, dst);
 }
 
 bool
 ASTSerializer::catchClause(ParseNode* pn, MutableHandleValue dst)
 {
-    MOZ_ASSERT(pn->isKind(PNK_CATCH));
+    MOZ_ASSERT(pn->isKind(ParseNodeKind::PNK_CATCH));
     MOZ_ASSERT_IF(pn->pn_left, pn->pn_pos.encloses(pn->pn_left->pn_pos));
     MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_right->pn_pos));
 
     RootedValue var(cx), body(cx);
 
     if (!optPattern(pn->pn_left, &var))
         return false;
 
@@ -2190,17 +2190,17 @@ ASTSerializer::tryStatement(ParseNode* p
     MOZ_ASSERT_IF(pn->pn_kid3, pn->pn_pos.encloses(pn->pn_kid3->pn_pos));
 
     RootedValue body(cx);
     if (!statement(pn->pn_kid1, &body))
         return false;
 
     RootedValue handler(cx, NullValue());
     if (ParseNode* catchScope = pn->pn_kid2) {
-        MOZ_ASSERT(catchScope->isKind(PNK_LEXICALSCOPE));
+        MOZ_ASSERT(catchScope->isKind(ParseNodeKind::PNK_LEXICALSCOPE));
         if (!catchClause(catchScope->scopeBody(), &handler))
             return false;
     }
 
     RootedValue finally(cx);
     return optStatement(pn->pn_kid3, &finally) &&
            builder.tryStatement(body, handler, finally, &pn->pn_pos, dst);
 }
@@ -2208,18 +2208,18 @@ ASTSerializer::tryStatement(ParseNode* p
 bool
 ASTSerializer::forInit(ParseNode* pn, MutableHandleValue dst)
 {
     if (!pn) {
         dst.setMagic(JS_SERIALIZE_NO_NODE);
         return true;
     }
 
-    bool lexical = pn->isKind(PNK_LET) || pn->isKind(PNK_CONST);
-    return (lexical || pn->isKind(PNK_VAR))
+    bool lexical = pn->isKind(ParseNodeKind::PNK_LET) || pn->isKind(ParseNodeKind::PNK_CONST);
+    return (lexical || pn->isKind(ParseNodeKind::PNK_VAR))
            ? variableDeclaration(pn, lexical, dst)
            : expression(pn, dst);
 }
 
 bool
 ASTSerializer::forOf(ParseNode* loop, ParseNode* head, HandleValue var, HandleValue stmt,
                          MutableHandleValue dst)
 {
@@ -2258,193 +2258,193 @@ ASTSerializer::classDefinition(ParseNode
 
 bool
 ASTSerializer::statement(ParseNode* pn, MutableHandleValue dst)
 {
     if (!CheckRecursionLimit(cx))
         return false;
 
     switch (pn->getKind()) {
-      case PNK_FUNCTION:
-      case PNK_VAR:
+      case ParseNodeKind::PNK_FUNCTION:
+      case ParseNodeKind::PNK_VAR:
         return declaration(pn, dst);
 
-      case PNK_LET:
-      case PNK_CONST:
+      case ParseNodeKind::PNK_LET:
+      case ParseNodeKind::PNK_CONST:
         return declaration(pn, dst);
 
-      case PNK_IMPORT:
+      case ParseNodeKind::PNK_IMPORT:
         return importDeclaration(pn, dst);
 
-      case PNK_EXPORT:
-      case PNK_EXPORT_DEFAULT:
-      case PNK_EXPORT_FROM:
+      case ParseNodeKind::PNK_EXPORT:
+      case ParseNodeKind::PNK_EXPORT_DEFAULT:
+      case ParseNodeKind::PNK_EXPORT_FROM:
         return exportDeclaration(pn, dst);
 
-      case PNK_SEMI:
+      case ParseNodeKind::PNK_SEMI:
         if (pn->pn_kid) {
             RootedValue expr(cx);
             return expression(pn->pn_kid, &expr) &&
                    builder.expressionStatement(expr, &pn->pn_pos, dst);
         }
         return builder.emptyStatement(&pn->pn_pos, dst);
 
-      case PNK_LEXICALSCOPE:
+      case ParseNodeKind::PNK_LEXICALSCOPE:
         pn = pn->pn_expr;
-        if (!pn->isKind(PNK_STATEMENTLIST))
+        if (!pn->isKind(ParseNodeKind::PNK_STATEMENTLIST))
             return statement(pn, dst);
         MOZ_FALLTHROUGH;
 
-      case PNK_STATEMENTLIST:
+      case ParseNodeKind::PNK_STATEMENTLIST:
         return blockStatement(pn, dst);
 
-      case PNK_IF:
+      case ParseNodeKind::PNK_IF:
       {
         MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_kid1->pn_pos));
         MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_kid2->pn_pos));
         MOZ_ASSERT_IF(pn->pn_kid3, pn->pn_pos.encloses(pn->pn_kid3->pn_pos));
 
         RootedValue test(cx), cons(cx), alt(cx);
 
         return expression(pn->pn_kid1, &test) &&
                statement(pn->pn_kid2, &cons) &&
                optStatement(pn->pn_kid3, &alt) &&
                builder.ifStatement(test, cons, alt, &pn->pn_pos, dst);
       }
 
-      case PNK_SWITCH:
+      case ParseNodeKind::PNK_SWITCH:
         return switchStatement(pn, dst);
 
-      case PNK_TRY:
+      case ParseNodeKind::PNK_TRY:
         return tryStatement(pn, dst);
 
-      case PNK_WITH:
-      case PNK_WHILE:
+      case ParseNodeKind::PNK_WITH:
+      case ParseNodeKind::PNK_WHILE:
       {
         MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_left->pn_pos));
         MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_right->pn_pos));
 
         RootedValue expr(cx), stmt(cx);
 
         return expression(pn->pn_left, &expr) &&
                statement(pn->pn_right, &stmt) &&
-               (pn->isKind(PNK_WITH)
+               (pn->isKind(ParseNodeKind::PNK_WITH)
                 ? builder.withStatement(expr, stmt, &pn->pn_pos, dst)
                 : builder.whileStatement(expr, stmt, &pn->pn_pos, dst));
       }
 
-      case PNK_DOWHILE:
+      case ParseNodeKind::PNK_DOWHILE:
       {
         MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_left->pn_pos));
         MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_right->pn_pos));
 
         RootedValue stmt(cx), test(cx);
 
         return statement(pn->pn_left, &stmt) &&
                expression(pn->pn_right, &test) &&
                builder.doWhileStatement(stmt, test, &pn->pn_pos, dst);
       }
 
-      case PNK_FOR:
+      case ParseNodeKind::PNK_FOR:
       {
         MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_left->pn_pos));
         MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_right->pn_pos));
 
         ParseNode* head = pn->pn_left;
 
         MOZ_ASSERT_IF(head->pn_kid1, head->pn_pos.encloses(head->pn_kid1->pn_pos));
         MOZ_ASSERT_IF(head->pn_kid2, head->pn_pos.encloses(head->pn_kid2->pn_pos));
         MOZ_ASSERT_IF(head->pn_kid3, head->pn_pos.encloses(head->pn_kid3->pn_pos));
 
         RootedValue stmt(cx);
         if (!statement(pn->pn_right, &stmt))
             return false;
 
-        if (head->isKind(PNK_FORIN) || head->isKind(PNK_FOROF)) {
+        if (head->isKind(ParseNodeKind::PNK_FORIN) || head->isKind(ParseNodeKind::PNK_FOROF)) {
             RootedValue var(cx);
-            if (head->pn_kid1->isKind(PNK_LEXICALSCOPE)) {
+            if (head->pn_kid1->isKind(ParseNodeKind::PNK_LEXICALSCOPE)) {
                 if (!variableDeclaration(head->pn_kid1->pn_expr, true, &var))
                     return false;
-            } else if (!head->pn_kid1->isKind(PNK_VAR) &&
-                       !head->pn_kid1->isKind(PNK_LET) &&
-                       !head->pn_kid1->isKind(PNK_CONST))
+            } else if (!head->pn_kid1->isKind(ParseNodeKind::PNK_VAR) &&
+                       !head->pn_kid1->isKind(ParseNodeKind::PNK_LET) &&
+                       !head->pn_kid1->isKind(ParseNodeKind::PNK_CONST))
             {
                 if (!pattern(head->pn_kid1, &var))
                     return false;
             } else {
                 if (!variableDeclaration(head->pn_kid1,
-                                         head->pn_kid1->isKind(PNK_LET) ||
-                                         head->pn_kid1->isKind(PNK_CONST),
+                                         head->pn_kid1->isKind(ParseNodeKind::PNK_LET) ||
+                                         head->pn_kid1->isKind(ParseNodeKind::PNK_CONST),
                                          &var))
                 {
                     return false;
                 }
             }
-            if (head->isKind(PNK_FORIN))
+            if (head->isKind(ParseNodeKind::PNK_FORIN))
                 return forIn(pn, head, var, stmt, dst);
             return forOf(pn, head, var, stmt, dst);
         }
 
         RootedValue init(cx), test(cx), update(cx);
 
         return forInit(head->pn_kid1, &init) &&
                optExpression(head->pn_kid2, &test) &&
                optExpression(head->pn_kid3, &update) &&
                builder.forStatement(init, test, update, stmt, &pn->pn_pos, dst);
       }
 
-      case PNK_BREAK:
-      case PNK_CONTINUE:
+      case ParseNodeKind::PNK_BREAK:
+      case ParseNodeKind::PNK_CONTINUE:
       {
         RootedValue label(cx);
         RootedAtom pnAtom(cx, pn->pn_atom);
         return optIdentifier(pnAtom, nullptr, &label) &&
-               (pn->isKind(PNK_BREAK)
+               (pn->isKind(ParseNodeKind::PNK_BREAK)
                 ? builder.breakStatement(label, &pn->pn_pos, dst)
                 : builder.continueStatement(label, &pn->pn_pos, dst));
       }
 
-      case PNK_LABEL:
+      case ParseNodeKind::PNK_LABEL:
       {
         MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_expr->pn_pos));
 
         RootedValue label(cx), stmt(cx);
         RootedAtom pnAtom(cx, pn->as<LabeledStatement>().label());
         return identifier(pnAtom, nullptr, &label) &&
                statement(pn->pn_expr, &stmt) &&
                builder.labeledStatement(label, stmt, &pn->pn_pos, dst);
       }
 
-      case PNK_THROW:
+      case ParseNodeKind::PNK_THROW:
       {
         MOZ_ASSERT_IF(pn->pn_kid, pn->pn_pos.encloses(pn->pn_kid->pn_pos));
 
         RootedValue arg(cx);
 
         return optExpression(pn->pn_kid, &arg) &&
                builder.throwStatement(arg, &pn->pn_pos, dst);
       }
 
-      case PNK_RETURN:
+      case ParseNodeKind::PNK_RETURN:
       {
         MOZ_ASSERT_IF(pn->pn_kid, pn->pn_pos.encloses(pn->pn_kid->pn_pos));
 
         RootedValue arg(cx);
 
         return optExpression(pn->pn_kid, &arg) &&
                builder.returnStatement(arg, &pn->pn_pos, dst);
       }
 
-      case PNK_DEBUGGER:
+      case ParseNodeKind::PNK_DEBUGGER:
         return builder.debuggerStatement(&pn->pn_pos, dst);
 
-      case PNK_CLASS:
+      case ParseNodeKind::PNK_CLASS:
         return classDefinition(pn, false, dst);
 
-      case PNK_CLASSMETHODLIST:
+      case ParseNodeKind::PNK_CLASSMETHODLIST:
       {
         NodeVector methods(cx);
         if (!methods.reserve(pn->pn_count))
             return false;
 
         for (ParseNode* next = pn->pn_head; next; next = next->pn_next) {
             MOZ_ASSERT(pn->pn_pos.encloses(next->pn_pos));
 
@@ -2452,17 +2452,17 @@ ASTSerializer::statement(ParseNode* pn, 
             if (!classMethod(next, &prop))
                 return false;
             methods.infallibleAppend(prop);
         }
 
         return builder.classMethods(methods, dst);
       }
 
-      case PNK_NOP:
+      case ParseNodeKind::PNK_NOP:
         return builder.emptyStatement(&pn->pn_pos, dst);
 
       default:
         LOCAL_NOT_REACHED("unexpected statement type");
     }
 }
 
 bool
@@ -2495,18 +2495,18 @@ ASTSerializer::classMethod(ParseNode* pn
 
 bool
 ASTSerializer::leftAssociate(ParseNode* pn, MutableHandleValue dst)
 {
     MOZ_ASSERT(pn->isArity(PN_LIST));
     MOZ_ASSERT(pn->pn_count >= 1);
 
     ParseNodeKind kind = pn->getKind();
-    bool lor = kind == PNK_OR;
-    bool logop = lor || (kind == PNK_AND);
+    bool lor = kind == ParseNodeKind::PNK_OR;
+    bool logop = lor || (kind == ParseNodeKind::PNK_AND);
 
     ParseNode* head = pn->pn_head;
     RootedValue left(cx);
     if (!expression(head, &left))
         return false;
     for (ParseNode* next = head->pn_next; next; next = next->pn_next) {
         RootedValue right(cx);
         if (!expression(next, &right))
@@ -2575,155 +2575,155 @@ ASTSerializer::rightAssociate(ParseNode*
 
 bool
 ASTSerializer::expression(ParseNode* pn, MutableHandleValue dst)
 {
     if (!CheckRecursionLimit(cx))
         return false;
 
     switch (pn->getKind()) {
-      case PNK_FUNCTION:
+      case ParseNodeKind::PNK_FUNCTION:
       {
         ASTType type = pn->pn_funbox->function()->isArrow() ? AST_ARROW_EXPR : AST_FUNC_EXPR;
         return function(pn, type, dst);
       }
 
-      case PNK_COMMA:
+      case ParseNodeKind::PNK_COMMA:
       {
         NodeVector exprs(cx);
         return expressions(pn, exprs) &&
                builder.sequenceExpression(exprs, &pn->pn_pos, dst);
       }
 
-      case PNK_CONDITIONAL:
+      case ParseNodeKind::PNK_CONDITIONAL:
       {
         MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_kid1->pn_pos));
         MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_kid2->pn_pos));
         MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_kid3->pn_pos));
 
         RootedValue test(cx), cons(cx), alt(cx);
 
         return expression(pn->pn_kid1, &test) &&
                expression(pn->pn_kid2, &cons) &&
                expression(pn->pn_kid3, &alt) &&
                builder.conditionalExpression(test, cons, alt, &pn->pn_pos, dst);
       }
 
-      case PNK_OR:
-      case PNK_AND:
+      case ParseNodeKind::PNK_OR:
+      case ParseNodeKind::PNK_AND:
         return leftAssociate(pn, dst);
 
-      case PNK_PREINCREMENT:
-      case PNK_PREDECREMENT:
+      case ParseNodeKind::PNK_PREINCREMENT:
+      case ParseNodeKind::PNK_PREDECREMENT:
       {
         MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_kid->pn_pos));
 
-        bool inc = pn->isKind(PNK_PREINCREMENT);
+        bool inc = pn->isKind(ParseNodeKind::PNK_PREINCREMENT);
         RootedValue expr(cx);
         return expression(pn->pn_kid, &expr) &&
                builder.updateExpression(expr, inc, true, &pn->pn_pos, dst);
       }
 
-      case PNK_POSTINCREMENT:
-      case PNK_POSTDECREMENT:
+      case ParseNodeKind::PNK_POSTINCREMENT:
+      case ParseNodeKind::PNK_POSTDECREMENT:
       {
         MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_kid->pn_pos));
 
-        bool inc = pn->isKind(PNK_POSTINCREMENT);
+        bool inc = pn->isKind(ParseNodeKind::PNK_POSTINCREMENT);
         RootedValue expr(cx);
         return expression(pn->pn_kid, &expr) &&
                builder.updateExpression(expr, inc, false, &pn->pn_pos, dst);
       }
 
-      case PNK_ASSIGN:
-      case PNK_ADDASSIGN:
-      case PNK_SUBASSIGN:
-      case PNK_BITORASSIGN:
-      case PNK_BITXORASSIGN:
-      case PNK_BITANDASSIGN:
-      case PNK_LSHASSIGN:
-      case PNK_RSHASSIGN:
-      case PNK_URSHASSIGN:
-      case PNK_MULASSIGN:
-      case PNK_DIVASSIGN:
-      case PNK_MODASSIGN:
-      case PNK_POWASSIGN:
+      case ParseNodeKind::PNK_ASSIGN:
+      case ParseNodeKind::PNK_ADDASSIGN:
+      case ParseNodeKind::PNK_SUBASSIGN:
+      case ParseNodeKind::PNK_BITORASSIGN:
+      case ParseNodeKind::PNK_BITXORASSIGN:
+      case ParseNodeKind::PNK_BITANDASSIGN:
+      case ParseNodeKind::PNK_LSHASSIGN:
+      case ParseNodeKind::PNK_RSHASSIGN:
+      case ParseNodeKind::PNK_URSHASSIGN:
+      case ParseNodeKind::PNK_MULASSIGN:
+      case ParseNodeKind::PNK_DIVASSIGN:
+      case ParseNodeKind::PNK_MODASSIGN:
+      case ParseNodeKind::PNK_POWASSIGN:
       {
         MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_left->pn_pos));
         MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_right->pn_pos));
 
         AssignmentOperator op = aop(pn->getKind());
         LOCAL_ASSERT(op > AOP_ERR && op < AOP_LIMIT);
 
         RootedValue lhs(cx), rhs(cx);
         return pattern(pn->pn_left, &lhs) &&
                expression(pn->pn_right, &rhs) &&
                builder.assignmentExpression(op, lhs, rhs, &pn->pn_pos, dst);
       }
 
-      case PNK_PIPELINE:
-      case PNK_ADD:
-      case PNK_SUB:
-      case PNK_STRICTEQ:
-      case PNK_EQ:
-      case PNK_STRICTNE:
-      case PNK_NE:
-      case PNK_LT:
-      case PNK_LE:
-      case PNK_GT:
-      case PNK_GE:
-      case PNK_LSH:
-      case PNK_RSH:
-      case PNK_URSH:
-      case PNK_STAR:
-      case PNK_DIV:
-      case PNK_MOD:
-      case PNK_BITOR:
-      case PNK_BITXOR:
-      case PNK_BITAND:
-      case PNK_IN:
-      case PNK_INSTANCEOF:
+      case ParseNodeKind::PNK_PIPELINE:
+      case ParseNodeKind::PNK_ADD:
+      case ParseNodeKind::PNK_SUB:
+      case ParseNodeKind::PNK_STRICTEQ:
+      case ParseNodeKind::PNK_EQ:
+      case ParseNodeKind::PNK_STRICTNE:
+      case ParseNodeKind::PNK_NE:
+      case ParseNodeKind::PNK_LT:
+      case ParseNodeKind::PNK_LE:
+      case ParseNodeKind::PNK_GT:
+      case ParseNodeKind::PNK_GE:
+      case ParseNodeKind::PNK_LSH:
+      case ParseNodeKind::PNK_RSH:
+      case ParseNodeKind::PNK_URSH:
+      case ParseNodeKind::PNK_STAR:
+      case ParseNodeKind::PNK_DIV:
+      case ParseNodeKind::PNK_MOD:
+      case ParseNodeKind::PNK_BITOR:
+      case ParseNodeKind::PNK_BITXOR:
+      case ParseNodeKind::PNK_BITAND:
+      case ParseNodeKind::PNK_IN:
+      case ParseNodeKind::PNK_INSTANCEOF:
         return leftAssociate(pn, dst);
 
-      case PNK_POW:
+      case ParseNodeKind::PNK_POW:
         return rightAssociate(pn, dst);
 
-      case PNK_DELETENAME:
-      case PNK_DELETEPROP:
-      case PNK_DELETEELEM:
-      case PNK_DELETEEXPR:
-      case PNK_TYPEOFNAME:
-      case PNK_TYPEOFEXPR:
-      case PNK_VOID:
-      case PNK_NOT:
-      case PNK_BITNOT:
-      case PNK_POS:
-      case PNK_AWAIT:
-      case PNK_NEG: {
+      case ParseNodeKind::PNK_DELETENAME:
+      case ParseNodeKind::PNK_DELETEPROP:
+      case ParseNodeKind::PNK_DELETEELEM:
+      case ParseNodeKind::PNK_DELETEEXPR:
+      case ParseNodeKind::PNK_TYPEOFNAME:
+      case ParseNodeKind::PNK_TYPEOFEXPR:
+      case ParseNodeKind::PNK_VOID:
+      case ParseNodeKind::PNK_NOT:
+      case ParseNodeKind::PNK_BITNOT:
+      case ParseNodeKind::PNK_POS:
+      case ParseNodeKind::PNK_AWAIT:
+      case ParseNodeKind::PNK_NEG: {
         MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_kid->pn_pos));
 
         UnaryOperator op = unop(pn->getKind());
         LOCAL_ASSERT(op > UNOP_ERR && op < UNOP_LIMIT);
 
         RootedValue expr(cx);
         return expression(pn->pn_kid, &expr) &&
                builder.unaryExpression(op, expr, &pn->pn_pos, dst);
       }
 
-      case PNK_NEW:
-      case PNK_TAGGED_TEMPLATE:
-      case PNK_CALL:
-      case PNK_SUPERCALL:
+      case ParseNodeKind::PNK_NEW:
+      case ParseNodeKind::PNK_TAGGED_TEMPLATE:
+      case ParseNodeKind::PNK_CALL:
+      case ParseNodeKind::PNK_SUPERCALL:
       {
         ParseNode* next = pn->pn_head;
         MOZ_ASSERT(pn->pn_pos.encloses(next->pn_pos));
 
         RootedValue callee(cx);
-        if (pn->isKind(PNK_SUPERCALL)) {
-            MOZ_ASSERT(next->isKind(PNK_SUPERBASE));
+        if (pn->isKind(ParseNodeKind::PNK_SUPERCALL)) {
+            MOZ_ASSERT(next->isKind(ParseNodeKind::PNK_SUPERBASE));
             if (!builder.super(&next->pn_pos, &callee))
                 return false;
         } else {
             if (!expression(next, &callee))
                 return false;
         }
 
         NodeVector args(cx);
@@ -2734,27 +2734,27 @@ ASTSerializer::expression(ParseNode* pn,
             MOZ_ASSERT(pn->pn_pos.encloses(next->pn_pos));
 
             RootedValue arg(cx);
             if (!expression(next, &arg))
                 return false;
             args.infallibleAppend(arg);
         }
 
-        if (pn->getKind() == PNK_TAGGED_TEMPLATE)
+        if (pn->getKind() == ParseNodeKind::PNK_TAGGED_TEMPLATE)
             return builder.taggedTemplate(callee, args, &pn->pn_pos, dst);
 
         // SUPERCALL is Call(super, args)
-        return pn->isKind(PNK_NEW)
+        return pn->isKind(ParseNodeKind::PNK_NEW)
                ? builder.newExpression(callee, args, &pn->pn_pos, dst)
 
             : builder.callExpression(callee, args, &pn->pn_pos, dst);
       }
 
-      case PNK_DOT:
+      case ParseNodeKind::PNK_DOT:
       {
         MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_expr->pn_pos));
 
         RootedValue expr(cx);
         RootedValue propname(cx);
         RootedAtom pnAtom(cx, pn->pn_atom);
 
         if (pn->as<PropertyAccess>().isSuper()) {
@@ -2764,17 +2764,17 @@ ASTSerializer::expression(ParseNode* pn,
             if (!expression(pn->pn_expr, &expr))
                 return false;
         }
 
         return identifier(pnAtom, nullptr, &propname) &&
                builder.memberExpression(false, expr, propname, &pn->pn_pos, dst);
       }
 
-      case PNK_ELEM:
+      case ParseNodeKind::PNK_ELEM:
       {
         MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_left->pn_pos));
         MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_right->pn_pos));
 
         RootedValue left(cx), right(cx);
 
         if (pn->as<PropertyByValue>().isSuper()) {
             if (!builder.super(&pn->pn_left->pn_pos, &left))
@@ -2783,17 +2783,17 @@ ASTSerializer::expression(ParseNode* pn,
             if (!expression(pn->pn_left, &left))
                 return false;
         }
 
         return expression(pn->pn_right, &right) &&
                builder.memberExpression(true, left, right, &pn->pn_pos, dst);
       }
 
-      case PNK_CALLSITEOBJ:
+      case ParseNodeKind::PNK_CALLSITEOBJ:
       {
         NodeVector raw(cx);
         if (!raw.reserve(pn->pn_head->pn_count))
             return false;
         for (ParseNode* next = pn->pn_head->pn_head; next; next = next->pn_next) {
             MOZ_ASSERT(pn->pn_pos.encloses(next->pn_pos));
 
             RootedValue expr(cx);
@@ -2804,65 +2804,65 @@ ASTSerializer::expression(ParseNode* pn,
         NodeVector cooked(cx);
         if (!cooked.reserve(pn->pn_count - 1))
             return false;
 
         for (ParseNode* next = pn->pn_head->pn_next; next; next = next->pn_next) {
             MOZ_ASSERT(pn->pn_pos.encloses(next->pn_pos));
 
             RootedValue expr(cx);
-            if (next->isKind(PNK_RAW_UNDEFINED)) {
+            if (next->isKind(ParseNodeKind::PNK_RAW_UNDEFINED)) {
                 expr.setUndefined();
             } else {
-                MOZ_ASSERT(next->isKind(PNK_TEMPLATE_STRING));
+                MOZ_ASSERT(next->isKind(ParseNodeKind::PNK_TEMPLATE_STRING));
                 expr.setString(next->pn_atom);
             }
             cooked.infallibleAppend(expr);
         }
 
         return builder.callSiteObj(raw, cooked, &pn->pn_pos, dst);
       }
 
-      case PNK_ARRAY:
+      case ParseNodeKind::PNK_ARRAY:
       {
         NodeVector elts(cx);
         if (!elts.reserve(pn->pn_count))
             return false;
 
         for (ParseNode* next = pn->pn_head; next; next = next->pn_next) {
             MOZ_ASSERT(pn->pn_pos.encloses(next->pn_pos));
 
-            if (next->isKind(PNK_ELISION)) {
+            if (next->isKind(ParseNodeKind::PNK_ELISION)) {
                 elts.infallibleAppend(NullValue());
             } else {
                 RootedValue expr(cx);
                 if (!expression(next, &expr))
                     return false;
                 elts.infallibleAppend(expr);
             }
         }
 
         return builder.arrayExpression(elts, &pn->pn_pos, dst);
       }
 
-      case PNK_SPREAD:
+      case ParseNodeKind::PNK_SPREAD:
       {
           RootedValue expr(cx);
           return expression(pn->pn_kid, &expr) &&
                  builder.spreadExpression(expr, &pn->pn_pos, dst);
       }
 
-      case PNK_COMPUTED_NAME:
+      case ParseNodeKind::PNK_COMPUTED_NAME:
       {
          RootedValue name(cx);
          return expression(pn->pn_kid, &name) &&
                 builder.computedName(name, &pn->pn_pos, dst);
       }
 
-      case PNK_OBJECT:
+      case ParseNodeKind::PNK_OBJECT:
       {
         NodeVector elts(cx);
         if (!elts.reserve(pn->pn_count))
             return false;
 
         for (ParseNode* next = pn->pn_head; next; next = next->pn_next) {
             MOZ_ASSERT(pn->pn_pos.encloses(next->pn_pos));
 
@@ -2870,23 +2870,23 @@ ASTSerializer::expression(ParseNode* pn,
             if (!property(next, &prop))
                 return false;
             elts.infallibleAppend(prop);
         }
 
         return builder.objectExpression(elts, &pn->pn_pos, dst);
       }
 
-      case PNK_NAME:
+      case ParseNodeKind::PNK_NAME:
         return identifier(pn, dst);
 
-      case PNK_THIS:
+      case ParseNodeKind::PNK_THIS:
         return builder.thisExpression(&pn->pn_pos, dst);
 
-      case PNK_TEMPLATE_STRING_LIST:
+      case ParseNodeKind::PNK_TEMPLATE_STRING_LIST:
       {
         NodeVector elts(cx);
         if (!elts.reserve(pn->pn_count))
             return false;
 
         for (ParseNode* next = pn->pn_head; next; next = next->pn_next) {
             MOZ_ASSERT(pn->pn_pos.encloses(next->pn_pos));
 
@@ -2894,98 +2894,98 @@ ASTSerializer::expression(ParseNode* pn,
             if (!expression(next, &expr))
                 return false;
             elts.infallibleAppend(expr);
         }
 
         return builder.templateLiteral(elts, &pn->pn_pos, dst);
       }
 
-      case PNK_TEMPLATE_STRING:
-      case PNK_STRING:
-      case PNK_REGEXP:
-      case PNK_NUMBER:
-      case PNK_TRUE:
-      case PNK_FALSE:
-      case PNK_NULL:
-      case PNK_RAW_UNDEFINED:
+      case ParseNodeKind::PNK_TEMPLATE_STRING:
+      case ParseNodeKind::PNK_STRING:
+      case ParseNodeKind::PNK_REGEXP:
+      case ParseNodeKind::PNK_NUMBER:
+      case ParseNodeKind::PNK_TRUE:
+      case ParseNodeKind::PNK_FALSE:
+      case ParseNodeKind::PNK_NULL:
+      case ParseNodeKind::PNK_RAW_UNDEFINED:
         return literal(pn, dst);
 
-      case PNK_YIELD_STAR:
+      case ParseNodeKind::PNK_YIELD_STAR:
       {
         MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_kid->pn_pos));
 
         RootedValue arg(cx);
         return expression(pn->pn_kid, &arg) &&
                builder.yieldExpression(arg, Delegating, &pn->pn_pos, dst);
       }
 
-      case PNK_YIELD:
+      case ParseNodeKind::PNK_YIELD:
       {
         MOZ_ASSERT_IF(pn->pn_kid, pn->pn_pos.encloses(pn->pn_kid->pn_pos));
 
         RootedValue arg(cx);
         return optExpression(pn->pn_kid, &arg) &&
                builder.yieldExpression(arg, NotDelegating, &pn->pn_pos, dst);
       }
 
-      case PNK_CLASS:
+      case ParseNodeKind::PNK_CLASS:
         return classDefinition(pn, true, dst);
 
-      case PNK_NEWTARGET:
+      case ParseNodeKind::PNK_NEWTARGET:
       {
-        MOZ_ASSERT(pn->pn_left->isKind(PNK_POSHOLDER));
+        MOZ_ASSERT(pn->pn_left->isKind(ParseNodeKind::PNK_POSHOLDER));
         MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_left->pn_pos));
-        MOZ_ASSERT(pn->pn_right->isKind(PNK_POSHOLDER));
+        MOZ_ASSERT(pn->pn_right->isKind(ParseNodeKind::PNK_POSHOLDER));
         MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_right->pn_pos));
 
         RootedValue newIdent(cx);
         RootedValue targetIdent(cx);
 
         RootedAtom newStr(cx, cx->names().new_);
         RootedAtom targetStr(cx, cx->names().target);
 
         return identifier(newStr, &pn->pn_left->pn_pos, &newIdent) &&
                identifier(targetStr, &pn->pn_right->pn_pos, &targetIdent) &&
                builder.metaProperty(newIdent, targetIdent, &pn->pn_pos, dst);
       }
 
-      case PNK_SETTHIS:
+      case ParseNodeKind::PNK_SETTHIS:
         // SETTHIS is used to assign the result of a super() call to |this|.
         // It's not part of the original AST, so just forward to the call.
-        MOZ_ASSERT(pn->pn_left->isKind(PNK_NAME));
+        MOZ_ASSERT(pn->pn_left->isKind(ParseNodeKind::PNK_NAME));
         return expression(pn->pn_right, dst);
 
       default:
         LOCAL_NOT_REACHED("unexpected expression type");
     }
 }
 
 bool
 ASTSerializer::propertyName(ParseNode* pn, MutableHandleValue dst)
 {
-    if (pn->isKind(PNK_COMPUTED_NAME))
+    if (pn->isKind(ParseNodeKind::PNK_COMPUTED_NAME))
         return expression(pn, dst);
-    if (pn->isKind(PNK_OBJECT_PROPERTY_NAME))
+    if (pn->isKind(ParseNodeKind::PNK_OBJECT_PROPERTY_NAME))
         return identifier(pn, dst);
 
-    LOCAL_ASSERT(pn->isKind(PNK_STRING) || pn->isKind(PNK_NUMBER));
+    LOCAL_ASSERT(pn->isKind(ParseNodeKind::PNK_STRING) || pn->isKind(ParseNodeKind::PNK_NUMBER));
 
     return literal(pn, dst);
 }
 
 bool
 ASTSerializer::property(ParseNode* pn, MutableHandleValue dst)
 {
-    if (pn->isKind(PNK_MUTATEPROTO)) {
+    if (pn->isKind(ParseNodeKind::PNK_MUTATEPROTO)) {
         RootedValue val(cx);
         return expression(pn->pn_kid, &val) &&
                builder.prototypeMutation(val, &pn->pn_pos, dst);
     }
-    if (pn->isKind(PNK_SPREAD))
+    if (pn->isKind(ParseNodeKind::PNK_SPREAD))
         return expression(pn, dst);
 
     PropKind kind;
     switch (pn->getOp()) {
       case JSOP_INITPROP:
         kind = PROP_INIT;
         break;
 
@@ -2996,89 +2996,89 @@ ASTSerializer::property(ParseNode* pn, M
       case JSOP_INITPROP_SETTER:
         kind = PROP_SETTER;
         break;
 
       default:
         LOCAL_NOT_REACHED("unexpected object-literal property");
     }
 
-    bool isShorthand = pn->isKind(PNK_SHORTHAND);
+    bool isShorthand = pn->isKind(ParseNodeKind::PNK_SHORTHAND);
     bool isMethod =
-        pn->pn_right->isKind(PNK_FUNCTION) &&
+        pn->pn_right->isKind(ParseNodeKind::PNK_FUNCTION) &&
         pn->pn_right->pn_funbox->function()->kind() == JSFunction::Method;
     RootedValue key(cx), val(cx);
     return propertyName(pn->pn_left, &key) &&
            expression(pn->pn_right, &val) &&
            builder.propertyInitializer(key, val, kind, isShorthand, isMethod, &pn->pn_pos, dst);
 }
 
 bool
 ASTSerializer::literal(ParseNode* pn, MutableHandleValue dst)
 {
     RootedValue val(cx);
     switch (pn->getKind()) {
-      case PNK_TEMPLATE_STRING:
-      case PNK_STRING:
+      case ParseNodeKind::PNK_TEMPLATE_STRING:
+      case ParseNodeKind::PNK_STRING:
         val.setString(pn->pn_atom);
         break;
 
-      case PNK_REGEXP:
+      case ParseNodeKind::PNK_REGEXP:
       {
         RootedObject re1(cx, pn->as<RegExpLiteral>().objbox()->object);
         LOCAL_ASSERT(re1 && re1->is<RegExpObject>());
 
         RootedObject re2(cx, CloneRegExpObject(cx, re1.as<RegExpObject>()));
         if (!re2)
             return false;
 
         val.setObject(*re2);
         break;
       }
 
-      case PNK_NUMBER:
+      case ParseNodeKind::PNK_NUMBER:
         val.setNumber(pn->pn_dval);
         break;
 
-      case PNK_NULL:
+      case ParseNodeKind::PNK_NULL:
         val.setNull();
         break;
 
-      case PNK_RAW_UNDEFINED:
+      case ParseNodeKind::PNK_RAW_UNDEFINED:
         val.setUndefined();
         break;
 
-      case PNK_TRUE:
+      case ParseNodeKind::PNK_TRUE:
         val.setBoolean(true);
         break;
 
-      case PNK_FALSE:
+      case ParseNodeKind::PNK_FALSE:
         val.setBoolean(false);
         break;
 
       default:
         LOCAL_NOT_REACHED("unexpected literal type");
     }
 
     return builder.literal(val, &pn->pn_pos, dst);
 }
 
 bool
 ASTSerializer::arrayPattern(ParseNode* pn, MutableHandleValue dst)
 {
-    MOZ_ASSERT(pn->isKind(PNK_ARRAY));
+    MOZ_ASSERT(pn->isKind(ParseNodeKind::PNK_ARRAY));
 
     NodeVector elts(cx);
     if (!elts.reserve(pn->pn_count))
         return false;
 
     for (ParseNode* next = pn->pn_head; next; next = next->pn_next) {
-        if (next->isKind(PNK_ELISION)) {
+        if (next->isKind(ParseNodeKind::PNK_ELISION)) {
             elts.infallibleAppend(NullValue());
-        } else if (next->isKind(PNK_SPREAD)) {
+        } else if (next->isKind(ParseNodeKind::PNK_SPREAD)) {
             RootedValue target(cx);
             RootedValue spread(cx);
             if (!pattern(next->pn_kid, &target))
                 return false;
             if(!builder.spreadExpression(target, &next->pn_pos, &spread))
                 return false;
             elts.infallibleAppend(spread);
         } else {
@@ -3090,51 +3090,52 @@ ASTSerializer::arrayPattern(ParseNode* p
     }
 
     return builder.arrayPattern(elts, &pn->pn_pos, dst);
 }
 
 bool
 ASTSerializer::objectPattern(ParseNode* pn, MutableHandleValue dst)
 {
-    MOZ_ASSERT(pn->isKind(PNK_OBJECT));
+    MOZ_ASSERT(pn->isKind(ParseNodeKind::PNK_OBJECT));
 
     NodeVector elts(cx);
     if (!elts.reserve(pn->pn_count))
         return false;
 
     for (ParseNode* propdef = pn->pn_head; propdef; propdef = propdef->pn_next) {
-        if (propdef->isKind(PNK_SPREAD)) {
+        if (propdef->isKind(ParseNodeKind::PNK_SPREAD)) {
             RootedValue target(cx);
             RootedValue spread(cx);
             if (!pattern(propdef->pn_kid, &target))
                 return false;
             if(!builder.spreadExpression(target, &propdef->pn_pos, &spread))
                 return false;
             elts.infallibleAppend(spread);
             continue;
         }
-        LOCAL_ASSERT(propdef->isKind(PNK_MUTATEPROTO) != propdef->isOp(JSOP_INITPROP));
+        LOCAL_ASSERT(propdef->isKind(ParseNodeKind::PNK_MUTATEPROTO) != propdef->isOp(JSOP_INITPROP));
 
         RootedValue key(cx);
         ParseNode* target;
-        if (propdef->isKind(PNK_MUTATEPROTO)) {
+        if (propdef->isKind(ParseNodeKind::PNK_MUTATEPROTO)) {
             RootedValue pname(cx, StringValue(cx->names().proto));
             if (!builder.literal(pname, &propdef->pn_pos, &key))
                 return false;
             target = propdef->pn_kid;
         } else {
             if (!propertyName(propdef->pn_left, &key))
                 return false;
             target = propdef->pn_right;
         }
 
         RootedValue patt(cx), prop(cx);
         if (!pattern(target, &patt) ||
-            !builder.propertyPattern(key, patt, propdef->isKind(PNK_SHORTHAND), &propdef->pn_pos,
+            !builder.propertyPattern(key, patt, propdef->isKind(ParseNodeKind::PNK_SHORTHAND),
+                                     &propdef->pn_pos,
                                      &prop))
         {
             return false;
         }
 
         elts.infallibleAppend(prop);
     }
 
@@ -3143,20 +3144,20 @@ ASTSerializer::objectPattern(ParseNode* 
 
 bool
 ASTSerializer::pattern(ParseNode* pn, MutableHandleValue dst)
 {
     if (!CheckRecursionLimit(cx))
         return false;
 
     switch (pn->getKind()) {
-      case PNK_OBJECT:
+      case ParseNodeKind::PNK_OBJECT:
         return objectPattern(pn, dst);
 
-      case PNK_ARRAY:
+      case ParseNodeKind::PNK_ARRAY:
         return arrayPattern(pn, dst);
 
       default:
         return expression(pn, dst);
     }
 }
 
 bool
@@ -3211,45 +3212,45 @@ bool
 ASTSerializer::functionArgsAndBody(ParseNode* pn, NodeVector& args, NodeVector& defaults,
                                    bool isAsync, bool isExpression,
                                    MutableHandleValue body, MutableHandleValue rest)
 {
     ParseNode* pnargs;
     ParseNode* pnbody;
 
     /* Extract the args and body separately. */
-    if (pn->isKind(PNK_PARAMSBODY)) {
+    if (pn->isKind(ParseNodeKind::PNK_PARAMSBODY)) {
         pnargs = pn;
         pnbody = pn->last();
     } else {
         pnargs = nullptr;
         pnbody = pn;
     }
 
-    if (pnbody->isKind(PNK_LEXICALSCOPE))
+    if (pnbody->isKind(ParseNodeKind::PNK_LEXICALSCOPE))
         pnbody = pnbody->scopeBody();
 
     /* Serialize the arguments and body. */
     switch (pnbody->getKind()) {
-      case PNK_RETURN: /* expression closure, no destructured args */
+      case ParseNodeKind::PNK_RETURN: /* expression closure, no destructured args */
         return functionArgs(pn, pnargs, args, defaults, rest) &&
                expression(pnbody->pn_kid, body);
 
-      case PNK_STATEMENTLIST:     /* statement closure */
+      case ParseNodeKind::PNK_STATEMENTLIST:     /* statement closure */
       {
         ParseNode* pnstart = pnbody->pn_head;
 
         // Skip over initial yield in generator.
-        if (pnstart && pnstart->isKind(PNK_INITIALYIELD))
+        if (pnstart && pnstart->isKind(ParseNodeKind::PNK_INITIALYIELD))
             pnstart = pnstart->pn_next;
 
         // Async arrow with expression body is converted into STATEMENTLIST
         // to insert initial yield.
         if (isAsync && isExpression) {
-            MOZ_ASSERT(pnstart->getKind() == PNK_RETURN);
+            MOZ_ASSERT(pnstart->getKind() == ParseNodeKind::PNK_RETURN);
             return functionArgs(pn, pnargs, args, defaults, rest) &&
                    expression(pnstart->pn_kid, body);
         }
 
         return functionArgs(pn, pnargs, args, defaults, rest) &&
                functionBody(pnstart, &pnbody->pn_pos, body);
       }
 
@@ -3270,27 +3271,32 @@ ASTSerializer::functionArgs(ParseNode* p
     bool defaultsNull = true;
     MOZ_ASSERT(defaults.empty(),
                "must be initially empty for it to be proper to clear this "
                "when there are no defaults");
 
     for (ParseNode* arg = pnargs->pn_head; arg && arg != pnargs->last(); arg = arg->pn_next) {
         ParseNode* pat;
         ParseNode* defNode;
-        if (arg->isKind(PNK_NAME) || arg->isKind(PNK_ARRAY) || arg->isKind(PNK_OBJECT)) {
+        if (arg->isKind(ParseNodeKind::PNK_NAME) ||
+            arg->isKind(ParseNodeKind::PNK_ARRAY) ||
+            arg->isKind(ParseNodeKind::PNK_OBJECT))
+        {
             pat = arg;
             defNode = nullptr;
         } else {
-            MOZ_ASSERT(arg->isKind(PNK_ASSIGN));
+            MOZ_ASSERT(arg->isKind(ParseNodeKind::PNK_ASSIGN));
             pat = arg->pn_left;
             defNode = arg->pn_right;
         }
 
         // Process the name or pattern.
-        MOZ_ASSERT(pat->isKind(PNK_NAME) || pat->isKind(PNK_ARRAY) || pat->isKind(PNK_OBJECT));
+        MOZ_ASSERT(pat->isKind(ParseNodeKind::PNK_NAME) ||
+                   pat->isKind(ParseNodeKind::PNK_ARRAY) ||
+                   pat->isKind(ParseNodeKind::PNK_OBJECT));
         if (!pattern(pat, &node))
             return false;
         if (rest.isUndefined() && arg->pn_next == pnargs->last()) {
             rest.setObject(node.toObject());
         } else {
             if (!args.append(node))
                 return false;
         }
@@ -3495,17 +3501,17 @@ reflect_parse(JSContext* cx, uint32_t ar
         if (!builder.init())
             return false;
 
         ModuleSharedContext modulesc(cx, module, &cx->global()->emptyGlobalScope(), builder);
         pn = parser.moduleBody(&modulesc);
         if (!pn)
             return false;
 
-        MOZ_ASSERT(pn->getKind() == PNK_MODULE);
+        MOZ_ASSERT(pn->getKind() == ParseNodeKind::PNK_MODULE);
         pn = pn->pn_body;
     }
 
     RootedValue val(cx);
     if (!serialize.program(pn, &val)) {
         args.rval().setNull();
         return false;
     }
--- a/js/src/ctypes/Library.cpp
+++ b/js/src/ctypes/Library.cpp
@@ -233,20 +233,21 @@ Library::Open(JSContext* cx, unsigned ar
   args.rval().setObject(*library);
   return true;
 }
 
 bool
 Library::Close(JSContext* cx, unsigned argc, Value* vp)
 {
   CallArgs args = CallArgsFromVp(argc, vp);
-  JSObject* obj = JS_THIS_OBJECT(cx, vp);
-  if (!obj)
-    return false;
-  if (!IsLibrary(obj)) {
+
+  RootedObject obj(cx);
+  if (args.thisv().isObject())
+    obj = &args.thisv().toObject();
+  if (!obj || !IsLibrary(obj)) {
     JS_ReportErrorASCII(cx, "not a library");
     return false;
   }
 
   if (args.length() != 0) {
     JS_ReportErrorASCII(cx, "close doesn't take any arguments");
     return false;
   }
--- a/js/src/frontend/BinSource.cpp
+++ b/js/src/frontend/BinSource.cpp
@@ -799,17 +799,18 @@ BinASTParser::parseStatementAux(const Bi
 
         if (!left)
             return raiseMissingField("ForInStatement", BinField::Left);
         if (!right)
             return raiseMissingField("ForInStatement", BinField::Right);
         if (!body)
             return raiseMissingField("ForInStatement", BinField::Body);
 
-        TRY_DECL(forHead, factory_.newForInOrOfHead(PNK_FORIN, left, right, tokenizer_->pos(start)));
+        TRY_DECL(forHead, factory_.newForInOrOfHead(ParseNodeKind::PNK_FORIN, left, right,
+                                                    tokenizer_->pos(start)));
         TRY_VAR(result, factory_.newForStatement(start, forHead, body, /*flags*/ 0));
 
         if (!scope.isEmpty()) {
             TRY_DECL(bindings, NewLexicalScopeData(cx_, scope, alloc_, parseContext_));
             TRY_VAR(result, factory_.newLexicalScope(*bindings, result));
         }
         break;
       }
@@ -831,17 +832,17 @@ BinASTParser::parseBreakOrContinueStatem
     const auto start = tokenizer_->offset();
     ParseNode* label(nullptr);
 
     for (auto field : fields) {
         switch (field) {
           case BinField::Label:
             MOZ_TRY_VAR(label, parsePattern());
 
-            if (label && !label->isKind(PNK_NAME))
+            if (label && !label->isKind(ParseNodeKind::PNK_NAME))
                 return raiseError("ContinueStatement | BreakStatement - Label MUST be an identifier"); // FIXME: This should be changed in the grammar.
 
             break;
           default:
             return raiseInvalidField("ContinueStatement", field);
         }
     }
 
@@ -1027,17 +1028,17 @@ BinASTParser::parseFunctionAux(const Bin
             break;
           default:
             return raiseInvalidField("Function", field);
         }
     }
 
     // Inject default values for absent fields.
     if (!params)
-        TRY_VAR(params, new_<ListNode>(PNK_PARAMSBODY, tokenizer_->pos()));
+        TRY_VAR(params, new_<ListNode>(ParseNodeKind::PNK_PARAMSBODY, tokenizer_->pos()));
 
     if (!body)
         TRY_VAR(body, factory_.newStatementList(tokenizer_->pos()));
 
     if (kind == BinKind::FunctionDeclaration && !id) {
         // The name is compulsory only for function declarations.
         return raiseMissingField("FunctionDeclaration", BinField::Id);
     }
@@ -1046,29 +1047,31 @@ BinASTParser::parseFunctionAux(const Bin
     if (isMethod(kind) && !key)
         return raiseMissingField("method", BinField::Key);
 
     if (id)
         fun->initAtom(id->pn_atom);
 
     MOZ_ASSERT(params->isArity(PN_LIST));
 
-    if (!(body->isKind(PNK_LEXICALSCOPE) && body->pn_u.scope.body->isKind(PNK_STATEMENTLIST))) {
+    if (!(body->isKind(ParseNodeKind::PNK_LEXICALSCOPE) &&
+          body->pn_u.scope.body->isKind(ParseNodeKind::PNK_STATEMENTLIST)))
+    {
         // Promote to lexical scope + statement list.
-        if (!body->isKind(PNK_STATEMENTLIST)) {
+        if (!body->isKind(ParseNodeKind::PNK_STATEMENTLIST)) {
             TRY_DECL(list, factory_.newStatementList(tokenizer_->pos(start)));
 
             list->initList(body);
             body = list;
         }
 
         // Promote to lexical scope.
         TRY_VAR(body, factory_.newLexicalScope(nullptr, body));
     }
-    MOZ_ASSERT(body->isKind(PNK_LEXICALSCOPE));
+    MOZ_ASSERT(body->isKind(ParseNodeKind::PNK_LEXICALSCOPE));
 
     MOZ_TRY_VAR(body, appendDirectivesToBody(body, directives));
 
     params->appendWithoutOrderAssumption(body);
 
     TokenPos pos = tokenizer_->pos(start);
     TRY_DECL(function, kind == BinKind::FunctionDeclaration
                        ? factory_.newFunctionStatement(pos)
@@ -1156,41 +1159,42 @@ BinASTParser::parseVariableDeclarationAu
 {
     const size_t start = tokenizer_->offset();
 
     ParseNode* result(nullptr);
     switch (kind) {
       default:
         return raiseInvalidKind("VariableDeclaration", kind);
       case BinKind::VariableDeclaration:
-        ParseNodeKind pnk = PNK_LIMIT;
+        ParseNodeKind pnk = ParseNodeKind::PNK_LIMIT;
 
         for (auto field : fields) {
             switch (field) {
               case BinField::Kind: {
                 Maybe<Chars> kindName;
                 MOZ_TRY(readString(kindName));
 
                 if (*kindName == "let")
-                    pnk = PNK_LET;
+                    pnk = ParseNodeKind::PNK_LET;
                 else if (*kindName == "var")
-                    pnk = PNK_VAR;
+                    pnk = ParseNodeKind::PNK_VAR;
                 else if (*kindName == "const")
-                    pnk = PNK_CONST;
+                    pnk = ParseNodeKind::PNK_CONST;
                 else
                     return raiseInvalidEnum("VariableDeclaration", *kindName);
 
                 break;
               }
               case BinField::Declarations: {
                 uint32_t length;
                 AutoList guard(*tokenizer_);
 
                 TRY(tokenizer_->enterList(length, guard));
-                TRY_VAR(result, factory_.newDeclarationList(PNK_CONST /*Placeholder*/, tokenizer_->pos(start)));
+                TRY_VAR(result, factory_.newDeclarationList(ParseNodeKind::PNK_CONST /*Placeholder*/,
+                                                            tokenizer_->pos(start)));
 
                 for (uint32_t i = 0; i < length; ++i) {
                     ParseNode* current;
                     MOZ_TRY_VAR(current, parseVariableDeclarator());
                     MOZ_ASSERT(current);
 
                     result->appendWithoutOrderAssumption(current);
                 }
@@ -1198,22 +1202,22 @@ BinASTParser::parseVariableDeclarationAu
                 TRY(guard.done());
                 break;
               }
               default:
                 return raiseInvalidField("VariableDeclaration", field);
             }
         }
 
-        if (!result || pnk == PNK_LIMIT)
+        if (!result || pnk == ParseNodeKind::PNK_LIMIT)
             return raiseMissingField("VariableDeclaration", BinField::Declarations);
 
         result->setKind(pnk);
 
-        MOZ_ASSERT(!result->isKind(PNK_NOP));
+        MOZ_ASSERT(!result->isKind(ParseNodeKind::PNK_NOP));
     }
 
     return result;
 }
 
 
 JS::Result<ParseNode*>
 BinASTParser::parseExpressionStatementAux(const BinKind kind, const BinFields& fields)
@@ -1271,31 +1275,31 @@ BinASTParser::parseVariableDeclarator()
 
     TRY(guard.done());
     if (!id)
         return raiseMissingField("VariableDeclarator", BinField::Id);
 
     ParseNode* result(nullptr);
 
     // FIXME: Documentation in ParseNode is clearly obsolete.
-    if (id->isKind(PNK_NAME)) {
+    if (id->isKind(ParseNodeKind::PNK_NAME)) {
         // `var foo [= bar]``
         TRY_VAR(result, factory_.newName(id->pn_atom->asPropertyName(), tokenizer_->pos(start), cx_));
 
         if (init)
             result->pn_expr = init;
 
     } else {
         // `var pattern = bar`
         if (!init) {
             // Here, `init` is required.
             return raiseMissingField("VariableDeclarator (with non-trivial pattern)", BinField::Init);
         }
 
-        TRY_VAR(result, factory_.newAssignment(PNK_ASSIGN, id, init));
+        TRY_VAR(result, factory_.newAssignment(ParseNodeKind::PNK_ASSIGN, id, init));
     }
 
     return result;
 }
 
 JS::Result<ParseNode*>
 BinASTParser::parseExpressionList(bool acceptElisions)
 {
@@ -1547,65 +1551,65 @@ BinASTParser::parseExpressionAux(const B
             return raiseMissingField("UpdateExpression", BinField::Argument);
         if (operation.isNothing())
             return raiseMissingField("UpdateExpression", BinField::Operator);
 
         // In case of absent optional fields, inject default values.
         if (prefix.isNothing())
             prefix.emplace(false);
 
-        ParseNodeKind pnk = PNK_LIMIT;
+        ParseNodeKind pnk = ParseNodeKind::PNK_LIMIT;
         if (kind == BinKind::UnaryExpression) {
             if (*operation == "-") {
-                pnk = PNK_NEG;
+                pnk = ParseNodeKind::PNK_NEG;
             } else if (*operation == "+") {
-                pnk = PNK_POS;
+                pnk = ParseNodeKind::PNK_POS;
             } else if (*operation == "!") {
-                pnk = PNK_NOT;
+                pnk = ParseNodeKind::PNK_NOT;
             } else if (*operation == "~") {
-                pnk = PNK_BITNOT;
+                pnk = ParseNodeKind::PNK_BITNOT;
             } else if (*operation == "typeof") {
-                if (expr->isKind(PNK_NAME))
-                    pnk = PNK_TYPEOFNAME;
+                if (expr->isKind(ParseNodeKind::PNK_NAME))
+                    pnk = ParseNodeKind::PNK_TYPEOFNAME;
                 else
-                    pnk = PNK_TYPEOFEXPR;
+                    pnk = ParseNodeKind::PNK_TYPEOFEXPR;
             } else if (*operation == "void") {
-                pnk = PNK_VOID;
+                pnk = ParseNodeKind::PNK_VOID;
             } else if (*operation == "delete") {
                 switch (expr->getKind()) {
-                  case PNK_NAME:
+                  case ParseNodeKind::PNK_NAME:
                     expr->setOp(JSOP_DELNAME);
-                    pnk = PNK_DELETENAME;
+                    pnk = ParseNodeKind::PNK_DELETENAME;
                     break;
-                  case PNK_DOT:
-                    pnk = PNK_DELETEPROP;
+                  case ParseNodeKind::PNK_DOT:
+                    pnk = ParseNodeKind::PNK_DELETEPROP;
                     break;
-                  case PNK_ELEM:
-                    pnk = PNK_DELETEELEM;
+                  case ParseNodeKind::PNK_ELEM:
+                    pnk = ParseNodeKind::PNK_DELETEELEM;
                     break;
                   default:
-                    pnk = PNK_DELETEEXPR;
+                    pnk = ParseNodeKind::PNK_DELETEEXPR;
                 }
             } else {
                 return raiseInvalidEnum("UnaryOperator", *operation);
             }
         } else if (kind == BinKind::UpdateExpression) {
-            if (!expr->isKind(PNK_NAME) && !factory_.isPropertyAccess(expr))
+            if (!expr->isKind(ParseNodeKind::PNK_NAME) && !factory_.isPropertyAccess(expr))
                 return raiseError("Invalid increment/decrement operand"); // FIXME: Shouldn't this be part of the syntax?
 
             if (*operation == "++") {
                 if (*prefix)
-                    pnk = PNK_PREINCREMENT;
+                    pnk = ParseNodeKind::PNK_PREINCREMENT;
                 else
-                    pnk = PNK_POSTINCREMENT;
+                    pnk = ParseNodeKind::PNK_POSTINCREMENT;
             } else if (*operation == "--") {
                 if (*prefix)
-                    pnk = PNK_PREDECREMENT;
+                    pnk = ParseNodeKind::PNK_PREDECREMENT;
                 else
-                    pnk = PNK_POSTDECREMENT;
+                    pnk = ParseNodeKind::PNK_POSTDECREMENT;
             } else {
                 return raiseInvalidEnum("UpdateOperator", *operation);
             }
         }
 
         TRY_VAR(result, factory_.newUnary(pnk, start, expr));
 
         break;
@@ -1635,69 +1639,71 @@ BinASTParser::parseExpressionAux(const B
             return raiseMissingField("LogicalExpression | BinaryExpression", BinField::Left);
         if (!right)
             return raiseMissingField("LogicalExpression | BinaryExpression", BinField::Right);
         if (operation.isNothing())
             return raiseMissingField("LogicalExpression | BinaryExpression", BinField::Operator);
 
         // FIXME: Instead of Chars, we should use atoms and comparison
         // between atom ptr.
-        ParseNodeKind pnk = PNK_LIMIT;
+        ParseNodeKind pnk = ParseNodeKind::PNK_LIMIT;
         if (*operation == "==")
-            pnk = PNK_EQ;
+            pnk = ParseNodeKind::PNK_EQ;
         else if (*operation == "!=")
-            pnk = PNK_NE;
+            pnk = ParseNodeKind::PNK_NE;
         else if (*operation == "===")
-            pnk = PNK_STRICTEQ;
+            pnk = ParseNodeKind::PNK_STRICTEQ;
         else if (*operation == "!==")
-            pnk = PNK_STRICTNE;
+            pnk = ParseNodeKind::PNK_STRICTNE;
         else if (*operation == "<")
-            pnk = PNK_LT;
+            pnk = ParseNodeKind::PNK_LT;
         else if (*operation == "<=")
-            pnk = PNK_LE;
+            pnk = ParseNodeKind::PNK_LE;
         else if (*operation == ">")
-            pnk = PNK_GT;
+            pnk = ParseNodeKind::PNK_GT;
         else if (*operation == ">=")
-            pnk = PNK_GE;
+            pnk = ParseNodeKind::PNK_GE;
         else if (*operation == "<<")
-            pnk = PNK_LSH;
+            pnk = ParseNodeKind::PNK_LSH;
         else if (*operation == ">>")
-            pnk = PNK_RSH;
+            pnk = ParseNodeKind::PNK_RSH;
         else if (*operation == ">>>")
-            pnk = PNK_URSH;
+            pnk = ParseNodeKind::PNK_URSH;
         else if (*operation == "+")
-            pnk = PNK_ADD;
+            pnk = ParseNodeKind::PNK_ADD;
         else if (*operation == "-")
-            pnk = PNK_SUB;
+            pnk = ParseNodeKind::PNK_SUB;
         else if (*operation == "*")
-            pnk = PNK_STAR;
+            pnk = ParseNodeKind::PNK_STAR;
         else if (*operation == "/")
-            pnk = PNK_DIV;
+            pnk = ParseNodeKind::PNK_DIV;
         else if (*operation == "%")
-            pnk = PNK_MOD;
+            pnk = ParseNodeKind::PNK_MOD;
         else if (*operation == "|")
-            pnk = PNK_BITOR;
+            pnk = ParseNodeKind::PNK_BITOR;
         else if (*operation == "^")
-            pnk = PNK_BITXOR;
+            pnk = ParseNodeKind::PNK_BITXOR;
         else if (*operation == "&")
-            pnk = PNK_BITAND;
+            pnk = ParseNodeKind::PNK_BITAND;
         else if (*operation == "in")
-            pnk = PNK_IN;
+            pnk = ParseNodeKind::PNK_IN;
         else if (*operation == "instanceof")
-            pnk = PNK_INSTANCEOF;
+            pnk = ParseNodeKind::PNK_INSTANCEOF;
         else if (*operation == "||")
-            pnk = PNK_OR;
+            pnk = ParseNodeKind::PNK_OR;
         else if (*operation == "&&")
-            pnk = PNK_AND;
+            pnk = ParseNodeKind::PNK_AND;
         else if (*operation == "**")
-            pnk = PNK_POW;
+            pnk = ParseNodeKind::PNK_POW;
         else
             return raiseInvalidEnum("BinaryOperator | LogicalOperator", *operation);
 
-        if (left->isKind(pnk) && pnk != PNK_POW /* PNK_POW is not left-associative */) {
+        if (left->isKind(pnk) &&
+            pnk != ParseNodeKind::PNK_POW /* ParseNodeKind::PNK_POW is not left-associative */)
+        {
             // Regroup left-associative operations into lists.
             left->appendWithoutOrderAssumption(right);
             result = left;
         } else {
             TRY_DECL(list, factory_.newList(pnk, tokenizer_->pos(start)));
 
             list->appendWithoutOrderAssumption(left);
             list->appendWithoutOrderAssumption(right);
@@ -1731,41 +1737,41 @@ BinASTParser::parseExpressionAux(const B
         if (!right)
             return raiseMissingField("AssignmentExpression", BinField::Right);
         if (operation.isNothing())
             return raiseMissingField("AssignmentExpression", BinField::Operator);
 
         // FIXME: Instead of Chars, we should use atoms and comparison
         // between atom ptr.
         // FIXME: We should probably turn associative operations into lists.
-        ParseNodeKind pnk = PNK_LIMIT;
+        ParseNodeKind pnk = ParseNodeKind::PNK_LIMIT;
         if (*operation == "=")
-            pnk = PNK_ASSIGN;
+            pnk = ParseNodeKind::PNK_ASSIGN;
         else if (*operation == "+=")
-            pnk = PNK_ADDASSIGN;
+            pnk = ParseNodeKind::PNK_ADDASSIGN;
         else if (*operation == "-=")
-            pnk = PNK_SUBASSIGN;
+            pnk = ParseNodeKind::PNK_SUBASSIGN;
         else if (*operation == "*=")
-            pnk = PNK_MULASSIGN;
+            pnk = ParseNodeKind::PNK_MULASSIGN;
         else if (*operation == "/=")
-            pnk = PNK_DIVASSIGN;
+            pnk = ParseNodeKind::PNK_DIVASSIGN;
         else if (*operation == "%=")
-            pnk = PNK_MODASSIGN;
+            pnk = ParseNodeKind::PNK_MODASSIGN;
         else if (*operation == "<<=")
-            pnk = PNK_LSHASSIGN;
+            pnk = ParseNodeKind::PNK_LSHASSIGN;
         else if (*operation == ">>=")
-            pnk = PNK_RSHASSIGN;
+            pnk = ParseNodeKind::PNK_RSHASSIGN;
         else if (*operation == ">>>=")
-            pnk = PNK_URSHASSIGN;
+            pnk = ParseNodeKind::PNK_URSHASSIGN;
         else if (*operation == "|=")
-            pnk = PNK_BITORASSIGN;
+            pnk = ParseNodeKind::PNK_BITORASSIGN;
         else if (*operation == "^=")
-            pnk = PNK_BITXORASSIGN;
+            pnk = ParseNodeKind::PNK_BITXORASSIGN;
         else if (*operation == "&=")
-            pnk = PNK_BITANDASSIGN;
+            pnk = ParseNodeKind::PNK_BITANDASSIGN;
         else
             return raiseInvalidEnum("AssignmentOperator", *operation);
 
         TRY_VAR(result, factory_.newAssignment(pnk, left, right));
 
         break;
       }
       case BinKind::BracketExpression:
@@ -1827,18 +1833,18 @@ BinASTParser::parseExpressionAux(const B
             return raiseMissingField("NewExpression", BinField::Callee);
 
         // In case of absent optional fields, inject default values.
         if (!result)
             TRY_VAR(result, factory_.newArrayLiteral(start));
 
         ParseNodeKind pnk =
             kind == BinKind::CallExpression
-            ? PNK_CALL
-            : PNK_NEW;
+            ? ParseNodeKind::PNK_CALL
+            : ParseNodeKind::PNK_NEW;
         result->setKind(pnk);
         result->prepend(callee);
 
         break;
       }
       case BinKind::SequenceExpression: {
         for (auto field : fields) {
             switch (field) {
@@ -1848,17 +1854,17 @@ BinASTParser::parseExpressionAux(const B
               default:
                 return raiseInvalidField("SequenceExpression", field);
             }
         }
 
         if (!result)
             return raiseMissingField("SequenceExpression", BinField::Expression);
 
-        result->setKind(PNK_COMMA);
+        result->setKind(ParseNodeKind::PNK_COMMA);
         break;
       }
       default:
         return raiseInvalidKind("Expression", kind);
     }
 
     return result;
 }
@@ -1926,17 +1932,17 @@ BinASTParser::parseArrayExpressionAux(co
             return raiseInvalidField("ArrayExpression", field);
         }
     }
 
     // Inject default values for absent fields.
     if (!result)
         TRY_VAR(result, factory_.newArrayLiteral(tokenizer_->offset()));
 
-    MOZ_ASSERT(result->isKind(PNK_ARRAY));
+    MOZ_ASSERT(result->isKind(ParseNodeKind::PNK_ARRAY));
     return result;
 }
 
 JS::Result<ParseNode*>
 BinASTParser::parseObjectExpressionAux(const BinKind kind, const BinFields& fields)
 {
     MOZ_ASSERT(kind == BinKind::ObjectExpression);
 
@@ -1951,22 +1957,22 @@ BinASTParser::parseObjectExpressionAux(c
             return raiseInvalidField("Property | Method", field);
         }
     }
 
     if (!result)
         TRY_VAR(result, factory_.newObjectLiteral(tokenizer_->offset()));
 
     MOZ_ASSERT(result->isArity(PN_LIST));
-    MOZ_ASSERT(result->isKind(PNK_OBJECT));
+    MOZ_ASSERT(result->isKind(ParseNodeKind::PNK_OBJECT));
 
 #if defined(DEBUG)
     // Sanity check.
     for (ParseNode* iter = result->pn_head; iter != nullptr; iter = iter->pn_next) {
-        MOZ_ASSERT(iter->isKind(PNK_COLON));
+        MOZ_ASSERT(iter->isKind(ParseNodeKind::PNK_COLON));
         MOZ_ASSERT(iter->pn_left != nullptr);
         MOZ_ASSERT(iter->pn_right != nullptr);
     }
 #endif // defined(DEBUG)
 
     return result;
 }
 
@@ -1997,17 +2003,17 @@ BinASTParser::parseMemberExpressionAux(c
     // In case of absent required fields, fail.
     if (!object)
         return raiseMissingField("MemberExpression", BinField::Object);
     if (!property)
         return raiseMissingField("MemberExpression", BinField::Property);
 
     ParseNode* result(nullptr);
     if (kind == BinKind::DotExpression) {
-        MOZ_ASSERT(property->isKind(PNK_NAME));
+        MOZ_ASSERT(property->isKind(ParseNodeKind::PNK_NAME));
         PropertyName* name = property->pn_atom->asPropertyName();
         TRY_VAR(result, factory_.newPropertyAccess(object, name, tokenizer_->offset()));
     } else {
         TRY_VAR(result, factory_.newPropertyByValue(object, property, tokenizer_->offset()));
     }
 
     return result;
 }
@@ -2063,17 +2069,17 @@ BinASTParser::parseSwitchCase()
             return raiseInvalidField("SwitchCase", field);
         }
     }
 
     TRY(guard.done());
     if (!statements)
         return raiseMissingField("SwitchCase", BinField::Consequent);
 
-    MOZ_ASSERT(statements->isKind(PNK_STATEMENTLIST));
+    MOZ_ASSERT(statements->isKind(ParseNodeKind::PNK_STATEMENTLIST));
 
     TRY_DECL(result, factory_.newCaseOrDefault(start, test, statements));
 
     return result;
 }
 
 JS::Result<ParseNode*>
 BinASTParser::parseCatchClause()
@@ -2129,17 +2135,17 @@ BinASTParser::parseCatchClause()
 
 JS::Result<ParseNode*>
 BinASTParser::parseArgumentList()
 {
     uint32_t length;
     AutoList guard(*tokenizer_);
 
     TRY(tokenizer_->enterList(length, guard));
-    ParseNode* result = new_<ListNode>(PNK_PARAMSBODY, tokenizer_->pos());
+    ParseNode* result = new_<ListNode>(ParseNodeKind::PNK_PARAMSBODY, tokenizer_->pos());
 
     for (uint32_t i = 0; i < length; ++i) {
         ParseNode* pattern;
         MOZ_TRY_VAR(pattern, parsePattern());
 
         result->appendWithoutOrderAssumption(pattern);
     }
 
@@ -2271,17 +2277,17 @@ BinASTParser::parseObjectMember()
       case BinKind::ObjectMethod:
       case BinKind::ObjectGetter:
       case BinKind::ObjectSetter:
         MOZ_TRY_VAR(result, parseFunctionAux(kind, fields));
 
         if (!result)
             return raiseEmpty("ObjectMethod");
 
-        MOZ_ASSERT(result->isKind(PNK_COLON));
+        MOZ_ASSERT(result->isKind(ParseNodeKind::PNK_COLON));
         break;
       default:
         return raiseInvalidKind("ObjectMember", kind);
     }
 
     TRY(guard.done());
     MOZ_ASSERT(result);
     return result;
--- a/js/src/frontend/BytecodeEmitter.cpp
+++ b/js/src/frontend/BytecodeEmitter.cpp
@@ -60,17 +60,17 @@ class BreakableControl;
 class LabelControl;
 class LoopControl;
 class ForOfLoopControl;
 class TryFinallyControl;
 
 static bool
 ParseNodeRequiresSpecialLineNumberNotes(ParseNode* pn)
 {
-    return pn->getKind() == PNK_WHILE || pn->getKind() == PNK_FOR;
+    return pn->getKind() == ParseNodeKind::PNK_WHILE || pn->getKind() == ParseNodeKind::PNK_FOR;
 }
 
 // A cache that tracks superfluous TDZ checks.
 //
 // Each basic block should have a TDZCheckCache in scope. Some NestableControl
 // subclasses contain a TDZCheckCache.
 class BytecodeEmitter::TDZCheckCache : public Nestable<BytecodeEmitter::TDZCheckCache>
 {
@@ -2569,38 +2569,38 @@ bool
 BytecodeEmitter::emitLoopHead(ParseNode* nextpn, JumpTarget* top)
 {
     if (nextpn) {
         /*
          * Try to give the JSOP_LOOPHEAD the same line number as the next
          * instruction. nextpn is often a block, in which case the next
          * instruction typically comes from the first statement inside.
          */
-        if (nextpn->isKind(PNK_LEXICALSCOPE))
+        if (nextpn->isKind(ParseNodeKind::PNK_LEXICALSCOPE))
             nextpn = nextpn->scopeBody();
-        MOZ_ASSERT_IF(nextpn->isKind(PNK_STATEMENTLIST), nextpn->isArity(PN_LIST));
-        if (nextpn->isKind(PNK_STATEMENTLIST) && nextpn->pn_head)
+        MOZ_ASSERT_IF(nextpn->isKind(ParseNodeKind::PNK_STATEMENTLIST), nextpn->isArity(PN_LIST));
+        if (nextpn->isKind(ParseNodeKind::PNK_STATEMENTLIST) && nextpn->pn_head)
             nextpn = nextpn->pn_head;
         if (!updateSourceCoordNotes(nextpn->pn_pos.begin))
             return false;
     }
 
     *top = { offset() };
     return emit1(JSOP_LOOPHEAD);
 }
 
 bool
 BytecodeEmitter::emitLoopEntry(ParseNode* nextpn, JumpList entryJump)
 {
     if (nextpn) {
         /* Update the line number, as for LOOPHEAD. */
-        if (nextpn->isKind(PNK_LEXICALSCOPE))
+        if (nextpn->isKind(ParseNodeKind::PNK_LEXICALSCOPE))
             nextpn = nextpn->scopeBody();
-        MOZ_ASSERT_IF(nextpn->isKind(PNK_STATEMENTLIST), nextpn->isArity(PN_LIST));
-        if (nextpn->isKind(PNK_STATEMENTLIST) && nextpn->pn_head)
+        MOZ_ASSERT_IF(nextpn->isKind(ParseNodeKind::PNK_STATEMENTLIST), nextpn->isArity(PN_LIST));
+        if (nextpn->isKind(ParseNodeKind::PNK_STATEMENTLIST) && nextpn->pn_head)
             nextpn = nextpn->pn_head;
         if (!updateSourceCoordNotes(nextpn->pn_pos.begin))
             return false;
     }
 
     JumpTarget entry{ offset() };
     patchJumpsToTarget(entryJump, entry);
 
@@ -2998,20 +2998,24 @@ BytecodeEmitter::emitEnvCoordOp(JSOp op,
     pc += ENVCOORD_SLOT_LEN;
     checkTypeSet(op);
     return true;
 }
 
 static JSOp
 GetIncDecInfo(ParseNodeKind kind, bool* post)
 {
-    MOZ_ASSERT(kind == PNK_POSTINCREMENT || kind == PNK_PREINCREMENT ||
-               kind == PNK_POSTDECREMENT || kind == PNK_PREDECREMENT);
-    *post = kind == PNK_POSTINCREMENT || kind == PNK_POSTDECREMENT;
-    return (kind == PNK_POSTINCREMENT || kind == PNK_PREINCREMENT) ? JSOP_ADD : JSOP_SUB;
+    MOZ_ASSERT(kind == ParseNodeKind::PNK_POSTINCREMENT ||
+               kind == ParseNodeKind::PNK_PREINCREMENT ||
+               kind == ParseNodeKind::PNK_POSTDECREMENT ||
+               kind == ParseNodeKind::PNK_PREDECREMENT);
+    *post = kind == ParseNodeKind::PNK_POSTINCREMENT || kind == ParseNodeKind::PNK_POSTDECREMENT;
+    return (kind == ParseNodeKind::PNK_POSTINCREMENT || kind == ParseNodeKind::PNK_PREINCREMENT)
+           ? JSOP_ADD
+           : JSOP_SUB;
 }
 
 JSOp
 BytecodeEmitter::strictifySetNameOp(JSOp op)
 {
     switch (op) {
       case JSOP_SETNAME:
         if (sc->strict())
@@ -3031,434 +3035,434 @@ BytecodeEmitter::checkSideEffects(ParseN
 {
     if (!CheckRecursionLimit(cx))
         return false;
 
  restart:
 
     switch (pn->getKind()) {
       // Trivial cases with no side effects.
-      case PNK_NOP:
-      case PNK_STRING:
-      case PNK_TEMPLATE_STRING:
-      case PNK_REGEXP:
-      case PNK_TRUE:
-      case PNK_FALSE:
-      case PNK_NULL:
-      case PNK_RAW_UNDEFINED:
-      case PNK_ELISION:
-      case PNK_GENERATOR:
-      case PNK_NUMBER:
-      case PNK_OBJECT_PROPERTY_NAME:
+      case ParseNodeKind::PNK_NOP:
+      case ParseNodeKind::PNK_STRING:
+      case ParseNodeKind::PNK_TEMPLATE_STRING:
+      case ParseNodeKind::PNK_REGEXP:
+      case ParseNodeKind::PNK_TRUE:
+      case ParseNodeKind::PNK_FALSE:
+      case ParseNodeKind::PNK_NULL:
+      case ParseNodeKind::PNK_RAW_UNDEFINED:
+      case ParseNodeKind::PNK_ELISION:
+      case ParseNodeKind::PNK_GENERATOR:
+      case ParseNodeKind::PNK_NUMBER:
+      case ParseNodeKind::PNK_OBJECT_PROPERTY_NAME:
         MOZ_ASSERT(pn->isArity(PN_NULLARY));
         *answer = false;
         return true;
 
       // |this| can throw in derived class constructors, including nested arrow
       // functions or eval.
-      case PNK_THIS:
+      case ParseNodeKind::PNK_THIS:
         MOZ_ASSERT(pn->isArity(PN_UNARY));
         *answer = sc->needsThisTDZChecks();
         return true;
 
       // Trivial binary nodes with more token pos holders.
-      case PNK_NEWTARGET:
+      case ParseNodeKind::PNK_NEWTARGET:
         MOZ_ASSERT(pn->isArity(PN_BINARY));
-        MOZ_ASSERT(pn->pn_left->isKind(PNK_POSHOLDER));
-        MOZ_ASSERT(pn->pn_right->isKind(PNK_POSHOLDER));
+        MOZ_ASSERT(pn->pn_left->isKind(ParseNodeKind::PNK_POSHOLDER));
+        MOZ_ASSERT(pn->pn_right->isKind(ParseNodeKind::PNK_POSHOLDER));
         *answer = false;
         return true;
 
-      case PNK_BREAK:
-      case PNK_CONTINUE:
-      case PNK_DEBUGGER:
+      case ParseNodeKind::PNK_BREAK:
+      case ParseNodeKind::PNK_CONTINUE:
+      case ParseNodeKind::PNK_DEBUGGER:
         MOZ_ASSERT(pn->isArity(PN_NULLARY));
         *answer = true;
         return true;
 
       // Watch out for getters!
-      case PNK_DOT:
+      case ParseNodeKind::PNK_DOT:
         MOZ_ASSERT(pn->isArity(PN_NAME));
         *answer = true;
         return true;
 
       // Unary cases with side effects only if the child has them.
-      case PNK_TYPEOFEXPR:
-      case PNK_VOID:
-      case PNK_NOT:
+      case ParseNodeKind::PNK_TYPEOFEXPR:
+      case ParseNodeKind::PNK_VOID:
+      case ParseNodeKind::PNK_NOT:
         MOZ_ASSERT(pn->isArity(PN_UNARY));
         return checkSideEffects(pn->pn_kid, answer);
 
       // Even if the name expression is effect-free, performing ToPropertyKey on
       // it might not be effect-free:
       //
       //   RegExp.prototype.toString = () => { throw 42; };
       //   ({ [/regex/]: 0 }); // ToPropertyKey(/regex/) throws 42
       //
       //   function Q() {
       //     ({ [new.target]: 0 });
       //   }
       //   Q.toString = () => { throw 17; };
       //   new Q; // new.target will be Q, ToPropertyKey(Q) throws 17
-      case PNK_COMPUTED_NAME:
+      case ParseNodeKind::PNK_COMPUTED_NAME:
         MOZ_ASSERT(pn->isArity(PN_UNARY));
         *answer = true;
         return true;
 
       // Looking up or evaluating the associated name could throw.
-      case PNK_TYPEOFNAME:
+      case ParseNodeKind::PNK_TYPEOFNAME:
         MOZ_ASSERT(pn->isArity(PN_UNARY));
         *answer = true;
         return true;
 
       // This unary case has side effects on the enclosing object, sure.  But
       // that's not the question this function answers: it's whether the
       // operation may have a side effect on something *other* than the result
       // of the overall operation in which it's embedded.  The answer to that
       // is no, because an object literal having a mutated prototype only
       // produces a value, without affecting anything else.
-      case PNK_MUTATEPROTO:
+      case ParseNodeKind::PNK_MUTATEPROTO:
         MOZ_ASSERT(pn->isArity(PN_UNARY));
         return checkSideEffects(pn->pn_kid, answer);
 
       // Unary cases with obvious side effects.
-      case PNK_PREINCREMENT:
-      case PNK_POSTINCREMENT:
-      case PNK_PREDECREMENT:
-      case PNK_POSTDECREMENT:
-      case PNK_THROW:
+      case ParseNodeKind::PNK_PREINCREMENT:
+      case ParseNodeKind::PNK_POSTINCREMENT:
+      case ParseNodeKind::PNK_PREDECREMENT:
+      case ParseNodeKind::PNK_POSTDECREMENT:
+      case ParseNodeKind::PNK_THROW:
         MOZ_ASSERT(pn->isArity(PN_UNARY));
         *answer = true;
         return true;
 
       // These might invoke valueOf/toString, even with a subexpression without
       // side effects!  Consider |+{ valueOf: null, toString: null }|.
-      case PNK_BITNOT:
-      case PNK_POS:
-      case PNK_NEG:
+      case ParseNodeKind::PNK_BITNOT:
+      case ParseNodeKind::PNK_POS:
+      case ParseNodeKind::PNK_NEG:
         MOZ_ASSERT(pn->isArity(PN_UNARY));
         *answer = true;
         return true;
 
       // This invokes the (user-controllable) iterator protocol.
-      case PNK_SPREAD:
+      case ParseNodeKind::PNK_SPREAD:
         MOZ_ASSERT(pn->isArity(PN_UNARY));
         *answer = true;
         return true;
 
-      case PNK_INITIALYIELD:
-      case PNK_YIELD_STAR:
-      case PNK_YIELD:
-      case PNK_AWAIT:
+      case ParseNodeKind::PNK_INITIALYIELD:
+      case ParseNodeKind::PNK_YIELD_STAR:
+      case ParseNodeKind::PNK_YIELD:
+      case ParseNodeKind::PNK_AWAIT:
         MOZ_ASSERT(pn->isArity(PN_UNARY));
         *answer = true;
         return true;
 
       // Deletion generally has side effects, even if isolated cases have none.
-      case PNK_DELETENAME:
-      case PNK_DELETEPROP:
-      case PNK_DELETEELEM:
+      case ParseNodeKind::PNK_DELETENAME:
+      case ParseNodeKind::PNK_DELETEPROP:
+      case ParseNodeKind::PNK_DELETEELEM:
         MOZ_ASSERT(pn->isArity(PN_UNARY));
         *answer = true;
         return true;
 
       // Deletion of a non-Reference expression has side effects only through
       // evaluating the expression.
-      case PNK_DELETEEXPR: {
+      case ParseNodeKind::PNK_DELETEEXPR: {
         MOZ_ASSERT(pn->isArity(PN_UNARY));
         ParseNode* expr = pn->pn_kid;
         return checkSideEffects(expr, answer);
       }
 
-      case PNK_SEMI:
+      case ParseNodeKind::PNK_SEMI:
         MOZ_ASSERT(pn->isArity(PN_UNARY));
         if (ParseNode* expr = pn->pn_kid)
             return checkSideEffects(expr, answer);
         *answer = false;
         return true;
 
       // Binary cases with obvious side effects.
-      case PNK_ASSIGN:
-      case PNK_ADDASSIGN:
-      case PNK_SUBASSIGN:
-      case PNK_BITORASSIGN:
-      case PNK_BITXORASSIGN:
-      case PNK_BITANDASSIGN:
-      case PNK_LSHASSIGN:
-      case PNK_RSHASSIGN:
-      case PNK_URSHASSIGN:
-      case PNK_MULASSIGN:
-      case PNK_DIVASSIGN:
-      case PNK_MODASSIGN:
-      case PNK_POWASSIGN:
-      case PNK_SETTHIS:
+      case ParseNodeKind::PNK_ASSIGN:
+      case ParseNodeKind::PNK_ADDASSIGN:
+      case ParseNodeKind::PNK_SUBASSIGN:
+      case ParseNodeKind::PNK_BITORASSIGN:
+      case ParseNodeKind::PNK_BITXORASSIGN:
+      case ParseNodeKind::PNK_BITANDASSIGN:
+      case ParseNodeKind::PNK_LSHASSIGN:
+      case ParseNodeKind::PNK_RSHASSIGN:
+      case ParseNodeKind::PNK_URSHASSIGN:
+      case ParseNodeKind::PNK_MULASSIGN:
+      case ParseNodeKind::PNK_DIVASSIGN:
+      case ParseNodeKind::PNK_MODASSIGN:
+      case ParseNodeKind::PNK_POWASSIGN:
+      case ParseNodeKind::PNK_SETTHIS:
         MOZ_ASSERT(pn->isArity(PN_BINARY));
         *answer = true;
         return true;
 
-      case PNK_STATEMENTLIST:
+      case ParseNodeKind::PNK_STATEMENTLIST:
       // Strict equality operations and logical operators are well-behaved and
       // perform no conversions.
-      case PNK_OR:
-      case PNK_AND:
-      case PNK_STRICTEQ:
-      case PNK_STRICTNE:
+      case ParseNodeKind::PNK_OR:
+      case ParseNodeKind::PNK_AND:
+      case ParseNodeKind::PNK_STRICTEQ:
+      case ParseNodeKind::PNK_STRICTNE:
       // Any subexpression of a comma expression could be effectful.
-      case PNK_COMMA:
+      case ParseNodeKind::PNK_COMMA:
         MOZ_ASSERT(pn->pn_count > 0);
         MOZ_FALLTHROUGH;
       // Subcomponents of a literal may be effectful.
-      case PNK_ARRAY:
-      case PNK_OBJECT:
+      case ParseNodeKind::PNK_ARRAY:
+      case ParseNodeKind::PNK_OBJECT:
         MOZ_ASSERT(pn->isArity(PN_LIST));
         for (ParseNode* item = pn->pn_head; item; item = item->pn_next) {
             if (!checkSideEffects(item, answer))
                 return false;
             if (*answer)
                 return true;
         }
         return true;
 
       // Most other binary operations (parsed as lists in SpiderMonkey) may
       // perform conversions triggering side effects.  Math operations perform
       // ToNumber and may fail invoking invalid user-defined toString/valueOf:
       // |5 < { toString: null }|.  |instanceof| throws if provided a
       // non-object constructor: |null instanceof null|.  |in| throws if given
       // a non-object RHS: |5 in null|.
-      case PNK_BITOR:
-      case PNK_BITXOR:
-      case PNK_BITAND:
-      case PNK_EQ:
-      case PNK_NE:
-      case PNK_LT:
-      case PNK_LE:
-      case PNK_GT:
-      case PNK_GE:
-      case PNK_INSTANCEOF:
-      case PNK_IN:
-      case PNK_LSH:
-      case PNK_RSH:
-      case PNK_URSH:
-      case PNK_ADD:
-      case PNK_SUB:
-      case PNK_STAR:
-      case PNK_DIV:
-      case PNK_MOD:
-      case PNK_POW:
+      case ParseNodeKind::PNK_BITOR:
+      case ParseNodeKind::PNK_BITXOR:
+      case ParseNodeKind::PNK_BITAND:
+      case ParseNodeKind::PNK_EQ:
+      case ParseNodeKind::PNK_NE:
+      case ParseNodeKind::PNK_LT:
+      case ParseNodeKind::PNK_LE:
+      case ParseNodeKind::PNK_GT:
+      case ParseNodeKind::PNK_GE:
+      case ParseNodeKind::PNK_INSTANCEOF:
+      case ParseNodeKind::PNK_IN:
+      case ParseNodeKind::PNK_LSH:
+      case ParseNodeKind::PNK_RSH:
+      case ParseNodeKind::PNK_URSH:
+      case ParseNodeKind::PNK_ADD:
+      case ParseNodeKind::PNK_SUB:
+      case ParseNodeKind::PNK_STAR:
+      case ParseNodeKind::PNK_DIV:
+      case ParseNodeKind::PNK_MOD:
+      case ParseNodeKind::PNK_POW:
         MOZ_ASSERT(pn->isArity(PN_LIST));
         MOZ_ASSERT(pn->pn_count >= 2);
         *answer = true;
         return true;
 
-      case PNK_COLON:
-      case PNK_CASE:
+      case ParseNodeKind::PNK_COLON:
+      case ParseNodeKind::PNK_CASE:
         MOZ_ASSERT(pn->isArity(PN_BINARY));
         if (!checkSideEffects(pn->pn_left, answer))
             return false;
         if (*answer)
             return true;
         return checkSideEffects(pn->pn_right, answer);
 
       // More getters.
-      case PNK_ELEM:
+      case ParseNodeKind::PNK_ELEM:
         MOZ_ASSERT(pn->isArity(PN_BINARY));
         *answer = true;
         return true;
 
       // These affect visible names in this code, or in other code.
-      case PNK_IMPORT:
-      case PNK_EXPORT_FROM:
-      case PNK_EXPORT_DEFAULT:
+      case ParseNodeKind::PNK_IMPORT:
+      case ParseNodeKind::PNK_EXPORT_FROM:
+      case ParseNodeKind::PNK_EXPORT_DEFAULT:
         MOZ_ASSERT(pn->isArity(PN_BINARY));
         *answer = true;
         return true;
 
       // Likewise.
-      case PNK_EXPORT:
+      case ParseNodeKind::PNK_EXPORT:
         MOZ_ASSERT(pn->isArity(PN_UNARY));
         *answer = true;
         return true;
 
       // Every part of a loop might be effect-free, but looping infinitely *is*
       // an effect.  (Language lawyer trivia: C++ says threads can be assumed
       // to exit or have side effects, C++14 [intro.multithread]p27, so a C++
       // implementation's equivalent of the below could set |*answer = false;|
       // if all loop sub-nodes set |*answer = false|!)
-      case PNK_DOWHILE:
-      case PNK_WHILE:
-      case PNK_FOR:
+      case ParseNodeKind::PNK_DOWHILE:
+      case ParseNodeKind::PNK_WHILE:
+      case ParseNodeKind::PNK_FOR:
         MOZ_ASSERT(pn->isArity(PN_BINARY));
         *answer = true;
         return true;
 
       // Declarations affect the name set of the relevant scope.
-      case PNK_VAR:
-      case PNK_CONST:
-      case PNK_LET:
+      case ParseNodeKind::PNK_VAR:
+      case ParseNodeKind::PNK_CONST:
+      case ParseNodeKind::PNK_LET:
         MOZ_ASSERT(pn->isArity(PN_LIST));
         *answer = true;
         return true;
 
-      case PNK_IF:
-      case PNK_CONDITIONAL:
+      case ParseNodeKind::PNK_IF:
+      case ParseNodeKind::PNK_CONDITIONAL:
         MOZ_ASSERT(pn->isArity(PN_TERNARY));
         if (!checkSideEffects(pn->pn_kid1, answer))
             return false;
         if (*answer)
             return true;
         if (!checkSideEffects(pn->pn_kid2, answer))
             return false;
         if (*answer)
             return true;
         if ((pn = pn->pn_kid3))
             goto restart;
         return true;
 
       // Function calls can invoke non-local code.
-      case PNK_NEW:
-      case PNK_CALL:
-      case PNK_TAGGED_TEMPLATE:
-      case PNK_SUPERCALL:
+      case ParseNodeKind::PNK_NEW:
+      case ParseNodeKind::PNK_CALL:
+      case ParseNodeKind::PNK_TAGGED_TEMPLATE:
+      case ParseNodeKind::PNK_SUPERCALL:
         MOZ_ASSERT(pn->isArity(PN_LIST));
         *answer = true;
         return true;
 
-      case PNK_PIPELINE:
+      case ParseNodeKind::PNK_PIPELINE:
         MOZ_ASSERT(pn->isArity(PN_LIST));
         MOZ_ASSERT(pn->pn_count >= 2);
         *answer = true;
         return true;
 
       // Classes typically introduce names.  Even if no name is introduced,
       // the heritage and/or class body (through computed property names)
       // usually have effects.
-      case PNK_CLASS:
+      case ParseNodeKind::PNK_CLASS:
         MOZ_ASSERT(pn->isArity(PN_TERNARY));
         *answer = true;
         return true;
 
       // |with| calls |ToObject| on its expression and so throws if that value
       // is null/undefined.
-      case PNK_WITH:
+      case ParseNodeKind::PNK_WITH:
         MOZ_ASSERT(pn->isArity(PN_BINARY));
         *answer = true;
         return true;
 
-      case PNK_RETURN:
+      case ParseNodeKind::PNK_RETURN:
         MOZ_ASSERT(pn->isArity(PN_BINARY));
         *answer = true;
         return true;
 
-      case PNK_NAME:
+      case ParseNodeKind::PNK_NAME:
         MOZ_ASSERT(pn->isArity(PN_NAME));
         *answer = true;
         return true;
 
       // Shorthands could trigger getters: the |x| in the object literal in
       // |with ({ get x() { throw 42; } }) ({ x });|, for example, triggers
       // one.  (Of course, it isn't necessary to use |with| for a shorthand to
       // trigger a getter.)
-      case PNK_SHORTHAND:
+      case ParseNodeKind::PNK_SHORTHAND:
         MOZ_ASSERT(pn->isArity(PN_BINARY));
         *answer = true;
         return true;
 
-      case PNK_FUNCTION:
+      case ParseNodeKind::PNK_FUNCTION:
         MOZ_ASSERT(pn->isArity(PN_CODE));
         /*
          * A named function, contrary to ES3, is no longer effectful, because
          * we bind its name lexically (using JSOP_CALLEE) instead of creating
          * an Object instance and binding a readonly, permanent property in it
          * (the object and binding can be detected and hijacked or captured).
          * This is a bug fix to ES3; it is fixed in ES3.1 drafts.
          */
         *answer = false;
         return true;
 
-      case PNK_MODULE:
+      case ParseNodeKind::PNK_MODULE:
         *answer = false;
         return true;
 
-      case PNK_TRY:
+      case ParseNodeKind::PNK_TRY:
         MOZ_ASSERT(pn->isArity(PN_TERNARY));
         if (!checkSideEffects(pn->pn_kid1, answer))
             return false;
         if (*answer)
             return true;
         if (ParseNode* catchScope = pn->pn_kid2) {
-            MOZ_ASSERT(catchScope->isKind(PNK_LEXICALSCOPE));
+            MOZ_ASSERT(catchScope->isKind(ParseNodeKind::PNK_LEXICALSCOPE));
             if (!checkSideEffects(catchScope, answer))
                 return false;
             if (*answer)
                 return true;
         }
         if (ParseNode* finallyBlock = pn->pn_kid3) {
             if (!checkSideEffects(finallyBlock, answer))
                 return false;
         }
         return true;
 
-      case PNK_CATCH:
+      case ParseNodeKind::PNK_CATCH:
         MOZ_ASSERT(pn->isArity(PN_BINARY));
         if (ParseNode* name = pn->pn_left) {
             if (!checkSideEffects(name, answer))
                 return false;
             if (*answer)
                 return true;
         }
         return checkSideEffects(pn->pn_right, answer);
 
-      case PNK_SWITCH:
+      case ParseNodeKind::PNK_SWITCH:
         MOZ_ASSERT(pn->isArity(PN_BINARY));
         if (!checkSideEffects(pn->pn_left, answer))
             return false;
         return *answer || checkSideEffects(pn->pn_right, answer);
 
-      case PNK_LABEL:
+      case ParseNodeKind::PNK_LABEL:
         MOZ_ASSERT(pn->isArity(PN_NAME));
         return checkSideEffects(pn->expr(), answer);
 
-      case PNK_LEXICALSCOPE:
+      case ParseNodeKind::PNK_LEXICALSCOPE:
         MOZ_ASSERT(pn->isArity(PN_SCOPE));
         return checkSideEffects(pn->scopeBody(), answer);
 
       // We could methodically check every interpolated expression, but it's
       // probably not worth the trouble.  Treat template strings as effect-free
       // only if they don't contain any substitutions.
-      case PNK_TEMPLATE_STRING_LIST:
+      case ParseNodeKind::PNK_TEMPLATE_STRING_LIST:
         MOZ_ASSERT(pn->isArity(PN_LIST));
         MOZ_ASSERT(pn->pn_count > 0);
         MOZ_ASSERT((pn->pn_count % 2) == 1,
                    "template strings must alternate template and substitution "
                    "parts");
         *answer = pn->pn_count > 1;
         return true;
 
       // This should be unreachable but is left as-is for now.
-      case PNK_PARAMSBODY:
+      case ParseNodeKind::PNK_PARAMSBODY:
         *answer = true;
         return true;
 
-      case PNK_FORIN:           // by PNK_FOR
-      case PNK_FOROF:           // by PNK_FOR
-      case PNK_FORHEAD:         // by PNK_FOR
-      case PNK_CLASSMETHOD:     // by PNK_CLASS
-      case PNK_CLASSNAMES:      // by PNK_CLASS
-      case PNK_CLASSMETHODLIST: // by PNK_CLASS
-      case PNK_IMPORT_SPEC_LIST: // by PNK_IMPORT
-      case PNK_IMPORT_SPEC:      // by PNK_IMPORT
-      case PNK_EXPORT_BATCH_SPEC:// by PNK_EXPORT
-      case PNK_EXPORT_SPEC_LIST: // by PNK_EXPORT
-      case PNK_EXPORT_SPEC:      // by PNK_EXPORT
-      case PNK_CALLSITEOBJ:      // by PNK_TAGGED_TEMPLATE
-      case PNK_POSHOLDER:        // by PNK_NEWTARGET
-      case PNK_SUPERBASE:        // by PNK_ELEM and others
+      case ParseNodeKind::PNK_FORIN:           // by ParseNodeKind::PNK_FOR
+      case ParseNodeKind::PNK_FOROF:           // by ParseNodeKind::PNK_FOR
+      case ParseNodeKind::PNK_FORHEAD:         // by ParseNodeKind::PNK_FOR
+      case ParseNodeKind::PNK_CLASSMETHOD:     // by ParseNodeKind::PNK_CLASS
+      case ParseNodeKind::PNK_CLASSNAMES:      // by ParseNodeKind::PNK_CLASS
+      case ParseNodeKind::PNK_CLASSMETHODLIST: // by ParseNodeKind::PNK_CLASS
+      case ParseNodeKind::PNK_IMPORT_SPEC_LIST: // by ParseNodeKind::PNK_IMPORT
+      case ParseNodeKind::PNK_IMPORT_SPEC:      // by ParseNodeKind::PNK_IMPORT
+      case ParseNodeKind::PNK_EXPORT_BATCH_SPEC:// by ParseNodeKind::PNK_EXPORT
+      case ParseNodeKind::PNK_EXPORT_SPEC_LIST: // by ParseNodeKind::PNK_EXPORT
+      case ParseNodeKind::PNK_EXPORT_SPEC:      // by ParseNodeKind::PNK_EXPORT
+      case ParseNodeKind::PNK_CALLSITEOBJ:      // by ParseNodeKind::PNK_TAGGED_TEMPLATE
+      case ParseNodeKind::PNK_POSHOLDER:        // by ParseNodeKind::PNK_NEWTARGET
+      case ParseNodeKind::PNK_SUPERBASE:        // by ParseNodeKind::PNK_ELEM and others
         MOZ_CRASH("handled by parent nodes");
 
-      case PNK_LIMIT: // invalid sentinel value
+      case ParseNodeKind::PNK_LIMIT: // invalid sentinel value
         MOZ_CRASH("invalid node kind");
     }
 
     MOZ_CRASH("invalid, unenumerated ParseNodeKind value encountered in "
               "BytecodeEmitter::checkSideEffects");
 }
 
 bool
@@ -3930,35 +3934,35 @@ BytecodeEmitter::emitTDZCheckIfNeeded(JS
     }
 
     return innermostTDZCheckCache->noteTDZCheck(this, name, DontCheckTDZ);
 }
 
 bool
 BytecodeEmitter::emitPropLHS(ParseNode* pn)
 {
-    MOZ_ASSERT(pn->isKind(PNK_DOT));
+    MOZ_ASSERT(pn->isKind(ParseNodeKind::PNK_DOT));
     MOZ_ASSERT(!pn->as<PropertyAccess>().isSuper());
 
     ParseNode* pn2 = pn->pn_expr;
 
     /*
      * 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
      * bottom up (reversing again as we go), to avoid excessive recursion.
      */
-    if (pn2->isKind(PNK_DOT) && !pn2->as<PropertyAccess>().isSuper()) {
+    if (pn2->isKind(ParseNodeKind::PNK_DOT) && !pn2->as<PropertyAccess>().isSuper()) {
         ParseNode* pndot = pn2;
         ParseNode* pnup = nullptr;
         ParseNode* pndown;
         for (;;) {
             /* Reverse pndot->pn_expr to point up, not down. */
             pndown = pndot->pn_expr;
             pndot->pn_expr = pnup;
-            if (!pndown->isKind(PNK_DOT) || pndown->as<PropertyAccess>().isSuper())
+            if (!pndown->isKind(ParseNodeKind::PNK_DOT) || pndown->as<PropertyAccess>().isSuper())
                 break;
             pnup = pndot;
             pndot = pndown;
         }
 
         /* pndown is a primary expression, not a dotted property reference. */
         if (!emitTree(pndown))
             return false;
@@ -4026,17 +4030,17 @@ BytecodeEmitter::emitSuperPropOp(ParseNo
         return false;
 
     return true;
 }
 
 bool
 BytecodeEmitter::emitPropIncDec(ParseNode* pn)
 {
-    MOZ_ASSERT(pn->pn_kid->isKind(PNK_DOT));
+    MOZ_ASSERT(pn->pn_kid->isKind(ParseNodeKind::PNK_DOT));
 
     bool post;
     bool isSuper = pn->pn_kid->as<PropertyAccess>().isSuper();
     JSOp binop = GetIncDecInfo(pn->getKind(), &post);
 
     if (isSuper) {
         ParseNode* base = &pn->pn_kid->as<PropertyAccess>().expression();
         if (!emitSuperPropLHS(base))                // THIS OBJ
@@ -4104,17 +4108,17 @@ BytecodeEmitter::emitGetNameAtLocationFo
     }
 
     return true;
 }
 
 bool
 BytecodeEmitter::emitNameIncDec(ParseNode* pn)
 {
-    MOZ_ASSERT(pn->pn_kid->isKind(PNK_NAME));
+    MOZ_ASSERT(pn->pn_kid->isKind(ParseNodeKind::PNK_NAME));
 
     bool post;
     JSOp binop = GetIncDecInfo(pn->getKind(), &post);
 
     auto emitRhs = [pn, post, binop](BytecodeEmitter* bce, const NameLocation& loc,
                                      bool emittedBindOp)
     {
         JSAtom* name = pn->pn_kid->name();
@@ -4175,17 +4179,17 @@ BytecodeEmitter::emitElemOperands(ParseN
             return false;
     }
     return true;
 }
 
 bool
 BytecodeEmitter::emitSuperElemOperands(ParseNode* pn, EmitElemOption opts)
 {
-    MOZ_ASSERT(pn->isKind(PNK_ELEM) && pn->as<PropertyByValue>().isSuper());
+    MOZ_ASSERT(pn->isKind(ParseNodeKind::PNK_ELEM) && pn->as<PropertyByValue>().isSuper());
 
     // The ordering here is somewhat screwy. We need to evaluate the propval
     // first, by spec. Do a little dance to not emit more than one JSOP_THIS.
     // Since JSOP_THIS might throw in derived class constructors, we cannot
     // just push it earlier as the receiver. We have to swap it down instead.
 
     if (!emitTree(pn->pn_right))
         return false;
@@ -4258,17 +4262,17 @@ BytecodeEmitter::emitSuperElemOp(ParseNo
         return false;
 
     return true;
 }
 
 bool
 BytecodeEmitter::emitElemIncDec(ParseNode* pn)
 {
-    MOZ_ASSERT(pn->pn_kid->isKind(PNK_ELEM));
+    MOZ_ASSERT(pn->pn_kid->isKind(ParseNodeKind::PNK_ELEM));
 
     bool isSuper = pn->pn_kid->as<PropertyByValue>().isSuper();
 
     // We need to convert the key to an object id first, so that we do not do
     // it inside both the GETELEM and the SETELEM. This is done by
     // emit(Super)ElemOperands.
     if (isSuper) {
         if (!emitSuperElemOperands(pn->pn_kid, EmitElemOption::IncDec))
@@ -4332,22 +4336,22 @@ BytecodeEmitter::emitElemIncDec(ParseNod
         return false;
 
     return true;
 }
 
 bool
 BytecodeEmitter::emitCallIncDec(ParseNode* incDec)
 {
-    MOZ_ASSERT(incDec->isKind(PNK_PREINCREMENT) ||
-               incDec->isKind(PNK_POSTINCREMENT) ||
-               incDec->isKind(PNK_PREDECREMENT) ||
-               incDec->isKind(PNK_POSTDECREMENT));
-
-    MOZ_ASSERT(incDec->pn_kid->isKind(PNK_CALL));
+    MOZ_ASSERT(incDec->isKind(ParseNodeKind::PNK_PREINCREMENT) ||
+               incDec->isKind(ParseNodeKind::PNK_POSTINCREMENT) ||
+               incDec->isKind(ParseNodeKind::PNK_PREDECREMENT) ||
+               incDec->isKind(ParseNodeKind::PNK_POSTDECREMENT));
+
+    MOZ_ASSERT(incDec->pn_kid->isKind(ParseNodeKind::PNK_CALL));
 
     ParseNode* call = incDec->pn_kid;
     if (!emitTree(call))                                // CALLRESULT
         return false;
     if (!emit1(JSOP_POS))                               // N
         return false;
 
     // The increment/decrement has no side effects, so proceed to throw for
@@ -4395,27 +4399,28 @@ BytecodeEmitter::emitNumberOp(double dva
  * Using MOZ_NEVER_INLINE in here is a workaround for llvm.org/pr14047.
  * LLVM is deciding to inline this function which uses a lot of stack space
  * into emitTree which is recursive and uses relatively little stack space.
  */
 MOZ_NEVER_INLINE bool
 BytecodeEmitter::emitSwitch(ParseNode* pn)
 {
     ParseNode* cases = pn->pn_right;
-    MOZ_ASSERT(cases->isKind(PNK_LEXICALSCOPE) || cases->isKind(PNK_STATEMENTLIST));
+    MOZ_ASSERT(cases->isKind(ParseNodeKind::PNK_LEXICALSCOPE) ||
+               cases->isKind(ParseNodeKind::PNK_STATEMENTLIST));
 
     // Emit code for the discriminant.
     if (!emitTree(pn->pn_left))
         return false;
 
     // Enter the scope before pushing the switch BreakableControl since all
     // breaks are under this scope.
     Maybe<TDZCheckCache> tdzCache;
     Maybe<EmitterScope> emitterScope;
-    if (cases->isKind(PNK_LEXICALSCOPE)) {
+    if (cases->isKind(ParseNodeKind::PNK_LEXICALSCOPE)) {
         if (!cases->isEmptyScope()) {
             tdzCache.emplace(this);
             emitterScope.emplace(this);
             if (!emitterScope->enterLexical(this, ScopeKind::Lexical, cases->scopeBindings()))
                 return false;
         }
 
         // Advance |cases| to refer to the switch case list.
@@ -4475,17 +4480,17 @@ BytecodeEmitter::emitSwitch(ParseNode* p
 
             if (switchOp == JSOP_CONDSWITCH)
                 continue;
 
             MOZ_ASSERT(switchOp == JSOP_TABLESWITCH);
 
             ParseNode* caseValue = caseNode->caseExpression();
 
-            if (caseValue->getKind() != PNK_NUMBER) {
+            if (caseValue->getKind() != ParseNodeKind::PNK_NUMBER) {
                 switchOp = JSOP_CONDSWITCH;
                 continue;
             }
 
             int32_t i;
             if (!NumberIsInt32(caseValue->pn_dval, &i)) {
                 switchOp = JSOP_CONDSWITCH;
                 continue;
@@ -4637,17 +4642,17 @@ BytecodeEmitter::emitSwitch(ParseNode* p
         pc += JUMP_OFFSET_LEN;
 
         if (tableLength != 0) {
             if (!table.growBy(tableLength))
                 return false;
 
             for (CaseClause* caseNode = firstCase; caseNode; caseNode = caseNode->next()) {
                 if (ParseNode* caseValue = caseNode->caseExpression()) {
-                    MOZ_ASSERT(caseValue->isKind(PNK_NUMBER));
+                    MOZ_ASSERT(caseValue->isKind(ParseNodeKind::PNK_NUMBER));
 
                     int32_t i = int32_t(caseValue->pn_dval);
                     MOZ_ASSERT(double(i) == caseValue->pn_dval);
 
                     i -= low;
                     MOZ_ASSERT(uint32_t(i) < tableLength);
                     MOZ_ASSERT(!table[i]);
                     table[i] = caseNode;
@@ -4783,21 +4788,21 @@ BytecodeEmitter::emitYieldOp(JSOp op)
         return false;
 
     return emit1(JSOP_DEBUGAFTERYIELD);
 }
 
 bool
 BytecodeEmitter::emitSetThis(ParseNode* pn)
 {
-    // PNK_SETTHIS is used to update |this| after a super() call in a derived
-    // class constructor.
-
-    MOZ_ASSERT(pn->isKind(PNK_SETTHIS));
-    MOZ_ASSERT(pn->pn_left->isKind(PNK_NAME));
+    // ParseNodeKind::PNK_SETTHIS is used to update |this| after a super() call
+    // in a derived class constructor.
+
+    MOZ_ASSERT(pn->isKind(ParseNodeKind::PNK_SETTHIS));
+    MOZ_ASSERT(pn->pn_left->isKind(ParseNodeKind::PNK_NAME));
 
     RootedAtom name(cx, pn->pn_left->name());
     auto emitRhs = [&name, pn](BytecodeEmitter* bce, const NameLocation&, bool) {
         // Emit the new |this| value.
         if (!bce->emitTree(pn->pn_right))
             return false;
         // Get the original |this| and throw if we already initialized
         // it. Do *not* use the NameLocation argument, as that's the special
@@ -4850,17 +4855,17 @@ BytecodeEmitter::emitScript(ParseNode* b
         MOZ_ASSERT(sc->isModuleContext());
         if (!emitterScope.enterModule(this, sc->asModuleContext()))
             return false;
     }
 
     setFunctionBodyEndPos(body->pn_pos);
 
     if (sc->isEvalContext() && !sc->strict() &&
-        body->isKind(PNK_LEXICALSCOPE) && !body->isEmptyScope())
+        body->isKind(ParseNodeKind::PNK_LEXICALSCOPE) && !body->isEmptyScope())
     {
         // Sloppy eval scripts may need to emit DEFFUNs in the prologue. If there is
         // an immediately enclosed lexical scope, we need to enter the lexical
         // scope in the prologue for the DEFFUNs to pick up the right
         // environment chain.
         EmitterScope lexicalEmitterScope(this);
 
         switchToPrologue();
@@ -4969,106 +4974,113 @@ BytecodeEmitter::emitFunctionScript(Pars
 
     return true;
 }
 
 template <typename NameEmitter>
 bool
 BytecodeEmitter::emitDestructuringDeclsWithEmitter(ParseNode* pattern, NameEmitter emitName)
 {
-    if (pattern->isKind(PNK_ARRAY)) {
+    if (pattern->isKind(ParseNodeKind::PNK_ARRAY)) {
         for (ParseNode* element = pattern->pn_head; element; element = element->pn_next) {
-            if (element->isKind(PNK_ELISION))
+            if (element->isKind(ParseNodeKind::PNK_ELISION))
                 continue;
             ParseNode* target = element;
-            if (element->isKind(PNK_SPREAD)) {
+            if (element->isKind(ParseNodeKind::PNK_SPREAD)) {
                 target = element->pn_kid;
             }
-            if (target->isKind(PNK_ASSIGN))
+            if (target->isKind(ParseNodeKind::PNK_ASSIGN))
                 target = target->pn_left;
-            if (target->isKind(PNK_NAME)) {
+            if (target->isKind(ParseNodeKind::PNK_NAME)) {
                 if (!emitName(this, target))
                     return false;
             } else {
                 if (!emitDestructuringDeclsWithEmitter(target, emitName))
                     return false;
             }
         }
         return true;
     }
 
-    MOZ_ASSERT(pattern->isKind(PNK_OBJECT));
+    MOZ_ASSERT(pattern->isKind(ParseNodeKind::PNK_OBJECT));
     for (ParseNode* member = pattern->pn_head; member; member = member->pn_next) {
-        MOZ_ASSERT(member->isKind(PNK_MUTATEPROTO) ||
-                   member->isKind(PNK_COLON) ||
-                   member->isKind(PNK_SHORTHAND));
-
-        ParseNode* target = member->isKind(PNK_MUTATEPROTO) ? member->pn_kid : member->pn_right;
-
-        if (target->isKind(PNK_ASSIGN))
+        MOZ_ASSERT(member->isKind(ParseNodeKind::PNK_MUTATEPROTO) ||
+                   member->isKind(ParseNodeKind::PNK_COLON) ||
+                   member->isKind(ParseNodeKind::PNK_SHORTHAND));
+
+        ParseNode* target = member->isKind(ParseNodeKind::PNK_MUTATEPROTO)
+                            ? member->pn_kid
+                            : member->pn_right;
+
+        if (target->isKind(ParseNodeKind::PNK_ASSIGN))
             target = target->pn_left;
-        if (target->isKind(PNK_NAME)) {
+        if (target->isKind(ParseNodeKind::PNK_NAME)) {
             if (!emitName(this, target))
                 return false;
         } else {
             if (!emitDestructuringDeclsWithEmitter(target, emitName))
                 return false;
         }
     }
     return true;
 }
 
 bool
 BytecodeEmitter::emitDestructuringLHSRef(ParseNode* target, size_t* emitted)
 {
     *emitted = 0;
 
-    if (target->isKind(PNK_SPREAD))
+    if (target->isKind(ParseNodeKind::PNK_SPREAD))
         target = target->pn_kid;
-    else if (target->isKind(PNK_ASSIGN))
+    else if (target->isKind(ParseNodeKind::PNK_ASSIGN))
         target = target->pn_left;
 
-    // No need to recur into PNK_ARRAY and PNK_OBJECT subpatterns here, since
-    // emitSetOrInitializeDestructuring does the recursion when setting or
-    // initializing value.  Getting reference doesn't recur.
-    if (target->isKind(PNK_NAME) || target->isKind(PNK_ARRAY) || target->isKind(PNK_OBJECT))
+    // No need to recur into ParseNodeKind::PNK_ARRAY and
+    // ParseNodeKind::PNK_OBJECT subpatterns here, since
+    // emitSetOrInitializeDestructuring does the recursion when
+    // setting or initializing value.  Getting reference doesn't recur.
+    if (target->isKind(ParseNodeKind::PNK_NAME) ||
+        target->isKind(ParseNodeKind::PNK_ARRAY) ||
+        target->isKind(ParseNodeKind::PNK_OBJECT))
+    {
         return true;
+    }
 
 #ifdef DEBUG
     int depth = stackDepth;
 #endif
 
     switch (target->getKind()) {
-      case PNK_DOT: {
+      case ParseNodeKind::PNK_DOT: {
         if (target->as<PropertyAccess>().isSuper()) {
             if (!emitSuperPropLHS(&target->as<PropertyAccess>().expression()))
                 return false;
             *emitted = 2;
         } else {
             if (!emitTree(target->pn_expr))
                 return false;
             *emitted = 1;
         }
         break;
       }
 
-      case PNK_ELEM: {
+      case ParseNodeKind::PNK_ELEM: {
         if (target->as<PropertyByValue>().isSuper()) {
             if (!emitSuperElemOperands(target, EmitElemOption::Ref))
                 return false;
             *emitted = 3;
         } else {
             if (!emitElemOperands(target, EmitElemOption::Ref))
                 return false;
             *emitted = 2;
         }
         break;
       }
 
-      case PNK_CALL:
+      case ParseNodeKind::PNK_CALL:
         MOZ_ASSERT_UNREACHABLE("Parser::reportIfNotValidSimpleAssignmentTarget "
                                "rejects function calls as assignment "
                                "targets in destructuring assignments");
         break;
 
       default:
         MOZ_CRASH("emitDestructuringLHSRef: bad lhs kind");
     }
@@ -5080,30 +5092,30 @@ BytecodeEmitter::emitDestructuringLHSRef
 
 bool
 BytecodeEmitter::emitSetOrInitializeDestructuring(ParseNode* target, DestructuringFlavor flav)
 {
     // Now emit the lvalue opcode sequence. If the lvalue is a nested
     // destructuring initialiser-form, call ourselves to handle it, then pop
     // the matched value. Otherwise emit an lvalue bytecode sequence followed
     // by an assignment op.
-    if (target->isKind(PNK_SPREAD))
+    if (target->isKind(ParseNodeKind::PNK_SPREAD))
         target = target->pn_kid;
-    else if (target->isKind(PNK_ASSIGN))
+    else if (target->isKind(ParseNodeKind::PNK_ASSIGN))
         target = target->pn_left;
-    if (target->isKind(PNK_ARRAY) || target->isKind(PNK_OBJECT)) {
+    if (target->isKind(ParseNodeKind::PNK_ARRAY) || target->isKind(ParseNodeKind::PNK_OBJECT)) {
         if (!emitDestructuringOps(target, flav))
             return false;
         // 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 PNK_NAME: {
+          case ParseNodeKind::PNK_NAME: {
             auto emitSwapScopeAndRhs = [](BytecodeEmitter* bce, const NameLocation&,
                                           bool emittedBindOp)
             {
                 if (emittedBindOp) {
                     // This is like ordinary assignment, but with one
                     // difference.
                     //
                     // In `a = b`, we first determine a binding for `a` (using
@@ -5149,45 +5161,45 @@ BytecodeEmitter::emitSetOrInitializeDest
                 if (!emitSetName(name, emitSwapScopeAndRhs))
                     return false;
                 break;
             }
 
             break;
           }
 
-          case PNK_DOT: {
+          case ParseNodeKind::PNK_DOT: {
             // The reference is already pushed by emitDestructuringLHSRef.
             JSOp setOp;
             if (target->as<PropertyAccess>().isSuper())
                 setOp = sc->strict() ? JSOP_STRICTSETPROP_SUPER : JSOP_SETPROP_SUPER;
             else
                 setOp = sc->strict() ? JSOP_STRICTSETPROP : JSOP_SETPROP;
             if (!emitAtomOp(target, setOp))
                 return false;
             break;
           }
 
-          case PNK_ELEM: {
+          case ParseNodeKind::PNK_ELEM: {
             // The reference is already pushed by emitDestructuringLHSRef.
             if (target->as<PropertyByValue>().isSuper()) {
                 JSOp setOp = sc->strict() ? JSOP_STRICTSETELEM_SUPER : JSOP_SETELEM_SUPER;
                 // emitDestructuringLHSRef already did emitSuperElemOperands
                 // part of emitSuperElemOp.  Perform remaining part here.
                 if (!emitElemOpBase(setOp))
                     return false;
             } else {
                 JSOp setOp = sc->strict() ? JSOP_STRICTSETELEM : JSOP_SETELEM;
                 if (!emitElemOpBase(setOp))
                     return false;
             }
             break;
           }
 
-          case PNK_CALL:
+          case ParseNodeKind::PNK_CALL:
             MOZ_ASSERT_UNREACHABLE("Parser::reportIfNotValidSimpleAssignmentTarget "
                                    "rejects function calls as assignment "
                                    "targets in destructuring assignments");
             break;
 
           default:
             MOZ_CRASH("emitSetOrInitializeDestructuring: bad lhs kind");
         }
@@ -5448,17 +5460,17 @@ BytecodeEmitter::emitDefault(ParseNode* 
         return false;
     return true;
 }
 
 bool
 BytecodeEmitter::setOrEmitSetFunName(ParseNode* maybeFun, HandleAtom name,
                                      FunctionPrefixKind prefixKind)
 {
-    if (maybeFun->isKind(PNK_FUNCTION)) {
+    if (maybeFun->isKind(ParseNodeKind::PNK_FUNCTION)) {
         // Function doesn't have 'name' property at this point.
         // Set function's name at compile time.
         JSFunction* fun = maybeFun->pn_funbox->function();
 
         // Single node can be emitted multiple times if it appears in
         // array destructuring default.  If function already has a name,
         // just return.
         if (fun->hasCompileTimeName()) {
@@ -5488,17 +5500,17 @@ BytecodeEmitter::setOrEmitSetFunName(Par
 }
 
 bool
 BytecodeEmitter::emitInitializer(ParseNode* initializer, ParseNode* pattern)
 {
     if (!emitTree(initializer))
         return false;
 
-    if (!pattern->isInParens() && pattern->isKind(PNK_NAME) &&
+    if (!pattern->isInParens() && pattern->isKind(ParseNodeKind::PNK_NAME) &&
         initializer->isDirectRHSAnonFunction())
     {
         RootedAtom name(cx, pattern->name());
         if (!setOrEmitSetFunName(initializer, name, FunctionPrefixKind::None))
             return false;
     }
 
     return true;
@@ -5509,17 +5521,17 @@ BytecodeEmitter::emitInitializerInBranch
 {
     TDZCheckCache tdzCache(this);
     return emitInitializer(initializer, pattern);
 }
 
 bool
 BytecodeEmitter::emitDestructuringOpsArray(ParseNode* pattern, DestructuringFlavor flav)
 {
-    MOZ_ASSERT(pattern->isKind(PNK_ARRAY));
+    MOZ_ASSERT(pattern->isKind(ParseNodeKind::PNK_ARRAY));
     MOZ_ASSERT(pattern->isArity(PN_LIST));
     MOZ_ASSERT(this->stackDepth != 0);
 
     // Here's pseudo code for |let [a, b, , c=y, ...d] = x;|
     //
     // Lines that are annotated "covered by trynote" mean that upon throwing
     // an exception, IteratorClose is called on iter only if done is false.
     //
@@ -5627,20 +5639,20 @@ BytecodeEmitter::emitDestructuringOpsArr
     for (ParseNode* member = pattern->pn_head; member; member = member->pn_next) {
         bool isFirst = member == pattern->pn_head;
         DebugOnly<bool> hasNext = !!member->pn_next;
 
         size_t emitted = 0;
 
         // Spec requires LHS reference to be evaluated first.
         ParseNode* lhsPattern = member;
-        if (lhsPattern->isKind(PNK_ASSIGN))
+        if (lhsPattern->isKind(ParseNodeKind::PNK_ASSIGN))
             lhsPattern = lhsPattern->pn_left;
 
-        bool isElision = lhsPattern->isKind(PNK_ELISION);
+        bool isElision = lhsPattern->isKind(ParseNodeKind::PNK_ELISION);
         if (!isElision) {
             auto emitLHSRef = [lhsPattern, &emitted](BytecodeEmitter* bce) {
                 return bce->emitDestructuringLHSRef(lhsPattern, &emitted); // ... OBJ ITER DONE *LREF
             };
             if (!wrapWithDestructuringIteratorCloseTryNote(tryNoteDepth, emitLHSRef))
                 return false;
         }
 
@@ -5654,17 +5666,17 @@ BytecodeEmitter::emitDestructuringOpsArr
             // If this element is the first, DONE is always FALSE, so pop it.
             //
             // Non-first elements should emit if-else depending on the
             // member pattern, below.
             if (!emit1(JSOP_POP))                                 // ... OBJ ITER *LREF
                 return false;
         }
 
-        if (member->isKind(PNK_SPREAD)) {
+        if (member->isKind(ParseNodeKind::PNK_SPREAD)) {
             IfThenElseEmitter ifThenElse(this);
             if (!isFirst) {
                 // If spread is not the first element of the pattern,
                 // iterator can already be completed.
                                                                   // ... OBJ ITER *LREF DONE
                 if (!ifThenElse.emitIfElse())                     // ... OBJ ITER *LREF
                     return false;
 
@@ -5705,20 +5717,20 @@ BytecodeEmitter::emitDestructuringOpsArr
             if (!wrapWithDestructuringIteratorCloseTryNote(tryNoteDepth, emitAssignment))
                 return false;
 
             MOZ_ASSERT(!hasNext);
             break;
         }
 
         ParseNode* pndefault = nullptr;
-        if (member->isKind(PNK_ASSIGN))
+        if (member->isKind(ParseNodeKind::PNK_ASSIGN))
             pndefault = member->pn_right;
 
-        MOZ_ASSERT(!member->isKind(PNK_SPREAD));
+        MOZ_ASSERT(!member->isKind(ParseNodeKind::PNK_SPREAD));
 
         IfThenElseEmitter ifAlreadyDone(this);
         if (!isFirst) {
                                                                   // ... OBJ ITER *LREF DONE
             if (!ifAlreadyDone.emitIfElse())                      // ... OBJ ITER *LREF
                 return false;
 
             if (!emit1(JSOP_UNDEFINED))                           // ... OBJ ITER *LREF UNDEF
@@ -5815,62 +5827,66 @@ BytecodeEmitter::emitDestructuringOpsArr
         return false;
 
     return true;
 }
 
 bool
 BytecodeEmitter::emitComputedPropertyName(ParseNode* computedPropName)
 {
-    MOZ_ASSERT(computedPropName->isKind(PNK_COMPUTED_NAME));
+    MOZ_ASSERT(computedPropName->isKind(ParseNodeKind::PNK_COMPUTED_NAME));
     return emitTree(computedPropName->pn_kid) && emit1(JSOP_TOID);
 }
 
 bool
 BytecodeEmitter::emitDestructuringOpsObject(ParseNode* pattern, DestructuringFlavor flav)
 {
-    MOZ_ASSERT(pattern->isKind(PNK_OBJECT));
+    MOZ_ASSERT(pattern->isKind(ParseNodeKind::PNK_OBJECT));
     MOZ_ASSERT(pattern->isArity(PN_LIST));
 
     MOZ_ASSERT(this->stackDepth > 0);                             // ... RHS
 
     if (!emit1(JSOP_CHECKOBJCOERCIBLE))                           // ... RHS
         return false;
 
     bool needsRestPropertyExcludedSet = pattern->pn_count > 1 &&
-                                        pattern->last()->isKind(PNK_SPREAD);
+                                        pattern->last()->isKind(ParseNodeKind::PNK_SPREAD);
     if (needsRestPropertyExcludedSet) {
         if (!emitDestructuringObjRestExclusionSet(pattern))       // ... RHS SET
             return false;
 
         if (!emit1(JSOP_SWAP))                                    // ... SET RHS
             return false;
     }
 
     for (ParseNode* member = pattern->pn_head; member; member = member->pn_next) {
         ParseNode* subpattern;
-        if (member->isKind(PNK_MUTATEPROTO) || member->isKind(PNK_SPREAD))
+        if (member->isKind(ParseNodeKind::PNK_MUTATEPROTO) ||
+            member->isKind(ParseNodeKind::PNK_SPREAD))
+        {
             subpattern = member->pn_kid;
-        else
+        } else {
             subpattern = member->pn_right;
+        }
 
         ParseNode* lhs = subpattern;
-        MOZ_ASSERT_IF(member->isKind(PNK_SPREAD), !lhs->isKind(PNK_ASSIGN));
-        if (lhs->isKind(PNK_ASSIGN))
+        MOZ_ASSERT_IF(member->isKind(ParseNodeKind::PNK_SPREAD),
+                      !lhs->isKind(ParseNodeKind::PNK_ASSIGN));
+        if (lhs->isKind(ParseNodeKind::PNK_ASSIGN))
             lhs = lhs->pn_left;
 
         size_t emitted;
         if (!emitDestructuringLHSRef(lhs, &emitted))              // ... *SET RHS *LREF
             return false;
 
         // Duplicate the value being destructured to use as a reference base.
         if (!emitDupAt(emitted))                                  // ... *SET RHS *LREF RHS
             return false;
 
-        if (member->isKind(PNK_SPREAD)) {
+        if (member->isKind(ParseNodeKind::PNK_SPREAD)) {
             if (!updateSourceCoordNotes(member->pn_pos.begin))
                 return false;
 
             if (!emitNewInit(JSProto_Object))                     // ... *SET RHS *LREF RHS TARGET
                 return false;
             if (!emit1(JSOP_DUP))                                 // ... *SET RHS *LREF RHS TARGET TARGET
                 return false;
             if (!emit2(JSOP_PICK, 2))                             // ... *SET RHS *LREF TARGET TARGET RHS
@@ -5895,28 +5911,31 @@ BytecodeEmitter::emitDestructuringOpsObj
             break;
         }
 
         // Now push the property name currently being matched, which is the
         // current property name "label" on the left of a colon in the object
         // initialiser.
         bool needsGetElem = true;
 
-        if (member->isKind(PNK_MUTATEPROTO)) {
+        if (member->isKind(ParseNodeKind::PNK_MUTATEPROTO)) {
             if (!emitAtomOp(cx->names().proto, JSOP_GETPROP))     // ... *SET RHS *LREF PROP
                 return false;
             needsGetElem = false;
         } else {
-            MOZ_ASSERT(member->isKind(PNK_COLON) || member->isKind(PNK_SHORTHAND));
+            MOZ_ASSERT(member->isKind(ParseNodeKind::PNK_COLON) ||
+                       member->isKind(ParseNodeKind::PNK_SHORTHAND));
 
             ParseNode* key = member->pn_left;
-            if (key->isKind(PNK_NUMBER)) {
+            if (key->isKind(ParseNodeKind::PNK_NUMBER)) {
                 if (!emitNumberOp(key->pn_dval))                  // ... *SET RHS *LREF RHS KEY
                     return false;
-            } else if (key->isKind(PNK_OBJECT_PROPERTY_NAME) || key->isKind(PNK_STRING)) {
+            } else if (key->isKind(ParseNodeKind::PNK_OBJECT_PROPERTY_NAME) ||
+                       key->isKind(ParseNodeKind::PNK_STRING))
+            {
                 if (!emitAtomOp(key->pn_atom, JSOP_GETPROP))      // ... *SET RHS *LREF PROP
                     return false;
                 needsGetElem = false;
             } else {
                 if (!emitComputedPropertyName(key))               // ... *SET RHS *LREF RHS KEY
                     return false;
 
                 // Add the computed property key to the exclusion set.
@@ -5934,35 +5953,35 @@ BytecodeEmitter::emitDestructuringOpsObj
                 }
             }
         }
 
         // Get the property value if not done already.
         if (needsGetElem && !emitElemOpBase(JSOP_GETELEM))        // ... *SET RHS *LREF PROP
             return false;
 
-        if (subpattern->isKind(PNK_ASSIGN)) {
+        if (subpattern->isKind(ParseNodeKind::PNK_ASSIGN)) {
             if (!emitDefault(subpattern->pn_right, lhs))          // ... *SET RHS *LREF VALUE
                 return false;
         }
 
         // Destructure PROP per this member's lhs.
         if (!emitSetOrInitializeDestructuring(subpattern, flav))  // ... *SET RHS
             return false;
     }
 
     return true;
 }
 
 bool
 BytecodeEmitter::emitDestructuringObjRestExclusionSet(ParseNode* pattern)
 {
-    MOZ_ASSERT(pattern->isKind(PNK_OBJECT));
+    MOZ_ASSERT(pattern->isKind(ParseNodeKind::PNK_OBJECT));
     MOZ_ASSERT(pattern->isArity(PN_LIST));
-    MOZ_ASSERT(pattern->last()->isKind(PNK_SPREAD));
+    MOZ_ASSERT(pattern->last()->isKind(ParseNodeKind::PNK_SPREAD));
 
     ptrdiff_t offset = this->offset();
     if (!emitNewInit(JSProto_Object))
         return false;
 
     // Try to construct the shape of the object as we go, so we can emit a
     // JSOP_NEWOBJECT with the final shape instead.
     // In the case of computed property names and indices, we cannot fix the
@@ -5973,29 +5992,31 @@ BytecodeEmitter::emitDestructuringObjRes
     // bound of how many properties we plan to have.
     gc::AllocKind kind = gc::GetGCObjectKind(pattern->pn_count - 1);
     RootedPlainObject obj(cx, NewBuiltinClassInstance<PlainObject>(cx, kind, TenuredObject));
     if (!obj)
         return false;
 
     RootedAtom pnatom(cx);
     for (ParseNode* member = pattern->pn_head; member; member = member->pn_next) {
-        if (member->isKind(PNK_SPREAD))
+        if (member->isKind(ParseNodeKind::PNK_SPREAD))
             break;
 
         bool isIndex = false;
-        if (member->isKind(PNK_MUTATEPROTO)) {
+        if (member->isKind(ParseNodeKind::PNK_MUTATEPROTO)) {
             pnatom.set(cx->names().proto);
         } else {
             ParseNode* key = member->pn_left;
-            if (key->isKind(PNK_NUMBER)) {
+            if (key->isKind(ParseNodeKind::PNK_NUMBER)) {
                 if (!emitNumberOp(key->pn_dval))
                     return false;
                 isIndex = true;
-            } else if (key->isKind(PNK_OBJECT_PROPERTY_NAME) || key->isKind(PNK_STRING)) {
+            } else if (key->isKind(ParseNodeKind::PNK_OBJECT_PROPERTY_NAME) ||
+                       key->isKind(ParseNodeKind::PNK_STRING))
+            {
                 pnatom.set(key->pn_atom);
             } else {
                 // Otherwise this is a computed property name which needs to
                 // be added dynamically.
                 obj.set(nullptr);
                 continue;
             }
         }
@@ -6035,30 +6056,31 @@ BytecodeEmitter::emitDestructuringObjRes
     }
 
     return true;
 }
 
 bool
 BytecodeEmitter::emitDestructuringOps(ParseNode* pattern, DestructuringFlavor flav)
 {
-    if (pattern->isKind(PNK_ARRAY))
+    if (pattern->isKind(ParseNodeKind::PNK_ARRAY))
         return emitDestructuringOpsArray(pattern, flav);
     return emitDestructuringOpsObject(pattern, flav);
 }
 
 bool
 BytecodeEmitter::emitTemplateString(ParseNode* pn)
 {
     MOZ_ASSERT(pn->isArity(PN_LIST));
 
     bool pushedString = false;
 
     for (ParseNode* pn2 = pn->pn_head; pn2 != NULL; pn2 = pn2->pn_next) {
-        bool isString = (pn2->getKind() == PNK_STRING || pn2->getKind() == PNK_TEMPLATE_STRING);
+        bool isString = (pn2->getKind() == ParseNodeKind::PNK_STRING ||
+                         pn2->getKind() == ParseNodeKind::PNK_TEMPLATE_STRING);
 
         // Skip empty strings. These are very common: a template string like
         // `${a}${b}` has three empty strings and without this optimization
         // we'd emit four JSOP_ADD operations instead of just one.
         if (isString && pn2->pn_atom->empty())
             continue;
 
         if (!isString) {
@@ -6102,21 +6124,22 @@ BytecodeEmitter::emitDeclarationList(Par
     MOZ_ASSERT(declList->isOp(JSOP_NOP));
 
     ParseNode* next;
     for (ParseNode* decl = declList->pn_head; decl; decl = next) {
         if (!updateSourceCoordNotes(decl->pn_pos.begin))
             return false;
         next = decl->pn_next;
 
-        if (decl->isKind(PNK_ASSIGN)) {
+        if (decl->isKind(ParseNodeKind::PNK_ASSIGN)) {
             MOZ_ASSERT(decl->isOp(JSOP_NOP));
 
             ParseNode* pattern = decl->pn_left;
-            MOZ_ASSERT(pattern->isKind(PNK_ARRAY) || pattern->isKind(PNK_OBJECT));
+            MOZ_ASSERT(pattern->isKind(ParseNodeKind::PNK_ARRAY) ||
+                       pattern->isKind(ParseNodeKind::PNK_OBJECT));
 
             if (!emitTree(decl->pn_right))
                 return false;
 
             if (!emitDestructuringOps(pattern, DestructuringDeclaration))
                 return false;
 
             if (!emit1(JSOP_POP))
@@ -6128,27 +6151,27 @@ BytecodeEmitter::emitDeclarationList(Par
     }
     return true;
 }
 
 bool
 BytecodeEmitter::emitSingleDeclaration(ParseNode* declList, ParseNode* decl,
                                        ParseNode* initializer)
 {
-    MOZ_ASSERT(decl->isKind(PNK_NAME));
+    MOZ_ASSERT(decl->isKind(ParseNodeKind::PNK_NAME));
 
     // Nothing to do for initializer-less 'var' declarations, as there's no TDZ.
-    if (!initializer && declList->isKind(PNK_VAR))
+    if (!initializer && declList->isKind(ParseNodeKind::PNK_VAR))
         return true;
 
     auto emitRhs = [initializer, declList, decl](BytecodeEmitter* bce, const NameLocation&, bool) {
         if (!initializer) {
             // Lexical declarations are initialized to undefined without an
             // initializer.
-            MOZ_ASSERT(declList->isKind(PNK_LET),
+            MOZ_ASSERT(declList->isKind(ParseNodeKind::PNK_LET),
                        "var declarations without initializers handled above, "
                        "and const declarations must have initializers");
             Unused << declList; // silence clang -Wunused-lambda-capture in opt builds
             return bce->emit1(JSOP_UNDEFINED);
         }
 
         MOZ_ASSERT(initializer);
         return bce->emitInitializer(initializer, decl);
@@ -6177,41 +6200,41 @@ EmitAssignmentRhs(BytecodeEmitter* bce, 
 
     return true;
 }
 
 static inline JSOp
 CompoundAssignmentParseNodeKindToJSOp(ParseNodeKind pnk)
 {
     switch (pnk) {
-      case PNK_ASSIGN:       return JSOP_NOP;
-      case PNK_ADDASSIGN:    return JSOP_ADD;
-      case PNK_SUBASSIGN:    return JSOP_SUB;
-      case PNK_BITORASSIGN:  return JSOP_BITOR;
-      case PNK_BITXORASSIGN: return JSOP_BITXOR;
-      case PNK_BITANDASSIGN: return JSOP_BITAND;
-      case PNK_LSHASSIGN:    return JSOP_LSH;
-      case PNK_RSHASSIGN:    return JSOP_RSH;
-      case PNK_URSHASSIGN:   return JSOP_URSH;
-      case PNK_MULASSIGN:    return JSOP_MUL;
-      case PNK_DIVASSIGN:    return JSOP_DIV;
-      case PNK_MODASSIGN:    return JSOP_MOD;
-      case PNK_POWASSIGN:    return JSOP_POW;
+      case ParseNodeKind::PNK_ASSIGN:       return JSOP_NOP;
+      case ParseNodeKind::PNK_ADDASSIGN:    return JSOP_ADD;
+      case ParseNodeKind::PNK_SUBASSIGN:    return JSOP_SUB;
+      case ParseNodeKind::PNK_BITORASSIGN:  return JSOP_BITOR;
+      case ParseNodeKind::PNK_BITXORASSIGN: return JSOP_BITXOR;
+      case ParseNodeKind::PNK_BITANDASSIGN: return JSOP_BITAND;
+      case ParseNodeKind::PNK_LSHASSIGN:    return JSOP_LSH;
+      case ParseNodeKind::PNK_RSHASSIGN:    return JSOP_RSH;
+      case ParseNodeKind::PNK_URSHASSIGN:   return JSOP_URSH;
+      case ParseNodeKind::PNK_MULASSIGN:    return JSOP_MUL;
+      case ParseNodeKind::PNK_DIVASSIGN:    return JSOP_DIV;
+      case ParseNodeKind::PNK_MODASSIGN:    return JSOP_MOD;
+      case ParseNodeKind::PNK_POWASSIGN:    return JSOP_POW;
       default: MOZ_CRASH("unexpected compound assignment op");
     }
 }
 
 bool
 BytecodeEmitter::emitAssignment(ParseNode* lhs, ParseNodeKind pnk, ParseNode* rhs)
 {
     JSOp op = CompoundAssignmentParseNodeKindToJSOp(pnk);
 
     // Name assignments are handled separately because choosing ops and when
     // to emit BINDNAME is involved and should avoid duplication.
-    if (lhs->isKind(PNK_NAME)) {
+    if (lhs->isKind(ParseNodeKind::PNK_NAME)) {
         auto emitRhs = [op, lhs, rhs](BytecodeEmitter* bce, const NameLocation& lhsLoc,
                                       bool emittedBindOp)
         {
             // For compound assignments, first get the LHS value, then emit
             // the RHS and the op.
             if (op != JSOP_NOP) {
                 if (!bce->emitGetNameAtLocationForCompoundAssignment(lhs->name(), lhsLoc))
                     return false;
@@ -6240,47 +6263,47 @@ BytecodeEmitter::emitAssignment(ParseNod
         return emitSetName(lhs, emitRhs);
     }
 
     // Deal with non-name assignments.
     uint32_t atomIndex = (uint32_t) -1;
     uint8_t offset = 1;
 
     switch (lhs->getKind()) {
-      case PNK_DOT:
+      case ParseNodeKind::PNK_DOT:
         if (lhs->as<PropertyAccess>().isSuper()) {
             if (!emitSuperPropLHS(&lhs->as<PropertyAccess>().expression()))
                 return false;
             offset += 2;
         } else {
             if (!emitTree(lhs->expr()))
                 return false;
             offset += 1;
         }
         if (!makeAtomIndex(lhs->pn_atom, &atomIndex))
             return false;
         break;
-      case PNK_ELEM: {
+      case ParseNodeKind::PNK_ELEM: {
         MOZ_ASSERT(lhs->isArity(PN_BINARY));
         EmitElemOption opt = op == JSOP_NOP ? EmitElemOption::Get : EmitElemOption::CompoundAssign;
         if (lhs->as<PropertyByValue>().isSuper()) {
             if (!emitSuperElemOperands(lhs, opt))
                 return false;
             offset += 3;
         } else {
             if (!emitElemOperands(lhs, opt))
                 return false;
             offset += 2;
         }
         break;
       }
-      case PNK_ARRAY:
-      case PNK_OBJECT:
-        break;
-      case PNK_CALL:
+      case ParseNodeKind::PNK_ARRAY:
+      case ParseNodeKind::PNK_OBJECT:
+        break;
+      case ParseNodeKind::PNK_CALL:
         if (!emitTree(lhs))
             return false;
 
         // Assignment to function calls is forbidden, but we have to make the
         // call first.  Now we can throw.
         if (!emitUint16Operand(JSOP_THROWMSG, JSMSG_BAD_LEFTSIDE_OF_ASS))
             return false;
 
@@ -6290,33 +6313,33 @@ BytecodeEmitter::emitAssignment(ParseNod
         break;
       default:
         MOZ_ASSERT(0);
     }
 
     if (op != JSOP_NOP) {
         MOZ_ASSERT(rhs);
         switch (lhs->getKind()) {
-          case PNK_DOT: {
+          case ParseNodeKind::PNK_DOT: {
             JSOp getOp;
             if (lhs->as<PropertyAccess>().isSuper()) {
                 if (!emit1(JSOP_DUP2))
                     return false;
                 getOp = JSOP_GETPROP_SUPER;
             } else {
                 if (!emit1(JSOP_DUP))
                     return false;
                 bool isLength = (lhs->pn_atom == cx->names().length);
                 getOp = isLength ? JSOP_LENGTH : JSOP_GETPROP;
             }
             if (!emitIndex32(getOp, atomIndex))
                 return false;
             break;
           }
-          case PNK_ELEM: {
+          case ParseNodeKind::PNK_ELEM: {
             JSOp elemOp;
             if (lhs->as<PropertyByValue>().isSuper()) {
                 if (!emitDupAt(2))
                     return false;
                 if (!emitDupAt(2))
                     return false;
                 if (!emitDupAt(2))
                     return false;
@@ -6325,17 +6348,17 @@ BytecodeEmitter::emitAssignment(ParseNod
                 if (!emit1(JSOP_DUP2))
                     return false;
                 elemOp = JSOP_GETELEM;
             }
             if (!emitElemOpBase(elemOp))
                 return false;
             break;
           }
-          case PNK_CALL:
+          case ParseNodeKind::PNK_CALL:
             // We just emitted a JSOP_THROWMSG and popped the call's return
             // value.  Push a random value to make sure the stack depth is
             // correct.
             if (!emit1(JSOP_NULL))
                 return false;
             break;
           default:;
         }
@@ -6349,37 +6372,37 @@ BytecodeEmitter::emitAssignment(ParseNod
         if (!newSrcNote(SRC_ASSIGNOP))
             return false;
         if (!emit1(op))
             return false;
     }
 
     /* Finally, emit the specialized assignment bytecode. */
     switch (lhs->getKind()) {
-      case PNK_DOT: {
+      case ParseNodeKind::PNK_DOT: {
         JSOp setOp = lhs->as<PropertyAccess>().isSuper() ?
                        (sc->strict() ? JSOP_STRICTSETPROP_SUPER : JSOP_SETPROP_SUPER) :
                        (sc->strict() ? JSOP_STRICTSETPROP : JSOP_SETPROP);
         if (!emitIndexOp(setOp, atomIndex))
             return false;
         break;
       }
-      case PNK_CALL:
+      case ParseNodeKind::PNK_CALL:
         // We threw above, so nothing to do here.
         break;
-      case PNK_ELEM: {
+      case ParseNodeKind::PNK_ELEM: {
         JSOp setOp = lhs->as<PropertyByValue>().isSuper() ?
                        sc->strict() ? JSOP_STRICTSETELEM_SUPER : JSOP_SETELEM_SUPER :
                        sc->strict() ? JSOP_STRICTSETELEM : JSOP_SETELEM;
         if (!emit1(setOp))
             return false;
         break;
       }
-      case PNK_ARRAY:
-      case PNK_OBJECT:
+      case ParseNodeKind::PNK_ARRAY:
+      case ParseNodeKind::PNK_OBJECT:
         if (!emitDestructuringOps(lhs, DestructuringAssignment))
             return false;
         break;
       default:
         MOZ_ASSERT(0);
     }
     return true;
 }
@@ -6387,52 +6410,52 @@ BytecodeEmitter::emitAssignment(ParseNod
 bool
 ParseNode::getConstantValue(JSContext* cx, AllowConstantObjects allowObjects,
                             MutableHandleValue vp, Value* compare, size_t ncompare,
                             NewObjectKind newKind)
 {
     MOZ_ASSERT(newKind == TenuredObject || newKind == SingletonObject);
 
     switch (getKind()) {
-      case PNK_NUMBER:
+      case ParseNodeKind::PNK_NUMBER:
         vp.setNumber(pn_dval);
         return true;
-      case PNK_TEMPLATE_STRING:
-      case PNK_STRING:
+      case ParseNodeKind::PNK_TEMPLATE_STRING:
+      case ParseNodeKind::PNK_STRING:
         vp.setString(pn_atom);
         return true;
-      case PNK_TRUE:
+      case ParseNodeKind::PNK_TRUE:
         vp.setBoolean(true);
         return true;
-      case PNK_FALSE:
+      case ParseNodeKind::PNK_FALSE:
         vp.setBoolean(false);
         return true;
-      case PNK_NULL:
+      case ParseNodeKind::PNK_NULL:
         vp.setNull();
         return true;
-      case PNK_RAW_UNDEFINED:
+      case ParseNodeKind::PNK_RAW_UNDEFINED:
         vp.setUndefined();
         return true;
-      case PNK_CALLSITEOBJ:
-      case PNK_ARRAY: {
+      case ParseNodeKind::PNK_CALLSITEOBJ:
+      case ParseNodeKind::PNK_ARRAY: {
         unsigned count;
         ParseNode* pn;
 
         if (allowObjects == DontAllowObjects) {
             vp.setMagic(JS_GENERIC_MAGIC);
             return true;
         }
 
         ObjectGroup::NewArrayKind arrayKind = ObjectGroup::NewArrayKind::Normal;
         if (allowObjects == ForCopyOnWriteArray) {
             arrayKind = ObjectGroup::NewArrayKind::CopyOnWrite;
             allowObjects = DontAllowObjects;
         }
 
-        if (getKind() == PNK_CALLSITEOBJ) {
+        if (getKind() == ParseNodeKind::PNK_CALLSITEOBJ) {
             count = pn_count - 1;
             pn = pn_head->pn_next;
         } else {
             MOZ_ASSERT(!(pn_xflags & PNX_NONCONST));
             count = pn_count;
             pn = pn_head;
         }
 
@@ -6456,17 +6479,17 @@ ParseNode::getConstantValue(JSContext* c
             return false;
 
         if (!CombineArrayElementTypes(cx, obj, compare, ncompare))
             return false;
 
         vp.setObject(*obj);
         return true;
       }
-      case PNK_OBJECT: {
+      case ParseNodeKind::PNK_OBJECT: {
         MOZ_ASSERT(!(pn_xflags & PNX_NONCONST));
 
         if (allowObjects == DontAllowObjects) {
             vp.setMagic(JS_GENERIC_MAGIC);
             return true;
         }
         MOZ_ASSERT(allowObjects == AllowObjects);
 
@@ -6477,20 +6500,21 @@ ParseNode::getConstantValue(JSContext* c
             if (!pn->pn_right->getConstantValue(cx, allowObjects, &value))
                 return false;
             if (value.isMagic(JS_GENERIC_MAGIC)) {
                 vp.setMagic(JS_GENERIC_MAGIC);
                 return true;
             }
 
             ParseNode* pnid = pn->pn_left;
-            if (pnid->isKind(PNK_NUMBER)) {
+            if (pnid->isKind(ParseNodeKind::PNK_NUMBER)) {
                 idvalue = NumberValue(pnid->pn_dval);
             } else {
-                MOZ_ASSERT(pnid->isKind(PNK_OBJECT_PROPERTY_NAME) || pnid->isKind(PNK_STRING));
+                MOZ_ASSERT(pnid->isKind(ParseNodeKind::PNK_OBJECT_PROPERTY_NAME) ||
+                           pnid->isKind(ParseNodeKind::PNK_STRING));
                 MOZ_ASSERT(pnid->pn_atom != cx->names().proto);
                 idvalue = StringValue(pnid->pn_atom);
             }
 
             RootedId id(cx);
             if (!ValueToId<CanGC>(cx, idvalue, &id))
                 return false;
 
@@ -6513,17 +6537,18 @@ ParseNode::getConstantValue(JSContext* c
         MOZ_CRASH("Unexpected node");
     }
     return false;
 }
 
 bool
 BytecodeEmitter::emitSingletonInitialiser(ParseNode* pn)
 {
-    NewObjectKind newKind = (pn->getKind() == PNK_OBJECT) ? SingletonObject : TenuredObject;
+    NewObjectKind newKind =
+        (pn->getKind() == ParseNodeKind::PNK_OBJECT) ? SingletonObject : TenuredObject;
 
     RootedValue value(cx);
     if (!pn->getConstantValue(cx, ParseNode::AllowObjects, &value, nullptr, 0, newKind))
         return false;
 
     MOZ_ASSERT_IF(newKind == SingletonObject, value.toObject().isSingleton());
 
     ObjectBox* objbox = parser.newObjectBox(&value.toObject());
@@ -6586,25 +6611,25 @@ BytecodeEmitter::emitCatch(ParseNode* pn
 
     ParseNode* pn2 = pn->pn_left;
     if (!pn2) {
         // Catch parameter was omitted; just discard the exception.
         if (!emit1(JSOP_POP))
             return false;
     } else {
         switch (pn2->getKind()) {
-          case PNK_ARRAY:
-          case PNK_OBJECT:
+          case ParseNodeKind::PNK_ARRAY:
+          case ParseNodeKind::PNK_OBJECT:
             if (!emitDestructuringOps(pn2, DestructuringDeclaration))
                 return false;
             if (!emit1(JSOP_POP))
                 return false;
             break;
 
-          case PNK_NAME:
+          case ParseNodeKind::PNK_NAME:
             if (!emitLexicalInitialization(pn2))
                 return false;
             if (!emit1(JSOP_POP))
                 return false;
             break;
 
           default:
             MOZ_ASSERT(0);
@@ -6653,17 +6678,17 @@ BytecodeEmitter::emitTry(ParseNode* pn)
         // [poplexicalenv]              only if any local aliased
         // if there is a finally block:
         //   gosub <finally>
         //   goto <after finally>
         if (!tryCatch.emitCatch())
             return false;
 
         // Emit the lexical scope and catch body.
-        MOZ_ASSERT(catchScope->isKind(PNK_LEXICALSCOPE));
+        MOZ_ASSERT(catchScope->isKind(ParseNodeKind::PNK_LEXICALSCOPE));
         if (!emitTree(catchScope))
             return false;
     }
 
     // Emit the finally handler, if there is one.
     if (finallyNode) {
         if (!tryCatch.emitFinally(Some(finallyNode->pn_pos.begin)))
             return false;
@@ -6700,17 +6725,17 @@ BytecodeEmitter::emitIf(ParseNode* pn)
     /* Emit code for the then part. */
     if (!emitTreeInBranch(pn->pn_kid2))
         return false;
 
     if (elseNode) {
         if (!ifThenElse.emitElse())
             return false;
 
-        if (elseNode->isKind(PNK_IF)) {
+        if (elseNode->isKind(ParseNodeKind::PNK_IF)) {
             pn = elseNode;
             goto if_again;
         }
 
         /* Emit code for the else part. */
         if (!emitTreeInBranch(elseNode))
             return false;
     }
@@ -6725,50 +6750,50 @@ bool
 BytecodeEmitter::emitHoistedFunctionsInList(ParseNode* list)
 {
     MOZ_ASSERT(list->pn_xflags & PNX_FUNCDEFS);
 
     for (ParseNode* pn = list->pn_head; pn; pn = pn->pn_next) {
         ParseNode* maybeFun = pn;
 
         if (!sc->strict()) {
-            while (maybeFun->isKind(PNK_LABEL))
+            while (maybeFun->isKind(ParseNodeKind::PNK_LABEL))
                 maybeFun = maybeFun->as<LabeledStatement>().statement();
         }
 
-        if (maybeFun->isKind(PNK_FUNCTION) && maybeFun->functionIsHoisted()) {
+        if (maybeFun->isKind(ParseNodeKind::PNK_FUNCTION) && maybeFun->functionIsHoisted()) {
             if (!emitTree(maybeFun))
                 return false;
         }
     }
 
     return true;
 }
 
 bool
 BytecodeEmitter::emitLexicalScopeBody(ParseNode* body, EmitLineNumberNote emitLineNote)
 {
-    if (body->isKind(PNK_STATEMENTLIST) && body->pn_xflags & PNX_FUNCDEFS) {
+    if (body->isKind(ParseNodeKind::PNK_STATEMENTLIST) && body->pn_xflags & PNX_FUNCDEFS) {
         // This block contains function statements whose definitions are
         // hoisted to the top of the block. Emit these as a separate pass
         // before the rest of the block.
         if (!emitHoistedFunctionsInList(body))
             return false;
     }
 
     // Line notes were updated by emitLexicalScope.
     return emitTree(body, ValueUsage::WantValue, emitLineNote);
 }
 
 // Using MOZ_NEVER_INLINE in here is a workaround for llvm.org/pr14047. See
 // the comment on emitSwitch.
 MOZ_NEVER_INLINE bool
 BytecodeEmitter::emitLexicalScope(ParseNode* pn)
 {
-    MOZ_ASSERT(pn->isKind(PNK_LEXICALSCOPE));
+    MOZ_ASSERT(pn->isKind(ParseNodeKind::PNK_LEXICALSCOPE));
 
     TDZCheckCache tdzCache(this);
 
     ParseNode* body = pn->scopeBody();
     if (pn->isEmptyScope())
         return emitLexicalScopeBody(body);
 
     // Update line number notes before emitting TDZ poison in
@@ -6781,35 +6806,36 @@ BytecodeEmitter::emitLexicalScope(ParseN
     // L2:   let x = 42;
     // L3: }
     //
     // If line number notes were not updated before the TDZ poison, the TDZ
     // poison bytecode sequence of 'uninitialized; initlexical' will have line
     // number L1, and the Debugger will pause there.
     if (!ParseNodeRequiresSpecialLineNumberNotes(body)) {
         ParseNode* pnForPos = body;
-        if (body->isKind(PNK_STATEMENTLIST) && body->pn_head)
+        if (body->isKind(ParseNodeKind::PNK_STATEMENTLIST) && body->pn_head)
             pnForPos = body->pn_head;
         if (!updateLineNumberNotes(pnForPos->pn_pos.begin))
             return false;
     }
 
     EmitterScope emitterScope(this);
     ScopeKind kind;
-    if (body->isKind(PNK_CATCH))
-        kind = (!body->pn_left || body->pn_left->isKind(PNK_NAME))
+    if (body->isKind(ParseNodeKind::PNK_CATCH)) {
+        kind = (!body->pn_left || body->pn_left->isKind(ParseNodeKind::PNK_NAME))
                ? ScopeKind::SimpleCatch
                : ScopeKind::Catch;
-    else
+    } else {
         kind = ScopeKind::Lexical;
+    }
 
     if (!emitterScope.enterLexical(this, kind, pn->scopeBindings()))
         return false;
 
-    if (body->isKind(PNK_FOR)) {
+    if (body->isKind(ParseNodeKind::PNK_FOR)) {
         // for loops need to emit {FRESHEN,RECREATE}LEXICALENV if there are
         // lexical declarations in the head. Signal this by passing a
         // non-nullptr lexical scope.
         if (!emitFor(body, &emitterScope))
             return false;
     } else {
         if (!emitLexicalScopeBody(body, SUPPRESS_LINENOTE))
             return false;
@@ -7037,44 +7063,45 @@ BytecodeEmitter::emitSpread(bool allowSe
         return false;
 
     return emitPopN(2);                                   // ARR FINAL_INDEX
 }
 
 bool
 BytecodeEmitter::emitInitializeForInOrOfTarget(ParseNode* forHead)
 {
-    MOZ_ASSERT(forHead->isKind(PNK_FORIN) || forHead->isKind(PNK_FOROF));
+    MOZ_ASSERT(forHead->isKind(ParseNodeKind::PNK_FORIN) ||
+               forHead->isKind(ParseNodeKind::PNK_FOROF));
     MOZ_ASSERT(forHead->isArity(PN_TERNARY));
 
     MOZ_ASSERT(this->stackDepth >= 1,
                "must have a per-iteration value for initializing");
 
     ParseNode* target = forHead->pn_kid1;
     MOZ_ASSERT(!forHead->pn_kid2);
 
     // If the for-in/of loop didn't have a variable declaration, per-loop
     // initialization is just assigning the iteration value to a target
     // expression.
     if (!parser.isDeclarationList(target))
-        return emitAssignment(target, PNK_ASSIGN, nullptr); // ... ITERVAL
+        return emitAssignment(target, ParseNodeKind::PNK_ASSIGN, nullptr); // ... ITERVAL
 
     // Otherwise, per-loop initialization is (possibly) declaration
     // initialization.  If the declaration is a lexical declaration, it must be
     // initialized.  If the declaration is a variable declaration, an
     // assignment to that name (which does *not* necessarily assign to the
     // variable!) must be generated.
 
     if (!updateSourceCoordNotes(target->pn_pos.begin))
         return false;
 
     MOZ_ASSERT(target->isForLoopDeclaration());
     target = parser.singleBindingFromDeclaration(target);
 
-    if (target->isKind(PNK_NAME)) {
+    if (target->isKind(ParseNodeKind::PNK_NAME)) {
         auto emitSwapScopeAndRhs = [](BytecodeEmitter* bce, const NameLocation&,
                                       bool emittedBindOp)
         {
             if (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.
@@ -7087,47 +7114,48 @@ BytecodeEmitter::emitInitializeForInOrOf
             MOZ_ASSERT(bce->stackDepth >= 1);
             return true;
         };
 
         // The caller handles removing the iteration value from the stack.
         return emitInitializeName(target, emitSwapScopeAndRhs);
     }
 
-    MOZ_ASSERT(!target->isKind(PNK_ASSIGN),
+    MOZ_ASSERT(!target->isKind(ParseNodeKind::PNK_ASSIGN),
                "for-in/of loop destructuring declarations can't have initializers");
 
-    MOZ_ASSERT(target->isKind(PNK_ARRAY) || target->isKind(PNK_OBJECT));
+    MOZ_ASSERT(target->isKind(ParseNodeKind::PNK_ARRAY) ||
+               target->isKind(ParseNodeKind::PNK_OBJECT));
     return emitDestructuringOps(target, DestructuringDeclaration);
 }
 
 bool
 BytecodeEmitter::emitForOf(ParseNode* forOfLoop, EmitterScope* headLexicalEmitterScope)
 {
-    MOZ_ASSERT(forOfLoop->isKind(PNK_FOR));
+    MOZ_ASSERT(forOfLoop->isKind(ParseNodeKind::PNK_FOR));
     MOZ_ASSERT(forOfLoop->isArity(PN_BINARY));
 
     ParseNode* forOfHead = forOfLoop->pn_left;
-    MOZ_ASSERT(forOfHead->isKind(PNK_FOROF));
+    MOZ_ASSERT(forOfHead->isKind(ParseNodeKind::PNK_FOROF));
     MOZ_ASSERT(forOfHead->isArity(PN_TERNARY));
 
     unsigned iflags = forOfLoop->pn_iflags;
     IteratorKind iterKind = (iflags & JSITER_FORAWAITOF)
                             ? IteratorKind::Async
                             : IteratorKind::Sync;
     MOZ_ASSERT_IF(iterKind == IteratorKind::Async, sc->asFunctionBox());
     MOZ_ASSERT_IF(iterKind == IteratorKind::Async, sc->asFunctionBox()->isAsync());
 
     ParseNode* forHeadExpr = forOfHead->pn_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(PNK_CALL) &&
+        forHeadExpr->isKind(ParseNodeKind::PNK_CALL) &&
         forHeadExpr->pn_head->name() == cx->names().allowContentIter)
     {
         allowSelfHostedIter = true;
     }
 
     // Evaluate the expression being iterated. The forHeadExpr should use a
     // distinct TDZCheckCache to evaluate since (abstractly) it runs in its own
     // LexicalEnvironment.
@@ -7167,17 +7195,18 @@ BytecodeEmitter::emitForOf(ParseNode* fo
     // environment with an dead zoned one to implement TDZ semantics.
     if (headLexicalEmitterScope) {
         // The environment chain only includes an environment for the for-of
         // loop head *if* a scope binding is captured, thereby requiring
         // recreation each iteration. If a lexical scope exists for the head,
         // it must be the innermost one. If that scope has closed-over
         // bindings inducing an environment, recreate the current environment.
         DebugOnly<ParseNode*> forOfTarget = forOfHead->pn_kid1;
-        MOZ_ASSERT(forOfTarget->isKind(PNK_LET) || forOfTarget->isKind(PNK_CONST));
+        MOZ_ASSERT(forOfTarget->isKind(ParseNodeKind::PNK_LET) ||
+                   forOfTarget->isKind(ParseNodeKind::PNK_CONST));
         MOZ_ASSERT(headLexicalEmitterScope == innermostEmitterScope);
         MOZ_ASSERT(headLexicalEmitterScope->scope(this)->kind() == ScopeKind::Lexical);
 
         if (headLexicalEmitterScope->hasEnvironment()) {
             if (!emit1(JSOP_RECREATELEXICALENV))          // ITER UNDEF
                 return false;
         }
 
@@ -7288,32 +7317,32 @@ BytecodeEmitter::emitForOf(ParseNode* fo
         return false;
 
     return emitPopN(2);                                   //
 }
 
 bool
 BytecodeEmitter::emitForIn(ParseNode* forInLoop, EmitterScope* headLexicalEmitterScope)
 {
-    MOZ_ASSERT(forInLoop->isKind(PNK_FOR));
+    MOZ_ASSERT(forInLoop->isKind(ParseNodeKind::PNK_FOR));
     MOZ_ASSERT(forInLoop->isArity(PN_BINARY));
     MOZ_ASSERT(forInLoop->isOp(JSOP_ITER));
 
     ParseNode* forInHead = forInLoop->pn_left;
-    MOZ_ASSERT(forInHead->isKind(PNK_FORIN));
+    MOZ_ASSERT(forInHead->isKind(ParseNodeKind::PNK_FORIN));
     MOZ_ASSERT(forInHead->isArity(PN_TERNARY));
 
     // Annex B: Evaluate the var-initializer expression if present.
     // |for (var i = initializer in expr) { ... }|
     ParseNode* forInTarget = forInHead->pn_kid1;
     if (parser.isDeclarationList(forInTarget)) {
         ParseNode* decl = parser.singleBindingFromDeclaration(forInTarget);
-        if (decl->isKind(PNK_NAME)) {
+        if (decl->isKind(ParseNodeKind::PNK_NAME)) {
             if (ParseNode* initializer = decl->expr()) {
-                MOZ_ASSERT(forInTarget->isKind(PNK_VAR),
+                MOZ_ASSERT(forInTarget->isKind(ParseNodeKind::PNK_VAR),
                            "for-in initializers are only permitted for |var| declarations");
 
                 if (!updateSourceCoordNotes(decl->pn_pos.begin))
                     return false;
 
                 auto emitRhs = [decl, initializer](BytecodeEmitter* bce, const NameLocation&, bool) {
                     return bce->emitInitializer(initializer, decl);
                 };
@@ -7363,17 +7392,18 @@ BytecodeEmitter::emitForIn(ParseNode* fo
     // If the loop had an escaping lexical declaration, replace the current
     // environment with an dead zoned one to implement TDZ semantics.
     if (headLexicalEmitterScope) {
         // The environment chain only includes an environment for the for-in
         // loop head *if* a scope binding is captured, thereby requiring
         // recreation each iteration. If a lexical scope exists for the head,
         // it must be the innermost one. If that scope has closed-over
         // bindings inducing an environment, recreate the current environment.
-        MOZ_ASSERT(forInTarget->isKind(PNK_LET) || forInTarget->isKind(PNK_CONST));
+        MOZ_ASSERT(forInTarget->isKind(ParseNodeKind::PNK_LET) ||
+                   forInTarget->isKind(ParseNodeKind::PNK_CONST));
         MOZ_ASSERT(headLexicalEmitterScope == innermostEmitterScope);
         MOZ_ASSERT(headLexicalEmitterScope->scope(this)->kind() == ScopeKind::Lexical);
 
         if (headLexicalEmitterScope->hasEnvironment()) {
             if (!emit1(JSOP_RECREATELEXICALENV))          // ITER ITERVAL
                 return false;
         }
 
@@ -7446,19 +7476,19 @@ bool
 BytecodeEmitter::emitCStyleFor(ParseNode* pn, EmitterScope* headLexicalEmitterScope)
 {
     LoopControl loopInfo(this, StatementKind::ForLoop);
 
     ParseNode* forHead = pn->pn_left;
     ParseNode* forBody = pn->pn_right;
 
     // If the head of this for-loop declared any lexical variables, the parser
-    // wrapped this PNK_FOR node in a PNK_LEXICALSCOPE representing the
-    // implicit scope of those variables. By the time we get here, we have
-    // already entered that scope. So far, so good.
+    // wrapped this ParseNodeKind::PNK_FOR node in a ParseNodeKind::PNK_LEXICALSCOPE
+    // representing the implicit scope of those variables. By the time we get here,
+    // we have already entered that scope. So far, so good.
     //
     // ### Scope freshening
     //
     // Each iteration of a `for (let V...)` loop creates a fresh loop variable
     // binding for V, even if the loop is a C-style `for(;;)` loop:
     //
     //     var funcs = [];
     //     for (let i = 0; i < 2; i++)
@@ -7492,17 +7522,17 @@ BytecodeEmitter::emitCStyleFor(ParseNode
                 return false;
         }
 
         // ES 13.7.4.8 step 2. The initial freshening.
         //
         // If an initializer let-declaration may be captured during loop iteration,
         // the current scope has an environment.  If so, freshen the current
         // environment to expose distinct bindings for each loop iteration.
-        forLoopRequiresFreshening = init->isKind(PNK_LET) && headLexicalEmitterScope;
+        forLoopRequiresFreshening = init->isKind(ParseNodeKind::PNK_LET) && headLexicalEmitterScope;
         if (forLoopRequiresFreshening) {
             // The environment chain only includes an environment for the for(;;)
             // loop head's let-declaration *if* a scope binding is captured, thus
             // requiring a fresh environment each iteration. If a lexical scope
             // exists for the head, it must be the innermost one. If that scope
             // has closed-over bindings inducing an environment, recreate the
             // current environment.
             MOZ_ASSERT(headLexicalEmitterScope == innermostEmitterScope);
@@ -7626,28 +7656,28 @@ BytecodeEmitter::emitCStyleFor(ParseNode
         return false;
 
     return true;
 }
 
 bool
 BytecodeEmitter::emitFor(ParseNode* pn, EmitterScope* headLexicalEmitterScope)
 {
-    MOZ_ASSERT(pn->isKind(PNK_FOR));
-
-    if (pn->pn_left->isKind(PNK_FORHEAD))
+    MOZ_ASSERT(pn->isKind(ParseNodeKind::PNK_FOR));
+
+    if (pn->pn_left->isKind(ParseNodeKind::PNK_FORHEAD))
         return emitCStyleFor(pn, headLexicalEmitterScope);
 
     if (!updateLineNumberNotes(pn->pn_pos.begin))
         return false;
 
-    if (pn->pn_left->isKind(PNK_FORIN))
+    if (pn->pn_left->isKind(ParseNodeKind::PNK_FORIN))
         return emitForIn(pn, headLexicalEmitterScope);
 
-    MOZ_ASSERT(pn->pn_left->isKind(PNK_FOROF));
+    MOZ_ASSERT(pn->pn_left->isKind(ParseNodeKind::PNK_FOROF));
     return emitForOf(pn, headLexicalEmitterScope);
 }
 
 MOZ_NEVER_INLINE bool
 BytecodeEmitter::emitFunction(ParseNode* pn, bool needsProto)
 {
     FunctionBox* funbox = pn->pn_funbox;
     RootedFunction fun(cx, funbox->function());
@@ -8111,38 +8141,38 @@ BytecodeEmitter::emitContinue(PropertyNa
     }
     return emitGoto(target, &target->continues, SRC_CONTINUE);
 }
 
 bool
 BytecodeEmitter::emitGetFunctionThis(ParseNode* pn)
 {
     MOZ_ASSERT(sc->thisBinding() == ThisBinding::Function);
-    MOZ_ASSERT(pn->isKind(PNK_NAME));
+    MOZ_ASSERT(pn->isKind(ParseNodeKind::PNK_NAME));
     MOZ_ASSERT(pn->name() == cx->names().dotThis);
 
     if (!emitTree(pn))
         return false;
     if (sc->needsThisTDZChecks() && !emit1(JSOP_CHECKTHIS))
         return false;
 
     return true;
 }
 
 bool
 BytecodeEmitter::emitGetThisForSuperBase(ParseNode* pn)
 {
-    MOZ_ASSERT(pn->isKind(PNK_SUPERBASE));
+    MOZ_ASSERT(pn->isKind(ParseNodeKind::PNK_SUPERBASE));
     return emitGetFunctionThis(pn->pn_kid);
 }
 
 bool
 BytecodeEmitter::emitThisLiteral(ParseNode* pn)
 {
-    MOZ_ASSERT(pn->isKind(PNK_THIS));
+    MOZ_ASSERT(pn->isKind(ParseNodeKind::PNK_THIS));
 
     if (ParseNode* thisName = pn->pn_kid)
         return emitGetFunctionThis(thisName);
 
     if (sc->thisBinding() == ThisBinding::Module)
         return emit1(JSOP_UNDEFINED);
 
     MOZ_ASSERT(sc->thisBinding() == ThisBinding::Global);
@@ -8276,17 +8306,17 @@ BytecodeEmitter::emitInitialYield(ParseN
 
     return true;
 }
 
 bool
 BytecodeEmitter::emitYield(ParseNode* pn)
 {
     MOZ_ASSERT(sc->isFunctionBox());
-    MOZ_ASSERT(pn->isKind(PNK_YIELD));
+    MOZ_ASSERT(pn->isKind(ParseNodeKind::PNK_YIELD));
 
     bool needsIteratorResult = sc->asFunctionBox()->needsIteratorResult();
     if (needsIteratorResult) {
         if (!emitPrepareIteratorResult())
             return false;
     }
     if (pn->pn_kid) {
         if (!emitTree(pn->pn_kid))
@@ -8326,17 +8356,17 @@ BytecodeEmitter::emitAwait()
         return false;
     return true;
 }
 
 bool
 BytecodeEmitter::emitAwait(ParseNode* pn)
 {
     MOZ_ASSERT(sc->isFunctionBox());
-    MOZ_ASSERT(pn->isKind(PNK_AWAIT));
+    MOZ_ASSERT(pn->isKind(ParseNodeKind::PNK_AWAIT));
 
     if (!emitTree(pn->pn_kid))
         return false;
     return emitAwait();
 }
 
 bool
 BytecodeEmitter::emitYieldStar(ParseNode* iter)
@@ -8630,17 +8660,17 @@ BytecodeEmitter::emitStatementList(Parse
             return false;
     }
     return true;
 }
 
 bool
 BytecodeEmitter::emitStatement(ParseNode* pn)
 {
-    MOZ_ASSERT(pn->isKind(PNK_SEMI));
+    MOZ_ASSERT(pn->isKind(ParseNodeKind::PNK_SEMI));
 
     ParseNode* pn2 = pn->pn_kid;
     if (!pn2)
         return true;
 
     if (!updateSourceCoordNotes(pn->pn_pos.begin))
         return false;
 
@@ -8676,17 +8706,17 @@ BytecodeEmitter::emitStatement(ParseNode
         {
             useful = true;
         }
     }
 
     if (useful) {
         JSOp op = wantval ? JSOP_SETRVAL : JSOP_POP;
         ValueUsage valueUsage = wantval ? ValueUsage::WantValue : ValueUsage::IgnoreValue;
-        MOZ_ASSERT_IF(pn2->isKind(PNK_ASSIGN), pn2->isOp(JSOP_NOP));
+        MOZ_ASSERT_IF(pn2->isKind(ParseNodeKind::PNK_ASSIGN), pn2->isOp(JSOP_NOP));
         if (!emitTree(pn2, valueUsage))
             return false;
         if (!emit1(op))
             return false;
     } else if (pn->isDirectivePrologueMember()) {
         // Don't complain about directive prologue members; just don't emit
         // their code.
     } else {
@@ -8718,33 +8748,33 @@ BytecodeEmitter::emitStatement(ParseNode
     }
 
     return true;
 }
 
 bool
 BytecodeEmitter::emitDeleteName(ParseNode* node)
 {
-    MOZ_ASSERT(node->isKind(PNK_DELETENAME));
+    MOZ_ASSERT(node->isKind(ParseNodeKind::PNK_DELETENAME));
     MOZ_ASSERT(node->isArity(PN_UNARY));
 
     ParseNode* nameExpr = node->pn_kid;
-    MOZ_ASSERT(nameExpr->isKind(PNK_NAME));
+    MOZ_ASSERT(nameExpr->isKind(ParseNodeKind::PNK_NAME));
 
     return emitAtomOp(nameExpr, JSOP_DELNAME);
 }
 
 bool
 BytecodeEmitter::emitDeleteProperty(ParseNode* node)
 {
-    MOZ_ASSERT(node->isKind(PNK_DELETEPROP));
+    MOZ_ASSERT(node->isKind(ParseNodeKind::PNK_DELETEPROP));
     MOZ_ASSERT(node->isArity(PN_UNARY));
 
     ParseNode* propExpr = node->pn_kid;
-    MOZ_ASSERT(propExpr->isKind(PNK_DOT));
+    MOZ_ASSERT(propExpr->isKind(ParseNodeKind::PNK_DOT));
 
     if (propExpr->as<PropertyAccess>().isSuper()) {
         // Still have to calculate the base, even though we are are going
         // to throw unconditionally, as calculating the base could also
         // throw.
         if (!emit1(JSOP_SUPERBASE))
             return false;
 
@@ -8753,21 +8783,21 @@ BytecodeEmitter::emitDeleteProperty(Pars
 
     JSOp delOp = sc->strict() ? JSOP_STRICTDELPROP : JSOP_DELPROP;
     return emitPropOp(propExpr, delOp);
 }
 
 bool
 BytecodeEmitter::emitDeleteElement(ParseNode* node)
 {
-    MOZ_ASSERT(node->isKind(PNK_DELETEELEM));
+    MOZ_ASSERT(node->isKind(ParseNodeKind::PNK_DELETEELEM));
     MOZ_ASSERT(node->isArity(PN_UNARY));
 
     ParseNode* elemExpr = node->pn_kid;
-    MOZ_ASSERT(elemExpr->isKind(PNK_ELEM));
+    MOZ_ASSERT(elemExpr->isKind(ParseNodeKind::PNK_ELEM));
 
     if (elemExpr->as<PropertyByValue>().isSuper()) {
         // Still have to calculate everything, even though we're gonna throw
         // since it may have side effects
         if (!emitTree(elemExpr->pn_right))
             return false;
 
         if (!emit1(JSOP_SUPERBASE))
@@ -8782,17 +8812,17 @@ BytecodeEmitter::emitDeleteElement(Parse
 
     JSOp delOp = sc->strict() ? JSOP_STRICTDELELEM : JSOP_DELELEM;
     return emitElemOp(elemExpr, delOp);
 }
 
 bool
 BytecodeEmitter::emitDeleteExpression(ParseNode* node)
 {
-    MOZ_ASSERT(node->isKind(PNK_DELETEEXPR));
+    MOZ_ASSERT(node->isKind(ParseNodeKind::PNK_DELETEEXPR));
     MOZ_ASSERT(node->isArity(PN_UNARY));
 
     ParseNode* expression = node->pn_kid;
 
     // If useless, just emit JSOP_TRUE; otherwise convert |delete <expr>| to
     // effectively |<expr>, true|.
     bool useful = false;
     if (!checkSideEffects(expression, &useful))
@@ -8844,20 +8874,22 @@ BytecodeEmitter::emitSelfHostedCallFunct
     JSOp callOp = pn->getOp();
     if (callOp != JSOP_CALL) {
         reportError(pn, JSMSG_NOT_CONSTRUCTOR, errorName);
         return false;
     }
 
     bool constructing = pn2->name() == cx->names().constructContentFunction;
     ParseNode* funNode = pn2->pn_next;
-    if (constructing)
+    if (constructing) {
         callOp = JSOP_NEW;
-    else if (funNode->getKind() == PNK_NAME && funNode->name() == cx->names().std_Function_apply)
+    } else if (funNode->getKind() == ParseNodeKind::PNK_NAME &&
+               funNode->name() == cx->names().std_Function_apply) {
         callOp = JSOP_FUNAPPLY;
+    }
 
     if (!emitTree(funNode))
         return false;
 
 #ifdef DEBUG
     if (emitterMode == BytecodeEmitter::SelfHosting &&
         pn2->name() == cx->names().callFunction)
     {
@@ -8911,17 +8943,17 @@ BytecodeEmitter::emitSelfHostedResumeGen
     if (!emitTree(genNode))
         return false;
 
     ParseNode* valNode = genNode->pn_next;
     if (!emitTree(valNode))
         return false;
 
     ParseNode* kindNode = valNode->pn_next;
-    MOZ_ASSERT(kindNode->isKind(PNK_STRING));
+    MOZ_ASSERT(kindNode->isKind(ParseNodeKind::PNK_STRING));
     uint16_t operand = GeneratorObject::getResumeKind(cx, kindNode->pn_atom);
     MOZ_ASSERT(!kindNode->pn_next);
 
     if (!emitCall(JSOP_RESUME, operand))
         return false;
 
     return true;
 }
@@ -9027,21 +9059,24 @@ BytecodeEmitter::isRestParameter(ParseNo
     if (!sc->isFunctionBox())
         return false;
 
     FunctionBox* funbox = sc->asFunctionBox();
     RootedFunction fun(cx, funbox->function());
     if (!funbox->hasRest())
         return false;
 
-    if (!pn->isKind(PNK_NAME)) {
-        if (emitterMode == BytecodeEmitter::SelfHosting && pn->isKind(PNK_CALL)) {
+    if (!pn->isKind(ParseNodeKind::PNK_NAME)) {
+        if (emitterMode == BytecodeEmitter::SelfHosting && pn->isKind(ParseNodeKind::PNK_CALL)) {
             ParseNode* pn2 = pn->pn_head;
-            if (pn2->getKind() == PNK_NAME && pn2->name() == cx->names().allowContentIter)
+            if (pn2->getKind() == ParseNodeKind::PNK_NAME &&
+                pn2->name() == cx->names().allowContentIter)
+            {
                 return isRestParameter(pn2->pn_next);
+            }
         }
         return false;
     }
 
     JSAtom* name = pn->name();
     Maybe<NameLocation> paramLoc = locationOfNameBoundInFunctionScope(name);
     if (paramLoc && lookupName(name) == *paramLoc) {
         FunctionScope::Data* bindings = funbox->functionScopeBindings();
@@ -9055,47 +9090,47 @@ BytecodeEmitter::isRestParameter(ParseNo
 
     return false;
 }
 
 bool
 BytecodeEmitter::emitCallee(ParseNode* callee, ParseNode* call, bool spread, bool* callop)
 {
     switch (callee->getKind()) {
-      case PNK_NAME:
+      case ParseNodeKind::PNK_NAME:
         if (!emitGetName(callee, *callop))
             return false;
         break;
-      case PNK_DOT:
+      case ParseNodeKind::PNK_DOT:
         MOZ_ASSERT(emitterMode != BytecodeEmitter::SelfHosting);
         if (callee->as<PropertyAccess>().isSuper()) {
             if (!emitSuperPropOp(callee, JSOP_GETPROP_SUPER, /* isCall = */ *callop))
                 return false;
         } else {
             if (!emitPropOp(callee, *callop ? JSOP_CALLPROP : JSOP_GETPROP))
                 return false;
         }
 
         break;
-      case PNK_ELEM:
+      case ParseNodeKind::PNK_ELEM:
         MOZ_ASSERT(emitterMode != BytecodeEmitter::SelfHosting);
         if (callee->as<PropertyByValue>().isSuper()) {
             if (!emitSuperElemOp(callee, JSOP_GETELEM_SUPER, /* isCall = */ *callop))
                 return false;
         } else {
             if (!emitElemOp(callee, *callop ? JSOP_CALLELEM : JSOP_GETELEM))
                 return false;
             if (*callop) {
                 if (!emit1(JSOP_SWAP))
                     return false;
             }
         }
 
         break;
-      case PNK_FUNCTION:
+      case ParseNodeKind::PNK_FUNCTION:
         /*
          * Top level lambdas which are immediately invoked should be
          * treated as only running once. Every time they execute we will
          * create new types and scripts for their contents, to increase
          * the quality of type information within them and enable more
          * backend optimizations. Note that this does not depend on the
          * lambda being invoked at most once (it may be named or be
          * accessed via foo.caller indirection), as multiple executions
@@ -9108,18 +9143,18 @@ BytecodeEmitter::emitCallee(ParseNode* c
                 return false;
             emittingRunOnceLambda = false;
         } else {
             if (!emitTree(callee))
                 return false;
         }
         *callop = false;
         break;
-      case PNK_SUPERBASE:
-        MOZ_ASSERT(call->isKind(PNK_SUPERCALL));
+      case ParseNodeKind::PNK_SUPERBASE:
+        MOZ_ASSERT(call->isKind(ParseNodeKind::PNK_SUPERCALL));
         MOZ_ASSERT(parser.isSuperBase(callee));
         if (!emit1(JSOP_SUPERFUN))
             return false;
         break;
       default:
         if (!emitTree(callee))
             return false;
         *callop = false;             /* trigger JSOP_UNDEFINED after */
@@ -9161,17 +9196,18 @@ BytecodeEmitter::emitPipeline(ParseNode*
     } while ((callee = callee->pn_next));
 
     return true;
 }
 
 bool
 BytecodeEmitter::emitCallOrNew(ParseNode* pn, ValueUsage valueUsage /* = ValueUsage::WantValue */)
 {
-    bool callop = pn->isKind(PNK_CALL) || pn->isKind(PNK_TAGGED_TEMPLATE);
+    bool callop =
+        pn->isKind(ParseNodeKind::PNK_CALL) || pn->isKind(ParseNodeKind::PNK_TAGGED_TEMPLATE);
     /*
      * Emit callable invocation or operator new (constructor call) code.
      * First, emit code for the left operand to evaluate the callable or
      * constructable object expression.
      *
      * For operator new, we emit JSOP_GETPROP instead of JSOP_CALLPROP, etc.
      * This is necessary to interpose the lambda-initialized method read
      * barrier -- see the code in jsinterp.cpp for JSOP_LAMBDA followed by
@@ -9187,17 +9223,17 @@ BytecodeEmitter::emitCallOrNew(ParseNode
     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(PNK_NAME) && emitterMode == BytecodeEmitter::SelfHosting && !spread) {
+    if (pn2->isKind(ParseNodeKind::PNK_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)
         {
             return emitSelfHostedCallFunction(pn);
@@ -9242,17 +9278,17 @@ BytecodeEmitter::emitCallOrNew(ParseNode
      */
     if (!spread) {
         for (ParseNode* pn3 = pn2->pn_next; pn3; pn3 = pn3->pn_next) {
             if (!emitTree(pn3))
                 return false;
         }
 
         if (isNewOp) {
-            if (pn->isKind(PNK_SUPERCALL)) {
+            if (pn->isKind(ParseNodeKind::PNK_SUPERCALL)) {
                 if (!emit1(JSOP_NEWTARGET))
                     return false;
             } else {
                 // Repush the callee as new.target
                 if (!emitDupAt(argc + 1))
                     return false;
             }
         }
@@ -9294,17 +9330,17 @@ BytecodeEmitter::emitCallOrNew(ParseNode
             return false;
 
         if (emitOptCode) {
             if (!ifNotOptimizable.emitEnd())
                 return false;
         }
 
         if (isNewOp) {
-            if (pn->isKind(PNK_SUPERCALL)) {
+            if (pn->isKind(ParseNodeKind::PNK_SUPERCALL)) {
                 if (!emit1(JSOP_NEWTARGET))
                     return false;
             } else {
                 if (!emitDupAt(2))
                     return false;
             }
         }
     }
@@ -9365,26 +9401,26 @@ static const JSOp ParseNodeKindToJSOp[] 
     JSOP_DIV,
     JSOP_MOD,
     JSOP_POW
 };
 
 static inline JSOp
 BinaryOpParseNodeKindToJSOp(ParseNodeKind pnk)
 {
-    MOZ_ASSERT(pnk >= PNK_BINOP_FIRST);
-    MOZ_ASSERT(pnk <= PNK_BINOP_LAST);
-    return ParseNodeKindToJSOp[pnk - PNK_BINOP_FIRST];
+    MOZ_ASSERT(pnk >= ParseNodeKind::PNK_BINOP_FIRST);
+    MOZ_ASSERT(pnk <= ParseNodeKind::PNK_BINOP_LAST);
+    return ParseNodeKindToJSOp[size_t(pnk) - size_t(ParseNodeKind::PNK_BINOP_FIRST)];
 }
 
 bool
 BytecodeEmitter::emitRightAssociative(ParseNode* pn)
 {
     // ** is the only right-associative operator.
-    MOZ_ASSERT(pn->isKind(PNK_POW));
+    MOZ_ASSERT(pn->isKind(ParseNodeKind::PNK_POW));
     MOZ_ASSERT(pn->isArity(PN_LIST));
 
     // Right-associative operator chain.
     for (ParseNode* subexpr = pn->pn_head; subexpr; subexpr = subexpr->pn_next) {
         if (!emitTree(subexpr))
             return false;
     }
     for (uint32_t i = 0; i < pn->pn_count - 1; i++) {
@@ -9412,17 +9448,17 @@ BytecodeEmitter::emitLeftAssociative(Par
     } while ((nextExpr = nextExpr->pn_next));
     return true;
 }
 
 bool
 BytecodeEmitter::emitLogical(ParseNode* pn)
 {
     MOZ_ASSERT(pn->isArity(PN_LIST));
-    MOZ_ASSERT(pn->isKind(PNK_OR) || pn->isKind(PNK_AND));
+    MOZ_ASSERT(pn->isKind(ParseNodeKind::PNK_OR) || pn->isKind(ParseNodeKind::PNK_AND));
 
     /*
      * JSOP_OR converts the operand on the stack to boolean, leaves the original
      * value on the stack and jumps if true; otherwise it falls into the next
      * bytecode, which pops the left operand and then evaluates the right operand.
      * The jump goes around the right operand evaluation.
      *
      * JSOP_AND converts the operand on the stack to boolean and jumps if false;
@@ -9430,17 +9466,17 @@ BytecodeEmitter::emitLogical(ParseNode* 
      */
 
     TDZCheckCache tdzCache(this);
 
     /* Left-associative operator chain: avoid too much recursion. */
     ParseNode* pn2 = pn->pn_head;
     if (!emitTree(pn2))
         return false;
-    JSOp op = pn->isKind(PNK_OR) ? JSOP_OR : JSOP_AND;
+    JSOp op = pn->isKind(ParseNodeKind::PNK_OR) ? JSOP_OR : JSOP_AND;
     JumpList jump;
     if (!emitJump(op, &jump))
         return false;
     if (!emit1(JSOP_POP))
         return false;
 
     /* Emit nodes between the head and the tail. */
     while ((pn2 = pn2->pn_next)->pn_next) {
@@ -9477,21 +9513,21 @@ BytecodeEmitter::emitSequenceExpr(ParseN
 }
 
 // Using MOZ_NEVER_INLINE in here is a workaround for llvm.org/pr14047. See
 // the comment on emitSwitch.
 MOZ_NEVER_INLINE bool
 BytecodeEmitter::emitIncOrDec(ParseNode* pn)
 {
     switch (pn->pn_kid->getKind()) {
-      case PNK_DOT:
+      case ParseNodeKind::PNK_DOT:
         return emitPropIncDec(pn);
-      case PNK_ELEM:
+      case ParseNodeKind::PNK_ELEM:
         return emitElemIncDec(pn);
-      case PNK_CALL:
+      case ParseNodeKind::PNK_CALL:
         return emitCallIncDec(pn);
       default:
         return emitNameIncDec(pn);
     }
 }
 
 // Using MOZ_NEVER_INLINE in here is a workaround for llvm.org/pr14047. See
 // the comment on emitSwitch.
@@ -9558,27 +9594,27 @@ bool
 BytecodeEmitter::emitPropertyList(ParseNode* pn, MutableHandlePlainObject objp, PropListType type)
 {
     for (ParseNode* propdef = pn->pn_head; propdef; propdef = propdef->pn_next) {
         if (!updateSourceCoordNotes(propdef->pn_pos.begin))
             return false;
 
         // Handle __proto__: v specially because *only* this form, and no other
         // involving "__proto__", performs [[Prototype]] mutation.
-        if (propdef->isKind(PNK_MUTATEPROTO)) {
+        if (propdef->isKind(ParseNodeKind::PNK_MUTATEPROTO)) {
             MOZ_ASSERT(type == ObjectLiteral);
             if (!emitTree(propdef->pn_kid))
                 return false;
             objp.set(nullptr);
             if (!emit1(JSOP_MUTATEPROTO))
                 return false;
             continue;
         }
 
-        if (propdef->isKind(PNK_SPREAD)) {
+        if (propdef->isKind(ParseNodeKind::PNK_SPREAD)) {
             MOZ_ASSERT(type == ObjectLiteral);
 
             if (!emit1(JSOP_DUP))
                 return false;
 
             if (!emitTree(propdef->pn_kid))
                 return false;
 
@@ -9596,21 +9632,23 @@ BytecodeEmitter::emitPropertyList(ParseN
                 return false;
             if (!emit1(JSOP_POP))
                 return false;
         }
 
         /* Emit an index for t[2] for later consumption by JSOP_INITELEM. */
         ParseNode* key = propdef->pn_left;
         bool isIndex = false;
-        if (key->isKind(PNK_NUMBER)) {
+        if (key->isKind(ParseNodeKind::PNK_NUMBER)) {
             if (!emitNumberOp(key->pn_dval))
                 return false;
             isIndex = true;
-        } else if (key->isKind(PNK_OBJECT_PROPERTY_NAME) || key->isKind(PNK_STRING)) {
+        } else if (key->isKind(ParseNodeKind::PNK_OBJECT_PROPERTY_NAME) ||
+                   key->isKind(ParseNodeKind::PNK_STRING))
+        {
             // EmitClass took care of constructor already.
             if (type == ClassBody && key->pn_atom == cx->names().constructor &&
                 !propdef->as<ClassMethod>().isStatic())
             {
                 continue;
             }
         } else {
             if (!emitComputedPropertyName(key))
@@ -9629,17 +9667,17 @@ BytecodeEmitter::emitPropertyList(ParseN
 
         FunctionPrefixKind prefixKind = op == JSOP_INITPROP_GETTER ? FunctionPrefixKind::Get
                                         : op == JSOP_INITPROP_SETTER ? FunctionPrefixKind::Set
                                         : FunctionPrefixKind::None;
 
         if (op == JSOP_INITPROP_GETTER || op == JSOP_INITPROP_SETTER)
             objp.set(nullptr);
 
-        if (propdef->pn_right->isKind(PNK_FUNCTION) &&
+        if (propdef->pn_right->isKind(ParseNodeKind::PNK_FUNCTION) &&
             propdef->pn_right->pn_funbox->needsHomeObject())
         {
             MOZ_ASSERT(propdef->pn_right->pn_funbox->function()->allowSuperProperty());
             bool isAsync = propdef->pn_right->pn_funbox->isAsync();
             if (isAsync) {
                 if (!emit1(JSOP_SWAP))
                     return false;
             }
@@ -9676,17 +9714,18 @@ BytecodeEmitter::emitPropertyList(ParseN
                 if (!emitDupAt(1))
                     return false;
                 if (!emit2(JSOP_SETFUNNAME, uint8_t(prefixKind)))
                     return false;
             }
             if (!emit1(op))
                 return false;
         } else {
-            MOZ_ASSERT(key->isKind(PNK_OBJECT_PROPERTY_NAME) || key->isKind(PNK_STRING));
+            MOZ_ASSERT(key->isKind(ParseNodeKind::PNK_OBJECT_PROPERTY_NAME) ||
+                       key->isKind(ParseNodeKind::PNK_STRING));
 
             uint32_t index;
             if (!makeAtomIndex(key->pn_atom, &index))
                 return false;
 
             if (objp) {
                 MOZ_ASSERT(type == ObjectLiteral);
                 MOZ_ASSERT(!IsHiddenInitOp(op));
@@ -9831,17 +9870,17 @@ BytecodeEmitter::emitArray(ParseNode* pn
      * it to the array, without invoking latent setters.  We use the
      * JSOP_NEWINIT and JSOP_INITELEM_ARRAY bytecodes to ignore setters and
      * to avoid dup'ing and popping the array as each element is added, as
      * JSOP_SETELEM/JSOP_SETPROP would do.
      */
 
     uint32_t nspread = 0;
     for (ParseNode* elt = pn; elt; elt = elt->pn_next) {
-        if (elt->isKind(PNK_SPREAD))
+        if (elt->isKind(ParseNodeKind::PNK_SPREAD))
             nspread++;
     }
 
     // Array literal's length is limited to NELEMENTS_LIMIT in parser.
     static_assert(NativeObject::MAX_DENSE_ELEMENTS_COUNT <= INT32_MAX,
                   "array literals' maximum length must not exceed limits "
                   "required by BaselineCompiler::emit_JSOP_NEWARRAY, "
                   "BaselineCompiler::emit_JSOP_INITELEM_ARRAY, "
@@ -9855,46 +9894,46 @@ BytecodeEmitter::emitArray(ParseNode* pn
     // minimum possible final size.
     if (!emitUint32Operand(JSOP_NEWARRAY, count - nspread))         // ARRAY
         return false;
 
     ParseNode* pn2 = pn;
     uint32_t index;
     bool afterSpread = false;
     for (index = 0; pn2; index++, pn2 = pn2->pn_next) {
-        if (!afterSpread && pn2->isKind(PNK_SPREAD)) {
+        if (!afterSpread && pn2->isKind(ParseNodeKind::PNK_SPREAD)) {
             afterSpread = true;
             if (!emitNumberOp(index))                               // ARRAY INDEX
                 return false;
         }
         if (!updateSourceCoordNotes(pn2->pn_pos.begin))
             return false;
 
         bool allowSelfHostedIter = false;
-        if (pn2->isKind(PNK_ELISION)) {
+        if (pn2->isKind(ParseNodeKind::PNK_ELISION)) {
             if (!emit1(JSOP_HOLE))
                 return false;
         } else {
             ParseNode* expr;
-            if (pn2->isKind(PNK_SPREAD)) {
+            if (pn2->isKind(ParseNodeKind::PNK_SPREAD)) {
                 expr = pn2->pn_kid;
 
                 if (emitterMode == BytecodeEmitter::SelfHosting &&
-                    expr->isKind(PNK_CALL) &&
+                    expr->isKind(ParseNodeKind::PNK_CALL) &&
                     expr->pn_head->name() == cx->names().allowContentIter)
                 {
                     allowSelfHostedIter = true;
                 }
             } else {
                 expr = pn2;
             }
             if (!emitTree(expr))                                         // ARRAY INDEX? VALUE
                 return false;
         }
-        if (pn2->isKind(PNK_SPREAD)) {
+        if (pn2->isKind(ParseNodeKind::PNK_SPREAD)) {
             if (!emitIterator())                                         // ARRAY INDEX ITER
                 return false;
             if (!emit2(JSOP_PICK, 2))                                    // INDEX ITER ARRAY
                 return false;
             if (!emit2(JSOP_PICK, 2))                                    // ITER ARRAY INDEX
                 return false;
             if (!emitSpread(allowSelfHostedIter))                        // ARRAY INDEX
                 return false;
@@ -9913,22 +9952,22 @@ BytecodeEmitter::emitArray(ParseNode* pn
     }
     return true;
 }
 
 static inline JSOp
 UnaryOpParseNodeKindToJSOp(ParseNodeKind pnk)
 {
     switch (pnk) {
-      case PNK_THROW: return JSOP_THROW;
-      case PNK_VOID: return JSOP_VOID;
-      case PNK_NOT: return JSOP_NOT;
-      case PNK_BITNOT: return JSOP_BITNOT;
-      case PNK_POS: return JSOP_POS;
-      case PNK_NEG: return JSOP_NEG;
+      case ParseNodeKind::PNK_THROW: return JSOP_THROW;
+      case ParseNodeKind::PNK_VOID: return JSOP_VOID;
+      case ParseNodeKind::PNK_NOT: return JSOP_NOT;
+      case ParseNodeKind::PNK_BITNOT: return JSOP_BITNOT;
+      case ParseNodeKind::PNK_POS: return JSOP_POS;
+      case ParseNodeKind::PNK_NEG: return JSOP_NEG;
       default: MOZ_CRASH("unexpected unary op");
     }
 }
 
 bool
 BytecodeEmitter::emitUnary(ParseNode* pn)
 {
     if (!updateSourceCoordNotes(pn->pn_pos.begin))
@@ -9950,17 +9989,17 @@ BytecodeEmitter::emitTypeof(ParseNode* n
         return false;
 
     return emit1(op);
 }
 
 bool
 BytecodeEmitter::emitFunctionFormalParametersAndBody(ParseNode *pn)
 {
-    MOZ_ASSERT(pn->isKind(PNK_PARAMSBODY));
+    MOZ_ASSERT(pn->isKind(ParseNodeKind::PNK_PARAMSBODY));
 
     ParseNode* funBody = pn->last();
     FunctionBox* funbox = sc->asFunctionBox();
 
     TDZCheckCache tdzCache(this);
 
     if (funbox->hasParameterExprs) {
         EmitterScope funEmitterScope(this);
@@ -10063,31 +10102,31 @@ BytecodeEmitter::emitFunctionFormalParam
 
     bool hasParameterExprs = funbox->hasParameterExprs;
     bool hasRest = funbox->hasRest();
 
     uint16_t argSlot = 0;
     for (ParseNode* arg = pn->pn_head; arg != funBody; arg = arg->pn_next, argSlot++) {
         ParseNode* bindingElement = arg;
         ParseNode* initializer = nullptr;
-        if (arg->isKind(PNK_ASSIGN)) {
+        if (arg->isKind(ParseNodeKind::PNK_ASSIGN)) {
             bindingElement = arg->pn_left;
             initializer = arg->pn_right;
         }
 
         // Left-hand sides are either simple names or destructuring patterns.
-        MOZ_ASSERT(bindingElement->isKind(PNK_NAME) ||
-                   bindingElement->isKind(PNK_ARRAY) ||
-                   bindingElement->isKind(PNK_OBJECT));
+        MOZ_ASSERT(bindingElement->isKind(ParseNodeKind::PNK_NAME) ||
+                   bindingElement->isKind(ParseNodeKind::PNK_ARRAY) ||
+                   bindingElement->isKind(ParseNodeKind::PNK_OBJECT));
 
         // The rest parameter doesn't have an initializer.
         bool isRest = hasRest && arg->pn_next == funBody;
         MOZ_ASSERT_IF(isRest, !initializer);
 
-        bool isDestructuring = !bindingElement->isKind(PNK_NAME);
+        bool isDestructuring = !bindingElement->isKind(ParseNodeKind::PNK_NAME);
 
         // ES 14.1.19 says if BindingElement contains an expression in the
         // production FormalParameter : BindingElement, it is evaluated in a
         // new var environment. This is needed to prevent vars from escaping
         // direct eval in parameter expressions.
         Maybe<EmitterScope> paramExprVarScope;
         if (funbox->hasDirectEvalInParameterExpr && (isDestructuring || initializer)) {
             paramExprVarScope.emplace(this);
@@ -10311,17 +10350,18 @@ BytecodeEmitter::emitClass(ParseNode* pn
     ParseNode* heritageExpression = classNode.heritage();
 
     ParseNode* classMethods = classNode.methodList();
     ParseNode* constructor = nullptr;
     for (ParseNode* mn = classMethods->pn_head; mn; mn = mn->pn_next) {
         ClassMethod& method = mn->as<ClassMethod>();
         ParseNode& methodName = method.name();
         if (!method.isStatic() &&
-            (methodName.isKind(PNK_OBJECT_PROPERTY_NAME) || methodName.isKind(PNK_STRING)) &&
+            (methodName.isKind(ParseNodeKind::PNK_OBJECT_PROPERTY_NAME) ||
+             methodName.isKind(ParseNodeKind::PNK_STRING)) &&
             methodName.pn_atom == cx->names().constructor)
         {
             constructor = &method.method();
             break;
         }
     }
 
     bool savedStrictness = sc->setLocalStrictMode(true);
@@ -10542,385 +10582,385 @@ BytecodeEmitter::emitTree(ParseNode* pn,
        However, a couple trees require special treatment; see the
        relevant emitter functions for details. */
     if (emitLineNote == EMIT_LINENOTE && !ParseNodeRequiresSpecialLineNumberNotes(pn)) {
         if (!updateLineNumberNotes(pn->pn_pos.begin))
             return false;
     }
 
     switch (pn->getKind()) {
-      case PNK_FUNCTION:
+      case ParseNodeKind::PNK_FUNCTION:
         if (!emitFunction(pn))
             return false;
         break;
 
-      case PNK_PARAMSBODY:
+      case ParseNodeKind::PNK_PARAMSBODY:
         if (!emitFunctionFormalParametersAndBody(pn))
             return false;
         break;
 
-      case PNK_IF:
+      case ParseNodeKind::PNK_IF:
         if (!emitIf(pn))
             return false;
         break;
 
-      case PNK_SWITCH:
+      case ParseNodeKind::PNK_SWITCH:
         if (!emitSwitch(pn))
             return false;
         break;
 
-      case PNK_WHILE:
+      case ParseNodeKind::PNK_WHILE:
         if (!emitWhile(pn))
             return false;
         break;
 
-      case PNK_DOWHILE:
+      case ParseNodeKind::PNK_DOWHILE:
         if (!emitDo(pn))
             return false;
         break;
 
-      case PNK_FOR:
+      case ParseNodeKind::PNK_FOR:
         if (!emitFor(pn))
             return false;
         break;
 
-      case PNK_BREAK:
+      case ParseNodeKind::PNK_BREAK:
         if (!emitBreak(pn->as<BreakStatement>().label()))
             return false;
         break;
 
-      case PNK_CONTINUE:
+      case ParseNodeKind::PNK_CONTINUE:
         if (!emitContinue(pn->as<ContinueStatement>().label()))
             return false;
         break;
 
-      case PNK_WITH:
+      case ParseNodeKind::PNK_WITH:
         if (!emitWith(pn))
             return false;
         break;
 
-      case PNK_TRY:
+      case ParseNodeKind::PNK_TRY:
         if (!emitTry(pn))
             return false;
         break;
 
-      case PNK_CATCH:
+      case ParseNodeKind::PNK_CATCH:
         if (!emitCatch(pn))
             return false;
         break;
 
-      case PNK_VAR:
+      case ParseNodeKind::PNK_VAR:
         if (!emitDeclarationList(pn))
             return false;
         break;
 
-      case PNK_RETURN:
+      case ParseNodeKind::PNK_RETURN:
         if (!emitReturn(pn))
             return false;
         break;
 
-      case PNK_YIELD_STAR:
+      case ParseNodeKind::PNK_YIELD_STAR:
         if (!emitYieldStar(pn->pn_kid))
             return false;
         break;
 
-      case PNK_GENERATOR:
+      case ParseNodeKind::PNK_GENERATOR:
         if (!emit1(JSOP_GENERATOR))
             return false;
         break;
 
-      case PNK_INITIALYIELD:
+      case ParseNodeKind::PNK_INITIALYIELD:
         if (!emitInitialYield(pn))
             return false;
         break;
 
-      case PNK_YIELD:
+      case ParseNodeKind::PNK_YIELD:
         if (!emitYield(pn))
             return false;
         break;
 
-      case PNK_AWAIT:
+      case ParseNodeKind::PNK_AWAIT:
         if (!emitAwait(pn))
             return false;
         break;
 
-      case PNK_STATEMENTLIST:
+      case ParseNodeKind::PNK_STATEMENTLIST:
         if (!emitStatementList(pn))
             return false;
         break;
 
-      case PNK_SEMI:
+      case ParseNodeKind::PNK_SEMI:
         if (!emitStatement(pn))
             return false;
         break;
 
-      case PNK_LABEL:
+      case ParseNodeKind::PNK_LABEL:
         if (!emitLabeledStatement(&pn->as<LabeledStatement>()))
             return false;
         break;
 
-      case PNK_COMMA:
+      case ParseNodeKind::PNK_COMMA:
         if (!emitSequenceExpr(pn, valueUsage))
             return false;
         break;
 
-      case PNK_ASSIGN:
-      case PNK_ADDASSIGN:
-      case PNK_SUBASSIGN:
-      case PNK_BITORASSIGN:
-      case PNK_BITXORASSIGN:
-      case PNK_BITANDASSIGN:
-      case PNK_LSHASSIGN:
-      case PNK_RSHASSIGN:
-      case PNK_URSHASSIGN:
-      case PNK_MULASSIGN:
-      case PNK_DIVASSIGN:
-      case PNK_MODASSIGN:
-      case PNK_POWASSIGN:
+      case ParseNodeKind::PNK_ASSIGN:
+      case ParseNodeKind::PNK_ADDASSIGN:
+      case ParseNodeKind::PNK_SUBASSIGN:
+      case ParseNodeKind::PNK_BITORASSIGN:
+      case ParseNodeKind::PNK_BITXORASSIGN:
+      case ParseNodeKind::PNK_BITANDASSIGN:
+      case ParseNodeKind::PNK_LSHASSIGN:
+      case ParseNodeKind::PNK_RSHASSIGN:
+      case ParseNodeKind::PNK_URSHASSIGN:
+      case ParseNodeKind::PNK_MULASSIGN:
+      case ParseNodeKind::PNK_DIVASSIGN:
+      case ParseNodeKind::PNK_MODASSIGN:
+      case ParseNodeKind::PNK_POWASSIGN:
         if (!emitAssignment(pn->pn_left, pn->getKind(), pn->pn_right))
             return false;
         break;
 
-      case PNK_CONDITIONAL:
+      case ParseNodeKind::PNK_CONDITIONAL:
         if (!emitConditionalExpression(pn->as<ConditionalExpression>(), valueUsage))
             return false;
         break;
 
-      case PNK_OR:
-      case PNK_AND:
+      case ParseNodeKind::PNK_OR:
+      case ParseNodeKind::PNK_AND:
         if (!emitLogical(pn))
             return false;
         break;
 
-      case PNK_ADD:
-      case PNK_SUB:
-      case PNK_BITOR:
-      case PNK_BITXOR:
-      case PNK_BITAND:
-      case PNK_STRICTEQ:
-      case PNK_EQ:
-      case PNK_STRICTNE:
-      case PNK_NE:
-      case PNK_LT:
-      case PNK_LE:
-      case PNK_GT:
-      case PNK_GE:
-      case PNK_IN:
-      case PNK_INSTANCEOF:
-      case PNK_LSH:
-      case PNK_RSH:
-      case PNK_URSH:
-      case PNK_STAR:
-      case PNK_DIV:
-      case PNK_MOD:
+      case ParseNodeKind::PNK_ADD:
+      case ParseNodeKind::PNK_SUB:
+      case ParseNodeKind::PNK_BITOR:
+      case ParseNodeKind::PNK_BITXOR:
+      case ParseNodeKind::PNK_BITAND:
+      case ParseNodeKind::PNK_STRICTEQ:
+      case ParseNodeKind::PNK_EQ:
+      case ParseNodeKind::PNK_STRICTNE:
+      case ParseNodeKind::PNK_NE:
+      case ParseNodeKind::PNK_LT:
+      case ParseNodeKind::PNK_LE:
+      case ParseNodeKind::PNK_GT:
+      case ParseNodeKind::PNK_GE:
+      case ParseNodeKind::PNK_IN:
+      case ParseNodeKind::PNK_INSTANCEOF:
+      case ParseNodeKind::PNK_LSH:
+      case ParseNodeKind::PNK_RSH:
+      case ParseNodeKind::PNK_URSH:
+      case ParseNodeKind::PNK_STAR:
+      case ParseNodeKind::PNK_DIV:
+      case ParseNodeKind::PNK_MOD:
         if (!emitLeftAssociative(pn))
             return false;
         break;
 
-      case PNK_POW:
+      case ParseNodeKind::PNK_POW:
         if (!emitRightAssociative(pn))
             return false;
         break;
 
-      case PNK_PIPELINE:
+      case ParseNodeKind::PNK_PIPELINE:
         if (!emitPipeline(pn))
             return false;
         break;
 
-      case PNK_TYPEOFNAME:
+      case ParseNodeKind::PNK_TYPEOFNAME:
         if (!emitTypeof(pn, JSOP_TYPEOF))
             return false;
         break;
 
-      case PNK_TYPEOFEXPR:
+      case ParseNodeKind::PNK_TYPEOFEXPR:
         if (!emitTypeof(pn, JSOP_TYPEOFEXPR))
             return false;
         break;
 
-      case PNK_THROW:
-      case PNK_VOID:
-      case PNK_NOT:
-      case PNK_BITNOT:
-      case PNK_POS:
-      case PNK_NEG:
+      case ParseNodeKind::PNK_THROW:
+      case ParseNodeKind::PNK_VOID:
+      case ParseNodeKind::PNK_NOT:
+      case ParseNodeKind::PNK_BITNOT:
+      case ParseNodeKind::PNK_POS:
+      case ParseNodeKind::PNK_NEG:
         if (!emitUnary(pn))
             return false;
         break;
 
-      case PNK_PREINCREMENT:
-      case PNK_PREDECREMENT:
-      case PNK_POSTINCREMENT:
-      case PNK_POSTDECREMENT:
+      case ParseNodeKind::PNK_PREINCREMENT:
+      case ParseNodeKind::PNK_PREDECREMENT:
+      case ParseNodeKind::PNK_POSTINCREMENT:
+      case ParseNodeKind::PNK_POSTDECREMENT:
         if (!emitIncOrDec(pn))
             return false;
         break;
 
-      case PNK_DELETENAME:
+      case ParseNodeKind::PNK_DELETENAME:
         if (!emitDeleteName(pn))
             return false;
         break;
 
-      case PNK_DELETEPROP:
+      case ParseNodeKind::PNK_DELETEPROP:
         if (!emitDeleteProperty(pn))
             return false;
         break;
 
-      case PNK_DELETEELEM:
+      case ParseNodeKind::PNK_DELETEELEM:
         if (!emitDeleteElement(pn))
             return false;
         break;
 
-      case PNK_DELETEEXPR:
+      case ParseNodeKind::PNK_DELETEEXPR:
         if (!emitDeleteExpression(pn))
             return false;
         break;
 
-      case PNK_DOT:
+      case ParseNodeKind::PNK_DOT:
         if (pn->as<PropertyAccess>().isSuper()) {
             if (!emitSuperPropOp(pn, JSOP_GETPROP_SUPER))
                 return false;
         } else {
             if (!emitPropOp(pn, JSOP_GETPROP))
                 return false;
         }
         break;
 
-      case PNK_ELEM:
+      case ParseNodeKind::PNK_ELEM:
         if (pn->as<PropertyByValue>().isSuper()) {
             if (!emitSuperElemOp(pn, JSOP_GETELEM_SUPER))
                 return false;
         } else {
             if (!emitElemOp(pn, JSOP_GETELEM))
                 return false;
         }
         break;
 
-      case PNK_NEW:
-      case PNK_TAGGED_TEMPLATE:
-      case PNK_CALL:
-      case PNK_SUPERCALL:
+      case ParseNodeKind::PNK_NEW:
+      case ParseNodeKind::PNK_TAGGED_TEMPLATE:
+      case ParseNodeKind::PNK_CALL:
+      case ParseNodeKind::PNK_SUPERCALL:
         if (!emitCallOrNew(pn, valueUsage))
             return false;
         break;
 
-      case PNK_LEXICALSCOPE:
+      case ParseNodeKind::PNK_LEXICALSCOPE:
         if (!emitLexicalScope(pn))
             return false;
         break;
 
-      case PNK_CONST:
-      case PNK_LET:
+      case ParseNodeKind::PNK_CONST:
+      case ParseNodeKind::PNK_LET:
         if (!emitDeclarationList(pn))
             return false;
         break;
 
-      case PNK_IMPORT:
+      case ParseNodeKind::PNK_IMPORT:
         MOZ_ASSERT(sc->isModuleContext());
         break;
 
-      case PNK_EXPORT:
+      case ParseNodeKind::PNK_EXPORT:
         MOZ_ASSERT(sc->isModuleContext());
-        if (pn->pn_kid->getKind() != PNK_EXPORT_SPEC_LIST) {
+        if (pn->pn_kid->getKind() != ParseNodeKind::PNK_EXPORT_SPEC_LIST) {
             if (!emitTree(pn->pn_kid))
                 return false;
         }
         break;
 
-      case PNK_EXPORT_DEFAULT:
+      case ParseNodeKind::PNK_EXPORT_DEFAULT:
         MOZ_ASSERT(sc->isModuleContext());
         if (!emitExportDefault(pn))
             return false;
         break;
 
-      case PNK_EXPORT_FROM:
+      case ParseNodeKind::PNK_EXPORT_FROM:
         MOZ_ASSERT(sc->isModuleContext());
         break;
 
-      case PNK_CALLSITEOBJ:
+      case ParseNodeKind::PNK_CALLSITEOBJ:
         if (!emitCallSiteObject(pn))
             return false;
         break;
 
-      case PNK_ARRAY:
+      case ParseNodeKind::PNK_ARRAY:
         if (!emitArrayLiteral(pn))
             return false;
         break;
 
-      case PNK_OBJECT:
+      case ParseNodeKind::PNK_OBJECT:
         if (!emitObject(pn))
             return false;
         break;
 
-      case PNK_NAME:
+      case ParseNodeKind::PNK_NAME:
         if (!emitGetName(pn))
             return false;
         break;
 
-      case PNK_TEMPLATE_STRING_LIST:
+      case ParseNodeKind::PNK_TEMPLATE_STRING_LIST:
         if (!emitTemplateString(pn))
             return false;
         break;
 
-      case PNK_TEMPLATE_STRING:
-      case PNK_STRING:
+      case ParseNodeKind::PNK_TEMPLATE_STRING:
+      case ParseNodeKind::PNK_STRING:
         if (!emitAtomOp(pn, JSOP_STRING))
             return false;
         break;
 
-      case PNK_NUMBER:
+      case ParseNodeKind::PNK_NUMBER:
         if (!emitNumberOp(pn->pn_dval))
             return false;
         break;
 
-      case PNK_REGEXP:
+      case ParseNodeKind::PNK_REGEXP:
         if (!emitRegExp(objectList.add(pn->as<RegExpLiteral>().objbox())))
             return false;
         break;
 
-      case PNK_TRUE:
-      case PNK_FALSE:
-      case PNK_NULL:
-      case PNK_RAW_UNDEFINED:
+      case ParseNodeKind::PNK_TRUE:
+      case ParseNodeKind::PNK_FALSE:
+      case ParseNodeKind::PNK_NULL:
+      case ParseNodeKind::PNK_RAW_UNDEFINED:
         if (!emit1(pn->getOp()))
             return false;
         break;
 
-      case PNK_THIS:
+      case ParseNodeKind::PNK_THIS:
         if (!emitThisLiteral(pn))
             return false;
         break;
 
-      case PNK_DEBUGGER:
+      case ParseNodeKind::PNK_DEBUGGER:
         if (!updateSourceCoordNotes(pn->pn_pos.begin))
             return false;
         if (!emit1(JSOP_DEBUGGER))
             return false;
         break;
 
-      case PNK_NOP:
+      case ParseNodeKind::PNK_NOP:
         MOZ_ASSERT(pn->getArity() == PN_NULLARY);
         break;
 
-      case PNK_CLASS:
+      case ParseNodeKind::PNK_CLASS:
         if (!emitClass(pn))
             return false;
         break;
 
-      case PNK_NEWTARGET:
+      case ParseNodeKind::PNK_NEWTARGET:
         if (!emit1(JSOP_NEWTARGET))
             return false;
         break;
 
-      case PNK_SETTHIS:
+      case ParseNodeKind::PNK_SETTHIS:
         if (!emitSetThis(pn))
             return false;
         break;
 
-      case PNK_POSHOLDER:
-        MOZ_FALLTHROUGH_ASSERT("Should never try to emit PNK_POSHOLDER");
+      case ParseNodeKind::PNK_POSHOLDER:
+        MOZ_FALLTHROUGH_ASSERT("Should never try to emit ParseNodeKind::PNK_POSHOLDER");
 
       default:
         MOZ_ASSERT(0);
     }
 
     /* bce->emitLevel == 1 means we're last on the stack, so finish up. */
     if (emitLevel == 1) {
         if (!updateSourceCoordNotes(pn->pn_pos.end))
--- a/js/src/frontend/FoldConstants.cpp
+++ b/js/src/frontend/FoldConstants.cpp
@@ -45,126 +45,126 @@ ListContainsHoistedDeclaration(JSContext
     return true;
 }
 
 // Determines whether the given ParseNode contains any declarations whose
 // visibility will extend outside the node itself -- that is, whether the
 // ParseNode contains any var statements.
 //
 // THIS IS NOT A GENERAL-PURPOSE FUNCTION.  It is only written to work in the
-// specific context of deciding that |node|, as one arm of a PNK_IF controlled
-// by a constant condition, contains a declaration that forbids |node| being
-// completely eliminated as dead.
+// specific context of deciding that |node|, as one arm of a ParseNodeKind::PNK_IF
+// controlled by a constant condition, contains a declaration that forbids
+// |node| being completely eliminated as dead.
 static bool
 ContainsHoistedDeclaration(JSContext* cx, ParseNode* node, bool* result)
 {
     if (!CheckRecursionLimit(cx))
         return false;
 
   restart:
 
     // With a better-typed AST, we would have distinct parse node classes for
     // expressions and for statements and would characterize expressions with
     // ExpressionKind and statements with StatementKind.  Perhaps someday.  In
     // the meantime we must characterize every ParseNodeKind, even the
     // expression/sub-expression ones that, if we handle all statement kinds
     // correctly, we'll never see.
     switch (node->getKind()) {
       // Base case.
-      case PNK_VAR:
+      case ParseNodeKind::PNK_VAR:
         *result = true;
         return true;
 
       // Non-global lexical declarations are block-scoped (ergo not hoistable).
-      case PNK_LET:
-      case PNK_CONST:
+      case ParseNodeKind::PNK_LET:
+      case ParseNodeKind::PNK_CONST:
         MOZ_ASSERT(node->isArity(PN_LIST));
         *result = false;
         return true;
 
       // Similarly to the lexical declarations above, classes cannot add hoisted
       // declarations
-      case PNK_CLASS:
+      case ParseNodeKind::PNK_CLASS:
         MOZ_ASSERT(node->isArity(PN_TERNARY));
         *result = false;
         return true;
 
       // Function declarations *can* be hoisted declarations.  But in the
       // magical world of the rewritten frontend, the declaration necessitated
       // by a nested function statement, not at body level, doesn't require
       // that we preserve an unreachable function declaration node against
       // dead-code removal.
-      case PNK_FUNCTION:
+      case ParseNodeKind::PNK_FUNCTION:
         MOZ_ASSERT(node->isArity(PN_CODE));
         *result = false;
         return true;
 
-      case PNK_MODULE:
+      case ParseNodeKind::PNK_MODULE:
         *result = false;
         return true;
 
       // Statements with no sub-components at all.
-      case PNK_NOP: // induced by function f() {} function f() {}
-      case PNK_DEBUGGER:
+      case ParseNodeKind::PNK_NOP: // induced by function f() {} function f() {}
+      case ParseNodeKind::PNK_DEBUGGER:
         MOZ_ASSERT(node->isArity(PN_NULLARY));
         *result = false;
         return true;
 
       // Statements containing only an expression have no declarations.
-      case PNK_SEMI:
-      case PNK_THROW:
-      case PNK_RETURN:
+      case ParseNodeKind::PNK_SEMI:
+      case ParseNodeKind::PNK_THROW:
+      case ParseNodeKind::PNK_RETURN:
         MOZ_ASSERT(node->isArity(PN_UNARY));
         *result = false;
         return true;
 
       // These two aren't statements in the spec, but we sometimes insert them
       // in statement lists anyway.
-      case PNK_INITIALYIELD:
-      case PNK_YIELD_STAR:
-      case PNK_YIELD:
+      case ParseNodeKind::PNK_INITIALYIELD:
+      case ParseNodeKind::PNK_YIELD_STAR:
+      case ParseNodeKind::PNK_YIELD:
         MOZ_ASSERT(node->isArity(PN_UNARY));
         *result = false;
         return true;
 
       // Other statements with no sub-statement components.
-      case PNK_BREAK:
-      case PNK_CONTINUE:
-      case PNK_IMPORT:
-      case PNK_IMPORT_SPEC_LIST:
-      case PNK_IMPORT_SPEC:
-      case PNK_EXPORT_FROM:
-      case PNK_EXPORT_DEFAULT:
-      case PNK_EXPORT_SPEC_LIST:
-      case PNK_EXPORT_SPEC:
-      case PNK_EXPORT:
-      case PNK_EXPORT_BATCH_SPEC:
+      case ParseNodeKind::PNK_BREAK:
+      case ParseNodeKind::PNK_CONTINUE:
+      case ParseNodeKind::PNK_IMPORT:
+      case ParseNodeKind::PNK_IMPORT_SPEC_LIST:
+      case ParseNodeKind::PNK_IMPORT_SPEC:
+      case ParseNodeKind::PNK_EXPORT_FROM:
+      case ParseNodeKind::PNK_EXPORT_DEFAULT:
+      case ParseNodeKind::PNK_EXPORT_SPEC_LIST:
+      case ParseNodeKind::PNK_EXPORT_SPEC:
+      case ParseNodeKind::PNK_EXPORT:
+      case ParseNodeKind::PNK_EXPORT_BATCH_SPEC:
         *result = false;
         return true;
 
       // Statements possibly containing hoistable declarations only in the left
       // half, in ParseNode terms -- the loop body in AST terms.
-      case PNK_DOWHILE:
+      case ParseNodeKind::PNK_DOWHILE:
         return ContainsHoistedDeclaration(cx, node->pn_left, result);
 
       // Statements possibly containing hoistable declarations only in the
       // right half, in ParseNode terms -- the loop body or nested statement
       // (usually a block statement), in AST terms.
-      case PNK_WHILE:
-      case PNK_WITH:
+      case ParseNodeKind::PNK_WHILE:
+      case ParseNodeKind::PNK_WITH:
         return ContainsHoistedDeclaration(cx, node->pn_right, result);
 
-      case PNK_LABEL:
+      case ParseNodeKind::PNK_LABEL:
         return ContainsHoistedDeclaration(cx, node->pn_expr, result);
 
       // Statements with more complicated structures.
 
       // if-statement nodes may have hoisted declarations in their consequent
       // and alternative components.
-      case PNK_IF: {
+      case ParseNodeKind::PNK_IF: {
         MOZ_ASSERT(node->isArity(PN_TERNARY));
 
         ParseNode* consequent = node->pn_kid2;
         if (!ContainsHoistedDeclaration(cx, consequent, result))
             return false;
         if (*result)
             return true;
 
@@ -172,32 +172,32 @@ ContainsHoistedDeclaration(JSContext* cx
             goto restart;
 
         *result = false;
         return true;
       }
 
       // try-statements have statements to execute, and one or both of a
       // catch-list and a finally-block.
-      case PNK_TRY: {
+      case ParseNodeKind::PNK_TRY: {
         MOZ_ASSERT(node->isArity(PN_TERNARY));
         MOZ_ASSERT(node->pn_kid2 || node->pn_kid3,
                    "must have either catch(es) or finally");
 
         ParseNode* tryBlock = node->pn_kid1;
         if (!ContainsHoistedDeclaration(cx, tryBlock, result))
             return false;
         if (*result)
             return true;
 
         if (ParseNode* catchScope = node->pn_kid2) {
-            MOZ_ASSERT(catchScope->isKind(PNK_LEXICALSCOPE));
+            MOZ_ASSERT(catchScope->isKind(ParseNodeKind::PNK_LEXICALSCOPE));
 
             ParseNode* catchNode = catchScope->pn_expr;
-            MOZ_ASSERT(catchNode->isKind(PNK_CATCH));
+            MOZ_ASSERT(catchNode->isKind(ParseNodeKind::PNK_CATCH));
 
             ParseNode* catchStatements = catchNode->pn_right;
             if (!ContainsHoistedDeclaration(cx, catchStatements, result))
                 return false;
             if (*result)
                 return true;
         }
 
@@ -206,223 +206,224 @@ ContainsHoistedDeclaration(JSContext* cx
 
         *result = false;
         return true;
       }
 
       // A switch node's left half is an expression; only its right half (a
       // list of cases/defaults, or a block node) could contain hoisted
       // declarations.
-      case PNK_SWITCH:
+      case ParseNodeKind::PNK_SWITCH:
         MOZ_ASSERT(node->isArity(PN_BINARY));
         return ContainsHoistedDeclaration(cx, node->pn_right, result);
 
-      case PNK_CASE:
+      case ParseNodeKind::PNK_CASE:
         return ContainsHoistedDeclaration(cx, node->as<CaseClause>().statementList(), result);
 
-      case PNK_FOR: {
+      case ParseNodeKind::PNK_FOR: {
         MOZ_ASSERT(node->isArity(PN_BINARY));
 
         ParseNode* loopHead = node->pn_left;
-        MOZ_ASSERT(loopHead->isKind(PNK_FORHEAD) ||
-                   loopHead->isKind(PNK_FORIN) ||
-                   loopHead->isKind(PNK_FOROF));
+        MOZ_ASSERT(loopHead->isKind(ParseNodeKind::PNK_FORHEAD) ||
+                   loopHead->isKind(ParseNodeKind::PNK_FORIN) ||
+                   loopHead->isKind(ParseNodeKind::PNK_FOROF));
 
-        if (loopHead->isKind(PNK_FORHEAD)) {
+        if (loopHead->isKind(ParseNodeKind::PNK_FORHEAD)) {
             // for (init?; cond?; update?), with only init possibly containing
             // a hoisted declaration.  (Note: a lexical-declaration |init| is
             // (at present) hoisted in SpiderMonkey parlance -- but such
             // hoisting doesn't extend outside of this statement, so it is not
             // hoisting in the sense meant by ContainsHoistedDeclaration.)
             MOZ_ASSERT(loopHead->isArity(PN_TERNARY));
 
             ParseNode* init = loopHead->pn_kid1;
-            if (init && init->isKind(PNK_VAR)) {
+            if (init && init->isKind(ParseNodeKind::PNK_VAR)) {
                 *result = true;
                 return true;
             }
         } else {
-            MOZ_ASSERT(loopHead->isKind(PNK_FORIN) || loopHead->isKind(PNK_FOROF));
+            MOZ_ASSERT(loopHead->isKind(ParseNodeKind::PNK_FORIN) ||
+                       loopHead->isKind(ParseNodeKind::PNK_FOROF));
 
             // for each? (target in ...), where only target may introduce
             // hoisted declarations.
             //
             //   -- or --
             //
             // for (target of ...), where only target may introduce hoisted
             // declarations.
             //
             // Either way, if |target| contains a declaration, it's |loopHead|'s
             // first kid.
             MOZ_ASSERT(loopHead->isArity(PN_TERNARY));
 
             ParseNode* decl = loopHead->pn_kid1;
-            if (decl && decl->isKind(PNK_VAR)) {
+            if (decl && decl->isKind(ParseNodeKind::PNK_VAR)) {
                 *result = true;
                 return true;
             }
         }
 
         ParseNode* loopBody = node->pn_right;
         return ContainsHoistedDeclaration(cx, loopBody, result);
       }
 
-      case PNK_LEXICALSCOPE: {
+      case ParseNodeKind::PNK_LEXICALSCOPE: {
         MOZ_ASSERT(node->isArity(PN_SCOPE));
         ParseNode* expr = node->pn_expr;
 
-        if (expr->isKind(PNK_FOR) || expr->isKind(PNK_FUNCTION))
+        if (expr->isKind(ParseNodeKind::PNK_FOR) || expr->isKind(ParseNodeKind::PNK_FUNCTION))
             return ContainsHoistedDeclaration(cx, expr, result);
 
-        MOZ_ASSERT(expr->isKind(PNK_STATEMENTLIST));
+        MOZ_ASSERT(expr->isKind(ParseNodeKind::PNK_STATEMENTLIST));
         return ListContainsHoistedDeclaration(cx, &node->pn_expr->as<ListNode>(), result);
       }
 
       // List nodes with all non-null children.
-      case PNK_STATEMENTLIST:
+      case ParseNodeKind::PNK_STATEMENTLIST:
         return ListContainsHoistedDeclaration(cx, &node->as<ListNode>(), result);
 
       // Grammar sub-components that should never be reached directly by this
       // method, because some parent component should have asserted itself.
-      case PNK_OBJECT_PROPERTY_NAME:
-      case PNK_COMPUTED_NAME:
-      case PNK_SPREAD:
-      case PNK_MUTATEPROTO:
-      case PNK_COLON:
-      case PNK_SHORTHAND:
-      case PNK_CONDITIONAL:
-      case PNK_TYPEOFNAME:
-      case PNK_TYPEOFEXPR:
-      case PNK_AWAIT:
-      case PNK_VOID:
-      case PNK_NOT:
-      case PNK_BITNOT:
-      case PNK_DELETENAME:
-      case PNK_DELETEPROP:
-      case PNK_DELETEELEM:
-      case PNK_DELETEEXPR:
-      case PNK_POS:
-      case PNK_NEG:
-      case PNK_PREINCREMENT:
-      case PNK_POSTINCREMENT:
-      case PNK_PREDECREMENT:
-      case PNK_POSTDECREMENT:
-      case PNK_OR:
-      case PNK_AND:
-      case PNK_BITOR:
-      case PNK_BITXOR:
-      case PNK_BITAND:
-      case PNK_STRICTEQ:
-      case PNK_EQ:
-      case PNK_STRICTNE:
-      case PNK_NE:
-      case PNK_LT:
-      case PNK_LE:
-      case PNK_GT:
-      case PNK_GE:
-      case PNK_INSTANCEOF:
-      case PNK_IN:
-      case PNK_LSH:
-      case PNK_RSH:
-      case PNK_URSH:
-      case PNK_ADD:
-      case PNK_SUB:
-      case PNK_STAR:
-      case PNK_DIV:
-      case PNK_MOD:
-      case PNK_POW:
-      case PNK_ASSIGN:
-      case PNK_ADDASSIGN:
-      case PNK_SUBASSIGN:
-      case PNK_BITORASSIGN:
-      case PNK_BITXORASSIGN:
-      case PNK_BITANDASSIGN:
-      case PNK_LSHASSIGN:
-      case PNK_RSHASSIGN:
-      case PNK_URSHASSIGN:
-      case PNK_MULASSIGN:
-      case PNK_DIVASSIGN:
-      case PNK_MODASSIGN:
-      case PNK_POWASSIGN:
-      case PNK_COMMA:
-      case PNK_ARRAY:
-      case PNK_OBJECT:
-      case PNK_DOT:
-      case PNK_ELEM:
-      case PNK_CALL:
-      case PNK_NAME:
-      case PNK_TEMPLATE_STRING:
-      case PNK_TEMPLATE_STRING_LIST:
-      case PNK_TAGGED_TEMPLATE:
-      case PNK_CALLSITEOBJ:
-      case PNK_STRING:
-      case PNK_REGEXP:
-      case PNK_TRUE:
-      case PNK_FALSE:
-      case PNK_NULL:
-      case PNK_RAW_UNDEFINED:
-      case PNK_THIS:
-      case PNK_ELISION:
-      case PNK_NUMBER:
-      case PNK_NEW:
-      case PNK_GENERATOR:
-      case PNK_PARAMSBODY:
-      case PNK_CATCH:
-      case PNK_FORIN:
-      case PNK_FOROF:
-      case PNK_FORHEAD:
-      case PNK_CLASSMETHOD:
-      case PNK_CLASSMETHODLIST:
-      case PNK_CLASSNAMES:
-      case PNK_NEWTARGET:
-      case PNK_POSHOLDER:
-      case PNK_SUPERCALL:
-      case PNK_SUPERBASE:
-      case PNK_SETTHIS:
+      case ParseNodeKind::PNK_OBJECT_PROPERTY_NAME:
+      case ParseNodeKind::PNK_COMPUTED_NAME:
+      case ParseNodeKind::PNK_SPREAD:
+      case ParseNodeKind::PNK_MUTATEPROTO:
+      case ParseNodeKind::PNK_COLON:
+      case ParseNodeKind::PNK_SHORTHAND:
+      case ParseNodeKind::PNK_CONDITIONAL:
+      case ParseNodeKind::PNK_TYPEOFNAME:
+      case ParseNodeKind::PNK_TYPEOFEXPR:
+      case ParseNodeKind::PNK_AWAIT:
+      case ParseNodeKind::PNK_VOID:
+      case ParseNodeKind::PNK_NOT:
+      case ParseNodeKind::PNK_BITNOT:
+      case ParseNodeKind::PNK_DELETENAME:
+      case ParseNodeKind::PNK_DELETEPROP:
+      case ParseNodeKind::PNK_DELETEELEM:
+      case ParseNodeKind::PNK_DELETEEXPR:
+      case ParseNodeKind::PNK_POS:
+      case ParseNodeKind::PNK_NEG:
+      case ParseNodeKind::PNK_PREINCREMENT:
+      case ParseNodeKind::PNK_POSTINCREMENT:
+      case ParseNodeKind::PNK_PREDECREMENT:
+      case ParseNodeKind::PNK_POSTDECREMENT:
+      case ParseNodeKind::PNK_OR:
+      case ParseNodeKind::PNK_AND:
+      case ParseNodeKind::PNK_BITOR:
+      case ParseNodeKind::PNK_BITXOR:
+      case ParseNodeKind::PNK_BITAND:
+      case ParseNodeKind::PNK_STRICTEQ:
+      case ParseNodeKind::PNK_EQ:
+      case ParseNodeKind::PNK_STRICTNE:
+      case ParseNodeKind::PNK_NE:
+      case ParseNodeKind::PNK_LT:
+      case ParseNodeKind::PNK_LE:
+      case ParseNodeKind::PNK_GT:
+      case ParseNodeKind::PNK_GE:
+      case ParseNodeKind::PNK_INSTANCEOF:
+      case ParseNodeKind::PNK_IN:
+      case ParseNodeKind::PNK_LSH:
+      case ParseNodeKind::PNK_RSH:
+      case ParseNodeKind::PNK_URSH:
+      case ParseNodeKind::PNK_ADD:
+      case ParseNodeKind::PNK_SUB:
+      case ParseNodeKind::PNK_STAR:
+      case ParseNodeKind::PNK_DIV:
+      case ParseNodeKind::PNK_MOD:
+      case ParseNodeKind::PNK_POW:
+      case ParseNodeKind::PNK_ASSIGN:
+      case ParseNodeKind::PNK_ADDASSIGN:
+      case ParseNodeKind::PNK_SUBASSIGN:
+      case ParseNodeKind::PNK_BITORASSIGN:
+      case ParseNodeKind::PNK_BITXORASSIGN:
+      case ParseNodeKind::PNK_BITANDASSIGN:
+      case ParseNodeKind::PNK_LSHASSIGN:
+      case ParseNodeKind::PNK_RSHASSIGN:
+      case ParseNodeKind::PNK_URSHASSIGN:
+      case ParseNodeKind::PNK_MULASSIGN:
+      case ParseNodeKind::PNK_DIVASSIGN:
+      case ParseNodeKind::PNK_MODASSIGN:
+      case ParseNodeKind::PNK_POWASSIGN:
+      case ParseNodeKind::PNK_COMMA:
+      case ParseNodeKind::PNK_ARRAY:
+      case ParseNodeKind::PNK_OBJECT:
+      case ParseNodeKind::PNK_DOT:
+      case ParseNodeKind::PNK_ELEM:
+      case ParseNodeKind::PNK_CALL:
+      case ParseNodeKind::PNK_NAME:
+      case ParseNodeKind::PNK_TEMPLATE_STRING:
+      case ParseNodeKind::PNK_TEMPLATE_STRING_LIST:
+      case ParseNodeKind::PNK_TAGGED_TEMPLATE:
+      case ParseNodeKind::PNK_CALLSITEOBJ:
+      case ParseNodeKind::PNK_STRING:
+      case ParseNodeKind::PNK_REGEXP:
+      case ParseNodeKind::PNK_TRUE:
+      case ParseNodeKind::PNK_FALSE:
+      case ParseNodeKind::PNK_NULL:
+      case ParseNodeKind::PNK_RAW_UNDEFINED:
+      case ParseNodeKind::PNK_THIS:
+      case ParseNodeKind::PNK_ELISION:
+      case ParseNodeKind::PNK_NUMBER:
+      case ParseNodeKind::PNK_NEW:
+      case ParseNodeKind::PNK_GENERATOR:
+      case ParseNodeKind::PNK_PARAMSBODY:
+      case ParseNodeKind::PNK_CATCH:
+      case ParseNodeKind::PNK_FORIN:
+      case ParseNodeKind::PNK_FOROF:
+      case ParseNodeKind::PNK_FORHEAD:
+      case ParseNodeKind::PNK_CLASSMETHOD:
+      case ParseNodeKind::PNK_CLASSMETHODLIST:
+      case ParseNodeKind::PNK_CLASSNAMES:
+      case ParseNodeKind::PNK_NEWTARGET:
+      case ParseNodeKind::PNK_POSHOLDER:
+      case ParseNodeKind::PNK_SUPERCALL:
+      case ParseNodeKind::PNK_SUPERBASE:
+      case ParseNodeKind::PNK_SETTHIS:
         MOZ_CRASH("ContainsHoistedDeclaration should have indicated false on "
                   "some parent node without recurring to test this node");
 
-      case PNK_PIPELINE:
+      case ParseNodeKind::PNK_PIPELINE:
         MOZ_ASSERT(node->isArity(PN_LIST));
         *result = false;
         return true;
 
-      case PNK_LIMIT: // invalid sentinel value
-        MOZ_CRASH("unexpected PNK_LIMIT in node");
+      case ParseNodeKind::PNK_LIMIT: // invalid sentinel value
+        MOZ_CRASH("unexpected ParseNodeKind::PNK_LIMIT in node");
     }
 
     MOZ_CRASH("invalid node kind");
 }
 
 /*
  * Fold from one constant type to another.
  * XXX handles only strings and numbers for now
  */
 static bool
 FoldType(JSContext* cx, ParseNode* pn, ParseNodeKind kind)
 {
     if (!pn->isKind(kind)) {
         switch (kind) {
-          case PNK_NUMBER:
-            if (pn->isKind(PNK_STRING)) {
+          case ParseNodeKind::PNK_NUMBER:
+            if (pn->isKind(ParseNodeKind::PNK_STRING)) {
                 double d;
                 if (!StringToNumber(cx, pn->pn_atom, &d))
                     return false;
                 pn->pn_dval = d;
-                pn->setKind(PNK_NUMBER);
+                pn->setKind(ParseNodeKind::PNK_NUMBER);
                 pn->setOp(JSOP_DOUBLE);
             }
             break;
 
-          case PNK_STRING:
-            if (pn->isKind(PNK_NUMBER)) {
+          case ParseNodeKind::PNK_STRING:
+            if (pn->isKind(ParseNodeKind::PNK_NUMBER)) {
                 pn->pn_atom = NumberToAtom(cx, pn->pn_dval);
                 if (!pn->pn_atom)
                     return false;
-                pn->setKind(PNK_STRING);
+                pn->setKind(ParseNodeKind::PNK_STRING);
                 pn->setOp(JSOP_STRING);
             }
             break;
 
           default:;
         }
     }
     return true;
@@ -440,58 +441,58 @@ ReplaceNode(ParseNode** pnp, ParseNode* 
 {
     pn->pn_next = (*pnp)->pn_next;
     *pnp = pn;
 }
 
 static bool
 IsEffectless(ParseNode* node)
 {
-    return node->isKind(PNK_TRUE) ||
-           node->isKind(PNK_FALSE) ||
-           node->isKind(PNK_STRING) ||
-           node->isKind(PNK_TEMPLATE_STRING) ||
-           node->isKind(PNK_NUMBER) ||
-           node->isKind(PNK_NULL) ||
-           node->isKind(PNK_RAW_UNDEFINED) ||
-           node->isKind(PNK_FUNCTION);
+    return node->isKind(ParseNodeKind::PNK_TRUE) ||
+           node->isKind(ParseNodeKind::PNK_FALSE) ||
+           node->isKind(ParseNodeKind::PNK_STRING) ||
+           node->isKind(ParseNodeKind::PNK_TEMPLATE_STRING) ||
+           node->isKind(ParseNodeKind::PNK_NUMBER) ||
+           node->isKind(ParseNodeKind::PNK_NULL) ||
+           node->isKind(ParseNodeKind::PNK_RAW_UNDEFINED) ||
+           node->isKind(ParseNodeKind::PNK_FUNCTION);
 }
 
 enum Truthiness { Truthy, Falsy, Unknown };
 
 static Truthiness
 Boolish(ParseNode* pn)
 {
     switch (pn->getKind()) {
-      case PNK_NUMBER:
+      case ParseNodeKind::PNK_NUMBER:
         return (pn->pn_dval != 0 && !IsNaN(pn->pn_dval)) ? Truthy : Falsy;
 
-      case PNK_STRING:
-      case PNK_TEMPLATE_STRING:
+      case ParseNodeKind::PNK_STRING:
+      case ParseNodeKind::PNK_TEMPLATE_STRING:
         return (pn->pn_atom->length() > 0) ? Truthy : Falsy;
 
-      case PNK_TRUE:
-      case PNK_FUNCTION:
+      case ParseNodeKind::PNK_TRUE:
+      case ParseNodeKind::PNK_FUNCTION:
         return Truthy;
 
-      case PNK_FALSE:
-      case PNK_NULL:
-      case PNK_RAW_UNDEFINED:
+      case ParseNodeKind::PNK_FALSE:
+      case ParseNodeKind::PNK_NULL:
+      case ParseNodeKind::PNK_RAW_UNDEFINED:
         return Falsy;
 
-      case PNK_VOID: {
+      case ParseNodeKind::PNK_VOID: {
         // |void <foo>| evaluates to |undefined| which isn't truthy.  But the
         // sense of this method requires that the expression be literally
         // replaceable with true/false: not the case if the nested expression
         // is effectful, might throw, &c.  Walk past the |void| (and nested
         // |void| expressions, for good measure) and check that the nested
         // expression doesn't break this requirement before indicating falsity.
         do {
             pn = pn->pn_kid;
-        } while (pn->isKind(PNK_VOID));
+        } while (pn->isKind(ParseNodeKind::PNK_VOID));
 
         return IsEffectless(pn) ? Falsy : Unknown;
       }
 
       default:
         return Unknown;
     }
 }
@@ -513,117 +514,117 @@ FoldCondition(JSContext* cx, ParseNode**
     if (t != Unknown) {
         // We can turn function nodes into constant nodes here, but mutating
         // function nodes is tricky --- in particular, mutating a function node
         // that appears on a method list corrupts the method list. However,
         // methods are M's in statements of the form 'this.foo = M;', which we
         // never fold, so we're okay.
         parser.prepareNodeForMutation(node);
         if (t == Truthy) {
-            node->setKind(PNK_TRUE);
+            node->setKind(ParseNodeKind::PNK_TRUE);
             node->setOp(JSOP_TRUE);
         } else {
-            node->setKind(PNK_FALSE);
+            node->setKind(ParseNodeKind::PNK_FALSE);
             node->setOp(JSOP_FALSE);
         }
         node->setArity(PN_NULLARY);
     }
 
     return true;
 }
 
 static bool
 FoldTypeOfExpr(JSContext* cx, ParseNode* node, GeneralParser<FullParseHandler, char16_t>& parser)
 {
-    MOZ_ASSERT(node->isKind(PNK_TYPEOFEXPR));
+    MOZ_ASSERT(node->isKind(ParseNodeKind::PNK_TYPEOFEXPR));
     MOZ_ASSERT(node->isArity(PN_UNARY));
 
     ParseNode*& expr = node->pn_kid;
     if (!Fold(cx, &expr, parser))
         return false;
 
     // Constant-fold the entire |typeof| if given a constant with known type.
     RootedPropertyName result(cx);
-    if (expr->isKind(PNK_STRING) || expr->isKind(PNK_TEMPLATE_STRING))
+    if (expr->isKind(ParseNodeKind::PNK_STRING) || expr->isKind(ParseNodeKind::PNK_TEMPLATE_STRING))
         result = cx->names().string;
-    else if (expr->isKind(PNK_NUMBER))
+    else if (expr->isKind(ParseNodeKind::PNK_NUMBER))
         result = cx->names().number;
-    else if (expr->isKind(PNK_NULL))
+    else if (expr->isKind(ParseNodeKind::PNK_NULL))
         result = cx->names().object;
-    else if (expr->isKind(PNK_TRUE) || expr->isKind(PNK_FALSE))
+    else if (expr->isKind(ParseNodeKind::PNK_TRUE) || expr->isKind(ParseNodeKind::PNK_FALSE))
         result = cx->names().boolean;
-    else if (expr->isKind(PNK_FUNCTION))
+    else if (expr->isKind(ParseNodeKind::PNK_FUNCTION))
         result = cx->names().function;
 
     if (result) {
         parser.prepareNodeForMutation(node);
 
-        node->setKind(PNK_STRING);
+        node->setKind(ParseNodeKind::PNK_STRING);
         node->setArity(PN_NULLARY);
         node->setOp(JSOP_NOP);
         node->pn_atom = result;
     }
 
     return true;
 }
 
 static bool
 FoldDeleteExpr(JSContext* cx, ParseNode* node, GeneralParser<FullParseHandler, char16_t>& parser)
 {
-    MOZ_ASSERT(node->isKind(PNK_DELETEEXPR));
+    MOZ_ASSERT(node->isKind(ParseNodeKind::PNK_DELETEEXPR));
     MOZ_ASSERT(node->isArity(PN_UNARY));
 
     ParseNode*& expr = node->pn_kid;
     if (!Fold(cx, &expr, parser))
         return false;
 
     // Expression deletion evaluates the expression, then evaluates to true.
     // For effectless expressions, eliminate the expression evaluation.
     if (IsEffectless(expr)) {
         parser.prepareNodeForMutation(node);
-        node->setKind(PNK_TRUE);
+        node->setKind(ParseNodeKind::PNK_TRUE);
         node->setArity(PN_NULLARY);
         node->setOp(JSOP_TRUE);
     }
 
     return true;
 }
 
 static bool
 FoldDeleteElement(JSContext* cx, ParseNode* node,
                   GeneralParser<FullParseHandler, char16_t>& parser)
 {
-    MOZ_ASSERT(node->isKind(PNK_DELETEELEM));
+    MOZ_ASSERT(node->isKind(ParseNodeKind::PNK_DELETEELEM));
     MOZ_ASSERT(node->isArity(PN_UNARY));
-    MOZ_ASSERT(node->pn_kid->isKind(PNK_ELEM));
+    MOZ_ASSERT(node->pn_kid->isKind(ParseNodeKind::PNK_ELEM));
 
     ParseNode*& expr = node->pn_kid;
     if (!Fold(cx, &expr, parser))
         return false;
 
     // If we're deleting an element, but constant-folding converted our
     // element reference into a dotted property access, we must *also*
     // morph the node's kind.
     //
     // In principle this also applies to |super["foo"] -> super.foo|,
     // but we don't constant-fold |super["foo"]| yet.
-    MOZ_ASSERT(expr->isKind(PNK_ELEM) || expr->isKind(PNK_DOT));
-    if (expr->isKind(PNK_DOT))
-        node->setKind(PNK_DELETEPROP);
+    MOZ_ASSERT(expr->isKind(ParseNodeKind::PNK_ELEM) || expr->isKind(ParseNodeKind::PNK_DOT));
+    if (expr->isKind(ParseNodeKind::PNK_DOT))
+        node->setKind(ParseNodeKind::PNK_DELETEPROP);
 
     return true;
 }
 
 static bool
 FoldDeleteProperty(JSContext* cx, ParseNode* node,
                    GeneralParser<FullParseHandler, char16_t>& parser)
 {
-    MOZ_ASSERT(node->isKind(PNK_DELETEPROP));
+    MOZ_ASSERT(node->isKind(ParseNodeKind::PNK_DELETEPROP));
     MOZ_ASSERT(node->isArity(PN_UNARY));
-    MOZ_ASSERT(node->pn_kid->isKind(PNK_DOT));
+    MOZ_ASSERT(node->pn_kid->isKind(ParseNodeKind::PNK_DOT));
 
     ParseNode*& expr = node->pn_kid;
 #ifdef DEBUG
     ParseNodeKind oldKind = expr->getKind();
 #endif
 
     if (!Fold(cx, &expr, parser))
         return false;
@@ -632,89 +633,94 @@ FoldDeleteProperty(JSContext* cx, ParseN
                "kind should have remained invariant under folding");
 
     return true;
 }
 
 static bool
 FoldNot(JSContext* cx, ParseNode* node, GeneralParser<FullParseHandler, char16_t>& parser)
 {
-    MOZ_ASSERT(node->isKind(PNK_NOT));
+    MOZ_ASSERT(node->isKind(ParseNodeKind::PNK_NOT));
     MOZ_ASSERT(node->isArity(PN_UNARY));
 
     ParseNode*& expr = node->pn_kid;
     if (!FoldCondition(cx, &expr, parser))
         return false;
 
-    if (expr->isKind(PNK_NUMBER)) {
+    if (expr->isKind(ParseNodeKind::PNK_NUMBER)) {
         double d = expr->pn_dval;
 
         parser.prepareNodeForMutation(node);
         if (d == 0 || IsNaN(d)) {
-            node->setKind(PNK_TRUE);
+            node->setKind(ParseNodeKind::PNK_TRUE);
             node->setOp(JSOP_TRUE);
         } else {
-            node->setKind(PNK_FALSE);
+            node->setKind(ParseNodeKind::PNK_FALSE);
             node->setOp(JSOP_FALSE);
         }
         node->setArity(PN_NULLARY);
-    } else if (expr->isKind(PNK_TRUE) || expr->isKind(PNK_FALSE)) {
-        bool newval = !expr->isKind(PNK_TRUE);
+    } else if (expr->isKind(ParseNodeKind::PNK_TRUE) || expr->isKind(ParseNodeKind::PNK_FALSE)) {
+        bool newval = !expr->isKind(ParseNodeKind::PNK_TRUE);
 
         parser.prepareNodeForMutation(node);
-        node->setKind(newval ? PNK_TRUE : PNK_FALSE);
+        node->setKind(newval ? ParseNodeKind::PNK_TRUE : ParseNodeKind::PNK_FALSE);
         node->setArity(PN_NULLARY);
         node->setOp(newval ? JSOP_TRUE : JSOP_FALSE);
     }
 
     return true;
 }
 
 static bool
 FoldUnaryArithmetic(JSContext* cx, ParseNode* node,
                     GeneralParser<FullParseHandler, char16_t>& parser)
 {
-    MOZ_ASSERT(node->isKind(PNK_BITNOT) || node->isKind(PNK_POS) || node->isKind(PNK_NEG),
+    MOZ_ASSERT(node->isKind(ParseNodeKind::PNK_BITNOT) ||
+               node->isKind(ParseNodeKind::PNK_POS) ||
+               node->isKind(ParseNodeKind::PNK_NEG),
                "need a different method for this node kind");
     MOZ_ASSERT(node->isArity(PN_UNARY));
 
     ParseNode*& expr = node->pn_kid;
     if (!Fold(cx, &expr, parser))
         return false;
 
-    if (expr->isKind(PNK_NUMBER) || expr->isKind(PNK_TRUE) || expr->isKind(PNK_FALSE)) {
-        double d = expr->isKind(PNK_NUMBER)
+    if (expr->isKind(ParseNodeKind::PNK_NUMBER) ||
+        expr->isKind(ParseNodeKind::PNK_TRUE) ||
+        expr->isKind(ParseNodeKind::PNK_FALSE))
+    {
+        double d = expr->isKind(ParseNodeKind::PNK_NUMBER)
                    ? expr->pn_dval
-                   : double(expr->isKind(PNK_TRUE));
+                   : double(expr->isKind(ParseNodeKind::PNK_TRUE));
 
-        if (node->isKind(PNK_BITNOT))
+        if (node->isKind(ParseNodeKind::PNK_BITNOT))
             d = ~ToInt32(d);
-        else if (node->isKind(PNK_NEG))
+        else if (node->isKind(ParseNodeKind::PNK_NEG))
             d = -d;
         else
-            MOZ_ASSERT(node->isKind(PNK_POS)); // nothing to do
+            MOZ_ASSERT(node->isKind(ParseNodeKind::PNK_POS)); // nothing to do
 
         parser.prepareNodeForMutation(node);
-        node->setKind(PNK_NUMBER);
+        node->setKind(ParseNodeKind::PNK_NUMBER);
         node->setOp(JSOP_DOUBLE);
         node->setArity(PN_NULLARY);
         node->pn_dval = d;
     }
 
     return true;
 }
 
 static bool
 FoldIncrementDecrement(JSContext* cx, ParseNode* node,
                        GeneralParser<FullParseHandler, char16_t>& parser)
 {
-    MOZ_ASSERT(node->isKind(PNK_PREINCREMENT) ||
-               node->isKind(PNK_POSTINCREMENT) ||
-               node->isKind(PNK_PREDECREMENT) ||
-               node->isKind(PNK_POSTDECREMENT));
+    MOZ_ASSERT(node->isKind(ParseNodeKind::PNK_PREINCREMENT) ||
+               node->isKind(ParseNodeKind::PNK_POSTINCREMENT) ||
+               node->isKind(ParseNodeKind::PNK_PREDECREMENT) ||
+               node->isKind(ParseNodeKind::PNK_POSTDECREMENT));
     MOZ_ASSERT(node->isArity(PN_UNARY));
 
     ParseNode*& target = node->pn_kid;
     MOZ_ASSERT(parser.isValidSimpleAssignmentTarget(target, PermitAssignmentToFunctionCalls));
 
     if (!Fold(cx, &target, parser))
         return false;
 
@@ -723,20 +729,20 @@ FoldIncrementDecrement(JSContext* cx, Pa
     return true;
 }
 
 static bool
 FoldAndOr(JSContext* cx, ParseNode** nodePtr, GeneralParser<FullParseHandler, char16_t>& parser)
 {
     ParseNode* node = *nodePtr;
 
-    MOZ_ASSERT(node->isKind(PNK_AND) || node->isKind(PNK_OR));
+    MOZ_ASSERT(node->isKind(ParseNodeKind::PNK_AND) || node->isKind(ParseNodeKind::PNK_OR));
     MOZ_ASSERT(node->isArity(PN_LIST));
 
-    bool isOrNode = node->isKind(PNK_OR);
+    bool isOrNode = node->isKind(ParseNodeKind::PNK_OR);
     ParseNode** elem = &node->pn_head;
     do {
         if (!Fold(cx, elem, parser))
             return false;
 
         Truthiness t = Boolish(*elem);
 
         // If we don't know the constant-folded node's truthiness, we can't
@@ -792,17 +798,17 @@ FoldAndOr(JSContext* cx, ParseNode** nod
     node->checkListConsistency();
 
     // If we removed nodes, we may have to replace a one-element list with
     // its element.
     if (node->pn_count == 1) {
         ParseNode* first = node->pn_head;
         ReplaceNode(nodePtr, first);
 
-        node->setKind(PNK_NULL);
+        node->setKind(ParseNodeKind::PNK_NULL);
         node->setArity(PN_NULLARY);
         parser.freeTree(node);
     }
 
     return true;
 }
 
 static bool
@@ -814,17 +820,17 @@ FoldConditional(JSContext* cx, ParseNode
     do {
         // |nextNode| on entry points to the C?T:F expression to be folded.
         // Reset it to exit the loop in the common case where F isn't another
         // ?: expression.
         nodePtr = nextNode;
         nextNode = nullptr;
 
         ParseNode* node = *nodePtr;
-        MOZ_ASSERT(node->isKind(PNK_CONDITIONAL));
+        MOZ_ASSERT(node->isKind(ParseNodeKind::PNK_CONDITIONAL));
         MOZ_ASSERT(node->isArity(PN_TERNARY));
 
         ParseNode*& expr = node->pn_kid1;
         if (!FoldCondition(cx, &expr, parser))
             return false;
 
         ParseNode*& ifTruthy = node->pn_kid2;
         if (!Fold(cx, &ifTruthy, parser))
@@ -834,17 +840,17 @@ FoldConditional(JSContext* cx, ParseNode
 
         // If our C?T:F node has F as another ?: node, *iteratively* constant-
         // fold F *after* folding C and T (and possibly eliminating C and one
         // of T/F entirely); otherwise fold F normally.  Making |nextNode| non-
         // null causes this loop to run again to fold F.
         //
         // Conceivably we could instead/also iteratively constant-fold T, if T
         // were more complex than F.  Such an optimization is unimplemented.
-        if (ifFalsy->isKind(PNK_CONDITIONAL)) {
+        if (ifFalsy->isKind(ParseNodeKind::PNK_CONDITIONAL)) {
             nextNode = &ifFalsy;
         } else {
             if (!Fold(cx, &ifFalsy, parser))
                 return false;
         }
 
         // Try to constant-fold based on the condition expression.
         Truthiness t = Boolish(expr);
@@ -882,17 +888,17 @@ FoldIf(JSContext* cx, ParseNode** nodePt
 
     do {
         // |nextNode| on entry points to the initial |if| to be folded.  Reset
         // it to exit the loop when the |else| arm isn't another |if|.
         nodePtr = nextNode;
         nextNode = nullptr;
 
         ParseNode* node = *nodePtr;
-        MOZ_ASSERT(node->isKind(PNK_IF));
+        MOZ_ASSERT(node->isKind(ParseNodeKind::PNK_IF));
         MOZ_ASSERT(node->isArity(PN_TERNARY));
 
         ParseNode*& expr = node->pn_kid1;
         if (!FoldCondition(cx, &expr, parser))
             return false;
 
         ParseNode*& consequent = node->pn_kid2;
         if (!Fold(cx, &consequent, parser))
@@ -900,17 +906,17 @@ FoldIf(JSContext* cx, ParseNode** nodePt
 
         ParseNode*& alternative = node->pn_kid3;
         if (alternative) {
             // If in |if (C) T; else F;| we have |F| as another |if|,
             // *iteratively* constant-fold |F| *after* folding |C| and |T| (and
             // possibly completely replacing the whole thing with |T| or |F|);
             // otherwise fold F normally.  Making |nextNode| non-null causes
             // this loop to run again to fold F.
-            if (alternative->isKind(PNK_IF)) {
+            if (alternative->isKind(ParseNodeKind::PNK_IF)) {
                 nextNode = &alternative;
             } else {
                 if (!Fold(cx, &alternative, parser))
                     return false;
             }
         }
 
         // Eliminate the consequent or alternative if the condition has
@@ -945,46 +951,46 @@ FoldIf(JSContext* cx, ParseNode** nodePt
         if (!performReplacement)
             continue;
 
         if (!replacement) {
             // If there's no replacement node, we have a constantly-false |if|
             // with no |else|.  Replace the entire thing with an empty
             // statement list.
             parser.prepareNodeForMutation(node);
-            node->setKind(PNK_STATEMENTLIST);
+            node->setKind(ParseNodeKind::PNK_STATEMENTLIST);
             node->setArity(PN_LIST);
             node->makeEmpty();
         } else {
             // Replacement invalidates |nextNode|, so reset it (if the
             // replacement requires folding) or clear it (if |alternative|
             // is dead code) as needed.
             if (nextNode)
                 nextNode = (*nextNode == replacement) ? nodePtr : nullptr;
             ReplaceNode(nodePtr, replacement);
 
             // Morph the original node into a discardable node, then
             // aggressively free it and the discarded arm (if any) to suss out
             // any bugs in the preceding logic.
-            node->setKind(PNK_STATEMENTLIST);
+            node->setKind(ParseNodeKind::PNK_STATEMENTLIST);
             node->setArity(PN_LIST);
             node->makeEmpty();
             if (discarded)
                 node->append(discarded);
             parser.freeTree(node);
         }
     } while (nextNode);
 
     return true;
 }
 
 static bool
 FoldFunction(JSContext* cx, ParseNode* node, GeneralParser<FullParseHandler, char16_t>& parser)
 {
-    MOZ_ASSERT(node->isKind(PNK_FUNCTION));
+    MOZ_ASSERT(node->isKind(ParseNodeKind::PNK_FUNCTION));
     MOZ_ASSERT(node->isArity(PN_CODE));
 
     // Don't constant-fold inside "use asm" code, as this could create a parse
     // tree that doesn't type-check as asm.js.
     if (node->pn_funbox->useAsmOrInsideUseAsm())
         return true;
 
     // Note: pn_body is null for lazily-parsed functions.
@@ -994,176 +1000,176 @@ FoldFunction(JSContext* cx, ParseNode* n
     }
 
     return true;
 }
 
 static double
 ComputeBinary(ParseNodeKind kind, double left, double right)
 {
-    if (kind == PNK_ADD)
+    if (kind == ParseNodeKind::PNK_ADD)
         return left + right;
 
-    if (kind == PNK_SUB)
+    if (kind == ParseNodeKind::PNK_SUB)
         return left - right;
 
-    if (kind == PNK_STAR)
+    if (kind == ParseNodeKind::PNK_STAR)
         return left * right;
 
-    if (kind == PNK_MOD)
+    if (kind == ParseNodeKind::PNK_MOD)
         return right == 0 ? GenericNaN() : js_fmod(left, right);
 
-    if (kind == PNK_URSH)
+    if (kind == ParseNodeKind::PNK_URSH)
         return ToUint32(left) >> (ToUint32(right) & 31);
 
-    if (kind == PNK_DIV) {
+    if (kind == ParseNodeKind::PNK_DIV) {
         if (right == 0) {
 #if defined(XP_WIN)
             /* XXX MSVC miscompiles such that (NaN == 0) */
             if (IsNaN(right))
                 return GenericNaN();
 #endif
             if (left == 0 || IsNaN(left))
                 return GenericNaN();
             if (IsNegative(left) != IsNegative(right))
                 return NegativeInfinity<double>();
             return PositiveInfinity<double>();
         }
 
         return left / right;
     }
 
-    MOZ_ASSERT(kind == PNK_LSH || kind == PNK_RSH);
+    MOZ_ASSERT(kind == ParseNodeKind::PNK_LSH || kind == ParseNodeKind::PNK_RSH);
 
     int32_t i = ToInt32(left);
     uint32_t j = ToUint32(right) & 31;
-    return int32_t((kind == PNK_LSH) ? uint32_t(i) << j : i >> j);
+    return int32_t((kind == ParseNodeKind::PNK_LSH) ? uint32_t(i) << j : i >> j);
 }
 
 static bool
 FoldModule(JSContext* cx, ParseNode* node, GeneralParser<FullParseHandler, char16_t>& parser)
 {
-    MOZ_ASSERT(node->isKind(PNK_MODULE));
+    MOZ_ASSERT(node->isKind(ParseNodeKind::PNK_MODULE));
     MOZ_ASSERT(node->isArity(PN_CODE));
 
     ParseNode*& moduleBody = node->pn_body;
     MOZ_ASSERT(moduleBody);
     return Fold(cx, &moduleBody, parser);
 }
 
 static bool
 FoldBinaryArithmetic(JSContext* cx, ParseNode* node,
                      GeneralParser<FullParseHandler, char16_t>& parser)
 {
-    MOZ_ASSERT(node->isKind(PNK_SUB) ||
-               node->isKind(PNK_STAR) ||
-               node->isKind(PNK_LSH) ||
-               node->isKind(PNK_RSH) ||
-               node->isKind(PNK_URSH) ||
-               node->isKind(PNK_DIV) ||
-               node->isKind(PNK_MOD));
+    MOZ_ASSERT(node->isKind(ParseNodeKind::PNK_SUB) ||
+               node->isKind(ParseNodeKind::PNK_STAR) ||
+               node->isKind(ParseNodeKind::PNK_LSH) ||
+               node->isKind(ParseNodeKind::PNK_RSH) ||
+               node->isKind(ParseNodeKind::PNK_URSH) ||
+               node->isKind(ParseNodeKind::PNK_DIV) ||
+               node->isKind(ParseNodeKind::PNK_MOD));
     MOZ_ASSERT(node->isArity(PN_LIST));
     MOZ_ASSERT(node->pn_count >= 2);
 
     // Fold each operand, ideally into a number.
     ParseNode** listp = &node->pn_head;
     for (; *listp; listp = &(*listp)->pn_next) {
         if (!Fold(cx, listp, parser))
             return false;
 
-        if (!FoldType(cx, *listp, PNK_NUMBER))
+        if (!FoldType(cx, *listp, ParseNodeKind::PNK_NUMBER))
             return false;
     }
 
     // Repoint the list's tail pointer.
     node->pn_tail = listp;
 
     // Now fold all leading numeric terms together into a single number.
     // (Trailing terms for the non-shift operations can't be folded together
     // due to floating point imprecision.  For example, if |x === -2**53|,
     // |x - 1 - 1 === -2**53| but |x - 2 === -2**53 - 2|.  Shifts could be
     // folded, but it doesn't seem worth the effort.)
     ParseNode* elem = node->pn_head;
     ParseNode* next = elem->pn_next;
-    if (elem->isKind(PNK_NUMBER)) {
+    if (elem->isKind(ParseNodeKind::PNK_NUMBER)) {
         ParseNodeKind kind = node->getKind();
         while (true) {
-            if (!next || !next->isKind(PNK_NUMBER))
+            if (!next || !next->isKind(ParseNodeKind::PNK_NUMBER))
                 break;
 
             double d = ComputeBinary(kind, elem->pn_dval, next->pn_dval);
 
             ParseNode* afterNext = next->pn_next;
             parser.freeTree(next);
             next = afterNext;
             elem->pn_next = next;
 
-            elem->setKind(PNK_NUMBER);
+            elem->setKind(ParseNodeKind::PNK_NUMBER);
             elem->setOp(JSOP_DOUBLE);
             elem->setArity(PN_NULLARY);
             elem->pn_dval = d;
 
             node->pn_count--;
         }
 
         if (node->pn_count == 1) {
             MOZ_ASSERT(node->pn_head == elem);
-            MOZ_ASSERT(elem->isKind(PNK_NUMBER));
+            MOZ_ASSERT(elem->isKind(ParseNodeKind::PNK_NUMBER));
 
             double d = elem->pn_dval;
-            node->setKind(PNK_NUMBER);
+            node->setKind(ParseNodeKind::PNK_NUMBER);
             node->setArity(PN_NULLARY);
             node->setOp(JSOP_DOUBLE);
             node->pn_dval = d;
 
             parser.freeTree(elem);
         }
     }
 
     return true;
 }
 
 static bool
 FoldExponentiation(JSContext* cx, ParseNode* node,
                    GeneralParser<FullParseHandler, char16_t>& parser)
 {
-    MOZ_ASSERT(node->isKind(PNK_POW));
+    MOZ_ASSERT(node->isKind(ParseNodeKind::PNK_POW));
     MOZ_ASSERT(node->isArity(PN_LIST));
     MOZ_ASSERT(node->pn_count >= 2);
 
     // Fold each operand, ideally into a number.
     ParseNode** listp = &node->pn_head;
     for (; *listp; listp = &(*listp)->pn_next) {
         if (!Fold(cx, listp, parser))
             return false;
 
-        if (!FoldType(cx, *listp, PNK_NUMBER))
+        if (!FoldType(cx, *listp, ParseNodeKind::PNK_NUMBER))
             return false;
     }
 
     // Repoint the list's tail pointer.
     node->pn_tail = listp;
 
     // Unlike all other binary arithmetic operators, ** is right-associative:
     // 2**3**5 is 2**(3**5), not (2**3)**5.  As list nodes singly-link their
     // children, full constant-folding requires either linear space or dodgy
     // in-place linked list reversal.  So we only fold one exponentiation: it's
     // easy and addresses common cases like |2**32|.
     if (node->pn_count > 2)
         return true;
 
     ParseNode* base = node->pn_head;
     ParseNode* exponent = base->pn_next;
-    if (!base->isKind(PNK_NUMBER) || !exponent->isKind(PNK_NUMBER))
+    if (!base->isKind(ParseNodeKind::PNK_NUMBER) || !exponent->isKind(ParseNodeKind::PNK_NUMBER))
         return true;
 
     double d1 = base->pn_dval, d2 = exponent->pn_dval;
 
     parser.prepareNodeForMutation(node);
-    node->setKind(PNK_NUMBER);
+    node->setKind(ParseNodeKind::PNK_NUMBER);
     node->setArity(PN_NULLARY);
     node->setOp(JSOP_DOUBLE);
     node->pn_dval = ecmaPow(d1, d2);
     return true;
 }
 
 static bool
 FoldList(JSContext* cx, ParseNode* list, GeneralParser<FullParseHandler, char16_t>& parser)
@@ -1182,31 +1188,31 @@ FoldList(JSContext* cx, ParseNode* list,
     list->checkListConsistency();
 
     return true;
 }
 
 static bool
 FoldReturn(JSContext* cx, ParseNode* node, GeneralParser<FullParseHandler, char16_t>& parser)
 {
-    MOZ_ASSERT(node->isKind(PNK_RETURN));
+    MOZ_ASSERT(node->isKind(ParseNodeKind::PNK_RETURN));
     MOZ_ASSERT(node->isArity(PN_UNARY));
 
     if (ParseNode*& expr = node->pn_kid) {
         if (!Fold(cx, &expr, parser))
             return false;
     }
 
     return true;
 }
 
 static bool
 FoldTry(JSContext* cx, ParseNode* node, GeneralParser<FullParseHandler, char16_t>& parser)
 {
-    MOZ_ASSERT(node->isKind(PNK_TRY));
+    MOZ_ASSERT(node->isKind(ParseNodeKind::PNK_TRY));
     MOZ_ASSERT(node->isArity(PN_TERNARY));
 
     ParseNode*& statements = node->pn_kid1;
     if (!Fold(cx, &statements, parser))
         return false;
 
     if (ParseNode*& catchScope = node->pn_kid2) {
         if (!Fold(cx, &catchScope, parser))
@@ -1219,17 +1225,17 @@ FoldTry(JSContext* cx, ParseNode* node, 
     }
 
     return true;
 }
 
 static bool
 FoldCatch(JSContext* cx, ParseNode* node, GeneralParser<FullParseHandler, char16_t>& parser)
 {
-    MOZ_ASSERT(node->isKind(PNK_CATCH));
+    MOZ_ASSERT(node->isKind(ParseNodeKind::PNK_CATCH));
     MOZ_ASSERT(node->isArity(PN_BINARY));
 
     if (ParseNode*& declPattern = node->pn_left) {
         if (!Fold(cx, &declPattern, parser))
             return false;
     }
 
     if (ParseNode*& statements = node->pn_right) {
@@ -1238,17 +1244,17 @@ FoldCatch(JSContext* cx, ParseNode* node
     }
 
     return true;
 }
 
 static bool
 FoldClass(JSContext* cx, ParseNode* node, GeneralParser<FullParseHandler, char16_t>& parser)
 {
-    MOZ_ASSERT(node->isKind(PNK_CLASS));
+    MOZ_ASSERT(node->isKind(ParseNodeKind::PNK_CLASS));
     MOZ_ASSERT(node->isArity(PN_TERNARY));
 
     if (ParseNode*& classNames = node->pn_kid1) {
         if (!Fold(cx, &classNames, parser))
             return false;
     }
 
     if (ParseNode*& heritage = node->pn_kid2) {
@@ -1260,42 +1266,42 @@ FoldClass(JSContext* cx, ParseNode* node
     return Fold(cx, &body, parser);
 }
 
 static bool
 FoldElement(JSContext* cx, ParseNode** nodePtr, GeneralParser<FullParseHandler, char16_t>& parser)
 {
     ParseNode* node = *nodePtr;
 
-    MOZ_ASSERT(node->isKind(PNK_ELEM));
+    MOZ_ASSERT(node->isKind(ParseNodeKind::PNK_ELEM));
     MOZ_ASSERT(node->isArity(PN_BINARY));
 
     ParseNode*& expr = node->pn_left;
     if (!Fold(cx, &expr, parser))
         return false;
 
     ParseNode*& key = node->pn_right;
     if (!Fold(cx, &key, parser))
         return false;
 
     PropertyName* name = nullptr;
-    if (key->isKind(PNK_STRING)) {
+    if (key->isKind(ParseNodeKind::PNK_STRING)) {
         JSAtom* atom = key->pn_atom;
         uint32_t index;
 
         if (atom->isIndex(&index)) {
             // Optimization 1: We have something like expr["100"]. This is
             // equivalent to expr[100] which is faster.
-            key->setKind(PNK_NUMBER);
+            key->setKind(ParseNodeKind::PNK_NUMBER);
             key->setOp(JSOP_DOUBLE);
             key->pn_dval = index;
         } else {
             name = atom->asPropertyName();
         }
-    } else if (key->isKind(PNK_NUMBER)) {
+    } else if (key->isKind(ParseNodeKind::PNK_NUMBER)) {
         double number = key->pn_dval;
         if (number != ToUint32(number)) {
             // Optimization 2: We have something like expr[3.14]. The number
             // isn't an array index, so it converts to a string ("3.14"),
             // enabling optimization 3 below.
             JSAtom* atom = ToAtom<NoGC>(cx, DoubleValue(number));
             if (!atom)
                 return false;
@@ -1315,48 +1321,48 @@ FoldElement(JSContext* cx, ParseNode** n
     dottedAccess->setInParens(node->isInParens());
     ReplaceNode(nodePtr, dottedAccess);
 
     // If we've replaced |expr["prop"]| with |expr.prop|, we can now free the
     // |"prop"| and |expr["prop"]| nodes -- but not the |expr| node that we're
     // now using as a sub-node of |dottedAccess|.  Munge |expr["prop"]| into a
     // node with |"prop"| as its only child, that'll pass AST sanity-checking
     // assertions during freeing, then free it.
-    node->setKind(PNK_TYPEOFEXPR);
+    node->setKind(ParseNodeKind::PNK_TYPEOFEXPR);
     node->setArity(PN_UNARY);
     node->pn_kid = key;
     parser.freeTree(node);
 
     return true;
 }
 
 static bool
 FoldAdd(JSContext* cx, ParseNode** nodePtr, GeneralParser<FullParseHandler, char16_t>& parser)
 {
     ParseNode* node = *nodePtr;
 
-    MOZ_ASSERT(node->isKind(PNK_ADD));
+    MOZ_ASSERT(node->isKind(ParseNodeKind::PNK_ADD));
     MOZ_ASSERT(node->isArity(PN_LIST));
     MOZ_ASSERT(node->pn_count >= 2);
 
     // Generically fold all operands first.
     if (!FoldList(cx, node, parser))
         return false;
 
     // Fold leading numeric operands together:
     //
     //   (1 + 2 + x)  becomes  (3 + x)
     //
     // Don't go past the leading operands: additions after a string are
     // string concatenations, not additions: ("1" + 2 + 3 === "123").
     ParseNode* current = node->pn_head;
     ParseNode* next = current->pn_next;
-    if (current->isKind(PNK_NUMBER)) {
+    if (current->isKind(ParseNodeKind::PNK_NUMBER)) {
         do {
-            if (!next->isKind(PNK_NUMBER))
+            if (!next->isKind(ParseNodeKind::PNK_NUMBER))
                 break;
 
             current->pn_dval += next->pn_dval;
             current->pn_next = next->pn_next;
             parser.freeTree(next);
             next = current->pn_next;
 
             MOZ_ASSERT(node->pn_count > 1);
@@ -1367,53 +1373,53 @@ FoldAdd(JSContext* cx, ParseNode** nodeP
     // If any operands remain, attempt string concatenation folding.
     do {
         // If no operands remain, we're done.
         if (!next)
             break;
 
         // (number + string) is string concatenation *only* at the start of
         // the list: (x + 1 + "2" !== x + "12") when x is a number.
-        if (current->isKind(PNK_NUMBER) && next->isKind(PNK_STRING)) {
-            if (!FoldType(cx, current, PNK_STRING))
+        if (current->isKind(ParseNodeKind::PNK_NUMBER) && next->isKind(ParseNodeKind::PNK_STRING)) {
+            if (!FoldType(cx, current, ParseNodeKind::PNK_STRING))
                 return false;
             next = current->pn_next;
         }
 
         // The first string forces all subsequent additions to be
         // string concatenations.
         do {
-            if (current->isKind(PNK_STRING))
+            if (current->isKind(ParseNodeKind::PNK_STRING))
                 break;
 
             current = next;
             next = next->pn_next;
         } while (next);
 
         // If there's nothing left to fold, we're done.
         if (!next)
             break;
 
         RootedString combination(cx);
         RootedString tmp(cx);
         do {
             // Create a rope of the current string and all succeeding
             // constants that we can convert to strings, then atomize it
             // and replace them all with that fresh string.
-            MOZ_ASSERT(current->isKind(PNK_STRING));
+            MOZ_ASSERT(current->isKind(ParseNodeKind::PNK_STRING));
 
             combination = current->pn_atom;
 
             do {
                 // Try folding the next operand to a string.
-                if (!FoldType(cx, next, PNK_STRING))
+                if (!FoldType(cx, next, ParseNodeKind::PNK_STRING))
                     return false;
 
                 // Stop glomming once folding doesn't produce a string.
-                if (!next->isKind(PNK_STRING))
+                if (!next->isKind(ParseNodeKind::PNK_STRING))
                     break;
 
                 // Add this string to the combination and remove the node.
                 tmp = next->pn_atom;
                 combination = ConcatStrings<CanGC>(cx, combination, tmp);
                 if (!combination)
                     return false;
 
@@ -1421,17 +1427,17 @@ FoldAdd(JSContext* cx, ParseNode** nodeP
                 parser.freeTree(next);
                 next = current->pn_next;
 
                 MOZ_ASSERT(node->pn_count > 1);
                 node->pn_count--;
             } while (next);
 
             // Replace |current|'s string with the entire combination.
-            MOZ_ASSERT(current->isKind(PNK_STRING));
+            MOZ_ASSERT(current->isKind(ParseNodeKind::PNK_STRING));
             combination = AtomizeString(cx, combination);
             if (!combination)
                 return false;
             current->pn_atom = &combination->asAtom();
 
 
             // If we're out of nodes, we're done.
             if (!next)
@@ -1445,49 +1451,50 @@ FoldAdd(JSContext* cx, ParseNode** nodeP
             if (!next)
                 break;
 
             // Otherwise find the next node foldable to a string, and loop.
             do {
                 current = next;
                 next = current->pn_next;
 
-                if (!FoldType(cx, current, PNK_STRING))
+                if (!FoldType(cx, current, ParseNodeKind::PNK_STRING))
                     return false;
                 next = current->pn_next;
-            } while (!current->isKind(PNK_STRING) && next);
+            } while (!current->isKind(ParseNodeKind::PNK_STRING) && next);
         } while (next);
     } while (false);
 
     MOZ_ASSERT(!next, "must have considered all nodes here");
     MOZ_ASSERT(!current->pn_next, "current node must be the last node");
 
     node->pn_tail = &current->pn_next;
     node->checkListConsistency();
 
     if (node->pn_count == 1) {
-        // We reduced the list to a constant.  Replace the PNK_ADD node
+        // We reduced the list to a constant.  Replace the ParseNodeKind::PNK_ADD node
         // with that constant.
         ReplaceNode(nodePtr, current);
 
         // Free the old node to aggressively verify nothing uses it.
-        node->setKind(PNK_TRUE);
+        node->setKind(ParseNodeKind::PNK_TRUE);
         node->setArity(PN_NULLARY);
         node->setOp(JSOP_TRUE);
         parser.freeTree(node);
     }
 
     return true;
 }
 
 static bool
 FoldCall(JSContext* cx, ParseNode* node, GeneralParser<FullParseHandler, char16_t>& parser)
 {
-    MOZ_ASSERT(node->isKind(PNK_CALL) || node->isKind(PNK_SUPERCALL) ||
-               node->isKind(PNK_TAGGED_TEMPLATE));
+    MOZ_ASSERT(node->isKind(ParseNodeKind::PNK_CALL) ||
+               node->isKind(ParseNodeKind::PNK_SUPERCALL) ||
+               node->isKind(ParseNodeKind::PNK_TAGGED_TEMPLATE));
     MOZ_ASSERT(node->isArity(PN_LIST));
 
     // Don't fold a parenthesized callable component in an invocation, as this
     // might cause a different |this| value to be used, changing semantics:
     //
     //   var prop = "global";
     //   var obj = { prop: "obj", f: function() { return this.prop; } };
     //   assertEq((true ? obj.f : null)(), "global");
@@ -1510,40 +1517,41 @@ FoldCall(JSContext* cx, ParseNode* node,
 
     node->checkListConsistency();
     return true;
 }
 
 static bool
 FoldForInOrOf(JSContext* cx, ParseNode* node, GeneralParser<FullParseHandler, char16_t>& parser)
 {
-    MOZ_ASSERT(node->isKind(PNK_FORIN) || node->isKind(PNK_FOROF));
+    MOZ_ASSERT(node->isKind(ParseNodeKind::PNK_FORIN) ||
+               node->isKind(ParseNodeKind::PNK_FOROF));
     MOZ_ASSERT(node->isArity(PN_TERNARY));
     MOZ_ASSERT(!node->pn_kid2);
 
     return Fold(cx, &node->pn_kid1, parser) &&
            Fold(cx, &node->pn_kid3, parser);
 }
 
 static bool
 FoldForHead(JSContext* cx, ParseNode* node, GeneralParser<FullParseHandler, char16_t>& parser)
 {
-    MOZ_ASSERT(node->isKind(PNK_FORHEAD));
+    MOZ_ASSERT(node->isKind(ParseNodeKind::PNK_FORHEAD));
     MOZ_ASSERT(node->isArity(PN_TERNARY));
 
     if (ParseNode*& init = node->pn_kid1) {
         if (!Fold(cx, &init, parser))
             return false;
     }
 
     if (ParseNode*& test = node->pn_kid2) {
         if (!FoldCondition(cx, &test, parser))
             return false;
 
-        if (test->isKind(PNK_TRUE)) {
+        if (test->isKind(ParseNodeKind::PNK_TRUE)) {
             parser.freeTree(test);
             test = nullptr;
         }
     }
 
     if (ParseNode*& update = node->pn_kid3) {
         if (!Fold(cx, &update, parser))
             return false;
@@ -1551,34 +1559,34 @@ FoldForHead(JSContext* cx, ParseNode* no
 
     return true;
 }
 
 static bool
 FoldDottedProperty(JSContext* cx, ParseNode* node,
                    GeneralParser<FullParseHandler, char16_t>& parser)
 {
-    MOZ_ASSERT(node->isKind(PNK_DOT));
+    MOZ_ASSERT(node->isKind(ParseNodeKind::PNK_DOT));
     MOZ_ASSERT(node->isArity(PN_NAME));
 
     // 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;
-    while ((*nested)->isKind(PNK_DOT)) {
+    while ((*nested)->isKind(ParseNodeKind::PNK_DOT)) {
         MOZ_ASSERT((*nested)->isArity(PN_NAME));
         nested = &(*nested)->pn_expr;
     }
 
     return Fold(cx, nested, parser);
 }
 
 static bool
 FoldName(JSContext* cx, ParseNode* node, GeneralParser<FullParseHandler, char16_t>& parser)
 {
-    MOZ_ASSERT(node->isKind(PNK_NAME));
+    MOZ_ASSERT(node->isKind(ParseNodeKind::PNK_NAME));
     MOZ_ASSERT(node->isArity(PN_NAME));
 
     if (!node->pn_expr)
         return true;
 
     return Fold(cx, &node->pn_expr, parser);
 }
 
@@ -1586,289 +1594,289 @@ bool
 Fold(JSContext* cx, ParseNode** pnp, GeneralParser<FullParseHandler, char16_t>& parser)
 {
     if (!CheckRecursionLimit(cx))
         return false;
 
     ParseNode* pn = *pnp;
 
     switch (pn->getKind()) {
-      case PNK_NOP:
-      case PNK_REGEXP:
-      case PNK_STRING:
-      case PNK_TRUE:
-      case PNK_FALSE:
-      case PNK_NULL:
-      case PNK_RAW_UNDEFINED:
-      case PNK_ELISION:
-      case PNK_NUMBER:
-      case PNK_DEBUGGER:
-      case PNK_BREAK:
-      case PNK_CONTINUE:
-      case PNK_TEMPLATE_STRING:
-      case PNK_GENERATOR:
-      case PNK_EXPORT_BATCH_SPEC:
-      case PNK_OBJECT_PROPERTY_NAME:
-      case PNK_POSHOLDER:
+      case ParseNodeKind::PNK_NOP:
+      case ParseNodeKind::PNK_REGEXP:
+      case ParseNodeKind::PNK_STRING:
+      case ParseNodeKind::PNK_TRUE:
+      case ParseNodeKind::PNK_FALSE:
+      case ParseNodeKind::PNK_NULL:
+      case ParseNodeKind::PNK_RAW_UNDEFINED:
+      case ParseNodeKind::PNK_ELISION:
+      case ParseNodeKind::PNK_NUMBER:
+      case ParseNodeKind::PNK_DEBUGGER:
+      case ParseNodeKind::PNK_BREAK:
+      case ParseNodeKind::PNK_CONTINUE:
+      case ParseNodeKind::PNK_TEMPLATE_STRING:
+      case ParseNodeKind::PNK_GENERATOR:
+      case ParseNodeKind::PNK_EXPORT_BATCH_SPEC:
+      case ParseNodeKind::PNK_OBJECT_PROPERTY_NAME:
+      case ParseNodeKind::PNK_POSHOLDER:
         MOZ_ASSERT(pn->isArity(PN_NULLARY));
         return true;
 
-      case PNK_SUPERBASE:
-      case PNK_TYPEOFNAME:
+      case ParseNodeKind::PNK_SUPERBASE:
+      case ParseNodeKind::PNK_TYPEOFNAME:
         MOZ_ASSERT(pn->isArity(PN_UNARY));
-        MOZ_ASSERT(pn->pn_kid->isKind(PNK_NAME));
+        MOZ_ASSERT(pn->pn_kid->isKind(ParseNodeKind::PNK_NAME));
         MOZ_ASSERT(!pn->pn_kid->expr());
         return true;
 
-      case PNK_TYPEOFEXPR:
+      case ParseNodeKind::PNK_TYPEOFEXPR:
         return FoldTypeOfExpr(cx, pn, parser);
 
-      case PNK_DELETENAME: {
+      case ParseNodeKind::PNK_DELETENAME: {
         MOZ_ASSERT(pn->isArity(PN_UNARY));
-        MOZ_ASSERT(pn->pn_kid->isKind(PNK_NAME));
+        MOZ_ASSERT(pn->pn_kid->isKind(ParseNodeKind::PNK_NAME));
         return true;
       }
 
-      case PNK_DELETEEXPR:
+      case ParseNodeKind::PNK_DELETEEXPR:
         return FoldDeleteExpr(cx, pn, parser);
 
-      case PNK_DELETEELEM:
+      case ParseNodeKind::PNK_DELETEELEM:
         return FoldDeleteElement(cx, pn, parser);
 
-      case PNK_DELETEPROP:
+      case ParseNodeKind::PNK_DELETEPROP:
         return FoldDeleteProperty(cx, pn, parser);
 
-      case PNK_CONDITIONAL:
+      case ParseNodeKind::PNK_CONDITIONAL:
         return FoldConditional(cx, pnp, parser);
 
-      case PNK_IF:
+      case ParseNodeKind::PNK_IF:
         return FoldIf(cx, pnp, parser);
 
-      case PNK_NOT:
+      case ParseNodeKind::PNK_NOT:
         return FoldNot(cx, pn, parser);
 
-      case PNK_BITNOT:
-      case PNK_POS:
-      case PNK_NEG:
+      case ParseNodeKind::PNK_BITNOT:
+      case ParseNodeKind::PNK_POS:
+      case ParseNodeKind::PNK_NEG:
         return FoldUnaryArithmetic(cx, pn, parser);
 
-      case PNK_PREINCREMENT:
-      case PNK_POSTINCREMENT:
-      case PNK_PREDECREMENT:
-      case PNK_POSTDECREMENT:
+      case ParseNodeKind::PNK_PREINCREMENT:
+      case ParseNodeKind::PNK_POSTINCREMENT:
+      case ParseNodeKind::PNK_PREDECREMENT:
+      case ParseNodeKind::PNK_POSTDECREMENT:
         return FoldIncrementDecrement(cx, pn, parser);
 
-      case PNK_THROW:
-      case PNK_MUTATEPROTO:
-      case PNK_COMPUTED_NAME:
-      case PNK_SPREAD:
-      case PNK_EXPORT:
-      case PNK_VOID:
+      case ParseNodeKind::PNK_THROW:
+      case ParseNodeKind::PNK_MUTATEPROTO:
+      case ParseNodeKind::PNK_COMPUTED_NAME:
+      case ParseNodeKind::PNK_SPREAD:
+      case ParseNodeKind::PNK_EXPORT:
+      case ParseNodeKind::PNK_VOID:
         MOZ_ASSERT(pn->isArity(PN_UNARY));
         return Fold(cx, &pn->pn_kid, parser);
 
-      case PNK_EXPORT_DEFAULT:
+      case ParseNodeKind::PNK_EXPORT_DEFAULT:
         MOZ_ASSERT(pn->isArity(PN_BINARY));
         return Fold(cx, &pn->pn_left, parser);
 
-      case PNK_SEMI:
-      case PNK_THIS:
+      case ParseNodeKind::PNK_SEMI:
+      case ParseNodeKind::PNK_THIS:
         MOZ_ASSERT(pn->isArity(PN_UNARY));
         if (ParseNode*& expr = pn->pn_kid)
             return Fold(cx, &expr, parser);
         return true;
 
-      case PNK_PIPELINE:
+      case ParseNodeKind::PNK_PIPELINE:
         return true;
 
-      case PNK_AND:
-      case PNK_OR:
+      case ParseNodeKind::PNK_AND:
+      case ParseNodeKind::PNK_OR:
         return FoldAndOr(cx, pnp, parser);
 
-      case PNK_FUNCTION:
+      case ParseNodeKind::PNK_FUNCTION:
         return FoldFunction(cx, pn, parser);
 
-      case PNK_MODULE:
+      case ParseNodeKind::PNK_MODULE:
         return FoldModule(cx, pn, parser);
 
-      case PNK_SUB:
-      case PNK_STAR:
-      case PNK_LSH:
-      case PNK_RSH:
-      case PNK_URSH:
-      case PNK_DIV:
-      case PNK_MOD:
+      case ParseNodeKind::PNK_SUB:
+      case ParseNodeKind::PNK_STAR:
+      case ParseNodeKind::PNK_LSH:
+      case ParseNodeKind::PNK_RSH:
+      case ParseNodeKind::PNK_URSH:
+      case ParseNodeKind::PNK_DIV:
+      case ParseNodeKind::PNK_MOD:
         return FoldBinaryArithmetic(cx, pn, parser);
 
-      case PNK_POW:
+      case ParseNodeKind::PNK_POW:
         return FoldExponentiation(cx, pn, parser);
 
       // Various list nodes not requiring care to minimally fold.  Some of
       // these could be further folded/optimized, but we don't make the effort.
-      case PNK_BITOR:
-      case PNK_BITXOR:
-      case PNK_BITAND:
-      case PNK_STRICTEQ:
-      case PNK_EQ:
-      case PNK_STRICTNE:
-      case PNK_NE:
-      case PNK_LT:
-      case PNK_LE:
-      case PNK_GT:
-      case PNK_GE:
-      case PNK_INSTANCEOF:
-      case PNK_IN:
-      case PNK_COMMA:
-      case PNK_NEW:
-      case PNK_ARRAY:
-      case PNK_OBJECT:
-      case PNK_STATEMENTLIST:
-      case PNK_CLASSMETHODLIST:
-      case PNK_TEMPLATE_STRING_LIST:
-      case PNK_VAR:
-      case PNK_CONST:
-      case PNK_LET:
-      case PNK_PARAMSBODY:
-      case PNK_CALLSITEOBJ:
-      case PNK_EXPORT_SPEC_LIST:
-      case PNK_IMPORT_SPEC_LIST:
+      case ParseNodeKind::PNK_BITOR:
+      case ParseNodeKind::PNK_BITXOR:
+      case ParseNodeKind::PNK_BITAND:
+      case ParseNodeKind::PNK_STRICTEQ:
+      case ParseNodeKind::PNK_EQ:
+      case ParseNodeKind::PNK_STRICTNE:
+      case ParseNodeKind::PNK_NE:
+      case ParseNodeKind::PNK_LT:
+      case ParseNodeKind::PNK_LE:
+      case ParseNodeKind::PNK_GT:
+      case ParseNodeKind::PNK_GE:
+      case ParseNodeKind::PNK_INSTANCEOF:
+      case ParseNodeKind::PNK_IN:
+      case ParseNodeKind::PNK_COMMA:
+      case ParseNodeKind::PNK_NEW:
+      case ParseNodeKind::PNK_ARRAY:
+      case ParseNodeKind::PNK_OBJECT:
+      case ParseNodeKind::PNK_STATEMENTLIST:
+      case ParseNodeKind::PNK_CLASSMETHODLIST:
+      case ParseNodeKind::PNK_TEMPLATE_STRING_LIST:
+      case ParseNodeKind::PNK_VAR:
+      case ParseNodeKind::PNK_CONST:
+      case ParseNodeKind::PNK_LET:
+      case ParseNodeKind::PNK_PARAMSBODY:
+      case ParseNodeKind::PNK_CALLSITEOBJ:
+      case ParseNodeKind::PNK_EXPORT_SPEC_LIST:
+      case ParseNodeKind::PNK_IMPORT_SPEC_LIST:
         return FoldList(cx, pn, parser);
 
-      case PNK_INITIALYIELD:
+      case ParseNodeKind::PNK_INITIALYIELD:
         MOZ_ASSERT(pn->isArity(PN_UNARY));
-        MOZ_ASSERT(pn->pn_kid->isKind(PNK_ASSIGN) &&
-                   pn->pn_kid->pn_left->isKind(PNK_NAME) &&
-                   pn->pn_kid->pn_right->isKind(PNK_GENERATOR));
+        MOZ_ASSERT(pn->pn_kid->isKind(ParseNodeKind::PNK_ASSIGN) &&
+                   pn->pn_kid->pn_left->isKind(ParseNodeKind::PNK_NAME) &&
+                   pn->pn_kid->pn_right->isKind(ParseNodeKind::PNK_GENERATOR));
         return true;
 
-      case PNK_YIELD_STAR:
+      case ParseNodeKind::PNK_YIELD_STAR:
         MOZ_ASSERT(pn->isArity(PN_UNARY));
         return Fold(cx, &pn->pn_kid, parser);
 
-      case PNK_YIELD:
-      case PNK_AWAIT:
+      case ParseNodeKind::PNK_YIELD:
+      case ParseNodeKind::PNK_AWAIT:
         MOZ_ASSERT(pn->isArity(PN_UNARY));
         if (!pn->pn_kid)
             return true;
         return Fold(cx, &pn->pn_kid, parser);
 
-      case PNK_RETURN:
+      case ParseNodeKind::PNK_RETURN:
         return FoldReturn(cx, pn, parser);
 
-      case PNK_TRY:
+      case ParseNodeKind::PNK_TRY:
         return FoldTry(cx, pn, parser);
 
-      case PNK_CATCH:
+      case ParseNodeKind::PNK_CATCH:
         return FoldCatch(cx, pn, parser);
 
-      case PNK_CLASS:
+      case ParseNodeKind::PNK_CLASS:
         return FoldClass(cx, pn, parser);
 
-      case PNK_ELEM:
+      case ParseNodeKind::PNK_ELEM:
         return FoldElement(cx, pnp, parser);
 
-      case PNK_ADD:
+      case ParseNodeKind::PNK_ADD:
         return FoldAdd(cx, pnp, parser);
 
-      case PNK_CALL:
-      case PNK_SUPERCALL:
-      case PNK_TAGGED_TEMPLATE:
+      case ParseNodeKind::PNK_CALL:
+      case ParseNodeKind::PNK_SUPERCALL:
+      case ParseNodeKind::PNK_TAGGED_TEMPLATE:
         return FoldCall(cx, pn, parser);
 
-      case PNK_SWITCH:
-      case PNK_COLON:
-      case PNK_ASSIGN:
-      case PNK_ADDASSIGN:
-      case PNK_SUBASSIGN:
-      case PNK_BITORASSIGN:
-      case PNK_BITANDASSIGN:
-      case PNK_BITXORASSIGN:
-      case PNK_LSHASSIGN:
-      case PNK_RSHASSIGN:
-      case PNK_URSHASSIGN:
-      case PNK_DIVASSIGN:
-      case PNK_MODASSIGN:
-      case PNK_MULASSIGN:
-      case PNK_POWASSIGN:
-      case PNK_IMPORT:
-      case PNK_EXPORT_FROM:
-      case PNK_SHORTHAND:
-      case PNK_FOR:
-      case PNK_CLASSMETHOD:
-      case PNK_IMPORT_SPEC:
-      case PNK_EXPORT_SPEC:
-      case PNK_SETTHIS:
+      case ParseNodeKind::PNK_SWITCH:
+      case ParseNodeKind::PNK_COLON:
+      case ParseNodeKind::PNK_ASSIGN:
+      case ParseNodeKind::PNK_ADDASSIGN:
+      case ParseNodeKind::PNK_SUBASSIGN:
+      case ParseNodeKind::PNK_BITORASSIGN:
+      case ParseNodeKind::PNK_BITANDASSIGN:
+      case ParseNodeKind::PNK_BITXORASSIGN:
+      case ParseNodeKind::PNK_LSHASSIGN:
+      case ParseNodeKind::PNK_RSHASSIGN:
+      case ParseNodeKind::PNK_URSHASSIGN:
+      case ParseNodeKind::PNK_DIVASSIGN:
+      case ParseNodeKind::PNK_MODASSIGN:
+      case ParseNodeKind::PNK_MULASSIGN:
+      case ParseNodeKind::PNK_POWASSIGN:
+      case ParseNodeKind::PNK_IMPORT:
+      case ParseNodeKind::PNK_EXPORT_FROM:
+      case ParseNodeKind::PNK_SHORTHAND:
+      case ParseNodeKind::PNK_FOR:
+      case ParseNodeKind::PNK_CLASSMETHOD:
+      case ParseNodeKind::PNK_IMPORT_SPEC:
+      case ParseNodeKind::PNK_EXPORT_SPEC:
+      case ParseNodeKind::PNK_SETTHIS:
         MOZ_ASSERT(pn->isArity(PN_BINARY));
         return Fold(cx, &pn->pn_left, parser) &&
                Fold(cx, &pn->pn_right, parser);
 
-      case PNK_NEWTARGET:
+      case ParseNodeKind::PNK_NEWTARGET:
         MOZ_ASSERT(pn->isArity(PN_BINARY));
-        MOZ_ASSERT(pn->pn_left->isKind(PNK_POSHOLDER));
-        MOZ_ASSERT(pn->pn_right->isKind(PNK_POSHOLDER));
+        MOZ_ASSERT(pn->pn_left->isKind(ParseNodeKind::PNK_POSHOLDER));
+        MOZ_ASSERT(pn->pn_right->isKind(ParseNodeKind::PNK_POSHOLDER));
         return true;
 
-      case PNK_CLASSNAMES:
+      case ParseNodeKind::PNK_CLASSNAMES:
         MOZ_ASSERT(pn->isArity(PN_BINARY));
         if (ParseNode*& outerBinding = pn->pn_left) {
             if (!Fold(cx, &outerBinding, parser))
                 return false;
         }
         return Fold(cx, &pn->pn_right, parser);
 
-      case PNK_DOWHILE:
+      case ParseNodeKind::PNK_DOWHILE:
         MOZ_ASSERT(pn->isArity(PN_BINARY));
         return Fold(cx, &pn->pn_left, parser) &&
                FoldCondition(cx, &pn->pn_right, parser);
 
-      case PNK_WHILE:
+      case ParseNodeKind::PNK_WHILE:
         MOZ_ASSERT(pn->isArity(PN_BINARY));
         return FoldCondition(cx, &pn->pn_left, parser) &&
                Fold(cx, &pn->pn_right, parser);
 
-      case PNK_CASE: {
+      case ParseNodeKind::PNK_CASE: {
         MOZ_ASSERT(pn->isArity(PN_BINARY));
 
         // pn_left is null for DefaultClauses.
         if (pn->pn_left) {
             if (!Fold(cx, &pn->pn_left, parser))
                 return false;
         }
         return Fold(cx, &pn->pn_right, parser);
       }
 
-      case PNK_WITH:
+      case ParseNodeKind::PNK_WITH:
         MOZ_ASSERT(pn->isArity(PN_BINARY));
         return Fold(cx, &pn->pn_left, parser) &&
                Fold(cx, &pn->pn_right, parser);
 
-      case PNK_FORIN:
-      case PNK_FOROF:
+      case ParseNodeKind::PNK_FORIN:
+      case ParseNodeKind::PNK_FOROF:
         return FoldForInOrOf(cx, pn, parser);
 
-      case PNK_FORHEAD:
+      case ParseNodeKind::PNK_FORHEAD:
         return FoldForHead(cx, pn, parser);
 
-      case PNK_LABEL:
+      case ParseNodeKind::PNK_LABEL:
         MOZ_ASSERT(pn->isArity(PN_NAME));
         return Fold(cx, &pn->pn_expr, parser);
 
-      case PNK_DOT:
+      case ParseNodeKind::PNK_DOT:
         return FoldDottedProperty(cx, pn, parser);
 
-      case PNK_LEXICALSCOPE:
+      case ParseNodeKind::PNK_LEXICALSCOPE:
         MOZ_ASSERT(pn->isArity(PN_SCOPE));
         if (!pn->scopeBody())
             return true;
         return Fold(cx, &pn->pn_u.scope.body, parser);
 
-      case PNK_NAME:
+      case ParseNodeKind::PNK_NAME:
         return FoldName(cx, pn, parser);
 
-      case PNK_LIMIT: // invalid sentinel value
+      case ParseNodeKind::PNK_LIMIT: // invalid sentinel value
         MOZ_CRASH("invalid node kind");
     }
 
     MOZ_CRASH("shouldn't reach here");
     return false;
 }
 
 template<typename CharT>
--- a/js/src/frontend/FullParseHandler.h
+++ b/js/src/frontend/FullParseHandler.h
@@ -52,34 +52,36 @@ class FullParseHandler
 
   public:
     /* new_ methods for creating parse nodes. These report OOM on context. */
     JS_DECLARE_NEW_METHODS(new_, allocParseNode, inline)
 
     typedef ParseNode* Node;
 
     bool isPropertyAccess(ParseNode* node) {
-        return node->isKind(PNK_DOT) || node->isKind(PNK_ELEM);
+        return node->isKind(ParseNodeKind::PNK_DOT) || node->isKind(ParseNodeKind::PNK_ELEM);
     }
 
     bool isFunctionCall(ParseNode* node) {
         // Note: super() is a special form, *not* a function call.
-        return node->isKind(PNK_CALL);
+        return node->isKind(ParseNodeKind::PNK_CALL);
     }
 
     static bool isUnparenthesizedDestructuringPattern(ParseNode* node) {
-        return !node->isInParens() && (node->isKind(PNK_OBJECT) || node->isKind(PNK_ARRAY));
+        return !node->isInParens() && (node->isKind(ParseNodeKind::PNK_OBJECT) ||
+                                       node->isKind(ParseNodeKind::PNK_ARRAY));
     }
 
     static bool isParenthesizedDestructuringPattern(ParseNode* node) {
         // Technically this isn't a destructuring pattern at all -- the grammar
         // doesn't treat it as such.  But we need to know when this happens to
         // consider it a SyntaxError rather than an invalid-left-hand-side
         // ReferenceError.
-        return node->isInParens() && (node->isKind(PNK_OBJECT) || node->isKind(PNK_ARRAY));
+        return node->isInParens() && (node->isKind(ParseNodeKind::PNK_OBJECT) ||
+                                      node->isKind(ParseNodeKind::PNK_ARRAY));
     }
 
     FullParseHandler(JSContext* cx, LifoAlloc& alloc, LazyScript* lazyOuterFunction,
                      SourceKind kind = SourceKind::Text)
       : allocator(cx, alloc),
         lazyOuterFunction_(cx, lazyOuterFunction),
         lazyInnerFunctionIndex(0),
         lazyClosedOverBindingIndex(0),
@@ -95,46 +97,46 @@ class FullParseHandler
     // to determine whether we need to check these assumptions.
     SourceKind sourceKind() const { return sourceKind_; }
 
     ParseNode* freeTree(ParseNode* pn) { return allocator.freeTree(pn); }
     void prepareNodeForMutation(ParseNode* pn) { return allocator.prepareNodeForMutation(pn); }
 
     ParseNode* newName(PropertyName* name, const TokenPos& pos, JSContext* cx)
     {
-        return new_<NameNode>(PNK_NAME, JSOP_GETNAME, name, pos);
+        return new_<NameNode>(ParseNodeKind::PNK_NAME, JSOP_GETNAME, name, pos);
     }
 
     ParseNode* newComputedName(ParseNode* expr, uint32_t begin, uint32_t end) {
         TokenPos pos(begin, end);
-        return new_<UnaryNode>(PNK_COMPUTED_NAME, pos, expr);
+        return new_<UnaryNode>(ParseNodeKind::PNK_COMPUTED_NAME, pos, expr);
     }
 
     ParseNode* newObjectLiteralPropertyName(JSAtom* atom, const TokenPos& pos) {
-        return new_<NullaryNode>(PNK_OBJECT_PROPERTY_NAME, JSOP_NOP, pos, atom);
+        return new_<NullaryNode>(ParseNodeKind::PNK_OBJECT_PROPERTY_NAME, JSOP_NOP, pos, atom);
     }
 
     ParseNode* newNumber(double value, DecimalPoint decimalPoint, const TokenPos& pos) {
-        ParseNode* pn = new_<NullaryNode>(PNK_NUMBER, pos);
+        ParseNode* pn = new_<NullaryNode>(ParseNodeKind::PNK_NUMBER, pos);
         if (!pn)
             return nullptr;
         pn->initNumber(value, decimalPoint);
         return pn;
     }
 
     ParseNode* newBooleanLiteral(bool cond, const TokenPos& pos) {
         return new_<BooleanLiteral>(cond, pos);
     }
 
     ParseNode* newStringLiteral(JSAtom* atom, const TokenPos& pos) {
-        return new_<NullaryNode>(PNK_STRING, JSOP_NOP, pos, atom);
+        return new_<NullaryNode>(ParseNodeKind::PNK_STRING, JSOP_NOP, pos, atom);
     }
 
     ParseNode* newTemplateStringLiteral(JSAtom* atom, const TokenPos& pos) {
-        return new_<NullaryNode>(PNK_TEMPLATE_STRING, JSOP_NOP, pos, atom);
+        return new_<NullaryNode>(ParseNodeKind::PNK_TEMPLATE_STRING, JSOP_NOP, pos, atom);
     }
 
     ParseNode* newCallSiteObject(uint32_t begin) {
         ParseNode* callSite = new_<CallSiteNode>(begin);
         if (!callSite)
             return null();
 
         Node propExpr = newArrayLiteral(callSite->pn_pos.begin);
@@ -142,17 +144,17 @@ class FullParseHandler
             return null();
 
         addArrayElement(callSite, propExpr);
 
         return callSite;
     }
 
     void addToCallSiteObject(ParseNode* callSiteObj, ParseNode* rawNode, ParseNode* cookedNode) {
-        MOZ_ASSERT(callSiteObj->isKind(PNK_CALLSITEOBJ));
+        MOZ_ASSERT(callSiteObj->isKind(ParseNodeKind::PNK_CALLSITEOBJ));
 
         addArrayElement(callSiteObj, cookedNode);
         addArrayElement(callSiteObj->pn_head, rawNode);
 
         /*
          * We don't know when the last noSubstTemplate will come in, and we
          * don't want to deal with this outside this method
          */
@@ -182,47 +184,50 @@ class FullParseHandler
         return new_<RegExpLiteral>(objbox, pos);
     }
 
     ParseNode* newConditional(ParseNode* cond, ParseNode* thenExpr, ParseNode* elseExpr) {
         return new_<ConditionalExpression>(cond, thenExpr, elseExpr);
     }
 
     ParseNode* newDelete(uint32_t begin, ParseNode* expr) {
-        if (expr->isKind(PNK_NAME)) {
+        if (expr->isKind(ParseNodeKind::PNK_NAME)) {
             expr->setOp(JSOP_DELNAME);
-            return newUnary(PNK_DELETENAME, begin, expr);
+            return newUnary(ParseNodeKind::PNK_DELETENAME, begin, expr);
         }
 
-        if (expr->isKind(PNK_DOT))
-            return newUnary(PNK_DELETEPROP, begin, expr);
+        if (expr->isKind(ParseNodeKind::PNK_DOT))
+            return newUnary(ParseNodeKind::PNK_DELETEPROP, begin, expr);
 
-        if (expr->isKind(PNK_ELEM))
-            return newUnary(PNK_DELETEELEM, begin, expr);
+        if (expr->isKind(ParseNodeKind::PNK_ELEM))
+            return newUnary(ParseNodeKind::PNK_DELETEELEM, begin, expr);
 
-        return newUnary(PNK_DELETEEXPR, begin, expr);
+        return newUnary(ParseNodeKind::PNK_DELETEEXPR, begin, expr);
     }
 
     ParseNode* newTypeof(uint32_t begin, ParseNode* kid) {
-        return newUnary(kid->isKind(PNK_NAME) ? PNK_TYPEOFNAME : PNK_TYPEOFEXPR, begin, kid);
+        ParseNodeKind pnk = kid->isKind(ParseNodeKind::PNK_NAME)
+                            ? ParseNodeKind::PNK_TYPEOFNAME
+                            : ParseNodeKind::PNK_TYPEOFEXPR;
+        return newUnary(pnk, begin, kid);
     }
 
     ParseNode* newUnary(ParseNodeKind kind, uint32_t begin, ParseNode* kid) {
         TokenPos pos(begin, kid->pn_pos.end);
         return new_<UnaryNode>(kind, pos, kid);
     }
 
     ParseNode* newUpdate(ParseNodeKind kind, uint32_t begin, ParseNode* kid) {
         TokenPos pos(begin, kid->pn_pos.end);
         return new_<UnaryNode>(kind, pos, kid);
     }
 
     ParseNode* newSpread(uint32_t begin, ParseNode* kid) {
         TokenPos pos(begin, kid->pn_pos.end);
-        return new_<UnaryNode>(PNK_SPREAD, pos, kid);
+        return new_<UnaryNode>(ParseNodeKind::PNK_SPREAD, pos, kid);
     }
 
   private:
     ParseNode* newBinary(ParseNodeKind kind, ParseNode* left, ParseNode* right,
                          JSOp op = JSOP_NOP)
     {
         TokenPos pos(left->pn_pos.begin, right->pn_pos.end);
         return new_<BinaryNode>(kind, op, pos, left, right);
@@ -233,33 +238,33 @@ class FullParseHandler
                                   ParseContext* pc)
     {
         return ParseNode::appendOrCreateList(kind, left, right, this, pc);
     }
 
     // Expressions
 
     ParseNode* newArrayLiteral(uint32_t begin) {
-        return new_<ListNode>(PNK_ARRAY, TokenPos(begin, begin + 1));
+        return new_<ListNode>(ParseNodeKind::PNK_ARRAY, TokenPos(begin, begin + 1));
     }
 
     MOZ_MUST_USE bool addElision(ParseNode* literal, const TokenPos& pos) {
-        MOZ_ASSERT(literal->isKind(PNK_ARRAY));
+        MOZ_ASSERT(literal->isKind(ParseNodeKind::PNK_ARRAY));
         MOZ_ASSERT(literal->isArity(PN_LIST));
 
-        ParseNode* elision = new_<NullaryNode>(PNK_ELISION, pos);
+        ParseNode* elision = new_<NullaryNode>(ParseNodeKind::PNK_ELISION, pos);
         if (!elision)
             return false;
         addList(/* list = */ literal, /* child = */ elision);
         literal->pn_xflags |= PNX_ARRAYHOLESPREAD | PNX_NONCONST;
         return true;
     }
 
     MOZ_MUST_USE bool addSpreadElement(ParseNode* literal, uint32_t begin, ParseNode* inner) {
-        MOZ_ASSERT(literal->isKind(PNK_ARRAY));
+        MOZ_ASSERT(literal->isKind(ParseNodeKind::PNK_ARRAY));
         MOZ_ASSERT(literal->isArity(PN_LIST));
 
         ParseNode* spread = newSpread(begin, inner);
         if (!spread)
             return false;
         addList(/* list = */ literal, /* child = */ spread);
         literal->pn_xflags |= PNX_ARRAYHOLESPREAD | PNX_NONCONST;
         return true;
@@ -269,98 +274,98 @@ class FullParseHandler
         MOZ_ASSERT(literal->isArity(PN_LIST));
 
         if (!element->isConstant())
             literal->pn_xflags |= PNX_NONCONST;
         addList(/* list = */ literal, /* child = */ element);
     }
 
     ParseNode* newCall(const TokenPos& pos) {
-        return new_<ListNode>(PNK_CALL, JSOP_CALL, pos);
+        return new_<ListNode>(ParseNodeKind::PNK_CALL, JSOP_CALL, pos);
     }
 
     ParseNode* newSuperCall(ParseNode* callee) {
-        return new_<ListNode>(PNK_SUPERCALL, JSOP_SUPERCALL, callee);
+        return new_<ListNode>(ParseNodeKind::PNK_SUPERCALL, JSOP_SUPERCALL, callee);
     }
 
     ParseNode* newTaggedTemplate(const TokenPos& pos) {
-        return new_<ListNode>(PNK_TAGGED_TEMPLATE, JSOP_CALL, pos);
+        return new_<ListNode>(ParseNodeKind::PNK_TAGGED_TEMPLATE, JSOP_CALL, pos);
     }
 
     ParseNode* newObjectLiteral(uint32_t begin) {
-        return new_<ListNode>(PNK_OBJECT, TokenPos(begin, begin + 1));
+        return new_<ListNode>(ParseNodeKind::PNK_OBJECT, TokenPos(begin, begin + 1));
     }
 
     ParseNode* newClass(ParseNode* name, ParseNode* heritage, ParseNode* methodBlock,
                         const TokenPos& pos)
     {
         return new_<ClassNode>(name, heritage, methodBlock, pos);
     }
     ParseNode* newClassMethodList(uint32_t begin) {
-        return new_<ListNode>(PNK_CLASSMETHODLIST, TokenPos(begin, begin + 1));
+        return new_<ListNode>(ParseNodeKind::PNK_CLASSMETHODLIST, TokenPos(begin, begin + 1));
     }
     ParseNode* newClassNames(ParseNode* outer, ParseNode* inner, const TokenPos& pos) {
         return new_<ClassNames>(outer, inner, pos);
     }
     ParseNode* newNewTarget(ParseNode* newHolder, ParseNode* targetHolder) {
-        return new_<BinaryNode>(PNK_NEWTARGET, JSOP_NOP, newHolder, targetHolder);
+        return new_<BinaryNode>(ParseNodeKind::PNK_NEWTARGET, JSOP_NOP, newHolder, targetHolder);
     }
     ParseNode* newPosHolder(const TokenPos& pos) {
-        return new_<NullaryNode>(PNK_POSHOLDER, pos);
+        return new_<NullaryNode>(ParseNodeKind::PNK_POSHOLDER, pos);
     }
     ParseNode* newSuperBase(ParseNode* thisName, const TokenPos& pos) {
-        return new_<UnaryNode>(PNK_SUPERBASE, pos, thisName);
+        return new_<UnaryNode>(ParseNodeKind::PNK_SUPERBASE, pos, thisName);
     }
     ParseNode* newCatchBlock(ParseNode* catchName, ParseNode* catchGuard, ParseNode* catchBody) {
-        return new_<TernaryNode>(PNK_CATCH, catchName, catchGuard, catchBody);
+        return new_<TernaryNode>(ParseNodeKind::PNK_CATCH, catchName, catchGuard, catchBody);
     }
     MOZ_MUST_USE bool addPrototypeMutation(ParseNode* literal, uint32_t begin, ParseNode* expr) {
-        MOZ_ASSERT(literal->isKind(PNK_OBJECT));
+        MOZ_ASSERT(literal->isKind(ParseNodeKind::PNK_OBJECT));
         MOZ_ASSERT(literal->isArity(PN_LIST));
 
         // Object literals with mutated [[Prototype]] are non-constant so that
         // singleton objects will have Object.prototype as their [[Prototype]].
         setListFlag(literal, PNX_NONCONST);
 
-        ParseNode* mutation = newUnary(PNK_MUTATEPROTO, begin, expr);
+        ParseNode* mutation = newUnary(ParseNodeKind::PNK_MUTATEPROTO, begin, expr);
         if (!mutation)
             return false;
         addList(/* list = */ literal, /* child = */ mutation);
         return true;
     }
 
     MOZ_MUST_USE bool addPropertyDefinition(ParseNode* literal, ParseNode* key, ParseNode* val) {
-        MOZ_ASSERT(literal->isKind(PNK_OBJECT));
+        MOZ_ASSERT(literal->isKind(ParseNodeKind::PNK_OBJECT));
         MOZ_ASSERT(literal->isArity(PN_LIST));
         MOZ_ASSERT(isUsableAsObjectPropertyName(key));
 
-        ParseNode* propdef = newBinary(PNK_COLON, key, val, JSOP_INITPROP);
+        ParseNode* propdef = newBinary(ParseNodeKind::PNK_COLON, key, val, JSOP_INITPROP);
         if (!propdef)
             return false;
         addList(/* list = */ literal, /* child = */ propdef);
         return true;
     }
 
     MOZ_MUST_USE bool addShorthand(ParseNode* literal, ParseNode* name, ParseNode* expr) {
-        MOZ_ASSERT(literal->isKind(PNK_OBJECT));
+        MOZ_ASSERT(literal->isKind(ParseNodeKind::PNK_OBJECT));
         MOZ_ASSERT(literal->isArity(PN_LIST));
-        MOZ_ASSERT(name->isKind(PNK_OBJECT_PROPERTY_NAME));
-        MOZ_ASSERT(expr->isKind(PNK_NAME));
+        MOZ_ASSERT(name->isKind(ParseNodeKind::PNK_OBJECT_PROPERTY_NAME));
+        MOZ_ASSERT(expr->isKind(ParseNodeKind::PNK_NAME));
         MOZ_ASSERT(name->pn_atom == expr->pn_atom);
 
         setListFlag(literal, PNX_NONCONST);
-        ParseNode* propdef = newBinary(PNK_SHORTHAND, name, expr, JSOP_INITPROP);
+        ParseNode* propdef = newBinary(ParseNodeKind::PNK_SHORTHAND, name, expr, JSOP_INITPROP);
         if (!propdef)
             return false;
         addList(/* list = */ literal, /* child = */ propdef);
         return true;
     }
 
     MOZ_MUST_USE bool addSpreadProperty(ParseNode* literal, uint32_t begin, ParseNode* inner) {
-        MOZ_ASSERT(literal->isKind(PNK_OBJECT));
+        MOZ_ASSERT(literal->isKind(ParseNodeKind::PNK_OBJECT));
         MOZ_ASSERT(literal->isArity(PN_LIST));
 
         setListFlag(literal, PNX_NONCONST);
         ParseNode* spread = newSpread(begin, inner);
         if (!spread)
             return false;
         addList(/* list = */ literal, /* child = */ spread);
         return true;
@@ -378,259 +383,262 @@ class FullParseHandler
 
         addList(/* list = */ literal, /* child = */ propdef);
         return true;
     }
 
     MOZ_MUST_USE bool addClassMethodDefinition(ParseNode* methodList, ParseNode* key, ParseNode* fn,
                                                AccessorType atype, bool isStatic)
     {
-        MOZ_ASSERT(methodList->isKind(PNK_CLASSMETHODLIST));
+        MOZ_ASSERT(methodList->isKind(ParseNodeKind::PNK_CLASSMETHODLIST));
         MOZ_ASSERT(isUsableAsObjectPropertyName(key));
 
         ParseNode* classMethod = new_<ClassMethod>(key, fn, AccessorTypeToJSOp(atype), isStatic);
         if (!classMethod)
             return false;
         addList(/* list = */ methodList, /* child = */ classMethod);
         return true;
     }
 
     ParseNode* newInitialYieldExpression(uint32_t begin, ParseNode* gen) {
         TokenPos pos(begin, begin + 1);
-        return new_<UnaryNode>(PNK_INITIALYIELD, pos, gen);
+        return new_<UnaryNode>(ParseNodeKind::PNK_INITIALYIELD, pos, gen);
     }
 
     ParseNode* newYieldExpression(uint32_t begin, ParseNode* value) {
         TokenPos pos(begin, value ? value->pn_pos.end : begin + 1);
-        return new_<UnaryNode>(PNK_YIELD, pos, value);
+        return new_<UnaryNode>(ParseNodeKind::PNK_YIELD, pos, value);
     }
 
     ParseNode* newYieldStarExpression(uint32_t begin, ParseNode* value) {
         TokenPos pos(begin, value->pn_pos.end);
-        return new_<UnaryNode>(PNK_YIELD_STAR, pos, value);
+        return new_<UnaryNode>(ParseNodeKind::PNK_YIELD_STAR, pos, value);
     }
 
     ParseNode* newAwaitExpression(uint32_t begin, ParseNode* value) {
         TokenPos pos(begin, value ? value->pn_pos.end : begin + 1);
-        return new_<UnaryNode>(PNK_AWAIT, pos, value);
+        return new_<UnaryNode>(ParseNodeKind::PNK_AWAIT, pos, value);
     }
 
     // Statements
 
     ParseNode* newStatementList(const TokenPos& pos) {
-        return new_<ListNode>(PNK_STATEMENTLIST, pos);
+        return new_<ListNode>(ParseNodeKind::PNK_STATEMENTLIST, pos);
     }
 
     MOZ_MUST_USE bool isFunctionStmt(ParseNode* stmt) {
-        while (stmt->isKind(PNK_LABEL))
+        while (stmt->isKind(ParseNodeKind::PNK_LABEL))
             stmt = stmt->as<LabeledStatement>().statement();
-        return stmt->isKind(PNK_FUNCTION);
+        return stmt->isKind(ParseNodeKind::PNK_FUNCTION);
     }
 
     void addStatementToList(ParseNode* list, ParseNode* stmt) {
-        MOZ_ASSERT(list->isKind(PNK_STATEMENTLIST));
+        MOZ_ASSERT(list->isKind(ParseNodeKind::PNK_STATEMENTLIST));
 
         addList(/* list = */ list, /* child = */ stmt);
 
         if (isFunctionStmt(stmt)) {
             // PNX_FUNCDEFS notifies the emitter that the block contains
             // body-level function definitions that should be processed
             // before the rest of nodes.
             list->pn_xflags |= PNX_FUNCDEFS;
         }
     }
 
     void setListEndPosition(ParseNode* list, const TokenPos& pos) {
-        MOZ_ASSERT(list->isKind(PNK_STATEMENTLIST));
+        MOZ_ASSERT(list->isKind(ParseNodeKind::PNK_STATEMENTLIST));
         list->pn_pos.end = pos.end;
     }
 
     void addCaseStatementToList(ParseNode* list, ParseNode* casepn) {
-        MOZ_ASSERT(list->isKind(PNK_STATEMENTLIST));
-        MOZ_ASSERT(casepn->isKind(PNK_CASE));
-        MOZ_ASSERT(casepn->pn_right->isKind(PNK_STATEMENTLIST));
+        MOZ_ASSERT(list->isKind(ParseNodeKind::PNK_STATEMENTLIST));
+        MOZ_ASSERT(casepn->isKind(ParseNodeKind::PNK_CASE));
+        MOZ_ASSERT(casepn->pn_right->isKind(ParseNodeKind::PNK_STATEMENTLIST));
 
         addList(/* list = */ list, /* child = */ casepn);
 
         if (casepn->pn_right->pn_xflags & PNX_FUNCDEFS)
             list->pn_xflags |= PNX_FUNCDEFS;
     }
 
     MOZ_MUST_USE inline bool addCatchBlock(ParseNode* catchList, ParseNode* lexicalScope,
                               ParseNode* catchName, ParseNode* catchGuard,
                               ParseNode* catchBody);
 
     MOZ_MUST_USE bool prependInitialYield(ParseNode* stmtList, ParseNode* genName) {
-        MOZ_ASSERT(stmtList->isKind(PNK_STATEMENTLIST));
+        MOZ_ASSERT(stmtList->isKind(ParseNodeKind::PNK_STATEMENTLIST));
         MOZ_ASSERT(stmtList->isArity(PN_LIST));
 
         TokenPos yieldPos(stmtList->pn_pos.begin, stmtList->pn_pos.begin + 1);
-        ParseNode* makeGen = new_<NullaryNode>(PNK_GENERATOR, yieldPos);
+        ParseNode* makeGen = new_<NullaryNode>(ParseNodeKind::PNK_GENERATOR, yieldPos);
         if (!makeGen)
             return false;
 
         MOZ_ASSERT(genName->getOp() == JSOP_GETNAME);
         genName->setOp(JSOP_SETNAME);
-        ParseNode* genInit = newAssignment(PNK_ASSIGN, /* lhs = */ genName, /* rhs = */ makeGen);
+        ParseNode* genInit = newAssignment(ParseNodeKind::PNK_ASSIGN, /* lhs = */ genName,
+                                           /* rhs = */ makeGen);
         if (!genInit)
             return false;
 
         ParseNode* initialYield = newInitialYieldExpression(yieldPos.begin, genInit);
         if (!initialYield)
             return false;
 
         stmtList->prepend(initialYield);
         return true;
     }
 
     ParseNode* newSetThis(ParseNode* thisName, ParseNode* val) {
         MOZ_ASSERT(thisName->getOp() == JSOP_GETNAME);
         thisName->setOp(JSOP_SETNAME);
-        return newBinary(PNK_SETTHIS, thisName, val);
+        return newBinary(ParseNodeKind::PNK_SETTHIS, thisName, val);
     }
 
     ParseNode* newEmptyStatement(const TokenPos& pos) {
-        return new_<UnaryNode>(PNK_SEMI, pos, nullptr);
+        return new_<UnaryNode>(ParseNodeKind::PNK_SEMI, pos, nullptr);
     }
 
     ParseNode* newImportDeclaration(ParseNode* importSpecSet,
                                     ParseNode* moduleSpec, const TokenPos& pos)
     {
-        ParseNode* pn = new_<BinaryNode>(PNK_IMPORT, JSOP_NOP, pos,
+        ParseNode* pn = new_<BinaryNode>(ParseNodeKind::PNK_IMPORT, JSOP_NOP, pos,
                                          importSpecSet, moduleSpec);
         if (!pn)
             return null();
         return pn;
     }
 
     ParseNode* newImportSpec(ParseNode* importNameNode, ParseNode* bindingName) {
-        return newBinary(PNK_IMPORT_SPEC, importNameNode, bindingName);
+        return newBinary(ParseNodeKind::PNK_IMPORT_SPEC, importNameNode, bindingName);
     }
 
     ParseNode* newExportDeclaration(ParseNode* kid, const TokenPos& pos) {
-        return new_<UnaryNode>(PNK_EXPORT, pos, kid);
+        return new_<UnaryNode>(ParseNodeKind::PNK_EXPORT, pos, kid);
     }
 
     ParseNode* newExportFromDeclaration(uint32_t begin, ParseNode* exportSpecSet,
                                         ParseNode* moduleSpec)
     {
-        ParseNode* pn = new_<BinaryNode>(PNK_EXPORT_FROM, JSOP_NOP, exportSpecSet, moduleSpec);
+        ParseNode* pn = new_<BinaryNode>(ParseNodeKind::PNK_EXPORT_FROM, JSOP_NOP, exportSpecSet,
+                                         moduleSpec);
         if (!pn)
             return null();
         pn->pn_pos.begin = begin;
         return pn;
     }
 
     ParseNode* newExportDefaultDeclaration(ParseNode* kid, ParseNode* maybeBinding,
                                            const TokenPos& pos) {
-        return new_<BinaryNode>(PNK_EXPORT_DEFAULT, JSOP_NOP, pos, kid, maybeBinding);
+        return new_<BinaryNode>(ParseNodeKind::PNK_EXPORT_DEFAULT, JSOP_NOP, pos, kid, maybeBinding);
     }
 
     ParseNode* newExportSpec(ParseNode* bindingName, ParseNode* exportName) {
-        return newBinary(PNK_EXPORT_SPEC, bindingName, exportName);
+        return newBinary(ParseNodeKind::PNK_EXPORT_SPEC, bindingName, exportName);
     }
 
     ParseNode* newExportBatchSpec(const TokenPos& pos) {
-        return new_<NullaryNode>(PNK_EXPORT_BATCH_SPEC, JSOP_NOP, pos);
+        return new_<NullaryNode>(ParseNodeKind::PNK_EXPORT_BATCH_SPEC, JSOP_NOP, pos);
     }
 
     ParseNode* newExprStatement(ParseNode* expr, uint32_t end) {
         MOZ_ASSERT(expr->pn_pos.end <= end);
-        return new_<UnaryNode>(PNK_SEMI, TokenPos(expr->pn_pos.begin, end), expr);
+        return new_<UnaryNode>(ParseNodeKind::PNK_SEMI, TokenPos(expr->pn_pos.begin, end), expr);
     }
 
     ParseNode* newIfStatement(uint32_t begin, ParseNode* cond, ParseNode* thenBranch,
                               ParseNode* elseBranch)
     {
-        ParseNode* pn = new_<TernaryNode>(PNK_IF, cond, thenBranch, elseBranch);
+        ParseNode* pn = new_<TernaryNode>(ParseNodeKind::PNK_IF, cond, thenBranch, elseBranch);
         if (!pn)
             return null();
         pn->pn_pos.begin = begin;
         return pn;
     }
 
     ParseNode* newDoWhileStatement(ParseNode* body, ParseNode* cond, const TokenPos& pos) {
-        return new_<BinaryNode>(PNK_DOWHILE, JSOP_NOP, pos, body, cond);
+        return new_<BinaryNode>(ParseNodeKind::PNK_DOWHILE, JSOP_NOP, pos, body, cond);
     }
 
     ParseNode* newWhileStatement(uint32_t begin, ParseNode* cond, ParseNode* body) {
         TokenPos pos(begin, body->pn_pos.end);
-        return new_<BinaryNode>(PNK_WHILE, JSOP_NOP, pos, cond, body);
+        return new_<BinaryNode>(ParseNodeKind::PNK_WHILE, JSOP_NOP, pos, cond, body);
     }
 
     ParseNode* newForStatement(uint32_t begin, ParseNode* forHead, ParseNode* body,
                                unsigned iflags)
     {
         /* A FOR node is binary, left is loop control and right is the body. */
-        JSOp op = forHead->isKind(PNK_FORIN) ? JSOP_ITER : JSOP_NOP;
-        BinaryNode* pn = new_<BinaryNode>(PNK_FOR, op, TokenPos(begin, body->pn_pos.end),
+        JSOp op = forHead->isKind(ParseNodeKind::PNK_FORIN) ? JSOP_ITER : JSOP_NOP;
+        BinaryNode* pn = new_<BinaryNode>(ParseNodeKind::PNK_FOR, op,
+                                          TokenPos(begin, body->pn_pos.end),
                                           forHead, body);
         if (!pn)
             return null();
         pn->pn_iflags = iflags;
         return pn;
     }
 
     ParseNode* newForHead(ParseNode* init, ParseNode* test, ParseNode* update,
                           const TokenPos& pos)
     {
-        return new_<TernaryNode>(PNK_FORHEAD, init, test, update, pos);
+        return new_<TernaryNode>(ParseNodeKind::PNK_FORHEAD, init, test, update, pos);
     }
 
     ParseNode* newForInOrOfHead(ParseNodeKind kind, ParseNode* target, ParseNode* iteratedExpr,
                                 const TokenPos& pos)
     {
-        MOZ_ASSERT(kind == PNK_FORIN || kind == PNK_FOROF);
+        MOZ_ASSERT(kind == ParseNodeKind::PNK_FORIN || kind == ParseNodeKind::PNK_FOROF);
         return new_<TernaryNode>(kind, target, nullptr, iteratedExpr, pos);
     }
 
     ParseNode* newSwitchStatement(uint32_t begin, ParseNode* discriminant, ParseNode* caseList) {
         TokenPos pos(begin, caseList->pn_pos.end);
-        return new_<BinaryNode>(PNK_SWITCH, JSOP_NOP, pos, discriminant, caseList);
+        return new_<BinaryNode>(ParseNodeKind::PNK_SWITCH, JSOP_NOP, pos, discriminant, caseList);
     }
 
     ParseNode* newCaseOrDefault(uint32_t begin, ParseNode* expr, ParseNode* body) {
         return new_<CaseClause>(expr, body, begin);
     }
 
     ParseNode* newContinueStatement(PropertyName* label, const TokenPos& pos) {
         return new_<ContinueStatement>(label, pos);
     }
 
     ParseNode* newBreakStatement(PropertyName* label, const TokenPos& pos) {
         return new_<BreakStatement>(label, pos);
     }
 
     ParseNode* newReturnStatement(ParseNode* expr, const TokenPos& pos) {
         MOZ_ASSERT_IF(expr, pos.encloses(expr->pn_pos));
-        return new_<UnaryNode>(PNK_RETURN, pos, expr);
+        return new_<UnaryNode>(ParseNodeKind::PNK_RETURN, pos, expr);
     }
 
     ParseNode* newExpressionBody(ParseNode* expr) {
-        return new_<UnaryNode>(PNK_RETURN, expr->pn_pos, expr);
+        return new_<UnaryNode>(ParseNodeKind::PNK_RETURN, expr->pn_pos, expr);
     }
 
     ParseNode* newWithStatement(uint32_t begin, ParseNode* expr, ParseNode* body) {
-        return new_<BinaryNode>(PNK_WITH, JSOP_NOP, TokenPos(begin, body->pn_pos.end),
+        return new_<BinaryNode>(ParseNodeKind::PNK_WITH, JSOP_NOP, TokenPos(begin, body->pn_pos.end),
                                 expr, body);
     }
 
     ParseNode* newLabeledStatement(PropertyName* label, ParseNode* stmt, uint32_t begin) {
         return new_<LabeledStatement>(label, stmt, begin);
     }
 
     ParseNode* newThrowStatement(ParseNode* expr, const TokenPos& pos) {
         MOZ_ASSERT(pos.encloses(expr->pn_pos));
-        return new_<UnaryNode>(PNK_THROW, pos, expr);
+        return new_<UnaryNode>(ParseNodeKind::PNK_THROW, pos, expr);
     }
 
     ParseNode* newTryStatement(uint32_t begin, ParseNode* body, ParseNode* catchScope,
                                ParseNode* finallyBlock) {
         TokenPos pos(begin, (finallyBlock ? finallyBlock : catchScope)->pn_pos.end);
-        return new_<TernaryNode>(PNK_TRY, body, catchScope, finallyBlock, pos);
+        return new_<TernaryNode>(ParseNodeKind::PNK_TRY, body, catchScope, finallyBlock, pos);
     }
 
     ParseNode* newDebuggerStatement(const TokenPos& pos) {
         return new_<DebuggerStatement>(pos);
     }
 
     ParseNode* newPropertyAccess(ParseNode* pn, PropertyName* name, uint32_t end) {
         return new_<PropertyAccess>(pn, name, pn->pn_pos.begin, end);
@@ -638,145 +646,154 @@ class FullParseHandler
 
     ParseNode* newPropertyByValue(ParseNode* lhs, ParseNode* index, uint32_t end) {
         return new_<PropertyByValue>(lhs, index, lhs->pn_pos.begin, end);
     }
 
     bool setupCatchScope(ParseNode* lexicalScope, ParseNode* catchName, ParseNode* catchBody) {
         ParseNode* catchpn;
         if (catchName) {
-            catchpn = new_<BinaryNode>(PNK_CATCH, JSOP_NOP, catchName, catchBody);
+            catchpn = new_<BinaryNode>(ParseNodeKind::PNK_CATCH, JSOP_NOP, catchName, catchBody);
         } else {
-            catchpn = new_<BinaryNode>(PNK_CATCH, JSOP_NOP, catchBody->pn_pos, catchName,
-                                       catchBody);
+            catchpn = new_<BinaryNode>(ParseNodeKind::PNK_CATCH, JSOP_NOP, catchBody->pn_pos,
+                                       catchName, catchBody);
         }
         if (!catchpn)
             return false;
         lexicalScope->setScopeBody(catchpn);
         return true;
     }
 
     inline MOZ_MUST_USE bool setLastFunctionFormalParameterDefault(ParseNode* funcpn,
                                                                    ParseNode* pn);
 
     void checkAndSetIsDirectRHSAnonFunction(ParseNode* pn) {
         if (IsAnonymousFunctionDefinition(pn))
             pn->setDirectRHSAnonFunction(true);
     }
 
     ParseNode* newFunctionStatement(const TokenPos& pos) {
-        return new_<CodeNode>(PNK_FUNCTION, JSOP_NOP, pos);
+        return new_<CodeNode>(ParseNodeKind::PNK_FUNCTION, JSOP_NOP, pos);
     }
 
     ParseNode* newFunctionExpression(const TokenPos& pos) {
-        return new_<CodeNode>(PNK_FUNCTION, JSOP_LAMBDA, pos);
+        return new_<CodeNode>(ParseNodeKind::PNK_FUNCTION, JSOP_LAMBDA, pos);
     }
 
     ParseNode* newArrowFunction(const TokenPos& pos) {
-        return new_<CodeNode>(PNK_FUNCTION, JSOP_LAMBDA_ARROW, pos);
+        return new_<CodeNode>(ParseNodeKind::PNK_FUNCTION, JSOP_LAMBDA_ARROW, pos);
     }
 
     bool isExpressionClosure(ParseNode* node) const {
-        return node->isKind(PNK_FUNCTION) &&
+        return node->isKind(ParseNodeKind::PNK_FUNCTION) &&
                node->pn_funbox->isExprBody() &&
                !node->pn_funbox->isArrow();
     }
 
     ParseNode* newObjectMethodOrPropertyDefinition(ParseNode* key, ParseNode* fn, AccessorType atype) {
         MOZ_ASSERT(isUsableAsObjectPropertyName(key));
 
-        return newBinary(PNK_COLON, key, fn, AccessorTypeToJSOp(atype));
+        return newBinary(ParseNodeKind::PNK_COLON, key, fn, AccessorTypeToJSOp(atype));
     }
 
     bool setComprehensionLambdaBody(ParseNode* pn, ParseNode* body) {
-        MOZ_ASSERT(body->isKind(PNK_STATEMENTLIST));
-        ParseNode* paramsBody = newList(PNK_PARAMSBODY, body);
+        MOZ_ASSERT(body->isKind(ParseNodeKind::PNK_STATEMENTLIST));
+        ParseNode* paramsBody = newList(ParseNodeKind::PNK_PARAMSBODY, body);
         if (!paramsBody)
             return false;
         setFunctionFormalParametersAndBody(pn, paramsBody);
         return true;
     }
     void setFunctionFormalParametersAndBody(ParseNode* funcNode, ParseNode* kid) {
-        MOZ_ASSERT_IF(kid, kid->isKind(PNK_PARAMSBODY));
+        MOZ_ASSERT_IF(kid, kid->isKind(ParseNodeKind::PNK_PARAMSBODY));
         funcNode->pn_body = kid;
     }
     void setFunctionBox(ParseNode* pn, FunctionBox* funbox) {
-        MOZ_ASSERT(pn->isKind(PNK_FUNCTION));
+        MOZ_ASSERT(pn->isKind(ParseNodeKind::PNK_FUNCTION));
         pn->pn_funbox = funbox;
         funbox->functionNode = pn;
     }
     void addFunctionFormalParameter(ParseNode* pn, ParseNode* argpn) {
         addList(/* list = */ pn->pn_body, /* child = */ argpn);
     }
     void setFunctionBody(ParseNode* fn, ParseNode* body) {
-        MOZ_ASSERT(fn->pn_body->isKind(PNK_PARAMSBODY));
+        MOZ_ASSERT(fn->pn_body->isKind(ParseNodeKind::PNK_PARAMSBODY));
         addList(/* list = */ fn->pn_body, /* child = */ body);
     }
 
     ParseNode* newModule(const TokenPos& pos) {
-        return new_<CodeNode>(PNK_MODULE, JSOP_NOP, pos);
+        return new_<CodeNode>(ParseNodeKind::PNK_MODULE, JSOP_NOP, pos);
     }
 
     ParseNode* newLexicalScope(LexicalScope::Data* bindings, ParseNode* body) {
         return new_<LexicalScopeNode>(bindings, body);
     }
 
     Node newNewExpression(uint32_t begin, ParseNode* ctor) {
-        ParseNode* newExpr = new_<ListNode>(PNK_NEW, JSOP_NEW, TokenPos(begin, begin + 1));
+        ParseNode* newExpr = new_<ListNode>(ParseNodeKind::PNK_NEW, JSOP_NEW, TokenPos(begin, begin + 1));
         if (!newExpr)
             return nullptr;
 
         addList(/* list = */ newExpr, /* child = */ ctor);
         return newExpr;
     }
 
     ParseNode* newAssignment(ParseNodeKind kind, ParseNode* lhs, ParseNode* rhs) {
         return newBinary(kind, lhs, rhs);
     }
 
     bool isUnparenthesizedAssignment(Node node) {
-        if (node->isKind(PNK_ASSIGN) && !node->isInParens()) {
-            // PNK_ASSIGN is also (mis)used for things like |var name = expr;|.
-            // But this method is only called on actual expressions, so we can
-            // just assert the node's op is the one used for plain assignment.
+        if (node->isKind(ParseNodeKind::PNK_ASSIGN) && !node->isInParens()) {
+            // ParseNodeKind::PNK_ASSIGN is also (mis)used for things like
+            // |var name = expr;|. But this method is only called on actual
+            // expressions, so we can just assert the node's op is the one used
+            // for plain assignment.
             MOZ_ASSERT(node->isOp(JSOP_NOP));
             return true;
         }
 
         return false;
     }
 
     bool isUnparenthesizedUnaryExpression(ParseNode* node) {
         if (!node->isInParens()) {
             ParseNodeKind kind = node->getKind();
-            return kind == PNK_VOID || kind == PNK_NOT || kind == PNK_BITNOT || kind == PNK_POS ||
-                   kind == PNK_NEG || IsTypeofKind(kind) || IsDeleteKind(kind);
+            return kind == ParseNodeKind::PNK_VOID ||
+                   kind == ParseNodeKind::PNK_NOT ||
+                   kind == ParseNodeKind::PNK_BITNOT ||
+                   kind == ParseNodeKind::PNK_POS ||
+                   kind == ParseNodeKind::PNK_NEG ||
+                   IsTypeofKind(kind) ||
+                   IsDeleteKind(kind);
         }
         return false;
     }
 
     bool isReturnStatement(ParseNode* node) {
-        return node->isKind(PNK_RETURN);
+        return node->isKind(ParseNodeKind::PNK_RETURN);
     }
 
     bool isStatementPermittedAfterReturnStatement(ParseNode *node) {
         ParseNodeKind kind = node->getKind();
-        return kind == PNK_FUNCTION || kind == PNK_VAR || kind == PNK_BREAK || kind == PNK_THROW ||
-               (kind == PNK_SEMI && !node->pn_kid);
+        return kind == ParseNodeKind::PNK_FUNCTION ||
+               kind == ParseNodeKind::PNK_VAR ||
+               kind == ParseNodeKind::PNK_BREAK ||
+               kind == ParseNodeKind::PNK_THROW ||
+               (kind == ParseNodeKind::PNK_SEMI && !node->pn_kid);
     }
 
     bool isSuperBase(ParseNode* node) {
-        return node->isKind(PNK_SUPERBASE);
+        return node->isKind(ParseNodeKind::PNK_SUPERBASE);
     }
 
     bool isUsableAsObjectPropertyName(ParseNode* node) {
-        return node->isKind(PNK_NUMBER)
-            || node->isKind(PNK_OBJECT_PROPERTY_NAME)
-            || node->isKind(PNK_STRING)
-            || node->isKind(PNK_COMPUTED_NAME);
+        return node->isKind(ParseNodeKind::PNK_NUMBER)
+            || node->isKind(ParseNodeKind::PNK_OBJECT_PROPERTY_NAME)
+            || node->isKind(ParseNodeKind::PNK_STRING)
+            || node->isKind(ParseNodeKind::PNK_COMPUTED_NAME);
     }
 
     inline MOZ_MUST_USE bool finishInitializerAssignment(ParseNode* pn, ParseNode* init);
 
     void setBeginPosition(ParseNode* pn, ParseNode* oth) {
         setBeginPosition(pn, oth->pn_pos.begin);
     }
     void setBeginPosition(ParseNode* pn, uint32_t begin) {
@@ -792,17 +809,19 @@ class FullParseHandler
         MOZ_ASSERT(pn->pn_pos.begin <= pn->pn_pos.end);
     }
 
     uint32_t getFunctionNameOffset(ParseNode* func, TokenStreamAnyChars& ts) {
         return func->pn_pos.begin;
     }
 
     bool isDeclarationKind(ParseNodeKind kind) {
-        return kind == PNK_VAR || kind == PNK_LET || kind == PNK_CONST;
+        return kind == ParseNodeKind::PNK_VAR ||
+               kind == ParseNodeKind::PNK_LET ||
+               kind == ParseNodeKind::PNK_CONST;
     }
 
     ParseNode* newList(ParseNodeKind kind, const TokenPos& pos) {
         MOZ_ASSERT(!isDeclarationKind(kind));
         return new_<ListNode>(kind, JSOP_NOP, pos);
     }
 
   private:
@@ -826,17 +845,17 @@ class FullParseHandler
 
     ParseNode* singleBindingFromDeclaration(ParseNode* decl) {
         MOZ_ASSERT(isDeclarationList(decl));
         MOZ_ASSERT(decl->pn_count == 1);
         return decl->pn_head;
     }
 
     ParseNode* newCommaExpressionList(ParseNode* kid) {
-        return new_<ListNode>(PNK_COMMA, JSOP_NOP, kid);
+        return new_<ListNode>(ParseNodeKind::PNK_COMMA, JSOP_NOP, kid);
     }
 
     void addList(ParseNode* list, ParseNode* kid) {
         if (sourceKind_ == SourceKind::Text)
             list->append(kid);
         else
             list->appendWithoutOrderAssumption(kid);
     }
@@ -859,29 +878,29 @@ class FullParseHandler
         pn->pn_prologue = true;
     }
 
     bool isConstant(ParseNode* pn) {
         return pn->isConstant();
     }
 
     bool isName(ParseNode* node) {
-        return node->isKind(PNK_NAME);
+        return node->isKind(ParseNodeKind::PNK_NAME);
     }
 
     bool isArgumentsName(ParseNode* node, JSContext* cx) {
-        return node->isKind(PNK_NAME) && node->pn_atom == cx->names().arguments;
+        return node->isKind(ParseNodeKind::PNK_NAME) && node->pn_atom == cx->names().arguments;
     }
 
     bool isEvalName(ParseNode* node, JSContext* cx) {
-        return node->isKind(PNK_NAME) && node->pn_atom == cx->names().eval;
+        return node->isKind(ParseNodeKind::PNK_NAME) && node->pn_atom == cx->names().eval;
     }
 
     bool isAsyncKeyword(ParseNode* node, JSContext* cx) {
-        return node->isKind(PNK_NAME) &&
+        return node->isKind(ParseNodeKind::PNK_NAME) &&
                node->pn_pos.begin + strlen("async") == node->pn_pos.end &&
                node->pn_atom == cx->names().async;
     }
 
     PropertyName* maybeDottedProperty(ParseNode* pn) {
         return pn->is<PropertyAccess>() ? &pn->as<PropertyAccess>().name() : nullptr;
     }
     JSAtom* isStringExprStatement(ParseNode* pn, TokenPos* pos) {
@@ -924,21 +943,21 @@ FullParseHandler::addCatchBlock(ParseNod
     lexicalScope->setScopeBody(catchpn);
     return true;
 }
 
 inline bool
 FullParseHandler::setLastFunctionFormalParameterDefault(ParseNode* funcpn,
                                                         ParseNode* defaultValue)
 {
-    MOZ_ASSERT(funcpn->isKind(PNK_FUNCTION));
+    MOZ_ASSERT(funcpn->isKind(ParseNodeKind::PNK_FUNCTION));
     MOZ_ASSERT(funcpn->isArity(PN_CODE));
 
     ParseNode* arg = funcpn->pn_body->last();
-    ParseNode* pn = newBinary(PNK_ASSIGN, arg, defaultValue);
+    ParseNode* pn = newBinary(ParseNodeKind::PNK_ASSIGN, arg, defaultValue);
     if (!pn)
         return false;
 
     checkAndSetIsDirectRHSAnonFunction(defaultValue);
 
     funcpn->pn_body->pn_pos.end = pn->pn_pos.end;
     ParseNode* pnchild = funcpn->pn_body->pn_head;
     ParseNode* pnlast = funcpn->pn_body->last();
--- a/js/src/frontend/NameFunctions.cpp
+++ b/js/src/frontend/NameFunctions.cpp
@@ -29,28 +29,28 @@ class NameResolver
     JSContext* cx;
     size_t nparents;                /* number of parents in the parents array */
     MOZ_INIT_OUTSIDE_CTOR
     ParseNode* parents[MaxParents]; /* history of ParseNodes we've been looking at */
     StringBuffer* buf;              /* when resolving, buffer to append to */
 
     /* Test whether a ParseNode represents a function invocation */
     bool call(ParseNode* pn) {
-        return pn && pn->isKind(PNK_CALL);
+        return pn && pn->isKind(ParseNodeKind::PNK_CALL);
     }
 
     /*
      * Append a reference to a property named |name| to |buf|. If |name| is
      * a proper identifier name, then we append '.name'; otherwise, we
      * append '["name"]'.
      *
      * Note that we need the IsIdentifier check for atoms from both
-     * PNK_NAME nodes and PNK_STRING nodes: given code like a["b c"], the
-     * front end will produce a PNK_DOT with a PNK_NAME child whose name
-     * contains spaces.
+     * ParseNodeKind::PNK_NAME nodes and ParseNodeKind::PNK_STRING nodes:
+     * given code like a["b c"], the front end will produce a ParseNodeKind::PNK_DOT
+     * with a ParseNodeKind::PNK_NAME child whose name contains spaces.
      */
     bool appendPropertyReference(JSAtom* name) {
         if (IsIdentifier(name))
             return buf->append('.') && buf->append(name);
 
         /* Quote the string as needed. */
         JSString* source = QuoteString(cx, name, '"');
         return source && buf->append('[') && buf->append(source) && buf->append(']');
@@ -71,43 +71,43 @@ class NameResolver
     /*
      * Walk over the given ParseNode, attempting to convert it to a stringified
      * name that respresents where the function is being assigned to.
      *
      * |*foundName| is set to true if a name is found for the expression.
      */
     bool nameExpression(ParseNode* n, bool* foundName) {
         switch (n->getKind()) {
-          case PNK_DOT:
+          case ParseNodeKind::PNK_DOT:
             if (!nameExpression(n->expr(), foundName))
                 return false;
             if (!*foundName)
                 return true;
             return appendPropertyReference(n->pn_atom);
 
-          case PNK_NAME:
+          case ParseNodeKind::PNK_NAME:
             *foundName = true;
             return buf->append(n->pn_atom);
 
-          case PNK_THIS:
+          case ParseNodeKind::PNK_THIS:
             *foundName = true;
             return buf->append("this");
 
-          case PNK_ELEM:
+          case ParseNodeKind::PNK_ELEM:
             if (!nameExpression(n->pn_left, foundName))
                 return false;
             if (!*foundName)
                 return true;
             if (!buf->append('[') || !nameExpression(n->pn_right, foundName))
                 return false;
             if (!*foundName)
                 return true;
             return buf->append(']');
 
-          case PNK_NUMBER:
+          case ParseNodeKind::PNK_NUMBER:
             *foundName = true;
             return appendNumber(n->pn_dval);
 
           default:
             /* We're confused as to what to call this function. */
             *foundName = false;
             return true;
         }
@@ -130,50 +130,51 @@ class NameResolver
         *size = 0;
 
         for (int pos = nparents - 1; pos >= 0; pos--) {
             ParseNode* cur = parents[pos];
             if (cur->isAssignment())
                 return cur;
 
             switch (cur->getKind()) {
-              case PNK_NAME:     return cur;  /* found the initialized declaration */
-              case PNK_THIS:     return cur;  /* Setting a property of 'this'. */
-              case PNK_FUNCTION: return nullptr; /* won't find an assignment or declaration */
+              case ParseNodeKind::PNK_NAME:     return cur;  /* found the initialized declaration */
+              case ParseNodeKind::PNK_THIS:     return cur;  /* Setting a property of 'this'. */
+              case ParseNodeKind::PNK_FUNCTION: return nullptr; /* won't find an assignment or declaration */
 
-              case PNK_RETURN:
+              case ParseNodeKind::PNK_RETURN:
                 /*
                  * Normally the relevant parent of a node is its direct parent, but
                  * sometimes with code like:
                  *
                  *    var foo = (function() { return function() {}; })();
                  *
                  * the outer function is just a helper to create a scope for the
                  * returned function. Hence the name of the returned function should
                  * actually be 'foo'.  This loop sees if the current node is a
-                 * PNK_RETURN, and if there is a direct function call we skip to
-                 * that.
+                 * ParseNodeKind::PNK_RETURN, and if there is a direct function
+                 * call we skip to that.
                  */
                 for (int tmp = pos - 1; tmp > 0; tmp--) {
                     if (isDirectCall(tmp, cur)) {
                         pos = tmp;
                         break;
                     } else if (call(cur)) {
                         /* Don't skip too high in the tree */
                         break;
                     }
                     cur = parents[tmp];
                 }
                 break;
 
-              case PNK_COLON:
-              case PNK_SHORTHAND:
+              case ParseNodeKind::PNK_COLON:
+              case ParseNodeKind::PNK_SHORTHAND:
                 /*
-                 * Record the PNK_COLON/SHORTHAND but skip the PNK_OBJECT so we're not
-                 * flagged as a contributor.
+                 * Record the ParseNodeKind::PNK_COLON/SHORTHAND but skip the
+                 * ParseNodeKind::PNK_OBJECT so we're not flagged as a
+                 * contributor.
                  */
                 pos--;
                 MOZ_FALLTHROUGH;
 
               default:
                 /* Save any other nodes we encounter on the way up. */
                 MOZ_ASSERT(*size < MaxParents);
                 nameable[(*size)++] = cur;
@@ -186,17 +187,17 @@ class NameResolver
 
     /*
      * Resolve the name of a function. If the function already has a name
      * listed, then it is skipped. Otherwise an intelligent name is guessed to
      * assign to the function's displayAtom field.
      */
     bool resolveFun(ParseNode* pn, HandleAtom prefix, MutableHandleAtom retAtom) {
         MOZ_ASSERT(pn != nullptr);
-        MOZ_ASSERT(pn->isKind(PNK_FUNCTION));
+        MOZ_ASSERT(pn->isKind(ParseNodeKind::PNK_FUNCTION));
         MOZ_ASSERT(pn->isArity(PN_CODE));
         RootedFunction fun(cx, pn->pn_funbox->function());
 
         StringBuffer buf(cx);
         this->buf = &buf;
 
         retAtom.set(nullptr);
 
@@ -237,26 +238,28 @@ class NameResolver
         /*
          * Other than the actual assignment, other relevant nodes to naming are
          * those in object initializers and then particular nodes marking a
          * contribution.
          */
         for (int pos = size - 1; pos >= 0; pos--) {
             ParseNode* node = toName[pos];
 
-            if (node->isKind(PNK_COLON) || node->isKind(PNK_SHORTHAND)) {
+            if (node->isKind(ParseNodeKind::PNK_COLON) || node->isKind(ParseNodeKind::PNK_SHORTHAND)) {
                 ParseNode* left = node->pn_left;
-                if (left->isKind(PNK_OBJECT_PROPERTY_NAME) || left->isKind(PNK_STRING)) {
+                if (left->isKind(ParseNodeKind::PNK_OBJECT_PROPERTY_NAME) ||
+                    left->isKind(ParseNodeKind::PNK_STRING))
+                {
                     if (!appendPropertyReference(left->pn_atom))
                         return false;
-                } else if (left->isKind(PNK_NUMBER)) {
+                } else if (left->isKind(ParseNodeKind::PNK_NUMBER)) {
                     if (!appendNumericPropertyReference(left->pn_dval))
                         return false;
                 } else {
-                    MOZ_ASSERT(left->isKind(PNK_COMPUTED_NAME));
+                    MOZ_ASSERT(left->isKind(ParseNodeKind::PNK_COMPUTED_NAME));
                 }
             } else {
                 /*
                  * Don't have consecutive '<' characters, and also don't start
                  * with a '<' character.
                  */
                 if (!buf.empty() && buf.getChar(buf.length() - 1) != '<' && !buf.append('<'))
                     return false;
@@ -286,55 +289,57 @@ class NameResolver
      * This is the case for functions which do things like simply create a scope
      * for new variables and then return an anonymous function using this scope.
      */
     bool isDirectCall(int pos, ParseNode* cur) {
         return pos >= 0 && call(parents[pos]) && parents[pos]->pn_head == cur;
     }
 
     bool resolveTemplateLiteral(ParseNode* node, HandleAtom prefix) {
-        MOZ_ASSERT(node->isKind(PNK_TEMPLATE_STRING_LIST));
+        MOZ_ASSERT(node->isKind(ParseNodeKind::PNK_TEMPLATE_STRING_LIST));
         ParseNode* element = node->pn_head;
         while (true) {
-            MOZ_ASSERT(element->isKind(PNK_TEMPLATE_STRING));
+            MOZ_ASSERT(element->isKind(ParseNodeKind::PNK_TEMPLATE_STRING));
 
             element = element->pn_next;
             if (!element)
                 return true;
 
             if (!resolve(element, prefix))
                 return false;
 
             element = element->pn_next;
         }
     }
 
     bool resolveTaggedTemplate(ParseNode* node, HandleAtom prefix) {
-        MOZ_ASSERT(node->isKind(PNK_TAGGED_TEMPLATE));
+        MOZ_ASSERT(node->isKind(ParseNodeKind::PNK_TAGGED_TEMPLATE));
 
         ParseNode* element = node->pn_head;
 
         // The list head is a leading expression, e.g. |tag| in |tag`foo`|,
         // that might contain functions.
         if (!resolve(element, prefix))
             return false;
 
         // Next is the callsite object node.  This node only contains
         // internal strings or undefined and an array -- no user-controlled
         // expressions.
         element = element->pn_next;
 #ifdef DEBUG
         {
-            MOZ_ASSERT(element->isKind(PNK_CALLSITEOBJ));
+            MOZ_ASSERT(element->isKind(ParseNodeKind::PNK_CALLSITEOBJ));
             ParseNode* array = element->pn_head;
-            MOZ_ASSERT(array->isKind(PNK_ARRAY));
+            MOZ_ASSERT(array->isKind(ParseNodeKind::PNK_ARRAY));
             for (ParseNode* kid = array->pn_head; kid; kid = kid->pn_next)
-                MOZ_ASSERT(kid->isKind(PNK_TEMPLATE_STRING));
-            for (ParseNode* next = array->pn_next; next; next = next->pn_next)
-                MOZ_ASSERT(next->isKind(PNK_TEMPLATE_STRING) || next->isKind(PNK_RAW_UNDEFINED));
+                MOZ_ASSERT(kid->isKind(ParseNodeKind::PNK_TEMPLATE_STRING));
+            for (ParseNode* next = array->pn_next; next; next = next->pn_next) {
+                MOZ_ASSERT(next->isKind(ParseNodeKind::PNK_TEMPLATE_STRING) ||
+                           next->isKind(ParseNodeKind::PNK_RAW_UNDEFINED));
+            }
         }
 #endif
 
         // Next come any interpolated expressions in the tagged template.
         ParseNode* interpolated = element->pn_next;
         for (; interpolated; interpolated = interpolated->pn_next) {
             if (!resolve(interpolated, prefix))
                 return false;
@@ -351,18 +356,19 @@ class NameResolver
      * ParseNode instance given. The prefix is for each subsequent name, and
      * should initially be nullptr.
      */
     bool resolve(ParseNode* const cur, HandleAtom prefixArg = nullptr) {
         RootedAtom prefix(cx, prefixArg);
         if (cur == nullptr)
             return true;
 
-        MOZ_ASSERT((cur->isKind(PNK_FUNCTION) || cur->isKind(PNK_MODULE)) == cur->isArity(PN_CODE));
-        if (cur->isKind(PNK_FUNCTION)) {
+        MOZ_ASSERT(cur->isArity(PN_CODE) == (cur->isKind(ParseNodeKind::PNK_FUNCTION) ||
+                                             cur->isKind(ParseNodeKind::PNK_MODULE)));
+        if (cur->isKind(ParseNodeKind::PNK_FUNCTION)) {
             RootedAtom prefix2(cx);
             if (!resolveFun(cur, prefix, &prefix2))
                 return false;
 
             /*
              * If a function looks like (function(){})() where the parent node
              * of the definition of the function is a call, then it shouldn't
              * contribute anything to the namespace, so don't bother updating
@@ -377,214 +383,214 @@ class NameResolver
 
         auto initialParents = nparents;
         parents[initialParents] = cur;
         nparents++;
 
         switch (cur->getKind()) {
           // Nodes with no children that might require name resolution need no
           // further work.
-          case PNK_NOP:
-          case PNK_STRING:
-          case PNK_TEMPLATE_STRING:
-          case PNK_REGEXP:
-          case PNK_TRUE:
-          case PNK_FALSE:
-          case PNK_NULL:
-          case PNK_RAW_UNDEFINED:
-          case PNK_ELISION:
-          case PNK_GENERATOR:
-          case PNK_NUMBER:
-          case PNK_BREAK:
-          case PNK_CONTINUE:
-          case PNK_DEBUGGER:
-          case PNK_EXPORT_BATCH_SPEC:
-          case PNK_OBJECT_PROPERTY_NAME:
-          case PNK_POSHOLDER:
+          case ParseNodeKind::PNK_NOP:
+          case ParseNodeKind::PNK_STRING:
+          case ParseNodeKind::PNK_TEMPLATE_STRING:
+          case ParseNodeKind::PNK_REGEXP:
+          case ParseNodeKind::PNK_TRUE:
+          case ParseNodeKind::PNK_FALSE:
+          case ParseNodeKind::PNK_NULL:
+          case ParseNodeKind::PNK_RAW_UNDEFINED:
+          case ParseNodeKind::PNK_ELISION:
+          case ParseNodeKind::PNK_GENERATOR:
+          case ParseNodeKind::PNK_NUMBER:
+          case ParseNodeKind::PNK_BREAK:
+          case ParseNodeKind::PNK_CONTINUE:
+          case ParseNodeKind::PNK_DEBUGGER:
+          case ParseNodeKind::PNK_EXPORT_BATCH_SPEC:
+          case ParseNodeKind::PNK_OBJECT_PROPERTY_NAME:
+          case ParseNodeKind::PNK_POSHOLDER:
             MOZ_ASSERT(cur->isArity(PN_NULLARY));
             break;
 
-          case PNK_TYPEOFNAME:
-          case PNK_SUPERBASE:
+          case ParseNodeKind::PNK_TYPEOFNAME:
+          case ParseNodeKind::PNK_SUPERBASE:
             MOZ_ASSERT(cur->isArity(PN_UNARY));
-            MOZ_ASSERT(cur->pn_kid->isKind(PNK_NAME));
+            MOZ_ASSERT(cur->pn_kid->isKind(ParseNodeKind::PNK_NAME));
             MOZ_ASSERT(!cur->pn_kid->expr());
             break;
 
-          case PNK_NEWTARGET:
+          case ParseNodeKind::PNK_NEWTARGET:
             MOZ_ASSERT(cur->isArity(PN_BINARY));
-            MOZ_ASSERT(cur->pn_left->isKind(PNK_POSHOLDER));
-            MOZ_ASSERT(cur->pn_right->isKind(PNK_POSHOLDER));
+            MOZ_ASSERT(cur->pn_left->isKind(ParseNodeKind::PNK_POSHOLDER));
+            MOZ_ASSERT(cur->pn_right->isKind(ParseNodeKind::PNK_POSHOLDER));
             break;
 
           // Nodes with a single non-null child requiring name resolution.
-          case PNK_TYPEOFEXPR:
-          case PNK_VOID:
-          case PNK_NOT:
-          case PNK_BITNOT:
-          case PNK_THROW:
-          case PNK_DELETENAME:
-          case PNK_DELETEPROP:
-          case PNK_DELETEELEM:
-          case PNK_DELETEEXPR:
-          case PNK_NEG:
-          case PNK_POS:
-          case PNK_PREINCREMENT:
-          case PNK_POSTINCREMENT:
-          case PNK_PREDECREMENT:
-          case PNK_POSTDECREMENT:
-          case PNK_COMPUTED_NAME:
-          case PNK_SPREAD:
-          case PNK_MUTATEPROTO:
-          case PNK_EXPORT:
+          case ParseNodeKind::PNK_TYPEOFEXPR:
+          case ParseNodeKind::PNK_VOID:
+          case ParseNodeKind::PNK_NOT:
+          case ParseNodeKind::PNK_BITNOT:
+          case ParseNodeKind::PNK_THROW:
+          case ParseNodeKind::PNK_DELETENAME:
+          case ParseNodeKind::PNK_DELETEPROP:
+          case ParseNodeKind::PNK_DELETEELEM:
+          case ParseNodeKind::PNK_DELETEEXPR:
+          case ParseNodeKind::PNK_NEG:
+          case ParseNodeKind::PNK_POS:
+          case ParseNodeKind::PNK_PREINCREMENT:
+          case ParseNodeKind::PNK_POSTINCREMENT:
+          case ParseNodeKind::PNK_PREDECREMENT:
+          case ParseNodeKind::PNK_POSTDECREMENT:
+          case ParseNodeKind::PNK_COMPUTED_NAME:
+          case ParseNodeKind::PNK_SPREAD:
+          case ParseNodeKind::PNK_MUTATEPROTO:
+          case ParseNodeKind::PNK_EXPORT:
             MOZ_ASSERT(cur->isArity(PN_UNARY));
             if (!resolve(cur->pn_kid, prefix))
                 return false;
             break;
 
           // Nodes with a single nullable child.
-          case PNK_SEMI:
-          case PNK_THIS:
+          case ParseNodeKind::PNK_SEMI:
+          case ParseNodeKind::PNK_THIS:
             MOZ_ASSERT(cur->isArity(PN_UNARY));
             if (ParseNode* expr = cur->pn_kid) {
                 if (!resolve(expr, prefix))
                     return false;
             }
             break;
 
           // Binary nodes with two non-null children.
-          case PNK_ASSIGN:
-          case PNK_ADDASSIGN:
-          case PNK_SUBASSIGN:
-          case PNK_BITORASSIGN:
-          case PNK_BITXORASSIGN:
-          case PNK_BITANDASSIGN:
-          case PNK_LSHASSIGN:
-          case PNK_RSHASSIGN:
-          case PNK_URSHASSIGN:
-          case PNK_MULASSIGN:
-          case PNK_DIVASSIGN:
-          case PNK_MODASSIGN:
-          case PNK_POWASSIGN:
-          case PNK_COLON:
-          case PNK_SHORTHAND:
-          case PNK_DOWHILE:
-          case PNK_WHILE:
-          case PNK_SWITCH:
-          case PNK_FOR:
-          case PNK_CLASSMETHOD:
-          case PNK_SETTHIS:
+          case ParseNodeKind::PNK_ASSIGN:
+          case ParseNodeKind::PNK_ADDASSIGN:
+          case ParseNodeKind::PNK_SUBASSIGN:
+          case ParseNodeKind::PNK_BITORASSIGN:
+          case ParseNodeKind::PNK_BITXORASSIGN:
+          case ParseNodeKind::PNK_BITANDASSIGN:
+          case ParseNodeKind::PNK_LSHASSIGN:
+          case ParseNodeKind::PNK_RSHASSIGN:
+          case ParseNodeKind::PNK_URSHASSIGN:
+          case ParseNodeKind::PNK_MULASSIGN:
+          case ParseNodeKind::PNK_DIVASSIGN:
+          case ParseNodeKind::PNK_MODASSIGN:
+          case ParseNodeKind::PNK_POWASSIGN:
+          case ParseNodeKind::PNK_COLON:
+          case ParseNodeKind::PNK_SHORTHAND:
+          case ParseNodeKind::PNK_DOWHILE:
+          case ParseNodeKind::PNK_WHILE:
+          case ParseNodeKind::PNK_SWITCH:
+          case ParseNodeKind::PNK_FOR:
+          case ParseNodeKind::PNK_CLASSMETHOD:
+          case ParseNodeKind::PNK_SETTHIS:
             MOZ_ASSERT(cur->isArity(PN_BINARY));
             if (!resolve(cur->pn_left, prefix))
                 return false;
             if (!resolve(cur->pn_right, prefix))
                 return false;
             break;
 
-          case PNK_ELEM:
+          case ParseNodeKind::PNK_ELEM:
             MOZ_ASSERT(cur->isArity(PN_BINARY));
             if (!cur->as<PropertyByValue>().isSuper() && !resolve(cur->pn_left, prefix))
                 return false;
             if (!resolve(cur->pn_right, prefix))
                 return false;
             break;
 
-          case PNK_WITH:
+          case ParseNodeKind::PNK_WITH:
             MOZ_ASSERT(cur->isArity(PN_BINARY));
             if (!resolve(cur->pn_left, prefix))
                 return false;
             if (!resolve(cur->pn_right, prefix))
                 return false;
             break;
 
-          case PNK_CASE:
+          case ParseNodeKind::PNK_CASE:
             MOZ_ASSERT(cur->isArity(PN_BINARY));
             if (ParseNode* caseExpr = cur->pn_left) {
                 if (!resolve(caseExpr, prefix))
                     return false;
             }
             if (!resolve(cur->pn_right, prefix))
                 return false;
             break;
 
-          case PNK_INITIALYIELD:
-            MOZ_ASSERT(cur->pn_kid->isKind(PNK_ASSIGN) &&
-                       cur->pn_kid->pn_left->isKind(PNK_NAME) &&
-                       cur->pn_kid->pn_right->isKind(PNK_GENERATOR));
+          case ParseNodeKind::PNK_INITIALYIELD:
+            MOZ_ASSERT(cur->pn_kid->isKind(ParseNodeKind::PNK_ASSIGN) &&
+                       cur->pn_kid->pn_left->isKind(ParseNodeKind::PNK_NAME) &&
+                       cur->pn_kid->pn_right->isKind(ParseNodeKind::PNK_GENERATOR));
             break;
 
-          case PNK_YIELD_STAR:
+          case ParseNodeKind::PNK_YIELD_STAR:
             MOZ_ASSERT(cur->isArity(PN_UNARY));
             if (!resolve(cur->pn_kid, prefix))
                 return false;
             break;
 
-          case PNK_YIELD:
-          case PNK_AWAIT:
+          case ParseNodeKind::PNK_YIELD:
+          case ParseNodeKind::PNK_AWAIT:
             MOZ_ASSERT(cur->isArity(PN_UNARY));
             if (cur->pn_kid) {
                 if (!resolve(cur->pn_kid, prefix))
                     return false;
             }
             break;
 
-          case PNK_RETURN:
+          case ParseNodeKind::PNK_RETURN:
             MOZ_ASSERT(cur->isArity(PN_UNARY));
             if (ParseNode* returnValue = cur->pn_kid) {
                 if (!resolve(returnValue, prefix))
                     return false;
             }
             break;
 
-          case PNK_IMPORT:
-          case PNK_EXPORT_FROM:
-          case PNK_EXPORT_DEFAULT:
+          case ParseNodeKind::PNK_IMPORT:
+          case ParseNodeKind::PNK_EXPORT_FROM:
+          case ParseNodeKind::PNK_EXPORT_DEFAULT:
             MOZ_ASSERT(cur->isArity(PN_BINARY));
             // The left halves of these nodes don't contain any unconstrained
             // expressions, but it's very hard to assert this to safely rely on
             // it.  So recur anyway.
             if (!resolve(cur->pn_left, prefix))
                 return false;
-            MOZ_ASSERT_IF(!cur->isKind(PNK_EXPORT_DEFAULT),
-                          cur->pn_right->isKind(PNK_STRING));
+            MOZ_ASSERT_IF(!cur->isKind(ParseNodeKind::PNK_EXPORT_DEFAULT),
+                          cur->pn_right->isKind(ParseNodeKind::PNK_STRING));
             break;
 
           // Ternary nodes with three expression children.
-          case PNK_CONDITIONAL:
+          case ParseNodeKind::PNK_CONDITIONAL:
             MOZ_ASSERT(cur->isArity(PN_TERNARY));
             if (!resolve(cur->pn_kid1, prefix))
                 return false;
             if (!resolve(cur->pn_kid2, prefix))
                 return false;
             if (!resolve(cur->pn_kid3, prefix))
                 return false;
             break;
 
           // The first part of a for-in/of is the declaration in the loop (or
           // null if no declaration).  The latter two parts are the location
           // assigned each loop and the value being looped over; obviously,
           // either might contain functions to name.  Declarations may (through
           // computed property names, and possibly through [deprecated!]
           // initializers) also contain functions to name.
-          case PNK_FORIN:
-          case PNK_FOROF:
+          case ParseNodeKind::PNK_FORIN:
+          case ParseNodeKind::PNK_FOROF:
             MOZ_ASSERT(cur->isArity(PN_TERNARY));
             if (ParseNode* decl = cur->pn_kid1) {
                 if (!resolve(decl, prefix))
                     return false;
             }
             if (!resolve(cur->pn_kid2, prefix))
                 return false;
             if (!resolve(cur->pn_kid3, prefix))
                 return false;
             break;
 
           // Every part of a for(;;) head may contain a function needing name
           // resolution.
-          case PNK_FORHEAD:
+          case ParseNodeKind::PNK_FORHEAD:
             MOZ_ASSERT(cur->isArity(PN_TERNARY));
             if (ParseNode* init = cur->pn_kid1) {
                 if (!resolve(init, prefix))
                     return false;
             }
             if (ParseNode* cond = cur->pn_kid2) {
                 if (!resolve(cond, prefix))
                     return false;
@@ -593,220 +599,222 @@ class NameResolver
                 if (!resolve(step, prefix))
                     return false;
             }
             break;
 
           // The first child of a class is a pair of names referring to it,
           // inside and outside the class.  The second is the class's heritage,
           // if any.  The third is the class body.
-          case PNK_CLASS:
+          case ParseNodeKind::PNK_CLASS:
             MOZ_ASSERT(cur->isArity(PN_TERNARY));
-            MOZ_ASSERT_IF(cur->pn_kid1, cur->pn_kid1->isKind(PNK_CLASSNAMES));
+            MOZ_ASSERT_IF(cur->pn_kid1, cur->pn_kid1->isKind(ParseNodeKind::PNK_CLASSNAMES));
             MOZ_ASSERT_IF(cur->pn_kid1, cur->pn_kid1->isArity(PN_BINARY));
             MOZ_ASSERT_IF(cur->pn_kid1 && cur->pn_kid1->pn_left,
-                          cur->pn_kid1->pn_left->isKind(PNK_NAME));
+                          cur->pn_kid1->pn_left->isKind(ParseNodeKind::PNK_NAME));
             MOZ_ASSERT_IF(cur->pn_kid1 && cur->pn_kid1->pn_left,
                           !cur->pn_kid1->pn_left->expr());
-            MOZ_ASSERT_IF(cur->pn_kid1, cur->pn_kid1->pn_right->isKind(PNK_NAME));
+            MOZ_ASSERT_IF(cur->pn_kid1, cur->pn_kid1->pn_right->isKind(ParseNodeKind::PNK_NAME));
             MOZ_ASSERT_IF(cur->pn_kid1, !cur->pn_kid1->pn_right->expr());
             if (cur->pn_kid2) {
                 if (!resolve(cur->pn_kid2, prefix))
                     return false;
             }
             if (!resolve(cur->pn_kid3, prefix))
                 return false;
             break;
 
           // The condition and consequent are non-optional, but the alternative
           // might be omitted.
-          case PNK_IF:
+          case ParseNodeKind::PNK_IF:
             MOZ_ASSERT(cur->isArity(PN_TERNARY));
             if (!resolve(cur->pn_kid1, prefix))
                 return false;
             if (!resolve(cur->pn_kid2, prefix))
                 return false;
             if (cur->pn_kid3) {
                 if (!resolve(cur->pn_kid3, prefix))
                     return false;
             }
             break;
 
           // The statements in the try-block are mandatory.  The catch-blocks
           // and finally block are optional (but at least one or the other must
           // be present).
-          case PNK_TRY:
+          case ParseNodeKind::PNK_TRY:
             MOZ_ASSERT(cur->isArity(PN_TERNARY));
             if (!resolve(cur->pn_kid1, prefix))
                 return false;
             MOZ_ASSERT(cur->pn_kid2 || cur->pn_kid3);
             if (ParseNode* catchScope = cur->pn_kid2) {
-                MOZ_ASSERT(catchScope->isKind(PNK_LEXICALSCOPE));
-                MOZ_ASSERT(catchScope->scopeBody()->isKind(PNK_CATCH));
+                MOZ_ASSERT(catchScope->isKind(ParseNodeKind::PNK_LEXICALSCOPE));
+                MOZ_ASSERT(catchScope->scopeBody()->isKind(ParseNodeKind::PNK_CATCH));
                 MOZ_ASSERT(catchScope->scopeBody()->isArity(PN_BINARY));
                 if (!resolve(catchScope->scopeBody(), prefix))
                     return false;
             }
             if (ParseNode* finallyBlock = cur->pn_kid3) {
                 if (!resolve(finallyBlock, prefix))
                     return false;
             }
             break;
 
           // The first child, the catch-pattern, may contain functions via
           // computed property names.  The optional catch-conditions may
           // contain any expression.  The catch statements, of course, may
           // contain arbitrary expressions.
-          case PNK_CATCH:
+          case ParseNodeKind::PNK_CATCH:
             MOZ_ASSERT(cur->isArity(PN_BINARY));
             if (cur->pn_left) {
               if (!resolve(cur->pn_left, prefix))
                   return false;
             }
             if (!resolve(cur->pn_right, prefix))
                 return false;
             break;
 
           // Nodes with arbitrary-expression children.
-          case PNK_OR:
-          case PNK_AND:
-          case PNK_BITOR:
-          case PNK_BITXOR:
-          case PNK_BITAND:
-          case PNK_STRICTEQ:
-          case PNK_EQ:
-          case PNK_STRICTNE:
-          case PNK_NE:
-          case PNK_LT:
-          case PNK_LE:
-          case PNK_GT:
-          case PNK_GE:
-          case PNK_INSTANCEOF:
-          case PNK_IN:
-          case PNK_LSH:
-          case PNK_RSH:
-          case PNK_URSH:
-          case PNK_ADD:
-          case PNK_SUB:
-          case PNK_STAR:
-          case PNK_DIV:
-          case PNK_MOD:
-          case PNK_POW:
-          case PNK_PIPELINE:
-          case PNK_COMMA:
-          case PNK_NEW:
-          case PNK_CALL:
-          case PNK_SUPERCALL:
-          case PNK_ARRAY:
-          case PNK_STATEMENTLIST:
-          case PNK_PARAMSBODY:
+          case ParseNodeKind::PNK_OR:
+          case ParseNodeKind::PNK_AND:
+          case ParseNodeKind::PNK_BITOR:
+          case ParseNodeKind::PNK_BITXOR:
+          case ParseNodeKind::PNK_BITAND:
+          case ParseNodeKind::PNK_STRICTEQ:
+          case ParseNodeKind::PNK_EQ:
+          case ParseNodeKind::PNK_STRICTNE:
+          case ParseNodeKind::PNK_NE:
+          case ParseNodeKind::PNK_LT:
+          case ParseNodeKind::PNK_LE:
+          case ParseNodeKind::PNK_GT:
+          case ParseNodeKind::PNK_GE:
+          case ParseNodeKind::PNK_INSTANCEOF:
+          case ParseNodeKind::PNK_IN:
+          case ParseNodeKind::PNK_LSH:
+          case ParseNodeKind::PNK_RSH:
+          case ParseNodeKind::PNK_URSH:
+          case ParseNodeKind::PNK_ADD:
+          case ParseNodeKind::PNK_SUB:
+          case ParseNodeKind::PNK_STAR:
+          case ParseNodeKind::PNK_DIV:
+          case ParseNodeKind::PNK_MOD:
+          case ParseNodeKind::PNK_POW:
+          case ParseNodeKind::PNK_PIPELINE:
+          case ParseNodeKind::PNK_COMMA:
+          case ParseNodeKind::PNK_NEW:
+          case ParseNodeKind::PNK_CALL:
+          case ParseNodeKind::PNK_SUPERCALL:
+          case ParseNodeKind::PNK_ARRAY:
+          case ParseNodeKind::PNK_STATEMENTLIST:
+          case ParseNodeKind::PNK_PARAMSBODY:
           // Initializers for individual variables, and computed property names
           // within destructuring patterns, may contain unnamed functions.
-          case PNK_VAR:
-          case PNK_CONST:
-          case PNK_LET:
+          case ParseNodeKind::PNK_VAR:
+          case ParseNodeKind::PNK_CONST:
+          case ParseNodeKind::PNK_LET:
             MOZ_ASSERT(cur->isArity(PN_LIST));
             for (ParseNode* element = cur->pn_head; element; element = element->pn_next) {
                 if (!resolve(element, prefix))
                     return false;
             }
             break;
 
-          case PNK_OBJECT:
-          case PNK_CLASSMETHODLIST:
+          case ParseNodeKind::PNK_OBJECT:
+          case ParseNodeKind::PNK_CLASSMETHODLIST:
             MOZ_ASSERT(cur->isArity(PN_LIST));
             for (ParseNode* element = cur->pn_head; element; element = element->pn_next) {
                 if (!resolve(element, prefix))
                     return false;
             }
             break;
 
           // A template string list's contents alternate raw template string
           // contents with expressions interpolated into the overall literal.
-          case PNK_TEMPLATE_STRING_LIST:
+          case ParseNodeKind::PNK_TEMPLATE_STRING_LIST:
             MOZ_ASSERT(cur->isArity(PN_LIST));
             if (!resolveTemplateLiteral(cur, prefix))
                 return false;
             break;
 
-          case PNK_TAGGED_TEMPLATE:
+          case ParseNodeKind::PNK_TAGGED_TEMPLATE:
             MOZ_ASSERT(cur->isArity(PN_LIST));
             if (!resolveTaggedTemplate(cur, 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.
-          case PNK_EXPORT_SPEC_LIST:
-          case PNK_IMPORT_SPEC_LIST: {
+          case ParseNodeKind::PNK_EXPORT_SPEC_LIST:
+          case ParseNodeKind::PNK_IMPORT_SPEC_LIST: {
             MOZ_ASSERT(cur->isArity(PN_LIST));
 #ifdef DEBUG
-            bool isImport = cur->isKind(PNK_IMPORT_SPEC_LIST);
+            bool isImport = cur->isKind(ParseNodeKind::PNK_IMPORT_SPEC_LIST);
             ParseNode* item = cur->pn_head;
-            if (!isImport && item && item->isKind(PNK_EXPORT_BATCH_SPEC)) {
+            if (!isImport && item && item->isKind(ParseNodeKind::PNK_EXPORT_BATCH_SPEC)) {
                 MOZ_ASSERT(item->isArity(PN_NULLARY));
                 break;
             }
             for (; item; item = item->pn_next) {
-                MOZ_ASSERT(item->isKind(isImport ? PNK_IMPORT_SPEC : PNK_EXPORT_SPEC));
+                MOZ_ASSERT(item->isKind(isImport
+                                        ? ParseNodeKind::PNK_IMPORT_SPEC
+                                        : ParseNodeKind::PNK_EXPORT_SPEC));
                 MOZ_ASSERT(item->isArity(PN_BINARY));
-                MOZ_ASSERT(item->pn_left->isKind(PNK_NAME));
+                MOZ_ASSERT(item->pn_left->isKind(ParseNodeKind::PNK_NAME));
                 MOZ_ASSERT(!item->pn_left->expr());
-                MOZ_ASSERT(item->pn_right->isKind(PNK_NAME));
+                MOZ_ASSERT(item->pn_right->isKind(ParseNodeKind::PNK_NAME));
                 MOZ_ASSERT(!item->pn_right->expr());
             }
 #endif
             break;
           }
 
-          case PNK_DOT:
+          case ParseNodeKind::PNK_DOT:
             MOZ_ASSERT(cur->isArity(PN_NAME));
 
             // Super prop nodes do not have a meaningful LHS
             if (cur->as<PropertyAccess>().isSuper())
                 break;
             if (!resolve(cur->expr(), prefix))
                 return false;
             break;
 
-          case PNK_LABEL:
+          case ParseNodeKind::PNK_LABEL:
             MOZ_ASSERT(cur->isArity(PN_NAME));
             if (!resolve(cur->expr(), prefix))
                 return false;
             break;
 
-          case PNK_NAME:
+          case ParseNodeKind::PNK_NAME:
             MOZ_ASSERT(cur->isArity(PN_NAME));
             if (!resolve(cur->expr(), prefix))
                 return false;
             break;
 
-          case PNK_LEXICALSCOPE:
+          case ParseNodeKind::PNK_LEXICALSCOPE:
             MOZ_ASSERT(cur->isArity(PN_SCOPE));
             if (!resolve(cur->scopeBody(), prefix))
                 return false;
             break;
 
-          case PNK_FUNCTION:
-          case PNK_MODULE:
+          case ParseNodeKind::PNK_FUNCTION:
+          case ParseNodeKind::PNK_MODULE:
             MOZ_ASSERT(cur->isArity(PN_CODE));
             if (!resolve(cur->pn_body, prefix))
                 return false;
             break;
 
           // Kinds that should be handled by parent node resolution.
 
-          case PNK_IMPORT_SPEC: // by PNK_IMPORT_SPEC_LIST
-          case PNK_EXPORT_SPEC: // by PNK_EXPORT_SPEC_LIST
-          case PNK_CALLSITEOBJ: // by PNK_TAGGED_TEMPLATE
-          case PNK_CLASSNAMES:  // by PNK_CLASS
+          case ParseNodeKind::PNK_IMPORT_SPEC: // by ParseNodeKind::PNK_IMPORT_SPEC_LIST
+          case ParseNodeKind::PNK_EXPORT_SPEC: // by ParseNodeKind::PNK_EXPORT_SPEC_LIST
+          case ParseNodeKind::PNK_CALLSITEOBJ: // by ParseNodeKind::PNK_TAGGED_TEMPLATE
+          case ParseNodeKind::PNK_CLASSNAMES:  // by ParseNodeKind::PNK_CLASS
             MOZ_CRASH("should have been handled by a parent node");
 
-          case PNK_LIMIT: // invalid sentinel value
+          case ParseNodeKind::PNK_LIMIT: // invalid sentinel value
             MOZ_CRASH("invalid node kind");
         }
 
         nparents--;
         MOZ_ASSERT(initialParents == nparents, "nparents imbalance detected");
 
         // It would be nice to common up the repeated |parents[initialParents]|
         // in a single variable, but the #if condition required to prevent an
--- a/js/src/frontend/ParseNode-inl.h
+++ b/js/src/frontend/ParseNode-inl.h
@@ -12,24 +12,24 @@
 #include "frontend/SharedContext.h"
 
 namespace js {
 namespace frontend {
 
 inline PropertyName*
 ParseNode::name() const
 {
-    MOZ_ASSERT(isKind(PNK_FUNCTION) || isKind(PNK_NAME));
-    JSAtom* atom = isKind(PNK_FUNCTION) ? pn_funbox->function()->explicitName() : pn_atom;
+    MOZ_ASSERT(isKind(ParseNodeKind::PNK_FUNCTION) || isKind(ParseNodeKind::PNK_NAME));
+    JSAtom* atom = isKind(ParseNodeKind::PNK_FUNCTION) ? pn_funbox->function()->explicitName() : pn_atom;
     return atom->asPropertyName();
 }
 
 inline JSAtom*
 ParseNode::atom() const
 {
-    MOZ_ASSERT(isKind(PNK_STRING));
+    MOZ_ASSERT(isKind(ParseNodeKind::PNK_STRING));
     return pn_atom;
 }
 
 } /* namespace frontend */
 } /* namespace js */
 
 #endif /* frontend_ParseNode_inl_h */
--- a/js/src/frontend/ParseNode.cpp
+++ b/js/src/frontend/ParseNode.cpp
@@ -178,308 +178,310 @@ PushUnaryNodeChild(ParseNode* node, Node
  * just need to take care of its children.
  */
 static PushResult
 PushNodeChildren(ParseNode* pn, NodeStack* stack)
 {
     switch (pn->getKind()) {
       // Trivial nodes that refer to no nodes, are referred to by nothing
       // but their parents, are never used, and are never a definition.
-      case PNK_NOP:
-      case PNK_STRING:
-      case PNK_TEMPLATE_STRING:
-      case PNK_REGEXP:
-      case PNK_TRUE:
-      case PNK_FALSE:
-      case PNK_NULL:
-      case PNK_RAW_UNDEFINED:
-      case PNK_ELISION:
-      case PNK_GENERATOR:
-      case PNK_NUMBER:
-      case PNK_BREAK:
-      case PNK_CONTINUE:
-      case PNK_DEBUGGER:
-      case PNK_EXPORT_BATCH_SPEC:
-      case PNK_OBJECT_PROPERTY_NAME:
-      case PNK_POSHOLDER:
+      case ParseNodeKind::PNK_NOP:
+      case ParseNodeKind::PNK_STRING:
+      case ParseNodeKind::PNK_TEMPLATE_STRING:
+      case ParseNodeKind::PNK_REGEXP:
+      case ParseNodeKind::PNK_TRUE:
+      case ParseNodeKind::PNK_FALSE:
+      case ParseNodeKind::PNK_NULL:
+      case ParseNodeKind::PNK_RAW_UNDEFINED:
+      case ParseNodeKind::PNK_ELISION:
+      case ParseNodeKind::PNK_GENERATOR:
+      case ParseNodeKind::PNK_NUMBER:
+      case ParseNodeKind::PNK_BREAK:
+      case ParseNodeKind::PNK_CONTINUE:
+      case ParseNodeKind::PNK_DEBUGGER:
+      case ParseNodeKind::PNK_EXPORT_BATCH_SPEC:
+      case ParseNodeKind::PNK_OBJECT_PROPERTY_NAME:
+      case ParseNodeKind::PNK_POSHOLDER:
         MOZ_ASSERT(pn->isArity(PN_NULLARY));
         return PushResult::Recyclable;
 
       // Nodes with a single non-null child.
-      case PNK_TYPEOFNAME:
-      case PNK_TYPEOFEXPR:
-      case PNK_VOID:
-      case PNK_NOT:
-      case PNK_BITNOT:
-      case PNK_THROW:
-      case PNK_DELETENAME:
-      case PNK_DELETEPROP:
-      case PNK_DELETEELEM:
-      case PNK_DELETEEXPR:
-      case PNK_POS:
-      case PNK_NEG:
-      case PNK_PREINCREMENT:
-      case PNK_POSTINCREMENT:
-      case PNK_PREDECREMENT:
-      case PNK_POSTDECREMENT:
-      case PNK_COMPUTED_NAME:
-      case PNK_SPREAD:
-      case PNK_MUTATEPROTO:
-      case PNK_EXPORT:
-      case PNK_SUPERBASE:
+      case ParseNodeKind::PNK_TYPEOFNAME:
+      case ParseNodeKind::PNK_TYPEOFEXPR:
+      case ParseNodeKind::PNK_VOID:
+      case ParseNodeKind::PNK_NOT:
+      case ParseNodeKind::PNK_BITNOT:
+      case ParseNodeKind::PNK_THROW:
+      case ParseNodeKind::PNK_DELETENAME:
+      case ParseNodeKind::PNK_DELETEPROP:
+      case ParseNodeKind::PNK_DELETEELEM:
+      case ParseNodeKind::PNK_DELETEEXPR:
+      case ParseNodeKind::PNK_POS:
+      case ParseNodeKind::PNK_NEG:
+      case ParseNodeKind::PNK_PREINCREMENT:
+      case ParseNodeKind::PNK_POSTINCREMENT:
+      case ParseNodeKind::PNK_PREDECREMENT:
+      case ParseNodeKind::PNK_POSTDECREMENT:
+      case ParseNodeKind::PNK_COMPUTED_NAME:
+      case ParseNodeKind::PNK_SPREAD:
+      case ParseNodeKind::PNK_MUTATEPROTO:
+      case ParseNodeKind::PNK_EXPORT:
+      case ParseNodeKind::PNK_SUPERBASE:
         return PushUnaryNodeChild(pn, stack);
 
       // Nodes with a single nullable child.
-      case PNK_THIS:
-      case PNK_SEMI: {
+      case ParseNodeKind::PNK_THIS:
+      case ParseNodeKind::PNK_SEMI: {
         MOZ_ASSERT(pn->isArity(PN_UNARY));
         if (pn->pn_kid)
             stack->push(pn->pn_kid);
         return PushResult::Recyclable;
       }
 
       // Binary nodes with two non-null children.
 
       // All assignment and compound assignment nodes qualify.
-      case PNK_ASSIGN:
-      case PNK_ADDASSIGN:
-      case PNK_SUBASSIGN:
-      case PNK_BITORASSIGN:
-      case PNK_BITXORASSIGN:
-      case PNK_BITANDASSIGN:
-      case PNK_LSHASSIGN:
-      case PNK_RSHASSIGN:
-      case PNK_URSHASSIGN:
-      case PNK_MULASSIGN:
-      case PNK_DIVASSIGN:
-      case PNK_MODASSIGN:
-      case PNK_POWASSIGN:
+      case ParseNodeKind::PNK_ASSIGN:
+      case ParseNodeKind::PNK_ADDASSIGN:
+      case ParseNodeKind::PNK_SUBASSIGN:
+      case ParseNodeKind::PNK_BITORASSIGN:
+      case ParseNodeKind::PNK_BITXORASSIGN:
+      case ParseNodeKind::PNK_BITANDASSIGN: