Merge mozilla-central to autoland. CLOSED TREE
authorCsoregi Natalia <ncsoregi@mozilla.com>
Mon, 26 Nov 2018 18:22:02 +0200
changeset 504430 c4cd222f9e583b7453b9076e57d6f21af2b76c3e
parent 504429 61c3a6ce72a0de3582d7a5bd08b173facdfba901 (current diff)
parent 504419 6c10213a8924b377ea37a37385698ebb09773a30 (diff)
child 504431 311a5cdece03653e7c25a4498fe90158cca4bcb0
push id10290
push userffxbld-merge
push dateMon, 03 Dec 2018 16:23:23 +0000
treeherdermozilla-beta@700bed2445e6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone65.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 mozilla-central to autoland. CLOSED TREE
intl/locale/langGroups.properties
testing/web-platform/meta/css/css-text/writing-system/writing-system-font-001.html.ini
--- a/browser/components/aboutconfig/content/aboutconfig.js
+++ b/browser/components/aboutconfig/content/aboutconfig.js
@@ -33,27 +33,41 @@ function onLoad() {
   gPrefArray.sort((a, b) => a.name > b.name);
 
   document.getElementById("search").addEventListener("keypress", function(e) {
     if (e.code == "Enter") {
       filterPrefs();
     }
   });
 
-  document.getElementById("prefs").appendChild(createPrefsFragment(gPrefArray));
   document.getElementById("prefs").addEventListener("click", (event) => {
     if (event.target.localName != "button") {
       return;
     }
     let prefRow = event.target.closest("tr");
     let prefName = prefRow.getAttribute("aria-label");
-    Services.prefs.clearUserPref(prefName);
-    gPrefArray.splice(gPrefArray.findIndex(pref => pref.name == prefName), 1);
-    prefRow.remove();
+    let button = event.target.closest("button");
+    if (button.classList.contains("button-reset")) {
+      // Reset pref and update gPrefArray.
+      Services.prefs.clearUserPref(prefName);
+      let pref = gPrefArray.find(p => p.name == prefName);
+      pref.value = Preferences.get(prefName);
+      pref.hasUserValue = false;
+      // Update UI.
+      prefRow.textContent = "";
+      prefRow.classList.remove("has-user-value");
+      prefRow.appendChild(getPrefRow(pref));
+    } else {
+      Services.prefs.clearUserPref(prefName);
+      gPrefArray.splice(gPrefArray.findIndex(pref => pref.name == prefName), 1);
+      prefRow.remove();
+    }
   });
+
+  document.getElementById("prefs").appendChild(createPrefsFragment(gPrefArray));
 }
 
 function filterPrefs() {
   let substring = document.getElementById("search").value.trim();
   let fragment = createPrefsFragment(gPrefArray.filter(pref => pref.name.includes(substring)));
   document.getElementById("prefs").textContent = "";
   document.getElementById("prefs").appendChild(fragment);
 }
@@ -62,43 +76,53 @@ function createPrefsFragment(prefArray) 
   let fragment = document.createDocumentFragment();
   for (let pref of prefArray) {
     let row = document.createElement("tr");
     if (pref.hasUserValue) {
       row.classList.add("has-user-value");
     }
     row.setAttribute("aria-label", pref.name);
 
-    let nameCell = document.createElement("td");
-    // Add <wbr> behind dots to prevent line breaking in random mid-word places.
-    let parts = pref.name.split(".");
-    for (let i = 0; i < parts.length - 1; i++) {
-      nameCell.append(parts[i] + ".", document.createElement("wbr"));
-    }
-    nameCell.append(parts[parts.length - 1]);
-    row.appendChild(nameCell);
-
-    let valueCell = document.createElement("td");
-    valueCell.classList.add("cell-value");
-    valueCell.textContent = pref.value;
-    row.appendChild(valueCell);
-
-    let buttonCell = document.createElement("td");
-    if (!pref.hasDefaultValue) {
-      let button = document.createElement("button");
-      document.l10n.setAttributes(button, "about-config-pref-delete");
-      buttonCell.appendChild(button);
-    }
-    row.appendChild(buttonCell);
-
+    row.appendChild(getPrefRow(pref));
     fragment.appendChild(row);
   }
   return fragment;
 }
 
+function getPrefRow(pref) {
+  let rowFragment = document.createDocumentFragment();
+  let nameCell = document.createElement("td");
+  // Add <wbr> behind dots to prevent line breaking in random mid-word places.
+  let parts = pref.name.split(".");
+  for (let i = 0; i < parts.length - 1; i++) {
+    nameCell.append(parts[i] + ".", document.createElement("wbr"));
+  }
+  nameCell.append(parts[parts.length - 1]);
+  rowFragment.appendChild(nameCell);
+
+  let valueCell = document.createElement("td");
+  valueCell.classList.add("cell-value");
+  valueCell.textContent = pref.value;
+  rowFragment.appendChild(valueCell);
+
+  let buttonCell = document.createElement("td");
+  if (pref.hasUserValue) {
+    let button = document.createElement("button");
+    if (!pref.hasDefaultValue) {
+      document.l10n.setAttributes(button, "about-config-pref-delete");
+    } else {
+      document.l10n.setAttributes(button, "about-config-pref-reset");
+      button.className = "button-reset";
+    }
+    buttonCell.appendChild(button);
+  }
+  rowFragment.appendChild(buttonCell);
+  return rowFragment;
+}
+
 function prefHasDefaultValue(name) {
   try {
     switch (Services.prefs.getPrefType(name)) {
       case Ci.nsIPrefBranch.PREF_STRING:
         gDefaultBranch.getStringPref(name);
         return true;
       case Ci.nsIPrefBranch.PREF_INT:
         gDefaultBranch.getIntPref(name);
--- a/browser/components/aboutconfig/content/aboutconfig.notftl
+++ b/browser/components/aboutconfig/content/aboutconfig.notftl
@@ -1,10 +1,11 @@
 # 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/.
 
 about-config-title = about:config
 
-about-config-pref-delete = Delete
-
 about-config-search =
     .placeholder = Search
+
+about-config-pref-reset = Reset
+about-config-pref-delete = Delete
--- a/browser/components/aboutconfig/test/browser/browser.ini
+++ b/browser/components/aboutconfig/test/browser/browser.ini
@@ -1,6 +1,7 @@
 [DEFAULT]
 
 [browser_basic.js]
 [browser_edit.js]
+skip-if = debug # Bug 1507747
 [browser_search.js]
 skip-if = debug # Bug 1507747
--- a/browser/components/aboutconfig/test/browser/browser_edit.js
+++ b/browser/components/aboutconfig/test/browser/browser_edit.js
@@ -3,24 +3,93 @@
 
 const PAGE_URL = "chrome://browser/content/aboutconfig/aboutconfig.html";
 
 add_task(async function test_delete_user_pref() {
   Services.prefs.setBoolPref("userAddedPref", true);
   await BrowserTestUtils.withNewTab({
     gBrowser,
     url: PAGE_URL,
-  }, browser => {
-    return ContentTask.spawn(browser, null, () => {
+  }, async browser => {
+    await ContentTask.spawn(browser, null, () => {
       let list = [...content.document.getElementById("prefs")
         .getElementsByTagName("tr")];
       function getRow(name) {
         return list.find(row => row.querySelector("td").textContent == name);
       }
       Assert.ok(getRow("userAddedPref"));
       getRow("userAddedPref").lastChild.lastChild.click();
       list = [...content.document.getElementById("prefs")
         .getElementsByTagName("tr")];
       Assert.ok(!getRow("userAddedPref"));
       Assert.ok(!Services.prefs.getChildList("").includes("userAddedPref"));
+
+      // Search for nothing to test gPrefArray
+      let search = content.document.getElementById("search");
+      search.focus();
+    });
+
+    EventUtils.sendKey("return");
+    await ContentTask.spawn(browser, null, () => {
+      let list = [...content.document.getElementById("prefs")
+        .getElementsByTagName("tr")];
+      function getRow(name) {
+        return list.find(row => row.querySelector("td").textContent == name);
+      }
+      Assert.ok(!getRow("userAddedPref"));
     });
   });
 });
+
+add_task(async function test_reset_user_pref() {
+  await SpecialPowers.pushPrefEnv({"set": [["browser.autofocus", false]]});
+
+  await BrowserTestUtils.withNewTab({
+    gBrowser,
+    url: PAGE_URL,
+  }, async browser => {
+    await ContentTask.spawn(browser, null, () => {
+      ChromeUtils.import("resource://gre/modules/Preferences.jsm");
+
+      function getRow(name) {
+        return list.find(row => row.querySelector("td").textContent == name);
+      }
+      function getValue(name) {
+        return getRow(name).querySelector("td.cell-value").textContent;
+      }
+      let testPref = "browser.autofocus";
+      // Click reset.
+      let list = [...content.document.getElementById("prefs")
+        .getElementsByTagName("tr")];
+      let row = getRow(testPref);
+      row.lastChild.lastChild.click();
+      // Check new layout and reset.
+      list = [...content.document.getElementById("prefs")
+        .getElementsByTagName("tr")];
+      Assert.ok(!row.classList.contains("has-user-value"));
+      Assert.equal(row.childNodes[2].childNodes.length, 0);
+      Assert.ok(!Services.prefs.prefHasUserValue(testPref));
+      Assert.equal(getValue(testPref), "" + Preferences.get(testPref));
+
+      // Search for nothing to test gPrefArray
+      let search = content.document.getElementById("search");
+      search.focus();
+    });
+
+    EventUtils.sendKey("return");
+    await ContentTask.spawn(browser, null, () => {
+      function getRow(name) {
+        return list.find(row => row.querySelector("td").textContent == name);
+      }
+      function getValue(name) {
+        return getRow(name).querySelector("td.cell-value").textContent;
+      }
+      let testPref = "browser.autofocus";
+      // Check new layout and reset.
+      let list = [...content.document.getElementById("prefs")
+        .getElementsByTagName("tr")];
+      let row = getRow(testPref);
+      Assert.ok(!row.classList.contains("has-user-value"));
+      Assert.equal(row.childNodes[2].childNodes.length, 0);
+      Assert.equal(getValue(testPref), "" + Preferences.get(testPref));
+    });
+  });
+});
--- a/intl/locale/MozLocale.cpp
+++ b/intl/locale/MozLocale.cpp
@@ -129,29 +129,29 @@ Locale::AsString() const
     for (const auto& subTag : mPrivateUse) {
       tag.AppendLiteral("-");
       tag.Append(subTag);
     }
   }
   return tag;
 }
 
-const nsACString&
+const nsCString&
 Locale::GetLanguage() const
 {
   return mLanguage;
 }
 
-const nsACString&
+const nsCString&
 Locale::GetScript() const
 {
   return mScript;
 }
 
-const nsACString&
+const nsCString&
 Locale::GetRegion() const
 {
   return mRegion;
 }
 
 const nsTArray<nsCString>&
 Locale::GetVariants() const
 {
--- a/intl/locale/MozLocale.h
+++ b/intl/locale/MozLocale.h
@@ -62,19 +62,19 @@ class Locale {
      * If the input language tag string is not well-formed, the Locale will be
      * created with its flag `mWellFormed` set to false which will make the Locale never match.
      */
     explicit Locale(const nsACString& aLocale);
     explicit Locale(const char* aLocale)
       : Locale(nsDependentCString(aLocale))
       { };
 
-    const nsACString& GetLanguage() const;
-    const nsACString& GetScript() const;
-    const nsACString& GetRegion() const;
+    const nsCString& GetLanguage() const;
+    const nsCString& GetScript() const;
+    const nsCString& GetRegion() const;
     const nsTArray<nsCString>& GetVariants() const;
 
     /**
      * Returns a `true` if the locale is well-formed, such that the
      * Locale object can validly be matched against others.
      */
     bool IsWellFormed() const {
       return mIsWellFormed;
deleted file mode 100644
--- a/intl/locale/langGroups.properties
+++ /dev/null
@@ -1,240 +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/.
-#
-# References: http://www.omniglot.com/writing/atoz.htm
-#             http://www.loc.gov/standards/iso639-2/englangn.html
-#             http://www.ethnologue.com
-#             http://www.worldlanguage.com/Languages/
-#             http://www.rosettaproject.org/
-#             http://www.sweb.cz/ls78/diacritics.htm
-#    see also toolkit/locales/en-US/chrome/global/languageNames.properties
-#             and bug 178491
-#
-# Strictly speaking, Avestan did not use Arabic script but Aramaic
-# (arc)/Avestan script.)
-#ae=ar
-
-ab=x-cyrillic
-ach=x-western
-af=x-western
-alg=x-cans
-am=x-ethi
-an=x-western
-ar=ar
-as=x-beng
-ast=x-western
-ay=x-western
-az=x-western
-be=x-cyrillic
-bg=x-cyrillic
-bn=x-beng
-bo=x-tibt
-br=x-western
-bs=x-western
-ca=x-western
-cak=x-western
-ce=x-western
-ch=x-western
-co=x-western
-cr=x-cans
-crh=x-western
-cs=x-western
-csb=x-western
-#cu=x-cyrillic
-cv=x-cyrillic
-cy=x-western
-da=x-western
-de=x-western
-dsb=x-western
-#dv=Thaanna
-dz=x-tibt
-ee=x-western
-el=el
-en=x-western
-eo=x-western
-es=x-western
-et=x-western
-eu=x-western
-fa=ar
-ff=x-western
-fi=x-western
-fj=x-western
-fo=x-western
-fr=x-western
-fy=x-western
-ga=x-western
-gd=x-western
-gl=x-western
-gn=x-western
-#ha=x-western : Latin and Ajami scripts
-gu=x-gujr
-gv=x-western
-haw=x-western
-he=he
-hi=x-devanagari
-hil=x-western
-hr=x-western
-hsb=x-western
-ht=x-western
-hu=x-western
-hy=x-armn
-ia=x-western
-id=x-western
-ie=x-western
-is=x-western
-it=x-western
-iu=x-cans
-ja=ja
-ka=x-geor
-kab=x-western
-kk=x-cyrillic
-kl=x-western
-km=x-khmr
-kn=x-knda
-ko=ko
-kok=x-devanagari
-ks=ar
-# Arabic script is also used for Kurdish
-ku=x-western
-kw=x-western
-#ky=x-cyrillic
-la=x-western
-lb=x-western
-lij=x-western
-ln=x-western
-lt=x-western
-ltg=x-western
-lv=x-western
-mai=x-devanagari
-meh=x-western
-mg=x-western
-mh=x-western
-mi=x-western
-mix=x-western
-mk=x-cyrillic
-ml=x-mlym
-# Mongolian script is also used for Mongolian
-mn=x-cyrillic
-mr=x-devanagari
-ms=x-western
-mt=x-western
-na=x-western
-nb=x-western
-nd=x-western
-ne=x-devanagari
-nl=x-western
-nn=x-western
-no=x-western
-nr=x-western
-nso=x-western
-nv=x-western
-ny=x-western
-oc=x-western
-oj=x-cans
-om=x-western
-or=x-orya
-os=x-cyrillic
-#pa: Punjabi is usually written in Gurmukhi script in India and Arabic script
-#    in Pakistan. We make pa default to Gurmukhi based on comments in bug 248690
-pa-in=x-guru
-pa-pk=ar
-pa=x-guru
-pl=x-western
-ps=ar
-pt=x-western
-qu=x-western
-rm=x-western
-rn=x-western
-ro=x-western
-ru=x-cyrillic
-rw=x-western
-sa=x-devanagari
-sc=x-western
-sd=ar
-# African language (but related with French)
-sg=x-western
-sh=x-western
-si=x-sinh
-sk=x-western
-sl=x-western
-sm=x-western
-so=x-western
-son=x-western
-sq=x-western
-sr=x-cyrillic
-ss=x-western
-st=x-western
-sv=x-western
-sw=x-western
-ta=x-tamil
-te=x-telu
-th=th
-ti=x-ethi
-tig=x-ethi
-tk=x-cyrillic
-#tk=x-western # (The country declared in 1992 to gradually move to Latin script)
-tl=x-western
-tlh=x-western
-tn=x-western
-to=x-western
-tr=x-western
-ts=x-western
-tt=x-western
-uk=x-cyrillic
-ur=ar
-uz=x-western
-ve=x-western
-vi=x-western
-vo=x-western
-wa=x-western
-wo=x-western
-xh=x-western
-yi=he
-yo=x-western
-zam=x-western
-zh-cn=zh-CN
-# XXX : The following five entries are added as a quick fix (bug 251241, bug 1104589).
-# When we have a general solution for ISO 15924 (script codes), the issue has
-# to be revisited.
-zh-hans=zh-CN
-zh-hant=zh-TW
-zh-latn=x-western
-ja-latn=x-western
-ko-latn=x-western
-#
-zh-tw=zh-TW
-zh-hk=zh-HK
-zh=zh-CN
-zh-min-nan=x-western
-zu=x-western
-#
-#==============================
-#
-# mapping mozilla's internal x-* to themselves (see bug 256257)
-x-western=x-western
-x-cyrillic=x-cyrillic
-# el
-# he
-# ar
-# th
-# ja
-# zh-CN
-# ko
-# zh-TW
-x-tamil=x-tamil
-x-devanagari=x-devanagari
-x-unicode=x-unicode
-x-armn=x-armn
-x-geor=x-geor
-x-math=x-math
-# These self-mappings are not necessary unless somebody use them to specify
-# lang in (X)HTML/XML documents, which they shouldn't. (see bug 256257)
-#x-beng=x-beng
-#x-cans=x-cans
-#x-ethi=x-ethi
-#x-guru=x-guru
-#x-gujr=x-gujr
-#x-khmr=x-khmr
-#x-mlym=x-mlym
--- a/intl/locale/moz.build
+++ b/intl/locale/moz.build
@@ -60,17 +60,16 @@ LOCAL_INCLUDES += [
 ]
 
 RESOURCE_FILES += [
     'language.properties',
 ]
 
 prefixes = (
     'encodingsgroups',
-    'langGroups',
 )
 
 for prefix in prefixes:
     input_file = prefix + '.properties'
     header = prefix + '.properties.h'
     GENERATED_FILES += [header]
     props = GENERATED_FILES[header]
     props.script = 'props2arrays.py'
--- a/intl/locale/nsLanguageAtomService.cpp
+++ b/intl/locale/nsLanguageAtomService.cpp
@@ -15,18 +15,78 @@
 
 using namespace mozilla;
 using mozilla::intl::OSPreferences;
 
 static constexpr nsUConvProp encodingsGroups[] = {
 #include "encodingsgroups.properties.h"
 };
 
-static constexpr nsUConvProp kLangGroups[] = {
-#include "langGroups.properties.h"
+// List of mozilla internal x-* tags that map to themselves (see bug 256257)
+static constexpr const char* kLangGroups[] = {
+  // This list must be sorted!
+  "x-armn",
+  "x-cyrillic",
+  "x-devanagari",
+  "x-geor",
+  "x-math",
+  "x-tamil",
+  "x-unicode",
+  "x-western"
+  // These self-mappings are not necessary unless somebody use them to specify
+  // lang in (X)HTML/XML documents, which they shouldn't. (see bug 256257)
+  // x-beng=x-beng
+  // x-cans=x-cans
+  // x-ethi=x-ethi
+  // x-guru=x-guru
+  // x-gujr=x-gujr
+  // x-khmr=x-khmr
+  // x-mlym=x-mlym
+};
+
+// Map ISO 15924 script codes from BCP47 lang tag to mozilla's langGroups.
+static constexpr struct {
+  const char* mTag;
+  nsAtom*     mAtom;
+} kScriptLangGroup[] =
+{
+  // This list must be sorted by script code!
+  { "Arab", nsGkAtoms::ar },
+  { "Armn", nsGkAtoms::x_armn },
+  { "Beng", nsGkAtoms::x_beng },
+  { "Cans", nsGkAtoms::x_cans },
+  { "Cyrl", nsGkAtoms::x_cyrillic },
+  { "Deva", nsGkAtoms::x_devanagari },
+  { "Ethi", nsGkAtoms::x_ethi },
+  { "Geok", nsGkAtoms::x_geor },
+  { "Geor", nsGkAtoms::x_geor },
+  { "Grek", nsGkAtoms::el },
+  { "Gujr", nsGkAtoms::x_gujr },
+  { "Guru", nsGkAtoms::x_guru },
+  { "Hang", nsGkAtoms::ko },
+  { "Hani", nsGkAtoms::Japanese },
+  { "Hans", nsGkAtoms::Chinese },
+  // Hant is special-cased in code
+  // Hant=zh-HK
+  // Hant=zh-TW
+  { "Hebr", nsGkAtoms::he },
+  { "Hira", nsGkAtoms::Japanese },
+  { "Jpan", nsGkAtoms::Japanese },
+  { "Kana", nsGkAtoms::Japanese },
+  { "Khmr", nsGkAtoms::x_khmr },
+  { "Knda", nsGkAtoms::x_knda },
+  { "Kore", nsGkAtoms::ko },
+  { "Latn", nsGkAtoms::x_western },
+  { "Mlym", nsGkAtoms::x_mlym },
+  { "Orya", nsGkAtoms::x_orya },
+  { "Sinh", nsGkAtoms::x_sinh },
+  { "Taml", nsGkAtoms::x_tamil },
+  { "Telu", nsGkAtoms::x_telu },
+  { "Thai", nsGkAtoms::th },
+  { "Tibt", nsGkAtoms::x_tibt }
 };
 
 // static
 nsLanguageAtomService*
 nsLanguageAtomService::GetService()
 {
   static UniquePtr<nsLanguageAtomService> gLangAtomService;
   if (!gLangAtomService) {
@@ -106,29 +166,53 @@ nsLanguageAtomService::GetLanguageGroup(
 
 already_AddRefed<nsAtom>
 nsLanguageAtomService::GetUncachedLanguageGroup(nsAtom* aLanguage) const
 {
   nsAutoCString langStr;
   aLanguage->ToUTF8String(langStr);
   ToLowerCase(langStr);
 
-  nsAutoCString langGroupStr;
-  nsresult res =
-    nsUConvPropertySearch::SearchPropertyValue(kLangGroups,
-                                               ArrayLength(kLangGroups),
-                                               langStr, langGroupStr);
-  while (NS_FAILED(res)) {
-    int32_t hyphen = langStr.RFindChar('-');
-    if (hyphen <= 0) {
-      langGroupStr.AssignLiteral("x-unicode");
-      break;
+  RefPtr<nsAtom> langGroup;
+  if (langStr[0] == 'x' && langStr[1] == '-') {
+    // Internal x-* langGroup codes map to themselves (see bug 256257)
+    size_t unused;
+    if (BinarySearchIf(kLangGroups, 0, ArrayLength(kLangGroups),
+                       [&langStr](const char* tag) -> int {
+                         return langStr.Compare(tag);
+                       },
+                       &unused)) {
+      langGroup = NS_Atomize(langStr);
+      return langGroup.forget();
     }
-    langStr.Truncate(hyphen);
-    res = nsUConvPropertySearch::SearchPropertyValue(kLangGroups,
-                                                     ArrayLength(kLangGroups),
-                                                     langStr, langGroupStr);
+  } else if (!langStr.IsEmpty()) {
+    // If the lang code can be parsed as BCP47, look up its (likely) script
+    Locale loc(langStr);
+    if (loc.IsWellFormed()) {
+      if (loc.GetScript().IsEmpty()) {
+        loc.AddLikelySubtags();
+      }
+      if (loc.GetScript().EqualsLiteral("Hant")) {
+        if (loc.GetRegion().EqualsLiteral("HK")) {
+          langGroup = nsGkAtoms::HongKongChinese;
+        } else {
+          langGroup = nsGkAtoms::Taiwanese;
+        }
+        return langGroup.forget();
+      } else {
+        size_t foundIndex;
+        const nsCString& script = loc.GetScript();
+        if (BinarySearchIf(kScriptLangGroup, 0, ArrayLength(kScriptLangGroup),
+                           [script](const auto& entry) -> int {
+                             return script.Compare(entry.mTag);
+                           },
+                           &foundIndex)) {
+          langGroup = kScriptLangGroup[foundIndex].mAtom;
+          return langGroup.forget();
+        }
+      }
+    }
   }
 
-  RefPtr<nsAtom> langGroup = NS_Atomize(langGroupStr);
-
+  // Fall back to x-unicode if no match was found
+  langGroup = nsGkAtoms::Unicode;
   return langGroup.forget();
 }
--- a/js/src/gc/GC.cpp
+++ b/js/src/gc/GC.cpp
@@ -588,17 +588,16 @@ Arena::finalize(FreeOp* fop, AllocKind t
     MOZ_ASSERT(thingSize % CellAlignBytes == 0);
     MOZ_ASSERT(thingSize >= MinCellSize);
     MOZ_ASSERT(thingSize <= 255);
 
     MOZ_ASSERT(allocated());
     MOZ_ASSERT(thingKind == getAllocKind());
     MOZ_ASSERT(thingSize == getThingSize());
     MOZ_ASSERT(!hasDelayedMarking);
-    MOZ_ASSERT(!markOverflow);
 
     uint_fast16_t firstThing = firstThingOffset(thingKind);
     uint_fast16_t firstThingOrSuccessorOfLastMarkedThing = firstThing;
     uint_fast16_t lastThing = ArenaSize - thingSize;
 
     FreeSpan newListHead;
     FreeSpan* newListTail = &newListHead;
     size_t nmarked = 0;
@@ -2202,17 +2201,16 @@ GCMarker::delayMarkingArena(Arena* arena
     markLaterArenas++;
 #endif
 }
 
 void
 GCMarker::delayMarkingChildren(const void* thing)
 {
     const TenuredCell* cell = TenuredCell::fromPointer(thing);
-    cell->arena()->markOverflow = 1;
     delayMarkingArena(cell->arena());
 }
 
 /* Compacting GC */
 
 bool
 GCRuntime::shouldCompact()
 {
@@ -2427,17 +2425,16 @@ RelocateCell(Zone* zone, TenuredCell* sr
     overlay->forwardTo(dst);
 }
 
 static void
 RelocateArena(Arena* arena, SliceBudget& sliceBudget)
 {
     MOZ_ASSERT(arena->allocated());
     MOZ_ASSERT(!arena->hasDelayedMarking);
-    MOZ_ASSERT(!arena->markOverflow);
     MOZ_ASSERT(arena->bufferedCells()->isEmpty());
 
     Zone* zone = arena->zone;
 
     AllocKind thingKind = arena->getAllocKind();
     size_t thingSize = arena->getThingSize();
 
     for (ArenaCellIterUnderGC i(arena); !i.done(); i.next()) {
@@ -5004,27 +5001,27 @@ js::gc::MarkingValidator::nonIncremental
         gcstats::AutoPhase ap2(gc->stats(), gcstats::PhaseKind::SWEEP_MARK);
 
         gc->markAllWeakReferences(gcstats::PhaseKind::SWEEP_MARK_WEAK);
 
         /* Update zone state for gray marking. */
         for (GCZonesIter zone(runtime); !zone.done(); zone.next()) {
             zone->changeGCState(Zone::Mark, Zone::MarkGray);
         }
-        gc->marker.setMarkColorGray();
+
+        AutoSetMarkColor setColorGray(gc->marker, MarkColor::Gray);
 
         gc->markAllGrayReferences(gcstats::PhaseKind::SWEEP_MARK_GRAY);
         gc->markAllWeakReferences(gcstats::PhaseKind::SWEEP_MARK_GRAY_WEAK);
 
         /* Restore zone state. */
         for (GCZonesIter zone(runtime); !zone.done(); zone.next()) {
             zone->changeGCState(Zone::MarkGray, Zone::Mark);
         }
         MOZ_ASSERT(gc->marker.isDrained());
-        gc->marker.setMarkColorBlack();
     }
 
     /* Take a copy of the non-incremental mark state and restore the original. */
     {
         AutoLockGC lock(runtime);
         for (auto chunk = gc->allNonEmptyChunks(lock); !chunk.done(); chunk.next()) {
             ChunkBitmap* bitmap = &chunk->bitmap;
             ChunkBitmap* entry = map.lookup(chunk)->value().get();
@@ -5630,32 +5627,32 @@ GCRuntime::endMarkingSweepGroup(FreeOp* 
 
     // Change state of current group to MarkGray to restrict marking to this
     // group.  Note that there may be pointers to the atoms zone, and
     // these will be marked through, as they are not marked with
     // TraceCrossCompartmentEdge.
     for (SweepGroupZonesIter zone(rt); !zone.done(); zone.next()) {
         zone->changeGCState(Zone::Mark, Zone::MarkGray);
     }
-    marker.setMarkColorGray();
+
+    AutoSetMarkColor setColorGray(marker, MarkColor::Gray);
 
     // Mark incoming gray pointers from previously swept compartments.
     markIncomingCrossCompartmentPointers(MarkColor::Gray);
 
     // Mark gray roots and mark transitively inside the current compartment
     // group.
     markGrayReferencesInCurrentGroup(gcstats::PhaseKind::SWEEP_MARK_GRAY);
     markWeakReferencesInCurrentGroup(gcstats::PhaseKind::SWEEP_MARK_GRAY_WEAK);
 
     // Restore marking state.
     for (SweepGroupZonesIter zone(rt); !zone.done(); zone.next()) {
         zone->changeGCState(Zone::MarkGray, Zone::Mark);
     }
     MOZ_ASSERT(marker.isDrained());
-    marker.setMarkColorBlack();
 
     // We must not yield after this point before we start sweeping the group.
     safeToYield = false;
 
     return Finished;
 }
 
 // Causes the given WeakCache to be swept when run.
@@ -7468,38 +7465,38 @@ GCRuntime::incrementalSlice(SliceBudget&
         MOZ_FALLTHROUGH;
 
       case State::MarkRoots:
         if (!beginMarkPhase(reason, session)) {
             incrementalState = State::NotActive;
             return IncrementalResult::Ok;
         }
 
+        /* If we needed delayed marking for gray roots, then collect until done. */
+        if (isIncremental && !hasValidGrayRootsBuffer()) {
+            budget.makeUnlimited();
+            isIncremental = false;
+            stats().nonincremental(AbortReason::GrayRootBufferingFailed);
+        }
+
         if (!destroyingRuntime) {
             pushZealSelectedObjects();
         }
 
         incrementalState = State::Mark;
 
         if (isIncremental && useZeal && hasZealMode(ZealMode::YieldBeforeMarking)) {
             break;
         }
 
         MOZ_FALLTHROUGH;
 
       case State::Mark:
         AutoGCRooter::traceAllWrappers(rt->mainContextFromOwnThread(), &marker);
 
-        // If we needed delayed marking for gray roots, then collect until done.
-        if (isIncremental && !hasValidGrayRootsBuffer()) {
-            budget.makeUnlimited();
-            isIncremental = false;
-            stats().nonincremental(AbortReason::GrayRootBufferingFailed);
-        }
-
         if (markUntilBudgetExhaused(budget, gcstats::PhaseKind::MARK) == NotFinished) {
             break;
         }
 
         MOZ_ASSERT(marker.isDrained());
 
         /*
          * There are a number of reasons why we break out of collection here,
--- a/js/src/gc/GCMarker.h
+++ b/js/src/gc/GCMarker.h
@@ -265,26 +265,19 @@ class GCMarker : public JSTracer
 
     /*
      * Care must be taken changing the mark color from gray to black. The cycle
      * collector depends on the invariant that there are no black to gray edges
      * in the GC heap. This invariant lets the CC not trace through black
      * objects. If this invariant is violated, the cycle collector may free
      * objects that are still reachable.
      */
-    void setMarkColorGray() {
-        MOZ_ASSERT(isDrained());
-        MOZ_ASSERT(color == gc::MarkColor::Black);
-        color = gc::MarkColor::Gray;
-    }
-    void setMarkColorBlack() {
-        MOZ_ASSERT(isDrained());
-        MOZ_ASSERT(color == gc::MarkColor::Gray);
-        color = gc::MarkColor::Black;
-    }
+    void setMarkColorGray();
+    void setMarkColorBlack();
+    void setMarkColor(gc::MarkColor newColor);
     gc::MarkColor markColor() const { return color; }
 
     void enterWeakMarkingMode();
     void leaveWeakMarkingMode();
     void abortLinearWeakMarking() {
         leaveWeakMarkingMode();
         linearWeakMarkingDisabled_ = true;
     }
@@ -394,16 +387,44 @@ class GCMarker : public JSTracer
     /*
      * If this is true, all marked objects must belong to a compartment being
      * GCed. This is used to look for compartment bugs.
      */
     MainThreadData<bool> strictCompartmentChecking;
 #endif // DEBUG
 };
 
+namespace gc {
+
+/*
+ * Temporarily change the mark color while this class is on the stack.
+ *
+ * During incremental sweeping this also transitions zones in the
+ * current sweep group into the Mark or MarkGray state as appropriate.
+ */
+class MOZ_RAII AutoSetMarkColor
+{
+    GCMarker& marker_;
+    MarkColor initialColor_;
+
+  public:
+    AutoSetMarkColor(GCMarker& marker, MarkColor newColor)
+      : marker_(marker),
+        initialColor_(marker.markColor())
+    {
+        marker_.setMarkColor(newColor);
+    }
+
+    ~AutoSetMarkColor() {
+        marker_.setMarkColor(initialColor_);
+    }
+};
+
+} /* namespace gc */
+
 } /* namespace js */
 
 // Exported for Tracer.cpp
 inline bool ThingIsPermanentAtomOrWellKnownSymbol(js::gc::Cell* thing) { return false; }
 bool ThingIsPermanentAtomOrWellKnownSymbol(JSString*);
 bool ThingIsPermanentAtomOrWellKnownSymbol(JSFlatString*);
 bool ThingIsPermanentAtomOrWellKnownSymbol(JSLinearString*);
 bool ThingIsPermanentAtomOrWellKnownSymbol(JSAtom*);
--- a/js/src/gc/Heap-inl.h
+++ b/js/src/gc/Heap-inl.h
@@ -14,25 +14,23 @@
 
 inline void
 js::gc::Arena::init(JS::Zone* zoneArg, AllocKind kind, const AutoLockGC& lock)
 {
     MOZ_ASSERT(firstFreeSpan.isEmpty());
     MOZ_ASSERT(!zone);
     MOZ_ASSERT(!allocated());
     MOZ_ASSERT(!hasDelayedMarking);
-    MOZ_ASSERT(!markOverflow);
     MOZ_ASSERT(!auxNextLink);
 
     MOZ_MAKE_MEM_UNDEFINED(this, ArenaSize);
 
     zone = zoneArg;
     allocKind = size_t(kind);
     hasDelayedMarking = 0;
-    markOverflow = 0;
     auxNextLink = 0;
     if (zone->isAtomsZone()) {
         zone->runtimeFromAnyThread()->gc.atomMarking.registerArena(this, lock);
     } else {
         bufferedCells() = &ArenaCellSet::Empty;
     }
 
     setAsFullyUnused();
--- a/js/src/gc/Heap.h
+++ b/js/src/gc/Heap.h
@@ -235,31 +235,23 @@ class Arena
      *
      * We use 8 bits for the alloc kind so the compiler can use byte-level
      * memory instructions to access it.
      */
     size_t allocKind : 8;
 
   public:
     /*
-     * When collecting we sometimes need to keep an auxillary list of arenas,
-     * for which we use the following fields. This happens for several reasons:
-     *
-     * When recursive marking uses too much stack, the marking is delayed and
-     * the corresponding arenas are put into a stack. To distinguish the bottom
-     * of the stack from the arenas not present in the stack we use the
-     * markOverflow flag to tag arenas on the stack.
-     *
-     * To minimize the size of the header fields we record the next linkage as
-     * address() >> ArenaShift and pack it with the allocKind and the flags.
+     * When recursive marking uses too much stack we delay marking of
+     * arenas and link them into a list for later processing. This
+     * uses the following fields.
      */
     size_t hasDelayedMarking : 1;
-    size_t markOverflow : 1;
-    size_t auxNextLink : JS_BITS_PER_WORD - 8 - 1 - 1;
-    static_assert(ArenaShift >= 8 + 1 + 1,
+    size_t auxNextLink : JS_BITS_PER_WORD - 8 - 1;
+    static_assert(ArenaShift >= 8 + 1,
                   "Arena::auxNextLink packing assumes that ArenaShift has "
                   "enough bits to cover allocKind and hasDelayedMarking.");
 
   private:
     union {
         /*
          * For arenas in zones other than the atoms zone, if non-null, points
          * to an ArenaCellSet that represents the set of cells in this arena
@@ -299,17 +291,16 @@ class Arena
 
     // Initialize an arena to its unallocated state. For arenas that were
     // previously allocated for some zone, use release() instead.
     void setAsNotAllocated() {
         firstFreeSpan.initAsEmpty();
         zone = nullptr;
         allocKind = size_t(AllocKind::LIMIT);
         hasDelayedMarking = 0;
-        markOverflow = 0;
         auxNextLink = 0;
         bufferedCells_ = nullptr;
     }
 
     // Return an allocated arena to its unallocated state.
     inline void release(const AutoLockGC& lock);
 
     uintptr_t address() const {
--- a/js/src/gc/Marking.cpp
+++ b/js/src/gc/Marking.cpp
@@ -303,66 +303,72 @@ namespace js {
 #define IMPL_CHECK_TRACED_THING(_, type, __) \
     template void CheckTracedThing<type>(JSTracer*, type*);
 JS_FOR_EACH_TRACEKIND(IMPL_CHECK_TRACED_THING);
 #undef IMPL_CHECK_TRACED_THING
 } // namespace js
 
 static bool UnmarkGrayGCThing(JSRuntime* rt, JS::GCCellPtr thing);
 
-static bool
-ShouldTraceCrossCompartment(JSTracer* trc, JSObject* src, Cell* cell)
+static inline bool
+ShouldMarkCrossCompartment(GCMarker* marker, JSObject* src, Cell* dstCell)
 {
-    if (!trc->isMarkingTracer()) {
-        return true;
-    }
-
-    MarkColor color = GCMarker::fromTracer(trc)->markColor();
-
-    if (!cell->isTenured()) {
+    MarkColor color = marker->markColor();
+
+    if (!dstCell->isTenured()) {
         MOZ_ASSERT(color == MarkColor::Black);
         return false;
     }
-    TenuredCell& tenured = cell->asTenured();
-
-    JS::Zone* zone = tenured.zone();
-    if (!src->zone()->isGCMarking() && !zone->isGCMarking()) {
+    TenuredCell& dst = dstCell->asTenured();
+
+    JS::Zone* dstZone = dst.zone();
+    if (!src->zone()->isGCMarking() && !dstZone->isGCMarking()) {
         return false;
     }
 
     if (color == MarkColor::Black) {
         /*
          * Having black->gray edges violates our promise to the cycle
          * collector. This can happen if we're collecting a compartment and it
          * has an edge to an uncollected compartment: it's possible that the
          * source and destination of the cross-compartment edge should be gray,
          * but the source was marked black by the write barrier.
          */
-        if (tenured.isMarkedGray()) {
-            MOZ_ASSERT(!zone->isCollecting());
-            UnmarkGrayGCThing(trc->runtime(), JS::GCCellPtr(cell, cell->getTraceKind()));
+        if (dst.isMarkedGray()) {
+            MOZ_ASSERT(!dstZone->isCollecting());
+            UnmarkGrayGCThing(marker->runtime(), JS::GCCellPtr(&dst, dst.getTraceKind()));
         }
-        return zone->isGCMarking();
+        return dstZone->isGCMarking();
     } else {
-        if (zone->isGCMarkingBlack()) {
+        if (dstZone->isGCMarkingBlack()) {
             /*
              * The destination compartment is being not being marked gray now,
              * but it will be later, so record the cell so it can be marked gray
              * at the appropriate time.
              */
-            if (!tenured.isMarkedAny()) {
+            if (!dst.isMarkedAny()) {
                 DelayCrossCompartmentGrayMarking(src);
             }
             return false;
         }
-        return zone->isGCMarkingGray();
+        return dstZone->isGCMarkingGray();
     }
 }
 
 static bool
+ShouldTraceCrossCompartment(JSTracer* trc, JSObject* src, Cell* dstCell)
+{
+    if (!trc->isMarkingTracer()) {
+        return true;
+    }
+
+    return ShouldMarkCrossCompartment(GCMarker::fromTracer(trc), src, dstCell);
+}
+
+static bool
 ShouldTraceCrossCompartment(JSTracer* trc, JSObject* src, const Value& val)
 {
     return val.isGCThing() && ShouldTraceCrossCompartment(trc, src, val.toGCThing());
 }
 
 static void
 AssertShouldMarkInZone(Cell* thing)
 {
@@ -2539,26 +2545,57 @@ GCMarker::reset()
     MOZ_ASSERT(isMarkStackEmpty());
 
     while (unmarkedArenaStackTop) {
         Arena* arena = unmarkedArenaStackTop;
         MOZ_ASSERT(arena->hasDelayedMarking);
         MOZ_ASSERT(markLaterArenas);
         unmarkedArenaStackTop = arena->getNextDelayedMarking();
         arena->unsetDelayedMarking();
-        arena->markOverflow = 0;
 
 #ifdef DEBUG
         markLaterArenas--;
 #endif
     }
     MOZ_ASSERT(isDrained());
     MOZ_ASSERT(!markLaterArenas);
 }
 
+void
+GCMarker::setMarkColor(gc::MarkColor newColor)
+{
+    if (color == newColor) {
+        return;
+    }
+    if (newColor == gc::MarkColor::Black) {
+        setMarkColorBlack();
+    } else {
+        setMarkColorGray();
+    }
+}
+
+void
+GCMarker::setMarkColorGray()
+{
+    MOZ_ASSERT(isDrained());
+    MOZ_ASSERT(color == gc::MarkColor::Black);
+    MOZ_ASSERT(runtime()->gc.state() == State::Sweep);
+
+    color = gc::MarkColor::Gray;
+}
+
+void
+GCMarker::setMarkColorBlack()
+{
+    MOZ_ASSERT(isDrained());
+    MOZ_ASSERT(color == gc::MarkColor::Gray);
+    MOZ_ASSERT(runtime()->gc.state() == State::Sweep);
+
+    color = gc::MarkColor::Black;
+}
 
 template <typename T>
 void
 GCMarker::pushTaggedPtr(T* ptr)
 {
     checkZone(ptr);
     if (!stack.push(ptr)) {
         delayMarkingChildren(ptr);
@@ -2629,19 +2666,16 @@ GCMarker::leaveWeakMarkingMode()
             oomUnsafe.crash("clearing weak keys in GCMarker::leaveWeakMarkingMode()");
         }
     }
 }
 
 void
 GCMarker::markDelayedChildren(Arena* arena)
 {
-    MOZ_ASSERT(arena->markOverflow);
-    arena->markOverflow = 0;
-
     JS::TraceKind kind = MapAllocToTraceKind(arena->getAllocKind());
 
     // Whether we need to mark children of gray or black cells in the arena
     // depends on which kind of marking we were doing when the arena as pushed
     // onto the list.  We never change mark color without draining the mark
     // stack though so this is the same as the current color.
     bool markGrayCells = markColor() == MarkColor::Gray && TraceKindParticipatesInCC(kind);
 
--- a/js/src/jit-test/tests/wasm/gc/TypedObject.js
+++ b/js/src/jit-test/tests/wasm/gc/TypedObject.js
@@ -1,15 +1,15 @@
 // |jit-test| skip-if: !wasmGcEnabled()
 
 // We can read the object fields from JS, and write them if they are mutable.
 
 {
     let ins = wasmEvalText(`(module
-                             (gc_feature_opt_in 1)
+                             (gc_feature_opt_in 2)
 
                              (type $p (struct (field f64) (field (mut i32))))
 
                              (func (export "mkp") (result anyref)
                               (struct.new $p (f64.const 1.5) (i32.const 33))))`).exports;
 
     let p = ins.mkp();
     assertEq(p._0, 1.5);
@@ -19,17 +19,17 @@
     p._1 = 44;
     assertEq(p._1, 44);
 }
 
 // Writing an immutable field from JS throws.
 
 {
     let ins = wasmEvalText(`(module
-                             (gc_feature_opt_in 1)
+                             (gc_feature_opt_in 2)
 
                              (type $p (struct (field f64)))
 
                              (func (export "mkp") (result anyref)
                               (struct.new $p (f64.const 1.5))))`).exports;
 
     let p = ins.mkp();
     assertErrorMessage(() => p._0 = 5.7,
@@ -39,28 +39,28 @@
 
 // MVA v1 restriction: structs that expose ref-typed fields should not be
 // constructible from JS.
 //
 // However, if the fields are anyref the structs can be constructed from JS.
 
 {
     let ins = wasmEvalText(`(module
-                             (gc_feature_opt_in 1)
+                             (gc_feature_opt_in 2)
 
                              (type $q (struct (field (mut f64))))
                              (type $p (struct (field (mut (ref $q)))))
 
                              (type $r (struct (field (mut anyref))))
 
                              (func (export "mkp") (result anyref)
-                              (struct.new $p (ref.null (ref $q))))
+                              (struct.new $p (ref.null)))
 
                              (func (export "mkr") (result anyref)
-                              (struct.new $r (ref.null anyref))))`).exports;
+                              (struct.new $r (ref.null))))`).exports;
 
     assertEq(typeof ins.mkp().constructor, "function");
     assertErrorMessage(() => new (ins.mkp().constructor)({_0:null}),
                        TypeError,
                        /not constructible/);
 
     assertEq(typeof ins.mkr().constructor, "function");
     let r = new (ins.mkr().constructor)({_0:null});
@@ -69,26 +69,26 @@
 
 // MVA v1 restriction: structs that expose ref-typed fields make those fields
 // immutable from JS even if we're trying to store the correct type.
 //
 // However, anyref fields are mutable from JS.
 
 {
     let ins = wasmEvalText(`(module
-                             (gc_feature_opt_in 1)
+                             (gc_feature_opt_in 2)
 
                              (type $q (struct (field (mut f64))))
                              (type $p (struct (field (mut (ref $q))) (field (mut anyref))))
 
                              (func (export "mkq") (result anyref)
                               (struct.new $q (f64.const 1.5)))
 
                              (func (export "mkp") (result anyref)
-                              (struct.new $p (ref.null (ref $q)) (ref.null anyref))))`).exports;
+                              (struct.new $p (ref.null) (ref.null))))`).exports;
     let q = ins.mkq();
     assertEq(typeof q, "object");
     assertEq(q._0, 1.5);
     let p = ins.mkp();
     assertEq(typeof p, "object");
     assertEq(p._0, null);
 
     assertErrorMessage(() => { p._0 = q },
@@ -99,17 +99,17 @@
     assertEq(p._1, q);
 }
 
 // MVA v1 restriction: structs that expose i64 fields make those fields
 // immutable from JS, and the structs are not constructible from JS.
 
 {
     let ins = wasmEvalText(`(module
-                             (gc_feature_opt_in 1)
+                             (gc_feature_opt_in 2)
                              (type $p (struct (field (mut i64))))
                              (func (export "mkp") (result anyref)
                               (struct.new $p (i64.const 0x1234567887654321))))`).exports;
 
     let p = ins.mkp();
     assertEq(typeof p, "object");
     assertEq(p._0_high, 0x12345678)
     assertEq(p._0_low, 0x87654321|0);
@@ -128,17 +128,17 @@
 }
 
 // A consequence of the current mapping of i64 as two i32 fields is that we run
 // a risk of struct.narrow not recognizing the difference.  So check this.
 
 {
     let ins = wasmEvalText(
         `(module
-          (gc_feature_opt_in 1)
+          (gc_feature_opt_in 2)
           (type $p (struct (field i64)))
           (type $q (struct (field i32) (field i32)))
           (func $f (param anyref) (result i32)
            (ref.is_null (struct.narrow anyref (ref $q) (get_local 0))))
           (func $g (param anyref) (result i32)
            (ref.is_null (struct.narrow anyref (ref $p) (get_local 0))))
           (func (export "t1") (result i32)
            (call $f (struct.new $p (i64.const 0))))
--- a/js/src/jit-test/tests/wasm/gc/anyref-global-postbarrier.js
+++ b/js/src/jit-test/tests/wasm/gc/anyref-global-postbarrier.js
@@ -5,38 +5,38 @@ const { startProfiling, endProfiling, as
 // Dummy constructor.
 function Baguette(calories) {
     this.calories = calories;
 }
 
 // Ensure the baseline compiler sync's before the postbarrier.
 (function() {
     wasmEvalText(`(module
-        (gc_feature_opt_in 1)
-        (global (mut anyref) (ref.null anyref))
+        (gc_feature_opt_in 2)
+        (global (mut anyref) (ref.null))
         (func (export "f")
             get_global 0
-            ref.null anyref
+            ref.null
             set_global 0
             set_global 0
         )
     )`).exports.f();
 })();
 
 let exportsPlain = wasmEvalText(`(module
-    (gc_feature_opt_in 1)
+    (gc_feature_opt_in 2)
     (global i32 (i32.const 42))
-    (global $g (mut anyref) (ref.null anyref))
+    (global $g (mut anyref) (ref.null))
     (func (export "set") (param anyref) get_local 0 set_global $g)
     (func (export "get") (result anyref) get_global $g)
 )`).exports;
 
 let exportsObj = wasmEvalText(`(module
-    (gc_feature_opt_in 1)
-    (global $g (export "g") (mut anyref) (ref.null anyref))
+    (gc_feature_opt_in 2)
+    (global $g (export "g") (mut anyref) (ref.null))
     (func (export "set") (param anyref) get_local 0 set_global $g)
     (func (export "get") (result anyref) get_global $g)
 )`).exports;
 
 // 7 => Generational GC zeal.
 gczeal(7, 1);
 
 for (var i = 0; i < 100; i++) {
--- a/js/src/jit-test/tests/wasm/gc/anyref-global-prebarrier.js
+++ b/js/src/jit-test/tests/wasm/gc/anyref-global-prebarrier.js
@@ -1,15 +1,15 @@
 // |jit-test| skip-if: !wasmGcEnabled()
 
 const { startProfiling, endProfiling, assertEqPreciseStacks, isSingleStepProfilingEnabled } = WasmHelpers;
 
 let e = wasmEvalText(`(module
-    (gc_feature_opt_in 1)
-    (global $g (mut anyref) (ref.null anyref))
+    (gc_feature_opt_in 2)
+    (global $g (mut anyref) (ref.null))
     (func (export "set") (param anyref) get_local 0 set_global $g)
 )`).exports;
 
 let obj = { field: null };
 
 // GCZeal mode 4 implies that prebarriers are being verified at many
 // locations in the interpreter, during interrupt checks, etc. It can be ultra
 // slow, so disable it with gczeal(0) when it's not strictly needed.
--- a/js/src/jit-test/tests/wasm/gc/anyref-val-tracing.js
+++ b/js/src/jit-test/tests/wasm/gc/anyref-val-tracing.js
@@ -1,13 +1,13 @@
 // |jit-test| skip-if: !wasmGcEnabled()
 
 gczeal(14, 1);
 let { exports } = wasmEvalText(`(module
-    (gc_feature_opt_in 1)
+    (gc_feature_opt_in 2)
     (global $anyref (import "glob" "anyref") anyref)
     (func (export "get") (result anyref) get_global $anyref)
 )`, {
     glob: {
         anyref: { sentinel: "lol" },
     }
 });
 assertEq(exports.get().sentinel, "lol");
--- a/js/src/jit-test/tests/wasm/gc/anyref.js
+++ b/js/src/jit-test/tests/wasm/gc/anyref.js
@@ -6,88 +6,88 @@ function Baguette(calories) {
     this.calories = calories;
 }
 
 // Type checking.
 
 const { validate, CompileError } = WebAssembly;
 
 assertErrorMessage(() => wasmEvalText(`(module
-    (gc_feature_opt_in 1)
+    (gc_feature_opt_in 2)
     (func (result anyref)
         i32.const 42
     )
 )`), CompileError, mismatchError('i32', 'anyref'));
 
 assertErrorMessage(() => wasmEvalText(`(module
-    (gc_feature_opt_in 1)
+    (gc_feature_opt_in 2)
     (func (result anyref)
         i32.const 0
-        ref.null anyref
+        ref.null
         i32.const 42
         select
     )
 )`), CompileError, /select operand types/);
 
 assertErrorMessage(() => wasmEvalText(`(module
-    (gc_feature_opt_in 1)
+    (gc_feature_opt_in 2)
     (func (result i32)
-        ref.null anyref
+        ref.null
         if
             i32.const 42
         end
     )
-)`), CompileError, mismatchError('anyref', 'i32'));
+)`), CompileError, mismatchError('nullref', 'i32'));
 
 
 // Basic compilation tests.
 
 let simpleTests = [
-    "(module (gc_feature_opt_in 1) (func (drop (ref.null anyref))))",
-    "(module (gc_feature_opt_in 1) (func $test (local anyref)))",
-    "(module (gc_feature_opt_in 1) (func $test (param anyref)))",
-    "(module (gc_feature_opt_in 1) (func $test (result anyref) (ref.null anyref)))",
-    "(module (gc_feature_opt_in 1) (func $test (block anyref (unreachable)) unreachable))",
-    "(module (gc_feature_opt_in 1) (func $test (local anyref) (result i32) (ref.is_null (get_local 0))))",
-    `(module (gc_feature_opt_in 1) (import "a" "b" (param anyref)))`,
-    `(module (gc_feature_opt_in 1) (import "a" "b" (result anyref)))`,
-    `(module (gc_feature_opt_in 1) (global anyref (ref.null anyref)))`,
-    `(module (gc_feature_opt_in 1) (global (mut anyref) (ref.null anyref)))`,
+    "(module (gc_feature_opt_in 2) (func (drop (ref.null))))",
+    "(module (gc_feature_opt_in 2) (func $test (local anyref)))",
+    "(module (gc_feature_opt_in 2) (func $test (param anyref)))",
+    "(module (gc_feature_opt_in 2) (func $test (result anyref) (ref.null)))",
+    "(module (gc_feature_opt_in 2) (func $test (block anyref (unreachable)) unreachable))",
+    "(module (gc_feature_opt_in 2) (func $test (local anyref) (result i32) (ref.is_null (get_local 0))))",
+    `(module (gc_feature_opt_in 2) (import "a" "b" (param anyref)))`,
+    `(module (gc_feature_opt_in 2) (import "a" "b" (result anyref)))`,
+    `(module (gc_feature_opt_in 2) (global anyref (ref.null)))`,
+    `(module (gc_feature_opt_in 2) (global (mut anyref) (ref.null)))`,
 ];
 
 for (let src of simpleTests) {
     wasmEvalText(src, {a:{b(){}}});
     assertEq(validate(wasmTextToBinary(src)), true);
 }
 
 // Basic behavioral tests.
 
 let { exports } = wasmEvalText(`(module
-    (gc_feature_opt_in 1)
+    (gc_feature_opt_in 2)
     (func (export "is_null") (result i32)
-        ref.null anyref
+        ref.null
         ref.is_null
     )
 
     (func $sum (result i32) (param i32)
         get_local 0
         i32.const 42
         i32.add
     )
 
     (func (export "is_null_spill") (result i32)
-        ref.null anyref
+        ref.null
         i32.const 58
         call $sum
         drop
         ref.is_null
     )
 
     (func (export "is_null_local") (result i32) (local anyref)
-        ref.null anyref
+        ref.null
         set_local 0
         i32.const 58
         call $sum
         drop
         get_local 0
         ref.is_null
     )
 
@@ -108,25 +108,25 @@ assertEq(exports.ref_eq(null, {}), 0);
 assertEq(exports.ref_eq(this, this), 1);
 assertEq(exports.ref_eq_for_control(null, null), 5);
 assertEq(exports.ref_eq_for_control(null, {}), 3);
 assertEq(exports.ref_eq_for_control(this, this), 5);
 
 // Anyref param and result in wasm functions.
 
 exports = wasmEvalText(`(module
-    (gc_feature_opt_in 1)
+    (gc_feature_opt_in 2)
     (func (export "is_null") (result i32) (param $ref anyref)
         get_local $ref
         ref.is_null
     )
 
     (func (export "ref_or_null") (result anyref) (param $ref anyref) (param $selector i32)
         get_local $ref
-        ref.null anyref
+        ref.null
         get_local $selector
         select
     )
 
     (func $recursive (export "nested") (result anyref) (param $ref anyref) (param $i i32)
         ;; i == 10 => ret $ref
         get_local $i
         i32.const 10
@@ -166,33 +166,33 @@ assertEq(ref.calories, baguette.calories
 
 ref = exports.nested(baguette, 0);
 assertEq(ref, baguette);
 assertEq(ref.calories, baguette.calories);
 
 // Make sure grow-memory isn't blocked by the lack of gc.
 (function() {
     assertEq(wasmEvalText(`(module
-    (gc_feature_opt_in 1)
+    (gc_feature_opt_in 2)
     (memory 0 64)
     (func (export "f") (param anyref) (result i32)
         i32.const 10
         grow_memory
         drop
         current_memory
     )
 )`).exports.f({}), 10);
 })();
 
 // More interesting use cases about control flow joins.
 
 function assertJoin(body) {
     let val = { i: -1 };
     assertEq(wasmEvalText(`(module
-        (gc_feature_opt_in 1)
+        (gc_feature_opt_in 2)
         (func (export "test") (param $ref anyref) (param $i i32) (result anyref)
             ${body}
         )
     )`).exports.test(val), val);
     assertEq(val.i, -1);
 }
 
 assertJoin("(block anyref get_local $ref)");
@@ -249,17 +249,17 @@ assertJoin(`(block $out anyref (block $u
     i32.add
     tee_local $i
     br_table $unreachable $out
     ) unreachable))
 `);
 
 let x = { i: 42 }, y = { f: 53 };
 exports = wasmEvalText(`(module
-    (gc_feature_opt_in 1)
+    (gc_feature_opt_in 2)
     (func (export "test") (param $lhs anyref) (param $rhs anyref) (param $i i32) (result anyref)
         get_local $lhs
         get_local $rhs
         get_local $i
         select
     )
 )`).exports;
 
@@ -304,17 +304,17 @@ let imports = {
         },
         ret() {
             return imports.myBaguette;
         }
     }
 };
 
 exports = wasmEvalText(`(module
-    (gc_feature_opt_in 1)
+    (gc_feature_opt_in 2)
     (import $ret "funcs" "ret" (result anyref))
     (import $param "funcs" "param" (param anyref))
 
     (func (export "param") (param $x anyref) (param $y anyref)
         get_local $y
         get_local $x
         call $param
         call $param
@@ -333,17 +333,17 @@ imports.myBaguette = null;
 assertEq(exports.ret(), null);
 
 imports.myBaguette = new Baguette(1337);
 assertEq(exports.ret(), imports.myBaguette);
 
 // Check lazy stubs generation.
 
 exports = wasmEvalText(`(module
-    (gc_feature_opt_in 1)
+    (gc_feature_opt_in 2)
     (import $mirror "funcs" "mirror" (param anyref) (result anyref))
     (import $augment "funcs" "augment" (param anyref) (result anyref))
 
     (global $count_f (mut i32) (i32.const 0))
     (global $count_g (mut i32) (i32.const 0))
 
     (func $f (param $param anyref) (result anyref)
         i32.const 1
@@ -417,48 +417,48 @@ assertEq(x.i, 24);
 assertEq(x.newProp, "hello");
 assertEq(exports.count_f(), 1);
 assertEq(exports.count_g(), 1);
 
 // Globals.
 
 // Anyref globals in wasm modules.
 
-assertErrorMessage(() => wasmEvalText(`(module (gc_feature_opt_in 1) (global (import "glob" "anyref") anyref))`, { glob: { anyref: 42 } }),
+assertErrorMessage(() => wasmEvalText(`(module (gc_feature_opt_in 2) (global (import "glob" "anyref") anyref))`, { glob: { anyref: 42 } }),
     WebAssembly.LinkError,
     /import object field 'anyref' is not a Object-or-null/);
 
-assertErrorMessage(() => wasmEvalText(`(module (gc_feature_opt_in 1) (global (import "glob" "anyref") anyref))`, { glob: { anyref: new WebAssembly.Global({ value: 'i32' }, 42) } }),
+assertErrorMessage(() => wasmEvalText(`(module (gc_feature_opt_in 2) (global (import "glob" "anyref") anyref))`, { glob: { anyref: new WebAssembly.Global({ value: 'i32' }, 42) } }),
     WebAssembly.LinkError,
     /imported global type mismatch/);
 
-assertErrorMessage(() => wasmEvalText(`(module (gc_feature_opt_in 1) (global (import "glob" "i32") i32))`, { glob: { i32: {} } }),
+assertErrorMessage(() => wasmEvalText(`(module (gc_feature_opt_in 2) (global (import "glob" "i32") i32))`, { glob: { i32: {} } }),
     WebAssembly.LinkError,
     /import object field 'i32' is not a Number/);
 
 imports = {
     constants: {
         imm_null: null,
         imm_bread: new Baguette(321),
         mut_null: new WebAssembly.Global({ value: "anyref", mutable: true }, null),
         mut_bread: new WebAssembly.Global({ value: "anyref", mutable: true }, new Baguette(123))
     }
 };
 
 exports = wasmEvalText(`(module
-    (gc_feature_opt_in 1)
+    (gc_feature_opt_in 2)
     (global $g_imp_imm_null  (import "constants" "imm_null") anyref)
     (global $g_imp_imm_bread (import "constants" "imm_bread") anyref)
 
     (global $g_imp_mut_null   (import "constants" "mut_null") (mut anyref))
     (global $g_imp_mut_bread  (import "constants" "mut_bread") (mut anyref))
 
-    (global $g_imm_null     anyref (ref.null anyref))
+    (global $g_imm_null     anyref (ref.null))
     (global $g_imm_getglob  anyref (get_global $g_imp_imm_bread))
-    (global $g_mut         (mut anyref) (ref.null anyref))
+    (global $g_mut         (mut anyref) (ref.null))
 
     (func (export "imm_null")      (result anyref) get_global $g_imm_null)
     (func (export "imm_getglob")   (result anyref) get_global $g_imm_getglob)
 
     (func (export "imp_imm_null")  (result anyref) get_global $g_imp_imm_null)
     (func (export "imp_imm_bread") (result anyref) get_global $g_imp_imm_bread)
     (func (export "imp_mut_null")  (result anyref) get_global $g_imp_mut_null)
     (func (export "imp_mut_bread") (result anyref) get_global $g_imp_mut_bread)
--- a/js/src/jit-test/tests/wasm/gc/binary.js
+++ b/js/src/jit-test/tests/wasm/gc/binary.js
@@ -2,39 +2,21 @@
 
 load(libdir + "wasm-binary.js");
 
 const v2vSig = {args:[], ret:VoidCode};
 const v2vSigSection = sigSection([v2vSig]);
 
 function checkInvalid(body, errorMessage) {
     assertErrorMessage(() => new WebAssembly.Module(
-        moduleWithSections([gcFeatureOptInSection(1), v2vSigSection, declSection([0]), bodySection([body])])),
+        moduleWithSections([gcFeatureOptInSection(2), v2vSigSection, declSection([0]), bodySection([body])])),
                        WebAssembly.CompileError,
                        errorMessage);
 }
 
-const invalidRefNullBody = funcBody({locals:[], body:[
-    RefNull,
-    RefCode,
-    0x42,
-
-    RefNull,
-    RefCode,
-    0x10,
-
-    // Condition code;
-    I32ConstCode,
-    0x10,
-
-    SelectCode,
-    DropCode
-]});
-checkInvalid(invalidRefNullBody, /invalid reference type for ref.null/);
-
 const invalidRefBlockType = funcBody({locals:[], body:[
     BlockCode,
     RefCode,
     0x42,
     EndCode,
 ]});
 checkInvalid(invalidRefBlockType, /invalid inline block type/);
 
--- a/js/src/jit-test/tests/wasm/gc/debugger.js
+++ b/js/src/jit-test/tests/wasm/gc/debugger.js
@@ -1,23 +1,23 @@
 // |jit-test| skip-if: !wasmGcEnabled() || !wasmDebuggingIsSupported()
 
 (function() {
     let g = newGlobal();
     let dbg = new Debugger(g);
-    g.eval(`o = new WebAssembly.Instance(new WebAssembly.Module(wasmTextToBinary('(module (gc_feature_opt_in 1) (func (result anyref) (param anyref) get_local 0) (export "" 0))')));`);
+    g.eval(`o = new WebAssembly.Instance(new WebAssembly.Module(wasmTextToBinary('(module (gc_feature_opt_in 2) (func (result anyref) (param anyref) get_local 0) (export "" 0))')));`);
 })();
 
 (function() {
     var g = newGlobal();
     g.parent = this;
 
     let src = `
       (module
-        (gc_feature_opt_in 1)
+        (gc_feature_opt_in 2)
         (func (export "func") (result anyref) (param $ref anyref)
             get_local $ref
         )
       )
     `;
 
     g.eval(`
         var obj = { somekey: 'somevalue' };
--- a/js/src/jit-test/tests/wasm/gc/disabled.js
+++ b/js/src/jit-test/tests/wasm/gc/disabled.js
@@ -4,25 +4,25 @@ const { CompileError, validate } = WebAs
 
 const UNRECOGNIZED_OPCODE_OR_BAD_TYPE = /unrecognized opcode|(Structure|reference) types not enabled|invalid inline block type/;
 
 function assertValidateError(text) {
     assertEq(validate(wasmTextToBinary(text)), false);
 }
 
 let simpleTests = [
-    "(module (gc_feature_opt_in 1) (func (drop (ref.null anyref))))",
-    "(module (gc_feature_opt_in 1) (func $test (local anyref)))",
-    "(module (gc_feature_opt_in 1) (func $test (param anyref)))",
-    "(module (gc_feature_opt_in 1) (func $test (result anyref) (ref.null anyref)))",
-    "(module (gc_feature_opt_in 1) (func $test (block anyref (unreachable)) unreachable))",
-    "(module (gc_feature_opt_in 1) (func $test (local anyref) (result i32) (ref.is_null (get_local 0))))",
-    `(module (gc_feature_opt_in 1) (import "a" "b" (param anyref)))`,
-    `(module (gc_feature_opt_in 1) (import "a" "b" (result anyref)))`,
-    `(module (gc_feature_opt_in 1) (type $s (struct)))`,
+    "(module (gc_feature_opt_in 2) (func (drop (ref.null))))",
+    "(module (gc_feature_opt_in 2) (func $test (local anyref)))",
+    "(module (gc_feature_opt_in 2) (func $test (param anyref)))",
+    "(module (gc_feature_opt_in 2) (func $test (result anyref) (ref.null)))",
+    "(module (gc_feature_opt_in 2) (func $test (block anyref (unreachable)) unreachable))",
+    "(module (gc_feature_opt_in 2) (func $test (local anyref) (result i32) (ref.is_null (get_local 0))))",
+    `(module (gc_feature_opt_in 2) (import "a" "b" (param anyref)))`,
+    `(module (gc_feature_opt_in 2) (import "a" "b" (result anyref)))`,
+    `(module (gc_feature_opt_in 2) (type $s (struct)))`,
 ];
 
 // Two distinct failure modes:
 //
 // - if we have no compiled-in support for wasm-gc we'll get a syntax error when
 //   parsing the test programs that use ref types and structures.
 //
 // - if we have compiled-in support for wasm-gc, but wasm-gc is not currently
--- a/js/src/jit-test/tests/wasm/gc/gc-feature-opt-in.js
+++ b/js/src/jit-test/tests/wasm/gc/gc-feature-opt-in.js
@@ -1,122 +1,132 @@
 // |jit-test| skip-if: !wasmGcEnabled()
 
+// Version numbers
+
+let CURRENT_VERSION = 2;
+let OLDER_INCOMPATIBLE_VERSION = 1; // v1 incompatible with v2
+let FUTURE_VERSION = 3;
+
 // Encoding.  If the section is present it must be first.
 
 var bad_order =
     new Uint8Array([0x00, 0x61, 0x73, 0x6d,
                     0x01, 0x00, 0x00, 0x00,
 
                     0x01,                   // Type section
                     0x01,                   // Section size
                     0x00,                   // Zero types
 
                     0x2a,                   // GcFeatureOptIn section
                     0x01,                   // Section size
-                    0x01]);                 // Version
+                    CURRENT_VERSION]);      // Version
 
 assertErrorMessage(() => new WebAssembly.Module(bad_order),
                    WebAssembly.CompileError,
                    /expected custom section/);
 
-// Version numbers.  Version 1 and 2 are good, version 3 is bad.
-
 new WebAssembly.Module(wasmTextToBinary(
     `(module
-      (gc_feature_opt_in 1))`));
+      (gc_feature_opt_in ${CURRENT_VERSION}))`));
 
 new WebAssembly.Module(wasmTextToBinary(
     `(module
-      (gc_feature_opt_in 1))`));
+      (gc_feature_opt_in ${CURRENT_VERSION}))`));
 
 assertErrorMessage(() => new WebAssembly.Module(wasmTextToBinary(
     `(module
-      (gc_feature_opt_in 3))`)),
+      (gc_feature_opt_in ${OLDER_INCOMPATIBLE_VERSION}))`)),
                    WebAssembly.CompileError,
-                   /unsupported version of the gc feature/);
+                   /GC feature version \d+ is no longer supported by this engine/);
+
+assertErrorMessage(() => new WebAssembly.Module(wasmTextToBinary(
+    `(module
+      (gc_feature_opt_in ${FUTURE_VERSION}))`)),
+                   WebAssembly.CompileError,
+                   /GC feature version is unknown/);
 
 // Struct types are only available if we opt in.
 
 new WebAssembly.Module(wasmTextToBinary(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in ${CURRENT_VERSION})
       (type (struct (field i32))))`));
 
 assertErrorMessage(() => new WebAssembly.Module(wasmTextToBinary(
     `(module
       (type (struct (field i32))))`)),
                    WebAssembly.CompileError,
                    /Structure types not enabled/);
 
 // Parameters of ref type are only available if we opt in.
 
 new WebAssembly.Module(wasmTextToBinary(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in ${CURRENT_VERSION})
       (type (func (param anyref))))`));
 
 assertErrorMessage(() => new WebAssembly.Module(wasmTextToBinary(
     `(module
       (type (func (param anyref))))`)),
                    WebAssembly.CompileError,
                    /reference types not enabled/);
 
 // Ditto returns
 
 new WebAssembly.Module(wasmTextToBinary(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in ${CURRENT_VERSION})
       (type (func (result anyref))))`));
 
 assertErrorMessage(() => new WebAssembly.Module(wasmTextToBinary(
     `(module
       (type (func (result anyref))))`)),
                    WebAssembly.CompileError,
                    /reference types not enabled/);
 
 // Ditto locals
 
 new WebAssembly.Module(wasmTextToBinary(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in ${CURRENT_VERSION})
       (func (result i32)
        (local anyref)
        (i32.const 0)))`));
 
 assertErrorMessage(() => new WebAssembly.Module(wasmTextToBinary(
     `(module
       (func (result i32)
        (local anyref)
        (i32.const 0)))`)),
                    WebAssembly.CompileError,
                    /reference types not enabled/);
 
 // Ditto globals
 
 new WebAssembly.Module(wasmTextToBinary(
     `(module
-      (gc_feature_opt_in 1)
-      (global (mut anyref) (ref.null anyref)))`));
+      (gc_feature_opt_in ${CURRENT_VERSION})
+      (global (mut anyref) (ref.null)))`));
 
 assertErrorMessage(() => new WebAssembly.Module(wasmTextToBinary(
     `(module
-      (global (mut anyref) (ref.null anyref)))`)),
+      (global (mut anyref) (ref.null)))`)),
                    WebAssembly.CompileError,
                    /reference types not enabled/);
 
 // Ref instructions are only available if we opt in.
 //
 // When testing these we need to avoid struct types or parameters, locals,
 // returns, or globals of ref type, or guards on those will preempt the guards
 // on the instructions.
 
 assertErrorMessage(() => new WebAssembly.Module(wasmTextToBinary(
     `(module
-      (func (ref.null anyref)))`)),
+      (func ref.null))`)),
                    WebAssembly.CompileError,
                    /unrecognized opcode/);
 
 assertErrorMessage(() => new WebAssembly.Module(wasmTextToBinary(
     `(module
       (func ref.is_null))`)),
                    WebAssembly.CompileError,
                    /unrecognized opcode/);
--- a/js/src/jit-test/tests/wasm/gc/ion-and-baseline.js
+++ b/js/src/jit-test/tests/wasm/gc/ion-and-baseline.js
@@ -15,35 +15,35 @@
 // Ion can't talk about references yet *but* we can call indirect from Ion to a
 // baseline module that has exported a function that accepts or returns anyref,
 // without the caller knowing this or having to declare it.  All such calls
 // should fail in an orderly manner with a type mismatch, at the point of the
 // call.
 
 var refmod = new WebAssembly.Module(wasmTextToBinary(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in 2)
 
       (import $tbl "" "tbl" (table 4 anyfunc))
       (import $print "" "print" (func (param i32)))
 
       (type $htype (func (param anyref)))
       (type $itype (func (result anyref)))
 
       (elem (i32.const 0) $f $g)
 
       (func $f (param anyref)
        (call $print (i32.const 1)))
 
       (func $g (result anyref)
        (call $print (i32.const 2))
-       (ref.null anyref))
+       (ref.null))
 
       (func (export "test_h")
-       (call_indirect $htype (ref.null anyref) (i32.const 2)))
+       (call_indirect $htype (ref.null) (i32.const 2)))
 
       (func (export "test_i")
        (drop (call_indirect $itype (i32.const 3))))
 
      )`));
 
 var nonrefmod = new WebAssembly.Module(wasmTextToBinary(
     `(module
--- a/js/src/jit-test/tests/wasm/gc/ref-global.js
+++ b/js/src/jit-test/tests/wasm/gc/ref-global.js
@@ -1,68 +1,68 @@
 // |jit-test| skip-if: !wasmGcEnabled()
 
 // Basic private-to-module functionality.  At the moment all we have is null
 // pointers, not very exciting.
 
 {
     let bin = wasmTextToBinary(
         `(module
-          (gc_feature_opt_in 1)
+          (gc_feature_opt_in 2)
 
           (type $point (struct
                         (field $x f64)
                         (field $y f64)))
 
-          (global $g1 (mut (ref $point)) (ref.null (ref $point)))
-          (global $g2 (mut (ref $point)) (ref.null (ref $point)))
-          (global $g3 (ref $point) (ref.null (ref $point)))
+          (global $g1 (mut (ref $point)) (ref.null))
+          (global $g2 (mut (ref $point)) (ref.null))
+          (global $g3 (ref $point) (ref.null))
 
           ;; Restriction: cannot expose Refs outside the module, not even
           ;; as a return value.  See ref-restrict.js.
 
           (func (export "get") (result anyref)
            (get_global $g1))
 
           (func (export "copy")
            (set_global $g2 (get_global $g1)))
 
           (func (export "clear")
            (set_global $g1 (get_global $g3))
-           (set_global $g2 (ref.null (ref $point)))))`);
+           (set_global $g2 (ref.null))))`);
 
     let mod = new WebAssembly.Module(bin);
     let ins = new WebAssembly.Instance(mod).exports;
 
     assertEq(ins.get(), null);
     ins.copy();                 // Should not crash
     ins.clear();                // Should not crash
 }
 
 // Global with struct type
 
 {
     let bin = wasmTextToBinary(
         `(module
-          (gc_feature_opt_in 1)
+          (gc_feature_opt_in 2)
 
           (type $point (struct
                         (field $x f64)
                         (field $y f64)))
 
-          (global $glob (mut (ref $point)) (ref.null (ref $point)))
+          (global $glob (mut (ref $point)) (ref.null))
 
           (func (export "init")
            (set_global $glob (struct.new $point (f64.const 0.5) (f64.const 2.75))))
 
           (func (export "change")
            (set_global $glob (struct.new $point (f64.const 3.5) (f64.const 37.25))))
 
           (func (export "clear")
-           (set_global $glob (ref.null (ref $point))))
+           (set_global $glob (ref.null)))
 
           (func (export "x") (result f64)
            (struct.get $point 0 (get_global $glob)))
 
           (func (export "y") (result f64)
            (struct.get $point 1 (get_global $glob))))`);
 
     let mod = new WebAssembly.Module(bin);
@@ -82,17 +82,17 @@
     assertErrorMessage(() => ins.x(), WebAssembly.RuntimeError, /dereferencing null pointer/);
 }
 
 // Global value of type anyref for initializer from a WebAssembly.Global,
 // just check that it works.
 {
     let bin = wasmTextToBinary(
         `(module
-          (gc_feature_opt_in 1)
+          (gc_feature_opt_in 2)
           (import $g "" "g" (global anyref))
           (global $glob anyref (get_global $g))
           (func (export "get") (result anyref)
            (get_global $glob)))`);
 
     let mod = new WebAssembly.Module(bin);
     let obj = {zappa:37};
     let g = new WebAssembly.Global({value: "anyref"}, obj);
@@ -100,30 +100,30 @@
     assertEq(ins.get(), obj);
 }
 
 // We can't import a global of a reference type because we don't have a good
 // notion of structural type compatibility yet.
 {
     let bin = wasmTextToBinary(
         `(module
-          (gc_feature_opt_in 1)
+          (gc_feature_opt_in 2)
           (type $box (struct (field $val i32)))
           (import "m" "g" (global (mut (ref $box)))))`);
 
     assertErrorMessage(() => new WebAssembly.Module(bin), WebAssembly.CompileError,
                        /cannot expose reference type/);
 }
 
 // We can't export a global of a reference type because we can't later import
 // it.  (Once we can export it, the value setter must also perform the necessary
 // subtype check, which implies we have some notion of exporting types, and we
 // don't have that yet.)
 {
     let bin = wasmTextToBinary(
         `(module
-          (gc_feature_opt_in 1)
+          (gc_feature_opt_in 2)
           (type $box (struct (field $val i32)))
-          (global $boxg (export "box") (mut (ref $box)) (ref.null (ref $box))))`);
+          (global $boxg (export "box") (mut (ref $box)) (ref.null)))`);
 
     assertErrorMessage(() => new WebAssembly.Module(bin), WebAssembly.CompileError,
                        /cannot expose reference type/);
 }
--- a/js/src/jit-test/tests/wasm/gc/ref-restrict.js
+++ b/js/src/jit-test/tests/wasm/gc/ref-restrict.js
@@ -46,304 +46,304 @@
 function wasmCompile(text) {
     return new WebAssembly.Module(wasmTextToBinary(text));
 }
 
 // Exported function can't take ref type parameter, but anyref is OK.
 
 assertErrorMessage(() => wasmCompile(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in 2)
       (type $box (struct (field $x i32)))
       (func (export "f") (param (ref $box)) (unreachable)))`),
                    WebAssembly.CompileError,
                    /cannot expose reference type/);
 
 assertEq(typeof wasmCompile(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in 2)
       (func (export "f") (param anyref) (unreachable)))`),
          "object");
 
 // Exported function can't return ref result, but anyref is OK.
 
 assertErrorMessage(() => wasmCompile(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in 2)
       (type $box (struct (field $x i32)))
-      (func (export "f") (result (ref $box)) (ref.null (ref $box))))`),
+      (func (export "f") (result (ref $box)) (ref.null)))`),
                    WebAssembly.CompileError,
                    /cannot expose reference type/);
 
 assertEq(typeof wasmCompile(
     `(module
-      (gc_feature_opt_in 1)
-      (func (export "f") (result anyref) (ref.null anyref)))`),
+      (gc_feature_opt_in 2)
+      (func (export "f") (result anyref) (ref.null)))`),
          "object");
 
 // Imported function can't take ref parameter, but anyref is OK.
 
 assertErrorMessage(() => wasmCompile(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in 2)
       (type $box (struct (field $x i32)))
       (import "m" "f" (param (ref $box))))`),
                    WebAssembly.CompileError,
                    /cannot expose reference type/);
 
 assertEq(typeof wasmCompile(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in 2)
       (import "m" "f" (param anyref)))`),
          "object");
 
 // Imported function can't return ref type, but anyref is OK.
 
 assertErrorMessage(() => wasmCompile(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in 2)
       (type $box (struct (field $x i32)))
       (import "m" "f" (param i32) (result (ref $box))))`),
                    WebAssembly.CompileError,
                    /cannot expose reference type/);
 
 assertEq(typeof wasmCompile(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in 2)
       (import "m" "f" (param i32) (result anyref)))`),
          "object");
 
 // Imported global can't be of Ref type (irrespective of mutability), though anyref is OK.
 
 assertErrorMessage(() => wasmCompile(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in 2)
       (type $box (struct (field $val i32)))
       (import "m" "g" (global (mut (ref $box)))))`),
                    WebAssembly.CompileError,
                    /cannot expose reference type/);
 
 assertErrorMessage(() => wasmCompile(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in 2)
       (type $box (struct (field $val i32)))
       (import "m" "g" (global (ref $box))))`),
                    WebAssembly.CompileError,
                    /cannot expose reference type/);
 
 assertEq(typeof wasmCompile(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in 2)
       (import "m" "g" (global (mut anyref))))`),
          "object");
 
 assertEq(typeof wasmCompile(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in 2)
       (import "m" "g" (global anyref)))`),
          "object");
 
 // Exported global can't be of Ref type (irrespective of mutability), though anyref is OK.
 
 assertErrorMessage(() => wasmCompile(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in 2)
       (type $box (struct (field $val i32)))
-      (global $boxg (export "box") (mut (ref $box)) (ref.null (ref $box))))`),
+      (global $boxg (export "box") (mut (ref $box)) (ref.null)))`),
                    WebAssembly.CompileError,
                    /cannot expose reference type/);
 
 assertErrorMessage(() => wasmCompile(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in 2)
       (type $box (struct (field $val i32)))
-      (global $boxg (export "box") (ref $box) (ref.null (ref $box))))`),
+      (global $boxg (export "box") (ref $box) (ref.null)))`),
                    WebAssembly.CompileError,
                    /cannot expose reference type/);
 
 assertEq(typeof wasmCompile(
     `(module
-      (gc_feature_opt_in 1)
-      (global $boxg (export "box") (mut anyref) (ref.null anyref)))`),
+      (gc_feature_opt_in 2)
+      (global $boxg (export "box") (mut anyref) (ref.null)))`),
          "object");
 
 assertEq(typeof wasmCompile(
     `(module
-      (gc_feature_opt_in 1)
-      (global $boxg (export "box") anyref (ref.null anyref)))`),
+      (gc_feature_opt_in 2)
+      (global $boxg (export "box") anyref (ref.null)))`),
          "object");
 
 // Exported table cannot reference functions that are exposed for Ref, but anyref is OK.
 
 assertErrorMessage(() => wasmCompile(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in 2)
       (type $box (struct (field $val i32)))
       (table (export "tbl") 1 anyfunc)
       (elem (i32.const 0) $f1)
       (func $f1 (param (ref $box)) (unreachable)))`),
                    WebAssembly.CompileError,
                    /cannot expose reference type/);
 
 assertErrorMessage(() => wasmCompile(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in 2)
       (type $box (struct (field $val i32)))
       (table (export "tbl") 1 anyfunc)
       (elem (i32.const 0) $f1)
-      (func $f1 (result (ref $box)) (ref.null (ref $box))))`),
+      (func $f1 (result (ref $box)) (ref.null)))`),
                    WebAssembly.CompileError,
                    /cannot expose reference type/);
 
 assertEq(typeof wasmCompile(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in 2)
       (table (export "tbl") 1 anyfunc)
       (elem (i32.const 0) $f1)
       (func $f1 (param anyref) (unreachable)))`),
          "object");
 
 assertEq(typeof wasmCompile(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in 2)
       (table (export "tbl") 1 anyfunc)
       (elem (i32.const 0) $f1)
-      (func $f1 (result anyref) (ref.null anyref)))`),
+      (func $f1 (result anyref) (ref.null)))`),
          "object");
 
 // Imported table cannot reference functions that are exposed for Ref, though anyref is OK.
 
 assertErrorMessage(() => wasmCompile(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in 2)
       (type $box (struct (field $val i32)))
       (import "m" "tbl" (table 1 anyfunc))
       (elem (i32.const 0) $f1)
       (func $f1 (param (ref $box)) (unreachable)))`),
                    WebAssembly.CompileError,
                    /cannot expose reference type/);
 
 assertErrorMessage(() => wasmCompile(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in 2)
       (type $box (struct (field $val i32)))
       (import "m" "tbl" (table 1 anyfunc))
       (elem (i32.const 0) $f1)
-      (func $f1 (result (ref $box)) (ref.null (ref $box))))`),
+      (func $f1 (result (ref $box)) (ref.null)))`),
                    WebAssembly.CompileError,
                    /cannot expose reference type/);
 
 assertEq(typeof wasmCompile(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in 2)
       (import "m" "tbl" (table 1 anyfunc))
       (elem (i32.const 0) $f1)
       (func $f1 (param anyref) (unreachable)))`),
          "object");
 
 assertEq(typeof wasmCompile(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in 2)
       (import "m" "tbl" (table 1 anyfunc))
       (elem (i32.const 0) $f1)
-      (func $f1 (result anyref) (ref.null anyref)))`),
+      (func $f1 (result anyref) (ref.null)))`),
          "object");
 
 // Can't call via exported table with type that is exposed for Ref, though anyref is OK.
 
 assertErrorMessage(() => wasmCompile(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in 2)
       (type $box (struct (field $val i32)))
       (type $fn (func (param (ref $box))))
       (table (export "tbl") 1 anyfunc)
       (func (param i32)
-       (call_indirect $fn (ref.null (ref $box)) (get_local 0))))`),
+       (call_indirect $fn (ref.null) (get_local 0))))`),
                    WebAssembly.CompileError,
                    /cannot expose reference type/);
 
 assertErrorMessage(() => wasmCompile(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in 2)
       (type $box (struct (field $val i32)))
       (type $fn (func (result (ref $box))))
       (table (export "tbl") 1 anyfunc)
       (func (param i32) (result (ref $box))
        (call_indirect $fn (get_local 0))))`),
                    WebAssembly.CompileError,
                    /cannot expose reference type/);
 
 assertEq(typeof wasmCompile(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in 2)
       (type $fn (func (param anyref)))
       (table (export "tbl") 1 anyfunc)
       (func (param i32)
-       (call_indirect $fn (ref.null anyref) (get_local 0))))`),
+       (call_indirect $fn (ref.null) (get_local 0))))`),
          "object");
 
 assertEq(typeof wasmCompile(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in 2)
       (type $fn (func (result anyref)))
       (table (export "tbl") 1 anyfunc)
       (func (param i32) (result anyref)
        (call_indirect $fn (get_local 0))))`),
          "object");
 
 // Can't call via imported table with type that is exposed for Ref, though anyref is OK.
 
 assertErrorMessage(() => wasmCompile(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in 2)
       (type $box (struct (field $val i32)))
       (type $fn (func (param (ref $box))))
       (import "m" "tbl" (table 1 anyfunc))
       (func (param i32)
-       (call_indirect $fn (ref.null (ref $box)) (get_local 0))))`),
+       (call_indirect $fn (ref.null) (get_local 0))))`),
                    WebAssembly.CompileError,
                    /cannot expose reference type/);
 
 assertErrorMessage(() => wasmCompile(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in 2)
       (type $box (struct (field $val i32)))
       (type $fn (func (result (ref $box))))
       (import "m" "tbl" (table 1 anyfunc))
       (func (param i32) (result (ref $box))
        (call_indirect $fn (get_local 0))))`),
                    WebAssembly.CompileError,
                    /cannot expose reference type/);
 
 assertEq(typeof wasmCompile(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in 2)
       (type $fn (func (param anyref)))
       (import "m" "tbl" (table 1 anyfunc))
       (func (param i32)
-       (call_indirect $fn (ref.null anyref) (get_local 0))))`),
+       (call_indirect $fn (ref.null) (get_local 0))))`),
          "object");
 
 assertEq(typeof wasmCompile(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in 2)
       (type $fn (func (result anyref)))
       (import "m" "tbl" (table 1 anyfunc))
       (func (param i32) (result anyref)
        (call_indirect $fn (get_local 0))))`),
          "object");
 
 // We can call via a private table with a type that is exposed for Ref.
 
 {
     let m = wasmCompile(
         `(module
-          (gc_feature_opt_in 1)
+          (gc_feature_opt_in 2)
           (type $box (struct (field $val i32)))
           (type $fn (func (param (ref $box)) (result i32)))
           (table 1 anyfunc)
           (elem (i32.const 0) $f1)
           (func $f1 (param (ref $box)) (result i32) (i32.const 37))
           (func (export "f") (param i32) (result i32)
-           (call_indirect $fn (ref.null (ref $box)) (get_local 0))))`);
+           (call_indirect $fn (ref.null) (get_local 0))))`);
     let i = new WebAssembly.Instance(m).exports;
     assertEq(i.f(0), 37);
 }
--- a/js/src/jit-test/tests/wasm/gc/ref-struct.js
+++ b/js/src/jit-test/tests/wasm/gc/ref-struct.js
@@ -3,54 +3,54 @@
 // We'll be running some binary-format tests shortly.
 
 load(libdir + "wasm-binary.js");
 
 const v2vSigSection = sigSection([{args:[], ret:VoidCode}]);
 
 function checkInvalid(body, errorMessage) {
     assertErrorMessage(() => new WebAssembly.Module(
-        moduleWithSections([gcFeatureOptInSection(1),
+        moduleWithSections([gcFeatureOptInSection(2),
                             v2vSigSection,
                             declSection([0]),
                             bodySection([body])])),
                        WebAssembly.CompileError,
                        errorMessage);
 }
 
 // General test case for struct.new, struct.get, and struct.set: binary tree
 // manipulation.
 
 {
     let bin = wasmTextToBinary(
         `(module
-          (gc_feature_opt_in 1)
+          (gc_feature_opt_in 2)
 
           (import $print_lp "" "print_lp" (func))
           (import $print_rp "" "print_rp" (func))
           (import $print_int "" "print_int" (func (param i32)))
 
           (type $wabbit (struct
                          (field $x (mut i32))
                          (field $left (mut (ref $wabbit)))
                          (field $right (mut (ref $wabbit)))))
 
-          (global $g (mut (ref $wabbit)) (ref.null (ref $wabbit)))
+          (global $g (mut (ref $wabbit)) (ref.null))
 
           (global $k (mut i32) (i32.const 0))
 
           (func (export "init") (param $n i32)
                 (set_global $g (call $make (get_local $n))))
 
           (func $make (param $n i32) (result (ref $wabbit))
                 (local $tmp i32)
                 (set_local $tmp (get_global $k))
                 (set_global $k (i32.add (get_local $tmp) (i32.const 1)))
                 (if (ref $wabbit) (i32.le_s (get_local $n) (i32.const 2))
-                    (struct.new $wabbit (get_local $tmp) (ref.null (ref $wabbit)) (ref.null (ref $wabbit)))
+                    (struct.new $wabbit (get_local $tmp) (ref.null) (ref.null))
                     (block (ref $wabbit)
                       (struct.new $wabbit
                                   (get_local $tmp)
                                   (call $make (i32.sub (get_local $n) (i32.const 1)))
                                   (call $make (i32.sub (get_local $n) (i32.const 2)))))))
 
           (func (export "accumulate") (result i32)
                 (call $accum (get_global $g)))
@@ -114,55 +114,55 @@ function checkInvalid(body, errorMessage
 }
 
 // Sanity check for struct.set: we /can/ store a (ref T) into a (ref U) field
 // with struct.set if T <: U; this should fall out of normal coercion but good
 // to test.
 
 wasmEvalText(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in 2)
       (type $node (struct (field (mut (ref $node)))))
       (type $nix (struct (field (mut (ref $node))) (field i32)))
       (func $f (param $p (ref $node)) (param $q (ref $nix))
        (struct.set $node 0 (get_local $p) (get_local $q))))`);
 
 // struct.narrow: if the pointer's null we get null
 
 assertEq(wasmEvalText(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in 2)
       (type $node (struct (field i32)))
       (type $node2 (struct (field i32) (field f32)))
       (func $f (param $p (ref $node)) (result (ref $node2))
        (struct.narrow (ref $node) (ref $node2) (get_local $p)))
       (func (export "test") (result anyref)
-       (call $f (ref.null (ref $node)))))`).exports.test(),
+       (call $f (ref.null))))`).exports.test(),
          null);
 
 // struct.narrow: if the downcast succeeds we get the original pointer
 
 assertEq(wasmEvalText(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in 2)
       (type $node (struct (field i32)))
       (type $node2 (struct (field i32) (field f32)))
       (func $f (param $p (ref $node)) (result (ref $node2))
        (struct.narrow (ref $node) (ref $node2) (get_local $p)))
       (func (export "test") (result i32)
        (local $n (ref $node))
        (set_local $n (struct.new $node2 (i32.const 0) (f32.const 12)))
        (ref.eq (call $f (get_local $n)) (get_local $n))))`).exports.test(),
          1);
 
 // And once more with mutable fields
 
 assertEq(wasmEvalText(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in 2)
       (type $node (struct (field (mut i32))))
       (type $node2 (struct (field (mut i32)) (field f32)))
       (func $f (param $p (ref $node)) (result (ref $node2))
        (struct.narrow (ref $node) (ref $node2) (get_local $p)))
       (func (export "test") (result i32)
        (local $n (ref $node))
        (set_local $n (struct.new $node2 (i32.const 0) (f32.const 12)))
        (ref.eq (call $f (get_local $n)) (get_local $n))))`).exports.test(),
@@ -174,111 +174,111 @@ assertEq(wasmEvalText(
 //
 // We use ref-typed fields here because they have the trickiest equality rules,
 // and we have two cases: one where the ref types are the same, and one where
 // they reference different structures that look the same; this latter case
 // should fail because our structural compatibility is shallow.
 
 assertEq(wasmEvalText(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in 2)
 
       (type $node (struct (field i32)))
       (type $node2a (struct (field i32) (field (ref $node))))
       (type $node2b (struct (field i32) (field (ref $node))))
 
       (func $f (param $p (ref $node)) (result (ref $node2b))
        (struct.narrow (ref $node) (ref $node2b) (get_local $p)))
 
       (func (export "test") (result i32)
        (local $n (ref $node))
-       (set_local $n (struct.new $node2a (i32.const 0) (ref.null (ref $node))))
+       (set_local $n (struct.new $node2a (i32.const 0) (ref.null)))
        (ref.eq (call $f (get_local $n)) (get_local $n))))`).exports.test(),
          1);
 
 assertEq(wasmEvalText(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in 2)
 
       (type $node (struct (field i32)))
       (type $nodeCopy (struct (field i32)))
       (type $node2a (struct (field i32) (field (ref $node))))
       (type $node2b (struct (field i32) (field (ref $nodeCopy))))
 
       (func $f (param $p (ref $node)) (result (ref $node2b))
        (struct.narrow (ref $node) (ref $node2b) (get_local $p)))
 
       (func (export "test") (result i32)
        (local $n (ref $node))
-       (set_local $n (struct.new $node2a (i32.const 0) (ref.null (ref $node))))
+       (set_local $n (struct.new $node2a (i32.const 0) (ref.null)))
        (ref.eq (call $f (get_local $n)) (get_local $n))))`).exports.test(),
          0);
 
 // Another subtle case: struct.narrow can target a type that is not the concrete
 // type of the object, but a prefix of that concrete type.
 
 assertEq(wasmEvalText(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in 2)
       (type $node (struct (field i32)))
       (type $node2 (struct (field i32) (field f32)))
       (type $node3 (struct (field i32) (field f32) (field f64)))
       (func $f (param $p (ref $node)) (result (ref $node2))
        (struct.narrow (ref $node) (ref $node2) (get_local $p)))
       (func (export "test") (result i32)
        (local $n (ref $node))
        (set_local $n (struct.new $node3 (i32.const 0) (f32.const 12) (f64.const 17)))
        (ref.eq (call $f (get_local $n)) (get_local $n))))`).exports.test(),
          1);
 
 // struct.narrow: if the downcast fails we get null
 
 assertEq(wasmEvalText(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in 2)
       (type $node (struct (field i32)))
       (type $node2 (struct (field i32) (field f32)))
       (type $snort (struct (field i32) (field f64)))
       (func $f (param $p (ref $node)) (result (ref $node2))
        (struct.narrow (ref $node) (ref $node2) (get_local $p)))
       (func (export "test") (result anyref)
        (call $f (struct.new $snort (i32.const 0) (f64.const 12)))))`).exports.test(),
          null);
 
 // struct.narrow: anyref -> struct when the anyref is the right struct;
 // special case since anyref requires unboxing
 
 assertEq(wasmEvalText(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in 2)
       (type $node (struct (field i32)))
       (func $f (param $p anyref) (result (ref $node))
        (struct.narrow anyref (ref $node) (get_local $p)))
       (func (export "test") (result i32)
        (local $n (ref $node))
        (set_local $n (struct.new $node (i32.const 0)))
        (ref.eq (call $f (get_local $n)) (get_local $n))))`).exports.test(),
          1);
 
 // struct.narrow: anyref -> struct when the anyref is some random gunk.
 
 assertEq(wasmEvalText(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in 2)
       (type $node (struct (field i32)))
       (func (export "test") (param $p anyref) (result anyref)
        (struct.narrow anyref (ref $node) (get_local $p))))`).exports.test({hi:37}),
          null);
 
 // Types are private to an instance and struct.narrow can't break this
 
 {
     let txt =
         `(module
-          (gc_feature_opt_in 1)
+          (gc_feature_opt_in 2)
           (type $node (struct (field i32)))
           (func (export "make") (param $n i32) (result anyref)
            (struct.new $node (get_local $n)))
           (func (export "coerce") (param $p anyref) (result i32)
            (ref.is_null (struct.narrow anyref (ref $node) (get_local $p)))))`;
     let mod = new WebAssembly.Module(wasmTextToBinary(txt));
     let ins1 = new WebAssembly.Instance(mod).exports;
     let ins2 = new WebAssembly.Instance(mod).exports;
@@ -288,201 +288,199 @@ assertEq(wasmEvalText(
 }
 
 // Negative tests
 
 // Attempting to mutate immutable field with struct.set
 
 assertErrorMessage(() => wasmEvalText(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in 2)
       (type $node (struct (field i32)))
       (func $f (param $p (ref $node))
        (struct.set $node 0 (get_local $p) (i32.const 37))))`),
                    WebAssembly.CompileError,
                    /field is not mutable/);
 
 // Attempting to store incompatible value in mutable field with struct.set
 
 assertErrorMessage(() => wasmEvalText(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in 2)
       (type $node (struct (field (mut i32))))
       (func $f (param $p (ref $node))
        (struct.set $node 0 (get_local $p) (f32.const 37))))`),
                    WebAssembly.CompileError,
                    /expression has type f32 but expected i32/);
 
 // Out-of-bounds reference for struct.get
 
 assertErrorMessage(() => wasmEvalText(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in 2)
       (type $node (struct (field i32)))
       (func $f (param $p (ref $node)) (result i32)
        (struct.get $node 1 (get_local $p))))`),
                    WebAssembly.CompileError,
                    /field index out of range/);
 
 // Out-of-bounds reference for struct.set
 
 assertErrorMessage(() => wasmEvalText(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in 2)
       (type $node (struct (field (mut i32))))
       (func $f (param $p (ref $node))
        (struct.set $node 1 (get_local $p) (i32.const 37))))`),
                    WebAssembly.CompileError,
                    /field index out of range/);
 
 // Base pointer is of unrelated type to stated type in struct.get
 
 assertErrorMessage(() => wasmEvalText(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in 2)
       (type $node (struct (field i32)))
       (type $snort (struct (field f64)))
       (func $f (param $p (ref $snort)) (result i32)
        (struct.get $node 0 (get_local $p))))`),
                    WebAssembly.CompileError,
                    /expression has type.*but expected.*/);
 
 // Base pointer is of unrelated type to stated type in struct.set
 
 assertErrorMessage(() => wasmEvalText(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in 2)
       (type $node (struct (field (mut i32))))
       (type $snort (struct (field f64)))
       (func $f (param $p (ref $snort)) (result i32)
        (struct.set $node 0 (get_local $p) (i32.const 0))))`),
                    WebAssembly.CompileError,
                    /expression has type.*but expected.*/);
 
 // Base pointer is of unrelated type to stated type in struct.narrow
 
 assertErrorMessage(() => wasmEvalText(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in 2)
       (type $node (struct (field i32)))
       (type $node2 (struct (field i32) (field f32)))
       (type $snort (struct (field f64)))
       (func $f (param $p (ref $snort)) (result (ref $node2))
        (struct.narrow (ref $node) (ref $node2) (get_local 0))))`),
                    WebAssembly.CompileError,
                    /expression has type.*but expected.*/);
 
 // source and target types are compatible except for mutability
 
 assertErrorMessage(() => wasmEvalText(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in 2)
       (type $node (struct (field i32)))
       (type $node2 (struct (field (mut i32)) (field f32)))
       (func $f (param $p (ref $node)) (result (ref $node2))
        (struct.narrow (ref $node) (ref $node2) (get_local 0))))`),
                    WebAssembly.CompileError,
                    /invalid narrowing operation/);
 
 assertErrorMessage(() => wasmEvalText(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in 2)
       (type $node (struct (field (mut i32))))
       (type $node2 (struct (field i32) (field f32)))
       (func $f (param $p (ref $node)) (result (ref $node2))
        (struct.narrow (ref $node) (ref $node2) (get_local 0))))`),
                    WebAssembly.CompileError,
                    /invalid narrowing operation/);
 
 // source and target types must be ref types: source syntax
 
 assertErrorMessage(() => wasmEvalText(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in 2)
       (type $node (struct (field i32)))
       (func $f (param $p (ref $node)) (result anyref)
        (struct.narrow i32 anyref (get_local 0))))`),
                    SyntaxError,
                    /struct.narrow requires ref type/);
 
 assertErrorMessage(() => wasmEvalText(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in 2)
       (type $node (struct (field i32)))
       (func $f (param $p (ref $node)) (result anyref)
        (struct.narrow anyref i32 (get_local 0))))`),
                    SyntaxError,
                    /struct.narrow requires ref type/);
 
 // source and target types must be ref types: binary format
 
 checkInvalid(funcBody({locals:[],
                        body:[
                            RefNull,
-                           AnyrefCode,
                            MiscPrefix, StructNarrow, I32Code, AnyrefCode,
                            DropCode
                        ]}),
              /invalid reference type for struct.narrow/);
 
 checkInvalid(funcBody({locals:[],
                        body:[
                            RefNull,
-                           AnyrefCode,
                            MiscPrefix, StructNarrow, AnyrefCode, I32Code,
                            DropCode
                        ]}),
              /invalid reference type for struct.narrow/);
 
 // target type is anyref so source type must be anyref as well (no upcasts)
 
 assertErrorMessage(() => wasmEvalText(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in 2)
       (type $node (struct (field i32)))
       (func $f (param $p (ref $node)) (result anyref)
        (struct.narrow (ref $node) anyref (get_local 0))))`),
                    WebAssembly.CompileError,
                    /invalid type combination in struct.narrow/);
 
 // target type must be subtype of source type (no upcasts)
 
 assertErrorMessage(() => wasmEvalText(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in 2)
       (type $node (struct (field i32)))
       (type $node2 (struct (field i32) (field f32)))
       (func $f (param $p (ref $node2)) (result anyref)
        (struct.narrow (ref $node2) (ref $node) (get_local 0))))`),
                    WebAssembly.CompileError,
                    /invalid narrowing operation/);
 
 // Null pointer dereference in struct.get
 
 assertErrorMessage(function() {
     let ins = wasmEvalText(
         `(module
-          (gc_feature_opt_in 1)
+          (gc_feature_opt_in 2)
           (type $node (struct (field i32)))
           (func (export "test")
-           (drop (call $f (ref.null (ref $node)))))
+           (drop (call $f (ref.null))))
           (func $f (param $p (ref $node)) (result i32)
            (struct.get $node 0 (get_local $p))))`);
     ins.exports.test();
 },
                    WebAssembly.RuntimeError,
                    /dereferencing null pointer/);
 
 // Null pointer dereference in struct.set
 
 assertErrorMessage(function() {
     let ins = wasmEvalText(
         `(module
-          (gc_feature_opt_in 1)
+          (gc_feature_opt_in 2)
           (type $node (struct (field (mut i32))))
           (func (export "test")
-           (call $f (ref.null (ref $node))))
+           (call $f (ref.null)))
           (func $f (param $p (ref $node))
            (struct.set $node 0 (get_local $p) (i32.const 0))))`);
     ins.exports.test();
 },
                    WebAssembly.RuntimeError,
                    /dereferencing null pointer/);
--- a/js/src/jit-test/tests/wasm/gc/ref.js
+++ b/js/src/jit-test/tests/wasm/gc/ref.js
@@ -3,17 +3,17 @@ if (!wasmGcEnabled()) {
                        WebAssembly.CompileError, /reference types not enabled/);
     quit(0);
 }
 
 // Parsing and resolving.
 
 var bin = wasmTextToBinary(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in 2)
       (type $cons (struct
                    (field $car i32)
                    (field $cdr (ref $cons))))
 
       (type $odd (struct
                   (field $odd.x i32)
                   (field $to_even (ref $even))))
 
@@ -29,191 +29,191 @@ var bin = wasmTextToBinary(
       ;; Note none of these functions are exported, as they use Ref types in their signatures.
 
       (func (param (ref $cons)) (result i32)
        (i32.const 0))
 
       (func $cdr (param $p (ref $cons)) (result (ref $cons))
        (local $l (ref $cons))
        ;; store null value of correct type
-       (set_local $l (ref.null (ref $cons)))
+       (set_local $l (ref.null))
        ;; store local of correct type
        (set_local $l (get_local $p))
        ;; store call result of correct type
        (set_local $l (call $cdr (get_local $p)))
        ;; TODO: eventually also a test with get_global
        ;; blocks and if with result type
        (block (ref $cons)
         (if (ref $cons) (i32.eqz (i32.const 0))
             (unreachable)
-            (ref.null (ref $cons)))))
+            (ref.null))))
 
       (func (param (ref $even)) (result (ref $odd))
-       (ref.null (ref $odd)))
+       (ref.null))
 
       (func (param (ref $odd)) (result (ref $even))
-       (ref.null (ref $even)))
+       (ref.null))
 
       (func (param (ref $cons))
        (call $cdr (get_local 0))
        drop
        (call $imp (get_local 0))
        drop)
 
       (func (param (ref $cons))
-       (drop (ref.eq (get_local 0) (ref.null (ref $cons))))
-       (drop (ref.eq (ref.null (ref $cons)) (get_local 0)))
-       (drop (ref.eq (get_local 0) (ref.null anyref)))
-       (drop (ref.eq (ref.null anyref) (get_local 0))))
+       (drop (ref.eq (get_local 0) (ref.null)))
+       (drop (ref.eq (ref.null) (get_local 0)))
+       (drop (ref.eq (get_local 0) (ref.null)))
+       (drop (ref.eq (ref.null) (get_local 0))))
      )`);
 
 // Validation
 
 assertEq(WebAssembly.validate(bin), true);
 
 // ref.is_null should work on any reference type
 
 new WebAssembly.Module(wasmTextToBinary(`
 (module
- (gc_feature_opt_in 1)
+ (gc_feature_opt_in 2)
  (type $s (struct))
  (func $null (param (ref $s)) (result i32)
    (ref.is_null (get_local 0))))
 `))
 
 // Automatic upcast to anyref
 
 new WebAssembly.Module(wasmTextToBinary(`
 (module
- (gc_feature_opt_in 1)
+ (gc_feature_opt_in 2)
  (type $s (struct (field i32)))
  (func $f (param (ref $s)) (call $g (get_local 0)))
  (func $g (param anyref) (unreachable)))
 `));
 
 // Misc failure modes
 
 assertErrorMessage(() => wasmEvalText(`
 (module
- (gc_feature_opt_in 1)
+ (gc_feature_opt_in 2)
  (func (param (ref $odd)) (unreachable)))
 `),
 SyntaxError, /Type label.*not found/);
 
 // Ref type mismatch in parameter is allowed through the prefix rule
 // but not if the structs are incompatible.
 
 wasmEvalText(`
 (module
- (gc_feature_opt_in 1)
+ (gc_feature_opt_in 2)
  (type $s (struct (field i32)))
  (type $t (struct (field i32)))
  (func $f (param (ref $s)) (unreachable))
  (func $g (param (ref $t)) (call $f (get_local 0)))
 )`);
 
 assertErrorMessage(() => wasmEvalText(`
 (module
- (gc_feature_opt_in 1)
+ (gc_feature_opt_in 2)
  (type $s (struct (field i32)))
  (type $t (struct (field f32))) ;; Incompatible type
  (func $f (param (ref $s)) (unreachable))
  (func $g (param (ref $t)) (call $f (get_local 0)))
 )`),
 WebAssembly.CompileError, /expression has type ref.*but expected ref/);
 
 assertErrorMessage(() => wasmEvalText(`
 (module
- (gc_feature_opt_in 1)
+ (gc_feature_opt_in 2)
  (type $s (struct (field i32)))
  (type $t (struct (field (mut i32)))) ;; Incompatible mutability
  (func $f (param (ref $s)) (unreachable))
  (func $g (param (ref $t)) (call $f (get_local 0)))
 )`),
 WebAssembly.CompileError, /expression has type ref.*but expected ref/);
 
 // Ref type mismatch in assignment to local but the prefix rule allows
 // the assignment to succeed if the structs are the same.
 
 wasmEvalText(`
 (module
- (gc_feature_opt_in 1)
+ (gc_feature_opt_in 2)
  (type $s (struct (field i32)))
  (type $t (struct (field i32)))
  (func $f (param (ref $s)) (local (ref $t)) (set_local 1 (get_local 0))))
 `)
 
 assertErrorMessage(() => wasmEvalText(`
 (module
- (gc_feature_opt_in 1)
+ (gc_feature_opt_in 2)
  (type $s (struct (field i32)))
  (type $t (struct (field f32)))
  (func $f (param (ref $s)) (local (ref $t)) (set_local 1 (get_local 0))))
 `),
 WebAssembly.CompileError, /expression has type ref.*but expected ref/);
 
 assertErrorMessage(() => wasmEvalText(`
 (module
- (gc_feature_opt_in 1)
+ (gc_feature_opt_in 2)
  (type $s (struct (field i32)))
  (type $t (struct (field (mut i32))))
  (func $f (param (ref $s)) (unreachable))
  (func $g (param (ref $t)) (call $f (get_local 0)))
 )`),
 WebAssembly.CompileError, /expression has type ref.*but expected ref/);
 
 // Ref type mismatch in return but the prefix rule allows the return
 // to succeed if the structs are the same.
 
 wasmEvalText(`
 (module
- (gc_feature_opt_in 1)
+ (gc_feature_opt_in 2)
  (type $s (struct (field i32)))
  (type $t (struct (field i32)))
  (func $f (param (ref $s)) (result (ref $t)) (get_local 0)))
 `);
 
 assertErrorMessage(() => wasmEvalText(`
 (module
- (gc_feature_opt_in 1)
+ (gc_feature_opt_in 2)
  (type $s (struct (field i32)))
  (type $t (struct (field f32)))
  (func $f (param (ref $s)) (result (ref $t)) (get_local 0)))
 `),
 WebAssembly.CompileError, /expression has type ref.*but expected ref/);
 
 assertErrorMessage(() => wasmEvalText(`
 (module
- (gc_feature_opt_in 1)
+ (gc_feature_opt_in 2)
  (type $s (struct (field i32)))
  (type $t (struct (field (mut i32))))
  (func $f (param (ref $s)) (result (ref $t)) (get_local 0)))
 `),
 WebAssembly.CompileError, /expression has type ref.*but expected ref/);
 
 // Ref type can't reference a function type
 
 assertErrorMessage(() => wasmEvalText(`
 (module
- (gc_feature_opt_in 1)
+ (gc_feature_opt_in 2)
  (type $x (func (param i32)))
  (func $f (param (ref $x)) (unreachable)))
 `),
 SyntaxError, /Type label.*not found/);
 
 assertErrorMessage(() => wasmEvalText(`
 (module
- (gc_feature_opt_in 1)
+ (gc_feature_opt_in 2)
  (type (func (param i32)))
  (func $f (param (ref 0)) (unreachable)))
 `),
 WebAssembly.CompileError, /does not reference a struct type/);
 
 // No automatic downcast from anyref
 
 assertErrorMessage(() => wasmEvalText(`
 (module
- (gc_feature_opt_in 1)
+ (gc_feature_opt_in 2)
  (type $s (struct (field i32)))
  (func $f (param anyref) (call $g (get_local 0)))
  (func $g (param (ref $s)) (unreachable)))
 `),
 WebAssembly.CompileError, /expression has type anyref but expected ref/);
--- a/js/src/jit-test/tests/wasm/gc/structs.js
+++ b/js/src/jit-test/tests/wasm/gc/structs.js
@@ -1,15 +1,15 @@
 // |jit-test| skip-if: !wasmGcEnabled()
 
 var conf = getBuildConfiguration();
 
 var bin = wasmTextToBinary(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in 2)
 
       (table 2 anyfunc)
       (elem (i32.const 0) $doit $doitagain)
 
       ;; Type array has a mix of types
 
       (type $f1 (func (param i32) (result i32)))
 
@@ -221,17 +221,17 @@ assertEq(withfloats._1, Math.PI);
 assertEq(withfloats._2, bigger);
 assertEq(withfloats._3, Math.fround(5/6));
 assertEq(withfloats._4, 0x1337);
 
 // A simple stress test
 
 var stress = wasmTextToBinary(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in 2)
       (type $node (struct (field i32) (field (ref $node))))
       (func (export "iota1") (param $n i32) (result anyref)
        (local $list (ref $node))
        (block $exit
         (loop $loop
          (br_if $exit (i32.eqz (get_local $n)))
          (set_local $list (struct.new $node (get_local $n) (get_local $list)))
          (set_local $n (i32.sub (get_local $n) (i32.const 1)))
@@ -249,17 +249,17 @@ assertEq(the_list, null);
 // Fields and their exposure in JS.  We can't export types yet so hide them
 // inside the module with globals.
 
 // i64 fields.
 
 {
     let txt =
         `(module
-          (gc_feature_opt_in 1)
+          (gc_feature_opt_in 2)
 
           (type $big (struct
                       (field (mut i32))
                       (field (mut i64))
                       (field (mut i32))))
 
           (func (export "set") (param anyref)
            (local (ref $big))
@@ -309,24 +309,24 @@ assertEq(the_list, null);
     assertEq(v._1_high, 0x31415926)
     assertEq(ins.low(v), 0x53589793);
     assertEq(ins.high(v), 0x31415926)
 }
 
 {
     let txt =
         `(module
-          (gc_feature_opt_in 1)
+          (gc_feature_opt_in 2)
 
           (type $big (struct
                       (field (mut i32))
                       (field (mut i64))
                       (field (mut i32))))
 
-          (global $g (mut (ref $big)) (ref.null (ref $big)))
+          (global $g (mut (ref $big)) (ref.null))
 
           (func (export "make") (result anyref)
            (set_global $g
             (struct.new $big (i32.const 0x7aaaaaaa) (i64.const 0x4201020337) (i32.const 0x6bbbbbbb)))
            (get_global $g))
 
           (func (export "update0") (param $x i32)
            (struct.set $big 0 (get_global $g) (get_local $x)))
@@ -384,21 +384,21 @@ assertEq(the_list, null);
     assertEq(ins.get1_high(), 0x77777777);
     assertEq(v._1_high, 0x77777777);
     assertEq(v._2, 0x62345123);
 }
 
 
 var bin = wasmTextToBinary(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in 2)
 
       (type $cons (struct (field i32) (field (ref $cons))))
 
-      (global $g (mut (ref $cons)) (ref.null (ref $cons)))
+      (global $g (mut (ref $cons)) (ref.null))
 
       (func (export "push") (param i32)
        (set_global $g (struct.new $cons (get_local 0) (get_global $g))))
 
       (func (export "top") (result i32)
        (struct.get $cons 0 (get_global $g)))
 
       (func (export "pop")
@@ -427,17 +427,17 @@ assertErrorMessage(() => ins.pop(),
 
 // Check that a wrapped object cannot be unboxed from anyref even if the wrapper
 // points to the right type.  This is a temporary restriction, until we're able
 // to avoid dealing with wrappers inside the engine.
 
 {
     var ins = wasmEvalText(
         `(module
-          (gc_feature_opt_in 1)
+          (gc_feature_opt_in 2)
           (type $Node (struct (field i32)))
           (func (export "mk") (result anyref)
            (struct.new $Node (i32.const 37)))
           (func (export "f") (param $n anyref) (result anyref)
            (struct.narrow anyref (ref $Node) (get_local $n))))`).exports;
     var n = ins.mk();
     assertEq(ins.f(n), n);
     assertEq(ins.f(wrapWithProto(n, {})), null);
@@ -445,17 +445,17 @@ assertErrorMessage(() => ins.pop(),
 
 // Field names.
 
 // Test that names map to the right fields.
 
 {
     let ins = new WebAssembly.Instance(new WebAssembly.Module(wasmTextToBinary(
         `(module
-          (gc_feature_opt_in 1)
+          (gc_feature_opt_in 2)
 
           (type $s (struct
                     (field $x i32)
                     (field $y i32)))
 
           (func $f (param $p (ref $s)) (result i32)
            (struct.get $s $x (get_local $p)))
 
@@ -473,165 +473,165 @@ assertErrorMessage(() => ins.pop(),
     assertEq(ins.testf(10), 10);
     assertEq(ins.testg(10), 20);
 }
 
 // Test that field names must be unique in the module.
 
 assertErrorMessage(() => wasmTextToBinary(
     `(module
-      (gc_feature_opt_in 1)
+      (gc_feature_opt_in 2)
 
       (type $s (struct (field $x i32)))
       (type $t (struct (field $x i32)))
      )`),
                   SyntaxError,
                   /duplicate field name/);
 
 // negative tests
 
 // Wrong type passed as initializer
 
 assertErrorMessage(() => new WebAssembly.Module(wasmTextToBinary(`
 (module
-  (gc_feature_opt_in 1)
+  (gc_feature_opt_in 2)
   (type $r (struct (field i32)))
   (func $f (param f64) (result anyref)
     (struct.new $r (get_local 0)))
 )`)),
 WebAssembly.CompileError, /type mismatch/);
 
 // Too few values passed for initializer
 
 assertErrorMessage(() => new WebAssembly.Module(wasmTextToBinary(`
 (module
-  (gc_feature_opt_in 1)
+  (gc_feature_opt_in 2)
   (type $r (struct (field i32) (field i32)))
   (func $f (result anyref)
     (struct.new $r (i32.const 0)))
 )`)),
 WebAssembly.CompileError, /popping value from empty stack/);
 
 // Too many values passed for initializer, sort of
 
 assertErrorMessage(() => new WebAssembly.Module(wasmTextToBinary(`
 (module
-  (gc_feature_opt_in 1)
+  (gc_feature_opt_in 2)
   (type $r (struct (field i32) (field i32)))
   (func $f (result anyref)
     (i32.const 0)
     (i32.const 1)
     (i32.const 2)
     struct.new $r)
 )`)),
 WebAssembly.CompileError, /unused values/);
 
 // Not referencing a structure type
 
 assertErrorMessage(() => new WebAssembly.Module(wasmTextToBinary(`
 (module
-  (gc_feature_opt_in 1)
+  (gc_feature_opt_in 2)
   (type (func (param i32) (result i32)))
   (func $f (result anyref)
     (struct.new 0))
 )`)),
 WebAssembly.CompileError, /not a struct type/);
 
 // Nominal type equivalence for structs, but the prefix rule allows this
 // conversion to succeed.
 
 wasmEvalText(`
  (module
-   (gc_feature_opt_in 1)
+   (gc_feature_opt_in 2)
    (type $p (struct (field i32)))
    (type $q (struct (field i32)))
    (func $f (result (ref $p))
     (struct.new $q (i32.const 0))))
 `);
 
 // The field name is optional, so this should work.
 
 wasmEvalText(`
 (module
- (gc_feature_opt_in 1)
+ (gc_feature_opt_in 2)
  (type $s (struct (field i32))))
 `)
 
 // Empty structs are OK.
 
 wasmEvalText(`
 (module
- (gc_feature_opt_in 1)
+ (gc_feature_opt_in 2)
  (type $s (struct)))
 `)
 
 // Multiply defined structures.
 
 assertErrorMessage(() => wasmEvalText(`
 (module
- (gc_feature_opt_in 1)
+ (gc_feature_opt_in 2)
  (type $s (struct (field $x i32)))
  (type $s (struct (field $y i32))))
 `),
 SyntaxError, /duplicate type name/);
 
 // Bogus type definition syntax.
 
 assertErrorMessage(() => wasmEvalText(`
 (module
- (gc_feature_opt_in 1)
+ (gc_feature_opt_in 2)
  (type $s))
 `),
 SyntaxError, /parsing wasm text/);
 
 assertErrorMessage(() => wasmEvalText(`
 (module
- (gc_feature_opt_in 1)
+ (gc_feature_opt_in 2)
  (type $s (field $x i32)))
 `),
 SyntaxError, /bad type definition/);
 
 assertErrorMessage(() => wasmEvalText(`
 (module
- (gc_feature_opt_in 1)
+ (gc_feature_opt_in 2)
  (type $s (struct (field $x i31))))
 `),
 SyntaxError, /parsing wasm text/);
 
 assertErrorMessage(() => wasmEvalText(`
 (module
- (gc_feature_opt_in 1)
+ (gc_feature_opt_in 2)
  (type $s (struct (fjeld $x i32))))
 `),
 SyntaxError, /parsing wasm text/);
 
 assertErrorMessage(() => wasmEvalText(`
 (module
- (gc_feature_opt_in 1)
+ (gc_feature_opt_in 2)
  (type $s (struct abracadabra)))
 `),
 SyntaxError, /parsing wasm text/);
 
 // Function should not reference struct type: syntactic test
 
 assertErrorMessage(() => wasmEvalText(`
 (module
- (gc_feature_opt_in 1)
+ (gc_feature_opt_in 2)
  (type $s (struct))
  (type $f (func (param i32) (result i32)))
  (func (type 0) (param i32) (result i32) (unreachable)))
 `),
 WebAssembly.CompileError, /signature index references non-signature/);
 
 // Can't set immutable fields from JS
 
 {
     let ins = wasmEvalText(
         `(module
-          (gc_feature_opt_in 1)
+          (gc_feature_opt_in 2)
           (type $s (struct
                     (field i32)
                     (field (mut i64))))
           (func (export "make") (result anyref)
            (struct.new $s (i32.const 37) (i64.const 42))))`).exports;
     let v = ins.make();
     assertErrorMessage(() => v._0 = 12,
                        Error,
@@ -646,17 +646,17 @@ WebAssembly.CompileError, /signature ind
 
 // Function should not reference struct type: binary test
 
 var bad = new Uint8Array([0x00, 0x61, 0x73, 0x6d,
                           0x01, 0x00, 0x00, 0x00,
 
                           0x2a,                   // GcFeatureOptIn section
                           0x01,                   // Section size
-                          0x01,                   // Version
+                          0x02,                   // Version
 
                           0x01,                   // Type section
                           0x03,                   // Section size
                           0x01,                   // One type
                           0x50,                   // Struct
                           0x00,                   // Zero fields
 
                           0x03,                   // Function section
--- a/js/src/jit-test/tests/wasm/gc/tables-generalized.js
+++ b/js/src/jit-test/tests/wasm/gc/tables-generalized.js
@@ -3,53 +3,53 @@
 ///////////////////////////////////////////////////////////////////////////
 //
 // General table management in wasm
 
 // Wasm: Create table-of-anyref
 
 new WebAssembly.Module(wasmTextToBinary(
     `(module
-       (gc_feature_opt_in 1)
+       (gc_feature_opt_in 2)
        (table 10 anyref))`));
 
 // Wasm: Import table-of-anyref
 // JS: create table-of-anyref
 
 new WebAssembly.Instance(new WebAssembly.Module(wasmTextToBinary(
     `(module
-       (gc_feature_opt_in 1)
+       (gc_feature_opt_in 2)
        (table (import "m" "t") 10 anyref))`)),
                          {m:{t: new WebAssembly.Table({element:"anyref", initial:10})}});
 
 new WebAssembly.Instance(new WebAssembly.Module(wasmTextToBinary(
     `(module
-       (gc_feature_opt_in 1)
+       (gc_feature_opt_in 2)
        (import "m" "t" (table 10 anyref)))`)),
                          {m:{t: new WebAssembly.Table({element:"anyref", initial:10})}});
 
 // Wasm: Export table-of-anyref, initial values shall be null
 
 {
     let ins = new WebAssembly.Instance(new WebAssembly.Module(wasmTextToBinary(
     `(module
-       (gc_feature_opt_in 1)
+       (gc_feature_opt_in 2)
        (table (export "t") 10 anyref))`)));
     let t = ins.exports.t;
     assertEq(t.length, 10);
     for (let i=0; i < t.length; i++)
         assertEq(t.get(0), null);
 }
 
 // JS: Exported table can be grown, and values are preserved
 
 {
     let ins = new WebAssembly.Instance(new WebAssembly.Module(wasmTextToBinary(
     `(module
-       (gc_feature_opt_in 1)
+       (gc_feature_opt_in 2)
        (table (export "t") 10 anyref))`)));
     let t = ins.exports.t;
     let objs = [{}, {}, {}, {}, {}, {}, {}, {}, {}, {}];
     for (let i in objs)
         t.set(i, objs[i]);
     ins.exports.t.grow(10);
     assertEq(ins.exports.t.length, 20);
     for (let i in objs)
@@ -57,17 +57,17 @@ new WebAssembly.Instance(new WebAssembly
 }
 
 // Wasm: table.copy between tables of anyref (currently source and destination
 // are both table zero)
 
 {
     let ins = new WebAssembly.Instance(new WebAssembly.Module(wasmTextToBinary(
     `(module
-       (gc_feature_opt_in 1)
+       (gc_feature_opt_in 2)
        (table (export "t") 10 anyref)
        (func (export "f")
          (table.copy (i32.const 5) (i32.const 0) (i32.const 3))))`)));
     let t = ins.exports.t;
     let objs = [{}, {}, {}, {}, {}, {}, {}, {}, {}, {}];
     for (let i in objs)
         t.set(i, objs[i]);
     ins.exports.f();
@@ -82,52 +82,52 @@ new WebAssembly.Instance(new WebAssembly
     assertEq(t.get(8), objs[8]);
     assertEq(t.get(9), objs[9]);
 }
 
 // Wasm: element segments targeting table-of-anyref is forbidden
 
 assertErrorMessage(() => new WebAssembly.Module(wasmTextToBinary(
     `(module
-       (gc_feature_opt_in 1)
+       (gc_feature_opt_in 2)
        (func $f1 (result i32) (i32.const 0))
        (table 10 anyref)
        (elem (i32.const 0) $f1))`)),
                    WebAssembly.CompileError,
                    /only tables of 'anyfunc' may have element segments/);
 
 // Wasm: table.init on table-of-anyref is forbidden
 
 assertErrorMessage(() => new WebAssembly.Module(wasmTextToBinary(
     `(module
-       (gc_feature_opt_in 1)
+       (gc_feature_opt_in 2)
        (func $f1 (result i32) (i32.const 0))
        (table 10 anyref)
        (elem passive $f1)
        (func
          (table.init 0 (i32.const 0) (i32.const 0) (i32.const 0))))`)),
                    WebAssembly.CompileError,
                    /only tables of 'anyfunc' may have element segments/);
 
 // Wasm: table types must match at link time
 
 assertErrorMessage(
     () => new WebAssembly.Instance(new WebAssembly.Module(wasmTextToBinary(
     `(module
-       (gc_feature_opt_in 1)
+       (gc_feature_opt_in 2)
        (import "m" "t" (table 10 anyref)))`)),
                                    {m:{t: new WebAssembly.Table({element:"anyfunc", initial:10})}}),
     WebAssembly.LinkError,
     /imported table type mismatch/);
 
 // call_indirect cannot reference table-of-anyref
 
 assertErrorMessage(() => new WebAssembly.Module(wasmTextToBinary(
     `(module
-       (gc_feature_opt_in 1)
+       (gc_feature_opt_in 2)
        (table 10 anyref)
        (type $t (func (param i32) (result i32)))
        (func (result i32)
          (call_indirect $t (i32.const 37))))`)),
                    WebAssembly.CompileError,
                    /indirect calls must go through a table of 'anyfunc'/);
 
 ///////////////////////////////////////////////////////////////////////////
@@ -237,17 +237,17 @@ assertErrorMessage(() => new WebAssembly
     let ins = wasmEvalText(
         `(module
            (gc_feature_opt_in 2)
            (table (export "t") 10 anyref)
            (type $dummy (struct (field i32)))
            (func (export "set_anyref") (param i32) (param anyref)
              (table.set (get_local 0) (get_local 1)))
            (func (export "set_null") (param i32)
-             (table.set (get_local 0) (ref.null anyref)))
+             (table.set (get_local 0) (ref.null)))
            (func (export "set_ref") (param i32) (param anyref)
              (table.set (get_local 0) (struct.narrow anyref (ref $dummy) (get_local 1))))
            (func (export "make_struct") (result anyref)
              (struct.new $dummy (i32.const 37))))`);
     let x = {};
     ins.exports.set_anyref(3, x);
     assertEq(ins.exports.t.get(3), x);
     ins.exports.set_null(3);
@@ -262,17 +262,17 @@ assertErrorMessage(() => new WebAssembly
 
 // table.set with non-i32 index - fails validation
 
 assertErrorMessage(() => new WebAssembly.Module(wasmTextToBinary(
     `(module
        (gc_feature_opt_in 2)
        (table 10 anyref)
        (func (export "f") (param f64)
-         (table.set (get_local 0) (ref.null anyref))))`)),
+         (table.set (get_local 0) (ref.null))))`)),
                    WebAssembly.CompileError,
                    /type mismatch/);
 
 // table.set with non-anyref value - fails validation
 
 assertErrorMessage(() => new WebAssembly.Module(wasmTextToBinary(
     `(module
        (gc_feature_opt_in 2)
@@ -311,17 +311,17 @@ assertErrorMessage(() => new WebAssembly
 // table.grow with delta at upper limit - fails
 // table.grow with negative delta - fails
 
 let ins = wasmEvalText(
     `(module
       (gc_feature_opt_in 2)
       (table (export "t") 10 20 anyref)
       (func (export "grow") (param i32) (result i32)
-       (table.grow (get_local 0) (ref.null anyref))))`);
+       (table.grow (get_local 0) (ref.null))))`);
 assertEq(ins.exports.grow(0), 10);
 assertEq(ins.exports.t.length, 10);
 assertEq(ins.exports.grow(1), 10);
 assertEq(ins.exports.t.length, 11);
 assertEq(ins.exports.t.get(10), null);
 assertEq(ins.exports.grow(9), 11);
 assertEq(ins.exports.t.length, 20);
 assertEq(ins.exports.t.get(19), null);
@@ -340,52 +340,52 @@ assertEq(ins.exports.t.length, 20)
 // Special case for private tables without a maximum
 
 {
     let ins = wasmEvalText(
         `(module
           (gc_feature_opt_in 2)
           (table 10 anyref)
           (func (export "grow") (param i32) (result i32)
-           (table.grow (get_local 0) (ref.null anyref))))`);
+           (table.grow (get_local 0) (ref.null))))`);
     assertEq(ins.exports.grow(0), 10);
     assertEq(ins.exports.grow(1), 10);
     assertEq(ins.exports.grow(9), 11);
     assertEq(ins.exports.grow(0), 20);
 }
 
 // Can't grow table of anyfunc yet
 
 assertErrorMessage(() => wasmEvalText(
     `(module
       (gc_feature_opt_in 2)     ;; Required because of the 'anyref' null value below
       (table $t 2 anyfunc)
       (func $f
-       (drop (table.grow (i32.const 1) (ref.null anyref)))))`),
+       (drop (table.grow (i32.const 1) (ref.null)))))`),
                    WebAssembly.CompileError,
                    /table.grow only on tables of anyref/);
 
 // table.grow with non-i32 argument - fails validation
 
 assertErrorMessage(() => new WebAssembly.Module(wasmTextToBinary(
     `(module
        (gc_feature_opt_in 2)
        (table 10 anyref)
        (func (export "f") (param f64)
-        (table.grow (get_local 0) (ref.null anyref))))`)),
+        (table.grow (get_local 0) (ref.null))))`)),
                    WebAssembly.CompileError,
                    /type mismatch/);
 
 // table.grow when there are no tables - fails validation
 
 assertErrorMessage(() => new WebAssembly.Module(wasmTextToBinary(
     `(module
        (gc_feature_opt_in 2)
        (func (export "f") (param i32)
-        (table.grow (get_local 0) (ref.null anyref))))`)),
+        (table.grow (get_local 0) (ref.null))))`)),
                    WebAssembly.CompileError,
                    /table index out of range for table.grow/);
 
 // table.grow on table of anyref with non-null ref value
 
 {
     let ins = wasmEvalText(
         `(module
@@ -406,17 +406,17 @@ for (let visibility of ['', '(export "t"
     let exp = {m:{t: new WebAssembly.Table({element:"anyref",
                                             initial: 10,
                                             maximum: 20})}};
     let ins = wasmEvalText(
         `(module
           (gc_feature_opt_in 2)
           (table ${visibility} 10 20 anyref)
           (func (export "grow") (param i32) (result i32)
-           (table.grow (get_local 0) (ref.null anyref)))
+           (table.grow (get_local 0) (ref.null)))
           (func (export "size") (result i32)
            (table.size)))`,
         exp);
     assertEq(ins.exports.grow(0), 10);
     assertEq(ins.exports.size(), 10);
     assertEq(ins.exports.grow(1), 10);
     assertEq(ins.exports.size(), 11);
     assertEq(ins.exports.grow(9), 11);
--- a/js/src/jit-test/tests/wasm/gc/tables-multiple.js
+++ b/js/src/jit-test/tests/wasm/gc/tables-multiple.js
@@ -113,17 +113,17 @@ var exp = {m:{t0: new WebAssembly.Table(
               t1: new WebAssembly.Table({element:"anyref", initial:3})}};
 var ins = wasmEvalText(
     `(module
       (gc_feature_opt_in 2)
 
       (table $t0 (import "m" "t0") 2 anyref)
       (table $t1 (import "m" "t1") 3 anyref)
       (func (export "f") (result i32)
-       (table.grow $t1 (i32.const 5) (ref.null anyref)))
+       (table.grow $t1 (i32.const 5) (ref.null)))
       (func (export "size0") (result i32)
        (table.size $t0))
       (func (export "size1") (result i32)
        (table.size $t1)))`,
     exp);
 
 assertEq(ins.exports.f(), 3);
 assertEq(exp.m.t1.length, 8);
@@ -229,19 +229,19 @@ var exp = {m: {t0: tbl, t1:tbl}};
 
 var ins = wasmEvalText(
     `(module
       (gc_feature_opt_in 2)
       (import $t0 "m" "t0" (table 1 anyref))
       (import $t1 "m" "t1" (table 1 anyref))
       (table $t2 (export "t2") 1 anyfunc)
       (func (export "f") (result i32)
-       (table.grow $t0 (i32.const 1) (ref.null anyref)))
+       (table.grow $t0 (i32.const 1) (ref.null)))
       (func (export "g") (result i32)
-       (table.grow $t1 (i32.const 1) (ref.null anyref)))
+       (table.grow $t1 (i32.const 1) (ref.null)))
       (func (export "size") (result i32)
        (table.size $t2)))`,
     exp);
 
 assertEq(ins.exports.f(), 1);
 assertEq(ins.exports.g(), 2);
 assertEq(ins.exports.f(), 3);
 assertEq(ins.exports.g(), 4);
@@ -382,17 +382,17 @@ assertErrorMessage(() => wasmEvalText(
                    /table index out of range for table.size/);
 
 assertErrorMessage(() => wasmEvalText(
     `(module
       (gc_feature_opt_in 2)
       (table $t0 2 anyref)
       (table $t1 2 anyref)
       (func $f (result i32)
-       (table.grow 2 (i32.const 1) (ref.null anyref))))`),
+       (table.grow 2 (i32.const 1) (ref.null))))`),
                    WebAssembly.CompileError,
                    /table index out of range for table.grow/);
 
 assertErrorMessage(() => wasmEvalText(
     `(module
       (table $t0 2 anyfunc)
       (elem passive) ;; 0
       (func $f (result i32)
--- a/js/src/jit-test/tests/wasm/gc/tables-stress.js
+++ b/js/src/jit-test/tests/wasm/gc/tables-stress.js
@@ -8,17 +8,17 @@ for ( let prefix of ['', '(table $prefix
        (table $tbl 0 anyref)
        (import $item "m" "item" (func (result anyref)))
        (func (export "run") (param $numiters i32)
          (local $i i32)
          (local $j i32)
          (local $last i32)
          (local $iters i32)
          (local $tmp anyref)
-         (set_local $last (table.grow $tbl (i32.const 1) (ref.null anyref)))
+         (set_local $last (table.grow $tbl (i32.const 1) (ref.null)))
          (table.set $tbl (get_local $last) (call $item))
          (loop $iter_continue
            (set_local $i (i32.const 0))
            (set_local $j (get_local $last))
            (block $l_break
              (loop $l_continue
                (br_if $l_break (i32.ge_s (get_local $j) (get_local $i)))
                (set_local $tmp (table.get $tbl (get_local $i)))
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/wasm/regress/baseline-stack-height.js
@@ -0,0 +1,1 @@
+new WebAssembly.Module(os.file.readFile(scriptdir + "/baseline-stack-height.wasm", 'binary'));
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..cc25a1dac8033e72ef5ea8f7a207f6f1636beaed
GIT binary patch
literal 67032
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
EA1oYNI{*Lx
--- a/js/src/jit/CodeGenerator.cpp
+++ b/js/src/jit/CodeGenerator.cpp
@@ -13932,16 +13932,18 @@ CodeGenerator::emitIonToWasmCallBase(LIo
             argMir = ToMIRType(sig.args()[i]);
             break;
           case wasm::ValType::I64:
           case wasm::ValType::Ref:
           case wasm::ValType::AnyRef:
             // Don't forget to trace GC type arguments in TraceJitExitFrames
             // when they're enabled.
             MOZ_CRASH("unexpected argument type when calling from ion to wasm");
+          case wasm::ValType::NullRef:
+            MOZ_CRASH("NullRef not expressible");
         }
 
         ABIArg arg = abi.next(argMir);
         switch (arg.kind()) {
           case ABIArg::GPR:
           case ABIArg::FPU: {
             MOZ_ASSERT(ToAnyRegister(lir->getOperand(i)) == arg.reg());
             stackArgs.infallibleEmplaceBack(wasm::JitCallStackArg());
@@ -13988,16 +13990,18 @@ CodeGenerator::emitIonToWasmCallBase(LIo
         MOZ_ASSERT(ToFloatRegister(lir->output()) == ReturnDoubleReg);
         break;
       case wasm::ExprType::Ref:
       case wasm::ExprType::AnyRef:
       case wasm::ExprType::I64:
         // Don't forget to trace GC type return value in TraceJitExitFrames
         // when they're enabled.
         MOZ_CRASH("unexpected return type when calling from ion to wasm");
+      case wasm::ExprType::NullRef:
+        MOZ_CRASH("NullRef not expressible");
       case wasm::ExprType::Limit:
         MOZ_CRASH("Limit");
     }
 
     bool profilingEnabled = isProfilerInstrumentationEnabled();
     WasmInstanceObject* instObj = lir->mir()->instanceObject();
 
     bool wasmGcEnabled = false;
--- a/js/src/jit/MCallOptimize.cpp
+++ b/js/src/jit/MCallOptimize.cpp
@@ -4108,16 +4108,18 @@ IonBuilder::inlineWasmCall(CallInfo& cal
             break;
           case wasm::ValType::F64:
             conversion = MToDouble::New(alloc(), arg);
             break;
           case wasm::ValType::I64:
           case wasm::ValType::AnyRef:
           case wasm::ValType::Ref:
             MOZ_CRASH("impossible per above check");
+          case wasm::ValType::NullRef:
+            MOZ_CRASH("NullRef not expressible");
         }
 
         current->add(conversion);
         call->initArg(i, conversion);
     }
 
     current->push(call);
     current->add(call);
--- a/js/src/tests/jstests.py
+++ b/js/src/tests/jstests.py
@@ -318,16 +318,17 @@ def load_wpt_tests(xul_tester, requested
         "testing/mozbase/mozprofile",
         "testing/mozbase/mozrunner",
         "testing/web-platform/",
         "testing/web-platform/tests/tools",
         "testing/web-platform/tests/tools/third_party/html5lib",
         "testing/web-platform/tests/tools/third_party/webencodings",
         "testing/web-platform/tests/tools/wptrunner",
         "testing/web-platform/tests/tools/wptserve",
+        "third_party/python/requests",
     ]
     abs_sys_paths = [os.path.join(repo_root, path) for path in sys_paths]
 
     failed = False
     for path in abs_sys_paths:
         if not os.path.isdir(path):
             failed = True
             print("Could not add '%s' to the path")
--- a/js/src/wasm/AsmJS.cpp
+++ b/js/src/wasm/AsmJS.cpp
@@ -6388,16 +6388,17 @@ ValidateGlobalVariable(JSContext* cx, co
             double d;
             if (!ToNumber(cx, v, &d)) {
                 return false;
             }
             val->emplace(d);
             return true;
           }
           case ValType::Ref:
+          case ValType::NullRef:
           case ValType::AnyRef: {
             MOZ_CRASH("not available in asm.js");
           }
         }
       }
     }
 
     MOZ_CRASH("unreachable");
--- a/js/src/wasm/WasmAST.h
+++ b/js/src/wasm/WasmAST.h
@@ -1782,25 +1782,21 @@ class AstExtraConversionOperator final :
     {}
 
     MiscOp op() const { return op_; }
     AstExpr* operand() const { return operand_; }
 };
 
 class AstRefNull final : public AstExpr
 {
-    AstValType refType_;
   public:
     static const AstExprKind Kind = AstExprKind::RefNull;
-    explicit AstRefNull(AstValType refType)
-      : AstExpr(Kind, ExprType::Limit), refType_(refType)
+    AstRefNull()
+      : AstExpr(Kind, ExprType::Limit)
     {}
-    AstValType& baseType() {
-        return refType_;
-    }
 };
 
 // This is an artificial AST node which can fill operand slots in an AST
 // constructed from parsing or decoding stack-machine code that doesn't have
 // an inherent AST structure.
 class AstPop final : public AstExpr
 {
   public:
--- a/js/src/wasm/WasmBaselineCompile.cpp
+++ b/js/src/wasm/WasmBaselineCompile.cpp
@@ -1082,16 +1082,17 @@ BaseLocalIter::settle()
           case ValType::I64:
           case ValType::F32:
           case ValType::F64:
           case ValType::Ref:
           case ValType::AnyRef:
             mirType_ = ToMIRType(locals_[index_]);
             frameOffset_ = pushLocal(MIRTypeToSize(mirType_));
             break;
+          case ValType::NullRef:
           default:
             MOZ_CRASH("Compiler bug: Unexpected local type");
         }
         return;
     }
 
     done_ = true;
 }
@@ -1159,17 +1160,16 @@ class BaseStackFrame
     // risk; if it is too small we spend too much time adjusting the stack
     // pointer.
     //
     // Good values for ChunkSize are the subject of future empirical analysis;
     // eight words is just an educated guess.
 
     static constexpr uint32_t ChunkSize = 8 * sizeof(void*);
     static constexpr uint32_t InitialChunk = ChunkSize;
-    static constexpr uint32_t ChunkCutoff = ChunkSize + InitialChunk;
 #endif
 
     MacroAssembler& masm;
 
     // Size of local area in bytes (stable after beginFunction).
     uint32_t localSize_;
 
     // Low byte offset of local area for true locals (not parameters).
@@ -1478,16 +1478,22 @@ class BaseStackFrame
         return maxFramePushed_ <= 512 * 1024;
     }
 
     // The current height of the stack area, not necessarily zero-based.
     StackHeight stackHeight() const {
         return StackHeight(currentFramePushed());
     }
 
+    // The current height of the dynamic part of the stack area (ie, the backing
+    // store for the evaluation stack), zero-based.
+    uint32_t dynamicHeight() const {
+        return currentFramePushed() - localSize_;
+    }
+
     // Set the frame height.
     void setStackHeight(StackHeight amount) {
 #ifdef RABALDR_CHUNKY_STACK
         currentFramePushed_ = amount.height;
         masm.setFramePushed(framePushedForHeight(amount));
         CHUNKY_INVARIANT();
 #else
         masm.setFramePushed(amount.height);
@@ -1574,16 +1580,18 @@ class BaseStackFrame
             masm.freeStack(bytes);
 #endif
         }
     }
 
     // Before branching to an outer control label, pop the execution stack to
     // the level expected by that region, but do not update masm.framePushed()
     // as that will happen as compilation leaves the block.
+    //
+    // Note these operate directly on the stack pointer register.
 
     void popStackBeforeBranch(StackHeight destStackHeight) {
         uint32_t framePushedHere = masm.framePushed();
         uint32_t framePushedThere = framePushedForHeight(destStackHeight);
         if (framePushedHere > framePushedThere) {
             masm.addToStackPtr(Imm32(framePushedHere - framePushedThere));
         }
     }
@@ -1592,32 +1600,36 @@ class BaseStackFrame
         uint32_t framePushedHere = masm.framePushed();
         uint32_t framePushedThere = framePushedForHeight(destStackHeight);
         return framePushedHere > framePushedThere;
     }
 
     // Before exiting a nested control region, pop the execution stack
     // to the level expected by the nesting region, and free the
     // stack.
+    //
+    // Note this operates on the stack height, which is not the same as the
+    // stack pointer on chunky-stack systems; the stack pointer may or may not
+    // change on such systems.
 
     void popStackOnBlockExit(StackHeight destStackHeight, bool deadCode) {
-        uint32_t framePushedHere = masm.framePushed();
-        uint32_t framePushedThere = framePushedForHeight(destStackHeight);
-        if (framePushedHere > framePushedThere) {
+        uint32_t stackHeightHere = currentFramePushed();
+        uint32_t stackHeightThere = destStackHeight.height;
+        if (stackHeightHere > stackHeightThere) {
 #ifdef RABALDR_CHUNKY_STACK
             if (deadCode) {
                 setStackHeight(destStackHeight);
             } else {
-                popChunkyBytes(framePushedHere - framePushedThere);
+                popChunkyBytes(stackHeightHere - stackHeightThere);
             }
 #else
             if (deadCode) {
-                masm.setFramePushed(framePushedThere);
+                masm.setFramePushed(stackHeightThere);
             } else {
-                masm.freeStack(framePushedHere - framePushedThere);
+                masm.freeStack(stackHeightHere - stackHeightThere);
             }
 #endif
         }
     }
 
     void loadStackI32(int32_t offset, RegI32 dest) {
         masm.load32(Address(sp_, stackOffset(offset)), dest);
     }
@@ -2189,32 +2201,34 @@ class BaseCompiler final : public BaseCo
         switch (type.code()) {
           case ExprType::I32:
             needI32(joinRegI32_);
             break;
           case ExprType::I64:
             needI64(joinRegI64_);
             break;
           case ExprType::AnyRef:
+          case ExprType::NullRef:
           case ExprType::Ref:
             needRef(joinRegPtr_);
             break;
           default:;
         }
     }
 
     void maybeUnreserveJoinRegI(ExprType type) {
         switch (type.code()) {
           case ExprType::I32:
             freeI32(joinRegI32_);
             break;
           case ExprType::I64:
             freeI64(joinRegI64_);
             break;
           case ExprType::AnyRef:
+          case ExprType::NullRef:
           case ExprType::Ref:
             freeRef(joinRegPtr_);
             break;
           default:;
         }
     }
 
     void maybeReserveJoinReg(ExprType type) {
@@ -2227,16 +2241,17 @@ class BaseCompiler final : public BaseCo
             break;
           case ExprType::F32:
             needF32(joinRegF32_);
             break;
           case ExprType::F64:
             needF64(joinRegF64_);
             break;
           case ExprType::Ref:
+          case ExprType::NullRef:
           case ExprType::AnyRef:
             needRef(joinRegPtr_);
             break;
           default:
             break;
         }
     }
 
@@ -2250,16 +2265,17 @@ class BaseCompiler final : public BaseCo
             break;
           case ExprType::F32:
             freeF32(joinRegF32_);
             break;
           case ExprType::F64:
             freeF64(joinRegF64_);
             break;
           case ExprType::Ref:
+          case ExprType::NullRef:
           case ExprType::AnyRef:
             freeRef(joinRegPtr_);
             break;
           default:
             break;
         }
     }
 
@@ -3217,16 +3233,17 @@ class BaseCompiler final : public BaseCo
           }
           case ExprType::F32: {
             DebugOnly<Stk::Kind> k(stk_.back().kind());
             MOZ_ASSERT(k == Stk::RegisterF32 || k == Stk::ConstF32 || k == Stk::MemF32 ||
                        k == Stk::LocalF32);
             return Some(AnyReg(popF32(joinRegF32_)));
           }
           case ExprType::Ref:
+          case ExprType::NullRef:
           case ExprType::AnyRef: {
             DebugOnly<Stk::Kind> k(stk_.back().kind());
             MOZ_ASSERT(k == Stk::RegisterRef || k == Stk::ConstRef || k == Stk::MemRef ||
                        k == Stk::LocalRef);
             return Some(AnyReg(popRef(joinRegPtr_)));
           }
           default: {
             MOZ_CRASH("Compiler bug: unexpected expression type");
@@ -3254,16 +3271,17 @@ class BaseCompiler final : public BaseCo
             MOZ_ASSERT(isAvailableF32(joinRegF32_));
             needF32(joinRegF32_);
             return Some(AnyReg(joinRegF32_));
           case ExprType::F64:
             MOZ_ASSERT(isAvailableF64(joinRegF64_));
             needF64(joinRegF64_);
             return Some(AnyReg(joinRegF64_));
           case ExprType::Ref:
+          case ExprType::NullRef:
           case ExprType::AnyRef:
             MOZ_ASSERT(isAvailableRef(joinRegPtr_));
             needRef(joinRegPtr_);
             return Some(AnyReg(joinRegPtr_));
           case ExprType::Void:
             return Nothing();
           default:
             MOZ_CRASH("Compiler bug: unexpected type");
@@ -3405,16 +3423,32 @@ class BaseCompiler final : public BaseCo
               case Stk::RegisterRef:
                 check.addKnownRef(item.refReg());
                 break;
               default:
                 break;
             }
         }
     }
+
+    void assertStackInvariants() const {
+        size_t size = 0;
+        for (const Stk& v : stk_) {
+            switch (v.kind()) {
+              case Stk::MemRef: size += BaseStackFrame::StackSizeOfPtr;    break;
+              case Stk::MemI32: size += BaseStackFrame::StackSizeOfPtr;    break;
+              case Stk::MemI64: size += BaseStackFrame::StackSizeOfInt64;  break;
+              case Stk::MemF64: size += BaseStackFrame::StackSizeOfDouble; break;
+              case Stk::MemF32: size += BaseStackFrame::StackSizeOfFloat;  break;
+              default:          MOZ_ASSERT(!v.isMem());                    break;
+            }
+        }
+        MOZ_ASSERT(size == fr.dynamicHeight());
+    }
+
 #endif
 
     ////////////////////////////////////////////////////////////
     //
     // Control stack
 
     void initControl(Control& item)
     {
@@ -3534,16 +3568,17 @@ class BaseCompiler final : public BaseCo
             break;
           case ExprType::F32:
             masm.storeFloat32(RegF32(ReturnFloat32Reg), resultsAddress);
             break;
           case ExprType::Ref:
           case ExprType::AnyRef:
             masm.storePtr(RegPtr(ReturnReg), resultsAddress);
             break;
+          case ExprType::NullRef:
           default:
             MOZ_CRASH("Function return type");
         }
     }
 
     void restoreResult() {
         MOZ_ASSERT(env_.debugEnabled());
         size_t debugFrameOffset = masm.framePushed() - DebugFrame::offsetOfFrame();
@@ -3562,16 +3597,17 @@ class BaseCompiler final : public BaseCo
             break;
           case ExprType::F32:
             masm.loadFloat32(resultsAddress, RegF32(ReturnFloat32Reg));
             break;
           case ExprType::Ref:
           case ExprType::AnyRef:
             masm.loadPtr(resultsAddress, RegPtr(ReturnReg));
             break;
+          case ExprType::NullRef:
           default:
             MOZ_CRASH("Function return type");
         }
     }
 
     bool endFunction() {
         // Always branch to returnLabel_.
         masm.breakpoint();
@@ -3852,16 +3888,18 @@ class BaseCompiler final : public BaseCo
                 ScratchPtr scratch(*this);
                 loadRef(arg, scratch);
                 masm.storePtr(scratch, Address(masm.getStackPointer(), argLoc.offsetFromArgBase()));
             } else {
                 loadRef(arg, RegPtr(argLoc.gpr()));
             }
             break;
           }
+          case ValType::NullRef:
+            MOZ_CRASH("NullRef not expressible");
           default:
             MOZ_CRASH("Function argument type");
         }
     }
 
     void callDefinition(uint32_t funcIndex, const FunctionCall& call)
     {
         CallSiteDesc desc(call.lineOrBytecode, CallSiteDesc::Func);
@@ -7414,17 +7452,17 @@ BaseCompiler::sniffConditionalControlCmp
     // reserved join register and the lhs and rhs operands require six, but we
     // only have five.
     if (operandType == ValType::I64) {
         return false;
     }
 #endif
 
     // No optimization for pointer compares yet.
-    if (operandType.isRefOrAnyRef()) {
+    if (operandType.isReference()) {
         return false;
     }
 
     OpBytes op;
     iter_.peekOp(&op);
     switch (op.b0) {
       case uint16_t(Op::BrIf):
       case uint16_t(Op::If):
@@ -8034,16 +8072,17 @@ BaseCompiler::doReturn(ExprType type, bo
       }
       case ExprType::F32: {
         RegF32 rv = popF32(RegF32(ReturnFloat32Reg));
         returnCleanup(popStack);
         freeF32(rv);
         break;
       }
       case ExprType::Ref:
+      case ExprType::NullRef:
       case ExprType::AnyRef: {
         RegPtr rv = popRef(RegPtr(ReturnReg));
         returnCleanup(popStack);
         freeRef(rv);
         break;
       }
       default: {
         MOZ_CRASH("Function return type");
@@ -8113,16 +8152,18 @@ BaseCompiler::pushReturnedIfNonVoid(cons
         break;
       }
       case ExprType::Ref:
       case ExprType::AnyRef: {
         RegPtr rv = captureReturnedRef();
         pushRef(rv);
         break;
       }
+      case ExprType::NullRef:
+        MOZ_CRASH("NullRef not expressible");
       default:
         MOZ_CRASH("Function return type");
     }
 }
 
 // For now, always sync() at the beginning of the call to easily save live
 // values.
 //
@@ -8459,16 +8500,17 @@ BaseCompiler::emitGetLocal()
         break;
       case ValType::F32:
         pushLocalF32(slot);
         break;
       case ValType::Ref:
       case ValType::AnyRef:
         pushLocalRef(slot);
         break;
+      case ValType::NullRef:
       default:
         MOZ_CRASH("Local variable type");
     }
 
     return true;
 }
 
 template<bool isSetLocal>
@@ -8532,16 +8574,17 @@ BaseCompiler::emitSetOrTeeLocal(uint32_t
         fr.storeLocalPtr(rv, localFromSlot(slot, MIRType::Pointer));
         if (isSetLocal) {
             freeRef(rv);
         } else {
             pushRef(rv);
         }
         break;
       }
+      case ValType::NullRef:
       default:
         MOZ_CRASH("Local variable type");
     }
 
     return true;
 }
 
 bool
@@ -8591,16 +8634,17 @@ BaseCompiler::emitGetGlobal()
             break;
           case ValType::F32:
             pushF32(value.f32());
             break;
           case ValType::F64:
             pushF64(value.f64());
             break;
           case ValType::Ref:
+          case ValType::NullRef:
           case ValType::AnyRef:
             pushRef(intptr_t(value.ptr()));
             break;
           default:
             MOZ_CRASH("Global constant type");
         }
         return true;
     }
@@ -8637,16 +8681,18 @@ BaseCompiler::emitGetGlobal()
       case ValType::Ref:
       case ValType::AnyRef: {
         RegPtr rv = needRef();
         ScratchI32 tmp(*this);
         masm.loadPtr(addressOfGlobalVar(global, tmp), rv);
         pushRef(rv);
         break;
       }
+      case ValType::NullRef:
+        MOZ_CRASH("NullRef not expressible");
       default:
         MOZ_CRASH("Global variable type");
         break;
     }
     return true;
 }
 
 bool
@@ -8701,16 +8747,18 @@ BaseCompiler::emitSetGlobal()
             ScratchI32 tmp(*this);
             masm.computeEffectiveAddress(addressOfGlobalVar(global, tmp), valueAddr);
         }
         RegPtr rv = popRef();
         emitBarrieredStore(Nothing(), valueAddr, rv); // Consumes valueAddr
         freeRef(rv);
         break;
       }
+      case ValType::NullRef:
+        MOZ_CRASH("NullRef not expressible");
       default:
         MOZ_CRASH("Global variable type");
         break;
     }
     return true;
 }
 
 // Bounds check elimination.
@@ -9099,16 +9147,17 @@ BaseCompiler::emitSelect()
         emitBranchPerform(&b);
         moveF64(rs, r);
         masm.bind(&done);
         freeF64(rs);
         pushF64(r);
         break;
       }
       case ValType::Ref:
+      case ValType::NullRef:
       case ValType::AnyRef: {
         RegPtr r, rs;
         pop2xRef(&r, &rs);
         emitBranchPerform(&b);
         moveRef(rs, r);
         masm.bind(&done);
         freeRef(rs);
         pushRef(r);
@@ -9301,18 +9350,17 @@ BaseCompiler::emitCurrentMemory()
     // infallible
     emitInstanceCall(lineOrBytecode, SigP_, ExprType::I32, SymbolicAddress::CurrentMemory);
     return true;
 }
 
 bool
 BaseCompiler::emitRefNull()
 {
-    ValType type;
-    if (!iter_.readRefNull(&type)) {
+    if (!iter_.readRefNull()) {
         return false;
     }
 
     if (deadCode_) {
         return true;
     }
 
     pushRef(NULLREF_VALUE);
@@ -10010,16 +10058,18 @@ BaseCompiler::emitStructNew()
             popRef(rp);                 // Restore rp
             if (!structType.isInline_) {
                 masm.loadPtr(Address(rp, OutlineTypedObject::offsetOfData()), rdata);
             }
 
             masm.bind(&skipBarrier);
             break;
           }
+          case ValType::NullRef:
+            MOZ_CRASH("NullRef not expressible");
           default: {
             MOZ_CRASH("Unexpected field type");
           }
         }
     }
 
     if (!structType.isInline_) {
         freeRef(rdata);
@@ -10085,18 +10135,21 @@ BaseCompiler::emitStructGet()
       }
       case ValType::Ref:
       case ValType::AnyRef: {
           RegPtr r = needRef();
           masm.loadPtr(Address(rp, offs), r);
           pushRef(r);
           break;
       }
+      case ValType::NullRef: {
+        MOZ_CRASH("NullRef not expressible");
+      }
       default: {
-          MOZ_CRASH("Unexpected field type");
+        MOZ_CRASH("Unexpected field type");
       }
     }
 
     freeRef(rp);
 
     return true;
 }
 
@@ -10120,17 +10173,17 @@ BaseCompiler::emitStructSet()
     RegI64 rl;
     RegF32 rf;
     RegF64 rd;
     RegPtr rr;
 
     // Reserve this register early if we will need it so that it is not taken by
     // rr or rp.
     RegPtr valueAddr;
-    if (structType.fields_[fieldIndex].type.isRefOrAnyRef()) {
+    if (structType.fields_[fieldIndex].type.isReference()) {
         valueAddr = RegPtr(PreBarrierReg);
         needRef(valueAddr);
     }
 
     switch (structType.fields_[fieldIndex].type.code()) {
       case ValType::I32:
         ri = popI32();
         break;
@@ -10142,16 +10195,18 @@ BaseCompiler::emitStructSet()
         break;
       case ValType::F64:
         rd = popF64();
         break;
       case ValType::Ref:
       case ValType::AnyRef:
         rr = popRef();
         break;
+      case ValType::NullRef:
+        MOZ_CRASH("NullRef not expressible");
       default:
         MOZ_CRASH("Unexpected field type");
     }
 
     RegPtr rp = popRef();
 
     Label ok;
     masm.branchTestPtr(Assembler::NonZero, rp, rp, &ok);
@@ -10180,21 +10235,25 @@ BaseCompiler::emitStructSet()
         break;
       }
       case ValType::F64: {
         masm.storeDouble(rd, Address(rp, offs));
         freeF64(rd);
         break;
       }
       case ValType::Ref:
-      case ValType::AnyRef:
+      case ValType::AnyRef: {
         masm.computeEffectiveAddress(Address(rp, offs), valueAddr);
         emitBarrieredStore(Some(rp), valueAddr, rr);// Consumes valueAddr
         freeRef(rr);
         break;
+      }
+      case ValType::NullRef: {
+        MOZ_CRASH("NullRef not expressible");
+      }
       default: {
         MOZ_CRASH("Unexpected field type");
       }
     }
 
     freeRef(rp);
 
     return true;
@@ -10252,16 +10311,17 @@ BaseCompiler::emitBody()
     uint32_t overhead = 0;
 
     for (;;) {
 
         Nothing unused_a, unused_b;
 
 #ifdef DEBUG
         performRegisterLeakCheck();
+        assertStackInvariants();
 #endif
 
 #define emitBinary(doEmit, type) \
         iter_.readBinary(type, &unused_a, &unused_b) && (deadCode_ || (doEmit(), true))
 
 #define emitUnary(doEmit, type) \
         iter_.readUnary(type, &unused_a) && (deadCode_ || (doEmit(), true))
 
--- a/js/src/wasm/WasmConstants.h
+++ b/js/src/wasm/WasmConstants.h
@@ -62,16 +62,19 @@ enum class TypeCode
     Func                                 = 0x60,  // SLEB128(-0x20)
 
     // Type constructor for structure types - unofficial
     Struct                               = 0x50,  // SLEB128(-0x30)
 
     // Special code representing the block signature ()->()
     BlockVoid                            = 0x40,  // SLEB128(-0x40)
 
+    // Type designator for null - unofficial, will not appear in the binary format
+    NullRef                              = 0x39,
+
     Limit                                = 0x80
 };
 
 enum class FuncTypeIdDescKind
 {
     None,
     Immediate,
     Global
--- a/js/src/wasm/WasmInstance.cpp
+++ b/js/src/wasm/WasmInstance.cpp
@@ -135,16 +135,18 @@ Instance::callImport(JSContext* cx, uint
             break;
           case ValType::Ref:
           case ValType::AnyRef: {
             args[i].set(ObjectOrNullValue(*(JSObject**)&argv[i]));
             break;
           }
           case ValType::I64:
             MOZ_CRASH("unhandled type in callImport");
+          case ValType::NullRef:
+            MOZ_CRASH("NullRef not expressible");
         }
     }
 
     FuncImportTls& import = funcImportTls(fi);
     RootedFunction importFun(cx, import.fun);
     MOZ_ASSERT(cx->realm() == importFun->realm());
 
     RootedValue fval(cx, ObjectValue(*importFun));
@@ -199,22 +201,23 @@ Instance::callImport(JSContext* cx, uint
     }
 
     const ValTypeVector& importArgs = fi.funcType().args();
 
     size_t numKnownArgs = Min(importArgs.length(), importFun->nargs());
     for (uint32_t i = 0; i < numKnownArgs; i++) {
         TypeSet::Type type = TypeSet::UnknownType();
         switch (importArgs[i].code()) {
-          case ValType::I32:    type = TypeSet::Int32Type(); break;
-          case ValType::F32:    type = TypeSet::DoubleType(); break;
-          case ValType::F64:    type = TypeSet::DoubleType(); break;
-          case ValType::Ref:    MOZ_CRASH("case guarded above");
-          case ValType::AnyRef: MOZ_CRASH("case guarded above");
-          case ValType::I64:    MOZ_CRASH("NYI");
+          case ValType::I32:     type = TypeSet::Int32Type(); break;
+          case ValType::F32:     type = TypeSet::DoubleType(); break;
+          case ValType::F64:     type = TypeSet::DoubleType(); break;
+          case ValType::Ref:     MOZ_CRASH("case guarded above");
+          case ValType::AnyRef:  MOZ_CRASH("case guarded above");
+          case ValType::I64:     MOZ_CRASH("NYI");
+          case ValType::NullRef: MOZ_CRASH("NullRef not expressible");
         }
         if (!TypeScript::ArgTypes(script, i)->hasType(type)) {
             return true;
         }
     }
 
     // These arguments will be filled with undefined at runtime by the
     // arguments rectifier: check that the imported function can handle
@@ -1088,17 +1091,17 @@ Instance::tracePrivate(JSTracer* trc)
     }
 
     for (const SharedTable& table : tables_) {
         table->trace(trc);
     }
 
     for (const GlobalDesc& global : code().metadata().globals) {
         // Indirect anyref global get traced by the owning WebAssembly.Global.
-        if (!global.type().isRefOrAnyRef() || global.isConstant() || global.isIndirect()) {
+        if (!global.type().isReference() || global.isConstant() || global.isIndirect()) {
             continue;
         }
         GCPtrObject* obj = (GCPtrObject*)(globalData() + global.offset());
         TraceNullableEdge(trc, obj, "wasm ref/anyref global");
     }
 
     TraceNullableEdge(trc, &memory_, "wasm buffer");
     structTypeDescrs_.trace(trc);
@@ -1199,16 +1202,19 @@ Instance::callExport(JSContext* cx, uint
             break;
           case ValType::Ref:
           case ValType::AnyRef: {
             if (!ToRef(cx, v, &exportArgs[i])) {
                 return false;
             }
             break;
           }
+          case ValType::NullRef: {
+            MOZ_CRASH("NullRef not expressible");
+          }
         }
     }
 
     {
         JitActivation activation(cx);
 
         void* callee;
         if (func.hasEagerStubs()) {
@@ -1256,16 +1262,18 @@ Instance::callExport(JSContext* cx, uint
       case ExprType::F64:
         args.rval().set(NumberValue(*(double*)retAddr));
         break;
       case ExprType::Ref:
       case ExprType::AnyRef:
         retObj = *(JSObject**)retAddr;
         expectsObject = true;
         break;
+      case ExprType::NullRef:
+        MOZ_CRASH("NullRef not expressible");
       case ExprType::Limit:
         MOZ_CRASH("Limit");
     }
 
     if (expectsObject) {
         args.rval().set(ObjectOrNullValue(retObj));
     } else if (retObj) {
         args.rval().set(ObjectValue(*retObj));
--- a/js/src/wasm/WasmIonCompile.cpp
+++ b/js/src/wasm/WasmIonCompile.cpp
@@ -223,16 +223,18 @@ class FunctionCompiler
                 break;
               case ValType::F64:
                 ins = MConstant::New(alloc(), DoubleValue(0.0), MIRType::Double);
                 break;
               case ValType::Ref:
               case ValType::AnyRef:
                 MOZ_CRASH("ion support for ref/anyref value NYI");
                 break;
+              case ValType::NullRef:
+                MOZ_CRASH("NullRef not expressible");
             }
 
             curBlock_->add(ins);
             curBlock_->initSlot(info().localSlot(i), ins);
             if (!mirGen_.ensureBallast()) {
                 return false;
             }
         }
--- a/js/src/wasm/WasmJS.cpp
+++ b/js/src/wasm/WasmJS.cpp
@@ -155,28 +155,29 @@ ToWebAssemblyValue(JSContext* cx, ValTyp
         if (!ToNumber(cx, v, &d)) {
             return false;
         }
         val.set(Val(d));
         return true;
       }
       case ValType::AnyRef: {
         if (v.isNull()) {
-            val.set(Val(nullptr));
+            val.set(Val(targetType, nullptr));
         } else {
             JSObject* obj = ToObject(cx, v);
             if (!obj) {
                 return false;
             }
             MOZ_ASSERT(obj->compartment() == cx->compartment());
-            val.set(Val(obj));
+            val.set(Val(targetType, obj));
         }
         return true;
       }
       case ValType::Ref:
+      case ValType::NullRef:
       case ValType::I64: {
         break;
       }
     }
     MOZ_CRASH("unexpected import value type, caller must guard");
 }
 
 static Value
@@ -190,16 +191,17 @@ ToJSValue(const Val& val)
       case ValType::F64:
         return DoubleValue(JS::CanonicalizeNaN(val.f64()));
       case ValType::AnyRef:
         if (!val.ptr()) {
             return NullValue();
         }
         return ObjectValue(*(JSObject*)val.ptr());
       case ValType::Ref:
+      case ValType::NullRef:
       case ValType::I64:
         break;
     }
     MOZ_CRASH("unexpected type when translating to a JS value");
 }
 
 // ============================================================================
 // Imports
@@ -331,17 +333,17 @@ GetImports(JSContext* cx,
                 globalObjs[index] = obj;
                 obj->val(&val);
             } else {
                 if (IsNumberType(global.type())) {
                     if (!v.isNumber()) {
                         return ThrowBadImportType(cx, import.field.get(), "Number");
                     }
                 } else {
-                    MOZ_ASSERT(global.type().isRefOrAnyRef());
+                    MOZ_ASSERT(global.type().isReference());
                     if (!v.isNull() && !v.isObject()) {
                         return ThrowBadImportType(cx, import.field.get(), "Object-or-null");
                     }
                 }
 
                 if (global.type() == ValType::I64) {
                     JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, JSMSG_WASM_BAD_I64_LINK);
                     return false;
@@ -2429,16 +2431,18 @@ WasmGlobalObject::trace(JSTracer* trc, J
         break;
       case ValType::I32:
       case ValType::F32:
       case ValType::I64:
       case ValType::F64:
         break;
       case ValType::Ref:
         MOZ_CRASH("Ref NYI");
+      case ValType::NullRef:
+        MOZ_CRASH("NullRef not expressible");
     }
 }
 
 /* static */ void
 WasmGlobalObject::finalize(FreeOp*, JSObject* obj)
 {
     WasmGlobalObject* global = reinterpret_cast<WasmGlobalObject*>(obj);
     if (!global->isNewborn()) {
@@ -2478,16 +2482,19 @@ WasmGlobalObject::create(JSContext* cx, 
         cell->i64 = val.i64();
         break;
       case ValType::F32:
         cell->f32 = val.f32();
         break;
       case ValType::F64:
         cell->f64 = val.f64();
         break;
+      case ValType::NullRef:
+        MOZ_ASSERT(!cell->ptr, "value should be null already");
+        break;
       case ValType::AnyRef:
         MOZ_ASSERT(!cell->ptr, "no prebarriers needed");
         cell->ptr = val.ptr();
         if (cell->ptr) {
             JSObject::writeBarrierPost(&cell->ptr, nullptr, cell->ptr);
         }
         break;
       case ValType::Ref:
@@ -2571,18 +2578,19 @@ WasmGlobalObject::construct(JSContext* c
     RootedVal globalVal(cx);
 
     // Initialize with default value.
     switch (globalType.code()) {
       case ValType::I32:    globalVal = Val(uint32_t(0)); break;
       case ValType::I64:    globalVal = Val(uint64_t(0)); break;
       case ValType::F32:    globalVal = Val(float(0.0));  break;
       case ValType::F64:    globalVal = Val(double(0.0)); break;
-      case ValType::AnyRef: globalVal = Val(nullptr);     break;
+      case ValType::AnyRef: globalVal = Val(ValType::AnyRef, nullptr); break;
       case ValType::Ref:    MOZ_CRASH("Ref NYI");
+      case ValType::NullRef:MOZ_CRASH("NullRef not expressible");
     }
 
     // Override with non-undefined value, if provided.
     RootedValue valueVal(cx, args.get(1));
     if (!valueVal.isUndefined()) {
         if (!ToWebAssemblyValue(cx, globalType, valueVal, &globalVal)) {
             return false;
         }
@@ -2613,16 +2621,18 @@ WasmGlobalObject::valueGetterImpl(JSCont
       case ValType::AnyRef:
         args.rval().set(args.thisv().toObject().as<WasmGlobalObject>().value(cx));
         return true;
       case ValType::I64:
         JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, JSMSG_WASM_BAD_I64_TYPE);
         return false;
       case ValType::Ref:
         MOZ_CRASH("Ref NYI");
+      case ValType::NullRef:
+        MOZ_CRASH("NullRef not expressible");
     }
     MOZ_CRASH();
 }
 
 /* static */ bool
 WasmGlobalObject::valueGetter(JSContext* cx, unsigned argc, Value* vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
@@ -2671,16 +2681,18 @@ WasmGlobalObject::valueSetterImpl(JSCont
             JSObject::writeBarrierPost(&cell->ptr, prevPtr, cell->ptr);
         }
         break;
       }
       case ValType::I64:
         MOZ_CRASH("unexpected i64 when setting global's value");
       case ValType::Ref:
         MOZ_CRASH("Ref NYI");
+      case ValType::NullRef:
+        MOZ_CRASH("NullRef not expressible");
     }
 
     args.rval().setUndefined();
     return true;
 }
 
 /* static */ bool
 WasmGlobalObject::valueSetter(JSContext* cx, unsigned argc, Value* vp)
@@ -2721,18 +2733,19 @@ void
 WasmGlobalObject::val(MutableHandleVal outval) const
 {
     Cell* cell = this->cell();
     switch (type().code()) {
       case ValType::I32:    outval.set(Val(uint32_t(cell->i32))); return;
       case ValType::I64:    outval.set(Val(uint64_t(cell->i64))); return;
       case ValType::F32:    outval.set(Val(cell->f32));           return;
       case ValType::F64:    outval.set(Val(cell->f64));           return;
-      case ValType::AnyRef: outval.set(Val(cell->ptr));           return;
+      case ValType::AnyRef: outval.set(Val(ValType::AnyRef, cell->ptr)); return;
       case ValType::Ref:    MOZ_CRASH("Ref NYI");
+      case ValType::NullRef:MOZ_CRASH("NullRef not expressible");
     }
     MOZ_CRASH("unexpected Global type");
 }
 
 Value
 WasmGlobalObject::value(JSContext* cx) const
 {
     // ToJSValue crashes on I64; this is desirable.
--- a/js/src/wasm/WasmOpIter.h
+++ b/js/src/wasm/WasmOpIter.h
@@ -48,35 +48,37 @@ class StackType
     bool isValidCode() {
         switch (UnpackTypeCodeType(tc_)) {
           case TypeCode::I32:
           case TypeCode::I64:
           case TypeCode::F32:
           case TypeCode::F64:
           case TypeCode::AnyRef:
           case TypeCode::Ref:
+          case TypeCode::NullRef:
           case TypeCode::Limit:
             return true;
           default:
             return false;
         }
     }
 #endif
 
   public:
     enum Code {
-        I32    = uint8_t(ValType::I32),
-        I64    = uint8_t(ValType::I64),
-        F32    = uint8_t(ValType::F32),
-        F64    = uint8_t(ValType::F64),
-
-        AnyRef = uint8_t(ValType::AnyRef),
-        Ref    = uint8_t(ValType::Ref),
-
-        Any    = uint8_t(TypeCode::Limit),
+        I32     = uint8_t(ValType::I32),
+        I64     = uint8_t(ValType::I64),
+        F32     = uint8_t(ValType::F32),
+        F64     = uint8_t(ValType::F64),
+
+        AnyRef  = uint8_t(ValType::AnyRef),
+        Ref     = uint8_t(ValType::Ref),
+        NullRef = uint8_t(ValType::NullRef),
+
+        TVar    = uint8_t(TypeCode::Limit),
     };
 
     StackType() : tc_(InvalidPackedTypeCode()) {}
 
     MOZ_IMPLICIT StackType(Code c)
       : tc_(PackTypeCode(TypeCode(c)))
     {
         MOZ_ASSERT(isValidCode());
@@ -97,19 +99,19 @@ class StackType
     uint32_t refTypeIndex() const {
         return UnpackTypeCodeIndex(tc_);
     }
 
     bool isRef() const {
         return UnpackTypeCodeType(tc_) == TypeCode::Ref;
     }
 
-    bool isRefOrAnyRef() const {
+    bool isReference() const {
         TypeCode tc = UnpackTypeCodeType(tc_);
-        return tc == TypeCode::Ref || tc == TypeCode::AnyRef;
+        return tc == TypeCode::Ref || tc == TypeCode::AnyRef || tc == TypeCode::NullRef;
     }
 
     bool operator ==(const StackType& that) const {
         return tc_ == that.tc_;
     }
 
     bool operator !=(const StackType& that) const {
         return tc_ != that.tc_;
@@ -123,17 +125,17 @@ class StackType
     bool operator !=(Code that) const {
         return !(*this == that);
     }
 };
 
 static inline ValType
 NonAnyToValType(StackType type)
 {
-    MOZ_ASSERT(type != StackType::Any);
+    MOZ_ASSERT(type != StackType::TVar);
     return ValType(type.packed());
 }
 
 #ifdef DEBUG
 // Families of opcodes that share a signature and validation logic.
 enum class OpKind {
     Block,
     Loop,
@@ -290,17 +292,17 @@ class ControlStackEntry<Nothing>
 
 template <typename Value>
 class TypeAndValue
 {
     StackType type_;
     Value value_;
 
   public:
-    TypeAndValue() : type_(StackType::Any), value_() {}
+    TypeAndValue() : type_(StackType::TVar), value_() {}
     explicit TypeAndValue(StackType type)
       : type_(type), value_()
     {}
     explicit TypeAndValue(ValType type)
       : type_(StackType(type)), value_()
     {}
     TypeAndValue(StackType type, Value value)
       : type_(type), value_(value)
@@ -324,17 +326,17 @@ class TypeAndValue
 
 // Specialization for when there is no additional data needed.
 template <>
 class TypeAndValue<Nothing>
 {
     StackType type_;
 
   public:
-    TypeAndValue() : type_(StackType::Any) {}
+    TypeAndValue() : type_(StackType::TVar) {}
     explicit TypeAndValue(StackType type) : type_(type) {}
     explicit TypeAndValue(ValType type) : type_(StackType(type)) {}
     TypeAndValue(StackType type, Nothing value) : type_(type) {}
     TypeAndValue(ValType type, Nothing value) : type_(StackType(type)) {}
 
     StackType type() const { return type_; }
     StackType& typeRef() { return type_; }
     Nothing value() const { return Nothing(); }
@@ -434,19 +436,16 @@ class MOZ_STACK_CLASS OpIter : private P
         valueStack_.infallibleAppend(tv);
     }
 
     void afterUnconditionalBranch() {
         valueStack_.shrinkTo(controlStack_.back().valueStackStart());
         controlStack_.back().setPolymorphicBase();
     }
 
-    inline bool IsPrefixOf(StackType a, StackType b);
-    inline bool IsSubtypeOf(StackType one, StackType two);
-    inline bool Unify(StackType observed, StackType expected, StackType* result);
     inline bool Join(StackType one, StackType two, StackType* result);
 
   public:
     typedef Vector<Value, 8, SystemAllocPolicy> ValueVector;
 
 #ifdef DEBUG
     explicit OpIter(const ModuleEnvironment& env, Decoder& decoder,
                     ExclusiveDeferredValidationState& dvs)
@@ -539,17 +538,17 @@ class MOZ_STACK_CLASS OpIter : private P
     MOZ_MUST_USE bool readTeeLocal(const ValTypeVector& locals, uint32_t* id, Value* value);
     MOZ_MUST_USE bool readGetGlobal(uint32_t* id);
     MOZ_MUST_USE bool readSetGlobal(uint32_t* id, Value* value);
     MOZ_MUST_USE bool readTeeGlobal(uint32_t* id, Value* value);
     MOZ_MUST_USE bool readI32Const(int32_t* i32);
     MOZ_MUST_USE bool readI64Const(int64_t* i64);
     MOZ_MUST_USE bool readF32Const(float* f32);
     MOZ_MUST_USE bool readF64Const(double* f64);
-    MOZ_MUST_USE bool readRefNull(ValType* type);
+    MOZ_MUST_USE bool readRefNull();
     MOZ_MUST_USE bool readCall(uint32_t* calleeIndex, ValueVector* argValues);
     MOZ_MUST_USE bool readCallIndirect(uint32_t* funcTypeIndex, uint32_t* tableIndex, Value* callee,
                                        ValueVector* argValues);
     MOZ_MUST_USE bool readOldCallDirect(uint32_t numFuncImports, uint32_t* funcIndex,
                                         ValueVector* argValues);
     MOZ_MUST_USE bool readOldCallIndirect(uint32_t* funcTypeIndex, Value* callee, ValueVector* argValues);
     MOZ_MUST_USE bool readWake(LinearMemoryAddress<Value>* addr, Value* count);
     MOZ_MUST_USE bool readWait(LinearMemoryAddress<Value>* addr,
@@ -626,86 +625,40 @@ class MOZ_STACK_CLASS OpIter : private P
     // end of the function body.
     bool controlStackEmpty() const {
         return controlStack_.empty();
     }
 };
 
 template <typename Policy>
 inline bool
-OpIter<Policy>::IsPrefixOf(StackType a, StackType b)
-{
-    const StructType& other = env_.types[a.refTypeIndex()].structType();
-    return env_.types[b.refTypeIndex()].structType().hasPrefix(other);
-}
-
-template <typename Policy>
-inline bool
-OpIter<Policy>::IsSubtypeOf(StackType one, StackType two)
-{
-    MOZ_ASSERT(one.isRefOrAnyRef());
-    MOZ_ASSERT(two.isRefOrAnyRef());
-    return one == two || two == StackType::AnyRef || (one.isRef() && IsPrefixOf(two, one));
-}
-
-template <typename Policy>
-inline bool
-OpIter<Policy>::Unify(StackType observed, StackType expected, StackType* result)
-{
-    if (MOZ_LIKELY(observed == expected)) {
-        *result = observed;
-        return true;
-    }
-
-    if (observed == StackType::Any) {
-        *result = expected;
-        return true;
-    }
-
-    if (expected == StackType::Any) {
-        *result = observed;
-        return true;
-    }
-
-    if (env_.gcTypesEnabled() == HasGcTypes::True && observed.isRefOrAnyRef() &&
-        expected.isRefOrAnyRef() && IsSubtypeOf(observed, expected))
-    {
-        *result = expected;
-        return true;
-    }
-
-    return false;
-}
-
-template <typename Policy>
-inline bool
 OpIter<Policy>::Join(StackType one, StackType two, StackType* result)
 {
     if (MOZ_LIKELY(one == two)) {
         *result = one;
         return true;
     }
 
-    if (one == StackType::Any) {
+    if (one == StackType::TVar) {
         *result = two;
         return true;
     }
 
-    if (two == StackType::Any) {
+    if (two == StackType::TVar) {
         *result = one;
         return true;
     }
 
-    if (env_.gcTypesEnabled() == HasGcTypes::True && one.isRefOrAnyRef() && two.isRefOrAnyRef()) {
-        if (IsSubtypeOf(two, one)) {
+    if (env_.gcTypesEnabled() == HasGcTypes::True && one.isReference() && two.isReference()) {
+        if (env_.isRefSubtypeOf(NonAnyToValType(two), NonAnyToValType(one))) {
             *result = one;
             return true;
         }
 
-        if (IsSubtypeOf(one, two)) {
+        if (env_.isRefSubtypeOf(NonAnyToValType(one), NonAnyToValType(two))) {
             *result = two;
             return true;
         }
 
         // No subtyping relations between the two types.
         *result = StackType::AnyRef;
         return true;
     }
@@ -741,29 +694,29 @@ OpIter<Policy>::fail_ctx(const char* fmt
     if (!error) {
         return false;
     }
     return fail(error.get());
 }
 
 // This function pops exactly one value from the stack, yielding Any types in
 // various cases and therefore making it the caller's responsibility to do the
-// right thing for StackType::Any. Prefer (pop|top)WithType.
+// right thing for StackType::TVar. Prefer (pop|top)WithType.
 template <typename Policy>
 inline bool
 OpIter<Policy>::popAnyType(StackType* type, Value* value)
 {
     ControlStackEntry<ControlItem>& block = controlStack_.back();
 
     MOZ_ASSERT(valueStack_.length() >= block.valueStackStart());
     if (MOZ_UNLIKELY(valueStack_.length() == block.valueStackStart())) {
         // If the base of this block's stack is polymorphic, then we can pop a
         // dummy value of any type; it won't be used since we're in unreachable code.
         if (block.polymorphicBase()) {
-            *type = StackType::Any;
+            *type = StackType::TVar;
             *value = Value();
 
             // Maintain the invariant that, after a pop, there is always memory
             // reserved to push a value infallibly.
             return valueStack_.reserve(valueStack_.length() + 1);
         }
 
         if (valueStack_.empty()) {
@@ -817,19 +770,26 @@ OpIter<Policy>::popWithType(StackType ex
         if (valueStack_.empty()) {
             return fail("popping value from empty stack");
         }
         return fail("popping value from outside block");
     }
 
     TypeAndValue<Value> tv = valueStack_.popCopy();
 
-    StackType _;
-    if (MOZ_UNLIKELY(!Unify(tv.type(), expectedType, &_))) {
-        return typeMismatch(tv.type(), expectedType);
+    StackType observedType = tv.type();
+    if (!(MOZ_LIKELY(observedType == expectedType) ||
+          observedType == StackType::TVar ||
+          expectedType == StackType::TVar ||
+          (env_.gcTypesEnabled() == HasGcTypes::True &&
+           observedType.isReference() && expectedType.isReference() &&
+           env_.isRefSubtypeOf(NonAnyToValType(observedType),
+                               NonAnyToValType(expectedType)))))
+    {
+        return typeMismatch(observedType, expectedType);
     }
 
     *value = tv.value();
     return true;
 }
 
 // This function pops as many types from the stack as determined by the given
 // signature. Currently, all signatures are limited to 0 or 1 types, with
@@ -873,18 +833,29 @@ OpIter<Policy>::topWithType(ValType expe
         if (valueStack_.empty()) {
             return fail("reading value from empty stack");
         }
         return fail("reading value from outside block");
     }
 
     TypeAndValue<Value>& tv = valueStack_.back();
 
-    if (MOZ_UNLIKELY(!Unify(tv.type(), StackType(expectedType), &tv.typeRef()))) {
-        return typeMismatch(tv.type(), StackType(expectedType));
+    StackType observed = tv.type();
+    StackType expected = StackType(expectedType);
+
+    if (!MOZ_UNLIKELY(observed == expected)) {
+        if (observed == StackType::TVar ||
+            (env_.gcTypesEnabled() == HasGcTypes::True &&
+             observed.isReference() && expected.isReference() &&
+             env_.isRefSubtypeOf(NonAnyToValType(observed), expectedType)))
+        {
+            tv.typeRef() = expected;
+        } else {
+            return typeMismatch(observed, expected);
+        }
     }
 
     *value = tv.value();
     return true;
 }
 
 template <typename Policy>
 inline bool
@@ -1702,24 +1673,21 @@ OpIter<Policy>::readF64Const(double* f64
     MOZ_ASSERT(Classify(op_) == OpKind::F64);
 
     return readFixedF64(f64) &&
            push(ValType::F64);
 }
 
 template <typename Policy>
 inline bool
-OpIter<Policy>::readRefNull(ValType* type)
+OpIter<Policy>::readRefNull()
 {
     MOZ_ASSERT(Classify(op_) == OpKind::RefNull);
-    if (!readReferenceType(type, "ref.null")) {
-        return false;
-    }
-
-    return push(StackType(*type));
+
+    return push(StackType(ValType::NullRef));
 }
 
 template <typename Policy>
 inline bool
 OpIter<Policy>::readReferenceType(ValType* type, const char* context)
 {
     uint8_t code;
     uint32_t refTypeIndex;
--- a/js/src/wasm/WasmStubs.cpp
+++ b/js/src/wasm/WasmStubs.cpp
@@ -175,16 +175,18 @@ StoreABIReturn(MacroAssembler& masm, con
       case ExprType::F64:
         masm.canonicalizeDouble(ReturnDoubleReg);
         masm.storeDouble(ReturnDoubleReg, Address(argv, 0));
         break;
       case ExprType::Ref:
       case ExprType::AnyRef:
         masm.storePtr(ReturnReg, Address(argv, 0));
         break;
+      case ExprType::NullRef:
+        MOZ_CRASH("NullRef not expressible");
       case ExprType::Limit:
         MOZ_CRASH("Limit");
     }
 }
 
 #if defined(JS_CODEGEN_ARM)
 // The ARM system ABI also includes d15 & s31 in the non volatile float registers.
 // Also exclude lr (a.k.a. r14) as we preserve it manually.
@@ -792,16 +794,18 @@ GenerateJitEntry(MacroAssembler& masm, s
       case ExprType::Ref:
         MOZ_CRASH("return ref in jitentry NYI");
         break;
       case ExprType::AnyRef:
         MOZ_CRASH("return anyref in jitentry NYI");
         break;
       case ExprType::I64:
         MOZ_CRASH("unexpected return type when calling from ion to wasm");
+      case ExprType::NullRef:
+        MOZ_CRASH("NullRef not expressible");
       case ExprType::Limit:
         MOZ_CRASH("Limit");
     }
 
     MOZ_ASSERT(masm.framePushed() == 0);
 #ifdef JS_CODEGEN_ARM64
     masm.loadPtr(Address(sp, 0), lr);
     masm.addToStackPtr(Imm32(8));
@@ -1004,16 +1008,18 @@ wasm::GenerateDirectCallFromJit(MacroAss
         break;
       case wasm::ExprType::F64:
         masm.canonicalizeDouble(ReturnDoubleReg);
         break;
       case wasm::ExprType::Ref:
       case wasm::ExprType::AnyRef:
       case wasm::ExprType::I64:
         MOZ_CRASH("unexpected return type when calling from ion to wasm");
+      case wasm::ExprType::NullRef:
+        MOZ_CRASH("NullRef not expressible");
       case wasm::ExprType::Limit:
         MOZ_CRASH("Limit");
     }
 
     // Free args + frame descriptor.
     masm.leaveExitFrame(bytesNeeded + ExitFrameLayout::Size());
 
     // If we pushed it, free FramePointer.
@@ -1344,16 +1350,18 @@ GenerateImportInterpExit(MacroAssembler&
         masm.loadDouble(argv, ReturnDoubleReg);
         break;
       case ExprType::Ref:
       case ExprType::AnyRef:
         masm.call(SymbolicAddress::CallImport_Ref);
         masm.branchTest32(Assembler::Zero, ReturnReg, ReturnReg, throwLabel);
         masm.loadPtr(argv, ReturnReg);
         break;
+      case ExprType::NullRef:
+        MOZ_CRASH("NullRef not expressible");
       case ExprType::Limit:
         MOZ_CRASH("Limit");
     }
 
     // The native ABI preserves the TLS, heap and global registers since they
     // are non-volatile.
     MOZ_ASSERT(NonVolatileRegs.has(WasmTlsReg));
 #if defined(JS_CODEGEN_X64) || \
@@ -1517,16 +1525,18 @@ GenerateImportJitExit(MacroAssembler& ma
         masm.convertValueToDouble(JSReturnOperand, ReturnDoubleReg, &oolConvert);
         break;
       case ExprType::Ref:
         MOZ_CRASH("ref returned by import (jit exit) NYI");
         break;
       case ExprType::AnyRef:
         MOZ_CRASH("anyref returned by import (jit exit) NYI");
         break;
+      case ExprType::NullRef:
+        MOZ_CRASH("NullRef not expressible");
       case ExprType::Limit:
         MOZ_CRASH("Limit");
     }
 
     Label done;
     masm.bind(&done);
 
     GenerateJitExitEpilogue(masm, masm.framePushed(), offsets);
--- a/js/src/wasm/WasmTextToBinary.cpp
+++ b/js/src/wasm/WasmTextToBinary.cpp
@@ -3875,29 +3875,17 @@ ParseStructNarrow(WasmParseContext& c, b
 
     return new(c.lifo) AstStructNarrow(inputType, outputType, ptr);
 }
 #endif
 
 static AstExpr*
 ParseRefNull(WasmParseContext& c)
 {
-    WasmToken token;
-    AstValType vt;
-
-    if (!ParseValType(c, &vt)) {
-        return nullptr;
-    }
-
-    if (!vt.isRefType()) {
-        c.ts.generateError(token, "ref.null requires ref type", c.error);
-        return nullptr;
-    }
-
-    return new(c.lifo) AstRefNull(vt);
+    return new(c.lifo) AstRefNull();
 }
 
 static AstExpr*
 ParseExprBody(WasmParseContext& c, WasmToken token, bool inParens)
 {
     if (!CheckRecursionLimitDontReport(c.stackLimit)) {
         return nullptr;
     }
@@ -5777,17 +5765,17 @@ ResolveStructNarrow(Resolver& r, AstStru
 
     return ResolveExpr(r, s.ptr());
 }
 #endif
 
 static bool
 ResolveRefNull(Resolver& r, AstRefNull& s)
 {
-    return ResolveType(r, s.baseType());
+    return true;
 }
 
 static bool
 ResolveExpr(Resolver& r, AstExpr& expr)
 {
     switch (expr.kind()) {
       case AstExprKind::Nop:
       case AstExprKind::Pop:
@@ -6731,18 +6719,17 @@ EncodeStructNarrow(Encoder& e, AstStruct
     }
     return true;
 }
 #endif
 
 static bool
 EncodeRefNull(Encoder& e, AstRefNull& s)
 {
-    return e.writeOp(Op::RefNull) &&
-           e.writeValType(s.baseType().type());
+    return e.writeOp(Op::RefNull);
 }
 
 static bool
 EncodeExpr(Encoder& e, AstExpr& expr)
 {
     switch (expr.kind()) {
       case AstExprKind::Pop:
         return true;
--- a/js/src/wasm/WasmTypes.cpp
+++ b/js/src/wasm/WasmTypes.cpp
@@ -64,16 +64,17 @@ Val::Val(const LitVal& val)
 {
     type_ = val.type();
     switch (type_.code()) {
       case ValType::I32: u.i32_ = val.i32(); return;
       case ValType::F32: u.f32_ = val.f32(); return;
       case ValType::I64: u.i64_ = val.i64(); return;
       case ValType::F64: u.f64_ = val.f64(); return;
       case ValType::Ref:
+      case ValType::NullRef:
       case ValType::AnyRef: u.ptr_ = val.ptr(); return;
     }
     MOZ_CRASH();
 }
 
 void
 Val::writePayload(uint8_t* dst) const
 {
@@ -82,16 +83,17 @@ Val::writePayload(uint8_t* dst) const
       case ValType::F32:
         memcpy(dst, &u.i32_, sizeof(u.i32_));
         return;
       case ValType::I64:
       case ValType::F64:
         memcpy(dst, &u.i64_, sizeof(u.i64_));
         return;
       case ValType::Ref:
+      case ValType::NullRef:
       case ValType::AnyRef:
         MOZ_ASSERT(*(JSObject**)dst == nullptr, "should be null so no need for a pre-barrier");
         memcpy(dst, &u.ptr_, sizeof(JSObject*));
         // Either the written location is in the global data section in the
         // WasmInstanceObject, or the Cell of a WasmGlobalObject:
         // - WasmInstanceObjects are always tenured and u.ptr_ may point to a
         // nursery object, so we need a post-barrier since the global data of
         // an instance is effectively a field of the WasmInstanceObject.
@@ -103,17 +105,17 @@ Val::writePayload(uint8_t* dst) const
         return;
     }
     MOZ_CRASH("unexpected Val type");
 }
 
 void
 Val::trace(JSTracer* trc)
 {
-    if (type_.isValid() && type_.isRefOrAnyRef() && u.ptr_) {
+    if (type_.isValid() && type_.isReference() && u.ptr_) {
         TraceManuallyBarrieredEdge(trc, &u.ptr_, "wasm ref/anyref global");
     }
 }
 
 bool
 wasm::IsRoundingFunction(SymbolicAddress callee, jit::RoundingMode* mode)
 {
     switch (callee) {
@@ -195,16 +197,17 @@ IsImmediateType(ValType vt)
 {
     switch (vt.code()) {
       case ValType::I32:
       case ValType::I64:
       case ValType::F32:
       case ValType::F64:
       case ValType::AnyRef:
         return true;
+      case ValType::NullRef:
       case ValType::Ref:
         return false;
     }
     MOZ_CRASH("bad ValType");
 }
 
 static unsigned
 EncodeImmediateType(ValType vt)
@@ -216,16 +219,17 @@ EncodeImmediateType(ValType vt)
       case ValType::I64:
         return 1;
       case ValType::F32:
         return 2;
       case ValType::F64:
         return 3;
       case ValType::AnyRef:
         return 4;
+      case ValType::NullRef:
       case ValType::Ref:
         break;
     }
     MOZ_CRASH("bad ValType");
 }
 
 /* static */ bool
 FuncTypeIdDesc::isGlobal(const FuncType& funcType)
--- a/js/src/wasm/WasmTypes.h
+++ b/js/src/wasm/WasmTypes.h
@@ -288,38 +288,40 @@ class ExprType
 #ifdef DEBUG
     bool isValidCode() {
         switch (UnpackTypeCodeType(tc_)) {
           case TypeCode::I32:
           case TypeCode::I64:
           case TypeCode::F32:
           case TypeCode::F64:
           case TypeCode::AnyRef:
+          case TypeCode::NullRef:
           case TypeCode::Ref:
           case TypeCode::BlockVoid:
           case TypeCode::Limit:
             return true;
           default:
             return false;
         }
     }
 #endif
 
   public:
     enum Code {
-        Void   = uint8_t(TypeCode::BlockVoid),
-
-        I32    = uint8_t(TypeCode::I32),
-        I64    = uint8_t(TypeCode::I64),
-        F32    = uint8_t(TypeCode::F32),
-        F64    = uint8_t(TypeCode::F64),
-        AnyRef = uint8_t(TypeCode::AnyRef),
-        Ref    = uint8_t(TypeCode::Ref),
-
-        Limit  = uint8_t(TypeCode::Limit)
+        Void    = uint8_t(TypeCode::BlockVoid),
+
+        I32     = uint8_t(TypeCode::I32),
+        I64     = uint8_t(TypeCode::I64),
+        F32     = uint8_t(TypeCode::F32),
+        F64     = uint8_t(TypeCode::F64),
+        AnyRef  = uint8_t(TypeCode::AnyRef),
+        NullRef = uint8_t(TypeCode::NullRef),
+        Ref     = uint8_t(TypeCode::Ref),
+
+        Limit   = uint8_t(TypeCode::Limit)
     };
 
     ExprType() : tc_() {}
 
     ExprType(const ExprType& that) : tc_(that.tc_) {}
 
     MOZ_IMPLICIT ExprType(Code c)
       : tc_(PackTypeCode(TypeCode(c)))
@@ -360,19 +362,19 @@ class ExprType
     bool isValid() const {
         return IsValid(tc_);
     }
 
     bool isRef() const {
         return UnpackTypeCodeType(tc_) == TypeCode::Ref;
     }
 
-    bool isRefOrAnyRef() const {
+    bool isReference() const {
         TypeCode tc = UnpackTypeCodeType(tc_);
-        return tc == TypeCode::Ref || tc == TypeCode::AnyRef;
+        return tc == TypeCode::Ref || tc == TypeCode::AnyRef || tc == TypeCode::NullRef;
     }
 
     bool operator ==(const ExprType& that) const {
         return tc_ == that.tc_;
     }
 
     bool operator !=(const ExprType& that) const {
         return tc_ != that.tc_;
@@ -398,33 +400,35 @@ class ValType
 #ifdef DEBUG
     bool isValidCode() {
         switch (UnpackTypeCodeType(tc_)) {
           case TypeCode::I32:
           case TypeCode::I64:
           case TypeCode::F32:
           case TypeCode::F64:
           case TypeCode::AnyRef:
+          case TypeCode::NullRef:
           case TypeCode::Ref:
             return true;
           default:
             return false;
         }
     }
 #endif
 
   public:
     enum Code {
-        I32    = uint8_t(TypeCode::I32),
-        I64    = uint8_t(TypeCode::I64),
-        F32    = uint8_t(TypeCode::F32),
-        F64    = uint8_t(TypeCode::F64),
-
-        AnyRef = uint8_t(TypeCode::AnyRef),
-        Ref    = uint8_t(TypeCode::Ref),
+        I32     = uint8_t(TypeCode::I32),
+        I64     = uint8_t(TypeCode::I64),
+        F32     = uint8_t(TypeCode::F32),
+        F64     = uint8_t(TypeCode::F64),
+
+        AnyRef  = uint8_t(TypeCode::AnyRef),
+        NullRef = uint8_t(TypeCode::NullRef),
+        Ref     = uint8_t(TypeCode::Ref),
     };
 
     ValType() : tc_(InvalidPackedTypeCode()) {}
 
     MOZ_IMPLICIT ValType(Code c)
       : tc_(PackTypeCode(TypeCode(c)))
     {
         MOZ_ASSERT(isValidCode());
@@ -471,19 +475,19 @@ class ValType
     bool isValid() const {
         return IsValid(tc_);
     }
 
     bool isRef() const {
         return UnpackTypeCodeType(tc_) == TypeCode::Ref;
     }
 
-    bool isRefOrAnyRef() const {
+    bool isReference() const {
         TypeCode tc = UnpackTypeCodeType(tc_);
-        return tc == TypeCode::Ref || tc == TypeCode::AnyRef;
+        return tc == TypeCode::Ref || tc == TypeCode::AnyRef || tc == TypeCode::NullRef;
     }
 
     bool operator ==(const ValType& that) const {
         return tc_ == that.tc_;
     }
 
     bool operator !=(const ValType& that) const {
         return tc_ != that.tc_;
@@ -509,40 +513,42 @@ SizeOf(ValType vt)
     switch (vt.code()) {
       case ValType::I32:
       case ValType::F32:
         return 4;
       case ValType::I64:
       case ValType::F64:
         return 8;
       case ValType::AnyRef:
+      case ValType::NullRef:
       case ValType::Ref:
         return sizeof(intptr_t);
     }
     MOZ_CRASH("Invalid ValType");
 }
 
 static inline jit::MIRType
 ToMIRType(ValType vt)
 {
     switch (vt.code()) {
-      case ValType::I32:    return jit::MIRType::Int32;
-      case ValType::I64:    return jit::MIRType::Int64;
-      case ValType::F32:    return jit::MIRType::Float32;
-      case ValType::F64:    return jit::MIRType::Double;
-      case ValType::Ref:    return jit::MIRType::Pointer;
-      case ValType::AnyRef: return jit::MIRType::Pointer;
+      case ValType::I32:     return jit::MIRType::Int32;
+      case ValType::I64:     return jit::MIRType::Int64;
+      case ValType::F32:     return jit::MIRType::Float32;
+      case ValType::F64:     return jit::MIRType::Double;
+      case ValType::Ref:     return jit::MIRType::Pointer;
+      case ValType::AnyRef:  return jit::MIRType::Pointer;
+      case ValType::NullRef: return jit::MIRType::Pointer;
     }
     MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE("bad type");
 }
 
 static inline bool
 IsNumberType(ValType vt)
 {
-    return !vt.isRefOrAnyRef();
+    return !vt.isReference();
 }
 
 // ExprType utilities
 
 inline
 ExprType::ExprType(const ValType& t)
   : tc_(t.packed())
 {}
@@ -571,16 +577,17 @@ ToCString(ExprType type)
 {
     switch (type.code()) {
       case ExprType::Void:    return "void";
       case ExprType::I32:     return "i32";
       case ExprType::I64:     return "i64";
       case ExprType::F32:     return "f32";
       case ExprType::F64:     return "f64";
       case ExprType::AnyRef:  return "anyref";
+      case ExprType::NullRef: return "nullref";
       case ExprType::Ref:     return "ref";
       case ExprType::Limit:;
     }
     MOZ_CRASH("bad expression type");
 }
 
 static inline const char*
 ToCString(ValType type)
@@ -703,29 +710,30 @@ class LitVal
 
     explicit LitVal(uint32_t i32) : type_(ValType::I32) { u.i32_ = i32; }
     explicit LitVal(uint64_t i64) : type_(ValType::I64) { u.i64_ = i64; }
 
     explicit LitVal(float f32) : type_(ValType::F32) { u.f32_ = f32; }
     explicit LitVal(double f64) : type_(ValType::F64) { u.f64_ = f64; }
 
     explicit LitVal(ValType refType, JSObject* ptr) : type_(refType) {
-        MOZ_ASSERT(refType.isRefOrAnyRef());
+        MOZ_ASSERT(refType.isReference());
+        MOZ_ASSERT(refType != ValType::NullRef);
         MOZ_ASSERT(ptr == nullptr, "use Val for non-nullptr ref types to get tracing");
         u.ptr_ = ptr;
     }
 
     ValType type() const { return type_; }
     static constexpr size_t sizeofLargestValue() { return sizeof(u); }
 
     uint32_t i32() const { MOZ_ASSERT(type_ == ValType::I32); return u.i32_; }
     uint64_t i64() const { MOZ_ASSERT(type_ == ValType::I64); return u.i64_; }
     const float& f32() const { MOZ_ASSERT(type_ == ValType::F32); return u.f32_; }
     const double& f64() const { MOZ_ASSERT(type_ == ValType::F64); return u.f64_; }
-    JSObject* ptr() const { MOZ_ASSERT(type_.isRefOrAnyRef()); return u.ptr_; }
+    JSObject* ptr() const { MOZ_ASSERT(type_.isReference()); return u.ptr_; }
 };
 
 typedef Vector<LitVal, 0, SystemAllocPolicy> LitValVector;
 
 // A Val is a LitVal that can contain pointers to JSObjects, thanks to their
 // trace implementation. Since a Val is able to store a pointer to a JSObject,
 // it needs to be traced during compilation in case the pointee is moved.
 // The classic shorthands for Rooted things are defined after this class, for
@@ -735,17 +743,17 @@ class MOZ_NON_PARAM Val : public LitVal
 {
   public:
     Val() : LitVal() {}
     explicit Val(const LitVal& val);
     explicit Val(uint32_t i32)  : LitVal(i32) {}
     explicit Val(uint64_t i64)  : LitVal(i64) {}
     explicit Val(float f32)     : LitVal(f32) {}
     explicit Val(double f64)    : LitVal(f64) {}
-    explicit Val(JSObject* obj) : LitVal(ValType::AnyRef, nullptr) { u.ptr_ = obj; }
+    explicit Val(ValType type, JSObject* obj) : LitVal(type, nullptr) { u.ptr_ = obj; }
     void writePayload(uint8_t* dst) const;
     void trace(JSTracer* trc);
 };
 
 typedef Rooted<Val> RootedVal;
 typedef Handle<Val> HandleVal;
 typedef MutableHandle<Val> MutableHandleVal;
 
@@ -804,21 +812,21 @@ class FuncType
         for (ValType arg : args()) {
             if (arg == ValType::I64) {
                 return true;
             }
         }
         return false;
     }
     bool temporarilyUnsupportedAnyRef() const {
-        if (ret().isRefOrAnyRef()) {
+        if (ret().isReference()) {
             return true;
         }
         for (ValType arg : args()) {
-            if (arg.isRefOrAnyRef()) {
+            if (arg.isReference()) {
                 return true;
             }
         }
         return false;
     }
 #ifdef WASM_PRIVATE_REFTYPES
     bool exposesRef() const {
         for (const ValType& arg : args()) {
@@ -1053,31 +1061,33 @@ class GlobalDesc
     bool isWasm() const { return !isConstant() && u.var.isWasm_; }
 
   public:
     GlobalDesc() = default;
 
     explicit GlobalDesc(InitExpr initial, bool isMutable, ModuleKind kind = ModuleKind::Wasm)
       : kind_((isMutable || !initial.isVal()) ? GlobalKind::Variable : GlobalKind::Constant)
     {
+        MOZ_ASSERT(initial.type() != ValType::NullRef);
         if (isVariable()) {
             u.var.val.initial_ = initial;
             u.var.isMutable_ = isMutable;
             u.var.isWasm_ = kind == Wasm;
             u.var.isExport_ = false;
             u.var.offset_ = UINT32_MAX;
         } else {
             u.cst_ = initial.val();
         }
     }
 
     explicit GlobalDesc(ValType type, bool isMutable, uint32_t importIndex,
                         ModuleKind kind = ModuleKind::Wasm)
       : kind_(GlobalKind::Import)
     {
+        MOZ_ASSERT(type != ValType::NullRef);
         u.var.val.import.type_ = type;
         u.var.val.import.index_ = importIndex;
         u.var.isMutable_ = isMutable;
         u.var.isWasm_ = kind == Wasm;
         u.var.isExport_ = false;
         u.var.offset_ = UINT32_MAX;
     }
 
--- a/js/src/wasm/WasmValidate.cpp
+++ b/js/src/wasm/WasmValidate.cpp
@@ -1000,18 +1000,17 @@ DecodeFunctionBodyExprs(const ModuleEnvi
             }
             CHECK(iter.readComparison(ValType::AnyRef, &nothing, &nothing));
             break;
           }
           case uint16_t(Op::RefNull): {
             if (env.gcTypesEnabled() == HasGcTypes::False) {
                 return iter.unrecognizedOpcode(&op);
             }
-            ValType unusedType;
-            CHECK(iter.readRefNull(&unusedType));
+            CHECK(iter.readRefNull());
             break;
           }
           case uint16_t(Op::RefIsNull): {
             if (env.gcTypesEnabled() == HasGcTypes::False) {
                 return iter.unrecognizedOpcode(&op);
             }
             CHECK(iter.readConversion(ValType::AnyRef, ValType::I32, &nothing));
             break;
@@ -1447,24 +1446,28 @@ DecodeGCFeatureOptInSection(Decoder& d, 
     if (!d.readVarU32(&version)) {
         return d.fail("expected gc feature version");
     }
 
     // For documentation of what's in the various versions, see
     // https://github.com/lars-t-hansen/moz-gc-experiments
     //
     // Version 1 is complete.
-    // Version 2 is in progress, currently backward compatible with version 1.
+    // Version 2 is in progress.
 
     switch (version) {
       case 1:
+        return d.fail("Wasm GC feature version 1 is no longer supported by this engine.\n"
+                      "The current version is 2, which is not backward-compatible:\n"
+                      " - The old encoding of ref.null is no longer accepted.");
       case 2:
         break;
       default:
-        return d.fail("unsupported version of the gc feature");
+        return d.fail("The specified Wasm GC feature version is unknown.\n"
+                      "The current version is 2.");
     }
 
     env->gcFeatureOptIn = HasGcTypes::True;
     return d.finishSection(*range, "gcfeatureoptin");
 }
 #endif
 
 static bool
@@ -1974,18 +1977,17 @@ DecodeMemorySection(Decoder& d, ModuleEn
             return false;
         }
     }
 
     return d.finishSection(*range, "memory");
 }
 
 static bool
-DecodeInitializerExpression(Decoder& d, HasGcTypes gcTypesEnabled, const GlobalDescVector& globals,
-                            ValType expected, uint32_t numTypes, InitExpr* init)
+DecodeInitializerExpression(Decoder& d, ModuleEnvironment* env, ValType expected, InitExpr* init)
 {
     OpBytes op;
     if (!d.readOp(&op)) {
         return d.fail("failed to read initializer type");
     }
 
     switch (op.b0) {
       case uint16_t(Op::I32Const): {
@@ -2016,48 +2018,48 @@ DecodeInitializerExpression(Decoder& d, 
         double f64;
         if (!d.readFixedF64(&f64)) {
             return d.fail("failed to read initializer f64 expression");
         }
         *init = InitExpr(LitVal(f64));
         break;
       }
       case uint16_t(Op::RefNull): {
-        if (gcTypesEnabled == HasGcTypes::False) {
+        if (env->gcTypesEnabled() == HasGcTypes::False) {
             return d.fail("unexpected initializer expression");
         }
-        uint8_t valType;
-        uint32_t refTypeIndex;
-        if (!d.readValType(&valType, &refTypeIndex)) {
-            return false;
+        if (!expected.isReference()) {
+            return d.fail("type mismatch: initializer type and expected type don't match");
         }
-        if (valType == uint8_t(ValType::AnyRef)) {
-            *init = InitExpr(LitVal(ValType::AnyRef, nullptr));
-        } else if (valType == uint8_t(ValType::Ref)) {
-            if (refTypeIndex >= numTypes) {
-                return d.fail("invalid reference type for ref.null");
-            }
-            *init = InitExpr(LitVal(ValType(ValType::Ref, refTypeIndex), nullptr));
-        } else {
-            return d.fail("expected anyref/ref as type for ref.null");
-        }
+        *init = InitExpr(LitVal(expected, nullptr));
         break;
       }
       case uint16_t(Op::GetGlobal): {
         uint32_t i;
+        const GlobalDescVector& globals = env->globals;
         if (!d.readVarU32(&i)) {
             return d.fail("failed to read get_global index in initializer expression");
         }
         if (i >= globals.length()) {
             return d.fail("global index out of range in initializer expression");
         }
         if (!globals[i].isImport() || globals[i].isMutable()) {
             return d.fail("initializer expression must reference a global immutable import");
         }
-        *init = InitExpr(i, globals[i].type());
+        if (expected.isReference()) {
+            if (!(env->gcTypesEnabled() == HasGcTypes::True &&
+                  globals[i].type().isReference() &&
+                  env->isRefSubtypeOf(globals[i].type(), expected)))
+            {
+                return d.fail("type mismatch: initializer type and expected type don't match");
+            }
+            *init = InitExpr(i, expected);
+        } else {
+            *init = InitExpr(i, globals[i].type());
+        }
         break;
       }
       default: {
         return d.fail("unexpected initializer expression");
       }
     }
 
     if (expected != init->type()) {
@@ -2101,19 +2103,17 @@ DecodeGlobalSection(Decoder& d, ModuleEn
     for (uint32_t i = 0; i < numDefs; i++) {
         ValType type;
         bool isMutable;
         if (!DecodeGlobalType(d, env->types, env->gcTypesEnabled(), &type, &isMutable)) {
             return false;
         }
 
         InitExpr initializer;
-        if (!DecodeInitializerExpression(d, env->gcTypesEnabled(), env->globals, type,
-                                         env->types.length(), &initializer))
-        {
+        if (!DecodeInitializerExpression(d, env, type, &initializer)) {
             return false;
         }
 
         env->globals.infallibleAppend(GlobalDesc(initializer, isMutable));
     }
 
     return d.finishSection(*range, "global");
 }
@@ -2355,19 +2355,17 @@ DecodeElemSection(Decoder& d, ModuleEnvi
         }
 
         seg->tableIndex = tableIndex;
 
         if (initializerKind == InitializerKind::Active ||
             initializerKind == InitializerKind::ActiveWithIndex)
         {
             InitExpr offset;
-            if (!DecodeInitializerExpression(d, env->gcTypesEnabled(), env->globals, ValType::I32,
-                                             env->types.length(), &offset))
-            {
+            if (!DecodeInitializerExpression(d, env, ValType::I32, &offset)) {
                 return false;
             }
             seg->offsetIfActive.emplace(offset);
         }
 
         uint32_t numElems;
         if (!d.readVarU32(&numElems)) {
             return d.fail("expected segment size");
@@ -2614,19 +2612,17 @@ DecodeDataSection(Decoder& d, ModuleEnvi
             }
         }
 
         DataSegmentEnv seg;
         if (initializerKind == InitializerKind::Active ||
             initializerKind == InitializerKind::ActiveWithIndex)
         {
             InitExpr segOffset;
-            if (!DecodeInitializerExpression(d, env->gcTypesEnabled(), env->globals, ValType::I32,
-                                             env->types.length(), &segOffset))
-            {
+            if (!DecodeInitializerExpression(d, env, ValType::I32, &segOffset)) {
                 return false;
             }
             seg.offsetIfActive.emplace(segOffset);
         }
 
         if (!d.readVarU32(&seg.length)) {
             return d.fail("expected segment size");
         }
--- a/js/src/wasm/WasmValidate.h
+++ b/js/src/wasm/WasmValidate.h
@@ -247,16 +247,29 @@ struct ModuleEnvironment
         return kind == ModuleKind::AsmJS;
     }
     bool debugEnabled() const {
         return compilerEnv->debug() == DebugEnabled::True;
     }
     bool funcIsImport(uint32_t funcIndex) const {
         return funcIndex < funcImportGlobalDataOffsets.length();
     }
+    bool isRefSubtypeOf(ValType one, ValType two) const {
+        MOZ_ASSERT(one.isReference());
+        MOZ_ASSERT(two.isReference());
+        MOZ_ASSERT(gcTypesEnabled() == HasGcTypes::True);
+        return one == two || two == ValType::AnyRef || one == ValType::NullRef ||
+               (one.isRef() && two.isRef() && isStructPrefixOf(two, one));
+    }
+
+  private:
+    bool isStructPrefixOf(ValType a, ValType b) const {
+        const StructType& other = types[a.refTypeIndex()].structType();
+        return types[b.refTypeIndex()].structType().hasPrefix(other);
+    }
 };
 
 // The Encoder class appends bytes to the Bytes object it is given during
 // construction. The client is responsible for the Bytes's lifetime and must
 // keep the Bytes alive as long as the Encoder is used.
 
 class Encoder
 {
deleted file mode 100644
--- a/testing/web-platform/meta/css/css-text/writing-system/writing-system-font-001.html.ini
+++ /dev/null
@@ -1,2 +0,0 @@
-[writing-system-font-001.html]
-  expected: FAIL