Merge mozilla-central to autoland. a=merge CLOSED TREE
authorGurzau Raul <rgurzau@mozilla.com>
Mon, 02 Jul 2018 00:52:31 +0300
changeset 813060 8c7b5e66c06cb8e5196909d1c421628b0ee3fc26
parent 813059 d1c14db600431c187fbade3dcf218778fc309710 (current diff)
parent 812962 3cfc350101967376909ad3c729f9779ae0ab7a94 (diff)
child 813061 8fb94a730b6c42d4dd0c9c76a2b2d697bb4b6025
push id114752
push userbmo:dave.hunt@gmail.com
push dateMon, 02 Jul 2018 10:28:01 +0000
reviewersmerge
milestone63.0a1
Merge mozilla-central to autoland. a=merge CLOSED TREE
intl/strres/nsIStringBundleOverride.idl
intl/strres/nsStringBundleTextOverride.cpp
intl/strres/nsStringBundleTextOverride.h
third_party/rust/clang-sys/CONTRIBUTING.md
third_party/rust/proc-macro2-0.3.6/.cargo-checksum.json
third_party/rust/proc-macro2-0.3.6/.travis.yml
third_party/rust/proc-macro2-0.3.6/Cargo.toml
third_party/rust/proc-macro2-0.3.6/LICENSE-APACHE
third_party/rust/proc-macro2-0.3.6/LICENSE-MIT
third_party/rust/proc-macro2-0.3.6/README.md
third_party/rust/proc-macro2-0.3.6/src/lib.rs
third_party/rust/proc-macro2-0.3.6/src/stable.rs
third_party/rust/proc-macro2-0.3.6/src/strnom.rs
third_party/rust/proc-macro2-0.3.6/src/unstable.rs
third_party/rust/proc-macro2-0.3.6/tests/test.rs
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -151,27 +151,28 @@ version = "1.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 1.0.66 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "bindgen"
-version = "0.33.2"
+version = "0.37.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "cexpr 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "clang-sys 0.22.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "clang-sys 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "clap 2.31.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "peeking_take_while 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
- "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "proc-macro2 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "regex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "which 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "binjs_meta"
 version = "0.3.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
@@ -288,17 +289,17 @@ version = "0.2.25"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "num 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
  "time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "clang-sys"
-version = "0.22.0"
+version = "0.23.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)",
  "libloading 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -458,17 +459,17 @@ dependencies = [
 ]
 
 [[package]]
 name = "cssparser-macros"
 version = "0.3.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "phf_codegen 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)",
- "proc-macro2 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "proc-macro2 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "procedural-masquerade 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "syn 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "cstr"
 version = "0.1.3"
@@ -542,17 +543,17 @@ dependencies = [
 ]
 
 [[package]]
 name = "darling_core"
 version = "0.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "ident_case 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "proc-macro2 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "proc-macro2 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "syn 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "darling_macro"
 version = "0.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -972,17 +973,17 @@ source = "registry+https://github.com/ru
 name = "itoa"
 version = "0.4.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "js"
 version = "0.1.4"
 dependencies = [
- "bindgen 0.33.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "bindgen 0.37.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "cmake 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)",
  "env_logger 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "mozjs_sys 0.0.0",
  "num-traits 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1587,17 +1588,17 @@ version = "0.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "prefs_parser"
 version = "0.0.1"
 
 [[package]]
 name = "proc-macro2"
-version = "0.3.6"
+version = "0.3.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "proc-macro2"
 version = "0.4.6"
@@ -1636,17 +1637,17 @@ name = "quote"
 version = "0.3.15"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "quote"
 version = "0.5.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "proc-macro2 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "proc-macro2 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "quote"
 version = "0.6.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "proc-macro2 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1931,17 +1932,17 @@ source = "registry+https://github.com/ru
 
 [[package]]
 name = "style"
 version = "0.0.1"
 dependencies = [
  "app_units 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "arrayvec 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "atomic_refcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "bindgen 0.33.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "bindgen 0.37.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "cssparser 0.24.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "euclid 0.17.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "fallible 0.0.1",
  "fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "hashglobe 0.1.0",
@@ -2024,17 +2025,17 @@ dependencies = [
  "style_traits 0.0.1",
 ]
 
 [[package]]
 name = "syn"
 version = "0.13.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "proc-macro2 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "proc-macro2 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "syn"
 version = "0.14.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2044,17 +2045,17 @@ dependencies = [
  "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "synstructure"
 version = "0.8.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "proc-macro2 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "proc-macro2 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "syn 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "tempdir"
 version = "0.3.5"
@@ -2528,34 +2529,34 @@ dependencies = [
 "checksum arrayvec 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2f0ef4a9820019a0c91d918918c93dc71d469f581a49b47ddc1d285d4270bbe2"
 "checksum ascii-canvas 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b385d69402821a1c254533a011a312531cbcc0e3e24f19bbb4747a5a2daf37e2"
 "checksum atomic_refcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fb2dcb6e6d35f20276943cc04bb98e538b348d525a04ac79c10021561d202f21"
 "checksum atty 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d0fd4c0631f06448cc45a6bbb3b710ebb7ff8ccb96a0800c994afe23a70d5df2"
 "checksum atty 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d912da0db7fa85514874458ca3651fe2cddace8d0b0505571dbdcd41ab490159"
 "checksum base64 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "96434f987501f0ed4eb336a411e0631ecd1afa11574fe148587adc4ff96143c9"
 "checksum binary-space-partition 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "88ceb0d16c4fd0e42876e298d7d3ce3780dd9ebdcbe4199816a32c77e08597ff"
 "checksum bincode 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bda13183df33055cbb84b847becce220d392df502ebe7a4a78d7021771ed94d0"
-"checksum bindgen 0.33.2 (registry+https://github.com/rust-lang/crates.io-index)" = "603ed8d8392ace9581e834e26bd09799bf1e989a79bd1aedbb893e72962bdc6e"
+"checksum bindgen 0.37.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1b25ab82877ea8fe6ce1ce1f8ac54361f0218bad900af9eb11803994bf67c221"
 "checksum binjs_meta 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "9fcfc86eecb125147e907529a5f1ac7978f6f26d20a52b82a7e053da5faefbc3"
 "checksum bit-set 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d9bf6104718e80d7b26a68fdbacff3481cfc05df670821affc7e9cbc1884400c"
 "checksum bit-vec 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "02b4ff8b16e6076c3e14220b39fbc1fabb6737522281a388998046859400895f"
 "checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d"
 "checksum bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b3c30d3802dfb7281680d6285f2ccdaa8c2d8fee41f93805dba5c4cf50dc23cf"
 "checksum bitreader 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "80b13e2ab064ff3aa0bdbf1eff533f9822dc37899821f5f98c67f263eab51707"
 "checksum boxfnonce 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8380105befe91099e6f69206164072c05bc92427ff6aa8a5171388317346dd75"
 "checksum build_const 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e90dc84f5e62d2ebe7676b83c22d33b6db8bd27340fb6ffbff0a364efa0cb9c9"
 "checksum byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "652805b7e73fada9d85e9a6682a4abd490cb52d96aeecc12e33a0de34dfd0d23"
 "checksum bytes 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d828f97b58cc5de3e40c421d0cf2132d6b2da4ee0e11b8632fa838f0f9333ad6"
 "checksum bzip2 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c3eafc42c44e0d827de6b1c131175098fe7fb53b8ce8a47e65cb3ea94688be24"
 "checksum bzip2-sys 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2c5162604199bbb17690ede847eaa6120a3f33d5ab4dcc8e7c25b16d849ae79b"
 "checksum cc 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)" = "2b4911e4bdcb4100c7680e7e854ff38e23f1b34d4d9e079efae3da2801341ffc"
 "checksum cexpr 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "393a5f0088efbe41f9d1fcd062f24e83c278608420e62109feb2c8abee07de7d"
 "checksum cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de"
 "checksum chrono 0.2.25 (registry+https://github.com/rust-lang/crates.io-index)" = "9213f7cd7c27e95c2b57c49f0e69b1ea65b27138da84a170133fd21b07659c00"
-"checksum clang-sys 0.22.0 (registry+https://github.com/rust-lang/crates.io-index)" = "939a1a34310b120d26eba35c29475933128b0ec58e24b43327f8dbe6036fc538"
+"checksum clang-sys 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d7f7c04e52c35222fffcc3a115b5daf5f7e2bfb71c13c4e2321afe1fc71859c2"
 "checksum clap 2.31.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f0f16b89cbb9ee36d87483dc939fe9f1e13c05898d56d7b230a0d4dff033a536"
 "checksum cmake 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)" = "56d741ea7a69e577f6d06b36b7dff4738f680593dc27a701ffa8506b73ce28bb"
 "checksum cookie 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "746858cae4eae40fff37e1998320068df317bc247dc91a67c6cfa053afdc2abb"
 "checksum core-foundation 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "286e0b41c3a20da26536c6000a280585d519fd07b3956b43aed8a79e9edce980"
 "checksum core-foundation 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c7caa6cb9e76ddddbea09a03266d6b3bc98cd41e9fb9b017c473e7cca593ec25"
 "checksum core-foundation-sys 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "716c271e8613ace48344f723b60b900a93150271e5be206212d052bbc0883efa"
 "checksum core-foundation-sys 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b2a53cce0ddcf7e7e1f998738d757d5a3bf08bf799a180e50ebe50d298f52f5a"
 "checksum core-graphics 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fb0ed45fdc32f9ab426238fba9407dfead7bacd7900c9b4dd3f396f46eafdae3"
@@ -2668,17 +2669,17 @@ dependencies = [
 "checksum phf 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "cb325642290f28ee14d8c6201159949a872f220c62af6e110a56ea914fbe42fc"
 "checksum phf_codegen 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "d62594c0bb54c464f633175d502038177e90309daf2e0158be42ed5f023ce88f"
 "checksum phf_generator 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "6b07ffcc532ccc85e3afc45865469bf5d9e4ef5bfcf9622e3cfe80c2d275ec03"
 "checksum phf_shared 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "07e24b0ca9643bdecd0632f2b3da6b1b89bbb0030e0b992afc1113b23a7bc2f2"
 "checksum pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "3a8b4c6b8165cd1a1cd4b9b120978131389f64bdaf456435caa41e630edba903"
 "checksum plane-split 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7079b8485b4f9d9560dee7a69ca8f6ca781f9f284ff9d2bf27255d440b03e4af"
 "checksum podio 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e5422a1ee1bc57cc47ae717b0137314258138f38fd5f3cea083f43a9725383a0"
 "checksum precomputed-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c"
-"checksum proc-macro2 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "49b6a521dc81b643e9a51e0d1cf05df46d5a2f3c0280ea72bcb68276ba64a118"
+"checksum proc-macro2 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "77997c53ae6edd6d187fec07ec41b207063b5ee6f33680e9fa86d405cdd313d4"
 "checksum proc-macro2 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "effdb53b25cdad54f8f48843d67398f7ef2e14f12c1b4cb4effc549a6462a4d6"
 "checksum procedural-masquerade 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9f566249236c6ca4340f7ca78968271f0ed2b0f234007a61b66f9ecd0af09260"
 "checksum quick-error 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eda5fe9b71976e62bc81b781206aaa076401769b2143379d3eb2118388babac4"
 "checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a"
 "checksum quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9949cfe66888ffe1d53e6ec9d9f3b70714083854be20fd5e271b232a017401e8"
 "checksum quote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e44651a0dc4cdd99f71c83b561e221f714912d11af1a4dff0631f923d53af035"
 "checksum rand 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)" = "6475140dfd8655aeb72e1fd4b7a1cc1c202be65d71669476e392fe62532b9edd"
 "checksum rayon 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "485541959c8ecc49865526fe6c4de9653dd6e60d829d6edf0be228167b60372d"
--- a/dom/base/nsContentUtils.cpp
+++ b/dom/base/nsContentUtils.cpp
@@ -557,45 +557,16 @@ class SameOriginCheckerImpl final : publ
 
   NS_DECL_ISUPPORTS
   NS_DECL_NSICHANNELEVENTSINK
   NS_DECL_NSIINTERFACEREQUESTOR
 };
 
 } // namespace
 
-class nsContentUtils::nsContentUtilsReporter final : public nsIMemoryReporter
-{
-  MOZ_DEFINE_MALLOC_SIZE_OF(MallocSizeOf);
-
-  ~nsContentUtilsReporter() = default;
-
-public:
-  NS_DECL_ISUPPORTS
-
-  NS_IMETHOD
-  CollectReports(nsIHandleReportCallback* aHandleReport,
-                 nsISupports* aData, bool aAnonymize) override
-  {
-    int64_t amt = 0;
-    for (int32_t i = 0; i < PropertiesFile_COUNT; ++i) {
-      if (sStringBundles[i]) {
-        amt += sStringBundles[i]->SizeOfIncludingThisIfUnshared(MallocSizeOf);
-      }
-    }
-
-    MOZ_COLLECT_REPORT("explicit/dom/content-utils-string-bundles", KIND_HEAP, UNITS_BYTES,
-                       amt, "string-bundles in ContentUtils");
-
-    return NS_OK;
-  }
-};
-
-NS_IMPL_ISUPPORTS(nsContentUtils::nsContentUtilsReporter, nsIMemoryReporter)
-
 /**
  * This class is used to determine whether or not the user is currently
  * interacting with the browser. It listens to observer events to toggle the
  * value of the sUserActive static.
  *
  * This class is an internal implementation detail.
  * nsContentUtils::GetUserIsInteracting() should be used to access current
  * user interaction status.
@@ -686,17 +657,16 @@ nsContentUtils::Init()
       EventListenerManagerHashClearEntry,
       EventListenerManagerHashInitEntry
     };
 
     sEventListenerManagersHash =
       new PLDHashTable(&hash_table_ops, sizeof(EventListenerManagerMapEntry));
 
     RegisterStrongMemoryReporter(new DOMEventListenerManagersHashReporter());
-    RegisterStrongMemoryReporter(new nsContentUtilsReporter());
   }
 
   sBlockedScriptRunners = new AutoTArray<nsCOMPtr<nsIRunnable>, 8>;
 
   Preferences::AddBoolVarCache(&sAllowXULXBL_for_file,
                                "dom.allow_XUL_XBL_for_file");
 
   Preferences::AddBoolVarCache(&sIsFullScreenApiEnabled,
@@ -3915,16 +3885,18 @@ nsContentUtils::GetEventArgNames(int32_t
     SET_EVENT_ARG_NAMES(gOnErrorNames);
   } else if (aNameSpaceID == kNameSpaceID_SVG) {
     SET_EVENT_ARG_NAMES(gSVGEventNames);
   } else {
     SET_EVENT_ARG_NAMES(gEventNames);
   }
 }
 
+// Note: The list of content bundles in nsStringBundle.cpp should be updated
+// whenever entries are added or removed from this list.
 static const char gPropertiesFiles[nsContentUtils::PropertiesFile_COUNT][56] = {
   // Must line up with the enum values in |PropertiesFile| enum.
   "chrome://global/locale/css.properties",
   "chrome://global/locale/xbl.properties",
   "chrome://global/locale/xul.properties",
   "chrome://global/locale/layout_errors.properties",
   "chrome://global/locale/layout/HtmlForm.properties",
   "chrome://global/locale/printing.properties",
@@ -3955,16 +3927,28 @@ nsContentUtils::EnsureStringBundle(Prope
   }
   return NS_OK;
 }
 
 /* static */
 void
 nsContentUtils::AsyncPrecreateStringBundles()
 {
+  // We only ever want to pre-create bundles in the parent process.
+  //
+  // All nsContentUtils bundles are shared between the parent and child
+  // precesses, and the shared memory regions that back them *must* be created
+  // in the parent, and then sent to all children.
+  //
+  // If we attempt to create a bundle in the child before its memory region is
+  // available, we need to create a temporary non-shared bundle, and later
+  // replace that with the shared memory copy. So attempting to pre-load in the
+  // child is wasteful and unnecessary.
+  MOZ_ASSERT(XRE_IsParentProcess());
+
   for (uint32_t bundleIndex = 0; bundleIndex < PropertiesFile_COUNT; ++bundleIndex) {
     nsresult rv = NS_IdleDispatchToCurrentThread(
       NS_NewRunnableFunction("AsyncPrecreateStringBundles",
                              [bundleIndex]() {
                                PropertiesFile file = static_cast<PropertiesFile>(bundleIndex);
                                EnsureStringBundle(file);
                                nsIStringBundle *bundle = sStringBundles[file];
                                bundle->AsyncPreload();
--- a/dom/ipc/ContentChild.cpp
+++ b/dom/ipc/ContentChild.cpp
@@ -80,16 +80,17 @@
 #include "mozilla/media/MediaChild.h"
 #include "mozilla/BasePrincipal.h"
 #include "mozilla/WebBrowserPersistDocumentChild.h"
 #include "mozilla/HangDetails.h"
 #include "imgLoader.h"
 #include "GMPServiceChild.h"
 #include "NullPrincipal.h"
 #include "nsISimpleEnumerator.h"
+#include "nsIStringBundle.h"
 #include "nsIWorkerDebuggerManager.h"
 
 #if !defined(XP_WIN)
 #include "mozilla/Omnijar.h"
 #endif
 
 #ifdef MOZ_GECKO_PROFILER
 #include "ChildProfilerController.h"
@@ -2257,21 +2258,16 @@ ContentChild::RecvRegisterChrome(Infalli
                                  const nsCString& locale,
                                  const bool& reset)
 {
   nsCOMPtr<nsIChromeRegistry> registrySvc = nsChromeRegistry::GetService();
   nsChromeRegistryContent* chromeRegistry =
     static_cast<nsChromeRegistryContent*>(registrySvc.get());
   chromeRegistry->RegisterRemoteChrome(packages, resources, overrides,
                                        locale, reset);
-  static bool preloadDone = false;
-  if (!preloadDone) {
-    preloadDone = true;
-    nsContentUtils::AsyncPrecreateStringBundles();
-  }
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult
 ContentChild::RecvRegisterChromeItem(const ChromeRegistryItem& item)
 {
   nsCOMPtr<nsIChromeRegistry> registrySvc = nsChromeRegistry::GetService();
   nsChromeRegistryContent* chromeRegistry =
@@ -2532,16 +2528,30 @@ ContentChild::RecvAsyncMessage(const nsS
     ipc::UnpackClonedMessageDataForChild(aData, data);
     cpm->ReceiveMessage(cpm, nullptr, aMsg, false, &data, &cpows, aPrincipal, nullptr,
                         IgnoreErrors());
   }
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult
+ContentChild::RecvRegisterStringBundles(nsTArray<mozilla::dom::StringBundleDescriptor>&& aDescriptors)
+{
+  nsCOMPtr<nsIStringBundleService> stringBundleService =
+    services::GetStringBundleService();
+
+  for (auto& descriptor : aDescriptors) {
+    stringBundleService->RegisterContentBundle(descriptor.bundleURL(), descriptor.mapFile(),
+                                               descriptor.mapSize());
+  }
+
+  return IPC_OK();
+}
+
+mozilla::ipc::IPCResult
 ContentChild::RecvGeolocationUpdate(nsIDOMGeoPosition* aPosition)
 {
   nsCOMPtr<nsIGeolocationUpdate> gs =
     do_GetService("@mozilla.org/geolocation/service;1");
   if (!gs) {
     return IPC_OK();
   }
   gs->Update(aPosition);
--- a/dom/ipc/ContentChild.h
+++ b/dom/ipc/ContentChild.h
@@ -389,16 +389,18 @@ public:
 
   virtual mozilla::ipc::IPCResult RecvLoadProcessScript(const nsString& aURL) override;
 
   virtual mozilla::ipc::IPCResult RecvAsyncMessage(const nsString& aMsg,
                                                    InfallibleTArray<CpowEntry>&& aCpows,
                                                    const IPC::Principal& aPrincipal,
                                                    const ClonedMessageData& aData) override;
 
+  mozilla::ipc::IPCResult RecvRegisterStringBundles(nsTArray<StringBundleDescriptor>&& stringBundles) override;
+
   virtual mozilla::ipc::IPCResult RecvGeolocationUpdate(nsIDOMGeoPosition* aPosition) override;
 
   virtual mozilla::ipc::IPCResult RecvGeolocationError(const uint16_t& errorCode) override;
 
   virtual mozilla::ipc::IPCResult RecvUpdateDictionaryList(InfallibleTArray<nsString>&& aDictionaries) override;
 
   virtual mozilla::ipc::IPCResult RecvUpdateFontList(InfallibleTArray<SystemFontListEntry>&& aFontList) override;
 
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -141,16 +141,17 @@
 #include "nsIParentChannel.h"
 #include "nsIPresShell.h"
 #include "nsIRemoteWindowContext.h"
 #include "nsIScriptError.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsISiteSecurityService.h"
 #include "nsISound.h"
 #include "nsISpellChecker.h"
+#include "nsIStringBundle.h"
 #include "nsISupportsPrimitives.h"
 #include "nsITimer.h"
 #include "nsIURIFixup.h"
 #include "nsIURL.h"
 #include "nsIDocShellTreeOwner.h"
 #include "nsIXULWindow.h"
 #include "nsIDOMChromeWindow.h"
 #include "nsIWindowWatcher.h"
@@ -1272,16 +1273,27 @@ ContentParent::GetAllEvenIfDead(nsTArray
 {
   aArray.Clear();
 
   for (auto* cp : AllProcesses(eAll)) {
     aArray.AppendElement(cp);
   }
 }
 
+void
+ContentParent::BroadcastStringBundle(const StringBundleDescriptor& aBundle)
+{
+  AutoTArray<StringBundleDescriptor, 1> array;
+  array.AppendElement(aBundle);
+
+  for (auto* cp : AllProcesses(eLive)) {
+    Unused << cp->SendRegisterStringBundles(array);
+  }
+}
+
 const nsAString&
 ContentParent::GetRemoteType() const
 {
   return mRemoteType;
 }
 
 void
 ContentParent::Init()
@@ -2312,16 +2324,20 @@ ContentParent::InitInternal(ProcessPrior
   Unused << SendSetXPCOMProcessAttributes(xpcomInit, initialData, lnfCache,
                                           fontList);
 
   nsCOMPtr<nsIChromeRegistry> registrySvc = nsChromeRegistry::GetService();
   nsChromeRegistryChrome* chromeRegistry =
     static_cast<nsChromeRegistryChrome*>(registrySvc.get());
   chromeRegistry->SendRegisteredChrome(this);
 
+  nsCOMPtr<nsIStringBundleService> stringBundleService =
+    services::GetStringBundleService();
+  stringBundleService->SendContentBundles(this);
+
   if (gAppData) {
     nsCString version(gAppData->version);
     nsCString buildID(gAppData->buildID);
     nsCString name(gAppData->name);
     nsCString UAName(gAppData->UAName);
     nsCString ID(gAppData->ID);
     nsCString vendor(gAppData->vendor);
     nsCString sourceURL(gAppData->sourceURL);
--- a/dom/ipc/ContentParent.h
+++ b/dom/ipc/ContentParent.h
@@ -199,16 +199,18 @@ public:
                 ContentParent* aOpenerContentParent,
                 TabParent* aSameTabGroupAs,
                 uint64_t aNextTabParentId);
 
   static void GetAll(nsTArray<ContentParent*>& aArray);
 
   static void GetAllEvenIfDead(nsTArray<ContentParent*>& aArray);
 
+  static void BroadcastStringBundle(const StringBundleDescriptor&);
+
   const nsAString& GetRemoteType() const;
 
   virtual void DoGetRemoteType(nsAString& aRemoteType, ErrorResult& aError) const override
   {
     aRemoteType = GetRemoteType();
   }
 
   enum CPIteratorPolicy {
new file mode 100644
--- /dev/null
+++ b/dom/ipc/MemMapSnapshot.cpp
@@ -0,0 +1,129 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* vim: set ts=8 sts=4 et sw=4 tw=99: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "MemMapSnapshot.h"
+
+#include "base/eintr_wrapper.h"
+#include "base/file_util.h"
+#include "mozilla/ResultExtensions.h"
+#include "mozilla/ScopeExit.h"
+#include "mozilla/ipc/FileDescriptorUtils.h"
+#include "nsIFile.h"
+
+#ifdef XP_UNIX
+#  include <sys/stat.h>
+#endif
+
+namespace mozilla {
+
+using loader::AutoMemMap;
+
+namespace ipc {
+
+Result<Ok, nsresult>
+MemMapSnapshot::Init(size_t aSize)
+{
+  MOZ_ASSERT(!mInitialized);
+
+  MOZ_TRY(Create(aSize));
+
+  mInitialized = true;
+  return Ok();
+}
+
+Result<Ok, nsresult>
+MemMapSnapshot::Finalize(AutoMemMap& aMem)
+{
+  MOZ_ASSERT(mInitialized);
+
+  MOZ_TRY(Freeze(aMem));
+
+  mInitialized = false;
+  return Ok();
+}
+
+#if defined(XP_WIN)
+
+Result<Ok, nsresult>
+MemMapSnapshot::Create(size_t aSize)
+{
+  HANDLE handle = CreateFileMapping(
+      INVALID_HANDLE_VALUE, nullptr, PAGE_READWRITE,
+      0, DWORD(aSize), nullptr);
+
+  if (!handle) {
+    return Err(NS_ERROR_FAILURE);
+  }
+
+  mFile.emplace(handle);
+  return mMem.initWithHandle(mFile.ref(), aSize, PR_PROT_READWRITE);
+}
+
+Result<Ok, nsresult>
+MemMapSnapshot::Freeze(AutoMemMap& aMem)
+{
+  auto orig = mFile.ref().ClonePlatformHandle();
+  mFile.reset();
+
+  HANDLE handle;
+  if (!::DuplicateHandle(GetCurrentProcess(), orig.release(), GetCurrentProcess(),
+                         &handle, GENERIC_READ | FILE_MAP_READ,
+                         false, DUPLICATE_CLOSE_SOURCE)) {
+    return Err(NS_ERROR_FAILURE);
+  }
+
+  return aMem.initWithHandle(FileDescriptor(handle), mMem.size());
+}
+
+#elif defined(XP_UNIX)
+
+Result<Ok, nsresult>
+MemMapSnapshot::Create(size_t aSize)
+{
+  FilePath path;
+  ScopedCloseFile fd(file_util::CreateAndOpenTemporaryShmemFile(&path));
+  if (!fd) {
+    return Err(NS_ERROR_FAILURE);
+  }
+
+  if (HANDLE_EINTR(ftruncate(fileno(fd), aSize)) != 0) {
+    return Err(NS_ERROR_FAILURE);
+  }
+
+  MOZ_TRY(mMem.init(FILEToFileDescriptor(fd), PR_PROT_READWRITE));
+
+  mPath.Assign(path.value().data(), path.value().length());
+  return Ok();
+}
+
+Result<Ok, nsresult>
+MemMapSnapshot::Freeze(AutoMemMap& aMem)
+{
+  // Delete the shm file after we're done here, whether we succeed or not. The
+  // open file descriptor will keep it alive until all remaining references
+  // are closed, at which point it will be automatically freed.
+  auto cleanup = MakeScopeExit([&]() {
+    PR_Delete(mPath.get());
+  });
+
+  // Make the shm file readonly. This doesn't make a difference in practice,
+  // since we open and share a read-only file descriptor, and then delete the
+  // file. But it doesn't hurt, either.
+  chmod(mPath.get(), 0400);
+
+  nsCOMPtr<nsIFile> file;
+  MOZ_TRY(NS_NewNativeLocalFile(mPath, /* followLinks = */ false,
+                                getter_AddRefs(file)));
+
+  return aMem.init(file);
+}
+
+#else
+#  error "Unsupported build configuration"
+#endif
+
+} // namespace ipc
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/dom/ipc/MemMapSnapshot.h
@@ -0,0 +1,64 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* vim: set ts=8 sts=4 et sw=4 tw=99: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef dom_ipc_MemMapSnapshot_h
+#define dom_ipc_MemMapSnapshot_h
+
+#include "AutoMemMap.h"
+#include "mozilla/Attributes.h"
+#include "mozilla/Maybe.h"
+#include "mozilla/RangedPtr.h"
+#include "mozilla/Result.h"
+#ifdef XP_WIN
+#  include "mozilla/ipc/FileDescriptor.h"
+#endif
+
+namespace mozilla {
+namespace ipc {
+
+/**
+ * A helper class for creating a read-only snapshot of memory-mapped data.
+ *
+ * The Init() method initializes a read-write memory mapped region of the given
+ * size, which can be initialized with arbitrary data. The Finalize() method
+ * remaps that region as read-only (and backs it with a read-only file
+ * descriptor), and initializes an AutoMemMap with the new contents.
+ *
+ * The file descriptor for the resulting AutoMemMap can be shared among
+ * processes, to safely access a shared, read-only copy of the data snapshot.
+ */
+class MOZ_RAII MemMapSnapshot
+{
+public:
+  Result<Ok, nsresult> Init(size_t aSize);
+  Result<Ok, nsresult> Finalize(loader::AutoMemMap& aMap);
+
+  template<typename T = void>
+  RangedPtr<T> Get()
+  {
+    MOZ_ASSERT(mInitialized);
+    return mMem.get<T>();
+  }
+
+private:
+  Result<Ok, nsresult> Create(size_t aSize);
+  Result<Ok, nsresult> Freeze(loader::AutoMemMap& aMem);
+
+  loader::AutoMemMap mMem;
+
+  bool mInitialized = false;
+
+#ifdef XP_WIN
+  Maybe<FileDescriptor> mFile;
+#else
+  nsCString mPath;
+#endif
+};
+
+} // ipc
+} // mozilla
+
+#endif // dom_ipc_MemMapSnapshot_h
--- a/dom/ipc/PContent.ipdl
+++ b/dom/ipc/PContent.ipdl
@@ -284,16 +284,23 @@ struct XPCOMInitData
     ContentDeviceData contentDeviceData;
     GfxInfoFeatureStatus[] gfxFeatureStatus;
     DataStorageEntry[] dataStorage;
     nsCString[] appLocales;
     nsCString[] requestedLocales;
     DynamicScalarDefinition[] dynamicScalarDefs;
 };
 
+struct StringBundleDescriptor
+{
+    nsCString bundleURL;
+    FileDescriptor mapFile;
+    uint32_t mapSize;
+};
+
 /**
  * The PContent protocol is a top-level protocol between the UI process
  * and a content process. There is exactly one PContentParent/PContentChild pair
  * for each content process.
  */
 nested(upto inside_cpow) sync protocol PContent
 {
     manages PBrowser;
@@ -452,16 +459,18 @@ child:
 
     async UpdateFontList(SystemFontListEntry[] fontList);
 
     async UpdateAppLocales(nsCString[] appLocales);
     async UpdateRequestedLocales(nsCString[] requestedLocales);
 
     async ClearSiteDataReloadNeeded(nsString origin);
 
+    async RegisterStringBundles(StringBundleDescriptor[] stringBundles);
+
     // nsIPermissionManager messages
     async AddPermission(Permission permission);
 
     async FlushMemory(nsString reason);
 
     async GarbageCollect();
     async CycleCollect();
     async UnlinkGhosts();
new file mode 100644
--- /dev/null
+++ b/dom/ipc/SharedStringMap.cpp
@@ -0,0 +1,158 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* vim: set ts=8 sts=4 et sw=4 tw=99: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "SharedStringMap.h"
+
+#include "MemMapSnapshot.h"
+#include "ScriptPreloader-inl.h"
+
+#include "mozilla/BinarySearch.h"
+#include "mozilla/ipc/FileDescriptor.h"
+
+using namespace mozilla::loader;
+
+namespace mozilla {
+
+using namespace ipc;
+
+namespace dom {
+namespace ipc {
+
+static inline size_t
+GetAlignmentOffset(size_t aOffset, size_t aAlign)
+{
+  auto mod = aOffset % aAlign;
+  return mod ? aAlign - mod : 0;
+}
+
+
+SharedStringMap::SharedStringMap(const FileDescriptor& aMapFile, size_t aMapSize)
+{
+  auto result = mMap.initWithHandle(aMapFile, aMapSize);
+  MOZ_RELEASE_ASSERT(result.isOk());
+  // We return literal nsStrings and nsCStrings pointing to the mapped data,
+  // which means that we may still have references to the mapped data even
+  // after this instance is destroyed. That means that we need to keep the
+  // mapping alive until process shutdown, in order to be safe.
+  mMap.setPersistent();
+}
+
+SharedStringMap::SharedStringMap(SharedStringMapBuilder&& aBuilder)
+{
+  auto result = aBuilder.Finalize(mMap);
+  MOZ_RELEASE_ASSERT(result.isOk());
+  mMap.setPersistent();
+}
+
+mozilla::ipc::FileDescriptor
+SharedStringMap::CloneFileDescriptor() const
+{
+  return mMap.cloneHandle();
+}
+
+bool
+SharedStringMap::Has(const nsCString& aKey)
+{
+  size_t index;
+  return Find(aKey, &index);
+}
+
+bool
+SharedStringMap::Get(const nsCString& aKey, nsAString& aValue)
+{
+  const auto& entries = Entries();
+
+  size_t index;
+  if (!Find(aKey, &index)) {
+    return false;
+  }
+
+  aValue.Assign(ValueTable().Get(entries[index].mValue));
+  return true;
+}
+
+bool
+SharedStringMap::Find(const nsCString& aKey, size_t* aIndex)
+{
+  const auto& keys = KeyTable();
+
+  return BinarySearchIf(Entries(), 0, EntryCount(),
+                        [&] (const Entry& aEntry) {
+                          return aKey.Compare(keys.GetBare(aEntry.mKey));
+                        },
+                        aIndex);
+}
+
+
+void
+SharedStringMapBuilder::Add(const nsCString& aKey, const nsString& aValue)
+{
+  mEntries.Put(aKey, {{mKeyTable.Add(aKey), aKey.Length()},
+                      {mValueTable.Add(aValue), aValue.Length()}});
+}
+
+Result<Ok, nsresult>
+SharedStringMapBuilder::Finalize(loader::AutoMemMap& aMap)
+{
+  using Header = SharedStringMap::Header;
+
+  MOZ_ASSERT(mEntries.Count() == mKeyTable.Count());
+
+  nsTArray<nsCString> keys(mEntries.Count());
+  for (auto iter = mEntries.Iter(); !iter.Done(); iter.Next()) {
+    keys.AppendElement(iter.Key());
+  }
+  keys.Sort();
+
+
+  Header header = {uint32_t(keys.Length())};
+
+  size_t offset = sizeof(header);
+  offset += GetAlignmentOffset(offset, alignof(Header));
+
+  offset += keys.Length() * sizeof(SharedStringMap::Entry);
+
+  header.mKeyStringsOffset = offset;
+  header.mKeyStringsSize = mKeyTable.Size();
+
+  offset += header.mKeyStringsSize;
+  offset += GetAlignmentOffset(offset, alignof(decltype(mValueTable)::ElemType));
+
+  header.mValueStringsOffset = offset;
+  header.mValueStringsSize = mValueTable.Size();
+
+  offset += header.mValueStringsSize;
+
+
+  MemMapSnapshot mem;
+  MOZ_TRY(mem.Init(offset));
+
+  auto headerPtr = mem.Get<Header>();
+  headerPtr[0] = header;
+
+  auto* entry = reinterpret_cast<Entry*>(&headerPtr[1]);
+  for (auto& key : keys) {
+    *entry++ = mEntries.Get(key);
+  }
+
+  auto ptr = mem.Get<uint8_t>();
+
+  mKeyTable.Write({ &ptr[header.mKeyStringsOffset],
+                    header.mKeyStringsSize });
+
+  mValueTable.Write({ &ptr[header.mValueStringsOffset],
+                      header.mValueStringsSize });
+
+  mKeyTable.Clear();
+  mValueTable.Clear();
+  mEntries.Clear();
+
+  return mem.Finalize(aMap);
+}
+
+} // ipc
+} // dom
+} // mozilla
new file mode 100644
--- /dev/null
+++ b/dom/ipc/SharedStringMap.h
@@ -0,0 +1,324 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* vim: set ts=8 sts=4 et sw=4 tw=99: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef dom_ipc_SharedStringMap_h
+#define dom_ipc_SharedStringMap_h
+
+#include "mozilla/AutoMemMap.h"
+#include "mozilla/Result.h"
+#include "mozilla/TypeTraits.h"
+#include "nsDataHashtable.h"
+
+namespace mozilla {
+namespace dom {
+namespace ipc {
+
+class SharedStringMapBuilder;
+
+/**
+ * This class provides a simple, read-only key-value string store, with all
+ * data packed into a single segment of memory, which can be shared between
+ * processes.
+ *
+ * Look-ups are performed by binary search of a static table in the mapped
+ * memory region, and all returned strings are literals which reference the
+ * mapped data. No copies are performed on instantiation or look-up.
+ *
+ * Important: The mapped memory created by this class is persistent. Once an
+ * instance has been initialized, the memory that it allocates can never be
+ * freed before process shutdown. Do not use it for short-lived mappings.
+ */
+class SharedStringMap
+{
+  using FileDescriptor = mozilla::ipc::FileDescriptor;
+
+public:
+  /**
+   * The header at the beginning of the shared memory region describing its
+   * layout. The layout of the shared memory is as follows:
+   *
+   * - Header:
+   *   A Header struct describing the contents of the rest of the memory region.
+   *
+   * - Optional alignment padding for Header[].
+   *
+   * - Entry[header.mEntryCount]:
+   *   An array of Entry structs, one for each entry in the map. Entries are
+   *   lexocographically sorted by key.
+   *
+   * - StringTable<nsCString>:
+   *   A region of flat, null-terminated C strings. Entry key strings are
+   *   encoded as character offsets into this region.
+   *
+   * - Optional alignment padding for char16_t[]
+   *
+   * - StringTable<nsString>:
+   *   A region of flat, null-terminated UTF-16 strings. Entry value strings are
+   *   encoded as character (*not* byte) offsets into this region.
+   */
+  struct Header {
+    // The number of entries in this map.
+    uint32_t mEntryCount;
+
+    // The raw byte offset of the beginning of the key string table, from the
+    // start of the shared memory region, and its size in bytes.
+    size_t mKeyStringsOffset;
+    size_t mKeyStringsSize;
+
+    // The raw byte offset of the beginning of the value string table, from the
+    // start of the shared memory region, and its size in bytes (*not*
+    // characters).
+    size_t mValueStringsOffset;
+    size_t mValueStringsSize;
+  };
+
+  /**
+   * Contains the character offset and character length of an entry in a string
+   * table. This may be used for either 8-bit or 16-bit strings, and is required
+   * to retrieve an entry from a string table.
+   */
+  struct StringEntry {
+    uint32_t mOffset;
+    uint32_t mLength;
+  };
+
+  /**
+   * Describes a value in the string map, as offsets into the key and value
+   * string tables.
+   */
+  struct Entry {
+    // The offset and size of the entry's UTF-8 key in the key string table.
+    StringEntry mKey;
+    // The offset and size of the entry's UTF-16 value in the value string table.
+    StringEntry mValue;
+  };
+
+  NS_INLINE_DECL_REFCOUNTING(SharedStringMap)
+
+  // Note: These constructors are infallible on the premise that this class
+  // is used primarily in cases where it is critical to platform
+  // functionality.
+  explicit SharedStringMap(const FileDescriptor&, size_t);
+  explicit SharedStringMap(SharedStringMapBuilder&&);
+
+  /**
+   * Searches for the given value in the map, and returns true if it exists.
+   */
+  bool Has(const nsCString& aKey);
+
+  /**
+   * Searches for the given value in the map, and, if it exists, returns true
+   * and places its value in aValue.
+   *
+   * The returned value is a literal string which references the mapped memory
+   * region.
+   */
+  bool Get(const nsCString& aKey, nsAString& aValue);
+
+private:
+  /**
+   * Searches for an entry for the given key. If found, returns true, and
+   * places its index in the entry array in aIndex.
+   */
+  bool Find(const nsCString& aKey, size_t* aIndex);
+
+public:
+  /**
+   * Returns the number of entries in the map.
+   */
+  uint32_t Count() const { return EntryCount(); }
+
+  /**
+   * Returns the string entry at the given index. Keys are guaranteed to be
+   * sorted lexographically.
+   *
+   * The given index *must* be less than the value returned by Count().
+   *
+   * The returned value is a literal string which references the mapped memory
+   * region.
+   */
+  nsCString GetKeyAt(uint32_t aIndex) const
+  {
+    MOZ_ASSERT(aIndex < Count());
+    return KeyTable().Get(Entries()[aIndex].mKey);
+  }
+
+  /**
+   * Returns the string value for the entry at the given index.
+   *
+   * The given index *must* be less than the value returned by Count().
+   *
+   * The returned value is a literal string which references the mapped memory
+   * region.
+   */
+  nsString GetValueAt(uint32_t aIndex) const
+  {
+    MOZ_ASSERT(aIndex < Count());
+    return ValueTable().Get(Entries()[aIndex].mValue);
+  }
+
+  /**
+   * Returns a copy of the read-only file descriptor which backs the shared
+   * memory region for this map. The file descriptor may be passed between
+   * processes, and used to construct new instances of SharedStringMap with
+   * the same data as this instance.
+   */
+  FileDescriptor CloneFileDescriptor() const;
+
+  size_t MapSize() const { return mMap.size(); }
+
+protected:
+  ~SharedStringMap() = default;
+
+private:
+  template <typename StringType>
+  class StringTable
+  {
+    using ElemType = decltype(DeclVal<StringType>()[0]);
+
+  public:
+    MOZ_IMPLICIT StringTable(const RangedPtr<uint8_t>& aBuffer)
+      : mBuffer(aBuffer.ReinterpretCast<ElemType>())
+    {
+      MOZ_ASSERT(uintptr_t(aBuffer.get()) % alignof(ElemType) == 0,
+                 "Got misalinged buffer");
+    }
+
+    StringType Get(const StringEntry& aEntry) const
+    {
+      StringType res;
+      res.AssignLiteral(GetBare(aEntry), aEntry.mLength);
+      return res;
+    }
+
+    const ElemType* GetBare(const StringEntry& aEntry) const
+    {
+      return &mBuffer[aEntry.mOffset];
+    }
+
+  private:
+    RangedPtr<ElemType> mBuffer;
+  };
+
+
+  // Type-safe getters for values in the shared memory region:
+  const Header& GetHeader() const
+  {
+    return mMap.get<Header>()[0];
+  }
+
+  RangedPtr<const Entry> Entries() const
+  {
+    return { reinterpret_cast<const Entry*>(&GetHeader() + 1),
+             EntryCount() };
+  }
+
+  uint32_t EntryCount() const
+  {
+    return GetHeader().mEntryCount;
+  }
+
+  StringTable<nsCString> KeyTable() const
+  {
+    auto& header = GetHeader();
+    return { { &mMap.get<uint8_t>()[header.mKeyStringsOffset],
+               header.mKeyStringsSize } };
+  }
+
+  StringTable<nsString> ValueTable() const
+  {
+    auto& header = GetHeader();
+    return { { &mMap.get<uint8_t>()[header.mValueStringsOffset],
+               header.mValueStringsSize } };
+  }
+
+
+  loader::AutoMemMap mMap;
+};
+
+/**
+ * A helper class which builds the contiguous look-up table used by
+ * SharedStringMap. Each key-value pair in the final map is added to the
+ * builder, before it is finalized and transformed into a snapshot.
+ */
+class MOZ_RAII SharedStringMapBuilder
+{
+public:
+  SharedStringMapBuilder() = default;
+
+  /**
+   * Adds a key-value pair to the map.
+   */
+  void Add(const nsCString& aKey, const nsString& aValue);
+
+  /**
+   * Finalizes the binary representation of the map, writes it to a shared
+   * memory region, and then initializes the given AutoMemMap with a reference
+   * to the read-only copy of it.
+   */
+  Result<Ok, nsresult> Finalize(loader::AutoMemMap& aMap);
+
+private:
+  template <typename KeyType, typename StringType>
+  class StringTableBuilder
+  {
+  public:
+    using ElemType = typename StringType::char_type;
+
+    uint32_t Add(const StringType& aKey)
+    {
+      auto entry = mEntries.LookupForAdd(aKey).OrInsert([&] () {
+        Entry newEntry { mSize, aKey };
+        mSize += aKey.Length() + 1;
+
+        return newEntry;
+      });
+
+      return entry.mOffset;
+    }
+
+    void Write(const RangedPtr<uint8_t>& aBuffer)
+    {
+      auto buffer = aBuffer.ReinterpretCast<ElemType>();
+
+      for (auto iter = mEntries.Iter(); !iter.Done(); iter.Next()) {
+        auto& entry = iter.Data();
+        memcpy(&buffer[entry.mOffset], entry.mValue.BeginReading(),
+               sizeof(ElemType) * (entry.mValue.Length() + 1));
+      }
+    }
+
+    uint32_t Count() const { return mEntries.Count(); }
+
+    uint32_t Size() const { return mSize * sizeof(ElemType); }
+
+    void Clear() { mEntries.Clear(); }
+
+  private:
+    struct Entry
+    {
+      uint32_t mOffset;
+      StringType mValue;
+    };
+
+    nsDataHashtable<KeyType, Entry> mEntries;
+    uint32_t mSize = 0;
+  };
+
+  using Entry = SharedStringMap::Entry;
+
+  StringTableBuilder<nsCStringHashKey, nsCString> mKeyTable;
+  StringTableBuilder<nsStringHashKey, nsString> mValueTable;
+
+  nsDataHashtable<nsCStringHashKey, Entry> mEntries;
+};
+
+} // ipc
+} // dom
+} // mozilla
+
+#endif // dom_ipc_SharedStringMap_h
+
--- a/dom/ipc/StructuredCloneData.cpp
+++ b/dom/ipc/StructuredCloneData.cpp
@@ -7,25 +7,29 @@
 #include "StructuredCloneData.h"
 
 #include "nsIMutable.h"
 #include "nsIXPConnect.h"
 
 #include "ipc/IPCMessageUtils.h"
 #include "mozilla/dom/BindingUtils.h"
 #include "mozilla/dom/BlobBinding.h"
+#include "mozilla/dom/DOMTypes.h"
+#include "mozilla/dom/File.h"
 #include "mozilla/dom/IPCBlobUtils.h"
-#include "mozilla/dom/File.h"
+#include "mozilla/ipc/BackgroundParent.h"
 #include "mozilla/ipc/IPCStreamUtils.h"
 #include "nsContentUtils.h"
 #include "nsJSEnvironment.h"
 #include "MainThreadUtils.h"
 #include "StructuredCloneTags.h"
 #include "jsapi.h"
 
+using namespace mozilla::ipc;
+
 namespace mozilla {
 namespace dom {
 namespace ipc {
 
 StructuredCloneData::StructuredCloneData()
   : StructuredCloneData(StructuredCloneHolder::TransferringSupported)
 {}
 
--- a/dom/ipc/moz.build
+++ b/dom/ipc/moz.build
@@ -10,16 +10,17 @@ with Files("**"):
 XPIDL_SOURCES += [
     'nsIHangReport.idl',
 ]
 
 XPIDL_MODULE = 'dom'
 
 EXPORTS.mozilla.dom.ipc += [
     'IdType.h',
+    'SharedStringMap.h',
     'StructuredCloneData.h',
 ]
 
 EXPORTS.mozilla.dom += [
     'CoalescedInputData.h',
     'CoalescedMouseData.h',
     'CoalescedWheelData.h',
     'ContentBridgeChild.h',
@@ -56,22 +57,24 @@ UNIFIED_SOURCES += [
     'ColorPickerParent.cpp',
     'ContentBridgeChild.cpp',
     'ContentBridgeParent.cpp',
     'ContentParent.cpp',
     'ContentProcess.cpp',
     'ContentProcessHost.cpp',
     'ContentProcessManager.cpp',
     'FilePickerParent.cpp',
+    'MemMapSnapshot.cpp',
     'MemoryReportRequest.cpp',
     'nsIContentChild.cpp',
     'nsIContentParent.cpp',
     'PermissionMessageUtils.cpp',
     'PreallocatedProcessManager.cpp',
     'ProcessPriorityManager.cpp',
+    'SharedStringMap.cpp',
     'StructuredCloneData.cpp',
     'TabChild.cpp',
     'TabContext.cpp',
     'TabMessageUtils.cpp',
     'TabParent.cpp',
     'URLClassifierParent.cpp',
 ]
 
@@ -127,16 +130,17 @@ LOCAL_INCLUDES += [
     '/dom/filesystem',
     '/dom/geolocation',
     '/dom/media/webspeech/synth/ipc',
     '/dom/security',
     '/extensions/cookie',
     '/extensions/spellcheck/src',
     '/gfx/2d',
     '/hal/sandbox',
+    '/js/xpconnect/loader',
     '/layout/base',
     '/media/webrtc',
     '/netwerk/base',
     '/toolkit/components/printingui/ipc',
     '/toolkit/crashreporter',
     '/toolkit/xre',
     '/uriloader/exthandler',
     '/widget',
--- a/dom/svg/SVGAngle.cpp
+++ b/dom/svg/SVGAngle.cpp
@@ -43,18 +43,18 @@ SVGAngle::Value() const
 void
 SVGAngle::SetValue(float aValue, ErrorResult& rv)
 {
   if (mType == AnimValue) {
     rv.Throw(NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR);
     return;
   }
   bool isBaseVal = mType == BaseValue;
-  mVal->SetBaseValue(aValue, isBaseVal ? mSVGElement.get() : nullptr,
-                     isBaseVal);
+  mVal->SetBaseValue(aValue, mVal->mBaseValUnit,
+                     isBaseVal ? mSVGElement.get() : nullptr, isBaseVal);
 }
 
 float
 SVGAngle::ValueInSpecifiedUnits() const
 {
   if (mType == AnimValue) {
     return mVal->mAnimVal;
   }
--- a/dom/svg/SVGMarkerElement.cpp
+++ b/dom/svg/SVGMarkerElement.cpp
@@ -177,17 +177,17 @@ void
 SVGMarkerElement::SetOrientToAngle(SVGAngle& angle, ErrorResult& rv)
 {
   float f = angle.Value();
   if (!IsFinite(f)) {
     rv.Throw(NS_ERROR_DOM_SVG_WRONG_TYPE_ERR);
     return;
   }
   mOrientType.SetBaseValue(SVG_MARKER_ORIENT_ANGLE);
-  mAngleAttributes[ORIENT].SetBaseValue(f, this, true);
+  mAngleAttributes[ORIENT].SetBaseValue(f, angle.UnitType(), this, true);
 }
 
 //----------------------------------------------------------------------
 // nsIContent methods
 
 NS_IMETHODIMP_(bool)
 SVGMarkerElement::IsAttributeMapped(const nsAtom* name) const
 {
@@ -217,24 +217,26 @@ SVGMarkerElement::ParseAttribute(int32_t
                                  const nsAString& aValue,
                                  nsIPrincipal* aMaybeScriptedPrincipal,
                                  nsAttrValue& aResult)
 {
   if (aNameSpaceID == kNameSpaceID_None && aName == nsGkAtoms::orient) {
     if (aValue.EqualsLiteral("auto")) {
       mOrientType.SetBaseValue(SVG_MARKER_ORIENT_AUTO);
       aResult.SetTo(aValue);
-      mAngleAttributes[ORIENT].SetBaseValue(0.f, this, false);
+      mAngleAttributes[ORIENT].SetBaseValue(0.f, SVG_ANGLETYPE_UNSPECIFIED,
+                                            this, false);
       return true;
     }
     if (aValue.EqualsLiteral("auto-start-reverse") &&
         MarkerImprovementsPrefEnabled()) {
       mOrientType.SetBaseValue(SVG_MARKER_ORIENT_AUTO_START_REVERSE);
       aResult.SetTo(aValue);
-      mAngleAttributes[ORIENT].SetBaseValue(0.f, this, false);
+      mAngleAttributes[ORIENT].SetBaseValue(0.f, SVG_ANGLETYPE_UNSPECIFIED,
+                                            this, false);
       return true;
     }
     mOrientType.SetBaseValue(SVG_MARKER_ORIENT_ANGLE);
   }
   return SVGMarkerElementBase::ParseAttribute(aNameSpaceID, aName,
                                               aValue,
                                               aMaybeScriptedPrincipal,
                                               aResult);
--- a/dom/svg/nsSVGAngle.cpp
+++ b/dom/svg/nsSVGAngle.cpp
@@ -158,20 +158,19 @@ nsSVGAngle::ConvertToSpecifiedUnits(uint
     return NS_OK;
 
   nsAttrValue emptyOrOldValue;
   if (aSVGElement) {
     emptyOrOldValue = aSVGElement->WillChangeAngle(mAttrEnum);
   }
 
   float valueInUserUnits = mBaseVal * GetDegreesPerUnit(mBaseValUnit);
-  mBaseValUnit = uint8_t(unitType);
   // Setting aDoSetAttr to false here will ensure we don't call
   // Will/DidChangeAngle a second time (and dispatch duplicate notifications).
-  SetBaseValue(valueInUserUnits, aSVGElement, false);
+  SetBaseValue(valueInUserUnits, unitType, aSVGElement, false);
 
   if (aSVGElement) {
     aSVGElement->DidChangeAngle(mAttrEnum, emptyOrOldValue);
   }
 
   return NS_OK;
 }
 
@@ -289,28 +288,30 @@ nsSVGAngle::GetBaseValueString(nsAString
 
 void
 nsSVGAngle::GetAnimValueString(nsAString & aValueAsString) const
 {
   GetValueString(aValueAsString, mAnimVal, mAnimValUnit);
 }
 
 void
-nsSVGAngle::SetBaseValue(float aValue, nsSVGElement *aSVGElement,
-                         bool aDoSetAttr)
+nsSVGAngle::SetBaseValue(float aValue, uint8_t aUnit,
+                         nsSVGElement *aSVGElement, bool aDoSetAttr)
 {
-  if (mBaseVal == aValue * GetDegreesPerUnit(mBaseValUnit)) {
+  float valueInSpecifiedUnits = aValue / GetDegreesPerUnit(aUnit);
+  if (aUnit == mBaseValUnit && mBaseVal == valueInSpecifiedUnits) {
     return;
   }
   nsAttrValue emptyOrOldValue;
   if (aSVGElement && aDoSetAttr) {
     emptyOrOldValue = aSVGElement->WillChangeAngle(mAttrEnum);
   }
 
-  mBaseVal = aValue / GetDegreesPerUnit(mBaseValUnit);
+  mBaseValUnit = aUnit;
+  mBaseVal = valueInSpecifiedUnits;
   if (!mIsAnimated) {
     mAnimVal = mBaseVal;
   }
   else {
     aSVGElement->AnimationNeedsResample();
   }
   if (aSVGElement && aDoSetAttr) {
     aSVGElement->DidChangeAngle(mAttrEnum, emptyOrOldValue);
--- a/dom/svg/nsSVGAngle.h
+++ b/dom/svg/nsSVGAngle.h
@@ -50,17 +50,18 @@ public:
   void GetBaseValueString(nsAString& aValue) const;
   void GetAnimValueString(nsAString& aValue) const;
 
   float GetBaseValue() const
     { return mBaseVal * GetDegreesPerUnit(mBaseValUnit); }
   float GetAnimValue() const
     { return mAnimVal * GetDegreesPerUnit(mAnimValUnit); }
 
-  void SetBaseValue(float aValue, nsSVGElement *aSVGElement, bool aDoSetAttr);
+  void SetBaseValue(float aValue, uint8_t aUnit, nsSVGElement *aSVGElement,
+                    bool aDoSetAttr);
   void SetAnimValue(float aValue, uint8_t aUnit, nsSVGElement *aSVGElement);
 
   uint8_t GetBaseValueUnit() const { return mBaseValUnit; }
   uint8_t GetAnimValueUnit() const { return mAnimValUnit; }
   float GetBaseValInSpecifiedUnits() const { return mBaseVal; }
   float GetAnimValInSpecifiedUnits() const { return mAnimVal; }
 
   static nsresult ToDOMSVGAngle(nsISupports **aResult);
--- a/intl/build/nsI18nModule.cpp
+++ b/intl/build/nsI18nModule.cpp
@@ -2,48 +2,43 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/ModuleUtils.h"
 
 // string bundles (intl)
 #include "nsStringBundleService.h"
-#include "nsStringBundleTextOverride.h"
 
 // locale
 #include "nsLocaleConstructors.h"
 
 // uconv
 
 NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsStringBundleService, Init)
-NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsStringBundleTextOverride, Init)
 
 NS_DEFINE_NAMED_CID(MOZ_LOCALESERVICE_CID);
 NS_DEFINE_NAMED_CID(MOZ_OSPREFERENCES_CID);
 NS_DEFINE_NAMED_CID(NS_STRINGBUNDLESERVICE_CID);
-NS_DEFINE_NAMED_CID(NS_STRINGBUNDLETEXTOVERRIDE_CID);
 NS_DEFINE_NAMED_CID(NS_COLLATIONFACTORY_CID);
 NS_DEFINE_NAMED_CID(NS_COLLATION_CID);
 
 static const mozilla::Module::CIDEntry kIntlCIDs[] = {
     { &kMOZ_LOCALESERVICE_CID, false, nullptr, mozilla::intl::LocaleServiceConstructor },
     { &kMOZ_OSPREFERENCES_CID, false, nullptr, mozilla::intl::OSPreferencesConstructor },
     { &kNS_STRINGBUNDLESERVICE_CID, false, nullptr, nsStringBundleServiceConstructor },
-    { &kNS_STRINGBUNDLETEXTOVERRIDE_CID, false, nullptr, nsStringBundleTextOverrideConstructor },
     { &kNS_COLLATIONFACTORY_CID, false, nullptr, nsCollationFactoryConstructor },
     { &kNS_COLLATION_CID, false, nullptr, nsCollationConstructor },
     { nullptr }
 };
 
 static const mozilla::Module::ContractIDEntry kIntlContracts[] = {
     { MOZ_LOCALESERVICE_CONTRACTID, &kMOZ_LOCALESERVICE_CID },
     { MOZ_OSPREFERENCES_CONTRACTID, &kMOZ_OSPREFERENCES_CID },
     { NS_STRINGBUNDLE_CONTRACTID, &kNS_STRINGBUNDLESERVICE_CID },
-    { NS_STRINGBUNDLETEXTOVERRIDE_CONTRACTID, &kNS_STRINGBUNDLETEXTOVERRIDE_CID },
     { NS_COLLATIONFACTORY_CONTRACTID, &kNS_COLLATIONFACTORY_CID },
     { NS_COLLATION_CONTRACTID, &kNS_COLLATION_CID },
     { nullptr }
 };
 
 static const mozilla::Module kIntlModule = {
     mozilla::Module::kVersion,
     kIntlCIDs,
--- a/intl/strres/moz.build
+++ b/intl/strres/moz.build
@@ -3,22 +3,26 @@
 # 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/.
 
 XPCSHELL_TESTS_MANIFESTS += ['tests/unit/xpcshell.ini']
 
 XPIDL_SOURCES += [
     'nsIStringBundle.idl',
-    'nsIStringBundleOverride.idl',
 ]
 
 XPIDL_MODULE = 'intl'
 
 UNIFIED_SOURCES += [
     'nsStringBundle.cpp',
-    'nsStringBundleTextOverride.cpp',
 ]
 
+LOCAL_INCLUDES += [
+    '/xpcom/ds',
+]
+
+include('/ipc/chromium/chromium-config.mozbuild')
+
 FINAL_LIBRARY = 'xul'
 
 if CONFIG['CC_TYPE'] in ('clang', 'gcc'):
     CXXFLAGS += ['-Wno-error=shadow']
--- a/intl/strres/nsIStringBundle.idl
+++ b/intl/strres/nsIStringBundle.idl
@@ -4,16 +4,25 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsISupports.idl"
 #include "nsISimpleEnumerator.idl"
 
 %{C++
 #include "mozilla/MemoryReporting.h"
 
+namespace mozilla {
+namespace dom {
+class ContentParent;
+}
+namespace ipc {
+class FileDescriptor;
+}
+}
+
 // Define Contractid and CID
 // {D85A17C1-AA7C-11d2-9B8C-00805F8A16D9}
 #define NS_STRINGBUNDLESERVICE_CID \
 { 0xd85a17c1, 0xaa7c, 0x11d2, \
   { 0x9b, 0x8c, 0x0, 0x80, 0x5f, 0x8a, 0x16, 0xd9 } }
 
 #define NS_STRINGBUNDLE_CONTRACTID "@mozilla.org/intl/stringbundle;1"
 
@@ -69,17 +78,16 @@ interface nsIStringBundle : nsISupports
   virtual size_t SizeOfIncludingThisIfUnshared(mozilla::MallocSizeOf aMallocSizeOf) const = 0;
 %}
 };
 
 [scriptable, uuid(D85A17C0-AA7C-11d2-9B8C-00805F8A16D9)]
 interface nsIStringBundleService : nsISupports
 {
   nsIStringBundle createBundle(in string aURLSpec);
-  nsIStringBundle createExtensibleBundle(in string aRegistryKey);
 
   /**
    * Formats a message string from a status code and status arguments.
    * @param aStatus - The status code. This is mapped into a string ID and
    *            and used in the string lookup process (see nsIErrorService).
    * @param aStatusArg - The status message argument(s). Multiple arguments
    *            can be separated by newline ('\n') characters.
    * @return the formatted message
@@ -94,10 +102,16 @@ interface nsIStringBundleService : nsISu
    * because any bundles that are floating around when the locale changes
    * will suddenly contain bad data
    *
    */
   void flushBundles();
 
   %{C++
     virtual size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const = 0;
+
+  virtual void SendContentBundles(mozilla::dom::ContentParent* aContentParent) const = 0;
+
+  virtual void RegisterContentBundle(const nsCString& aBundleURL,
+                                     const mozilla::ipc::FileDescriptor& aMapFile,
+                                     size_t aMapSize) = 0;
   %}
 };
deleted file mode 100644
--- a/intl/strres/nsIStringBundleOverride.idl
+++ /dev/null
@@ -1,33 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsISupports.idl"
-
-interface nsISimpleEnumerator;
-
-%{C++
-#include "mozilla/MemoryReporting.h"
-%}
-
-// to be implemented by an embeddor that wants to override some strings
-[scriptable, uuid(965eb278-5678-456b-82a7-20a0c86a803c)]
-interface nsIStringBundleOverride : nsISupports
-{
-  /**
-   * get the override value for a particular key in a particular
-   * string bundle
-   */
-  AString getStringFromName(in AUTF8String url,
-                            in ACString key);
-
-  /**
-   * get all override keys for a given string bundle
-   */
-  nsISimpleEnumerator enumerateKeysInBundle(in AUTF8String url);
-
-%{C++
-  virtual size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const = 0;
-%}
-};
--- a/intl/strres/nsStringBundle.cpp
+++ b/intl/strres/nsStringBundle.cpp
@@ -3,109 +3,465 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsStringBundle.h"
 #include "nsID.h"
 #include "nsString.h"
 #include "nsIStringBundle.h"
 #include "nsStringBundleService.h"
-#include "nsStringBundleTextOverride.h"
 #include "nsISupportsPrimitives.h"
 #include "nsIMutableArray.h"
 #include "nsArrayEnumerator.h"
 #include "nscore.h"
 #include "nsMemory.h"
 #include "nsNetUtil.h"
 #include "nsComponentManagerUtils.h"
 #include "nsServiceManagerUtils.h"
 #include "nsIInputStream.h"
 #include "nsIURI.h"
 #include "nsIObserverService.h"
 #include "nsCOMArray.h"
 #include "nsTextFormatter.h"
 #include "nsIErrorService.h"
 #include "nsICategoryManager.h"
 #include "nsContentUtils.h"
+#include "nsPersistentProperties.h"
+#include "nsQueryObject.h"
 #include "nsStringStream.h"
+#include "mozilla/BinarySearch.h"
 #include "mozilla/ResultExtensions.h"
 #include "mozilla/URLPreloader.h"
+#include "mozilla/ResultExtensions.h"
+#include "mozilla/dom/ContentParent.h"
+#include "mozilla/dom/ipc/SharedStringMap.h"
 
 // for async loading
 #ifdef ASYNC_LOADING
 #include "nsIBinaryInputStream.h"
 #include "nsIStringStream.h"
 #endif
 
 using namespace mozilla;
 
+using mozilla::dom::ContentParent;
+using mozilla::dom::StringBundleDescriptor;
+using mozilla::dom::ipc::SharedStringMap;
+using mozilla::dom::ipc::SharedStringMapBuilder;
+using mozilla::ipc::FileDescriptor;
+
 static NS_DEFINE_CID(kErrorServiceCID, NS_ERRORSERVICE_CID);
 
-NS_IMPL_ISUPPORTS(nsStringBundle, nsIStringBundle)
+/**
+ * A set of string bundle URLs which are loaded by content processes, and
+ * should be allocated in a shared memory region, and then sent to content
+ * processes.
+ *
+ * Note: This layout is chosen to avoid having to create a separate char*
+ * array pointing to the string constant values, which would require
+ * per-process relocations. The second array size is the length of the longest
+ * URL plus its null terminator. Shorter strings are null padded to this
+ * length.
+ *
+ * This should be kept in sync with the similar array in nsContentUtils.cpp,
+ * and updated with any other property files which need to be loaded in all
+ * content processes.
+ */
+static const char kContentBundles[][52] = {
+  "chrome://branding/locale/brand.properties",
+  "chrome://global/locale/commonDialogs.properties",
+  "chrome://global/locale/css.properties",
+  "chrome://global/locale/dom/dom.properties",
+  "chrome://global/locale/intl.properties",
+  "chrome://global/locale/layout/HtmlForm.properties",
+  "chrome://global/locale/layout/htmlparser.properties",
+  "chrome://global/locale/layout_errors.properties",
+  "chrome://global/locale/mathml/mathml.properties",
+  "chrome://global/locale/printing.properties",
+  "chrome://global/locale/security/csp.properties",
+  "chrome://global/locale/security/security.properties",
+  "chrome://global/locale/svg/svg.properties",
+  "chrome://global/locale/xbl.properties",
+  "chrome://global/locale/xul.properties",
+  "chrome://necko/locale/necko.properties",
+  "chrome://onboarding/locale/onboarding.properties",
+};
+
+static bool
+IsContentBundle(const nsCString& aUrl)
+{
+  size_t index;
+  return BinarySearchIf(kContentBundles, 0, MOZ_ARRAY_LENGTH(kContentBundles),
+                        [&] (const char* aElem) { return aUrl.Compare(aElem); },
+                        &index);
+}
+
+namespace {
+
+#define STRINGBUNDLEPROXY_IID \
+{ 0x537cf21b, 0x99fc, 0x4002, \
+  { 0x9e, 0xec, 0x97, 0xbe, 0x4d, 0xe0, 0xb3, 0xdc } }
+
+/**
+ * A simple proxy class for a string bundle instance which will be replaced by
+ * a different implementation later in the session.
+ *
+ * This is used when creating string bundles which should use shared memory,
+ * but the content process has not yet received their shared memory buffer.
+ * When the shared memory variant becomes available, this proxy is retarged to
+ * that instance, and the original non-shared instance is destroyed.
+ *
+ * At that point, the cache entry for the proxy is replaced with the shared
+ * memory instance, and callers which already have an instance of the proxy
+ * are redirected to the new instance.
+ */
+class StringBundleProxy : public nsIStringBundle
+{
+  NS_DECL_THREADSAFE_ISUPPORTS
+
+  NS_DECLARE_STATIC_IID_ACCESSOR(STRINGBUNDLEPROXY_IID)
+
+  explicit StringBundleProxy(already_AddRefed<nsIStringBundle> aTarget)
+    : mReentrantMonitor("StringBundleProxy::mReentrantMonitor")
+    , mTarget(aTarget)
+  {}
+
+  NS_FORWARD_NSISTRINGBUNDLE(Target()->);
+
+  void Retarget(nsIStringBundle* aTarget)
+  {
+    ReentrantMonitorAutoEnter automon(mReentrantMonitor);
+    mTarget = aTarget;
+  }
+
+  size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const override
+  {
+    return aMallocSizeOf(this);
+  }
+
+  size_t SizeOfIncludingThisIfUnshared(mozilla::MallocSizeOf aMallocSizeOf) const override
+  {
+    return mRefCnt == 1 ? SizeOfIncludingThis(aMallocSizeOf) : 0;
+  }
+
+protected:
+  virtual ~StringBundleProxy() = default;
+
+private:
+  ReentrantMonitor mReentrantMonitor;
+  nsCOMPtr<nsIStringBundle> mTarget;
+
+  // Atomically reads mTarget and returns a strong reference to it. This
+  // allows for safe multi-threaded use when the proxy may be retargetted by
+  // the main thread during access.
+  nsCOMPtr<nsIStringBundle> Target()
+  {
+    ReentrantMonitorAutoEnter automon(mReentrantMonitor);
+    return mTarget;
+  }
+};
+
+NS_DEFINE_STATIC_IID_ACCESSOR(StringBundleProxy, STRINGBUNDLEPROXY_IID)
+
+NS_IMPL_ISUPPORTS(StringBundleProxy, nsIStringBundle, StringBundleProxy)
+
+
+#define SHAREDSTRINGBUNDLE_IID \
+{ 0x7a8df5f7, 0x9e50, 0x44f6, \
+  { 0xbf, 0x89, 0xc7, 0xad, 0x6c, 0x17, 0xf8, 0x5f } }
 
-nsStringBundle::nsStringBundle(const char* aURLSpec,
-                               nsIStringBundleOverride* aOverrideStrings) :
+/**
+ * A string bundle backed by a read-only, shared memory buffer. This should
+ * only be used for string bundles which are used in child processes.
+ *
+ * Important: The memory allocated by these string bundles will never be freed
+ * before process shutdown, per the restrictions in SharedStringMap.h, so they
+ * should never be used for short-lived bundles.
+ */
+class SharedStringBundle final : public nsStringBundleBase
+{
+public:
+  /**
+   * Initialize the string bundle with a file descriptor pointing to a
+   * pre-populated key-value store for this string bundle. This should only be
+   * called in child processes, for bundles initially created in the parent
+   * process.
+   */
+  void SetMapFile(const FileDescriptor& aFile, size_t aSize);
+
+  NS_DECL_ISUPPORTS_INHERITED
+  NS_DECLARE_STATIC_IID_ACCESSOR(SHAREDSTRINGBUNDLE_IID)
+
+  nsresult LoadProperties() override;
+
+  /**
+   * Returns a copy of the file descriptor pointing to the shared memory
+   * key-values tore for this string bundle. This should only be called in the
+   * parent process, and may be used to send shared string bundles to child
+   * processes.
+   */
+  FileDescriptor CloneFileDescriptor() const
+  {
+    MOZ_ASSERT(XRE_IsParentProcess());
+    if (mMapFile.isSome()) {
+      return mMapFile.ref();
+    }
+    return mStringMap->CloneFileDescriptor();
+  }
+
+  size_t MapSize() const
+  {
+    if (mMapFile.isSome()) {
+      return mMapSize;
+    }
+    if (mStringMap) {
+      return mStringMap->MapSize();
+    }
+    return 0;
+  }
+
+  bool Initialized() const { return mStringMap || mMapFile.isSome(); }
+
+  StringBundleDescriptor GetDescriptor() const
+  {
+    MOZ_ASSERT(Initialized());
+
+    StringBundleDescriptor descriptor;
+    descriptor.bundleURL() = BundleURL();
+    descriptor.mapFile() = CloneFileDescriptor();
+    descriptor.mapSize() = MapSize();
+    return descriptor;
+  }
+
+  size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const override;
+
+  static SharedStringBundle* Cast(nsIStringBundle* aStringBundle)
+  {
+    return static_cast<SharedStringBundle*>(aStringBundle);
+  }
+
+protected:
+  friend class nsStringBundleBase;
+
+  explicit SharedStringBundle(const char* aURLSpec)
+    : nsStringBundleBase(aURLSpec)
+  {}
+
+  ~SharedStringBundle() override = default;
+
+  nsresult GetStringImpl(const nsACString& aName, nsAString& aResult) override;
+
+  nsresult GetSimpleEnumerationImpl(nsISimpleEnumerator** elements) override;
+
+private:
+  RefPtr<SharedStringMap> mStringMap;
+
+  Maybe<FileDescriptor> mMapFile;
+  size_t mMapSize;
+};
+
+NS_DEFINE_STATIC_IID_ACCESSOR(SharedStringBundle, SHAREDSTRINGBUNDLE_IID)
+
+
+class StringMapEnumerator final : public nsISimpleEnumerator
+{
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSISIMPLEENUMERATOR
+
+  explicit StringMapEnumerator(SharedStringMap* aStringMap)
+    : mStringMap(aStringMap)
+  {}
+
+protected:
+  virtual ~StringMapEnumerator() = default;
+
+private:
+  RefPtr<SharedStringMap> mStringMap;
+
+  uint32_t mIndex = 0;
+};
+
+NS_IMPL_ISUPPORTS(StringMapEnumerator, nsISimpleEnumerator)
+
+template <typename T, typename... Args>
+already_AddRefed<T>
+MakeBundle(Args... args)
+{
+  return nsStringBundleBase::Create<T>(args...);
+}
+
+template <typename T, typename... Args>
+RefPtr<T>
+MakeBundleRefPtr(Args... args)
+{
+  return nsStringBundleBase::Create<T>(args...);
+}
+
+} // anonymous namespace
+
+NS_IMPL_ISUPPORTS(nsStringBundleBase, nsIStringBundle, nsIMemoryReporter)
+
+NS_IMPL_ISUPPORTS_INHERITED0(nsStringBundle, nsStringBundleBase)
+NS_IMPL_ISUPPORTS_INHERITED(SharedStringBundle, nsStringBundleBase, SharedStringBundle)
+
+nsStringBundleBase::nsStringBundleBase(const char* aURLSpec) :
   mPropertiesURL(aURLSpec),
-  mOverrideStrings(aOverrideStrings),
   mReentrantMonitor("nsStringBundle.mReentrantMonitor"),
   mAttemptedLoad(false),
   mLoaded(false)
 {
 }
 
+nsStringBundleBase::~nsStringBundleBase()
+{
+  UnregisterWeakMemoryReporter(this);
+}
+
+void
+nsStringBundleBase::RegisterMemoryReporter()
+{
+  RegisterWeakMemoryReporter(this);
+}
+
+template <typename T, typename... Args>
+/* static */ already_AddRefed<T>
+nsStringBundleBase::Create(Args... args)
+{
+  RefPtr<T> bundle = new T(args...);
+  bundle->RegisterMemoryReporter();
+  return bundle.forget();
+}
+
+nsStringBundle::nsStringBundle(const char* aURLSpec)
+  : nsStringBundleBase(aURLSpec)
+{}
+
 nsStringBundle::~nsStringBundle()
 {
 }
 
 NS_IMETHODIMP
-nsStringBundle::AsyncPreload()
+nsStringBundleBase::AsyncPreload()
 {
   return NS_IdleDispatchToCurrentThread(
-    NewIdleRunnableMethod("nsStringBundle::LoadProperties",
+    NewIdleRunnableMethod("nsStringBundleBase::LoadProperties",
                           this,
-                          &nsStringBundle::LoadProperties));
+                          &nsStringBundleBase::LoadProperties));
 }
 
 size_t
-nsStringBundle::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
+nsStringBundle::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
 {
   size_t n = 0;
   if (mProps) {
     n += mProps->SizeOfIncludingThis(aMallocSizeOf);
   }
-  if (mOverrideStrings) {
-    n += mOverrideStrings->SizeOfIncludingThis(aMallocSizeOf);
-  }
   return aMallocSizeOf(this) + n;
 }
 
 size_t
-nsStringBundle::SizeOfIncludingThisIfUnshared(MallocSizeOf aMallocSizeOf) const
+nsStringBundleBase::SizeOfIncludingThisIfUnshared(mozilla::MallocSizeOf aMallocSizeOf) const
 {
   if (mRefCnt == 1) {
     return SizeOfIncludingThis(aMallocSizeOf);
   } else {
     return 0;
   }
 }
 
+size_t
+SharedStringBundle::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
+{
+  size_t n = 0;
+  if (mStringMap) {
+    n += aMallocSizeOf(mStringMap);
+  }
+  return aMallocSizeOf(this) + n;
+}
+
+NS_IMETHODIMP
+nsStringBundleBase::CollectReports(nsIHandleReportCallback* aHandleReport,
+                                   nsISupports* aData,
+                                   bool aAnonymize)
+{
+  // String bundle URLs are always local, and part of the distribution.
+  // There's no need to anonymize.
+  nsAutoCStringN<64> escapedURL(mPropertiesURL);
+  escapedURL.ReplaceChar('/', '\\');
+
+  size_t sharedSize = 0;
+  size_t heapSize = SizeOfIncludingThis(MallocSizeOf);
+
+  nsAutoCStringN<256> path("explicit/string-bundles/");
+  if (RefPtr<SharedStringBundle> shared = do_QueryObject(this)) {
+    path.AppendLiteral("SharedStringBundle");
+    if (XRE_IsParentProcess()) {
+      sharedSize = shared->MapSize();
+    }
+  } else {
+    path.AppendLiteral("nsStringBundle");
+  }
+
+  path.AppendLiteral("(url=\"");
+  path.Append(escapedURL);
+
+  // Note: The memory reporter service holds a strong reference to reporters
+  // while collecting reports, so we want to ignore the extra ref in reports.
+  path.AppendLiteral("\", shared=");
+  path.AppendASCII(mRefCnt > 2 ? "true" : "false");
+  path.AppendLiteral(", refCount=");
+  path.AppendInt(uint32_t(mRefCnt - 1));
+
+  if (sharedSize) {
+    path.AppendLiteral(", sharedMemorySize=");
+    path.AppendInt(uint32_t(sharedSize));
+  }
+
+  path.AppendLiteral(")");
+
+  NS_NAMED_LITERAL_CSTRING(
+      desc,
+      "A StringBundle instance representing the data in a (probably "
+      "localized) .properties file. Data may be shared between "
+      "processes.");
+
+  aHandleReport->Callback(
+    EmptyCString(), path, KIND_HEAP, UNITS_BYTES,
+    heapSize, desc, aData);
+
+  if (sharedSize) {
+    path.ReplaceLiteral(0, sizeof("explicit/") - 1,
+                        "shared-");
+
+    aHandleReport->Callback(
+      EmptyCString(), path, KIND_OTHER, UNITS_BYTES,
+      sharedSize, desc, aData);
+  }
+
+  return NS_OK;
+}
+
 nsresult
-nsStringBundle::LoadProperties()
+nsStringBundleBase::ParseProperties(nsIPersistentProperties** aProps)
 {
   // this is different than mLoaded, because we only want to attempt
   // to load once
   // we only want to load once, but if we've tried once and failed,
   // continue to throw an error!
   if (mAttemptedLoad) {
     if (mLoaded)
       return NS_OK;
 
     return NS_ERROR_UNEXPECTED;
   }
 
+  MOZ_ASSERT(NS_IsMainThread(),
+             "String bundles must be initialized on the main thread "
+             "before they may be used off-main-thread");
+
   mAttemptedLoad = true;
 
   nsresult rv;
 
   // do it synchronously
   nsCOMPtr<nsIURI> uri;
   rv = NS_NewURI(getter_AddRefs(uri), mPropertiesURL);
   if (NS_FAILED(rv)) return rv;
@@ -136,190 +492,232 @@ nsStringBundle::LoadProperties()
 
     // It's a string bundle.  We expect a text/plain type, so set that as hint
     channel->SetContentType(NS_LITERAL_CSTRING("text/plain"));
 
     rv = channel->Open2(getter_AddRefs(in));
     if (NS_FAILED(rv)) return rv;
   }
 
-  NS_ASSERTION(NS_SUCCEEDED(rv) && in, "Error in OpenBlockingStream");
-  NS_ENSURE_TRUE(NS_SUCCEEDED(rv) && in, NS_ERROR_FAILURE);
+  auto props = MakeRefPtr<nsPersistentProperties>();
 
-  static NS_DEFINE_CID(kPersistentPropertiesCID, NS_IPERSISTENTPROPERTIES_CID);
-  mProps = do_CreateInstance(kPersistentPropertiesCID, &rv);
-  NS_ENSURE_SUCCESS(rv, rv);
+  mAttemptedLoad = true;
+
+  MOZ_TRY(props->Load(in));
+  props.forget(aProps);
 
-  mAttemptedLoad = mLoaded = true;
-  rv = mProps->Load(in);
+  mLoaded = true;
+  return NS_OK;
+}
 
-  mLoaded = NS_SUCCEEDED(rv);
-
-  return rv;
+nsresult
+nsStringBundle::LoadProperties()
+{
+  if (mProps) {
+    return NS_OK;
+  }
+  return ParseProperties(getter_AddRefs(mProps));
 }
 
+nsresult
+SharedStringBundle::LoadProperties()
+{
+  if (mStringMap)
+    return NS_OK;
+
+  if (mMapFile.isSome()) {
+    mStringMap = new SharedStringMap(mMapFile.ref(), mMapSize);
+    mMapFile.reset();
+    return NS_OK;
+  }
+
+  // We should only populate shared memory string bundles in the parent
+  // process. Instances in the child process should always be instantiated
+  // with a shared memory file descriptor sent from the parent.
+  MOZ_ASSERT(XRE_IsParentProcess());
+
+  nsCOMPtr<nsIPersistentProperties> props;
+  MOZ_TRY(ParseProperties(getter_AddRefs(props)));
+
+  SharedStringMapBuilder builder;
+
+  nsCOMPtr<nsISimpleEnumerator> iter;
+  MOZ_TRY(props->Enumerate(getter_AddRefs(iter)));
+  bool hasMore;
+  while (NS_SUCCEEDED(iter->HasMoreElements(&hasMore)) && hasMore) {
+    nsCOMPtr<nsISupports> next;
+    MOZ_TRY(iter->GetNext(getter_AddRefs(next)));
+
+    nsresult rv;
+    nsCOMPtr<nsIPropertyElement> elem = do_QueryInterface(next, &rv);
+    MOZ_TRY(rv);
+
+    nsCString key;
+    nsString value;
+    MOZ_TRY(elem->GetKey(key));
+    MOZ_TRY(elem->GetValue(value));
+
+    builder.Add(key, value);
+  }
+
+  mStringMap = new SharedStringMap(std::move(builder));
+
+  ContentParent::BroadcastStringBundle(GetDescriptor());
+
+  return NS_OK;
+}
+
+void
+SharedStringBundle::SetMapFile(const FileDescriptor& aFile, size_t aSize)
+{
+  MOZ_ASSERT(XRE_IsContentProcess());
+  mStringMap = nullptr;
+  mMapFile.emplace(aFile);
+  mMapSize = aSize;
+}
+
+
 NS_IMETHODIMP
-nsStringBundle::GetStringFromID(int32_t aID, nsAString& aResult)
+nsStringBundleBase::GetStringFromID(int32_t aID, nsAString& aResult)
 {
   nsAutoCString idStr;
   idStr.AppendInt(aID, 10);
   return GetStringFromName(idStr.get(), aResult);
 }
 
 NS_IMETHODIMP
-nsStringBundle::GetStringFromAUTF8Name(const nsACString& aName,
-                                       nsAString& aResult)
+nsStringBundleBase::GetStringFromAUTF8Name(const nsACString& aName,
+                                           nsAString& aResult)
 {
   return GetStringFromName(PromiseFlatCString(aName).get(), aResult);
 }
 
 NS_IMETHODIMP
-nsStringBundle::GetStringFromName(const char* aName, nsAString& aResult)
+nsStringBundleBase::GetStringFromName(const char* aName, nsAString& aResult)
 {
   NS_ENSURE_ARG_POINTER(aName);
 
-  nsresult rv = LoadProperties();
-  if (NS_FAILED(rv)) return rv;
-
   ReentrantMonitorAutoEnter automon(mReentrantMonitor);
 
-  // try override first
-  if (mOverrideStrings) {
-    rv = mOverrideStrings->GetStringFromName(mPropertiesURL,
-                                             nsDependentCString(aName),
-                                             aResult);
-    if (NS_SUCCEEDED(rv)) return rv;
+  return GetStringImpl(nsDependentCString(aName), aResult);
+}
+
+nsresult
+nsStringBundle::GetStringImpl(const nsACString& aName, nsAString& aResult)
+{
+  MOZ_TRY(LoadProperties());
+
+  return mProps->GetStringProperty(aName, aResult);
+}
+
+nsresult
+SharedStringBundle::GetStringImpl(const nsACString& aName, nsAString& aResult)
+{
+  MOZ_TRY(LoadProperties());
+
+  if (mStringMap->Get(PromiseFlatCString(aName), aResult)) {
+    return NS_OK;
   }
-
-  return mProps->GetStringProperty(nsDependentCString(aName), aResult);
+  return NS_ERROR_FAILURE;
 }
 
 NS_IMETHODIMP
-nsStringBundle::FormatStringFromID(int32_t aID,
-                                   const char16_t **aParams,
-                                   uint32_t aLength,
-                                   nsAString& aResult)
+nsStringBundleBase::FormatStringFromID(int32_t aID,
+                                       const char16_t **aParams,
+                                       uint32_t aLength,
+                                       nsAString& aResult)
 {
   nsAutoCString idStr;
   idStr.AppendInt(aID, 10);
   return FormatStringFromName(idStr.get(), aParams, aLength, aResult);
 }
 
 // this function supports at most 10 parameters.. see below for why
 NS_IMETHODIMP
-nsStringBundle::FormatStringFromAUTF8Name(const nsACString& aName,
-                                          const char16_t **aParams,
-                                          uint32_t aLength,
-                                          nsAString& aResult)
+nsStringBundleBase::FormatStringFromAUTF8Name(const nsACString& aName,
+                                              const char16_t **aParams,
+                                              uint32_t aLength,
+                                              nsAString& aResult)
 {
   return FormatStringFromName(PromiseFlatCString(aName).get(), aParams,
                               aLength, aResult);
 }
 
 // this function supports at most 10 parameters.. see below for why
 NS_IMETHODIMP
-nsStringBundle::FormatStringFromName(const char* aName,
-                                     const char16_t** aParams,
-                                     uint32_t aLength,
-                                     nsAString& aResult)
+nsStringBundleBase::FormatStringFromName(const char* aName,
+                                         const char16_t** aParams,
+                                         uint32_t aLength,
+                                         nsAString& aResult)
 {
   NS_ASSERTION(aParams && aLength, "FormatStringFromName() without format parameters: use GetStringFromName() instead");
 
   nsAutoString formatStr;
   nsresult rv = GetStringFromName(aName, formatStr);
   if (NS_FAILED(rv)) return rv;
 
   return FormatString(formatStr.get(), aParams, aLength, aResult);
 }
 
-nsresult
-nsStringBundle::GetCombinedEnumeration(nsIStringBundleOverride* aOverrideStrings,
-                                       nsISimpleEnumerator** aResult)
+NS_IMETHODIMP
+nsStringBundleBase::GetSimpleEnumeration(nsISimpleEnumerator** aElements)
 {
-  nsCOMPtr<nsISupports> supports;
-  nsCOMPtr<nsIPropertyElement> propElement;
-
-  nsresult rv;
-
-  nsCOMPtr<nsIMutableArray> resultArray =
-    do_CreateInstance(NS_ARRAY_CONTRACTID, &rv);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  // first, append the override elements
-  nsCOMPtr<nsISimpleEnumerator> overrideEnumerator;
-  rv = aOverrideStrings->EnumerateKeysInBundle(mPropertiesURL,
-                                               getter_AddRefs(overrideEnumerator));
-
-  bool hasMore;
-  rv = overrideEnumerator->HasMoreElements(&hasMore);
-  NS_ENSURE_SUCCESS(rv, rv);
-  while (hasMore) {
-
-    rv = overrideEnumerator->GetNext(getter_AddRefs(supports));
-    if (NS_SUCCEEDED(rv))
-      resultArray->AppendElement(supports);
-
-    rv = overrideEnumerator->HasMoreElements(&hasMore);
-    NS_ENSURE_SUCCESS(rv, rv);
-  }
+  NS_ENSURE_ARG_POINTER(aElements);
 
-  // ok, now we have the override elements in resultArray
-  nsCOMPtr<nsISimpleEnumerator> propEnumerator;
-  rv = mProps->Enumerate(getter_AddRefs(propEnumerator));
-  if (NS_FAILED(rv)) {
-    // no elements in mProps anyway, just return what we have
-    return NS_NewArrayEnumerator(aResult, resultArray);
-  }
-
-  // second, append all the elements that are in mProps
-  do {
-    rv = propEnumerator->GetNext(getter_AddRefs(supports));
-    if (NS_SUCCEEDED(rv) &&
-        (propElement = do_QueryInterface(supports, &rv))) {
-
-      // now check if its in the override bundle
-      nsAutoCString key;
-      propElement->GetKey(key);
-
-      nsAutoString value;
-      rv = aOverrideStrings->GetStringFromName(mPropertiesURL, key, value);
-
-      // if it isn't there, then it is safe to append
-      if (NS_FAILED(rv))
-        resultArray->AppendElement(propElement);
-    }
-
-    rv = propEnumerator->HasMoreElements(&hasMore);
-    NS_ENSURE_SUCCESS(rv, rv);
-  } while (hasMore);
-
-  return resultArray->Enumerate(aResult);
+  return GetSimpleEnumerationImpl(aElements);
 }
 
-
-NS_IMETHODIMP
-nsStringBundle::GetSimpleEnumeration(nsISimpleEnumerator** elements)
+nsresult
+nsStringBundle::GetSimpleEnumerationImpl(nsISimpleEnumerator** elements)
 {
-  if (!elements)
-    return NS_ERROR_INVALID_POINTER;
-
-  nsresult rv;
-  rv = LoadProperties();
-  if (NS_FAILED(rv)) return rv;
-
-  if (mOverrideStrings)
-      return GetCombinedEnumeration(mOverrideStrings, elements);
+  MOZ_TRY(LoadProperties());
 
   return mProps->Enumerate(elements);
 }
 
 nsresult
-nsStringBundle::FormatString(const char16_t *aFormatStr,
-                             const char16_t **aParams, uint32_t aLength,
-                             nsAString& aResult)
+SharedStringBundle::GetSimpleEnumerationImpl(nsISimpleEnumerator** aEnumerator)
+{
+  MOZ_TRY(LoadProperties());
+
+  auto iter = MakeRefPtr<StringMapEnumerator>(mStringMap);
+  iter.forget(aEnumerator);
+  return NS_OK;
+}
+
+
+NS_IMETHODIMP
+StringMapEnumerator::HasMoreElements(bool* aHasMore)
+{
+  *aHasMore = mIndex < mStringMap->Count();
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+StringMapEnumerator::GetNext(nsISupports** aNext)
+{
+  if (mIndex >= mStringMap->Count()) {
+    return NS_ERROR_FAILURE;
+  }
+
+  auto elem = MakeRefPtr<nsPropertyElement>(
+    mStringMap->GetKeyAt(mIndex),
+    mStringMap->GetValueAt(mIndex));
+
+  elem.forget(aNext);
+
+  mIndex++;
+  return NS_OK;
+}
+
+
+nsresult
+nsStringBundleBase::FormatString(const char16_t *aFormatStr,
+                                 const char16_t **aParams, uint32_t aLength,
+                                 nsAString& aResult)
 {
   NS_ENSURE_ARG(aLength <= 10); // enforce 10-parameter limit
 
   // implementation note: you would think you could use vsmprintf
   // to build up an arbitrary length array.. except that there
   // is no way to build up a va_list at runtime!
   // Don't believe me? See:
   //   http://www.eskimo.com/~scs/C-faq/q15.13.html
@@ -334,185 +732,16 @@ nsStringBundle::FormatString(const char1
                             aLength >= 7 ? aParams[6] : nullptr,
                             aLength >= 8 ? aParams[7] : nullptr,
                             aLength >= 9 ? aParams[8] : nullptr,
                             aLength >= 10 ? aParams[9] : nullptr);
 
   return NS_OK;
 }
 
-NS_IMPL_ISUPPORTS(nsExtensibleStringBundle, nsIStringBundle)
-
-nsExtensibleStringBundle::nsExtensibleStringBundle()
-{
-  mLoaded = false;
-}
-
-nsresult
-nsExtensibleStringBundle::Init(const char * aCategory,
-                               nsIStringBundleService* aBundleService)
-{
-
-  nsresult rv;
-  nsCOMPtr<nsICategoryManager> catman =
-    do_GetService(NS_CATEGORYMANAGER_CONTRACTID, &rv);
-  if (NS_FAILED(rv)) return rv;
-
-  nsCOMPtr<nsISimpleEnumerator> enumerator;
-  rv = catman->EnumerateCategory(aCategory, getter_AddRefs(enumerator));
-  if (NS_FAILED(rv)) return rv;
-
-  bool hasMore;
-  while (NS_SUCCEEDED(enumerator->HasMoreElements(&hasMore)) && hasMore) {
-    nsCOMPtr<nsISupports> supports;
-    rv = enumerator->GetNext(getter_AddRefs(supports));
-    if (NS_FAILED(rv))
-      continue;
-
-    nsCOMPtr<nsISupportsCString> supStr = do_QueryInterface(supports, &rv);
-    if (NS_FAILED(rv))
-      continue;
-
-    nsAutoCString name;
-    rv = supStr->GetData(name);
-    if (NS_FAILED(rv))
-      continue;
-
-    nsCOMPtr<nsIStringBundle> bundle;
-    rv = aBundleService->CreateBundle(name.get(), getter_AddRefs(bundle));
-    if (NS_FAILED(rv))
-      continue;
-
-    mBundles.AppendObject(bundle);
-  }
-
-  return rv;
-}
-
-NS_IMETHODIMP
-nsExtensibleStringBundle::AsyncPreload()
-{
-  nsresult rv = NS_OK;
-  const uint32_t size = mBundles.Count();
-  for (uint32_t i = 0; i < size; ++i) {
-    nsIStringBundle* bundle = mBundles[i];
-    if (bundle) {
-      nsresult rv2 = bundle->AsyncPreload();
-      rv = NS_FAILED(rv) ? rv : rv2;
-    }
-  }
-  return rv;
-}
-
-nsExtensibleStringBundle::~nsExtensibleStringBundle()
-{
-}
-
-size_t
-nsExtensibleStringBundle::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
-{
-  size_t n = 0;
-  const uint32_t sz = mBundles.Count();
-  for (uint32_t i = 0; i < sz; ++i) {
-    nsIStringBundle* bundle = mBundles[i];
-    if (bundle) {
-      n += bundle->SizeOfIncludingThis(aMallocSizeOf);
-    }
-  }
-  n += mBundles.ShallowSizeOfExcludingThis(aMallocSizeOf);
-  return aMallocSizeOf(this) + n;
-}
-
-size_t
-nsExtensibleStringBundle::SizeOfIncludingThisIfUnshared(MallocSizeOf aMallocSizeOf) const
-{
-  if (mRefCnt == 1) {
-    return SizeOfIncludingThis(aMallocSizeOf);
-  } else {
-    return 0;
-  }
-}
-
-nsresult
-nsExtensibleStringBundle::GetStringFromID(int32_t aID, nsAString& aResult)
-{
-  nsAutoCString idStr;
-  idStr.AppendInt(aID, 10);
-  return GetStringFromName(idStr.get(), aResult);
-}
-
-nsresult
-nsExtensibleStringBundle::GetStringFromAUTF8Name(const nsACString& aName,
-                                                 nsAString& aResult)
-{
-  return GetStringFromName(PromiseFlatCString(aName).get(), aResult);
-}
-
-nsresult
-nsExtensibleStringBundle::GetStringFromName(const char* aName,
-                                            nsAString& aResult)
-{
-  nsresult rv;
-  const uint32_t size = mBundles.Count();
-  for (uint32_t i = 0; i < size; ++i) {
-    nsIStringBundle* bundle = mBundles[i];
-    if (bundle) {
-      rv = bundle->GetStringFromName(aName, aResult);
-      if (NS_SUCCEEDED(rv))
-        return NS_OK;
-    }
-  }
-
-  return NS_ERROR_FAILURE;
-}
-
-NS_IMETHODIMP
-nsExtensibleStringBundle::FormatStringFromID(int32_t aID,
-                                             const char16_t ** aParams,
-                                             uint32_t aLength,
-                                             nsAString& aResult)
-{
-  nsAutoCString idStr;
-  idStr.AppendInt(aID, 10);
-  return FormatStringFromName(idStr.get(), aParams, aLength, aResult);
-}
-
-NS_IMETHODIMP
-nsExtensibleStringBundle::FormatStringFromAUTF8Name(const nsACString& aName,
-                                                    const char16_t ** aParams,
-                                                    uint32_t aLength,
-                                                    nsAString& aResult)
-{
-  return FormatStringFromName(PromiseFlatCString(aName).get(),
-                              aParams, aLength, aResult);
-}
-
-NS_IMETHODIMP
-nsExtensibleStringBundle::FormatStringFromName(const char* aName,
-                                               const char16_t** aParams,
-                                               uint32_t aLength,
-                                               nsAString& aResult)
-{
-  nsAutoString formatStr;
-  nsresult rv;
-  rv = GetStringFromName(aName, formatStr);
-  if (NS_FAILED(rv))
-    return rv;
-
-  return nsStringBundle::FormatString(formatStr.get(), aParams, aLength,
-                                      aResult);
-}
-
-nsresult nsExtensibleStringBundle::GetSimpleEnumeration(nsISimpleEnumerator ** aResult)
-{
-  // XXX write me
-  *aResult = nullptr;
-  return NS_ERROR_NOT_IMPLEMENTED;
-}
-
 /////////////////////////////////////////////////////////////////////////////////////////
 
 #define MAX_CACHED_BUNDLES 16
 
 struct bundleCacheEntry_t final : public LinkedListElement<bundleCacheEntry_t> {
   nsCString mHashKey;
   nsCOMPtr<nsIStringBundle> mBundle;
 
@@ -539,178 +768,236 @@ NS_IMPL_ISUPPORTS(nsStringBundleService,
                   nsIStringBundleService,
                   nsIObserver,
                   nsISupportsWeakReference,
                   nsIMemoryReporter)
 
 nsStringBundleService::~nsStringBundleService()
 {
   UnregisterWeakMemoryReporter(this);
-  flushBundleCache();
+  flushBundleCache(/* ignoreShared = */ false);
 }
 
 nsresult
 nsStringBundleService::Init()
 {
   nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
   if (os) {
     os->AddObserver(this, "memory-pressure", true);
     os->AddObserver(this, "profile-do-change", true);
     os->AddObserver(this, "chrome-flush-caches", true);
-    os->AddObserver(this, "xpcom-category-entry-added", true);
     os->AddObserver(this, "intl:app-locales-changed", true);
   }
 
-  // instantiate the override service, if there is any.
-  // at some point we probably want to make this a category, and
-  // support multiple overrides
-  mOverrideStrings = do_GetService(NS_STRINGBUNDLETEXTOVERRIDE_CONTRACTID);
-
   RegisterWeakMemoryReporter(this);
 
   return NS_OK;
 }
 
 size_t
 nsStringBundleService::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
 {
   size_t n = mBundleMap.ShallowSizeOfExcludingThis(aMallocSizeOf);
   for (auto iter = mBundleMap.ConstIter(); !iter.Done(); iter.Next()) {
-    n += iter.Data()->mBundle->SizeOfIncludingThis(aMallocSizeOf);
+    n += aMallocSizeOf(iter.Data());
     n += iter.Data()->mHashKey.SizeOfExcludingThisIfUnshared(aMallocSizeOf);
   }
   return aMallocSizeOf(this) + n;
 }
 
 NS_IMETHODIMP
 nsStringBundleService::Observe(nsISupports* aSubject,
                                const char* aTopic,
                                const char16_t* aSomeData)
 {
-  if (strcmp("memory-pressure", aTopic) == 0 ||
-      strcmp("profile-do-change", aTopic) == 0 ||
+  if (strcmp("profile-do-change", aTopic) == 0 ||
       strcmp("chrome-flush-caches", aTopic) == 0 ||
       strcmp("intl:app-locales-changed", aTopic) == 0)
   {
-    flushBundleCache();
-  }
-  else if (strcmp("xpcom-category-entry-added", aTopic) == 0 &&
-           NS_LITERAL_STRING("xpcom-autoregistration").Equals(aSomeData))
-  {
-    mOverrideStrings = do_GetService(NS_STRINGBUNDLETEXTOVERRIDE_CONTRACTID);
+    flushBundleCache(/* ignoreShared = */ false);
+  } else if (strcmp("memory-pressure", aTopic) == 0) {
+    flushBundleCache(/* ignoreShared = */ true);
   }
 
   return NS_OK;
 }
 
 void
-nsStringBundleService::flushBundleCache()
+nsStringBundleService::flushBundleCache(bool ignoreShared)
 {
-  // release all bundles in the cache
-  mBundleMap.Clear();
+  LinkedList<bundleCacheEntry_t> newList;
 
   while (!mBundleCache.isEmpty()) {
-    delete mBundleCache.popFirst();
+    UniquePtr<bundleCacheEntry_t> entry(mBundleCache.popFirst());
+    auto* bundle = nsStringBundleBase::Cast(entry->mBundle);
+
+    if (ignoreShared && bundle->IsShared()) {
+      newList.insertBack(entry.release());
+    } else {
+      mBundleMap.Remove(entry->mHashKey);
+    }
   }
+
+  mBundleCache = std::move(newList);
 }
 
 NS_IMETHODIMP
 nsStringBundleService::FlushBundles()
 {
-  flushBundleCache();
+  flushBundleCache(/* ignoreShared = */ false);
   return NS_OK;
 }
 
 void
+nsStringBundleService::SendContentBundles(ContentParent* aContentParent) const
+{
+  nsTArray<StringBundleDescriptor> bundles;
+
+  for (auto* entry : mSharedBundles) {
+    auto bundle = SharedStringBundle::Cast(entry->mBundle);
+
+    if (bundle->Initialized()) {
+      bundles.AppendElement(bundle->GetDescriptor());
+    }
+  }
+
+  Unused << aContentParent->SendRegisterStringBundles(std::move(bundles));
+}
+
+void
+nsStringBundleService::RegisterContentBundle(const nsCString& aBundleURL,
+                                             const FileDescriptor& aMapFile,
+                                             size_t aMapSize)
+{
+  RefPtr<StringBundleProxy> proxy;
+
+  bundleCacheEntry_t* cacheEntry = mBundleMap.Get(aBundleURL);
+  if (cacheEntry) {
+    if (RefPtr<SharedStringBundle> shared = do_QueryObject(cacheEntry->mBundle)) {
+      return;
+    }
+
+    proxy = do_QueryObject(cacheEntry->mBundle);
+    MOZ_ASSERT(proxy);
+    cacheEntry->remove();
+    delete cacheEntry;
+  }
+
+  auto bundle = MakeBundleRefPtr<SharedStringBundle>(aBundleURL.get());
+  bundle->SetMapFile(aMapFile, aMapSize);
+
+  if (proxy) {
+    proxy->Retarget(bundle);
+  }
+
+  cacheEntry = insertIntoCache(bundle.forget(), aBundleURL);
+  mSharedBundles.insertBack(cacheEntry);
+}
+
+void
 nsStringBundleService::getStringBundle(const char *aURLSpec,
                                        nsIStringBundle **aResult)
 {
   nsDependentCString key(aURLSpec);
   bundleCacheEntry_t* cacheEntry = mBundleMap.Get(key);
 
+  RefPtr<SharedStringBundle> shared;
+
   if (cacheEntry) {
-    // cache hit!
-    // remove it from the list, it will later be reinserted
-    // at the head of the list
+    // Remove the entry from the list so it can be re-inserted at the back.
     cacheEntry->remove();
 
+    shared = do_QueryObject(cacheEntry->mBundle);
   } else {
-    // hasn't been cached, so insert it into the hash table
-    RefPtr<nsStringBundle> bundle = new nsStringBundle(aURLSpec, mOverrideStrings);
+    nsCOMPtr<nsIStringBundle> bundle;
+    bool isContent = IsContentBundle(key);
+    if (!isContent || !XRE_IsParentProcess()) {
+      bundle = MakeBundle<nsStringBundle>(aURLSpec);
+    }
+
+    // If this is a bundle which is used by the content processes, we want to
+    // load it into a shared memory region.
+    //
+    // If we're in the parent process, just create a new SharedStringBundle,
+    // and populate it from the properties file.
+    //
+    // If we're in a child process, the fact that the bundle is not already in
+    // the cache means that we haven't received its shared memory descriptor
+    // from the parent yet. There's not much we can do about that besides
+    // wait, but we need to return a bundle now. So instead of a shared memory
+    // bundle, we create a temporary proxy, which points to a non-shared
+    // bundle initially, and is retarged to a shared memory bundle when it
+    // becomes available.
+    if (isContent) {
+      if (XRE_IsParentProcess()) {
+        shared = MakeBundle<SharedStringBundle>(aURLSpec);
+        bundle = shared;
+      } else {
+        bundle = new StringBundleProxy(bundle.forget());
+      }
+    }
+
     cacheEntry = insertIntoCache(bundle.forget(), key);
   }
 
-  // at this point the cacheEntry should exist in the hashtable,
-  // but is not in the LRU cache.
-  // put the cache entry at the front of the list
-  mBundleCache.insertFront(cacheEntry);
+  if (shared) {
+    mSharedBundles.insertBack(cacheEntry);
+  } else {
+    mBundleCache.insertBack(cacheEntry);
+  }
 
   // finally, return the value
   *aResult = cacheEntry->mBundle;
   NS_ADDREF(*aResult);
 }
 
-bundleCacheEntry_t *
-nsStringBundleService::insertIntoCache(already_AddRefed<nsIStringBundle> aBundle,
-                                       nsCString &aHashKey)
+UniquePtr<bundleCacheEntry_t>
+nsStringBundleService::evictOneEntry()
 {
-  bundleCacheEntry_t *cacheEntry;
+  for (auto* entry : mBundleCache) {
+    auto* bundle = nsStringBundleBase::Cast(entry->mBundle);
+    if (!bundle->IsShared()) {
+      entry->remove();
+      mBundleMap.Remove(entry->mHashKey);
+      return UniquePtr<bundleCacheEntry_t>(entry);
+    }
+  }
+  return nullptr;
+}
 
-  if (mBundleMap.Count() < MAX_CACHED_BUNDLES) {
-    // cache not full - create a new entry
-    cacheEntry = new bundleCacheEntry_t();
-  } else {
-    // cache is full
-    // take the last entry in the list, and recycle it.
-    cacheEntry = mBundleCache.getLast();
+bundleCacheEntry_t*
+nsStringBundleService::insertIntoCache(already_AddRefed<nsIStringBundle> aBundle,
+                                       const nsACString& aHashKey)
+{
+  UniquePtr<bundleCacheEntry_t> cacheEntry;
 
-    // remove it from the hash table and linked list
-    NS_ASSERTION(mBundleMap.Contains(cacheEntry->mHashKey),
-                 "Element will not be removed!");
-    mBundleMap.Remove(cacheEntry->mHashKey);
-    cacheEntry->remove();
+  if (mBundleMap.Count() >= MAX_CACHED_BUNDLES) {
+    cacheEntry = evictOneEntry();
   }
 
-  // at this point we have a new cacheEntry that doesn't exist
-  // in the hashtable, so set up the cacheEntry
+  if (!cacheEntry) {
+    cacheEntry.reset(new bundleCacheEntry_t());
+  }
+
   cacheEntry->mHashKey = aHashKey;
   cacheEntry->mBundle = aBundle;
 
-  // insert the entry into the cache and map, make it the MRU
-  mBundleMap.Put(cacheEntry->mHashKey, cacheEntry);
+  mBundleMap.Put(cacheEntry->mHashKey, cacheEntry.get());
 
-  return cacheEntry;
+  return cacheEntry.release();
 }
 
 NS_IMETHODIMP
 nsStringBundleService::CreateBundle(const char* aURLSpec,
                                     nsIStringBundle** aResult)
 {
   getStringBundle(aURLSpec,aResult);
   return NS_OK;
 }
 
-NS_IMETHODIMP
-nsStringBundleService::CreateExtensibleBundle(const char* aCategory,
-                                              nsIStringBundle** aResult)
-{
-  NS_ENSURE_ARG_POINTER(aResult);
-  *aResult = nullptr;
-
-  RefPtr<nsExtensibleStringBundle> bundle = new nsExtensibleStringBundle();
-
-  nsresult res = bundle->Init(aCategory, this);
-  if (NS_FAILED(res)) {
-    return res;
-  }
-
-  bundle.forget(aResult);
-  return NS_OK;
-}
-
 #define GLOBAL_PROPERTIES "chrome://global/locale/global-strres.properties"
 
 nsresult
 nsStringBundleService::FormatWithBundle(nsIStringBundle* bundle, nsresult aStatus,
                                         uint32_t argCount, char16_t** argArray,
                                         nsAString& result)
 {
   nsresult rv;
--- a/intl/strres/nsStringBundle.h
+++ b/intl/strres/nsStringBundle.h
@@ -3,78 +3,92 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef nsStringBundle_h__
 #define nsStringBundle_h__
 
 #include "mozilla/ReentrantMonitor.h"
 #include "nsIStringBundle.h"
+#include "nsIMemoryReporter.h"
 #include "nsCOMPtr.h"
 #include "nsString.h"
 #include "nsCOMArray.h"
 
 class nsIPersistentProperties;
-class nsIStringBundleOverride;
+
 
-class nsStringBundle : public nsIStringBundle
+class nsStringBundleBase : public nsIStringBundle
+                         , public nsIMemoryReporter
 {
 public:
-    // init version
-    nsStringBundle(const char* aURLSpec, nsIStringBundleOverride*);
-    nsresult LoadProperties();
+    MOZ_DEFINE_MALLOC_SIZE_OF(MallocSizeOf)
+
+    nsresult ParseProperties(nsIPersistentProperties**);
 
     NS_DECL_THREADSAFE_ISUPPORTS
     NS_DECL_NSISTRINGBUNDLE
+    NS_DECL_NSIMEMORYREPORTER
 
-    nsCOMPtr<nsIPersistentProperties> mProps;
+    virtual nsresult LoadProperties() = 0;
+
+    const nsCString& BundleURL() const { return mPropertiesURL; }
 
-    size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const override;
-    size_t SizeOfIncludingThisIfUnshared(mozilla::MallocSizeOf aMallocSizeOf) const override;
+    // Returns true if this bundle has more than one reference. If it has only
+    // a single reference, it is assumed to be held alive by the bundle cache.
+    bool IsShared() const { return mRefCnt > 1; }
+
+    static nsStringBundleBase* Cast(nsIStringBundle* aBundle)
+    {
+      return static_cast<nsStringBundleBase*>(aBundle);
+    }
+
+    template <typename T, typename... Args>
+    static already_AddRefed<T> Create(Args... args);
 
 protected:
-    virtual ~nsStringBundle();
+    nsStringBundleBase(const char* aURLSpec);
+
+    virtual ~nsStringBundleBase();
+
+    virtual nsresult GetStringImpl(const nsACString& aName, nsAString& aResult) = 0;
 
-    nsresult GetCombinedEnumeration(nsIStringBundleOverride* aOverrideString,
-                                    nsISimpleEnumerator** aResult);
-private:
+    virtual nsresult GetSimpleEnumerationImpl(nsISimpleEnumerator** elements) = 0;
+
+    void RegisterMemoryReporter();
+
     nsCString              mPropertiesURL;
-    nsCOMPtr<nsIStringBundleOverride> mOverrideStrings;
     mozilla::ReentrantMonitor    mReentrantMonitor;
     bool                         mAttemptedLoad;
     bool                         mLoaded;
 
+    size_t SizeOfIncludingThisIfUnshared(mozilla::MallocSizeOf aMallocSizeOf) const override;
+
 public:
     static nsresult FormatString(const char16_t *formatStr,
                                  const char16_t **aParams, uint32_t aLength,
                                  nsAString& aResult);
 };
 
-class nsExtensibleStringBundle;
+class nsStringBundle : public nsStringBundleBase
+{
+public:
+    NS_DECL_ISUPPORTS_INHERITED
 
-/**
- * An extensible implementation of the StringBundle interface.
- *
- * @created         28/Dec/1999
- * @author  Catalin Rotaru [CATA]
- */
-class nsExtensibleStringBundle final : public nsIStringBundle
-{
-  NS_DECL_ISUPPORTS
-  NS_DECL_NSISTRINGBUNDLE
+    nsCOMPtr<nsIPersistentProperties> mProps;
+
+    nsresult LoadProperties() override;
+
+    size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const override;
 
-  nsresult Init(const char * aCategory, nsIStringBundleService *);
+protected:
+    friend class nsStringBundleBase;
+
+    explicit nsStringBundle(const char* aURLSpec);
 
-public:
-  nsExtensibleStringBundle();
-  size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const override;
-  size_t SizeOfIncludingThisIfUnshared(mozilla::MallocSizeOf aMallocSizeOf) const override;
+    virtual ~nsStringBundle();
 
-private:
-  virtual ~nsExtensibleStringBundle();
+    nsresult GetStringImpl(const nsACString& aName, nsAString& aResult) override;
 
-  nsCOMArray<nsIStringBundle> mBundles;
-  bool mLoaded;
+    nsresult GetSimpleEnumerationImpl(nsISimpleEnumerator** elements) override;
 };
 
-
-
 #endif
--- a/intl/strres/nsStringBundleService.h
+++ b/intl/strres/nsStringBundleService.h
@@ -9,20 +9,20 @@
 #include "nsCOMPtr.h"
 #include "nsDataHashtable.h"
 #include "nsHashKeys.h"
 #include "nsIPersistentProperties2.h"
 #include "nsIStringBundle.h"
 #include "nsIObserver.h"
 #include "nsWeakReference.h"
 #include "nsIErrorService.h"
-#include "nsIStringBundleOverride.h"
 #include "nsIMemoryReporter.h"
 
 #include "mozilla/LinkedList.h"
+#include "mozilla/UniquePtr.h"
 
 struct bundleCacheEntry_t;
 
 class nsStringBundleService : public nsIStringBundleService,
                               public nsIObserver,
                               public nsSupportsWeakReference,
                               public nsIMemoryReporter
 {
@@ -38,37 +38,47 @@ public:
   NS_DECL_NSIOBSERVER
 
   NS_IMETHOD CollectReports(nsIHandleReportCallback* aHandleReport,
                             nsISupports* aData, bool anonymize) override
   {
     size_t amt = SizeOfIncludingThis(MallocSizeOf);
 
     MOZ_COLLECT_REPORT(
-      "explicit/string-bundle-service", KIND_HEAP, UNITS_BYTES,
+      "explicit/string-bundles/service", KIND_HEAP, UNITS_BYTES,
       amt,
-      "Memory used for StringBundleService bundles");
+      "Memory used for StringBundleService overhead");
     return NS_OK;
   };
 
   size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const override;
 
+  void SendContentBundles(mozilla::dom::ContentParent* aContentParent) const override;
+
+  void RegisterContentBundle(const nsCString& aBundleURL,
+                             const mozilla::ipc::FileDescriptor& aMapFile,
+                             size_t aMapSize) override;
+
 private:
   virtual ~nsStringBundleService();
 
   void getStringBundle(const char *aUrl, nsIStringBundle** aResult);
   nsresult FormatWithBundle(nsIStringBundle* bundle, nsresult aStatus,
                             uint32_t argCount, char16_t** argArray,
                             nsAString& result);
 
-  void flushBundleCache();
+  void flushBundleCache(bool ignoreShared = true);
 
-  bundleCacheEntry_t *insertIntoCache(already_AddRefed<nsIStringBundle> aBundle,
-                                      nsCString &aHashKey);
+  mozilla::UniquePtr<bundleCacheEntry_t> evictOneEntry();
+
+  bundleCacheEntry_t* insertIntoCache(already_AddRefed<nsIStringBundle> aBundle,
+                                      const nsACString &aHashKey);
 
   nsDataHashtable<nsCStringHashKey, bundleCacheEntry_t*> mBundleMap;
+  // LRU list of cached entries, with the least-recently-used entry first.
   mozilla::LinkedList<bundleCacheEntry_t> mBundleCache;
+  // List of cached shared-memory string bundles, in arbitrary order.
+  mozilla::AutoCleanLinkedList<bundleCacheEntry_t> mSharedBundles;
 
   nsCOMPtr<nsIErrorService> mErrorService;
-  nsCOMPtr<nsIStringBundleOverride> mOverrideStrings;
 };
 
 #endif
deleted file mode 100644
--- a/intl/strres/nsStringBundleTextOverride.cpp
+++ /dev/null
@@ -1,292 +0,0 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-
-#include "nsStringBundleTextOverride.h"
-#include "nsString.h"
-
-#include "nsNetUtil.h"
-#include "nsAppDirectoryServiceDefs.h"
-#include "nsContentUtils.h"
-#include "nsDirectoryServiceUtils.h"
-
-// first we need a simple class which wraps a nsIPropertyElement and
-// cuts out the leading URL from the key
-class URLPropertyElement : public nsIPropertyElement
-{
-public:
-    URLPropertyElement(nsIPropertyElement *aRealElement, uint32_t aURLLength) :
-        mRealElement(aRealElement),
-        mURLLength(aURLLength)
-    { }
-
-    NS_DECL_ISUPPORTS
-    NS_DECL_NSIPROPERTYELEMENT
-
-private:
-    nsCOMPtr<nsIPropertyElement> mRealElement;
-    uint32_t mURLLength;
-
-    virtual ~URLPropertyElement() {}
-};
-
-NS_IMPL_ISUPPORTS(URLPropertyElement, nsIPropertyElement)
-
-// we'll tweak the key on the way through, and remove the url prefix
-NS_IMETHODIMP
-URLPropertyElement::GetKey(nsACString& aKey)
-{
-    nsresult rv =  mRealElement->GetKey(aKey);
-    if (NS_FAILED(rv)) return rv;
-
-    // chop off the url
-    aKey.Cut(0, mURLLength);
-
-    return NS_OK;
-}
-
-// values are unaffected
-NS_IMETHODIMP
-URLPropertyElement::GetValue(nsAString& aValue)
-{
-    return mRealElement->GetValue(aValue);
-}
-
-// setters are kind of strange, hopefully we'll never be called
-NS_IMETHODIMP
-URLPropertyElement::SetKey(const nsACString& aKey)
-{
-    // this is just wrong - ideally you'd take the key, append it to
-    // the url, and set that as the key. However, that would require
-    // us to hold onto a copy of the string, and that's a waste,
-    // considering nobody should ever be calling this.
-    NS_ERROR("This makes no sense!");
-    return NS_ERROR_NOT_IMPLEMENTED;
-}
-
-NS_IMETHODIMP
-URLPropertyElement::SetValue(const nsAString& aValue)
-{
-    return mRealElement->SetValue(aValue);
-}
-
-
-// this is a special enumerator which returns only the elements which
-// are prefixed with a particular url
-class nsPropertyEnumeratorByURL : public nsISimpleEnumerator
-{
-public:
-    nsPropertyEnumeratorByURL(const nsACString& aURL,
-                              nsISimpleEnumerator* aOuter) :
-        mOuter(aOuter),
-        mURL(aURL)
-    {
-        // prepare the url once so we can use its value later
-        // persistent properties uses ":" as a delimiter, so escape
-        // that character
-        mURL.ReplaceSubstring(":", "%3A");
-        // there is always a # between the url and the real key
-        mURL.Append('#');
-    }
-
-    NS_DECL_ISUPPORTS
-    NS_DECL_NSISIMPLEENUMERATOR
-
-private:
-
-    // actual enumerator of all strings from nsIProperties
-    nsCOMPtr<nsISimpleEnumerator> mOuter;
-
-    // the current element that is valid for this url
-    nsCOMPtr<nsIPropertyElement> mCurrent;
-
-    // the url in question, pre-escaped and with the # already in it
-    nsCString mURL;
-
-    virtual ~nsPropertyEnumeratorByURL() {}
-};
-
-//
-// nsStringBundleTextOverride implementation
-//
-NS_IMPL_ISUPPORTS(nsStringBundleTextOverride,
-                  nsIStringBundleOverride)
-
-nsresult
-nsStringBundleTextOverride::Init()
-{
-    nsresult rv;
-
-    // check for existence of custom-strings.txt
-
-    nsCOMPtr<nsIFile> customStringsFile;
-    rv = NS_GetSpecialDirectory(NS_APP_CHROME_DIR,
-                                getter_AddRefs(customStringsFile));
-
-    if (NS_FAILED(rv)) return rv;
-
-    // bail if not found - this will cause the service creation to
-    // bail as well, and cause this object to go away
-
-    customStringsFile->AppendNative(NS_LITERAL_CSTRING("custom-strings.txt"));
-
-    bool exists;
-    rv = customStringsFile->Exists(&exists);
-    if (NS_FAILED(rv) || !exists)
-        return NS_ERROR_FAILURE;
-
-    NS_WARNING("Using custom-strings.txt to override string bundles.");
-    // read in the custom bundle. Keys are in the form
-    // chrome://package/locale/foo.properties:keyname
-
-    nsAutoCString customStringsURLSpec;
-    rv = NS_GetURLSpecFromFile(customStringsFile, customStringsURLSpec);
-    if (NS_FAILED(rv)) return rv;
-
-    nsCOMPtr<nsIURI> uri;
-    rv = NS_NewURI(getter_AddRefs(uri), customStringsURLSpec);
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    nsCOMPtr<nsIChannel> channel;
-    rv = NS_NewChannel(getter_AddRefs(channel),
-                       uri,
-                       nsContentUtils::GetSystemPrincipal(),
-                       nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL,
-                       nsIContentPolicy::TYPE_OTHER);
-
-    NS_ENSURE_SUCCESS(rv, rv);
-    nsCOMPtr<nsIInputStream> in;
-    rv = channel->Open2(getter_AddRefs(in));
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    static NS_DEFINE_CID(kPersistentPropertiesCID, NS_IPERSISTENTPROPERTIES_CID);
-    mValues = do_CreateInstance(kPersistentPropertiesCID, &rv);
-    if (NS_FAILED(rv)) return rv;
-
-    rv = mValues->Load(in);
-
-    // turn this on to see the contents of custom-strings.txt
-#ifdef DEBUG_alecf
-    nsCOMPtr<nsISimpleEnumerator> enumerator;
-    mValues->Enumerate(getter_AddRefs(enumerator));
-    NS_ASSERTION(enumerator, "no enumerator!\n");
-
-    printf("custom-strings.txt contains:\n");
-    printf("----------------------------\n");
-
-    bool hasMore;
-    enumerator->HasMoreElements(&hasMore);
-    do {
-        nsCOMPtr<nsISupports> sup;
-        enumerator->GetNext(getter_AddRefs(sup));
-
-        nsCOMPtr<nsIPropertyElement> prop = do_QueryInterface(sup);
-
-        nsAutoCString key;
-        nsAutoString value;
-        prop->GetKey(key);
-        prop->GetValue(value);
-
-        printf("%s = '%s'\n", key.get(), NS_ConvertUTF16toUTF8(value).get());
-
-        enumerator->HasMoreElements(&hasMore);
-    } while (hasMore);
-#endif
-
-    return rv;
-}
-
-NS_IMETHODIMP
-nsStringBundleTextOverride::GetStringFromName(const nsACString& aURL,
-                                              const nsACString& key,
-                                              nsAString& aResult)
-{
-    // concatenate url#key to get the key to read
-    nsAutoCString combinedURL(aURL + NS_LITERAL_CSTRING("#") + key);
-
-    // persistent properties uses ":" as a delimiter, so escape that character
-    combinedURL.ReplaceSubstring(":", "%3A");
-
-    return mValues->GetStringProperty(combinedURL, aResult);
-}
-
-size_t
-nsStringBundleTextOverride::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
-{
-  return aMallocSizeOf(this) + (mValues ? mValues->SizeOfIncludingThis(aMallocSizeOf) : 0);
-}
-
-NS_IMETHODIMP
-nsStringBundleTextOverride::EnumerateKeysInBundle(const nsACString& aURL,
-                                                  nsISimpleEnumerator** aResult)
-{
-    // enumerate all strings, and let the enumerator know
-    nsCOMPtr<nsISimpleEnumerator> enumerator;
-    mValues->Enumerate(getter_AddRefs(enumerator));
-
-    // make the enumerator wrapper and pass it off
-    nsPropertyEnumeratorByURL* propEnum =
-        new nsPropertyEnumeratorByURL(aURL, enumerator);
-
-    if (!propEnum) return NS_ERROR_OUT_OF_MEMORY;
-
-    NS_ADDREF(*aResult = propEnum);
-
-    return NS_OK;
-}
-
-
-//
-// nsPropertyEnumeratorByURL implementation
-//
-
-
-NS_IMPL_ISUPPORTS(nsPropertyEnumeratorByURL, nsISimpleEnumerator)
-
-NS_IMETHODIMP
-nsPropertyEnumeratorByURL::GetNext(nsISupports **aResult)
-{
-    if (!mCurrent) return NS_ERROR_UNEXPECTED;
-
-    // wrap mCurrent instead of returning it
-    *aResult = new URLPropertyElement(mCurrent, mURL.Length());
-    NS_ADDREF(*aResult);
-
-    // release it so we don't return it twice
-    mCurrent = nullptr;
-
-    return NS_OK;
-}
-
-NS_IMETHODIMP
-nsPropertyEnumeratorByURL::HasMoreElements(bool * aResult)
-{
-    bool hasMore;
-    mOuter->HasMoreElements(&hasMore);
-    while (hasMore) {
-
-        nsCOMPtr<nsISupports> supports;
-        mOuter->GetNext(getter_AddRefs(supports));
-
-        mCurrent = do_QueryInterface(supports);
-
-        if (mCurrent) {
-            nsAutoCString curKey;
-            mCurrent->GetKey(curKey);
-
-            if (StringBeginsWith(curKey, mURL))
-                break;
-        }
-
-        mOuter->HasMoreElements(&hasMore);
-    }
-
-    if (!hasMore)
-        mCurrent = nullptr;
-
-    *aResult = mCurrent ? true : false;
-
-    return NS_OK;
-}
deleted file mode 100644
--- a/intl/strres/nsStringBundleTextOverride.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-
-#ifndef nsStringBundleTextOverride_h__
-#define nsStringBundleTextOverride_h__
-
-#include "nsIStringBundleOverride.h"
-#include "nsCOMPtr.h"
-#include "nsIPersistentProperties2.h"
-
-// {6316C6CE-12D3-479e-8F53-E289351412B8}
-#define NS_STRINGBUNDLETEXTOVERRIDE_CID \
-  { 0x6316c6ce, 0x12d3, 0x479e, \
-  { 0x8f, 0x53, 0xe2, 0x89, 0x35, 0x14, 0x12, 0xb8 } }
-
-
-#define NS_STRINGBUNDLETEXTOVERRIDE_CONTRACTID \
-    "@mozilla.org/intl/stringbundle/text-override;1"
-
-// an implementation which does overrides from a text file
-
-class nsStringBundleTextOverride : public nsIStringBundleOverride
-{
-  public:
-    nsStringBundleTextOverride() { }
-
-    nsresult Init();
-
-    NS_DECL_ISUPPORTS
-    NS_DECL_NSISTRINGBUNDLEOVERRIDE
-
-    size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const override;
-
-  private:
-    nsCOMPtr<nsIPersistentProperties> mValues;
-
-    virtual ~nsStringBundleTextOverride() {}
-};
-
-#endif
--- a/js/rust/Cargo.toml
+++ b/js/rust/Cargo.toml
@@ -2,17 +2,17 @@
 name = "js"
 version = "0.1.4"
 authors = ["The Servo Project Developers"]
 build = "build.rs"
 license = "MPL-2.0"
 
 [build-dependencies]
 env_logger = {version = "0.5", default-features = false} # disable `regex` to reduce code size
-bindgen = {version = "0.33.1", default-features = false} # disable `logging` to reduce code size
+bindgen = {version = "0.37", default-features = false} # disable `logging` to reduce code size
 cmake = "0.1"
 glob = "0.2.11"
 
 [[test]]
 name = "bigint"
 required-features = ["bigint"]
 [[test]]
 name = "callback"
--- a/js/src/frontend/BinSource-auto.cpp
+++ b/js/src/frontend/BinSource-auto.cpp
@@ -60,24 +60,22 @@ BinASTParser<Tok>::parseArrowExpression(
     MOZ_TRY(guard.done());
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseSumArrowExpression(const size_t start, const BinKind kind, const BinFields& fields)
 {
     ParseNode* result;
-    switch(kind) {
+    switch (kind) {
       case BinKind::EagerArrowExpression:
         MOZ_TRY_VAR(result, parseInterfaceEagerArrowExpression(start, kind, fields));
-
         break;
       case BinKind::SkippableArrowExpression:
         MOZ_TRY_VAR(result, parseInterfaceSkippableArrowExpression(start, kind, fields));
-
         break;
       default:
         return raiseInvalidKind("ArrowExpression", kind);
     }
     return result;
 }
 
 /*
@@ -102,36 +100,31 @@ BinASTParser<Tok>::parseAssignmentTarget
     MOZ_TRY(guard.done());
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseSumAssignmentTarget(const size_t start, const BinKind kind, const BinFields& fields)
 {
     ParseNode* result;
-    switch(kind) {
+    switch (kind) {
       case BinKind::ArrayAssignmentTarget:
         MOZ_TRY_VAR(result, parseInterfaceArrayAssignmentTarget(start, kind, fields));
-
         break;
       case BinKind::AssignmentTargetIdentifier:
         MOZ_TRY_VAR(result, parseInterfaceAssignmentTargetIdentifier(start, kind, fields));
-
         break;
       case BinKind::ComputedMemberAssignmentTarget:
         MOZ_TRY_VAR(result, parseInterfaceComputedMemberAssignmentTarget(start, kind, fields));
-
         break;
       case BinKind::ObjectAssignmentTarget:
         MOZ_TRY_VAR(result, parseInterfaceObjectAssignmentTarget(start, kind, fields));
-
         break;
       case BinKind::StaticMemberAssignmentTarget:
         MOZ_TRY_VAR(result, parseInterfaceStaticMemberAssignmentTarget(start, kind, fields));
-
         break;
       default:
         return raiseInvalidKind("AssignmentTarget", kind);
     }
     return result;
 }
 
 /*
@@ -157,40 +150,34 @@ BinASTParser<Tok>::parseAssignmentTarget
     MOZ_TRY(guard.done());
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseSumAssignmentTargetOrAssignmentTargetWithInitializer(const size_t start, const BinKind kind, const BinFields& fields)
 {
     ParseNode* result;
-    switch(kind) {
+    switch (kind) {
       case BinKind::ArrayAssignmentTarget:
         MOZ_TRY_VAR(result, parseInterfaceArrayAssignmentTarget(start, kind, fields));
-
         break;
       case BinKind::AssignmentTargetIdentifier:
         MOZ_TRY_VAR(result, parseInterfaceAssignmentTargetIdentifier(start, kind, fields));
-
         break;
       case BinKind::AssignmentTargetWithInitializer:
         MOZ_TRY_VAR(result, parseInterfaceAssignmentTargetWithInitializer(start, kind, fields));
-
         break;
       case BinKind::ComputedMemberAssignmentTarget:
         MOZ_TRY_VAR(result, parseInterfaceComputedMemberAssignmentTarget(start, kind, fields));
-
         break;
       case BinKind::ObjectAssignmentTarget:
         MOZ_TRY_VAR(result, parseInterfaceObjectAssignmentTarget(start, kind, fields));
-
         break;
       case BinKind::StaticMemberAssignmentTarget:
         MOZ_TRY_VAR(result, parseInterfaceStaticMemberAssignmentTarget(start, kind, fields));
-
         break;
       default:
         return raiseInvalidKind("AssignmentTargetOrAssignmentTargetWithInitializer", kind);
     }
     return result;
 }
 
 /*
@@ -212,24 +199,22 @@ BinASTParser<Tok>::parseAssignmentTarget
     MOZ_TRY(guard.done());
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseSumAssignmentTargetPattern(const size_t start, const BinKind kind, const BinFields& fields)
 {
     ParseNode* result;
-    switch(kind) {
+    switch (kind) {
       case BinKind::ArrayAssignmentTarget:
         MOZ_TRY_VAR(result, parseInterfaceArrayAssignmentTarget(start, kind, fields));
-
         break;
       case BinKind::ObjectAssignmentTarget:
         MOZ_TRY_VAR(result, parseInterfaceObjectAssignmentTarget(start, kind, fields));
-
         break;
       default:
         return raiseInvalidKind("AssignmentTargetPattern", kind);
     }
     return result;
 }
 
 /*
@@ -251,24 +236,22 @@ BinASTParser<Tok>::parseAssignmentTarget
     MOZ_TRY(guard.done());
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseSumAssignmentTargetProperty(const size_t start, const BinKind kind, const BinFields& fields)
 {
     ParseNode* result;
-    switch(kind) {
+    switch (kind) {
       case BinKind::AssignmentTargetPropertyIdentifier:
         MOZ_TRY_VAR(result, parseInterfaceAssignmentTargetPropertyIdentifier(start, kind, fields));
-
         break;
       case BinKind::AssignmentTargetPropertyProperty:
         MOZ_TRY_VAR(result, parseInterfaceAssignmentTargetPropertyProperty(start, kind, fields));
-
         break;
       default:
         return raiseInvalidKind("AssignmentTargetProperty", kind);
     }
     return result;
 }
 
 /*
@@ -291,28 +274,25 @@ BinASTParser<Tok>::parseBinding()
     MOZ_TRY(guard.done());
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseSumBinding(const size_t start, const BinKind kind, const BinFields& fields)
 {
     ParseNode* result;
-    switch(kind) {
+    switch (kind) {
       case BinKind::ArrayBinding:
         MOZ_TRY_VAR(result, parseInterfaceArrayBinding(start, kind, fields));
-
         break;
       case BinKind::BindingIdentifier:
         MOZ_TRY_VAR(result, parseInterfaceBindingIdentifier(start, kind, fields));
-
         break;
       case BinKind::ObjectBinding:
         MOZ_TRY_VAR(result, parseInterfaceObjectBinding(start, kind, fields));
-
         break;
       default:
         return raiseInvalidKind("Binding", kind);
     }
     return result;
 }
 
 /*
@@ -336,32 +316,28 @@ BinASTParser<Tok>::parseBindingOrBinding
     MOZ_TRY(guard.done());
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseSumBindingOrBindingWithInitializer(const size_t start, const BinKind kind, const BinFields& fields)
 {
     ParseNode* result;
-    switch(kind) {
+    switch (kind) {
       case BinKind::ArrayBinding:
         MOZ_TRY_VAR(result, parseInterfaceArrayBinding(start, kind, fields));
-
         break;
       case BinKind::BindingIdentifier:
         MOZ_TRY_VAR(result, parseInterfaceBindingIdentifier(start, kind, fields));
-
         break;
       case BinKind::BindingWithInitializer:
         MOZ_TRY_VAR(result, parseInterfaceBindingWithInitializer(start, kind, fields));
-
         break;
       case BinKind::ObjectBinding:
         MOZ_TRY_VAR(result, parseInterfaceObjectBinding(start, kind, fields));
-
         break;
       default:
         return raiseInvalidKind("BindingOrBindingWithInitializer", kind);
     }
     return result;
 }
 
 /*
@@ -383,24 +359,22 @@ BinASTParser<Tok>::parseBindingPattern()
     MOZ_TRY(guard.done());
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseSumBindingPattern(const size_t start, const BinKind kind, const BinFields& fields)
 {
     ParseNode* result;
-    switch(kind) {
+    switch (kind) {
       case BinKind::ArrayBinding:
         MOZ_TRY_VAR(result, parseInterfaceArrayBinding(start, kind, fields));
-
         break;
       case BinKind::ObjectBinding:
         MOZ_TRY_VAR(result, parseInterfaceObjectBinding(start, kind, fields));
-
         break;
       default:
         return raiseInvalidKind("BindingPattern", kind);
     }
     return result;
 }
 
 /*
@@ -422,24 +396,22 @@ BinASTParser<Tok>::parseBindingProperty(
     MOZ_TRY(guard.done());
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseSumBindingProperty(const size_t start, const BinKind kind, const BinFields& fields)
 {
     ParseNode* result;
-    switch(kind) {
+    switch (kind) {
       case BinKind::BindingPropertyIdentifier:
         MOZ_TRY_VAR(result, parseInterfaceBindingPropertyIdentifier(start, kind, fields));
-
         break;
       case BinKind::BindingPropertyProperty:
         MOZ_TRY_VAR(result, parseInterfaceBindingPropertyProperty(start, kind, fields));
-
         break;
       default:
         return raiseInvalidKind("BindingProperty", kind);
     }
     return result;
 }
 
 /*
@@ -464,36 +436,31 @@ BinASTParser<Tok>::parseExportDeclaratio
     MOZ_TRY(guard.done());
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseSumExportDeclaration(const size_t start, const BinKind kind, const BinFields& fields)
 {
     ParseNode* result;
-    switch(kind) {
+    switch (kind) {
       case BinKind::Export:
         MOZ_TRY_VAR(result, parseInterfaceExport(start, kind, fields));
-
         break;
       case BinKind::ExportAllFrom:
         MOZ_TRY_VAR(result, parseInterfaceExportAllFrom(start, kind, fields));
-
         break;
       case BinKind::ExportDefault:
         MOZ_TRY_VAR(result, parseInterfaceExportDefault(start, kind, fields));
-
         break;
       case BinKind::ExportFrom:
         MOZ_TRY_VAR(result, parseInterfaceExportFrom(start, kind, fields));
-
         break;
       case BinKind::ExportLocals:
         MOZ_TRY_VAR(result, parseInterfaceExportLocals(start, kind, fields));
-
         break;
       default:
         return raiseInvalidKind("ExportDeclaration", kind);
     }
     return result;
 }
 
 /*
@@ -543,136 +510,106 @@ BinASTParser<Tok>::parseExpression()
     MOZ_TRY(guard.done());
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseSumExpression(const size_t start, const BinKind kind, const BinFields& fields)
 {
     ParseNode* result;
-    switch(kind) {
+    switch (kind) {
       case BinKind::ArrayExpression:
         MOZ_TRY_VAR(result, parseInterfaceArrayExpression(start, kind, fields));
-
         break;
       case BinKind::AssignmentExpression:
         MOZ_TRY_VAR(result, parseInterfaceAssignmentExpression(start, kind, fields));
-
         break;
       case BinKind::AwaitExpression:
         MOZ_TRY_VAR(result, parseInterfaceAwaitExpression(start, kind, fields));
-
         break;
       case BinKind::BinaryExpression:
         MOZ_TRY_VAR(result, parseInterfaceBinaryExpression(start, kind, fields));
-
         break;
       case BinKind::CallExpression:
         MOZ_TRY_VAR(result, parseInterfaceCallExpression(start, kind, fields));
-
         break;
       case BinKind::ClassExpression:
         MOZ_TRY_VAR(result, parseInterfaceClassExpression(start, kind, fields));
-
         break;
       case BinKind::CompoundAssignmentExpression:
         MOZ_TRY_VAR(result, parseInterfaceCompoundAssignmentExpression(start, kind, fields));
-
         break;
       case BinKind::ComputedMemberExpression:
         MOZ_TRY_VAR(result, parseInterfaceComputedMemberExpression(start, kind, fields));
-
         break;
       case BinKind::ConditionalExpression:
         MOZ_TRY_VAR(result, parseInterfaceConditionalExpression(start, kind, fields));
-
         break;
       case BinKind::EagerArrowExpression:
         MOZ_TRY_VAR(result, parseInterfaceEagerArrowExpression(start, kind, fields));
-
         break;
       case BinKind::EagerFunctionExpression:
         MOZ_TRY_VAR(result, parseInterfaceEagerFunctionExpression(start, kind, fields));
-
         break;
       case BinKind::IdentifierExpression:
         MOZ_TRY_VAR(result, parseInterfaceIdentifierExpression(start, kind, fields));
-
         break;
       case BinKind::LiteralBooleanExpression:
         MOZ_TRY_VAR(result, parseInterfaceLiteralBooleanExpression(start, kind, fields));
-
         break;
       case BinKind::LiteralInfinityExpression:
         MOZ_TRY_VAR(result, parseInterfaceLiteralInfinityExpression(start, kind, fields));
-
         break;
       case BinKind::LiteralNullExpression:
         MOZ_TRY_VAR(result, parseInterfaceLiteralNullExpression(start, kind, fields));
-
         break;
       case BinKind::LiteralNumericExpression:
         MOZ_TRY_VAR(result, parseInterfaceLiteralNumericExpression(start, kind, fields));
-
         break;
       case BinKind::LiteralRegExpExpression:
         MOZ_TRY_VAR(result, parseInterfaceLiteralRegExpExpression(start, kind, fields));
-
         break;
       case BinKind::LiteralStringExpression:
         MOZ_TRY_VAR(result, parseInterfaceLiteralStringExpression(start, kind, fields));
-
         break;
       case BinKind::NewExpression:
         MOZ_TRY_VAR(result, parseInterfaceNewExpression(start, kind, fields));
-
         break;
       case BinKind::NewTargetExpression:
         MOZ_TRY_VAR(result, parseInterfaceNewTargetExpression(start, kind, fields));
-
         break;
       case BinKind::ObjectExpression:
         MOZ_TRY_VAR(result, parseInterfaceObjectExpression(start, kind, fields));
-
         break;
       case BinKind::SkippableArrowExpression:
         MOZ_TRY_VAR(result, parseInterfaceSkippableArrowExpression(start, kind, fields));
-
         break;
       case BinKind::SkippableFunctionExpression:
         MOZ_TRY_VAR(result, parseInterfaceSkippableFunctionExpression(start, kind, fields));
-
         break;
       case BinKind::StaticMemberExpression:
         MOZ_TRY_VAR(result, parseInterfaceStaticMemberExpression(start, kind, fields));
-
         break;
       case BinKind::TemplateExpression:
         MOZ_TRY_VAR(result, parseInterfaceTemplateExpression(start, kind, fields));
-
         break;
       case BinKind::ThisExpression:
         MOZ_TRY_VAR(result, parseInterfaceThisExpression(start, kind, fields));
-
         break;
       case BinKind::UnaryExpression:
         MOZ_TRY_VAR(result, parseInterfaceUnaryExpression(start, kind, fields));
-
         break;
       case BinKind::UpdateExpression:
         MOZ_TRY_VAR(result, parseInterfaceUpdateExpression(start, kind, fields));
-
         break;
       case BinKind::YieldExpression:
         MOZ_TRY_VAR(result, parseInterfaceYieldExpression(start, kind, fields));
-
         break;
       case BinKind::YieldStarExpression:
         MOZ_TRY_VAR(result, parseInterfaceYieldStarExpression(start, kind, fields));
-
         break;
       default:
         return raiseInvalidKind("Expression", kind);
     }
     return result;
 }
 
 /*
@@ -723,140 +660,109 @@ BinASTParser<Tok>::parseExpressionOrSupe
     MOZ_TRY(guard.done());
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseSumExpressionOrSuper(const size_t start, const BinKind kind, const BinFields& fields)
 {
     ParseNode* result;
-    switch(kind) {
+    switch (kind) {
       case BinKind::ArrayExpression:
         MOZ_TRY_VAR(result, parseInterfaceArrayExpression(start, kind, fields));
-
         break;
       case BinKind::AssignmentExpression:
         MOZ_TRY_VAR(result, parseInterfaceAssignmentExpression(start, kind, fields));
-
         break;
       case BinKind::AwaitExpression:
         MOZ_TRY_VAR(result, parseInterfaceAwaitExpression(start, kind, fields));
-
         break;
       case BinKind::BinaryExpression:
         MOZ_TRY_VAR(result, parseInterfaceBinaryExpression(start, kind, fields));
-
         break;
       case BinKind::CallExpression:
         MOZ_TRY_VAR(result, parseInterfaceCallExpression(start, kind, fields));
-
         break;
       case BinKind::ClassExpression:
         MOZ_TRY_VAR(result, parseInterfaceClassExpression(start, kind, fields));
-
         break;
       case BinKind::CompoundAssignmentExpression:
         MOZ_TRY_VAR(result, parseInterfaceCompoundAssignmentExpression(start, kind, fields));
-
         break;
       case BinKind::ComputedMemberExpression:
         MOZ_TRY_VAR(result, parseInterfaceComputedMemberExpression(start, kind, fields));
-
         break;
       case BinKind::ConditionalExpression:
         MOZ_TRY_VAR(result, parseInterfaceConditionalExpression(start, kind, fields));
-
         break;
       case BinKind::EagerArrowExpression:
         MOZ_TRY_VAR(result, parseInterfaceEagerArrowExpression(start, kind, fields));
-
         break;
       case BinKind::EagerFunctionExpression:
         MOZ_TRY_VAR(result, parseInterfaceEagerFunctionExpression(start, kind, fields));
-
         break;
       case BinKind::IdentifierExpression:
         MOZ_TRY_VAR(result, parseInterfaceIdentifierExpression(start, kind, fields));
-
         break;
       case BinKind::LiteralBooleanExpression:
         MOZ_TRY_VAR(result, parseInterfaceLiteralBooleanExpression(start, kind, fields));
-
         break;
       case BinKind::LiteralInfinityExpression:
         MOZ_TRY_VAR(result, parseInterfaceLiteralInfinityExpression(start, kind, fields));
-
         break;
       case BinKind::LiteralNullExpression:
         MOZ_TRY_VAR(result, parseInterfaceLiteralNullExpression(start, kind, fields));
-
         break;
       case BinKind::LiteralNumericExpression:
         MOZ_TRY_VAR(result, parseInterfaceLiteralNumericExpression(start, kind, fields));
-
         break;
       case BinKind::LiteralRegExpExpression:
         MOZ_TRY_VAR(result, parseInterfaceLiteralRegExpExpression(start, kind, fields));
-
         break;
       case BinKind::LiteralStringExpression:
         MOZ_TRY_VAR(result, parseInterfaceLiteralStringExpression(start, kind, fields));
-
         break;
       case BinKind::NewExpression:
         MOZ_TRY_VAR(result, parseInterfaceNewExpression(start, kind, fields));
-
         break;
       case BinKind::NewTargetExpression:
         MOZ_TRY_VAR(result, parseInterfaceNewTargetExpression(start, kind, fields));
-
         break;
       case BinKind::ObjectExpression:
         MOZ_TRY_VAR(result, parseInterfaceObjectExpression(start, kind, fields));
-
         break;
       case BinKind::SkippableArrowExpression:
         MOZ_TRY_VAR(result, parseInterfaceSkippableArrowExpression(start, kind, fields));
-
         break;
       case BinKind::SkippableFunctionExpression:
         MOZ_TRY_VAR(result, parseInterfaceSkippableFunctionExpression(start, kind, fields));
-
         break;
       case BinKind::StaticMemberExpression:
         MOZ_TRY_VAR(result, parseInterfaceStaticMemberExpression(start, kind, fields));
-
         break;
       case BinKind::Super:
         MOZ_TRY_VAR(result, parseInterfaceSuper(start, kind, fields));
-
         break;
       case BinKind::TemplateExpression:
         MOZ_TRY_VAR(result, parseInterfaceTemplateExpression(start, kind, fields));
-
         break;
       case BinKind::ThisExpression:
         MOZ_TRY_VAR(result, parseInterfaceThisExpression(start, kind, fields));
-
         break;
       case BinKind::UnaryExpression:
         MOZ_TRY_VAR(result, parseInterfaceUnaryExpression(start, kind, fields));
-
         break;
       case BinKind::UpdateExpression:
         MOZ_TRY_VAR(result, parseInterfaceUpdateExpression(start, kind, fields));
-
         break;
       case BinKind::YieldExpression:
         MOZ_TRY_VAR(result, parseInterfaceYieldExpression(start, kind, fields));
-
         break;
       case BinKind::YieldStarExpression:
         MOZ_TRY_VAR(result, parseInterfaceYieldStarExpression(start, kind, fields));
-
         break;
       default:
         return raiseInvalidKind("ExpressionOrSuper", kind);
     }
     return result;
 }
 
 /*
@@ -907,140 +813,109 @@ BinASTParser<Tok>::parseExpressionOrTemp
     MOZ_TRY(guard.done());
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseSumExpressionOrTemplateElement(const size_t start, const BinKind kind, const BinFields& fields)
 {
     ParseNode* result;
-    switch(kind) {
+    switch (kind) {
       case BinKind::ArrayExpression:
         MOZ_TRY_VAR(result, parseInterfaceArrayExpression(start, kind, fields));
-
         break;
       case BinKind::AssignmentExpression:
         MOZ_TRY_VAR(result, parseInterfaceAssignmentExpression(start, kind, fields));
-
         break;
       case BinKind::AwaitExpression:
         MOZ_TRY_VAR(result, parseInterfaceAwaitExpression(start, kind, fields));
-
         break;
       case BinKind::BinaryExpression:
         MOZ_TRY_VAR(result, parseInterfaceBinaryExpression(start, kind, fields));
-
         break;
       case BinKind::CallExpression:
         MOZ_TRY_VAR(result, parseInterfaceCallExpression(start, kind, fields));
-
         break;
       case BinKind::ClassExpression:
         MOZ_TRY_VAR(result, parseInterfaceClassExpression(start, kind, fields));
-
         break;
       case BinKind::CompoundAssignmentExpression:
         MOZ_TRY_VAR(result, parseInterfaceCompoundAssignmentExpression(start, kind, fields));
-
         break;
       case BinKind::ComputedMemberExpression:
         MOZ_TRY_VAR(result, parseInterfaceComputedMemberExpression(start, kind, fields));
-
         break;
       case BinKind::ConditionalExpression:
         MOZ_TRY_VAR(result, parseInterfaceConditionalExpression(start, kind, fields));
-
         break;
       case BinKind::EagerArrowExpression:
         MOZ_TRY_VAR(result, parseInterfaceEagerArrowExpression(start, kind, fields));
-
         break;
       case BinKind::EagerFunctionExpression:
         MOZ_TRY_VAR(result, parseInterfaceEagerFunctionExpression(start, kind, fields));
-
         break;
       case BinKind::IdentifierExpression:
         MOZ_TRY_VAR(result, parseInterfaceIdentifierExpression(start, kind, fields));
-
         break;
       case BinKind::LiteralBooleanExpression:
         MOZ_TRY_VAR(result, parseInterfaceLiteralBooleanExpression(start, kind, fields));
-
         break;
       case BinKind::LiteralInfinityExpression:
         MOZ_TRY_VAR(result, parseInterfaceLiteralInfinityExpression(start, kind, fields));
-
         break;
       case BinKind::LiteralNullExpression:
         MOZ_TRY_VAR(result, parseInterfaceLiteralNullExpression(start, kind, fields));
-
         break;
       case BinKind::LiteralNumericExpression:
         MOZ_TRY_VAR(result, parseInterfaceLiteralNumericExpression(start, kind, fields));
-
         break;
       case BinKind::LiteralRegExpExpression:
         MOZ_TRY_VAR(result, parseInterfaceLiteralRegExpExpression(start, kind, fields));
-
         break;
       case BinKind::LiteralStringExpression:
         MOZ_TRY_VAR(result, parseInterfaceLiteralStringExpression(start, kind, fields));
-
         break;
       case BinKind::NewExpression:
         MOZ_TRY_VAR(result, parseInterfaceNewExpression(start, kind, fields));
-
         break;
       case BinKind::NewTargetExpression:
         MOZ_TRY_VAR(result, parseInterfaceNewTargetExpression(start, kind, fields));
-
         break;
       case BinKind::ObjectExpression:
         MOZ_TRY_VAR(result, parseInterfaceObjectExpression(start, kind, fields));
-
         break;
       case BinKind::SkippableArrowExpression:
         MOZ_TRY_VAR(result, parseInterfaceSkippableArrowExpression(start, kind, fields));
-
         break;
       case BinKind::SkippableFunctionExpression:
         MOZ_TRY_VAR(result, parseInterfaceSkippableFunctionExpression(start, kind, fields));
-
         break;
       case BinKind::StaticMemberExpression:
         MOZ_TRY_VAR(result, parseInterfaceStaticMemberExpression(start, kind, fields));
-
         break;
       case BinKind::TemplateElement:
         MOZ_TRY_VAR(result, parseInterfaceTemplateElement(start, kind, fields));
-
         break;
       case BinKind::TemplateExpression:
         MOZ_TRY_VAR(result, parseInterfaceTemplateExpression(start, kind, fields));
-
         break;
       case BinKind::ThisExpression:
         MOZ_TRY_VAR(result, parseInterfaceThisExpression(start, kind, fields));
-
         break;
       case BinKind::UnaryExpression:
         MOZ_TRY_VAR(result, parseInterfaceUnaryExpression(start, kind, fields));
-
         break;
       case BinKind::UpdateExpression:
         MOZ_TRY_VAR(result, parseInterfaceUpdateExpression(start, kind, fields));
-
         break;
       case BinKind::YieldExpression:
         MOZ_TRY_VAR(result, parseInterfaceYieldExpression(start, kind, fields));
-
         break;
       case BinKind::YieldStarExpression:
         MOZ_TRY_VAR(result, parseInterfaceYieldStarExpression(start, kind, fields));
-
         break;
       default:
         return raiseInvalidKind("ExpressionOrTemplateElement", kind);
     }
     return result;
 }
 
 /*
@@ -1066,40 +941,34 @@ BinASTParser<Tok>::parseForInOfBindingOr
     MOZ_TRY(guard.done());
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseSumForInOfBindingOrAssignmentTarget(const size_t start, const BinKind kind, const BinFields& fields)
 {
     ParseNode* result;
-    switch(kind) {
+    switch (kind) {
       case BinKind::ArrayAssignmentTarget:
         MOZ_TRY_VAR(result, parseInterfaceArrayAssignmentTarget(start, kind, fields));
-
         break;
       case BinKind::AssignmentTargetIdentifier:
         MOZ_TRY_VAR(result, parseInterfaceAssignmentTargetIdentifier(start, kind, fields));
-
         break;
       case BinKind::ComputedMemberAssignmentTarget:
         MOZ_TRY_VAR(result, parseInterfaceComputedMemberAssignmentTarget(start, kind, fields));
-
         break;
       case BinKind::ForInOfBinding:
         MOZ_TRY_VAR(result, parseInterfaceForInOfBinding(start, kind, fields));
-
         break;
       case BinKind::ObjectAssignmentTarget:
         MOZ_TRY_VAR(result, parseInterfaceObjectAssignmentTarget(start, kind, fields));
-
         break;
       case BinKind::StaticMemberAssignmentTarget:
         MOZ_TRY_VAR(result, parseInterfaceStaticMemberAssignmentTarget(start, kind, fields));
-
         break;
       default:
         return raiseInvalidKind("ForInOfBindingOrAssignmentTarget", kind);
     }
     return result;
 }
 
 /*
@@ -1150,140 +1019,109 @@ BinASTParser<Tok>::parseFunctionBodyOrEx
     MOZ_TRY(guard.done());
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseSumFunctionBodyOrExpression(const size_t start, const BinKind kind, const BinFields& fields)
 {
     ParseNode* result;
-    switch(kind) {
+    switch (kind) {
       case BinKind::ArrayExpression:
         MOZ_TRY_VAR(result, parseInterfaceArrayExpression(start, kind, fields));
-
         break;
       case BinKind::AssignmentExpression:
         MOZ_TRY_VAR(result, parseInterfaceAssignmentExpression(start, kind, fields));
-
         break;
       case BinKind::AwaitExpression:
         MOZ_TRY_VAR(result, parseInterfaceAwaitExpression(start, kind, fields));
-
         break;
       case BinKind::BinaryExpression:
         MOZ_TRY_VAR(result, parseInterfaceBinaryExpression(start, kind, fields));
-
         break;
       case BinKind::CallExpression:
         MOZ_TRY_VAR(result, parseInterfaceCallExpression(start, kind, fields));
-
         break;
       case BinKind::ClassExpression:
         MOZ_TRY_VAR(result, parseInterfaceClassExpression(start, kind, fields));
-
         break;
       case BinKind::CompoundAssignmentExpression:
         MOZ_TRY_VAR(result, parseInterfaceCompoundAssignmentExpression(start, kind, fields));
-
         break;
       case BinKind::ComputedMemberExpression:
         MOZ_TRY_VAR(result, parseInterfaceComputedMemberExpression(start, kind, fields));
-
         break;
       case BinKind::ConditionalExpression:
         MOZ_TRY_VAR(result, parseInterfaceConditionalExpression(start, kind, fields));
-
         break;
       case BinKind::EagerArrowExpression:
         MOZ_TRY_VAR(result, parseInterfaceEagerArrowExpression(start, kind, fields));
-
         break;
       case BinKind::EagerFunctionExpression:
         MOZ_TRY_VAR(result, parseInterfaceEagerFunctionExpression(start, kind, fields));
-
         break;
       case BinKind::FunctionBody:
         MOZ_TRY_VAR(result, parseInterfaceFunctionBody(start, kind, fields));
-
         break;
       case BinKind::IdentifierExpression:
         MOZ_TRY_VAR(result, parseInterfaceIdentifierExpression(start, kind, fields));
-
         break;
       case BinKind::LiteralBooleanExpression:
         MOZ_TRY_VAR(result, parseInterfaceLiteralBooleanExpression(start, kind, fields));
-
         break;
       case BinKind::LiteralInfinityExpression:
         MOZ_TRY_VAR(result, parseInterfaceLiteralInfinityExpression(start, kind, fields));
-
         break;
       case BinKind::LiteralNullExpression:
         MOZ_TRY_VAR(result, parseInterfaceLiteralNullExpression(start, kind, fields));
-
         break;
       case BinKind::LiteralNumericExpression:
         MOZ_TRY_VAR(result, parseInterfaceLiteralNumericExpression(start, kind, fields));
-
         break;
       case BinKind::LiteralRegExpExpression:
         MOZ_TRY_VAR(result, parseInterfaceLiteralRegExpExpression(start, kind, fields));
-
         break;
       case BinKind::LiteralStringExpression:
         MOZ_TRY_VAR(result, parseInterfaceLiteralStringExpression(start, kind, fields));
-
         break;
       case BinKind::NewExpression:
         MOZ_TRY_VAR(result, parseInterfaceNewExpression(start, kind, fields));
-
         break;
       case BinKind::NewTargetExpression:
         MOZ_TRY_VAR(result, parseInterfaceNewTargetExpression(start, kind, fields));
-
         break;
       case BinKind::ObjectExpression:
         MOZ_TRY_VAR(result, parseInterfaceObjectExpression(start, kind, fields));
-
         break;
       case BinKind::SkippableArrowExpression:
         MOZ_TRY_VAR(result, parseInterfaceSkippableArrowExpression(start, kind, fields));
-
         break;
       case BinKind::SkippableFunctionExpression:
         MOZ_TRY_VAR(result, parseInterfaceSkippableFunctionExpression(start, kind, fields));
-
         break;
       case BinKind::StaticMemberExpression:
         MOZ_TRY_VAR(result, parseInterfaceStaticMemberExpression(start, kind, fields));
-
         break;
       case BinKind::TemplateExpression:
         MOZ_TRY_VAR(result, parseInterfaceTemplateExpression(start, kind, fields));
-
         break;
       case BinKind::ThisExpression:
         MOZ_TRY_VAR(result, parseInterfaceThisExpression(start, kind, fields));
-
         break;
       case BinKind::UnaryExpression:
         MOZ_TRY_VAR(result, parseInterfaceUnaryExpression(start, kind, fields));
-
         break;
       case BinKind::UpdateExpression:
         MOZ_TRY_VAR(result, parseInterfaceUpdateExpression(start, kind, fields));
-
         break;
       case BinKind::YieldExpression:
         MOZ_TRY_VAR(result, parseInterfaceYieldExpression(start, kind, fields));
-
         break;
       case BinKind::YieldStarExpression:
         MOZ_TRY_VAR(result, parseInterfaceYieldStarExpression(start, kind, fields));
-
         break;
       default:
         return raiseInvalidKind("FunctionBodyOrExpression", kind);
     }
     return result;
 }
 
 /*
@@ -1305,24 +1143,22 @@ BinASTParser<Tok>::parseFunctionDeclarat
     MOZ_TRY(guard.done());
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseSumFunctionDeclaration(const size_t start, const BinKind kind, const BinFields& fields)
 {
     ParseNode* result;
-    switch(kind) {
+    switch (kind) {
       case BinKind::EagerFunctionDeclaration:
         MOZ_TRY_VAR(result, parseInterfaceEagerFunctionDeclaration(start, kind, fields));
-
         break;
       case BinKind::SkippableFunctionDeclaration:
         MOZ_TRY_VAR(result, parseInterfaceSkippableFunctionDeclaration(start, kind, fields));
-
         break;
       default:
         return raiseInvalidKind("FunctionDeclaration", kind);
     }
     return result;
 }
 
 /*
@@ -1375,148 +1211,115 @@ BinASTParser<Tok>::parseFunctionDeclarat
     MOZ_TRY(guard.done());
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseSumFunctionDeclarationOrClassDeclarationOrExpression(const size_t start, const BinKind kind, const BinFields& fields)
 {
     ParseNode* result;
-    switch(kind) {
+    switch (kind) {
       case BinKind::ArrayExpression:
         MOZ_TRY_VAR(result, parseInterfaceArrayExpression(start, kind, fields));
-
         break;
       case BinKind::AssignmentExpression:
         MOZ_TRY_VAR(result, parseInterfaceAssignmentExpression(start, kind, fields));
-
         break;
       case BinKind::AwaitExpression:
         MOZ_TRY_VAR(result, parseInterfaceAwaitExpression(start, kind, fields));
-
         break;
       case BinKind::BinaryExpression:
         MOZ_TRY_VAR(result, parseInterfaceBinaryExpression(start, kind, fields));
-
         break;
       case BinKind::CallExpression:
         MOZ_TRY_VAR(result, parseInterfaceCallExpression(start, kind, fields));
-
         break;
       case BinKind::ClassDeclaration:
         MOZ_TRY_VAR(result, parseInterfaceClassDeclaration(start, kind, fields));
-
         break;
       case BinKind::ClassExpression:
         MOZ_TRY_VAR(result, parseInterfaceClassExpression(start, kind, fields));
-
         break;
       case BinKind::CompoundAssignmentExpression:
         MOZ_TRY_VAR(result, parseInterfaceCompoundAssignmentExpression(start, kind, fields));
-
         break;
       case BinKind::ComputedMemberExpression:
         MOZ_TRY_VAR(result, parseInterfaceComputedMemberExpression(start, kind, fields));
-
         break;
       case BinKind::ConditionalExpression:
         MOZ_TRY_VAR(result, parseInterfaceConditionalExpression(start, kind, fields));
-
         break;
       case BinKind::EagerArrowExpression:
         MOZ_TRY_VAR(result, parseInterfaceEagerArrowExpression(start, kind, fields));
-
         break;
       case BinKind::EagerFunctionDeclaration:
         MOZ_TRY_VAR(result, parseInterfaceEagerFunctionDeclaration(start, kind, fields));
-
         break;
       case BinKind::EagerFunctionExpression:
         MOZ_TRY_VAR(result, parseInterfaceEagerFunctionExpression(start, kind, fields));
-
         break;
       case BinKind::IdentifierExpression:
         MOZ_TRY_VAR(result, parseInterfaceIdentifierExpression(start, kind, fields));
-
         break;
       case BinKind::LiteralBooleanExpression:
         MOZ_TRY_VAR(result, parseInterfaceLiteralBooleanExpression(start, kind, fields));
-
         break;
       case BinKind::LiteralInfinityExpression:
         MOZ_TRY_VAR(result, parseInterfaceLiteralInfinityExpression(start, kind, fields));
-
         break;
       case BinKind::LiteralNullExpression:
         MOZ_TRY_VAR(result, parseInterfaceLiteralNullExpression(start, kind, fields));
-
         break;
       case BinKind::LiteralNumericExpression:
         MOZ_TRY_VAR(result, parseInterfaceLiteralNumericExpression(start, kind, fields));
-
         break;
       case BinKind::LiteralRegExpExpression:
         MOZ_TRY_VAR(result, parseInterfaceLiteralRegExpExpression(start, kind, fields));
-
         break;
       case BinKind::LiteralStringExpression:
         MOZ_TRY_VAR(result, parseInterfaceLiteralStringExpression(start, kind, fields));
-
         break;
       case BinKind::NewExpression:
         MOZ_TRY_VAR(result, parseInterfaceNewExpression(start, kind, fields));
-
         break;
       case BinKind::NewTargetExpression:
         MOZ_TRY_VAR(result, parseInterfaceNewTargetExpression(start, kind, fields));
-
         break;
       case BinKind::ObjectExpression:
         MOZ_TRY_VAR(result, parseInterfaceObjectExpression(start, kind, fields));
-
         break;
       case BinKind::SkippableArrowExpression:
         MOZ_TRY_VAR(result, parseInterfaceSkippableArrowExpression(start, kind, fields));
-
         break;
       case BinKind::SkippableFunctionDeclaration:
         MOZ_TRY_VAR(result, parseInterfaceSkippableFunctionDeclaration(start, kind, fields));
-
         break;
       case BinKind::SkippableFunctionExpression:
         MOZ_TRY_VAR(result, parseInterfaceSkippableFunctionExpression(start, kind, fields));
-
         break;
       case BinKind::StaticMemberExpression:
         MOZ_TRY_VAR(result, parseInterfaceStaticMemberExpression(start, kind, fields));
-
         break;
       case BinKind::TemplateExpression:
         MOZ_TRY_VAR(result, parseInterfaceTemplateExpression(start, kind, fields));
-
         break;
       case BinKind::ThisExpression:
         MOZ_TRY_VAR(result, parseInterfaceThisExpression(start, kind, fields));
-
         break;
       case BinKind::UnaryExpression:
         MOZ_TRY_VAR(result, parseInterfaceUnaryExpression(start, kind, fields));
-
         break;
       case BinKind::UpdateExpression:
         MOZ_TRY_VAR(result, parseInterfaceUpdateExpression(start, kind, fields));
-
         break;
       case BinKind::YieldExpression:
         MOZ_TRY_VAR(result, parseInterfaceYieldExpression(start, kind, fields));
-
         break;
       case BinKind::YieldStarExpression:
         MOZ_TRY_VAR(result, parseInterfaceYieldStarExpression(start, kind, fields));
-
         break;
       default:
         return raiseInvalidKind("FunctionDeclarationOrClassDeclarationOrExpression", kind);
     }
     return result;
 }
 
 /*
@@ -1540,32 +1343,28 @@ BinASTParser<Tok>::parseFunctionDeclarat
     MOZ_TRY(guard.done());
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseSumFunctionDeclarationOrClassDeclarationOrVariableDeclaration(const size_t start, const BinKind kind, const BinFields& fields)
 {
     ParseNode* result;
-    switch(kind) {
+    switch (kind) {
       case BinKind::ClassDeclaration:
         MOZ_TRY_VAR(result, parseInterfaceClassDeclaration(start, kind, fields));
-
         break;
       case BinKind::EagerFunctionDeclaration:
         MOZ_TRY_VAR(result, parseInterfaceEagerFunctionDeclaration(start, kind, fields));
-
         break;
       case BinKind::SkippableFunctionDeclaration:
         MOZ_TRY_VAR(result, parseInterfaceSkippableFunctionDeclaration(start, kind, fields));
-
         break;
       case BinKind::VariableDeclaration:
         MOZ_TRY_VAR(result, parseInterfaceVariableDeclaration(start, kind, fields));
-
         break;
       default:
         return raiseInvalidKind("FunctionDeclarationOrClassDeclarationOrVariableDeclaration", kind);
     }
     return result;
 }
 
 /*
@@ -1587,24 +1386,22 @@ BinASTParser<Tok>::parseFunctionExpressi
     MOZ_TRY(guard.done());
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseSumFunctionExpression(const size_t start, const BinKind kind, const BinFields& fields)
 {
     ParseNode* result;
-    switch(kind) {
+    switch (kind) {
       case BinKind::EagerFunctionExpression:
         MOZ_TRY_VAR(result, parseInterfaceEagerFunctionExpression(start, kind, fields));
-
         break;
       case BinKind::SkippableFunctionExpression:
         MOZ_TRY_VAR(result, parseInterfaceSkippableFunctionExpression(start, kind, fields));
-
         break;
       default:
         return raiseInvalidKind("FunctionExpression", kind);
     }
     return result;
 }
 
 /*
@@ -1626,24 +1423,22 @@ BinASTParser<Tok>::parseGetter()
     MOZ_TRY(guard.done());
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseSumGetter(const size_t start, const BinKind kind, const BinFields& fields)
 {
     ParseNode* result;
-    switch(kind) {
+    switch (kind) {
       case BinKind::EagerGetter:
         MOZ_TRY_VAR(result, parseInterfaceEagerGetter(start, kind, fields));
-
         break;
       case BinKind::SkippableGetter:
         MOZ_TRY_VAR(result, parseInterfaceSkippableGetter(start, kind, fields));
-
         break;
       default:
         return raiseInvalidKind("Getter", kind);
     }
     return result;
 }
 
 /*
@@ -1665,24 +1460,22 @@ BinASTParser<Tok>::parseImportDeclaratio
     MOZ_TRY(guard.done());
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseSumImportDeclaration(const size_t start, const BinKind kind, const BinFields& fields)
 {
     ParseNode* result;
-    switch(kind) {
+    switch (kind) {
       case BinKind::Import:
         MOZ_TRY_VAR(result, parseInterfaceImport(start, kind, fields));
-
         break;
       case BinKind::ImportNamespace:
         MOZ_TRY_VAR(result, parseInterfaceImportNamespace(start, kind, fields));
-
         break;
       default:
         return raiseInvalidKind("ImportDeclaration", kind);
     }
     return result;
 }
 
 /*
@@ -1733,140 +1526,109 @@ BinASTParser<Tok>::parseImportDeclaratio
     MOZ_TRY(guard.done());
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseSumImportDeclarationOrExportDeclarationOrStatement(const size_t start, const BinKind kind, const BinFields& fields)
 {
     ParseNode* result;
-    switch(kind) {
+    switch (kind) {
       case BinKind::Block:
         MOZ_TRY_VAR(result, parseInterfaceBlock(start, kind, fields));
-
         break;
       case BinKind::BreakStatement:
         MOZ_TRY_VAR(result, parseInterfaceBreakStatement(start, kind, fields));
-
         break;
       case BinKind::ClassDeclaration:
         MOZ_TRY_VAR(result, parseInterfaceClassDeclaration(start, kind, fields));
-
         break;
       case BinKind::ContinueStatement:
         MOZ_TRY_VAR(result, parseInterfaceContinueStatement(start, kind, fields));
-
         break;
       case BinKind::DebuggerStatement:
         MOZ_TRY_VAR(result, parseInterfaceDebuggerStatement(start, kind, fields));
-
         break;
       case BinKind::DoWhileStatement:
         MOZ_TRY_VAR(result, parseInterfaceDoWhileStatement(start, kind, fields));
-
         break;
       case BinKind::EagerFunctionDeclaration:
         MOZ_TRY_VAR(result, parseInterfaceEagerFunctionDeclaration(start, kind, fields));
-
         break;
       case BinKind::EmptyStatement:
         MOZ_TRY_VAR(result, parseInterfaceEmptyStatement(start, kind, fields));
-
         break;
       case BinKind::Export:
         MOZ_TRY_VAR(result, parseInterfaceExport(start, kind, fields));
-
         break;
       case BinKind::ExportAllFrom:
         MOZ_TRY_VAR(result, parseInterfaceExportAllFrom(start, kind, fields));
-
         break;
       case BinKind::ExportDefault:
         MOZ_TRY_VAR(result, parseInterfaceExportDefault(start, kind, fields));
-
         break;
       case BinKind::ExportFrom:
         MOZ_TRY_VAR(result, parseInterfaceExportFrom(start, kind, fields));
-
         break;
       case BinKind::ExportLocals:
         MOZ_TRY_VAR(result, parseInterfaceExportLocals(start, kind, fields));
-
         break;
       case BinKind::ExpressionStatement:
         MOZ_TRY_VAR(result, parseInterfaceExpressionStatement(start, kind, fields));
-
         break;
       case BinKind::ForInStatement:
         MOZ_TRY_VAR(result, parseInterfaceForInStatement(start, kind, fields));
-
         break;
       case BinKind::ForOfStatement:
         MOZ_TRY_VAR(result, parseInterfaceForOfStatement(start, kind, fields));
-
         break;
       case BinKind::ForStatement:
         MOZ_TRY_VAR(result, parseInterfaceForStatement(start, kind, fields));
-
         break;
       case BinKind::IfStatement:
         MOZ_TRY_VAR(result, parseInterfaceIfStatement(start, kind, fields));
-
         break;
       case BinKind::Import:
         MOZ_TRY_VAR(result, parseInterfaceImport(start, kind, fields));
-
         break;
       case BinKind::ImportNamespace:
         MOZ_TRY_VAR(result, parseInterfaceImportNamespace(start, kind, fields));
-
         break;
       case BinKind::LabelledStatement:
         MOZ_TRY_VAR(result, parseInterfaceLabelledStatement(start, kind, fields));
-
         break;
       case BinKind::ReturnStatement:
         MOZ_TRY_VAR(result, parseInterfaceReturnStatement(start, kind, fields));
-
         break;
       case BinKind::SkippableFunctionDeclaration:
         MOZ_TRY_VAR(result, parseInterfaceSkippableFunctionDeclaration(start, kind, fields));
-
         break;
       case BinKind::SwitchStatement:
         MOZ_TRY_VAR(result, parseInterfaceSwitchStatement(start, kind, fields));
-
         break;
       case BinKind::SwitchStatementWithDefault:
         MOZ_TRY_VAR(result, parseInterfaceSwitchStatementWithDefault(start, kind, fields));
-
         break;
       case BinKind::ThrowStatement:
         MOZ_TRY_VAR(result, parseInterfaceThrowStatement(start, kind, fields));
-
         break;
       case BinKind::TryCatchStatement:
         MOZ_TRY_VAR(result, parseInterfaceTryCatchStatement(start, kind, fields));
-
         break;
       case BinKind::TryFinallyStatement:
         MOZ_TRY_VAR(result, parseInterfaceTryFinallyStatement(start, kind, fields));
-
         break;
       case BinKind::VariableDeclaration:
         MOZ_TRY_VAR(result, parseInterfaceVariableDeclaration(start, kind, fields));
-
         break;
       case BinKind::WhileStatement:
         MOZ_TRY_VAR(result, parseInterfaceWhileStatement(start, kind, fields));
-
         break;
       case BinKind::WithStatement:
         MOZ_TRY_VAR(result, parseInterfaceWithStatement(start, kind, fields));
-
         break;
       default:
         return raiseInvalidKind("ImportDeclarationOrExportDeclarationOrStatement", kind);
     }
     return result;
 }
 
 /*
@@ -1891,36 +1653,31 @@ BinASTParser<Tok>::parseIterationStateme
     MOZ_TRY(guard.done());
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseSumIterationStatement(const size_t start, const BinKind kind, const BinFields& fields)
 {
     ParseNode* result;
-    switch(kind) {
+    switch (kind) {
       case BinKind::DoWhileStatement:
         MOZ_TRY_VAR(result, parseInterfaceDoWhileStatement(start, kind, fields));
-
         break;
       case BinKind::ForInStatement:
         MOZ_TRY_VAR(result, parseInterfaceForInStatement(start, kind, fields));
-
         break;
       case BinKind::ForOfStatement:
         MOZ_TRY_VAR(result, parseInterfaceForOfStatement(start, kind, fields));
-
         break;
       case BinKind::ForStatement:
         MOZ_TRY_VAR(result, parseInterfaceForStatement(start, kind, fields));
-
         break;
       case BinKind::WhileStatement:
         MOZ_TRY_VAR(result, parseInterfaceWhileStatement(start, kind, fields));
-
         break;
       default:
         return raiseInvalidKind("IterationStatement", kind);
     }
     return result;
 }
 
 /*
@@ -1945,36 +1702,31 @@ BinASTParser<Tok>::parseLiteral()
     MOZ_TRY(guard.done());
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseSumLiteral(const size_t start, const BinKind kind, const BinFields& fields)
 {
     ParseNode* result;
-    switch(kind) {
+    switch (kind) {
       case BinKind::LiteralBooleanExpression:
         MOZ_TRY_VAR(result, parseInterfaceLiteralBooleanExpression(start, kind, fields));
-
         break;
       case BinKind::LiteralInfinityExpression:
         MOZ_TRY_VAR(result, parseInterfaceLiteralInfinityExpression(start, kind, fields));
-
         break;
       case BinKind::LiteralNullExpression:
         MOZ_TRY_VAR(result, parseInterfaceLiteralNullExpression(start, kind, fields));
-
         break;
       case BinKind::LiteralNumericExpression:
         MOZ_TRY_VAR(result, parseInterfaceLiteralNumericExpression(start, kind, fields));
-
         break;
       case BinKind::LiteralStringExpression:
         MOZ_TRY_VAR(result, parseInterfaceLiteralStringExpression(start, kind, fields));
-
         break;
       default:
         return raiseInvalidKind("Literal", kind);
     }
     return result;
 }
 
 /*
@@ -1996,24 +1748,22 @@ BinASTParser<Tok>::parseMethod()
     MOZ_TRY(guard.done());
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseSumMethod(const size_t start, const BinKind kind, const BinFields& fields)
 {
     ParseNode* result;
-    switch(kind) {
+    switch (kind) {
       case BinKind::EagerMethod:
         MOZ_TRY_VAR(result, parseInterfaceEagerMethod(start, kind, fields));
-
         break;
       case BinKind::SkippableMethod:
         MOZ_TRY_VAR(result, parseInterfaceSkippableMethod(start, kind, fields));
-
         break;
       default:
         return raiseInvalidKind("Method", kind);
     }
     return result;
 }
 
 /*
@@ -2039,40 +1789,34 @@ BinASTParser<Tok>::parseMethodDefinition
     MOZ_TRY(guard.done());
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseSumMethodDefinition(const size_t start, const BinKind kind, const BinFields& fields)
 {
     ParseNode* result;
-    switch(kind) {
+    switch (kind) {
       case BinKind::EagerGetter:
         MOZ_TRY_VAR(result, parseInterfaceEagerGetter(start, kind, fields));
-
         break;
       case BinKind::EagerMethod:
         MOZ_TRY_VAR(result, parseInterfaceEagerMethod(start, kind, fields));
-
         break;
       case BinKind::EagerSetter:
         MOZ_TRY_VAR(result, parseInterfaceEagerSetter(start, kind, fields));
-
         break;
       case BinKind::SkippableGetter:
         MOZ_TRY_VAR(result, parseInterfaceSkippableGetter(start, kind, fields));
-
         break;
       case BinKind::SkippableMethod:
         MOZ_TRY_VAR(result, parseInterfaceSkippableMethod(start, kind, fields));
-
         break;
       case BinKind::SkippableSetter:
         MOZ_TRY_VAR(result, parseInterfaceSkippableSetter(start, kind, fields));
-
         break;
       default:
         return raiseInvalidKind("MethodDefinition", kind);
     }
     return result;
 }
 
 /*
@@ -2100,48 +1844,40 @@ BinASTParser<Tok>::parseObjectProperty()
     MOZ_TRY(guard.done());
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseSumObjectProperty(const size_t start, const BinKind kind, const BinFields& fields)
 {
     ParseNode* result;
-    switch(kind) {
+    switch (kind) {
       case BinKind::DataProperty:
         MOZ_TRY_VAR(result, parseInterfaceDataProperty(start, kind, fields));
-
         break;
       case BinKind::EagerGetter:
         MOZ_TRY_VAR(result, parseInterfaceEagerGetter(start, kind, fields));
-
         break;
       case BinKind::EagerMethod:
         MOZ_TRY_VAR(result, parseInterfaceEagerMethod(start, kind, fields));
-
         break;
       case BinKind::EagerSetter:
         MOZ_TRY_VAR(result, parseInterfaceEagerSetter(start, kind, fields));
-
         break;
       case BinKind::ShorthandProperty:
         MOZ_TRY_VAR(result, parseInterfaceShorthandProperty(start, kind, fields));
-
         break;
       case BinKind::SkippableGetter:
         MOZ_TRY_VAR(result, parseInterfaceSkippableGetter(start, kind, fields));
-
         break;
       case BinKind::SkippableMethod:
         MOZ_TRY_VAR(result, parseInterfaceSkippableMethod(start, kind, fields));
-
         break;
       case BinKind::SkippableSetter:
         MOZ_TRY_VAR(result, parseInterfaceSkippableSetter(start, kind, fields));
-
         break;
       default:
         return raiseInvalidKind("ObjectProperty", kind);
     }
     return result;
 }
 
 /*
@@ -2165,35 +1901,32 @@ BinASTParser<Tok>::parseParameter()
     MOZ_TRY(guard.done());
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseSumParameter(const size_t start, const BinKind kind, const BinFields& fields)
 {
     ParseNode* result;
-    switch(kind) {
+    switch (kind) {
       case BinKind::ArrayBinding:
         MOZ_TRY_VAR(result, parseInterfaceArrayBinding(start, kind, fields));
-
         break;
       case BinKind::BindingIdentifier:
         MOZ_TRY_VAR(result, parseInterfaceBindingIdentifier(start, kind, fields));
         if (!parseContext_->positionalFormalParameterNames().append(result->pn_atom))
             return raiseOOM();
         if (parseContext_->isFunctionBox())
             parseContext_->functionBox()->length++;
         break;
       case BinKind::BindingWithInitializer:
         MOZ_TRY_VAR(result, parseInterfaceBindingWithInitializer(start, kind, fields));
-
         break;
       case BinKind::ObjectBinding:
         MOZ_TRY_VAR(result, parseInterfaceObjectBinding(start, kind, fields));
-
         break;
       default:
         return raiseInvalidKind("Parameter", kind);
     }
     return result;
 }
 
 /*
@@ -2215,24 +1948,22 @@ BinASTParser<Tok>::parseProgram()
     MOZ_TRY(guard.done());
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseSumProgram(const size_t start, const BinKind kind, const BinFields& fields)
 {
     ParseNode* result;
-    switch(kind) {
+    switch (kind) {
       case BinKind::Module:
         MOZ_TRY_VAR(result, parseInterfaceModule(start, kind, fields));
-
         break;
       case BinKind::Script:
         MOZ_TRY_VAR(result, parseInterfaceScript(start, kind, fields));
-
         break;
       default:
         return raiseInvalidKind("Program", kind);
     }
     return result;
 }
 
 /*
@@ -2254,24 +1985,22 @@ BinASTParser<Tok>::parsePropertyName()
     MOZ_TRY(guard.done());
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseSumPropertyName(const size_t start, const BinKind kind, const BinFields& fields)
 {
     ParseNode* result;
-    switch(kind) {
+    switch (kind) {
       case BinKind::ComputedPropertyName:
         MOZ_TRY_VAR(result, parseInterfaceComputedPropertyName(start, kind, fields));
-
         break;
       case BinKind::LiteralPropertyName:
         MOZ_TRY_VAR(result, parseInterfaceLiteralPropertyName(start, kind, fields));
-
         break;
       default:
         return raiseInvalidKind("PropertyName", kind);
     }
     return result;
 }
 
 /*
@@ -2293,24 +2022,22 @@ BinASTParser<Tok>::parseSetter()
     MOZ_TRY(guard.done());
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseSumSetter(const size_t start, const BinKind kind, const BinFields& fields)
 {
     ParseNode* result;
-    switch(kind) {
+    switch (kind) {
       case BinKind::EagerSetter:
         MOZ_TRY_VAR(result, parseInterfaceEagerSetter(start, kind, fields));
-
         break;
       case BinKind::SkippableSetter:
         MOZ_TRY_VAR(result, parseInterfaceSkippableSetter(start, kind, fields));
-
         break;
       default:
         return raiseInvalidKind("Setter", kind);
     }
     return result;
 }
 
 /*
@@ -2333,28 +2060,25 @@ BinASTParser<Tok>::parseSimpleAssignment
     MOZ_TRY(guard.done());
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseSumSimpleAssignmentTarget(const size_t start, const BinKind kind, const BinFields& fields)
 {
     ParseNode* result;
-    switch(kind) {
+    switch (kind) {
       case BinKind::AssignmentTargetIdentifier:
         MOZ_TRY_VAR(result, parseInterfaceAssignmentTargetIdentifier(start, kind, fields));
-
         break;
       case BinKind::ComputedMemberAssignmentTarget:
         MOZ_TRY_VAR(result, parseInterfaceComputedMemberAssignmentTarget(start, kind, fields));
-
         break;
       case BinKind::StaticMemberAssignmentTarget:
         MOZ_TRY_VAR(result, parseInterfaceStaticMemberAssignmentTarget(start, kind, fields));
-
         break;
       default:
         return raiseInvalidKind("SimpleAssignmentTarget", kind);
     }
     return result;
 }
 
 /*
@@ -2405,140 +2129,109 @@ BinASTParser<Tok>::parseSpreadElementOrE
     MOZ_TRY(guard.done());
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseSumSpreadElementOrExpression(const size_t start, const BinKind kind, const BinFields& fields)
 {
     ParseNode* result;
-    switch(kind) {
+    switch (kind) {
       case BinKind::ArrayExpression:
         MOZ_TRY_VAR(result, parseInterfaceArrayExpression(start, kind, fields));
-
         break;
       case BinKind::AssignmentExpression:
         MOZ_TRY_VAR(result, parseInterfaceAssignmentExpression(start, kind, fields));
-
         break;
       case BinKind::AwaitExpression:
         MOZ_TRY_VAR(result, parseInterfaceAwaitExpression(start, kind, fields));
-
         break;
       case BinKind::BinaryExpression:
         MOZ_TRY_VAR(result, parseInterfaceBinaryExpression(start, kind, fields));
-
         break;
       case BinKind::CallExpression:
         MOZ_TRY_VAR(result, parseInterfaceCallExpression(start, kind, fields));
-
         break;
       case BinKind::ClassExpression:
         MOZ_TRY_VAR(result, parseInterfaceClassExpression(start, kind, fields));
-
         break;
       case BinKind::CompoundAssignmentExpression:
         MOZ_TRY_VAR(result, parseInterfaceCompoundAssignmentExpression(start, kind, fields));
-
         break;
       case BinKind::ComputedMemberExpression:
         MOZ_TRY_VAR(result, parseInterfaceComputedMemberExpression(start, kind, fields));
-
         break;
       case BinKind::ConditionalExpression:
         MOZ_TRY_VAR(result, parseInterfaceConditionalExpression(start, kind, fields));
-
         break;
       case BinKind::EagerArrowExpression:
         MOZ_TRY_VAR(result, parseInterfaceEagerArrowExpression(start, kind, fields));
-
         break;
       case BinKind::EagerFunctionExpression:
         MOZ_TRY_VAR(result, parseInterfaceEagerFunctionExpression(start, kind, fields));
-
         break;
       case BinKind::IdentifierExpression:
         MOZ_TRY_VAR(result, parseInterfaceIdentifierExpression(start, kind, fields));
-
         break;
       case BinKind::LiteralBooleanExpression:
         MOZ_TRY_VAR(result, parseInterfaceLiteralBooleanExpression(start, kind, fields));
-
         break;
       case BinKind::LiteralInfinityExpression:
         MOZ_TRY_VAR(result, parseInterfaceLiteralInfinityExpression(start, kind, fields));
-
         break;
       case BinKind::LiteralNullExpression:
         MOZ_TRY_VAR(result, parseInterfaceLiteralNullExpression(start, kind, fields));
-
         break;
       case BinKind::LiteralNumericExpression:
         MOZ_TRY_VAR(result, parseInterfaceLiteralNumericExpression(start, kind, fields));
-
         break;
       case BinKind::LiteralRegExpExpression:
         MOZ_TRY_VAR(result, parseInterfaceLiteralRegExpExpression(start, kind, fields));
-
         break;
       case BinKind::LiteralStringExpression:
         MOZ_TRY_VAR(result, parseInterfaceLiteralStringExpression(start, kind, fields));
-
         break;
       case BinKind::NewExpression:
         MOZ_TRY_VAR(result, parseInterfaceNewExpression(start, kind, fields));
-
         break;
       case BinKind::NewTargetExpression:
         MOZ_TRY_VAR(result, parseInterfaceNewTargetExpression(start, kind, fields));
-
         break;
       case BinKind::ObjectExpression:
         MOZ_TRY_VAR(result, parseInterfaceObjectExpression(start, kind, fields));
-
         break;
       case BinKind::SkippableArrowExpression:
         MOZ_TRY_VAR(result, parseInterfaceSkippableArrowExpression(start, kind, fields));
-
         break;
       case BinKind::SkippableFunctionExpression:
         MOZ_TRY_VAR(result, parseInterfaceSkippableFunctionExpression(start, kind, fields));
-
         break;
       case BinKind::SpreadElement:
         MOZ_TRY_VAR(result, parseInterfaceSpreadElement(start, kind, fields));
-
         break;
       case BinKind::StaticMemberExpression:
         MOZ_TRY_VAR(result, parseInterfaceStaticMemberExpression(start, kind, fields));
-
         break;
       case BinKind::TemplateExpression:
         MOZ_TRY_VAR(result, parseInterfaceTemplateExpression(start, kind, fields));
-
         break;
       case BinKind::ThisExpression:
         MOZ_TRY_VAR(result, parseInterfaceThisExpression(start, kind, fields));
-
         break;
       case BinKind::UnaryExpression:
         MOZ_TRY_VAR(result, parseInterfaceUnaryExpression(start, kind, fields));
-
         break;
       case BinKind::UpdateExpression:
         MOZ_TRY_VAR(result, parseInterfaceUpdateExpression(start, kind, fields));
-
         break;
       case BinKind::YieldExpression:
         MOZ_TRY_VAR(result, parseInterfaceYieldExpression(start, kind, fields));
-
         break;
       case BinKind::YieldStarExpression:
         MOZ_TRY_VAR(result, parseInterfaceYieldStarExpression(start, kind, fields));
-
         break;
       default:
         return raiseInvalidKind("SpreadElementOrExpression", kind);
     }
     return result;
 }
 
 /*
@@ -2582,112 +2275,88 @@ BinASTParser<Tok>::parseStatement()
     MOZ_TRY(guard.done());
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseSumStatement(const size_t start, const BinKind kind, const BinFields& fields)
 {
     ParseNode* result;
-    switch(kind) {
+    switch (kind) {
       case BinKind::Block:
         MOZ_TRY_VAR(result, parseInterfaceBlock(start, kind, fields));
-
         break;
       case BinKind::BreakStatement:
         MOZ_TRY_VAR(result, parseInterfaceBreakStatement(start, kind, fields));
-
         break;
       case BinKind::ClassDeclaration:
         MOZ_TRY_VAR(result, parseInterfaceClassDeclaration(start, kind, fields));
-
         break;
       case BinKind::ContinueStatement:
         MOZ_TRY_VAR(result, parseInterfaceContinueStatement(start, kind, fields));
-
         break;
       case BinKind::DebuggerStatement:
         MOZ_TRY_VAR(result, parseInterfaceDebuggerStatement(start, kind, fields));
-
         break;
       case BinKind::DoWhileStatement:
         MOZ_TRY_VAR(result, parseInterfaceDoWhileStatement(start, kind, fields));
-
         break;
       case BinKind::EagerFunctionDeclaration:
         MOZ_TRY_VAR(result, parseInterfaceEagerFunctionDeclaration(start, kind, fields));
-
         break;
       case BinKind::EmptyStatement:
         MOZ_TRY_VAR(result, parseInterfaceEmptyStatement(start, kind, fields));
-
         break;
       case BinKind::ExpressionStatement:
         MOZ_TRY_VAR(result, parseInterfaceExpressionStatement(start, kind, fields));
-
         break;
       case BinKind::ForInStatement:
         MOZ_TRY_VAR(result, parseInterfaceForInStatement(start, kind, fields));
-
         break;
       case BinKind::ForOfStatement:
         MOZ_TRY_VAR(result, parseInterfaceForOfStatement(start, kind, fields));
-
         break;
       case BinKind::ForStatement:
         MOZ_TRY_VAR(result, parseInterfaceForStatement(start, kind, fields));
-
         break;
       case BinKind::IfStatement:
         MOZ_TRY_VAR(result, parseInterfaceIfStatement(start, kind, fields));
-
         break;
       case BinKind::LabelledStatement:
         MOZ_TRY_VAR(result, parseInterfaceLabelledStatement(start, kind, fields));
-
         break;
       case BinKind::ReturnStatement:
         MOZ_TRY_VAR(result, parseInterfaceReturnStatement(start, kind, fields));
-
         break;
       case BinKind::SkippableFunctionDeclaration:
         MOZ_TRY_VAR(result, parseInterfaceSkippableFunctionDeclaration(start, kind, fields));
-
         break;
       case BinKind::SwitchStatement:
         MOZ_TRY_VAR(result, parseInterfaceSwitchStatement(start, kind, fields));
-
         break;
       case BinKind::SwitchStatementWithDefault:
         MOZ_TRY_VAR(result, parseInterfaceSwitchStatementWithDefault(start, kind, fields));
-
         break;
       case BinKind::ThrowStatement:
         MOZ_TRY_VAR(result, parseInterfaceThrowStatement(start, kind, fields));
-
         break;
       case BinKind::TryCatchStatement:
         MOZ_TRY_VAR(result, parseInterfaceTryCatchStatement(start, kind, fields));
-
         break;
       case BinKind::TryFinallyStatement:
         MOZ_TRY_VAR(result, parseInterfaceTryFinallyStatement(start, kind, fields));
-
         break;
       case BinKind::VariableDeclaration:
         MOZ_TRY_VAR(result, parseInterfaceVariableDeclaration(start, kind, fields));
-
         break;
       case BinKind::WhileStatement:
         MOZ_TRY_VAR(result, parseInterfaceWhileStatement(start, kind, fields));
-
         break;
       case BinKind::WithStatement:
         MOZ_TRY_VAR(result, parseInterfaceWithStatement(start, kind, fields));
-
         break;
       default:
         return raiseInvalidKind("Statement", kind);
     }
     return result;
 }
 
 /*
@@ -2738,140 +2407,109 @@ BinASTParser<Tok>::parseVariableDeclarat
     MOZ_TRY(guard.done());
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseSumVariableDeclarationOrExpression(const size_t start, const BinKind kind, const BinFields& fields)
 {
     ParseNode* result;
-    switch(kind) {
+    switch (kind) {
       case BinKind::ArrayExpression:
         MOZ_TRY_VAR(result, parseInterfaceArrayExpression(start, kind, fields));
-
         break;
       case BinKind::AssignmentExpression:
         MOZ_TRY_VAR(result, parseInterfaceAssignmentExpression(start, kind, fields));
-
         break;
       case BinKind::AwaitExpression:
         MOZ_TRY_VAR(result, parseInterfaceAwaitExpression(start, kind, fields));
-
         break;
       case BinKind::BinaryExpression:
         MOZ_TRY_VAR(result, parseInterfaceBinaryExpression(start, kind, fields));
-
         break;
       case BinKind::CallExpression:
         MOZ_TRY_VAR(result, parseInterfaceCallExpression(start, kind, fields));
-
         break;
       case BinKind::ClassExpression:
         MOZ_TRY_VAR(result, parseInterfaceClassExpression(start, kind, fields));
-
         break;
       case BinKind::CompoundAssignmentExpression:
         MOZ_TRY_VAR(result, parseInterfaceCompoundAssignmentExpression(start, kind, fields));
-
         break;
       case BinKind::ComputedMemberExpression:
         MOZ_TRY_VAR(result, parseInterfaceComputedMemberExpression(start, kind, fields));
-
         break;
       case BinKind::ConditionalExpression:
         MOZ_TRY_VAR(result, parseInterfaceConditionalExpression(start, kind, fields));
-
         break;
       case BinKind::EagerArrowExpression:
         MOZ_TRY_VAR(result, parseInterfaceEagerArrowExpression(start, kind, fields));
-
         break;
       case BinKind::EagerFunctionExpression:
         MOZ_TRY_VAR(result, parseInterfaceEagerFunctionExpression(start, kind, fields));
-
         break;
       case BinKind::IdentifierExpression:
         MOZ_TRY_VAR(result, parseInterfaceIdentifierExpression(start, kind, fields));
-
         break;
       case BinKind::LiteralBooleanExpression:
         MOZ_TRY_VAR(result, parseInterfaceLiteralBooleanExpression(start, kind, fields));
-
         break;
       case BinKind::LiteralInfinityExpression:
         MOZ_TRY_VAR(result, parseInterfaceLiteralInfinityExpression(start, kind, fields));
-
         break;
       case BinKind::LiteralNullExpression:
         MOZ_TRY_VAR(result, parseInterfaceLiteralNullExpression(start, kind, fields));
-
         break;
       case BinKind::LiteralNumericExpression:
         MOZ_TRY_VAR(result, parseInterfaceLiteralNumericExpression(start, kind, fields));
-
         break;
       case BinKind::LiteralRegExpExpression:
         MOZ_TRY_VAR(result, parseInterfaceLiteralRegExpExpression(start, kind, fields));
-
         break;
       case BinKind::LiteralStringExpression:
         MOZ_TRY_VAR(result, parseInterfaceLiteralStringExpression(start, kind, fields));
-
         break;
       case BinKind::NewExpression:
         MOZ_TRY_VAR(result, parseInterfaceNewExpression(start, kind, fields));
-
         break;
       case BinKind::NewTargetExpression:
         MOZ_TRY_VAR(result, parseInterfaceNewTargetExpression(start, kind, fields));
-
         break;
       case BinKind::ObjectExpression:
         MOZ_TRY_VAR(result, parseInterfaceObjectExpression(start, kind, fields));
-
         break;
       case BinKind::SkippableArrowExpression:
         MOZ_TRY_VAR(result, parseInterfaceSkippableArrowExpression(start, kind, fields));
-
         break;
       case BinKind::SkippableFunctionExpression:
         MOZ_TRY_VAR(result, parseInterfaceSkippableFunctionExpression(start, kind, fields));
-
         break;
       case BinKind::StaticMemberExpression:
         MOZ_TRY_VAR(result, parseInterfaceStaticMemberExpression(start, kind, fields));
-
         break;
       case BinKind::TemplateExpression:
         MOZ_TRY_VAR(result, parseInterfaceTemplateExpression(start, kind, fields));
-
         break;
       case BinKind::ThisExpression:
         MOZ_TRY_VAR(result, parseInterfaceThisExpression(start, kind, fields));
-
         break;
       case BinKind::UnaryExpression:
         MOZ_TRY_VAR(result, parseInterfaceUnaryExpression(start, kind, fields));
-
         break;
       case BinKind::UpdateExpression:
         MOZ_TRY_VAR(result, parseInterfaceUpdateExpression(start, kind, fields));
-
         break;
       case BinKind::VariableDeclaration:
         MOZ_TRY_VAR(result, parseInterfaceVariableDeclaration(start, kind, fields));
-
         break;
       case BinKind::YieldExpression:
         MOZ_TRY_VAR(result, parseInterfaceYieldExpression(start, kind, fields));
-
         break;
       case BinKind::YieldStarExpression:
         MOZ_TRY_VAR(result, parseInterfaceYieldStarExpression(start, kind, fields));
-
         break;
       default:
         return raiseInvalidKind("VariableDeclarationOrExpression", kind);
     }
     return result;
 }
 
 
@@ -2886,18 +2524,20 @@ BinASTParser<Tok>::parseSumVariableDecla
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseNull()
 {
     BinKind kind;
     BinFields fields(cx_);
     AutoTaggedTuple guard(*tokenizer_);
 
     MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    const auto start = tokenizer_->offset();
-
+    if (kind != BinKind::_Null) {
+        return raiseInvalidKind("_Null", kind);
+    }
+    const auto start = tokenizer_->offset();
     BINJS_MOZ_TRY_DECL(result, parseInterfaceNull(start, kind, fields));
     MOZ_TRY(guard.done());
 
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceNull(const size_t start, const BinKind kind, const BinFields& fields)
@@ -2915,18 +2555,20 @@ BinASTParser<Tok>::parseInterfaceNull(co
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseArrayAssignmentTarget()
 {
     BinKind kind;
     BinFields fields(cx_);
     AutoTaggedTuple guard(*tokenizer_);
 
     MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    const auto start = tokenizer_->offset();
-
+    if (kind != BinKind::ArrayAssignmentTarget) {
+        return raiseInvalidKind("ArrayAssignmentTarget", kind);
+    }
+    const auto start = tokenizer_->offset();
     BINJS_MOZ_TRY_DECL(result, parseInterfaceArrayAssignmentTarget(start, kind, fields));
     MOZ_TRY(guard.done());
 
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceArrayAssignmentTarget(const size_t start, const BinKind kind, const BinFields& fields)
@@ -2944,18 +2586,20 @@ BinASTParser<Tok>::parseInterfaceArrayAs
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseArrayBinding()
 {
     BinKind kind;
     BinFields fields(cx_);
     AutoTaggedTuple guard(*tokenizer_);
 
     MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    const auto start = tokenizer_->offset();
-
+    if (kind != BinKind::ArrayBinding) {
+        return raiseInvalidKind("ArrayBinding", kind);
+    }
+    const auto start = tokenizer_->offset();
     BINJS_MOZ_TRY_DECL(result, parseInterfaceArrayBinding(start, kind, fields));
     MOZ_TRY(guard.done());
 
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceArrayBinding(const size_t start, const BinKind kind, const BinFields& fields)
@@ -2972,42 +2616,39 @@ BinASTParser<Tok>::parseInterfaceArrayBi
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseArrayExpression()
 {
     BinKind kind;
     BinFields fields(cx_);
     AutoTaggedTuple guard(*tokenizer_);
 
     MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    const auto start = tokenizer_->offset();
-
+    if (kind != BinKind::ArrayExpression) {
+        return raiseInvalidKind("ArrayExpression", kind);
+    }
+    const auto start = tokenizer_->offset();
     BINJS_MOZ_TRY_DECL(result, parseInterfaceArrayExpression(start, kind, fields));
     MOZ_TRY(guard.done());
 
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceArrayExpression(const size_t start, const BinKind kind, const BinFields& fields)
 {
     MOZ_ASSERT(kind == BinKind::ArrayExpression);
     BINJS_TRY(CheckRecursionLimit(cx_));
 
-
 #if defined(DEBUG)
     const BinField expected_fields[1] = { BinField::Elements };
     MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif // defined(DEBUG)
 
-
-
-
     BINJS_MOZ_TRY_DECL(elements, parseListOfOptionalSpreadElementOrExpression());
 
-
     auto result = elements;
     return result;
 }
 
 
 /*
  interface AssertedBlockScope : Node {
     FrozenArray<IdentifierName> lexicallyDeclaredNames;
@@ -3018,47 +2659,44 @@ BinASTParser<Tok>::parseInterfaceArrayEx
 template<typename Tok> JS::Result<Ok>
 BinASTParser<Tok>::parseAssertedBlockScope()
 {
     BinKind kind;
     BinFields fields(cx_);
     AutoTaggedTuple guard(*tokenizer_);
 
     MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    const auto start = tokenizer_->offset();
-
+    if (kind != BinKind::AssertedBlockScope) {
+        return raiseInvalidKind("AssertedBlockScope", kind);
+    }
+    const auto start = tokenizer_->offset();
     BINJS_MOZ_TRY_DECL(result, parseInterfaceAssertedBlockScope(start, kind, fields));
     MOZ_TRY(guard.done());
 
     return result;
 }
 
 template<typename Tok> JS::Result<Ok>
 BinASTParser<Tok>::parseInterfaceAssertedBlockScope(const size_t start, const BinKind kind, const BinFields& fields)
 {
     MOZ_ASSERT(kind == BinKind::AssertedBlockScope);
     BINJS_TRY(CheckRecursionLimit(cx_));
 
-
 #if defined(DEBUG)
     const BinField expected_fields[3] = { BinField::LexicallyDeclaredNames, BinField::CapturedNames, BinField::HasDirectEval };
     MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif // defined(DEBUG)
-
     MOZ_TRY(parseAndUpdateScopeNames(*parseContext_->innermostScope(), DeclarationKind::Let));
     MOZ_TRY(parseAndUpdateCapturedNames(kind));
 
-
-
     BINJS_MOZ_TRY_DECL(hasDirectEval, tokenizer_->readBool());
     if (hasDirectEval) {
         parseContext_->sc()->setHasDirectEval();
         parseContext_->sc()->setBindingsAccessedDynamically();
     }
-
     if (hasDirectEval && parseContext_->isFunctionBox() && !parseContext_->sc()->strict()) {
         // In non-strict mode code, direct calls to eval can
         // add variables to the call object.
         parseContext_->functionBox()->setHasExtensibleScope();
     }
     auto result = Ok();
     return result;
 }
@@ -3074,55 +2712,52 @@ BinASTParser<Tok>::parseInterfaceAsserte
 template<typename Tok> JS::Result<Ok>
 BinASTParser<Tok>::parseAssertedParameterScope()
 {
     BinKind kind;
     BinFields fields(cx_);
     AutoTaggedTuple guard(*tokenizer_);
 
     MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    const auto start = tokenizer_->offset();
-
+    if (kind != BinKind::AssertedParameterScope) {
+        return raiseInvalidKind("AssertedParameterScope", kind);
+    }
+    const auto start = tokenizer_->offset();
     BINJS_MOZ_TRY_DECL(result, parseInterfaceAssertedParameterScope(start, kind, fields));
     MOZ_TRY(guard.done());
 
     return result;
 }
 
 template<typename Tok> JS::Result<Ok>
 BinASTParser<Tok>::parseInterfaceAssertedParameterScope(const size_t start, const BinKind kind, const BinFields& fields)
 {
     MOZ_ASSERT(kind == BinKind::AssertedParameterScope);
     BINJS_TRY(CheckRecursionLimit(cx_));
 
-
 #if defined(DEBUG)
     const BinField expected_fields[3] = { BinField::ParameterNames, BinField::CapturedNames, BinField::HasDirectEval };
     MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif // defined(DEBUG)
-
     ParseContext::Statement* inStatement = parseContext_->innermostStatement();
 
     // If we are in a `CatchClause`, the binding is a implicit CatchParameter
     // and it goes into the innermost scope. Otherwise, we're in a function,
     // so it goes in the function scope.
     if (inStatement && inStatement->kind() == StatementKind::Catch)
         MOZ_TRY(parseAndUpdateScopeNames(*parseContext_->innermostScope(), DeclarationKind::CatchParameter));
     else
         MOZ_TRY(parseAndUpdateScopeNames(parseContext_->functionScope(), DeclarationKind::PositionalFormalParameter));
     MOZ_TRY(parseAndUpdateCapturedNames(kind));
 
-
-
     BINJS_MOZ_TRY_DECL(hasDirectEval, tokenizer_->readBool());
     if (hasDirectEval) {
         parseContext_->sc()->setHasDirectEval();
         parseContext_->sc()->setBindingsAccessedDynamically();
     }
-
     if (hasDirectEval && parseContext_->isFunctionBox() && !parseContext_->sc()->strict()) {
         // In non-strict mode code, direct calls to eval can
         // add variables to the call object.
         parseContext_->functionBox()->setHasExtensibleScope();
     }
     auto result = Ok();
     return result;
 }
@@ -3139,48 +2774,45 @@ BinASTParser<Tok>::parseInterfaceAsserte
 template<typename Tok> JS::Result<Ok>
 BinASTParser<Tok>::parseAssertedVarScope()
 {
     BinKind kind;
     BinFields fields(cx_);
     AutoTaggedTuple guard(*tokenizer_);
 
     MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    const auto start = tokenizer_->offset();
-
+    if (kind != BinKind::AssertedVarScope) {
+        return raiseInvalidKind("AssertedVarScope", kind);
+    }
+    const auto start = tokenizer_->offset();
     BINJS_MOZ_TRY_DECL(result, parseInterfaceAssertedVarScope(start, kind, fields));
     MOZ_TRY(guard.done());
 
     return result;
 }
 
 template<typename Tok> JS::Result<Ok>
 BinASTParser<Tok>::parseInterfaceAssertedVarScope(const size_t start, const BinKind kind, const BinFields& fields)
 {
     MOZ_ASSERT(kind == BinKind::AssertedVarScope);
     BINJS_TRY(CheckRecursionLimit(cx_));
 
-
 #if defined(DEBUG)
     const BinField expected_fields[4] = { BinField::LexicallyDeclaredNames, BinField::VarDeclaredNames, BinField::CapturedNames, BinField::HasDirectEval };
     MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif // defined(DEBUG)
-
     MOZ_TRY(parseAndUpdateScopeNames(*parseContext_->innermostScope(), DeclarationKind::Let));
     MOZ_TRY(parseAndUpdateScopeNames(parseContext_->varScope(), DeclarationKind::Var));
     MOZ_TRY(parseAndUpdateCapturedNames(kind));
 
-
-
     BINJS_MOZ_TRY_DECL(hasDirectEval, tokenizer_->readBool());
     if (hasDirectEval) {
         parseContext_->sc()->setHasDirectEval();
         parseContext_->sc()->setBindingsAccessedDynamically();
     }
-
     if (hasDirectEval && parseContext_->isFunctionBox() && !parseContext_->sc()->strict()) {
         // In non-strict mode code, direct calls to eval can
         // add variables to the call object.
         parseContext_->functionBox()->setHasExtensibleScope();
     }
     auto result = Ok();
     return result;
 }
@@ -3195,47 +2827,41 @@ BinASTParser<Tok>::parseInterfaceAsserte
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseAssignmentExpression()
 {
     BinKind kind;
     BinFields fields(cx_);
     AutoTaggedTuple guard(*tokenizer_);
 
     MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    const auto start = tokenizer_->offset();
-
+    if (kind != BinKind::AssignmentExpression) {
+        return raiseInvalidKind("AssignmentExpression", kind);
+    }
+    const auto start = tokenizer_->offset();
     BINJS_MOZ_TRY_DECL(result, parseInterfaceAssignmentExpression(start, kind, fields));
     MOZ_TRY(guard.done());
 
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceAssignmentExpression(const size_t start, const BinKind kind, const BinFields& fields)
 {
     MOZ_ASSERT(kind == BinKind::AssignmentExpression);
     BINJS_TRY(CheckRecursionLimit(cx_));
 
-
 #if defined(DEBUG)
     const BinField expected_fields[2] = { BinField::Binding, BinField::Expression };
     MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif // defined(DEBUG)
 
-
-
-
     BINJS_MOZ_TRY_DECL(binding, parseAssignmentTarget());
 
-
-
-
     BINJS_MOZ_TRY_DECL(expression, parseExpression());
 
-
     BINJS_TRY_DECL(result, factory_.newAssignment(ParseNodeKind::Assign, binding, expression));
     return result;
 }
 
 
 /*
  interface AssignmentTargetIdentifier : Node {
     Identifier name;
@@ -3244,42 +2870,40 @@ BinASTParser<Tok>::parseInterfaceAssignm
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseAssignmentTargetIdentifier()
 {
     BinKind kind;
     BinFields fields(cx_);
     AutoTaggedTuple guard(*tokenizer_);
 
     MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    const auto start = tokenizer_->offset();
-
+    if (kind != BinKind::AssignmentTargetIdentifier) {
+        return raiseInvalidKind("AssignmentTargetIdentifier", kind);
+    }
+    const auto start = tokenizer_->offset();
     BINJS_MOZ_TRY_DECL(result, parseInterfaceAssignmentTargetIdentifier(start, kind, fields));
     MOZ_TRY(guard.done());
 
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceAssignmentTargetIdentifier(const size_t start, const BinKind kind, const BinFields& fields)
 {
     MOZ_ASSERT(kind == BinKind::AssignmentTargetIdentifier);
     BINJS_TRY(CheckRecursionLimit(cx_));
 
-
 #if defined(DEBUG)
     const BinField expected_fields[1] = { BinField::Name };
     MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif // defined(DEBUG)
 
-
-
     RootedAtom name(cx_);
     MOZ_TRY_VAR(name, tokenizer_->readAtom());
 
-
     if (!IsIdentifier(name))
         return raiseError("Invalid identifier");
     BINJS_TRY(usedNames_.noteUse(cx_, name, parseContext_->scriptId(), parseContext_->innermostScope()->id()));
     BINJS_TRY_DECL(result, factory_.newName(name->asPropertyName(), tokenizer_->pos(start), cx_));
     return result;
 }
 
 
@@ -3292,18 +2916,20 @@ BinASTParser<Tok>::parseInterfaceAssignm
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseAssignmentTargetPropertyIdentifier()
 {
     BinKind kind;
     BinFields fields(cx_);
     AutoTaggedTuple guard(*tokenizer_);
 
     MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    const auto start = tokenizer_->offset();
-
+    if (kind != BinKind::AssignmentTargetPropertyIdentifier) {
+        return raiseInvalidKind("AssignmentTargetPropertyIdentifier", kind);
+    }
+    const auto start = tokenizer_->offset();
     BINJS_MOZ_TRY_DECL(result, parseInterfaceAssignmentTargetPropertyIdentifier(start, kind, fields));
     MOZ_TRY(guard.done());
 
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceAssignmentTargetPropertyIdentifier(const size_t start, const BinKind kind, const BinFields& fields)
@@ -3321,18 +2947,20 @@ BinASTParser<Tok>::parseInterfaceAssignm
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseAssignmentTargetPropertyProperty()
 {
     BinKind kind;
     BinFields fields(cx_);
     AutoTaggedTuple guard(*tokenizer_);
 
     MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    const auto start = tokenizer_->offset();
-
+    if (kind != BinKind::AssignmentTargetPropertyProperty) {
+        return raiseInvalidKind("AssignmentTargetPropertyProperty", kind);
+    }
+    const auto start = tokenizer_->offset();
     BINJS_MOZ_TRY_DECL(result, parseInterfaceAssignmentTargetPropertyProperty(start, kind, fields));
     MOZ_TRY(guard.done());
 
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceAssignmentTargetPropertyProperty(const size_t start, const BinKind kind, const BinFields& fields)
@@ -3350,18 +2978,20 @@ BinASTParser<Tok>::parseInterfaceAssignm
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseAssignmentTargetWithInitializer()
 {
     BinKind kind;
     BinFields fields(cx_);
     AutoTaggedTuple guard(*tokenizer_);
 
     MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    const auto start = tokenizer_->offset();
-
+    if (kind != BinKind::AssignmentTargetWithInitializer) {
+        return raiseInvalidKind("AssignmentTargetWithInitializer", kind);
+    }
+    const auto start = tokenizer_->offset();
     BINJS_MOZ_TRY_DECL(result, parseInterfaceAssignmentTargetWithInitializer(start, kind, fields));
     MOZ_TRY(guard.done());
 
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceAssignmentTargetWithInitializer(const size_t start, const BinKind kind, const BinFields& fields)
@@ -3378,18 +3008,20 @@ BinASTParser<Tok>::parseInterfaceAssignm
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseAwaitExpression()
 {
     BinKind kind;
     BinFields fields(cx_);
     AutoTaggedTuple guard(*tokenizer_);
 
     MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    const auto start = tokenizer_->offset();
-
+    if (kind != BinKind::AwaitExpression) {
+        return raiseInvalidKind("AwaitExpression", kind);
+    }
+    const auto start = tokenizer_->offset();
     BINJS_MOZ_TRY_DECL(result, parseInterfaceAwaitExpression(start, kind, fields));
     MOZ_TRY(guard.done());
 
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceAwaitExpression(const size_t start, const BinKind kind, const BinFields& fields)
@@ -3408,52 +3040,43 @@ BinASTParser<Tok>::parseInterfaceAwaitEx
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseBinaryExpression()
 {
     BinKind kind;
     BinFields fields(cx_);
     AutoTaggedTuple guard(*tokenizer_);
 
     MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    const auto start = tokenizer_->offset();
-
+    if (kind != BinKind::BinaryExpression) {
+        return raiseInvalidKind("BinaryExpression", kind);
+    }
+    const auto start = tokenizer_->offset();
     BINJS_MOZ_TRY_DECL(result, parseInterfaceBinaryExpression(start, kind, fields));
     MOZ_TRY(guard.done());
 
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceBinaryExpression(const size_t start, const BinKind kind, const BinFields& fields)
 {
     MOZ_ASSERT(kind == BinKind::BinaryExpression);
     BINJS_TRY(CheckRecursionLimit(cx_));
 
-
 #if defined(DEBUG)
     const BinField expected_fields[3] = { BinField::Operator, BinField::Left, BinField::Right };
     MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif // defined(DEBUG)
 
-
-
-
     BINJS_MOZ_TRY_DECL(operator_, parseBinaryOperator());
 
-
-
-
     BINJS_MOZ_TRY_DECL(left, parseExpression());
 
-
-
-
     BINJS_MOZ_TRY_DECL(right, parseExpression());
 
-
     ParseNodeKind pnk;
     switch (operator_) {
       case BinaryOperator::Comma:
         pnk = ParseNodeKind::Comma;
         break;
       case BinaryOperator::LogicalOr:
         pnk = ParseNodeKind::Or;
         break;
@@ -3554,42 +3177,40 @@ BinASTParser<Tok>::parseInterfaceBinaryE
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseBindingIdentifier()
 {
     BinKind kind;
     BinFields fields(cx_);
     AutoTaggedTuple guard(*tokenizer_);
 
     MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    const auto start = tokenizer_->offset();
-
+    if (kind != BinKind::BindingIdentifier) {
+        return raiseInvalidKind("BindingIdentifier", kind);
+    }
+    const auto start = tokenizer_->offset();
     BINJS_MOZ_TRY_DECL(result, parseInterfaceBindingIdentifier(start, kind, fields));
     MOZ_TRY(guard.done());
 
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceBindingIdentifier(const size_t start, const BinKind kind, const BinFields& fields)
 {
     MOZ_ASSERT(kind == BinKind::BindingIdentifier);
     BINJS_TRY(CheckRecursionLimit(cx_));
 
-
 #if defined(DEBUG)
     const BinField expected_fields[1] = { BinField::Name };
     MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif // defined(DEBUG)
 
-
-
     RootedAtom name(cx_);
     MOZ_TRY_VAR(name, tokenizer_->readAtom());
 
-
     if (!IsIdentifier(name))
         return raiseError("Invalid identifier");
     BINJS_TRY_DECL(result, factory_.newName(name->asPropertyName(), tokenizer_->pos(start), cx_));
     return result;
 }
 
 
 /*
@@ -3601,18 +3222,20 @@ BinASTParser<Tok>::parseInterfaceBinding
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseBindingPropertyIdentifier()
 {
     BinKind kind;
     BinFields fields(cx_);
     AutoTaggedTuple guard(*tokenizer_);
 
     MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    const auto start = tokenizer_->offset();
-
+    if (kind != BinKind::BindingPropertyIdentifier) {
+        return raiseInvalidKind("BindingPropertyIdentifier", kind);
+    }
+    const auto start = tokenizer_->offset();
     BINJS_MOZ_TRY_DECL(result, parseInterfaceBindingPropertyIdentifier(start, kind, fields));
     MOZ_TRY(guard.done());
 
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceBindingPropertyIdentifier(const size_t start, const BinKind kind, const BinFields& fields)
@@ -3630,18 +3253,20 @@ BinASTParser<Tok>::parseInterfaceBinding
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseBindingPropertyProperty()
 {
     BinKind kind;
     BinFields fields(cx_);
     AutoTaggedTuple guard(*tokenizer_);
 
     MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    const auto start = tokenizer_->offset();
-
+    if (kind != BinKind::BindingPropertyProperty) {
+        return raiseInvalidKind("BindingPropertyProperty", kind);
+    }
+    const auto start = tokenizer_->offset();
     BINJS_MOZ_TRY_DECL(result, parseInterfaceBindingPropertyProperty(start, kind, fields));
     MOZ_TRY(guard.done());
 
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceBindingPropertyProperty(const size_t start, const BinKind kind, const BinFields& fields)
@@ -3659,18 +3284,20 @@ BinASTParser<Tok>::parseInterfaceBinding
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseBindingWithInitializer()
 {
     BinKind kind;
     BinFields fields(cx_);
     AutoTaggedTuple guard(*tokenizer_);
 
     MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    const auto start = tokenizer_->offset();
-
+    if (kind != BinKind::BindingWithInitializer) {
+        return raiseInvalidKind("BindingWithInitializer", kind);
+    }
+    const auto start = tokenizer_->offset();
     BINJS_MOZ_TRY_DECL(result, parseInterfaceBindingWithInitializer(start, kind, fields));
     MOZ_TRY(guard.done());
 
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceBindingWithInitializer(const size_t start, const BinKind kind, const BinFields& fields)
@@ -3688,49 +3315,44 @@ BinASTParser<Tok>::parseInterfaceBinding
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseBlock()
 {
     BinKind kind;
     BinFields fields(cx_);
     AutoTaggedTuple guard(*tokenizer_);
 
     MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    const auto start = tokenizer_->offset();
-
+    if (kind != BinKind::Block) {
+        return raiseInvalidKind("Block", kind);
+    }
+    const auto start = tokenizer_->offset();
     BINJS_MOZ_TRY_DECL(result, parseInterfaceBlock(start, kind, fields));
     MOZ_TRY(guard.done());
 
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceBlock(const size_t start, const BinKind kind, const BinFields& fields)
 {
     MOZ_ASSERT(kind == BinKind::Block);
     BINJS_TRY(CheckRecursionLimit(cx_));
 
-
 #if defined(DEBUG)
     const BinField expected_fields[2] = { BinField::Scope, BinField::Statements };
     MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif // defined(DEBUG)
-
     ParseContext::Statement stmt(parseContext_, StatementKind::Block);
     ParseContext::Scope currentScope(cx_, parseContext_, usedNames_);
     BINJS_TRY(currentScope.init(parseContext_));
 
-
     MOZ_TRY(parseOptionalAssertedBlockScope());
 
-
-
-
     BINJS_MOZ_TRY_DECL(statements, parseListOfStatement());
 
-
     MOZ_TRY(checkClosedVars(currentScope));
     BINJS_TRY_DECL(bindings, NewLexicalScopeData(cx_, currentScope, alloc_, parseContext_));
     BINJS_TRY_DECL(result, factory_.newLexicalScope(*bindings, statements));
     return result;
 }
 
 
 /*
@@ -3741,36 +3363,36 @@ BinASTParser<Tok>::parseInterfaceBlock(c
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseBreakStatement()
 {
     BinKind kind;
     BinFields fields(cx_);
     AutoTaggedTuple guard(*tokenizer_);
 
     MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    const auto start = tokenizer_->offset();
-
+    if (kind != BinKind::BreakStatement) {
+        return raiseInvalidKind("BreakStatement", kind);
+    }
+    const auto start = tokenizer_->offset();
     BINJS_MOZ_TRY_DECL(result, parseInterfaceBreakStatement(start, kind, fields));
     MOZ_TRY(guard.done());
 
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceBreakStatement(const size_t start, const BinKind kind, const BinFields& fields)
 {
     MOZ_ASSERT(kind == BinKind::BreakStatement);
     BINJS_TRY(CheckRecursionLimit(cx_));
 
-
 #if defined(DEBUG)
     const BinField expected_fields[1] = { BinField::Label };
     MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif // defined(DEBUG)
-
     RootedAtom label(cx_);
     MOZ_TRY_VAR(label, tokenizer_->readMaybeAtom());
 
     if (label) {
         if (!IsIdentifier(label))
             return raiseError("Invalid identifier");
 
         auto validity = parseContext_->checkBreakStatement(label->asPropertyName());
@@ -3798,47 +3420,41 @@ BinASTParser<Tok>::parseInterfaceBreakSt
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseCallExpression()
 {
     BinKind kind;
     BinFields fields(cx_);
     AutoTaggedTuple guard(*tokenizer_);
 
     MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    const auto start = tokenizer_->offset();
-
+    if (kind != BinKind::CallExpression) {
+        return raiseInvalidKind("CallExpression", kind);
+    }
+    const auto start = tokenizer_->offset();
     BINJS_MOZ_TRY_DECL(result, parseInterfaceCallExpression(start, kind, fields));
     MOZ_TRY(guard.done());
 
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceCallExpression(const size_t start, const BinKind kind, const BinFields& fields)
 {
     MOZ_ASSERT(kind == BinKind::CallExpression);
     BINJS_TRY(CheckRecursionLimit(cx_));
 
-
 #if defined(DEBUG)
     const BinField expected_fields[2] = { BinField::Callee, BinField::Arguments };
     MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif // defined(DEBUG)
 
-
-
-
     BINJS_MOZ_TRY_DECL(callee, parseExpressionOrSuper());
 
-
-
-
     BINJS_MOZ_TRY_DECL(arguments, parseArguments());
 
-
     auto op = JSOP_CALL;
     // Check for direct calls to `eval`.
     if (factory_.isEvalName(callee, cx_)) {
         if (!parseContext_->varScope().lookupDeclaredNameForAdd(callee->name())
          && !parseContext_->innermostScope()->lookupDeclaredNameForAdd(callee->name())) {
             // This is a direct call to `eval`.
             if (!parseContext_->sc()->hasDirectEval())
                 return raiseMissingDirectEvalInAssertedScope();
@@ -3864,54 +3480,46 @@ BinASTParser<Tok>::parseInterfaceCallExp
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseCatchClause()
 {
     BinKind kind;
     BinFields fields(cx_);
     AutoTaggedTuple guard(*tokenizer_);
 
     MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    const auto start = tokenizer_->offset();
-
+    if (kind != BinKind::CatchClause) {
+        return raiseInvalidKind("CatchClause", kind);
+    }
+    const auto start = tokenizer_->offset();
     BINJS_MOZ_TRY_DECL(result, parseInterfaceCatchClause(start, kind, fields));
     MOZ_TRY(guard.done());
 
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceCatchClause(const size_t start, const BinKind kind, const BinFields& fields)
 {
     MOZ_ASSERT(kind == BinKind::CatchClause);
     BINJS_TRY(CheckRecursionLimit(cx_));
 
-
 #if defined(DEBUG)
     const BinField expected_fields[3] = { BinField::BindingScope, BinField::Binding, BinField::Body };
     MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif // defined(DEBUG)
-
     ParseContext::Statement stmt(parseContext_, StatementKind::Catch);
     ParseContext::Scope currentScope(cx_, parseContext_, usedNames_);
     BINJS_TRY(currentScope.init(parseContext_));
 
-
     MOZ_TRY(parseOptionalAssertedParameterScope());
 
-
-
-
     BINJS_MOZ_TRY_DECL(binding, parseBinding());
 
-
-
-
     BINJS_MOZ_TRY_DECL(body, parseBlock());
 
-
     BINJS_TRY_DECL(bindings, NewLexicalScopeData(cx_, currentScope, alloc_, parseContext_));
     BINJS_TRY_DECL(result, factory_.newLexicalScope(*bindings, body));
     BINJS_TRY(factory_.setupCatchScope(result, binding, body));
     return result;
 }
 
 
 /*
@@ -3924,18 +3532,20 @@ BinASTParser<Tok>::parseInterfaceCatchCl
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseClassDeclaration()
 {
     BinKind kind;
     BinFields fields(cx_);
     AutoTaggedTuple guard(*tokenizer_);
 
     MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    const auto start = tokenizer_->offset();
-
+    if (kind != BinKind::ClassDeclaration) {
+        return raiseInvalidKind("ClassDeclaration", kind);
+    }
+    const auto start = tokenizer_->offset();
     BINJS_MOZ_TRY_DECL(result, parseInterfaceClassDeclaration(start, kind, fields));
     MOZ_TRY(guard.done());
 
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceClassDeclaration(const size_t start, const BinKind kind, const BinFields& fields)
@@ -3953,18 +3563,20 @@ BinASTParser<Tok>::parseInterfaceClassDe
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseClassElement()
 {
     BinKind kind;
     BinFields fields(cx_);
     AutoTaggedTuple guard(*tokenizer_);
 
     MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    const auto start = tokenizer_->offset();
-
+    if (kind != BinKind::ClassElement) {
+        return raiseInvalidKind("ClassElement", kind);
+    }
+    const auto start = tokenizer_->offset();
     BINJS_MOZ_TRY_DECL(result, parseInterfaceClassElement(start, kind, fields));
     MOZ_TRY(guard.done());
 
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceClassElement(const size_t start, const BinKind kind, const BinFields& fields)
@@ -3983,18 +3595,20 @@ BinASTParser<Tok>::parseInterfaceClassEl
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseClassExpression()
 {
     BinKind kind;
     BinFields fields(cx_);
     AutoTaggedTuple guard(*tokenizer_);
 
     MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    const auto start = tokenizer_->offset();
-
+    if (kind != BinKind::ClassExpression) {
+        return raiseInvalidKind("ClassExpression", kind);
+    }
+    const auto start = tokenizer_->offset();
     BINJS_MOZ_TRY_DECL(result, parseInterfaceClassExpression(start, kind, fields));
     MOZ_TRY(guard.done());
 
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceClassExpression(const size_t start, const BinKind kind, const BinFields& fields)
@@ -4013,52 +3627,43 @@ BinASTParser<Tok>::parseInterfaceClassEx
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseCompoundAssignmentExpression()
 {
     BinKind kind;
     BinFields fields(cx_);
     AutoTaggedTuple guard(*tokenizer_);
 
     MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    const auto start = tokenizer_->offset();
-
+    if (kind != BinKind::CompoundAssignmentExpression) {
+        return raiseInvalidKind("CompoundAssignmentExpression", kind);
+    }
+    const auto start = tokenizer_->offset();
     BINJS_MOZ_TRY_DECL(result, parseInterfaceCompoundAssignmentExpression(start, kind, fields));
     MOZ_TRY(guard.done());
 
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceCompoundAssignmentExpression(const size_t start, const BinKind kind, const BinFields& fields)
 {
     MOZ_ASSERT(kind == BinKind::CompoundAssignmentExpression);
     BINJS_TRY(CheckRecursionLimit(cx_));
 
-
 #if defined(DEBUG)
     const BinField expected_fields[3] = { BinField::Operator, BinField::Binding, BinField::Expression };
     MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif // defined(DEBUG)
 
-
-
-
     BINJS_MOZ_TRY_DECL(operator_, parseCompoundAssignmentOperator());
 
-
-
-
     BINJS_MOZ_TRY_DECL(binding, parseSimpleAssignmentTarget());
 
-
-
-
     BINJS_MOZ_TRY_DECL(expression, parseExpression());
 
-
     ParseNodeKind pnk;
     switch (operator_){
       case CompoundAssignmentOperator::PlusAssign:
         pnk = ParseNodeKind::AddAssign;
         break;
       case CompoundAssignmentOperator::MinusAssign:
         pnk = ParseNodeKind::SubAssign;
         break;
@@ -4107,47 +3712,41 @@ BinASTParser<Tok>::parseInterfaceCompoun
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseComputedMemberAssignmentTarget()
 {
     BinKind kind;
     BinFields fields(cx_);
     AutoTaggedTuple guard(*tokenizer_);
 
     MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    const auto start = tokenizer_->offset();
-
+    if (kind != BinKind::ComputedMemberAssignmentTarget) {
+        return raiseInvalidKind("ComputedMemberAssignmentTarget", kind);
+    }
+    const auto start = tokenizer_->offset();
     BINJS_MOZ_TRY_DECL(result, parseInterfaceComputedMemberAssignmentTarget(start, kind, fields));
     MOZ_TRY(guard.done());
 
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceComputedMemberAssignmentTarget(const size_t start, const BinKind kind, const BinFields& fields)
 {
     MOZ_ASSERT(kind == BinKind::ComputedMemberAssignmentTarget);
     BINJS_TRY(CheckRecursionLimit(cx_));
 
-
 #if defined(DEBUG)
     const BinField expected_fields[2] = { BinField::Object, BinField::Expression };
     MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif // defined(DEBUG)
 
-
-
-
     BINJS_MOZ_TRY_DECL(object, parseExpressionOrSuper());
 
-
-
-
     BINJS_MOZ_TRY_DECL(expression, parseExpression());
 
-
     BINJS_TRY_DECL(result, factory_.newPropertyByValue(object, expression, start));
     return result;
 }
 
 
 /*
  interface ComputedMemberExpression : Node {
     (Expression or Super) object;
@@ -4157,47 +3756,41 @@ BinASTParser<Tok>::parseInterfaceCompute
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseComputedMemberExpression()
 {
     BinKind kind;
     BinFields fields(cx_);
     AutoTaggedTuple guard(*tokenizer_);
 
     MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    const auto start = tokenizer_->offset();
-
+    if (kind != BinKind::ComputedMemberExpression) {
+        return raiseInvalidKind("ComputedMemberExpression", kind);
+    }
+    const auto start = tokenizer_->offset();
     BINJS_MOZ_TRY_DECL(result, parseInterfaceComputedMemberExpression(start, kind, fields));
     MOZ_TRY(guard.done());
 
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceComputedMemberExpression(const size_t start, const BinKind kind, const BinFields& fields)
 {
     MOZ_ASSERT(kind == BinKind::ComputedMemberExpression);
     BINJS_TRY(CheckRecursionLimit(cx_));
 
-
 #if defined(DEBUG)
     const BinField expected_fields[2] = { BinField::Object, BinField::Expression };
     MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif // defined(DEBUG)
 
-
-
-
     BINJS_MOZ_TRY_DECL(object, parseExpressionOrSuper());
 
-
-
-
     BINJS_MOZ_TRY_DECL(expression, parseExpression());
 
-
     BINJS_TRY_DECL(result, factory_.newPropertyByValue(object, expression, start));
     return result;
 }
 
 
 /*
  interface ComputedPropertyName : Node {
     Expression expression;
@@ -4206,18 +3799,20 @@ BinASTParser<Tok>::parseInterfaceCompute
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseComputedPropertyName()
 {
     BinKind kind;
     BinFields fields(cx_);
     AutoTaggedTuple guard(*tokenizer_);
 
     MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    const auto start = tokenizer_->offset();
-
+    if (kind != BinKind::ComputedPropertyName) {
+        return raiseInvalidKind("ComputedPropertyName", kind);
+    }
+    const auto start = tokenizer_->offset();
     BINJS_MOZ_TRY_DECL(result, parseInterfaceComputedPropertyName(start, kind, fields));
     MOZ_TRY(guard.done());
 
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceComputedPropertyName(const size_t start, const BinKind kind, const BinFields& fields)
@@ -4236,52 +3831,43 @@ BinASTParser<Tok>::parseInterfaceCompute
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseConditionalExpression()
 {
     BinKind kind;
     BinFields fields(cx_);
     AutoTaggedTuple guard(*tokenizer_);
 
     MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    const auto start = tokenizer_->offset();
-
+    if (kind != BinKind::ConditionalExpression) {
+        return raiseInvalidKind("ConditionalExpression", kind);
+    }
+    const auto start = tokenizer_->offset();
     BINJS_MOZ_TRY_DECL(result, parseInterfaceConditionalExpression(start, kind, fields));
     MOZ_TRY(guard.done());
 
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceConditionalExpression(const size_t start, const BinKind kind, const BinFields& fields)
 {
     MOZ_ASSERT(kind == BinKind::ConditionalExpression);
     BINJS_TRY(CheckRecursionLimit(cx_));
 
-
 #if defined(DEBUG)
     const BinField expected_fields[3] = { BinField::Test, BinField::Consequent, BinField::Alternate };
     MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif // defined(DEBUG)
 
-
-
-
     BINJS_MOZ_TRY_DECL(test, parseExpression());
 
-
-
-
     BINJS_MOZ_TRY_DECL(consequent, parseExpression());
 
-
-
-
     BINJS_MOZ_TRY_DECL(alternate, parseExpression());
 
-
     BINJS_TRY_DECL(result, factory_.newConditional(test, consequent, alternate));
     return result;
 }
 
 
 /*
  interface ContinueStatement : Node {
     Label? label;
@@ -4290,36 +3876,36 @@ BinASTParser<Tok>::parseInterfaceConditi
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseContinueStatement()
 {
     BinKind kind;
     BinFields fields(cx_);
     AutoTaggedTuple guard(*tokenizer_);
 
     MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    const auto start = tokenizer_->offset();
-
+    if (kind != BinKind::ContinueStatement) {
+        return raiseInvalidKind("ContinueStatement", kind);
+    }
+    const auto start = tokenizer_->offset();
     BINJS_MOZ_TRY_DECL(result, parseInterfaceContinueStatement(start, kind, fields));
     MOZ_TRY(guard.done());
 
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceContinueStatement(const size_t start, const BinKind kind, const BinFields& fields)
 {
     MOZ_ASSERT(kind == BinKind::ContinueStatement);
     BINJS_TRY(CheckRecursionLimit(cx_));
 
-
 #if defined(DEBUG)
     const BinField expected_fields[1] = { BinField::Label };
     MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif // defined(DEBUG)
-
     RootedAtom label(cx_);
     MOZ_TRY_VAR(label, tokenizer_->readMaybeAtom());
 
     if (label) {
         if (!IsIdentifier(label))
             return raiseError("ContinueStatement - Label MUST be an identifier");
 
         auto validity = parseContext_->checkContinueStatement(label ? label->asPropertyName() : nullptr);
@@ -4347,47 +3933,41 @@ BinASTParser<Tok>::parseInterfaceContinu
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseDataProperty()
 {
     BinKind kind;
     BinFields fields(cx_);
     AutoTaggedTuple guard(*tokenizer_);
 
     MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    const auto start = tokenizer_->offset();
-
+    if (kind != BinKind::DataProperty) {
+        return raiseInvalidKind("DataProperty", kind);
+    }
+    const auto start = tokenizer_->offset();
     BINJS_MOZ_TRY_DECL(result, parseInterfaceDataProperty(start, kind, fields));
     MOZ_TRY(guard.done());
 
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceDataProperty(const size_t start, const BinKind kind, const BinFields& fields)
 {
     MOZ_ASSERT(kind == BinKind::DataProperty);
     BINJS_TRY(CheckRecursionLimit(cx_));
 
-
 #if defined(DEBUG)
     const BinField expected_fields[2] = { BinField::Name, BinField::Expression };
     MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif // defined(DEBUG)
 
-
-
-
     BINJS_MOZ_TRY_DECL(name, parsePropertyName());
 
-
-
-
     BINJS_MOZ_TRY_DECL(expression, parseExpression());
 
-
     if (!factory_.isUsableAsObjectPropertyName(name))
         return raiseError("DataProperty key kind");
 
     BINJS_TRY_DECL(result, factory_.newObjectMethodOrPropertyDefinition(name, expression, AccessorType::None));
     return result;
 }
 
 
@@ -4398,18 +3978,20 @@ BinASTParser<Tok>::parseInterfaceDataPro
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseDebuggerStatement()
 {
     BinKind kind;
     BinFields fields(cx_);
     AutoTaggedTuple guard(*tokenizer_);
 
     MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    const auto start = tokenizer_->offset();
-
+    if (kind != BinKind::DebuggerStatement) {
+        return raiseInvalidKind("DebuggerStatement", kind);
+    }
+    const auto start = tokenizer_->offset();
     BINJS_MOZ_TRY_DECL(result, parseInterfaceDebuggerStatement(start, kind, fields));
     MOZ_TRY(guard.done());
 
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceDebuggerStatement(const size_t start, const BinKind kind, const BinFields& fields)
@@ -4426,42 +4008,40 @@ BinASTParser<Tok>::parseInterfaceDebugge
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseDirective()
 {
     BinKind kind;
     BinFields fields(cx_);
     AutoTaggedTuple guard(*tokenizer_);
 
     MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    const auto start = tokenizer_->offset();
-
+    if (kind != BinKind::Directive) {
+        return raiseInvalidKind("Directive", kind);
+    }
+    const auto start = tokenizer_->offset();
     BINJS_MOZ_TRY_DECL(result, parseInterfaceDirective(start, kind, fields));
     MOZ_TRY(guard.done());
 
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceDirective(const size_t start, const BinKind kind, const BinFields& fields)
 {
     MOZ_ASSERT(kind == BinKind::Directive);
     BINJS_TRY(CheckRecursionLimit(cx_));
 
-
 #if defined(DEBUG)
     const BinField expected_fields[1] = { BinField::RawValue };
     MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif // defined(DEBUG)
 
-
-
     RootedAtom rawValue(cx_);
     MOZ_TRY_VAR(rawValue, tokenizer_->readAtom());
 
-
     TokenPos pos = tokenizer_->pos(start);
     BINJS_TRY_DECL(result, factory_.newStringLiteral(rawValue, pos));
     return result;
 }
 
 
 /*
  interface DoWhileStatement : Node {
@@ -4472,47 +4052,42 @@ BinASTParser<Tok>::parseInterfaceDirecti
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseDoWhileStatement()
 {
     BinKind kind;
     BinFields fields(cx_);
     AutoTaggedTuple guard(*tokenizer_);
 
     MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    const auto start = tokenizer_->offset();
-
+    if (kind != BinKind::DoWhileStatement) {
+        return raiseInvalidKind("DoWhileStatement", kind);
+    }
+    const auto start = tokenizer_->offset();
     BINJS_MOZ_TRY_DECL(result, parseInterfaceDoWhileStatement(start, kind, fields));
     MOZ_TRY(guard.done());
 
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceDoWhileStatement(const size_t start, const BinKind kind, const BinFields& fields)
 {
     MOZ_ASSERT(kind == BinKind::DoWhileStatement);
     BINJS_TRY(CheckRecursionLimit(cx_));
 
-
 #if defined(DEBUG)
     const BinField expected_fields[2] = { BinField::Test, BinField::Body };
     MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif // defined(DEBUG)
-
     ParseContext::Statement stmt(parseContext_, StatementKind::DoLoop);
 
-
     BINJS_MOZ_TRY_DECL(test, parseExpression());
 
-
-
-
     BINJS_MOZ_TRY_DECL(body, parseStatement());
 
-
     BINJS_TRY_DECL(result, factory_.newDoWhileStatement(body, test, tokenizer_->pos(start)));
     return result;
 }
 
 
 /*
  interface EagerArrowExpression : Node {
     bool isAsync;
@@ -4525,18 +4100,20 @@ BinASTParser<Tok>::parseInterfaceDoWhile
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseEagerArrowExpression()
 {
     BinKind kind;
     BinFields fields(cx_);
     AutoTaggedTuple guard(*tokenizer_);
 
     MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    const auto start = tokenizer_->offset();
-
+    if (kind != BinKind::EagerArrowExpression) {
+        return raiseInvalidKind("EagerArrowExpression", kind);
+    }
+    const auto start = tokenizer_->offset();
     BINJS_MOZ_TRY_DECL(result, parseInterfaceEagerArrowExpression(start, kind, fields));
     MOZ_TRY(guard.done());
 
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceEagerArrowExpression(const size_t start, const BinKind kind, const BinFields& fields)
@@ -4559,86 +4136,67 @@ BinASTParser<Tok>::parseInterfaceEagerAr
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseEagerFunctionDeclaration()
 {
     BinKind kind;
     BinFields fields(cx_);
     AutoTaggedTuple guard(*tokenizer_);
 
     MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    const auto start = tokenizer_->offset();
-
+    if (kind != BinKind::EagerFunctionDeclaration) {
+        return raiseInvalidKind("EagerFunctionDeclaration", kind);
+    }
+    const auto start = tokenizer_->offset();
     BINJS_MOZ_TRY_DECL(result, parseInterfaceEagerFunctionDeclaration(start, kind, fields));
     MOZ_TRY(guard.done());
 
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceEagerFunctionDeclaration(const size_t start, const BinKind kind, const BinFields& fields)
 {
     MOZ_ASSERT(kind == BinKind::EagerFunctionDeclaration);
     BINJS_TRY(CheckRecursionLimit(cx_));
 
-
 #if defined(DEBUG)
     const BinField expected_fields[7] = { BinField::IsAsync, BinField::IsGenerator, BinField::Name, BinField::ParameterScope, BinField::BodyScope, BinField::Params, BinField::Body };
     MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif // defined(DEBUG)
-
     const auto syntax = FunctionSyntaxKind::Statement;
 
-
     BINJS_MOZ_TRY_DECL(isAsync, tokenizer_->readBool());
 
-
-
-
     BINJS_MOZ_TRY_DECL(isGenerator, tokenizer_->readBool());
 
-
-
-
     BINJS_MOZ_TRY_DECL(name, parseBindingIdentifier());
 
-
     BINJS_MOZ_TRY_DECL(funbox, buildFunctionBox(
         isGenerator ? GeneratorKind::Generator
                     : GeneratorKind::NotGenerator,
         isAsync ? FunctionAsyncKind::AsyncFunction
                 : FunctionAsyncKind::SyncFunction,
         syntax, name));
 
     // Push a new ParseContext. It will be used to parse `scope`, the arguments, the function.
     BinParseContext funpc(cx_, this, funbox, /* newDirectives = */ nullptr);
     BINJS_TRY(funpc.init());
     parseContext_->functionScope().useAsVarScope(parseContext_);
     MOZ_ASSERT(parseContext_->isFunctionBox());
 
     ParseContext::Scope lexicalScope(cx_, parseContext_, usedNames_);
     BINJS_TRY(lexicalScope.init(parseContext_));
-
     MOZ_TRY(parseOptionalAssertedParameterScope());
 
-
-
-
     MOZ_TRY(parseOptionalAssertedVarScope());
 
-
-
-
     BINJS_MOZ_TRY_DECL(params, parseFormalParameters());
 
-
-
-
     BINJS_MOZ_TRY_DECL(body, parseFunctionBody());
 
-
     BINJS_TRY_DECL(lexicalScopeData, NewLexicalScopeData(cx_, lexicalScope, alloc_, parseContext_));
     BINJS_TRY_VAR(body, factory_.newLexicalScope(*lexicalScopeData, body));
     BINJS_MOZ_TRY_DECL(result, buildFunction(start, kind, name, params, body, funbox));
     return result;
 }
 
 
 /*
@@ -4655,86 +4213,67 @@ BinASTParser<Tok>::parseInterfaceEagerFu
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseEagerFunctionExpression()
 {
     BinKind kind;
     BinFields fields(cx_);
     AutoTaggedTuple guard(*tokenizer_);
 
     MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    const auto start = tokenizer_->offset();
-
+    if (kind != BinKind::EagerFunctionExpression) {
+        return raiseInvalidKind("EagerFunctionExpression", kind);
+    }
+    const auto start = tokenizer_->offset();
     BINJS_MOZ_TRY_DECL(result, parseInterfaceEagerFunctionExpression(start, kind, fields));
     MOZ_TRY(guard.done());
 
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceEagerFunctionExpression(const size_t start, const BinKind kind, const BinFields& fields)
 {
     MOZ_ASSERT(kind == BinKind::EagerFunctionExpression);
     BINJS_TRY(CheckRecursionLimit(cx_));
 
-
 #if defined(DEBUG)
     const BinField expected_fields[7] = { BinField::IsAsync, BinField::IsGenerator, BinField::Name, BinField::ParameterScope, BinField::BodyScope, BinField::Params, BinField::Body };
     MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif // defined(DEBUG)
-
     const auto syntax = FunctionSyntaxKind::Expression;
 
-
     BINJS_MOZ_TRY_DECL(isAsync, tokenizer_->readBool());
 
-
-
-
     BINJS_MOZ_TRY_DECL(isGenerator, tokenizer_->readBool());
 
-
-
-
     BINJS_MOZ_TRY_DECL(name, parseOptionalBindingIdentifier());
 
-
     BINJS_MOZ_TRY_DECL(funbox, buildFunctionBox(
         isGenerator ? GeneratorKind::Generator
                     : GeneratorKind::NotGenerator,
         isAsync ? FunctionAsyncKind::AsyncFunction
                 : FunctionAsyncKind::SyncFunction,
         syntax, name));
 
     // Push a new ParseContext. It will be used to parse `scope`, the arguments, the function.
     BinParseContext funpc(cx_, this, funbox, /* newDirectives = */ nullptr);
     BINJS_TRY(funpc.init());
     parseContext_->functionScope().useAsVarScope(parseContext_);
     MOZ_ASSERT(parseContext_->isFunctionBox());
 
     ParseContext::Scope lexicalScope(cx_, parseContext_, usedNames_);
     BINJS_TRY(lexicalScope.init(parseContext_));
-
     MOZ_TRY(parseOptionalAssertedParameterScope());
 
-
-
-
     MOZ_TRY(parseOptionalAssertedVarScope());
 
-
-
-
     BINJS_MOZ_TRY_DECL(params, parseFormalParameters());
 
-
-
-
     BINJS_MOZ_TRY_DECL(body, parseFunctionBody());
 
-
     BINJS_TRY_DECL(lexicalScopeData, NewLexicalScopeData(cx_, lexicalScope, alloc_, parseContext_));
     BINJS_TRY_VAR(body, factory_.newLexicalScope(*lexicalScopeData, body));
     BINJS_MOZ_TRY_DECL(result, buildFunction(start, kind, name, params, body, funbox));
     return result;
 }
 
 
 /*
@@ -4747,64 +4286,55 @@ BinASTParser<Tok>::parseInterfaceEagerFu
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseEagerGetter()
 {
     BinKind kind;
     BinFields fields(cx_);
     AutoTaggedTuple guard(*tokenizer_);
 
     MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    const auto start = tokenizer_->offset();
-
+    if (kind != BinKind::EagerGetter) {
+        return raiseInvalidKind("EagerGetter", kind);
+    }
+    const auto start = tokenizer_->offset();
     BINJS_MOZ_TRY_DECL(result, parseInterfaceEagerGetter(start, kind, fields));
     MOZ_TRY(guard.done());
 
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceEagerGetter(const size_t start, const BinKind kind, const BinFields& fields)
 {
     MOZ_ASSERT(kind == BinKind::EagerGetter);
     BINJS_TRY(CheckRecursionLimit(cx_));
 
-
 #if defined(DEBUG)
     const BinField expected_fields[3] = { BinField::Name, BinField::BodyScope, BinField::Body };
     MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif // defined(DEBUG)
 
-
-
-
     BINJS_MOZ_TRY_DECL(name, parsePropertyName());
     BINJS_MOZ_TRY_DECL(funbox, buildFunctionBox(
         GeneratorKind::NotGenerator,
         FunctionAsyncKind::SyncFunction,
         FunctionSyntaxKind::Getter, /* name = */ nullptr));
 
     // Push a new ParseContext. It will be used to parse `scope`, the arguments, the function.
     BinParseContext funpc(cx_, this, funbox, /* newDirectives = */ nullptr);
     BINJS_TRY(funpc.init());
     parseContext_->functionScope().useAsVarScope(parseContext_);
     MOZ_ASSERT(parseContext_->isFunctionBox());
 
     ParseContext::Scope lexicalScope(cx_, parseContext_, usedNames_);
     BINJS_TRY(lexicalScope.init(parseContext_));
-
-
-
     MOZ_TRY(parseOptionalAssertedVarScope());
 
-
-
-
     BINJS_MOZ_TRY_DECL(body, parseFunctionBody());
 
-
     BINJS_TRY_DECL(params, new_<ListNode>(ParseNodeKind::ParamsBody, tokenizer_->pos(start)));
     BINJS_MOZ_TRY_DECL(method, buildFunction(start, kind, name, params, body, funbox));
     BINJS_TRY_DECL(result, factory_.newObjectMethodOrPropertyDefinition(name, method, AccessorType::Getter));
     return result;
 }
 
 
 /*
@@ -4821,86 +4351,67 @@ BinASTParser<Tok>::parseInterfaceEagerGe
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseEagerMethod()
 {
     BinKind kind;
     BinFields fields(cx_);
     AutoTaggedTuple guard(*tokenizer_);
 
     MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    const auto start = tokenizer_->offset();
-
+    if (kind != BinKind::EagerMethod) {
+        return raiseInvalidKind("EagerMethod", kind);
+    }
+    const auto start = tokenizer_->offset();
     BINJS_MOZ_TRY_DECL(result, parseInterfaceEagerMethod(start, kind, fields));
     MOZ_TRY(guard.done());
 
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceEagerMethod(const size_t start, const BinKind kind, const BinFields& fields)
 {
     MOZ_ASSERT(kind == BinKind::EagerMethod);
     BINJS_TRY(CheckRecursionLimit(cx_));
 
-
 #if defined(DEBUG)
     const BinField expected_fields[7] = { BinField::IsAsync, BinField::IsGenerator, BinField::Name, BinField::ParameterScope, BinField::BodyScope, BinField::Params, BinField::Body };
     MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif // defined(DEBUG)
-
     const auto syntax = FunctionSyntaxKind::Method;
 
-
     BINJS_MOZ_TRY_DECL(isAsync, tokenizer_->readBool());
 
-
-
-
     BINJS_MOZ_TRY_DECL(isGenerator, tokenizer_->readBool());
 
-
-
-
     BINJS_MOZ_TRY_DECL(name, parsePropertyName());
 
-
     BINJS_MOZ_TRY_DECL(funbox, buildFunctionBox(
         isGenerator ? GeneratorKind::Generator
                     : GeneratorKind::NotGenerator,
         isAsync ? FunctionAsyncKind::AsyncFunction
                 : FunctionAsyncKind::SyncFunction,
         syntax, name));
 
     // Push a new ParseContext. It will be used to parse `scope`, the arguments, the function.
     BinParseContext funpc(cx_, this, funbox, /* newDirectives = */ nullptr);
     BINJS_TRY(funpc.init());
     parseContext_->functionScope().useAsVarScope(parseContext_);
     MOZ_ASSERT(parseContext_->isFunctionBox());
 
     ParseContext::Scope lexicalScope(cx_, parseContext_, usedNames_);
     BINJS_TRY(lexicalScope.init(parseContext_));
-
     MOZ_TRY(parseOptionalAssertedParameterScope());
 
-
-
-
     MOZ_TRY(parseOptionalAssertedVarScope());
 
-
-
-
     BINJS_MOZ_TRY_DECL(params, parseFormalParameters());
 
-
-
-
     BINJS_MOZ_TRY_DECL(body, parseFunctionBody());
 
-
     BINJS_MOZ_TRY_DECL(method, buildFunction(start, kind, name, params, body, funbox));
     BINJS_TRY_DECL(result, factory_.newObjectMethodOrPropertyDefinition(name, method, AccessorType::None));
     return result;
 }
 
 
 /*
  interface EagerSetter : Node {
@@ -4914,74 +4425,59 @@ BinASTParser<Tok>::parseInterfaceEagerMe
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseEagerSetter()
 {
     BinKind kind;
     BinFields fields(cx_);
     AutoTaggedTuple guard(*tokenizer_);
 
     MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    const auto start = tokenizer_->offset();
-
+    if (kind != BinKind::EagerSetter) {
+        return raiseInvalidKind("EagerSetter", kind);
+    }
+    const auto start = tokenizer_->offset();
     BINJS_MOZ_TRY_DECL(result, parseInterfaceEagerSetter(start, kind, fields));
     MOZ_TRY(guard.done());
 
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceEagerSetter(const size_t start, const BinKind kind, const BinFields& fields)
 {
     MOZ_ASSERT(kind == BinKind::EagerSetter);
     BINJS_TRY(CheckRecursionLimit(cx_));
 
-
 #if defined(DEBUG)
     const BinField expected_fields[5] = { BinField::Name, BinField::ParameterScope, BinField::BodyScope, BinField::Param, BinField::Body };
     MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif // defined(DEBUG)
 
-
-
-
     BINJS_MOZ_TRY_DECL(name, parsePropertyName());
     BINJS_MOZ_TRY_DECL(funbox, buildFunctionBox(
         GeneratorKind::NotGenerator,
         FunctionAsyncKind::SyncFunction,
         FunctionSyntaxKind::Setter, /* name = */ nullptr));
 
     // Push a new ParseContext. It will be used to parse `scope`, the arguments, the function.
     BinParseContext funpc(cx_, this, funbox, /* newDirectives = */ nullptr);
     BINJS_TRY(funpc.init());
     parseContext_->functionScope().useAsVarScope(parseContext_);
     MOZ_ASSERT(parseContext_->isFunctionBox());
 
     ParseContext::Scope lexicalScope(cx_, parseContext_, usedNames_);
     BINJS_TRY(lexicalScope.init(parseContext_));
-
-
-
     MOZ_TRY(parseOptionalAssertedParameterScope());
 
-
-
-
     MOZ_TRY(parseOptionalAssertedVarScope());
 
-
-
-
     BINJS_MOZ_TRY_DECL(param, parseParameter());
 
-
-
-
     BINJS_MOZ_TRY_DECL(body, parseFunctionBody());
 
-
     BINJS_TRY_DECL(params, new_<ListNode>(ParseNodeKind::ParamsBody, param->pn_pos));
     factory_.addList(params, param);
     BINJS_MOZ_TRY_DECL(method, buildFunction(start, kind, name, params, body, funbox));
     BINJS_TRY_DECL(result, factory_.newObjectMethodOrPropertyDefinition(name, method, AccessorType::Setter));
     return result;
 }
 
 
@@ -4992,30 +4488,31 @@ BinASTParser<Tok>::parseInterfaceEagerSe
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseEmptyStatement()
 {
     BinKind kind;
     BinFields fields(cx_);
     AutoTaggedTuple guard(*tokenizer_);
 
     MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    const auto start = tokenizer_->offset();
-
+    if (kind != BinKind::EmptyStatement) {
+        return raiseInvalidKind("EmptyStatement", kind);
+    }
+    const auto start = tokenizer_->offset();
     BINJS_MOZ_TRY_DECL(result, parseInterfaceEmptyStatement(start, kind, fields));
     MOZ_TRY(guard.done());
 
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceEmptyStatement(const size_t start, const BinKind kind, const BinFields& fields)
 {
     MOZ_ASSERT(kind == BinKind::EmptyStatement);
     BINJS_TRY(CheckRecursionLimit(cx_));
-
 MOZ_TRY(tokenizer_->checkFields0(kind, fields));
 
     BINJS_TRY_DECL(result, factory_.newEmptyStatement(tokenizer_->pos(start)));
     return result;
 }
 
 
 /*
@@ -5026,18 +4523,20 @@ MOZ_TRY(tokenizer_->checkFields0(kind, f
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseExport()
 {
     BinKind kind;
     BinFields fields(cx_);
     AutoTaggedTuple guard(*tokenizer_);
 
     MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    const auto start = tokenizer_->offset();
-
+    if (kind != BinKind::Export) {
+        return raiseInvalidKind("Export", kind);
+    }
+    const auto start = tokenizer_->offset();
     BINJS_MOZ_TRY_DECL(result, parseInterfaceExport(start, kind, fields));
     MOZ_TRY(guard.done());
 
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceExport(const size_t start, const BinKind kind, const BinFields& fields)
@@ -5054,18 +4553,20 @@ BinASTParser<Tok>::parseInterfaceExport(
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseExportAllFrom()
 {
     BinKind kind;
     BinFields fields(cx_);
     AutoTaggedTuple guard(*tokenizer_);
 
     MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    const auto start = tokenizer_->offset();
-
+    if (kind != BinKind::ExportAllFrom) {
+        return raiseInvalidKind("ExportAllFrom", kind);
+    }
+    const auto start = tokenizer_->offset();
     BINJS_MOZ_TRY_DECL(result, parseInterfaceExportAllFrom(start, kind, fields));
     MOZ_TRY(guard.done());
 
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceExportAllFrom(const size_t start, const BinKind kind, const BinFields& fields)
@@ -5082,18 +4583,20 @@ BinASTParser<Tok>::parseInterfaceExportA
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseExportDefault()
 {
     BinKind kind;
     BinFields fields(cx_);
     AutoTaggedTuple guard(*tokenizer_);
 
     MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    const auto start = tokenizer_->offset();
-
+    if (kind != BinKind::ExportDefault) {
+        return raiseInvalidKind("ExportDefault", kind);
+    }
+    const auto start = tokenizer_->offset();
     BINJS_MOZ_TRY_DECL(result, parseInterfaceExportDefault(start, kind, fields));
     MOZ_TRY(guard.done());
 
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceExportDefault(const size_t start, const BinKind kind, const BinFields& fields)
@@ -5111,18 +4614,20 @@ BinASTParser<Tok>::parseInterfaceExportD
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseExportFrom()
 {
     BinKind kind;
     BinFields fields(cx_);
     AutoTaggedTuple guard(*tokenizer_);
 
     MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    const auto start = tokenizer_->offset();
-
+    if (kind != BinKind::ExportFrom) {
+        return raiseInvalidKind("ExportFrom", kind);
+    }
+    const auto start = tokenizer_->offset();
     BINJS_MOZ_TRY_DECL(result, parseInterfaceExportFrom(start, kind, fields));
     MOZ_TRY(guard.done());
 
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceExportFrom(const size_t start, const BinKind kind, const BinFields& fields)
@@ -5140,18 +4645,20 @@ BinASTParser<Tok>::parseInterfaceExportF
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseExportFromSpecifier()
 {
     BinKind kind;
     BinFields fields(cx_);
     AutoTaggedTuple guard(*tokenizer_);
 
     MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    const auto start = tokenizer_->offset();
-
+    if (kind != BinKind::ExportFromSpecifier) {
+        return raiseInvalidKind("ExportFromSpecifier", kind);
+    }
+    const auto start = tokenizer_->offset();
     BINJS_MOZ_TRY_DECL(result, parseInterfaceExportFromSpecifier(start, kind, fields));
     MOZ_TRY(guard.done());
 
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceExportFromSpecifier(const size_t start, const BinKind kind, const BinFields& fields)
@@ -5169,18 +4676,20 @@ BinASTParser<Tok>::parseInterfaceExportF
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseExportLocalSpecifier()
 {
     BinKind kind;
     BinFields fields(cx_);
     AutoTaggedTuple guard(*tokenizer_);
 
     MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    const auto start = tokenizer_->offset();
-
+    if (kind != BinKind::ExportLocalSpecifier) {
+        return raiseInvalidKind("ExportLocalSpecifier", kind);
+    }
+    const auto start = tokenizer_->offset();
     BINJS_MOZ_TRY_DECL(result, parseInterfaceExportLocalSpecifier(start, kind, fields));
     MOZ_TRY(guard.done());
 
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceExportLocalSpecifier(const size_t start, const BinKind kind, const BinFields& fields)
@@ -5197,18 +4706,20 @@ BinASTParser<Tok>::parseInterfaceExportL
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseExportLocals()
 {
     BinKind kind;
     BinFields fields(cx_);
     AutoTaggedTuple guard(*tokenizer_);
 
     MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    const auto start = tokenizer_->offset();
-
+    if (kind != BinKind::ExportLocals) {
+        return raiseInvalidKind("ExportLocals", kind);
+    }
+    const auto start = tokenizer_->offset();
     BINJS_MOZ_TRY_DECL(result, parseInterfaceExportLocals(start, kind, fields));
     MOZ_TRY(guard.done());
 
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceExportLocals(const size_t start, const BinKind kind, const BinFields& fields)
@@ -5225,42 +4736,39 @@ BinASTParser<Tok>::parseInterfaceExportL
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseExpressionStatement()
 {
     BinKind kind;
     BinFields fields(cx_);
     AutoTaggedTuple guard(*tokenizer_);
 
     MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    const auto start = tokenizer_->offset();
-
+    if (kind != BinKind::ExpressionStatement) {
+        return raiseInvalidKind("ExpressionStatement", kind);
+    }
+    const auto start = tokenizer_->offset();
     BINJS_MOZ_TRY_DECL(result, parseInterfaceExpressionStatement(start, kind, fields));
     MOZ_TRY(guard.done());
 
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceExpressionStatement(const size_t start, const BinKind kind, const BinFields& fields)
 {
     MOZ_ASSERT(kind == BinKind::ExpressionStatement);
     BINJS_TRY(CheckRecursionLimit(cx_));
 
-
 #if defined(DEBUG)
     const BinField expected_fields[1] = { BinField::Expression };
     MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif // defined(DEBUG)
 
-
-
-
     BINJS_MOZ_TRY_DECL(expression, parseExpression());
 
-
     BINJS_TRY_DECL(result, factory_.newExprStatement(expression, tokenizer_->offset()));
     return result;
 }
 
 
 /*
  interface ForInOfBinding : Node {
     VariableDeclarationKind kind;
@@ -5270,47 +4778,42 @@ BinASTParser<Tok>::parseInterfaceExpress
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseForInOfBinding()
 {
     BinKind kind;
     BinFields fields(cx_);
     AutoTaggedTuple guard(*tokenizer_);
 
     MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    const auto start = tokenizer_->offset();
-
+    if (kind != BinKind::ForInOfBinding) {
+        return raiseInvalidKind("ForInOfBinding", kind);
+    }
+    const auto start = tokenizer_->offset();
     BINJS_MOZ_TRY_DECL(result, parseInterfaceForInOfBinding(start, kind, fields));
     MOZ_TRY(guard.done());
 
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceForInOfBinding(const size_t start, const BinKind kind, const BinFields& fields)
 {
     MOZ_ASSERT(kind == BinKind::ForInOfBinding);
     BINJS_TRY(CheckRecursionLimit(cx_));
 
-
 #if defined(DEBUG)
     const BinField expected_fields[2] = { BinField::Kind, BinField::Binding };
     MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif // defined(DEBUG)
-
     AutoVariableDeclarationKind kindGuard(this);
 
-
     BINJS_MOZ_TRY_DECL(kind_, parseVariableDeclarationKind());
 
-
-
-
     BINJS_MOZ_TRY_DECL(binding, parseBinding());
 
-
     // Restored by `kindGuard`.
     variableDeclarationKind_ = kind_;
     MOZ_TRY(checkBinding(binding->pn_atom->asPropertyName()));
     auto pnk =
         kind_ == VariableDeclarationKind::Let
             ? ParseNodeKind::Let
             : ParseNodeKind::Var;
     BINJS_TRY_DECL(result, factory_.newDeclarationList(pnk, tokenizer_->pos(start)));
@@ -5329,58 +4832,50 @@ BinASTParser<Tok>::parseInterfaceForInOf
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseForInStatement()
 {
     BinKind kind;
     BinFields fields(cx_);
     AutoTaggedTuple guard(*tokenizer_);
 
     MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    const auto start = tokenizer_->offset();
-
+    if (kind != BinKind::ForInStatement) {
+        return raiseInvalidKind("ForInStatement", kind);
+    }
+    const auto start = tokenizer_->offset();
     BINJS_MOZ_TRY_DECL(result, parseInterfaceForInStatement(start, kind, fields));
     MOZ_TRY(guard.done());
 
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceForInStatement(const size_t start, const BinKind kind, const BinFields& fields)
 {
     MOZ_ASSERT(kind == BinKind::ForInStatement);
     BINJS_TRY(CheckRecursionLimit(cx_));
 
-
 #if defined(DEBUG)
     const BinField expected_fields[3] = { BinField::Left, BinField::Right, BinField::Body };
     MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif // defined(DEBUG)
-
     ParseContext::Statement stmt(parseContext_, StatementKind::ForInLoop);
 
     // Implicit scope around the `for`, used to store `for (let x in  ...)`
     // or `for (const x in ...)`-style declarations. Detail on the
     // declaration is stored as part of `scope`.
     ParseContext::Scope scope(cx_, parseContext_, usedNames_);
     BINJS_TRY(scope.init(parseContext_));
 
-
     BINJS_MOZ_TRY_DECL(left, parseForInOfBindingOrAssignmentTarget());
 
-
-
-
     BINJS_MOZ_TRY_DECL(right, parseExpression());
 
-
-
-
     BINJS_MOZ_TRY_DECL(body, parseStatement());
 
-
     BINJS_TRY_DECL(forHead, factory_.newForInOrOfHead(ParseNodeKind::ForIn, left, right, tokenizer_->pos(start)));
     BINJS_TRY_DECL(result, factory_.newForStatement(start, forHead, body, /*flags*/ 0));
 
     if (!scope.isEmpty()) {
         BINJS_TRY_DECL(bindings, NewLexicalScopeData(cx_, scope, alloc_, parseContext_));
         BINJS_TRY_VAR(result, factory_.newLexicalScope(*bindings, result));
     }
     return result;
@@ -5397,18 +4892,20 @@ BinASTParser<Tok>::parseInterfaceForInSt
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseForOfStatement()
 {
     BinKind kind;
     BinFields fields(cx_);
     AutoTaggedTuple guard(*tokenizer_);
 
     MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    const auto start = tokenizer_->offset();
-
+    if (kind != BinKind::ForOfStatement) {
+        return raiseInvalidKind("ForOfStatement", kind);
+    }
+    const auto start = tokenizer_->offset();
     BINJS_MOZ_TRY_DECL(result, parseInterfaceForOfStatement(start, kind, fields));
     MOZ_TRY(guard.done());
 
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceForOfStatement(const size_t start, const BinKind kind, const BinFields& fields)
@@ -5428,63 +4925,52 @@ BinASTParser<Tok>::parseInterfaceForOfSt
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseForStatement()
 {
     BinKind kind;
     BinFields fields(cx_);
     AutoTaggedTuple guard(*tokenizer_);
 
     MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    const auto start = tokenizer_->offset();
-
+    if (kind != BinKind::ForStatement) {
+        return raiseInvalidKind("ForStatement", kind);
+    }
+    const auto start = tokenizer_->offset();
     BINJS_MOZ_TRY_DECL(result, parseInterfaceForStatement(start, kind, fields));
     MOZ_TRY(guard.done());
 
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceForStatement(const size_t start, const BinKind kind, const BinFields& fields)
 {
     MOZ_ASSERT(kind == BinKind::ForStatement);
     BINJS_TRY(CheckRecursionLimit(cx_));
 
-
 #if defined(DEBUG)
     const BinField expected_fields[4] = { BinField::Init, BinField::Test, BinField::Update, BinField::Body };
     MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif // defined(DEBUG)
-
     ParseContext::Statement stmt(parseContext_, StatementKind::ForLoop);
 
     // Implicit scope around the `for`, used to store `for (let x; ...; ...)`
     // or `for (const x; ...; ...)`-style declarations. Detail on the
     // declaration is stored as part of `BINJS_Scope`.
     ParseContext::Scope scope(cx_, parseContext_, usedNames_);
     BINJS_TRY(scope.init(parseContext_));
 
-
     BINJS_MOZ_TRY_DECL(init, parseOptionalVariableDeclarationOrExpression());
 
-
-
-
     BINJS_MOZ_TRY_DECL(test, parseOptionalExpression());
 
-
-
-
     BINJS_MOZ_TRY_DECL(update, parseOptionalExpression());
 
-
-
-
     BINJS_MOZ_TRY_DECL(body, parseStatement());
 
-
     BINJS_TRY_DECL(forHead, factory_.newForHead(init, test, update, tokenizer_->pos(start)));
     BINJS_TRY_DECL(result, factory_.newForStatement(start, forHead, body, /* iflags = */ 0));
 
     if (!scope.isEmpty()) {
         BINJS_TRY_DECL(bindings, NewLexicalScopeData(cx_, scope, alloc_, parseContext_));
         BINJS_TRY_VAR(result, factory_.newLexicalScope(*bindings, result));
     }
     return result;
@@ -5500,47 +4986,41 @@ BinASTParser<Tok>::parseInterfaceForStat
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseFormalParameters()
 {
     BinKind kind;
     BinFields fields(cx_);
     AutoTaggedTuple guard(*tokenizer_);
 
     MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    const auto start = tokenizer_->offset();
-
+    if (kind != BinKind::FormalParameters) {
+        return raiseInvalidKind("FormalParameters", kind);
+    }
+    const auto start = tokenizer_->offset();
     BINJS_MOZ_TRY_DECL(result, parseInterfaceFormalParameters(start, kind, fields));
     MOZ_TRY(guard.done());
 
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceFormalParameters(const size_t start, const BinKind kind, const BinFields& fields)
 {
     MOZ_ASSERT(kind == BinKind::FormalParameters);
     BINJS_TRY(CheckRecursionLimit(cx_));
 
-
 #if defined(DEBUG)
     const BinField expected_fields[2] = { BinField::Items, BinField::Rest };
     MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif // defined(DEBUG)
 
-
-
-
     BINJS_MOZ_TRY_DECL(items, parseListOfParameter());
 
-
-
-
     BINJS_MOZ_TRY_DECL(rest, parseOptionalBinding());
 
-
     auto result = items;
     if (rest) {
         BINJS_TRY_DECL(spread, factory_.newSpread(start, rest));
         factory_.addList(result, spread);
     }
     return result;
 }
 
@@ -5554,47 +5034,41 @@ BinASTParser<Tok>::parseInterfaceFormalP
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseFunctionBody()
 {
     BinKind kind;
     BinFields fields(cx_);
     AutoTaggedTuple guard(*tokenizer_);
 
     MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    const auto start = tokenizer_->offset();
-
+    if (kind != BinKind::FunctionBody) {
+        return raiseInvalidKind("FunctionBody", kind);
+    }
+    const auto start = tokenizer_->offset();
     BINJS_MOZ_TRY_DECL(result, parseInterfaceFunctionBody(start, kind, fields));
     MOZ_TRY(guard.done());
 
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceFunctionBody(const size_t start, const BinKind kind, const BinFields& fields)
 {
     MOZ_ASSERT(kind == BinKind::FunctionBody);
     BINJS_TRY(CheckRecursionLimit(cx_));
 
-
 #if defined(DEBUG)
     const BinField expected_fields[2] = { BinField::Directives, BinField::Statements };
     MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif // defined(DEBUG)
 
-
-
-
     BINJS_MOZ_TRY_DECL(directives, parseListOfDirective());
 
-
-
-
     BINJS_MOZ_TRY_DECL(statements, parseListOfStatement());
 
-
     BINJS_MOZ_TRY_DECL(result, appendDirectivesToBody(/* body = */ statements, /* directives = */ directives));
     return result;
 }
 
 
 /*
  interface IdentifierExpression : Node {
     Identifier name;
@@ -5603,42 +5077,40 @@ BinASTParser<Tok>::parseInterfaceFunctio
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseIdentifierExpression()
 {
     BinKind kind;
     BinFields fields(cx_);
     AutoTaggedTuple guard(*tokenizer_);
 
     MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    const auto start = tokenizer_->offset();
-
+    if (kind != BinKind::IdentifierExpression) {
+        return raiseInvalidKind("IdentifierExpression", kind);
+    }
+    const auto start = tokenizer_->offset();
     BINJS_MOZ_TRY_DECL(result, parseInterfaceIdentifierExpression(start, kind, fields));
     MOZ_TRY(guard.done());
 
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceIdentifierExpression(const size_t start, const BinKind kind, const BinFields& fields)
 {
     MOZ_ASSERT(kind == BinKind::IdentifierExpression);
     BINJS_TRY(CheckRecursionLimit(cx_));
 
-
 #if defined(DEBUG)
     const BinField expected_fields[1] = { BinField::Name };
     MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif // defined(DEBUG)
 
-
-
     RootedAtom name(cx_);
     MOZ_TRY_VAR(name, tokenizer_->readAtom());
 
-
     if (!IsIdentifier(name))
         return raiseError("Invalid identifier");
     BINJS_TRY(usedNames_.noteUse(cx_, name, parseContext_->scriptId(), parseContext_->innermostScope()->id()));
     BINJS_TRY_DECL(result, factory_.newName(name->asPropertyName(), tokenizer_->pos(start), cx_));
     return result;
 }
 
 
@@ -5652,52 +5124,43 @@ BinASTParser<Tok>::parseInterfaceIdentif
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseIfStatement()
 {
     BinKind kind;
     BinFields fields(cx_);
     AutoTaggedTuple guard(*tokenizer_);
 
     MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    const auto start = tokenizer_->offset();
-
+    if (kind != BinKind::IfStatement) {
+        return raiseInvalidKind("IfStatement", kind);
+    }
+    const auto start = tokenizer_->offset();
     BINJS_MOZ_TRY_DECL(result, parseInterfaceIfStatement(start, kind, fields));
     MOZ_TRY(guard.done());
 
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceIfStatement(const size_t start, const BinKind kind, const BinFields& fields)
 {
     MOZ_ASSERT(kind == BinKind::IfStatement);
     BINJS_TRY(CheckRecursionLimit(cx_));
 
-
 #if defined(DEBUG)
     const BinField expected_fields[3] = { BinField::Test, BinField::Consequent, BinField::Alternate };
     MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif // defined(DEBUG)
 
-
-
-
     BINJS_MOZ_TRY_DECL(test, parseExpression());
 
-
-
-
     BINJS_MOZ_TRY_DECL(consequent, parseStatement());
 
-
-
-
     BINJS_MOZ_TRY_DECL(alternate, parseOptionalStatement());
 
-
     BINJS_TRY_DECL(result, factory_.newIfStatement(start, test, consequent, alternate));
     return result;
 }
 
 
 /*
  interface Import : Node {
     string moduleSpecifier;
@@ -5708,18 +5171,20 @@ BinASTParser<Tok>::parseInterfaceIfState
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseImport()
 {
     BinKind kind;
     BinFields fields(cx_);
     AutoTaggedTuple guard(*tokenizer_);
 
     MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    const auto start = tokenizer_->offset();
-
+    if (kind != BinKind::Import) {
+        return raiseInvalidKind("Import", kind);
+    }
+    const auto start = tokenizer_->offset();
     BINJS_MOZ_TRY_DECL(result, parseInterfaceImport(start, kind, fields));
     MOZ_TRY(guard.done());
 
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceImport(const size_t start, const BinKind kind, const BinFields& fields)
@@ -5738,18 +5203,20 @@ BinASTParser<Tok>::parseInterfaceImport(
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseImportNamespace()
 {
     BinKind kind;
     BinFields fields(cx_);
     AutoTaggedTuple guard(*tokenizer_);
 
     MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    const auto start = tokenizer_->offset();
-
+    if (kind != BinKind::ImportNamespace) {
+        return raiseInvalidKind("ImportNamespace", kind);
+    }
+    const auto start = tokenizer_->offset();
     BINJS_MOZ_TRY_DECL(result, parseInterfaceImportNamespace(start, kind, fields));
     MOZ_TRY(guard.done());
 
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceImportNamespace(const size_t start, const BinKind kind, const BinFields& fields)
@@ -5767,18 +5234,20 @@ BinASTParser<Tok>::parseInterfaceImportN
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseImportSpecifier()
 {
     BinKind kind;
     BinFields fields(cx_);
     AutoTaggedTuple guard(*tokenizer_);
 
     MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    const auto start = tokenizer_->offset();
-
+    if (kind != BinKind::ImportSpecifier) {
+        return raiseInvalidKind("ImportSpecifier", kind);
+    }
+    const auto start = tokenizer_->offset();
     BINJS_MOZ_TRY_DECL(result, parseInterfaceImportSpecifier(start, kind, fields));
     MOZ_TRY(guard.done());
 
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceImportSpecifier(const size_t start, const BinKind kind, const BinFields& fields)
@@ -5796,49 +5265,44 @@ BinASTParser<Tok>::parseInterfaceImportS
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseLabelledStatement()
 {
     BinKind kind;
     BinFields fields(cx_);
     AutoTaggedTuple guard(*tokenizer_);
 
     MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    const auto start = tokenizer_->offset();
-
+    if (kind != BinKind::LabelledStatement) {
+        return raiseInvalidKind("LabelledStatement", kind);
+    }
+    const auto start = tokenizer_->offset();
     BINJS_MOZ_TRY_DECL(result, parseInterfaceLabelledStatement(start, kind, fields));
     MOZ_TRY(guard.done());
 
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceLabelledStatement(const size_t start, const BinKind kind, const BinFields& fields)
 {
     MOZ_ASSERT(kind == BinKind::LabelledStatement);
     BINJS_TRY(CheckRecursionLimit(cx_));
 
-
 #if defined(DEBUG)
     const BinField expected_fields[2] = { BinField::Label, BinField::Body };
     MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif // defined(DEBUG)
 
-
-
     RootedAtom label(cx_);
     MOZ_TRY_VAR(label, tokenizer_->readAtom());
     if (!IsIdentifier(label))
         return raiseError("Invalid identifier");
     ParseContext::LabelStatement stmt(parseContext_, label);
-
-
-
     BINJS_MOZ_TRY_DECL(body, parseStatement());
 
-
     BINJS_TRY_DECL(result, factory_.newLabeledStatement(label->asPropertyName(), body, start));
     return result;
 }
 
 
 /*
  interface LiteralBooleanExpression : Node {
     bool value;
@@ -5847,42 +5311,39 @@ BinASTParser<Tok>::parseInterfaceLabelle
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseLiteralBooleanExpression()
 {
     BinKind kind;
     BinFields fields(cx_);
     AutoTaggedTuple guard(*tokenizer_);
 
     MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    const auto start = tokenizer_->offset();
-
+    if (kind != BinKind::LiteralBooleanExpression) {
+        return raiseInvalidKind("LiteralBooleanExpression", kind);
+    }
+    const auto start = tokenizer_->offset();
     BINJS_MOZ_TRY_DECL(result, parseInterfaceLiteralBooleanExpression(start, kind, fields));
     MOZ_TRY(guard.done());
 
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceLiteralBooleanExpression(const size_t start, const BinKind kind, const BinFields& fields)
 {
     MOZ_ASSERT(kind == BinKind::LiteralBooleanExpression);
     BINJS_TRY(CheckRecursionLimit(cx_));
 
-
 #if defined(DEBUG)
     const BinField expected_fields[1] = { BinField::Value };
     MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif // defined(DEBUG)
 
-
-
-
     BINJS_MOZ_TRY_DECL(value, tokenizer_->readBool());
 
-
     BINJS_TRY_DECL(result, factory_.newBooleanLiteral(value, tokenizer_->pos(start)));
     return result;
 }
 
 
 /*
  interface LiteralInfinityExpression : Node {
  }
@@ -5890,18 +5351,20 @@ BinASTParser<Tok>::parseInterfaceLiteral
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseLiteralInfinityExpression()
 {
     BinKind kind;
     BinFields fields(cx_);
     AutoTaggedTuple guard(*tokenizer_);
 
     MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    const auto start = tokenizer_->offset();
-
+    if (kind != BinKind::LiteralInfinityExpression) {
+        return raiseInvalidKind("LiteralInfinityExpression", kind);
+    }
+    const auto start = tokenizer_->offset();
     BINJS_MOZ_TRY_DECL(result, parseInterfaceLiteralInfinityExpression(start, kind, fields));
     MOZ_TRY(guard.done());
 
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceLiteralInfinityExpression(const size_t start, const BinKind kind, const BinFields& fields)
@@ -5917,30 +5380,31 @@ BinASTParser<Tok>::parseInterfaceLiteral
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseLiteralNullExpression()
 {
     BinKind kind;
     BinFields fields(cx_);
     AutoTaggedTuple guard(*tokenizer_);
 
     MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    const auto start = tokenizer_->offset();
-
+    if (kind != BinKind::LiteralNullExpression) {
+        return raiseInvalidKind("LiteralNullExpression", kind);
+    }
+    const auto start = tokenizer_->offset();
     BINJS_MOZ_TRY_DECL(result, parseInterfaceLiteralNullExpression(start, kind, fields));
     MOZ_TRY(guard.done());
 
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceLiteralNullExpression(const size_t start, const BinKind kind, const BinFields& fields)
 {
     MOZ_ASSERT(kind == BinKind::LiteralNullExpression);
     BINJS_TRY(CheckRecursionLimit(cx_));
-
 MOZ_TRY(tokenizer_->checkFields0(kind, fields));
 
     BINJS_TRY_DECL(result, factory_.newNullLiteral(tokenizer_->pos(start)));
     return result;
 }
 
 
 /*
@@ -5951,42 +5415,39 @@ MOZ_TRY(tokenizer_->checkFields0(kind, f
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseLiteralNumericExpression()
 {
     BinKind kind;
     BinFields fields(cx_);
     AutoTaggedTuple guard(*tokenizer_);
 
     MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    const auto start = tokenizer_->offset();
-
+    if (kind != BinKind::LiteralNumericExpression) {
+        return raiseInvalidKind("LiteralNumericExpression", kind);
+    }
+    const auto start = tokenizer_->offset();
     BINJS_MOZ_TRY_DECL(result, parseInterfaceLiteralNumericExpression(start, kind, fields));
     MOZ_TRY(guard.done());
 
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceLiteralNumericExpression(const size_t start, const BinKind kind, const BinFields& fields)
 {
     MOZ_ASSERT(kind == BinKind::LiteralNumericExpression);
     BINJS_TRY(CheckRecursionLimit(cx_));
 
-
 #if defined(DEBUG)
     const BinField expected_fields[1] = { BinField::Value };
     MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif // defined(DEBUG)
 
-
-
-
     BINJS_MOZ_TRY_DECL(value, tokenizer_->readDouble());
 
-
     BINJS_TRY_DECL(result, factory_.newNumber(value, DecimalPoint::HasDecimal, tokenizer_->pos(start)));
     return result;
 }
 
 
 /*
  interface LiteralPropertyName : Node {
     string value;
@@ -5995,42 +5456,40 @@ BinASTParser<Tok>::parseInterfaceLiteral
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseLiteralPropertyName()
 {
     BinKind kind;
     BinFields fields(cx_);
     AutoTaggedTuple guard(*tokenizer_);
 
     MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    const auto start = tokenizer_->offset();
-
+    if (kind != BinKind::LiteralPropertyName) {
+        return raiseInvalidKind("LiteralPropertyName", kind);
+    }
+    const auto start = tokenizer_->offset();
     BINJS_MOZ_TRY_DECL(result, parseInterfaceLiteralPropertyName(start, kind, fields));
     MOZ_TRY(guard.done());
 
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceLiteralPropertyName(const size_t start, const BinKind kind, const BinFields& fields)
 {
     MOZ_ASSERT(kind == BinKind::LiteralPropertyName);
     BINJS_TRY(CheckRecursionLimit(cx_));
 
-
 #if defined(DEBUG)
     const BinField expected_fields[1] = { BinField::Value };
     MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif // defined(DEBUG)
 
-
-
     RootedAtom value(cx_);
     MOZ_TRY_VAR(value, tokenizer_->readAtom());
 
-
     ParseNode* result;
     uint32_t index;
     if (value->isIndex(&index))
         BINJS_TRY_VAR(result, factory_.newNumber(index, NoDecimal, TokenPos(start, tokenizer_->offset())));
     else
         BINJS_TRY_VAR(result, factory_.newObjectLiteralPropertyName(value, tokenizer_->pos(start)));
     return result;
 }
@@ -6045,41 +5504,39 @@ BinASTParser<Tok>::parseInterfaceLiteral
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseLiteralRegExpExpression()
 {
     BinKind kind;
     BinFields fields(cx_);
     AutoTaggedTuple guard(*tokenizer_);
 
     MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    const auto start = tokenizer_->offset();
-
+    if (kind != BinKind::LiteralRegExpExpression) {
+        return raiseInvalidKind("LiteralRegExpExpression", kind);
+    }
+    const auto start = tokenizer_->offset();
     BINJS_MOZ_TRY_DECL(result, parseInterfaceLiteralRegExpExpression(start, kind, fields));
     MOZ_TRY(guard.done());
 
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceLiteralRegExpExpression(const size_t start, const BinKind kind, const BinFields& fields)
 {
     MOZ_ASSERT(kind == BinKind::LiteralRegExpExpression);
     BINJS_TRY(CheckRecursionLimit(cx_));
 
-
 #if defined(DEBUG)
     const BinField expected_fields[2] = { BinField::Pattern, BinField::Flags };
     MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif // defined(DEBUG)
 
-
-
     RootedAtom pattern(cx_);
     MOZ_TRY_VAR(pattern, tokenizer_->readAtom());
-
     Chars flags(cx_);
     MOZ_TRY(tokenizer_->readChars(flags));
 
     RegExpFlag reflags = NoFlags;
     for (auto c : flags) {
         if (c == 'g' && !(reflags & GlobalFlag))
             reflags = RegExpFlag(reflags | GlobalFlag);
         else if (c == 'i' && !(reflags & IgnoreCaseFlag))
@@ -6115,42 +5572,40 @@ BinASTParser<Tok>::parseInterfaceLiteral
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseLiteralStringExpression()
 {
     BinKind kind;
     BinFields fields(cx_);
     AutoTaggedTuple guard(*tokenizer_);
 
     MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    const auto start = tokenizer_->offset();
-
+    if (kind != BinKind::LiteralStringExpression) {
+        return raiseInvalidKind("LiteralStringExpression", kind);
+    }
+    const auto start = tokenizer_->offset();
     BINJS_MOZ_TRY_DECL(result, parseInterfaceLiteralStringExpression(start, kind, fields));
     MOZ_TRY(guard.done());
 
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceLiteralStringExpression(const size_t start, const BinKind kind, const BinFields& fields)
 {
     MOZ_ASSERT(kind == BinKind::LiteralStringExpression);
     BINJS_TRY(CheckRecursionLimit(cx_));
 
-
 #if defined(DEBUG)
     const BinField expected_fields[1] = { BinField::Value };
     MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif // defined(DEBUG)
 
-
-
     RootedAtom value(cx_);
     MOZ_TRY_VAR(value, tokenizer_->readAtom());
 
-
     BINJS_TRY_DECL(result, factory_.newStringLiteral(value, tokenizer_->pos(start)));
     return result;
 }
 
 
 /*
  interface Module : Node {
     AssertedVarScope? scope;
@@ -6161,18 +5616,20 @@ BinASTParser<Tok>::parseInterfaceLiteral
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseModule()
 {
     BinKind kind;
     BinFields fields(cx_);
     AutoTaggedTuple guard(*tokenizer_);
 
     MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    const auto start = tokenizer_->offset();
-
+    if (kind != BinKind::Module) {
+        return raiseInvalidKind("Module", kind);
+    }
+    const auto start = tokenizer_->offset();
     BINJS_MOZ_TRY_DECL(result, parseInterfaceModule(start, kind, fields));
     MOZ_TRY(guard.done());
 
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceModule(const size_t start, const BinKind kind, const BinFields& fields)
@@ -6190,47 +5647,41 @@ BinASTParser<Tok>::parseInterfaceModule(
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseNewExpression()
 {
     BinKind kind;
     BinFields fields(cx_);
     AutoTaggedTuple guard(*tokenizer_);
 
     MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    const auto start = tokenizer_->offset();
-
+    if (kind != BinKind::NewExpression) {
+        return raiseInvalidKind("NewExpression", kind);
+    }
+    const auto start = tokenizer_->offset();
     BINJS_MOZ_TRY_DECL(result, parseInterfaceNewExpression(start, kind, fields));
     MOZ_TRY(guard.done());
 
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceNewExpression(const size_t start, const BinKind kind, const BinFields& fields)
 {
     MOZ_ASSERT(kind == BinKind::NewExpression);
     BINJS_TRY(CheckRecursionLimit(cx_));
 
-
 #if defined(DEBUG)
     const BinField expected_fields[2] = { BinField::Callee, BinField::Arguments };
     MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif // defined(DEBUG)
 
-
-
-
     BINJS_MOZ_TRY_DECL(callee, parseExpression());
 
-
-
-
     BINJS_MOZ_TRY_DECL(arguments, parseArguments());
 
-
     auto result = arguments;
     result->setKind(ParseNodeKind::New);
     result->prepend(callee);
     result->setOp(JSOP_NEW);
     return result;
 }
 
 
@@ -6241,18 +5692,20 @@ BinASTParser<Tok>::parseInterfaceNewExpr
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseNewTargetExpression()
 {
     BinKind kind;
     BinFields fields(cx_);
     AutoTaggedTuple guard(*tokenizer_);
 
     MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    const auto start = tokenizer_->offset();
-
+    if (kind != BinKind::NewTargetExpression) {
+        return raiseInvalidKind("NewTargetExpression", kind);
+    }
+    const auto start = tokenizer_->offset();
     BINJS_MOZ_TRY_DECL(result, parseInterfaceNewTargetExpression(start, kind, fields));
     MOZ_TRY(guard.done());
 
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceNewTargetExpression(const size_t start, const BinKind kind, const BinFields& fields)
@@ -6269,18 +5722,20 @@ BinASTParser<Tok>::parseInterfaceNewTarg
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseObjectAssignmentTarget()
 {
     BinKind kind;
     BinFields fields(cx_);
     AutoTaggedTuple guard(*tokenizer_);
 
     MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    const auto start = tokenizer_->offset();
-
+    if (kind != BinKind::ObjectAssignmentTarget) {
+        return raiseInvalidKind("ObjectAssignmentTarget", kind);
+    }
+    const auto start = tokenizer_->offset();
     BINJS_MOZ_TRY_DECL(result, parseInterfaceObjectAssignmentTarget(start, kind, fields));
     MOZ_TRY(guard.done());
 
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceObjectAssignmentTarget(const size_t start, const BinKind kind, const BinFields& fields)
@@ -6297,18 +5752,20 @@ BinASTParser<Tok>::parseInterfaceObjectA
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseObjectBinding()
 {
     BinKind kind;
     BinFields fields(cx_);
     AutoTaggedTuple guard(*tokenizer_);
 
     MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    const auto start = tokenizer_->offset();
-
+    if (kind != BinKind::ObjectBinding) {
+        return raiseInvalidKind("ObjectBinding", kind);
+    }
+    const auto start = tokenizer_->offset();
     BINJS_MOZ_TRY_DECL(result, parseInterfaceObjectBinding(start, kind, fields));
     MOZ_TRY(guard.done());
 
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceObjectBinding(const size_t start, const BinKind kind, const BinFields& fields)
@@ -6325,42 +5782,39 @@ BinASTParser<Tok>::parseInterfaceObjectB
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseObjectExpression()
 {
     BinKind kind;
     BinFields fields(cx_);
     AutoTaggedTuple guard(*tokenizer_);
 
     MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    const auto start = tokenizer_->offset();
-
+    if (kind != BinKind::ObjectExpression) {
+        return raiseInvalidKind("ObjectExpression", kind);
+    }
+    const auto start = tokenizer_->offset();
     BINJS_MOZ_TRY_DECL(result, parseInterfaceObjectExpression(start, kind, fields));
     MOZ_TRY(guard.done());
 
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceObjectExpression(const size_t start, const BinKind kind, const BinFields& fields)
 {
     MOZ_ASSERT(kind == BinKind::ObjectExpression);
     BINJS_TRY(CheckRecursionLimit(cx_));
 
-
 #if defined(DEBUG)
     const BinField expected_fields[1] = { BinField::Properties };
     MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif // defined(DEBUG)
 
-
-
-
     BINJS_MOZ_TRY_DECL(properties, parseListOfObjectProperty());
 
-
     auto result = properties;
     return result;
 }
 
 
 /*
  interface ReturnStatement : Node {
     Expression? expression;
@@ -6369,47 +5823,45 @@ BinASTParser<Tok>::parseInterfaceObjectE
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseReturnStatement()
 {
     BinKind kind;
     BinFields fields(cx_);
     AutoTaggedTuple guard(*tokenizer_);
 
     MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    const auto start = tokenizer_->offset();
-
+    if (kind != BinKind::ReturnStatement) {
+        return raiseInvalidKind("ReturnStatement", kind);
+    }
+    const auto start = tokenizer_->offset();
     BINJS_MOZ_TRY_DECL(result, parseInterfaceReturnStatement(start, kind, fields));
     MOZ_TRY(guard.done());
 
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceReturnStatement(const size_t start, const BinKind kind, const BinFields& fields)
 {
     MOZ_ASSERT(kind == BinKind::ReturnStatement);
     BINJS_TRY(CheckRecursionLimit(cx_));
 
-
 #if defined(DEBUG)
     const BinField expected_fields[1] = { BinField::Expression };
     MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif // defined(DEBUG)
-
     if (!parseContext_->isFunctionBox()) {
         // Return statements are permitted only inside functions.
         return raiseInvalidKind("Toplevel Statement", kind);
     }
 
     parseContext_->functionBox()->usesReturn = true;
 
-
     BINJS_MOZ_TRY_DECL(expression, parseOptionalExpression());
 
-
     BINJS_TRY_DECL(result, factory_.newReturnStatement(expression, tokenizer_->pos(start)));
     return result;
 }
 
 
 /*
  interface Script : Node {
     AssertedVarScope? scope;
@@ -6420,52 +5872,43 @@ BinASTParser<Tok>::parseInterfaceReturnS
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseScript()
 {
     BinKind kind;
     BinFields fields(cx_);
     AutoTaggedTuple guard(*tokenizer_);
 
     MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    const auto start = tokenizer_->offset();
-
+    if (kind != BinKind::Script) {
+        return raiseInvalidKind("Script", kind);
+    }
+    const auto start = tokenizer_->offset();
     BINJS_MOZ_TRY_DECL(result, parseInterfaceScript(start, kind, fields));
     MOZ_TRY(guard.done());
 
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceScript(const size_t start, const BinKind kind, const BinFields& fields)
 {
     MOZ_ASSERT(kind == BinKind::Script);
     BINJS_TRY(CheckRecursionLimit(cx_));
 
-
 #if defined(DEBUG)
     const BinField expected_fields[3] = { BinField::Scope, BinField::Directives, BinField::Statements };
     MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif // defined(DEBUG)
 
-
-
-
     MOZ_TRY(parseOptionalAssertedVarScope());
 
-
-
-
     BINJS_MOZ_TRY_DECL(directives, parseListOfDirective());
 
-
-
-
     BINJS_MOZ_TRY_DECL(statements, parseListOfStatement());
 
-
     MOZ_TRY(checkClosedVars(parseContext_->varScope())); BINJS_MOZ_TRY_DECL(result, appendDirectivesToBody(/* body = */ statements, /* directives = */ directives));
     return result;
 }
 
 
 /*
  interface ShorthandProperty : Node {
     IdentifierExpression name;
@@ -6474,42 +5917,39 @@ BinASTParser<Tok>::parseInterfaceScript(
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseShorthandProperty()
 {
     BinKind kind;
     BinFields fields(cx_);
     AutoTaggedTuple guard(*tokenizer_);
 
     MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    const auto start = tokenizer_->offset();
-
+    if (kind != BinKind::ShorthandProperty) {
+        return raiseInvalidKind("ShorthandProperty", kind);
+    }
+    const auto start = tokenizer_->offset();
     BINJS_MOZ_TRY_DECL(result, parseInterfaceShorthandProperty(start, kind, fields));
     MOZ_TRY(guard.done());
 
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceShorthandProperty(const size_t start, const BinKind kind, const BinFields& fields)
 {
     MOZ_ASSERT(kind == BinKind::ShorthandProperty);
     BINJS_TRY(CheckRecursionLimit(cx_));
 
-
 #if defined(DEBUG)
     const BinField expected_fields[1] = { BinField::Name };
     MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif // defined(DEBUG)
 
-
-
-
     BINJS_MOZ_TRY_DECL(name, parseIdentifierExpression());
 
-
     if (!factory_.isUsableAsObjectPropertyName(name))
         BINJS_TRY_VAR(name, factory_.newObjectLiteralPropertyName(name->name(), tokenizer_->pos(start)));
 
     BINJS_TRY_DECL(result, factory_.newObjectMethodOrPropertyDefinition(name, name, AccessorType::None));
     return result;
 }
 
 
@@ -6521,18 +5961,20 @@ BinASTParser<Tok>::parseInterfaceShortha
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseSkippableArrowExpression()
 {
     BinKind kind;
     BinFields fields(cx_);
     AutoTaggedTuple guard(*tokenizer_);
 
     MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    const auto start = tokenizer_->offset();
-
+    if (kind != BinKind::SkippableArrowExpression) {
+        return raiseInvalidKind("SkippableArrowExpression", kind);
+    }
+    const auto start = tokenizer_->offset();
     BINJS_MOZ_TRY_DECL(result, parseInterfaceSkippableArrowExpression(start, kind, fields));
     MOZ_TRY(guard.done());
 
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceSkippableArrowExpression(const size_t start, const BinKind kind, const BinFields& fields)
@@ -6549,18 +5991,20 @@ BinASTParser<Tok>::parseInterfaceSkippab
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseSkippableFunctionDeclaration()
 {
     BinKind kind;
     BinFields fields(cx_);
     AutoTaggedTuple guard(*tokenizer_);
 
     MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    const auto start = tokenizer_->offset();
-
+    if (kind != BinKind::SkippableFunctionDeclaration) {
+        return raiseInvalidKind("SkippableFunctionDeclaration", kind);
+    }
+    const auto start = tokenizer_->offset();
     BINJS_MOZ_TRY_DECL(result, parseInterfaceSkippableFunctionDeclaration(start, kind, fields));
     MOZ_TRY(guard.done());
 
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceSkippableFunctionDeclaration(const size_t start, const BinKind kind, const BinFields& fields)
@@ -6577,18 +6021,20 @@ BinASTParser<Tok>::parseInterfaceSkippab
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseSkippableFunctionExpression()
 {
     BinKind kind;
     BinFields fields(cx_);
     AutoTaggedTuple guard(*tokenizer_);
 
     MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    const auto start = tokenizer_->offset();
-
+    if (kind != BinKind::SkippableFunctionExpression) {
+        return raiseInvalidKind("SkippableFunctionExpression", kind);
+    }
+    const auto start = tokenizer_->offset();
     BINJS_MOZ_TRY_DECL(result, parseInterfaceSkippableFunctionExpression(start, kind, fields));
     MOZ_TRY(guard.done());
 
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceSkippableFunctionExpression(const size_t start, const BinKind kind, const BinFields& fields)
@@ -6605,18 +6051,20 @@ BinASTParser<Tok>::parseInterfaceSkippab
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseSkippableGetter()
 {
     BinKind kind;
     BinFields fields(cx_);
     AutoTaggedTuple guard(*tokenizer_);
 
     MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    const auto start = tokenizer_->offset();
-
+    if (kind != BinKind::SkippableGetter) {
+        return raiseInvalidKind("SkippableGetter", kind);
+    }
+    const auto start = tokenizer_->offset();
     BINJS_MOZ_TRY_DECL(result, parseInterfaceSkippableGetter(start, kind, fields));
     MOZ_TRY(guard.done());
 
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceSkippableGetter(const size_t start, const BinKind kind, const BinFields& fields)
@@ -6633,18 +6081,20 @@ BinASTParser<Tok>::parseInterfaceSkippab
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseSkippableMethod()
 {
     BinKind kind;
     BinFields fields(cx_);
     AutoTaggedTuple guard(*tokenizer_);
 
     MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    const auto start = tokenizer_->offset();
-
+    if (kind != BinKind::SkippableMethod) {
+        return raiseInvalidKind("SkippableMethod", kind);
+    }
+    const auto start = tokenizer_->offset();
     BINJS_MOZ_TRY_DECL(result, parseInterfaceSkippableMethod(start, kind, fields));
     MOZ_TRY(guard.done());
 
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceSkippableMethod(const size_t start, const BinKind kind, const BinFields& fields)
@@ -6661,18 +6111,20 @@ BinASTParser<Tok>::parseInterfaceSkippab
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseSkippableSetter()
 {
     BinKind kind;
     BinFields fields(cx_);
     AutoTaggedTuple guard(*tokenizer_);
 
     MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    const auto start = tokenizer_->offset();
-
+    if (kind != BinKind::SkippableSetter) {
+        return raiseInvalidKind("SkippableSetter", kind);
+    }
+    const auto start = tokenizer_->offset();
     BINJS_MOZ_TRY_DECL(result, parseInterfaceSkippableSetter(start, kind, fields));
     MOZ_TRY(guard.done());
 
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceSkippableSetter(const size_t start, const BinKind kind, const BinFields& fields)
@@ -6689,18 +6141,20 @@ BinASTParser<Tok>::parseInterfaceSkippab
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseSpreadElement()
 {
     BinKind kind;
     BinFields fields(cx_);
     AutoTaggedTuple guard(*tokenizer_);
 
     MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    const auto start = tokenizer_->offset();
-
+    if (kind != BinKind::SpreadElement) {
+        return raiseInvalidKind("SpreadElement", kind);
+    }
+    const auto start = tokenizer_->offset();
     BINJS_MOZ_TRY_DECL(result, parseInterfaceSpreadElement(start, kind, fields));
     MOZ_TRY(guard.done());
 
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceSpreadElement(const size_t start, const BinKind kind, const BinFields& fields)
@@ -6718,47 +6172,42 @@ BinASTParser<Tok>::parseInterfaceSpreadE
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseStaticMemberAssignmentTarget()
 {
     BinKind kind;
     BinFields fields(cx_);
     AutoTaggedTuple guard(*tokenizer_);
 
     MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    const auto start = tokenizer_->offset();
-
+    if (kind != BinKind::StaticMemberAssignmentTarget) {
+        return raiseInvalidKind("StaticMemberAssignmentTarget", kind);
+    }
+    const auto start = tokenizer_->offset();
     BINJS_MOZ_TRY_DECL(result, parseInterfaceStaticMemberAssignmentTarget(start, kind, fields));
     MOZ_TRY(guard.done());
 
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceStaticMemberAssignmentTarget(const size_t start, const BinKind kind, const BinFields& fields)
 {
     MOZ_ASSERT(kind == BinKind::StaticMemberAssignmentTarget);
     BINJS_TRY(CheckRecursionLimit(cx_));
 
-
 #if defined(DEBUG)
     const BinField expected_fields[2] = { BinField::Object, BinField::Property };
     MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif // defined(DEBUG)
 
-
-
-
     BINJS_MOZ_TRY_DECL(object, parseExpressionOrSuper());
 
-
-
     RootedAtom property(cx_);
     MOZ_TRY_VAR(property, tokenizer_->readAtom());
 
-
     BINJS_TRY_DECL(result, factory_.newPropertyAccess(object, property->asPropertyName(), start));
     return result;
 }
 
 
 /*
  interface StaticMemberExpression : Node {
     (Expression or Super) object;
@@ -6768,47 +6217,42 @@ BinASTParser<Tok>::parseInterfaceStaticM
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseStaticMemberExpression()
 {
     BinKind kind;
     BinFields fields(cx_);
     AutoTaggedTuple guard(*tokenizer_);
 
     MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    const auto start = tokenizer_->offset();
-
+    if (kind != BinKind::StaticMemberExpression) {
+        return raiseInvalidKind("StaticMemberExpression", kind);
+    }
+    const auto start = tokenizer_->offset();
     BINJS_MOZ_TRY_DECL(result, parseInterfaceStaticMemberExpression(start, kind, fields));
     MOZ_TRY(guard.done());
 
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceStaticMemberExpression(const size_t start, const BinKind kind, const BinFields& fields)
 {
     MOZ_ASSERT(kind == BinKind::StaticMemberExpression);
     BINJS_TRY(CheckRecursionLimit(cx_));
 
-
 #if defined(DEBUG)
     const BinField expected_fields[2] = { BinField::Object, BinField::Property };
     MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif // defined(DEBUG)
 
-
-
-
     BINJS_MOZ_TRY_DECL(object, parseExpressionOrSuper());
 
-
-
     RootedAtom property(cx_);
     MOZ_TRY_VAR(property, tokenizer_->readAtom());
 
-
     BINJS_TRY_DECL(result, factory_.newPropertyAccess(object, property->asPropertyName(), start));
     return result;
 }
 
 
 /*
  interface Super : Node {
  }
@@ -6816,18 +6260,20 @@ BinASTParser<Tok>::parseInterfaceStaticM
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseSuper()
 {
     BinKind kind;
     BinFields fields(cx_);
     AutoTaggedTuple guard(*tokenizer_);
 
     MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    const auto start = tokenizer_->offset();
-
+    if (kind != BinKind::Super) {
+        return raiseInvalidKind("Super", kind);
+    }
+    const auto start = tokenizer_->offset();
     BINJS_MOZ_TRY_DECL(result, parseInterfaceSuper(start, kind, fields));
     MOZ_TRY(guard.done());
 
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceSuper(const size_t start, const BinKind kind, const BinFields& fields)
@@ -6845,47 +6291,41 @@ BinASTParser<Tok>::parseInterfaceSuper(c
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseSwitchCase()
 {
     BinKind kind;
     BinFields fields(cx_);
     AutoTaggedTuple guard(*tokenizer_);
 
     MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    const auto start = tokenizer_->offset();
-
+    if (kind != BinKind::SwitchCase) {
+        return raiseInvalidKind("SwitchCase", kind);
+    }
+    const auto start = tokenizer_->offset();
     BINJS_MOZ_TRY_DECL(result, parseInterfaceSwitchCase(start, kind, fields));
     MOZ_TRY(guard.done());
 
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceSwitchCase(const size_t start, const BinKind kind, const BinFields& fields)
 {
     MOZ_ASSERT(kind == BinKind::SwitchCase);
     BINJS_TRY(CheckRecursionLimit(cx_));
 
-
 #if defined(DEBUG)
     const BinField expected_fields[2] = { BinField::Test, BinField::Consequent };
     MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif // defined(DEBUG)
 
-
-
-
     BINJS_MOZ_TRY_DECL(test, parseExpression());
 
-
-
-
     BINJS_MOZ_TRY_DECL(consequent, parseListOfStatement());
 
-
     BINJS_TRY_DECL(result, factory_.newCaseOrDefault(start, test, consequent));
     return result;
 }
 
 
 /*
  interface SwitchDefault : Node {
     FrozenArray<Statement> consequent;
@@ -6894,42 +6334,39 @@ BinASTParser<Tok>::parseInterfaceSwitchC
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseSwitchDefault()
 {
     BinKind kind;
     BinFields fields(cx_);
     AutoTaggedTuple guard(*tokenizer_);
 
     MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    const auto start = tokenizer_->offset();
-
+    if (kind != BinKind::SwitchDefault) {
+        return raiseInvalidKind("SwitchDefault", kind);
+    }
+    const auto start = tokenizer_->offset();
     BINJS_MOZ_TRY_DECL(result, parseInterfaceSwitchDefault(start, kind, fields));
     MOZ_TRY(guard.done());
 
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceSwitchDefault(const size_t start, const BinKind kind, const BinFields& fields)
 {
     MOZ_ASSERT(kind == BinKind::SwitchDefault);
     BINJS_TRY(CheckRecursionLimit(cx_));
 
-
 #if defined(DEBUG)
     const BinField expected_fields[1] = { BinField::Consequent };
     MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif // defined(DEBUG)
 
-
-
-
     BINJS_MOZ_TRY_DECL(consequent, parseListOfStatement());
 
-
     BINJS_TRY_DECL(result, factory_.newCaseOrDefault(start, nullptr, consequent));
     return result;
 }
 
 
 /*
  interface SwitchStatement : Node {
     Expression discriminant;
@@ -6939,47 +6376,41 @@ BinASTParser<Tok>::parseInterfaceSwitchD
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseSwitchStatement()
 {
     BinKind kind;
     BinFields fields(cx_);
     AutoTaggedTuple guard(*tokenizer_);
 
     MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    const auto start = tokenizer_->offset();
-
+    if (kind != BinKind::SwitchStatement) {
+        return raiseInvalidKind("SwitchStatement", kind);
+    }
+    const auto start = tokenizer_->offset();
     BINJS_MOZ_TRY_DECL(result, parseInterfaceSwitchStatement(start, kind, fields));
     MOZ_TRY(guard.done());
 
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceSwitchStatement(const size_t start, const BinKind kind, const BinFields& fields)
 {
     MOZ_ASSERT(kind == BinKind::SwitchStatement);
     BINJS_TRY(CheckRecursionLimit(cx_));
 
-
 #if defined(DEBUG)
     const BinField expected_fields[2] = { BinField::Discriminant, BinField::Cases };
     MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif // defined(DEBUG)
 
-
-
-
     BINJS_MOZ_TRY_DECL(discriminant, parseExpression());
 
-
-
-
     BINJS_MOZ_TRY_DECL(cases, parseListOfSwitchCase());
 
-
     BINJS_TRY_DECL(scope, factory_.newLexicalScope(nullptr, cases));
     BINJS_TRY_DECL(result, factory_.newSwitchStatement(start, discriminant, scope));
     return result;
 }
 
 
 /*
  interface SwitchStatementWithDefault : Node {
@@ -6992,57 +6423,45 @@ BinASTParser<Tok>::parseInterfaceSwitchS
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseSwitchStatementWithDefault()
 {
     BinKind kind;
     BinFields fields(cx_);
     AutoTaggedTuple guard(*tokenizer_);
 
     MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    const auto start = tokenizer_->offset();
-
+    if (kind != BinKind::SwitchStatementWithDefault) {
+        return raiseInvalidKind("SwitchStatementWithDefault", kind);
+    }
+    const auto start = tokenizer_->offset();
     BINJS_MOZ_TRY_DECL(result, parseInterfaceSwitchStatementWithDefault(start, kind, fields));
     MOZ_TRY(guard.done());
 
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceSwitchStatementWithDefault(const size_t start, const BinKind kind, const BinFields& fields)
 {
     MOZ_ASSERT(kind == BinKind::SwitchStatementWithDefault);
     BINJS_TRY(CheckRecursionLimit(cx_));
 
-
 #if defined(DEBUG)
     const BinField expected_fields[4] = { BinField::Discriminant, BinField::PreDefaultCases, BinField::DefaultCase, BinField::PostDefaultCases };
     MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif // defined(DEBUG)
 
-
-
-
     BINJS_MOZ_TRY_DECL(discriminant, parseExpression());
 
-
-
-
     BINJS_MOZ_TRY_DECL(preDefaultCases, parseListOfSwitchCase());
 
-
-
-
     BINJS_MOZ_TRY_DECL(defaultCase, parseSwitchDefault());
 
-
-
-
     BINJS_MOZ_TRY_DECL(postDefaultCases, parseListOfSwitchCase());
 
-
     // Concatenate `preDefaultCase`, `defaultCase`, `postDefaultCase`
     auto cases = preDefaultCases;
     factory_.addList(cases, defaultCase);
     ParseNode* iter = postDefaultCases->pn_head;
     while (iter) {
         ParseNode* next = iter->pn_next;
         factory_.addList(cases, iter);
         iter = next;
@@ -7061,18 +6480,20 @@ BinASTParser<Tok>::parseInterfaceSwitchS
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseTemplateElement()
 {
     BinKind kind;
     BinFields fields(cx_);
     AutoTaggedTuple guard(*tokenizer_);
 
     MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    const auto start = tokenizer_->offset();
-
+    if (kind != BinKind::TemplateElement) {
+        return raiseInvalidKind("TemplateElement", kind);
+    }
+    const auto start = tokenizer_->offset();
     BINJS_MOZ_TRY_DECL(result, parseInterfaceTemplateElement(start, kind, fields));
     MOZ_TRY(guard.done());
 
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceTemplateElement(const size_t start, const BinKind kind, const BinFields& fields)
@@ -7090,18 +6511,20 @@ BinASTParser<Tok>::parseInterfaceTemplat
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseTemplateExpression()
 {
     BinKind kind;
     BinFields fields(cx_);
     AutoTaggedTuple guard(*tokenizer_);
 
     MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    const auto start = tokenizer_->offset();
-
+    if (kind != BinKind::TemplateExpression) {
+        return raiseInvalidKind("TemplateExpression", kind);
+    }
+    const auto start = tokenizer_->offset();
     BINJS_MOZ_TRY_DECL(result, parseInterfaceTemplateExpression(start, kind, fields));
     MOZ_TRY(guard.done());
 
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceTemplateExpression(const size_t start, const BinKind kind, const BinFields& fields)
@@ -7117,30 +6540,31 @@ BinASTParser<Tok>::parseInterfaceTemplat
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseThisExpression()
 {
     BinKind kind;
     BinFields fields(cx_);
     AutoTaggedTuple guard(*tokenizer_);
 
     MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    const auto start = tokenizer_->offset();
-
+    if (kind != BinKind::ThisExpression) {
+        return raiseInvalidKind("ThisExpression", kind);
+    }
+    const auto start = tokenizer_->offset();
     BINJS_MOZ_TRY_DECL(result, parseInterfaceThisExpression(start, kind, fields));
     MOZ_TRY(guard.done());
 
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceThisExpression(const size_t start, const BinKind kind, const BinFields& fields)
 {
     MOZ_ASSERT(kind == BinKind::ThisExpression);
     BINJS_TRY(CheckRecursionLimit(cx_));
-
 MOZ_TRY(tokenizer_->checkFields0(kind, fields));
 
     if (parseContext_->isFunctionBox())
         parseContext_->functionBox()->usesThis = true;
 
     TokenPos pos = tokenizer_->pos(start);
     ParseNode* thisName(nullptr);
     if (parseContext_->sc()->thisBinding() == ThisBinding::Function) {
@@ -7162,42 +6586,39 @@ MOZ_TRY(tokenizer_->checkFields0(kind, f
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseThrowStatement()
 {
     BinKind kind;
     BinFields fields(cx_);
     AutoTaggedTuple guard(*tokenizer_);
 
     MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    const auto start = tokenizer_->offset();
-
+    if (kind != BinKind::ThrowStatement) {
+        return raiseInvalidKind("ThrowStatement", kind);
+    }
+    const auto start = tokenizer_->offset();
     BINJS_MOZ_TRY_DECL(result, parseInterfaceThrowStatement(start, kind, fields));
     MOZ_TRY(guard.done());
 
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceThrowStatement(const size_t start, const BinKind kind, const BinFields& fields)
 {
     MOZ_ASSERT(kind == BinKind::ThrowStatement);
     BINJS_TRY(CheckRecursionLimit(cx_));
 
-
 #if defined(DEBUG)
     const BinField expected_fields[1] = { BinField::Expression };
     MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif // defined(DEBUG)
 
-
-
-
     BINJS_MOZ_TRY_DECL(expression, parseExpression());
 
-
     BINJS_TRY_DECL(result, factory_.newThrowStatement(expression, tokenizer_->pos(start)));
     return result;
 }
 
 
 /*
  interface TryCatchStatement : Node {
     Block body;
@@ -7207,51 +6628,47 @@ BinASTParser<Tok>::parseInterfaceThrowSt
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseTryCatchStatement()
 {
     BinKind kind;
     BinFields fields(cx_);
     AutoTaggedTuple guard(*tokenizer_);
 
     MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    const auto start = tokenizer_->offset();
-
+    if (kind != BinKind::TryCatchStatement) {
+        return raiseInvalidKind("TryCatchStatement", kind);
+    }
+    const auto start = tokenizer_->offset();
     BINJS_MOZ_TRY_DECL(result, parseInterfaceTryCatchStatement(start, kind, fields));
     MOZ_TRY(guard.done());
 
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceTryCatchStatement(const size_t start, const BinKind kind, const BinFields& fields)
 {
     MOZ_ASSERT(kind == BinKind::TryCatchStatement);
     BINJS_TRY(CheckRecursionLimit(cx_));
 
-
 #if defined(DEBUG)
     const BinField expected_fields[2] = { BinField::Body, BinField::CatchClause };
     MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif // defined(DEBUG)
-
-
     ParseNode* body;
     {
         ParseContext::Statement stmt(parseContext_, StatementKind::Try);
         ParseContext::Scope scope(cx_, parseContext_, usedNames_);
         BINJS_TRY(scope.init(parseContext_));
         MOZ_TRY_VAR(body, parseBlock());
 
     }
 
-
-
     BINJS_MOZ_TRY_DECL(catchClause, parseCatchClause());
 
-
     BINJS_TRY_DECL(result, factory_.newTryStatement(start, body, catchClause, /* finally = */ nullptr));
     return result;
 }
 
 
 /*
  interface TryFinallyStatement : Node {
     Block body;
@@ -7262,51 +6679,46 @@ BinASTParser<Tok>::parseInterfaceTryCatc
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseTryFinallyStatement()
 {
     BinKind kind;
     BinFields fields(cx_);
     AutoTaggedTuple guard(*tokenizer_);
 
     MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    const auto start = tokenizer_->offset();
-
+    if (kind != BinKind::TryFinallyStatement) {
+        return raiseInvalidKind("TryFinallyStatement", kind);
+    }
+    const auto start = tokenizer_->offset();
     BINJS_MOZ_TRY_DECL(result, parseInterfaceTryFinallyStatement(start, kind, fields));
     MOZ_TRY(guard.done());
 
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceTryFinallyStatement(const size_t start, const BinKind kind, const BinFields& fields)
 {
     MOZ_ASSERT(kind == BinKind::TryFinallyStatement);
     BINJS_TRY(CheckRecursionLimit(cx_));
 
-
 #if defined(DEBUG)
     const BinField expected_fields[3] = { BinField::Body, BinField::CatchClause, BinField::Finalizer };
     MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif // defined(DEBUG)
-
-
     ParseNode* body;
     {
         ParseContext::Statement stmt(parseContext_, StatementKind::Try);
         ParseContext::Scope scope(cx_, parseContext_, usedNames_);
         BINJS_TRY(scope.init(parseContext_));
         MOZ_TRY_VAR(body, parseBlock());
 
     }
 
-
-
     BINJS_MOZ_TRY_DECL(catchClause, parseOptionalCatchClause());
-
-
     ParseNode* finalizer;
     {
         ParseContext::Statement stmt(parseContext_, StatementKind::Finally);
         ParseContext::Scope scope(cx_, parseContext_, usedNames_);
         BINJS_TRY(scope.init(parseContext_));
         MOZ_TRY_VAR(finalizer, parseBlock());
 
     }
@@ -7325,47 +6737,41 @@ BinASTParser<Tok>::parseInterfaceTryFina
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseUnaryExpression()
 {
     BinKind kind;
     BinFields fields(cx_);
     AutoTaggedTuple guard(*tokenizer_);
 
     MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    const auto start = tokenizer_->offset();
-
+    if (kind != BinKind::UnaryExpression) {
+        return raiseInvalidKind("UnaryExpression", kind);
+    }
+    const auto start = tokenizer_->offset();
     BINJS_MOZ_TRY_DECL(result, parseInterfaceUnaryExpression(start, kind, fields));
     MOZ_TRY(guard.done());
 
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceUnaryExpression(const size_t start, const BinKind kind, const BinFields& fields)
 {
     MOZ_ASSERT(kind == BinKind::UnaryExpression);
     BINJS_TRY(CheckRecursionLimit(cx_));
 
-
 #if defined(DEBUG)
     const BinField expected_fields[2] = { BinField::Operator, BinField::Operand };
     MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif // defined(DEBUG)
 
-
-
-
     BINJS_MOZ_TRY_DECL(operator_, parseUnaryOperator());
 
-
-
-
     BINJS_MOZ_TRY_DECL(operand, parseExpression());
 
-
     ParseNodeKind pnk;
     switch (operator_) {
       case UnaryOperator::Minus:
         pnk = ParseNodeKind::Neg;
         break;
       case UnaryOperator::Plus:
         pnk = ParseNodeKind::Pos;
         break;
@@ -7418,52 +6824,43 @@ BinASTParser<Tok>::parseInterfaceUnaryEx
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseUpdateExpression()
 {
     BinKind kind;
     BinFields fields(cx_);
     AutoTaggedTuple guard(*tokenizer_);
 
     MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    const auto start = tokenizer_->offset();
-
+    if (kind != BinKind::UpdateExpression) {
+        return raiseInvalidKind("UpdateExpression", kind);
+    }
+    const auto start = tokenizer_->offset();
     BINJS_MOZ_TRY_DECL(result, parseInterfaceUpdateExpression(start, kind, fields));
     MOZ_TRY(guard.done());
 
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceUpdateExpression(const size_t start, const BinKind kind, const BinFields& fields)
 {
     MOZ_ASSERT(kind == BinKind::UpdateExpression);
     BINJS_TRY(CheckRecursionLimit(cx_));
 
-
 #if defined(DEBUG)
     const BinField expected_fields[3] = { BinField::IsPrefix, BinField::Operator, BinField::Operand };
     MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif // defined(DEBUG)
 
-
-
-
     BINJS_MOZ_TRY_DECL(isPrefix, tokenizer_->readBool());
 
-
-
-
     BINJS_MOZ_TRY_DECL(operator_, parseUpdateOperator());
 
-
-
-
     BINJS_MOZ_TRY_DECL(operand, parseSimpleAssignmentTarget());
 
-
     ParseNodeKind pnk;
     switch (operator_) {
       case UpdateOperator::Incr:
         pnk = isPrefix ? ParseNodeKind::PreIncrement
                        : ParseNodeKind::PostIncrement;
         break;
       case UpdateOperator::Decr:
         pnk = isPrefix ? ParseNodeKind::PreDecrement
@@ -7484,48 +6881,43 @@ BinASTParser<Tok>::parseInterfaceUpdateE
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseVariableDeclaration()
 {
     BinKind kind;
     BinFields fields(cx_);
     AutoTaggedTuple guard(*tokenizer_);
 
     MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    const auto start = tokenizer_->offset();
-
+    if (kind != BinKind::VariableDeclaration) {
+        return raiseInvalidKind("VariableDeclaration", kind);
+    }
+    const auto start = tokenizer_->offset();
     BINJS_MOZ_TRY_DECL(result, parseInterfaceVariableDeclaration(start, kind, fields));
     MOZ_TRY(guard.done());
 
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceVariableDeclaration(const size_t start, const BinKind kind, const BinFields& fields)
 {
     MOZ_ASSERT(kind == BinKind::VariableDeclaration);
     BINJS_TRY(CheckRecursionLimit(cx_));
 
-
 #if defined(DEBUG)
     const BinField expected_fields[2] = { BinField::Kind, BinField::Declarators };
     MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif // defined(DEBUG)
-
     AutoVariableDeclarationKind kindGuard(this);
 
-
     BINJS_MOZ_TRY_DECL(kind_, parseVariableDeclarationKind());
     // Restored by `kindGuard`.
     variableDeclarationKind_ = kind_;
-
-
-
     BINJS_MOZ_TRY_DECL(declarators, parseListOfVariableDeclarator());
 
-
     // By specification, the list may not be empty.
     if (declarators->pn_count == 0)
         return raiseEmpty("VariableDeclaration");
 
     ParseNodeKind pnk;
     switch (kind_) {
       case VariableDeclarationKind::Var:
         pnk = ParseNodeKind::Var;
@@ -7552,47 +6944,41 @@ BinASTParser<Tok>::parseInterfaceVariabl
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseVariableDeclarator()
 {
     BinKind kind;
     BinFields fields(cx_);
     AutoTaggedTuple guard(*tokenizer_);
 
     MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    const auto start = tokenizer_->offset();
-
+    if (kind != BinKind::VariableDeclarator) {
+        return raiseInvalidKind("VariableDeclarator", kind);
+    }
+    const auto start = tokenizer_->offset();
     BINJS_MOZ_TRY_DECL(result, parseInterfaceVariableDeclarator(start, kind, fields));
     MOZ_TRY(guard.done());
 
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceVariableDeclarator(const size_t start, const BinKind kind, const BinFields& fields)
 {
     MOZ_ASSERT(kind == BinKind::VariableDeclarator);
     BINJS_TRY(CheckRecursionLimit(cx_));
 
-
 #if defined(DEBUG)
     const BinField expected_fields[2] = { BinField::Binding, BinField::Init };
     MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif // defined(DEBUG)
 
-
-
-
     BINJS_MOZ_TRY_DECL(binding, parseBinding());
 
-
-
-
     BINJS_MOZ_TRY_DECL(init, parseOptionalExpression());
 
-
     ParseNode* result;
     if (binding->isKind(ParseNodeKind::Name)) {
         // `var foo [= bar]``
         MOZ_TRY(checkBinding(binding->pn_atom->asPropertyName()));
 
         BINJS_TRY_VAR(result, factory_.newName(binding->pn_atom->asPropertyName(), tokenizer_->pos(start), cx_));
         if (init)
             result->pn_expr = init;
@@ -7619,47 +7005,42 @@ BinASTParser<Tok>::parseInterfaceVariabl
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseWhileStatement()
 {
     BinKind kind;
     BinFields fields(cx_);
     AutoTaggedTuple guard(*tokenizer_);
 
     MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    const auto start = tokenizer_->offset();
-
+    if (kind != BinKind::WhileStatement) {
+        return raiseInvalidKind("WhileStatement", kind);
+    }
+    const auto start = tokenizer_->offset();
     BINJS_MOZ_TRY_DECL(result, parseInterfaceWhileStatement(start, kind, fields));
     MOZ_TRY(guard.done());
 
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceWhileStatement(const size_t start, const BinKind kind, const BinFields& fields)
 {
     MOZ_ASSERT(kind == BinKind::WhileStatement);
     BINJS_TRY(CheckRecursionLimit(cx_));
 
-
 #if defined(DEBUG)
     const BinField expected_fields[2] = { BinField::Test, BinField::Body };
     MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif // defined(DEBUG)
-
     ParseContext::Statement stmt(parseContext_, StatementKind::WhileLoop);
 
-
     BINJS_MOZ_TRY_DECL(test, parseExpression());
 
-
-
-
     BINJS_MOZ_TRY_DECL(body, parseStatement());
 
-
     BINJS_TRY_DECL(result, factory_.newWhileStatement(start, test, body));
     return result;
 }
 
 
 /*
  interface WithStatement : Node {
     Expression object;
@@ -7669,47 +7050,41 @@ BinASTParser<Tok>::parseInterfaceWhileSt
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseWithStatement()
 {
     BinKind kind;
     BinFields fields(cx_);
     AutoTaggedTuple guard(*tokenizer_);
 
     MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    const auto start = tokenizer_->offset();
-
+    if (kind != BinKind::WithStatement) {
+        return raiseInvalidKind("WithStatement", kind);
+    }
+    const auto start = tokenizer_->offset();
     BINJS_MOZ_TRY_DECL(result, parseInterfaceWithStatement(start, kind, fields));
     MOZ_TRY(guard.done());
 
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceWithStatement(const size_t start, const BinKind kind, const BinFields& fields)
 {
     MOZ_ASSERT(kind == BinKind::WithStatement);
     BINJS_TRY(CheckRecursionLimit(cx_));
 
-
 #if defined(DEBUG)
     const BinField expected_fields[2] = { BinField::Object, BinField::Body };
     MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif // defined(DEBUG)
 
-
-
-
     BINJS_MOZ_TRY_DECL(object, parseExpression());
 
-
-
-
     BINJS_MOZ_TRY_DECL(body, parseStatement());
 
-
     BINJS_TRY_DECL(result, factory_.newWithStatement(start, object, body));
     return result;
 }
 
 
 /*
  interface YieldExpression : Node {
     Expression? expression;
@@ -7718,18 +7093,20 @@ BinASTParser<Tok>::parseInterfaceWithSta
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseYieldExpression()
 {
     BinKind kind;
     BinFields fields(cx_);
     AutoTaggedTuple guard(*tokenizer_);
 
     MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    const auto start = tokenizer_->offset();
-
+    if (kind != BinKind::YieldExpression) {
+        return raiseInvalidKind("YieldExpression", kind);
+    }
+    const auto start = tokenizer_->offset();
     BINJS_MOZ_TRY_DECL(result, parseInterfaceYieldExpression(start, kind, fields));
     MOZ_TRY(guard.done());
 
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceYieldExpression(const size_t start, const BinKind kind, const BinFields& fields)
@@ -7746,18 +7123,20 @@ BinASTParser<Tok>::parseInterfaceYieldEx
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseYieldStarExpression()
 {
     BinKind kind;
     BinFields fields(cx_);
     AutoTaggedTuple guard(*tokenizer_);
 
     MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    const auto start = tokenizer_->offset();
-
+    if (kind != BinKind::YieldStarExpression) {
+        return raiseInvalidKind("YieldStarExpression", kind);
+    }
+    const auto start = tokenizer_->offset();
     BINJS_MOZ_TRY_DECL(result, parseInterfaceYieldStarExpression(start, kind, fields));
     MOZ_TRY(guard.done());
 
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceYieldStarExpression(const size_t start, const BinKind kind, const BinFields& fields)
@@ -8224,19 +7603,21 @@ BinASTParser<Tok>::parseOptionalAsserted
     BinKind kind;
     BinFields fields(cx_);
     AutoTaggedTuple guard(*tokenizer_);
 
     MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
     Ok result;
     if (kind == BinKind::_Null) {
         result = Ok();
-    } else {
+    } else if (kind == BinKind::AssertedBlockScope) {
         const auto start = tokenizer_->offset();
         MOZ_TRY_VAR(result, parseInterfaceAssertedBlockScope(start, kind, fields));
+    } else {
+        return raiseInvalidKind("AssertedBlockScope", kind);
     }
     MOZ_TRY(guard.done());
 
     return result;
 }
 
 template<typename Tok> JS::Result<Ok>
 BinASTParser<Tok>::parseOptionalAssertedParameterScope()
@@ -8244,19 +7625,21 @@ BinASTParser<Tok>::parseOptionalAsserted
     BinKind kind;
     BinFields fields(cx_);
     AutoTaggedTuple guard(*tokenizer_);
 
     MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
     Ok result;
     if (kind == BinKind::_Null) {
         result = Ok();
-    } else {
+    } else if (kind == BinKind::AssertedParameterScope) {
         const auto start = tokenizer_->offset();
         MOZ_TRY_VAR(result, parseInterfaceAssertedParameterScope(start, kind, fields));
+    } else {
+        return raiseInvalidKind("AssertedParameterScope", kind);
     }
     MOZ_TRY(guard.done());
 
     return result;
 }
 
 template<typename Tok> JS::Result<Ok>
 BinASTParser<Tok>::parseOptionalAssertedVarScope()
@@ -8264,19 +7647,21 @@ BinASTParser<Tok>::parseOptionalAsserted
     BinKind kind;
     BinFields fields(cx_);
     AutoTaggedTuple guard(*tokenizer_);
 
     MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
     Ok result;
     if (kind == BinKind::_Null) {
         result = Ok();
-    } else {
+    } else if (kind == BinKind::AssertedVarScope) {
         const auto start = tokenizer_->offset();
         MOZ_TRY_VAR(result, parseInterfaceAssertedVarScope(start, kind, fields));
+    } else {
+        return raiseInvalidKind("AssertedVarScope", kind);
     }
     MOZ_TRY(guard.done());
 
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseOptionalAssignmentTarget()
@@ -8324,19 +7709,21 @@ BinASTParser<Tok>::parseOptionalBindingI
     BinKind kind;
     BinFields fields(cx_);
     AutoTaggedTuple guard(*tokenizer_);
 
     MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
     ParseNode* result;
     if (kind == BinKind::_Null) {
         result = nullptr;
-    } else {
+    } else if (kind == BinKind::BindingIdentifier) {
         const auto start = tokenizer_->offset();
         MOZ_TRY_VAR(result, parseInterfaceBindingIdentifier(start, kind, fields));
+    } else {
+        return raiseInvalidKind("BindingIdentifier", kind);
     }
     MOZ_TRY(guard.done());
 
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseOptionalBindingOrBindingWithInitializer()
@@ -8364,19 +7751,21 @@ BinASTParser<Tok>::parseOptionalCatchCla
     BinKind kind;
     BinFields fields(cx_);
     AutoTaggedTuple guard(*tokenizer_);
 
     MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
     ParseNode* result;
     if (kind == BinKind::_Null) {
         result = nullptr;
-    } else {
+    } else if (kind == BinKind::CatchClause) {
         const auto start = tokenizer_->offset();
         MOZ_TRY_VAR(result, parseInterfaceCatchClause(start, kind, fields));
+    } else {
+        return raiseInvalidKind("CatchClause", kind);
     }
     MOZ_TRY(guard.done());
 
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseOptionalExpression()
new file mode 100755
--- /dev/null
+++ b/js/src/frontend/binsource/build.sh
@@ -0,0 +1,8 @@
+#!/bin/sh
+
+cargo run -- \
+      ../BinSource.webidl_ \
+      ../BinSource.yaml \
+      --out-class ../BinSource-auto.h    \
+      --out-impl ../BinSource-auto.cpp   \
+      --out-token ../BinToken.h
--- a/js/src/frontend/binsource/src/main.rs
+++ b/js/src/frontend/binsource/src/main.rs
@@ -14,16 +14,32 @@ use binjs_meta::util:: { Reindentable, T
 use std::collections::{ HashMap, HashSet };
 use std::fs::*;
 use std::io::{ Read, Write };
 
 use clap::{ App, Arg };
 
 use itertools::Itertools;
 
+/// A string or string-like construction that can be appended newline.
+trait NewLineIfNotEmpty {
+    /// Append newline if the string is not empty.
+    fn newline_if_not_empty(&self) -> String;
+}
+impl<T> NewLineIfNotEmpty for T where T: ToStr {
+    fn newline_if_not_empty(&self) -> String {
+        let str = self.to_str();
+        if str.len() == 0 {
+            "".to_string()
+        } else {
+            format!("{}\n", str)
+        }
+    }
+}
+
 /// Rules for generating the code for parsing a single field
 /// of a node.
 ///
 /// Extracted from the yaml file.
 #[derive(Clone, Default)]
 struct FieldRules {
     /// Declaring the variable to hold the contents of that field.
     declare: Option<String>,
@@ -730,28 +746,28 @@ impl CPPExporter {
         ));
 
         // Generate inner method
         let mut buffer_cases = String::new();
         for node in nodes {
             buffer_cases.push_str(&format!("
       case BinKind::{variant_name}:
         MOZ_TRY_VAR(result, parseInterface{class_name}(start, kind, fields));
-{arm_after}
-        break;",
+{arm_after}        break;",
                 class_name = node.to_class_cases(),
                 variant_name = node.to_cpp_enum_case(),
                 arm_after = rules_for_this_sum.by_sum.get(&node)
                     .cloned()
-                    .unwrap_or_default().after_arm.reindent("        ")));
+                    .unwrap_or_default().after_arm.reindent("        ")
+                    .newline_if_not_empty()));
         }
         buffer.push_str(&format!("\n{first_line}
 {{
     {type_ok} result;
-    switch(kind) {{{cases}
+    switch (kind) {{{cases}
       default:
         return raiseInvalidKind(\"{kind}\", kind);
     }}
     return result;
 }}
 
 ",
             kind = kind,
@@ -883,31 +899,34 @@ impl CPPExporter {
     BinKind kind;
     BinFields fields(cx_);
     AutoTaggedTuple guard(*tokenizer_);
 
     MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
     {type_ok} result;
     if (kind == BinKind::{null}) {{
         result = {default_value};
-    }} else {{
+    }} else if (kind == BinKind::{kind}) {{
         const auto start = tokenizer_->offset();
         MOZ_TRY_VAR(result, parseInterface{contents}(start, kind, fields));
+    }} else {{
+        return raiseInvalidKind(\"{kind}\", kind);
     }}
     MOZ_TRY(guard.done());
 
     return result;
 }}
 
 ",
                     first_line = self.get_method_definition_start(&parser.name, "ParseNode*", "", ""),
                     null = self.syntax.get_null_name().to_cpp_enum_case(),
                     contents = parser.elements.to_class_cases(),
                     type_ok = type_ok,
                     default_value = default_value,
+                    kind = parser.elements.to_cpp_enum_case(),
                 ));
             }
             NamedType::Typedef(ref type_) => {
                 match type_.spec() {
                     &TypeSpec::TypeSum(_) => {
                 buffer.push_str(&format!("{first_line}
 {{
     BinKind kind;
@@ -983,35 +1002,37 @@ impl CPPExporter {
             }
         }
 
         // Generate comments
         let comment = format!("\n/*\n{}*/\n", ToWebidl::interface(interface, "", "    "));
         buffer.push_str(&comment);
 
         // Generate public method
-        let kind = name.to_class_cases();
         buffer.push_str(&format!("{first_line}
 {{
     BinKind kind;
     BinFields fields(cx_);
     AutoTaggedTuple guard(*tokenizer_);
 
     MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+    if (kind != BinKind::{kind}) {{
+        return raiseInvalidKind(\"{kind}\", kind);
+    }}
     const auto start = tokenizer_->offset();
-
-    BINJS_MOZ_TRY_DECL(result, parseInterface{kind}(start, kind, fields));
+    BINJS_MOZ_TRY_DECL(result, parseInterface{class_name}(start, kind, fields));
     MOZ_TRY(guard.done());
 
     return result;
 }}
 
 ",
             first_line = self.get_method_definition_start(name, "ParseNode*", "", ""),
-            kind = kind
+            kind = name.to_cpp_enum_case(),
+            class_name = name.to_class_cases(),
         ));
 
         // Generate aux method
         let number_of_fields = interface.contents().fields().len();
         let first_line = self.get_method_definition_start(name, "ParseNode*", "Interface", "const size_t start, const BinKind kind, const BinFields& fields");
 
         let fields_type_list = format!("{{ {} }}", interface.contents()
             .fields()
@@ -1110,92 +1131,81 @@ impl CPPExporter {
                     let after_field = rules_for_this_field.after_field.reindent("    ");
                     let decl_var = if rules_for_this_field.declare.is_some() {
                         rules_for_this_field.declare.reindent("    ")
                     } else {
                         decl_var.reindent("    ")
                     };
                     if needs_block {
                         let parse_var = parse_var.reindent("        ");
-                        format!("{before_field}
-{decl_var}
-    {{
-{block_before_field}
-{parse_var}
-{block_after_field}
+                        format!("{before_field}{decl_var}    {{
+{block_before_field}{parse_var}{block_after_field}
     }}
 {after_field}",
-                            before_field = before_field.reindent("    "),
-                            decl_var = decl_var.reindent("    "),
-                            parse_var = parse_var.reindent("        "),
-                            after_field = after_field.reindent("    "),
-                            block_before_field = rules_for_this_field.block_before_field.reindent("        "),
-                            block_after_field = rules_for_this_field.block_after_field.reindent("        "))
+                            before_field = before_field.reindent("    ").newline_if_not_empty(),
+                            decl_var = decl_var.reindent("    ").newline_if_not_empty(),
+                            block_before_field = rules_for_this_field.block_before_field.reindent("        ").newline_if_not_empty(),
+                            parse_var = parse_var.reindent("        ").newline_if_not_empty(),
+                            block_after_field = rules_for_this_field.block_after_field.reindent("        "),
+                            after_field = after_field.reindent("    "))
                     } else {
                         // We have a before_field and an after_field. This will create newlines
                         // for them.
                         format!("
-{before_field}
-{decl_var}
-{parse_var}
-{after_field}
-",
-                            before_field = before_field.reindent("    "),
-                            decl_var = decl_var.reindent("    "),
-                            parse_var = parse_var.reindent("    "),
+{before_field}{decl_var}{parse_var}{after_field}",
+                            before_field = before_field.reindent("    ").newline_if_not_empty(),
+                            decl_var = decl_var.reindent("    ").newline_if_not_empty(),
+                            parse_var = parse_var.reindent("    ").newline_if_not_empty(),
                             after_field = after_field.reindent("    "))
                     }
                 }
             };
             fields_implem.push_str(&rendered);
         }
 
         let init = rules_for_this_interface.init.reindent("    ");
         let build_result = rules_for_this_interface.build_result.reindent("    ");
 
         if build_result == "" {
             buffer.push_str(&format!("{first_line}
 {{
-    return raiseError(\"FIXME: Not implemented yet ({})\");
+    return raiseError(\"FIXME: Not implemented yet ({class_name})\");
 }}
 
 ",
-                kind = kind.to_str(),
+                class_name = name.to_class_cases(),
                 first_line = first_line,
             ));
         } else {
             let check_fields = if number_of_fields == 0 {
                 format!("MOZ_TRY(tokenizer_->checkFields0(kind, fields));")
             } else {
                 // The following strategy is designed for old versions of clang.
                 format!("
 #if defined(DEBUG)
     const BinField expected_fields[{number_of_fields}] = {fields_type_list};
     MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
-#endif // defined(DEBUG)
-",
+#endif // defined(DEBUG)",
                     fields_type_list = fields_type_list,
                     number_of_fields = number_of_fields)
             };
             buffer.push_str(&format!("{first_line}
 {{
     MOZ_ASSERT(kind == BinKind::{kind});
     BINJS_TRY(CheckRecursionLimit(cx_));
-
 {check_fields}
 {pre}{fields_implem}
-{post}
-    return result;
+{post}    return result;
 }}
 
 ",
                 check_fields = check_fields,
                 fields_implem = fields_implem,
-                pre = init,
-                post = build_result,
+                pre = init.newline_if_not_empty(),
+                post = build_result.newline_if_not_empty(),
                 kind = name.to_cpp_enum_case(),
                 first_line = first_line,
             ));
         }
     }
 
     /// Generate C++ code for SpiderMonkey
     fn to_spidermonkey_cpp(&self) -> String {
--- a/js/xpconnect/loader/AutoMemMap.cpp
+++ b/js/xpconnect/loader/AutoMemMap.cpp
@@ -14,29 +14,21 @@
 
 namespace mozilla {
 namespace loader {
 
 using namespace mozilla::ipc;
 
 AutoMemMap::~AutoMemMap()
 {
-    if (fileMap) {
-        if (addr) {
-            Unused << NS_WARN_IF(PR_MemUnmap(addr, size()) != PR_SUCCESS);
-            addr = nullptr;
-        }
-
-        Unused << NS_WARN_IF(PR_CloseFileMap(fileMap) != PR_SUCCESS);
-        fileMap = nullptr;
-    }
+    reset();
 }
 
 FileDescriptor
-AutoMemMap::cloneFileDescriptor()
+AutoMemMap::cloneFileDescriptor() const
 {
     if (fd.get()) {
         auto handle = FileDescriptor::PlatformHandleType(PR_FileDesc2NativeHandle(fd.get()));
         return FileDescriptor(handle);
     }
     return FileDescriptor();
 }
 
@@ -46,52 +38,127 @@ AutoMemMap::init(nsIFile* file, int flag
     MOZ_ASSERT(!fd);
 
     MOZ_TRY(file->OpenNSPRFileDesc(flags, mode, &fd.rwget()));
 
     return initInternal(prot);
 }
 
 Result<Ok, nsresult>
-AutoMemMap::init(const FileDescriptor& file)
+AutoMemMap::init(const FileDescriptor& file, PRFileMapProtect prot,
+                 size_t expectedSize)
 {
     MOZ_ASSERT(!fd);
     if (!file.IsValid()) {
         return Err(NS_ERROR_INVALID_ARG);
     }
 
     auto handle = file.ClonePlatformHandle();
 
     fd = PR_ImportFile(PROsfd(handle.get()));
     if (!fd) {
         return Err(NS_ERROR_FAILURE);
     }
     Unused << handle.release();
 
-    return initInternal();
+    return initInternal(prot, expectedSize);
 }
 
 Result<Ok, nsresult>
-AutoMemMap::initInternal(PRFileMapProtect prot)
+AutoMemMap::initInternal(PRFileMapProtect prot, size_t expectedSize)
 {
     MOZ_ASSERT(!fileMap);
     MOZ_ASSERT(!addr);
 
     PRFileInfo64 fileInfo;
     MOZ_TRY(PR_GetOpenFileInfo64(fd.get(), &fileInfo));
 
     if (fileInfo.size > UINT32_MAX)
         return Err(NS_ERROR_INVALID_ARG);
 
     fileMap = PR_CreateFileMap(fd, 0, prot);
     if (!fileMap)
         return Err(NS_ERROR_FAILURE);
 
     size_ = fileInfo.size;
+    // The memory region size passed in certain IPC messages isn't necessary on
+    // Unix-like systems, since we can always stat the file descriptor to
+    // determine it accurately. But since we have it, anyway, sanity check that
+    // it matches the size returned by the stat.
+    MOZ_ASSERT_IF(expectedSize > 0, size_ == expectedSize);
+
     addr = PR_MemMap(fileMap, 0, size_);
     if (!addr)
         return Err(NS_ERROR_FAILURE);
 
     return Ok();
 }
 
+#ifdef XP_WIN
+
+Result<Ok, nsresult>
+AutoMemMap::initWithHandle(const FileDescriptor& file, size_t size, PRFileMapProtect prot)
+{
+    MOZ_ASSERT(!fd);
+    MOZ_ASSERT(!handle_);
+    if (!file.IsValid()) {
+        return Err(NS_ERROR_INVALID_ARG);
+    }
+
+    handle_ = file.ClonePlatformHandle().release();
+
+    MOZ_ASSERT(!addr);
+
+    size_ = size;
+
+    addr = MapViewOfFile(
+          handle_,
+          prot == PR_PROT_READONLY ? FILE_MAP_READ : FILE_MAP_ALL_ACCESS,
+          0, 0, size);
+
+    return Ok();
+}
+
+FileDescriptor
+AutoMemMap::cloneHandle() const
+{
+    return FileDescriptor(handle_);
+}
+
+#else
+
+Result<Ok, nsresult>
+AutoMemMap::initWithHandle(const FileDescriptor& file, size_t size, PRFileMapProtect prot)
+{
+    return init(file, prot);
+}
+
+FileDescriptor
+AutoMemMap::cloneHandle() const
+{
+    return cloneFileDescriptor();
+}
+
+#endif
+
+void
+AutoMemMap::reset()
+{
+    if (fileMap) {
+        if (addr && !persistent_) {
+            Unused << NS_WARN_IF(PR_MemUnmap(addr, size()) != PR_SUCCESS);
+            addr = nullptr;
+        }
+
+        Unused << NS_WARN_IF(PR_CloseFileMap(fileMap) != PR_SUCCESS);
+        fileMap = nullptr;
+    }
+#ifdef XP_WIN
+    if (handle_) {
+      CloseHandle(handle_);
+      handle_ = nullptr;
+    }
+#endif
+    fd.dispose();
+}
+
 } // namespace loader
 } // namespace mozilla
--- a/js/xpconnect/loader/AutoMemMap.h
+++ b/js/xpconnect/loader/AutoMemMap.h
@@ -29,49 +29,76 @@ class AutoMemMap
 
         ~AutoMemMap();
 
         Result<Ok, nsresult>
         init(nsIFile* file, int flags = PR_RDONLY, int mode = 0,
              PRFileMapProtect prot = PR_PROT_READONLY);
 
         Result<Ok, nsresult>
-        init(const ipc::FileDescriptor& file);
+        init(const ipc::FileDescriptor& file,
+             PRFileMapProtect prot = PR_PROT_READONLY,
+             size_t expectedSize = 0);
+
+        // Initializes the mapped memory with a shared memory handle. On
+        // Unix-like systems, this is identical to the above init() method. On
+        // Windows, the FileDescriptor must be a handle for a file mapping,
+        // rather than a file descriptor.
+        Result<Ok, nsresult>
+        initWithHandle(const ipc::FileDescriptor& file, size_t size,
+                       PRFileMapProtect prot = PR_PROT_READONLY);
+
+        void reset();
 
         bool initialized() { return addr; }
 
-        uint32_t size() const { MOZ_ASSERT(fd); return size_; }
+        uint32_t size() const { return size_; }
 
         template<typename T = void>
-        const RangedPtr<T> get()
+        RangedPtr<T> get()
         {
             MOZ_ASSERT(addr);
             return { static_cast<T*>(addr), size_ };
         }
 
         template<typename T = void>
         const RangedPtr<T> get() const
         {
             MOZ_ASSERT(addr);
             return { static_cast<T*>(addr), size_ };
         }
 
         size_t nonHeapSizeOfExcludingThis() { return size_; }
 
-        FileDescriptor cloneFileDescriptor();
+        FileDescriptor cloneFileDescriptor() const;
+        FileDescriptor cloneHandle() const;
+
+        // Makes this mapping persistent. After calling this, the mapped memory
+        // will remained mapped, even after this instance is destroyed.
+        void setPersistent() { persistent_ = true; }
 
     private:
-        Result<Ok, nsresult> initInternal(PRFileMapProtect prot = PR_PROT_READONLY);
+        Result<Ok, nsresult> initInternal(PRFileMapProtect prot = PR_PROT_READONLY,
+                                          size_t expectedSize = 0);
 
         AutoFDClose fd;
         PRFileMap* fileMap = nullptr;
 
+#ifdef XP_WIN
+        // We can't include windows.h in this header, since it gets included
+        // by some binding headers (which are explicitly incompatible with
+        // windows.h). So we can't use the HANDLE type here.
+        void* handle_ = nullptr;
+#endif
+
         uint32_t size_ = 0;
         void* addr = nullptr;
 
+        bool persistent_ = 0;
+
         AutoMemMap(const AutoMemMap&) = delete;
         void operator=(const AutoMemMap&) = delete;
 };
 
 } // namespace loader
 } // namespace mozilla
 
 #endif // loader_AutoMemMap_h
--- a/js/xpconnect/loader/moz.build
+++ b/js/xpconnect/loader/moz.build
@@ -20,16 +20,17 @@ SOURCES += [
     'mozJSComponentLoader.cpp'
 ]
 
 IPDL_SOURCES += [
     'PScriptCache.ipdl',
 ]
 
 EXPORTS.mozilla += [
+    'AutoMemMap.h',
     'ScriptPreloader.h',
     'URLPreloader.h',
 ]
 
 EXPORTS.mozilla.dom += [
     'PrecompiledScript.h',
 ]
 
new file mode 100644
--- /dev/null
+++ b/layout/generic/crashtests/1233607.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<html style="width: 1px;">
+<head>
+<meta charset="UTF-8">
+</head>
+<body onload="x.style.color='red';">
+<div id="x" style="overflow: scroll;"><input type="image" style="display: contents;"></div>
+</body>
+</html>
--- a/layout/generic/crashtests/crashtests.list
+++ b/layout/generic/crashtests/crashtests.list
@@ -636,16 +636,17 @@ load text-overflow-bug666751-1.html
 load text-overflow-bug666751-2.html
 load text-overflow-bug670564.xhtml
 load text-overflow-bug671796.xhtml
 load text-overflow-bug713610.html
 load text-overflow-form-elements.html
 load text-overflow-iframe.html
 asserts(1-4) load 1225005.html # bug 682647 and bug 448083
 load 1233191.html
+load 1233607.html
 load 1234701-1.html
 load 1234701-2.html
 load 1271765.html
 asserts(2) asserts-if(Android,1) load 1272983-1.html # bug 586628
 asserts(2) asserts-if(Android,1) load 1272983-2.html # bug 586628
 load 1275059.html
 load 1278007.html
 load 1278080.html
--- a/mfbt/RangedPtr.h
+++ b/mfbt/RangedPtr.h
@@ -118,16 +118,29 @@ public:
   explicit operator bool() const { return mPtr != nullptr; }
 
   void checkIdenticalRange(const RangedPtr<T>& aOther) const
   {
     MOZ_ASSERT(mRangeStart == aOther.mRangeStart);
     MOZ_ASSERT(mRangeEnd == aOther.mRangeEnd);
   }
 
+  template <typename U>
+  RangedPtr<U>
+  ReinterpretCast() const
+  {
+#ifdef DEBUG
+    return { reinterpret_cast<U*>(mPtr),
+             reinterpret_cast<U*>(mRangeStart),
+             reinterpret_cast<U*>(mRangeEnd) };
+#else
+    return { reinterpret_cast<U*>(mPtr), nullptr, nullptr };
+#endif
+  }
+
   /*
    * You can only assign one RangedPtr into another if the two pointers have
    * the same valid range:
    *
    *   char arr1[] = "hi";
    *   char arr2[] = "bye";
    *   RangedPtr<char> p1(arr1, 2);
    *   p1 = RangedPtr<char>(arr1 + 1, arr1, arr1 + 2); // works
--- a/servo/components/malloc_size_of/lib.rs
+++ b/servo/components/malloc_size_of/lib.rs
@@ -802,18 +802,16 @@ malloc_size_of_is_0!(webrender_api::Imag
 malloc_size_of_is_0!(webrender_api::LineStyle);
 #[cfg(feature = "webrender_api")]
 malloc_size_of_is_0!(webrender_api::MixBlendMode);
 #[cfg(feature = "webrender_api")]
 malloc_size_of_is_0!(webrender_api::NormalBorder);
 #[cfg(feature = "webrender_api")]
 malloc_size_of_is_0!(webrender_api::RepeatMode);
 #[cfg(feature = "webrender_api")]
-malloc_size_of_is_0!(webrender_api::ScrollPolicy);
-#[cfg(feature = "webrender_api")]
 malloc_size_of_is_0!(webrender_api::ScrollSensitivity);
 #[cfg(feature = "webrender_api")]
 malloc_size_of_is_0!(webrender_api::StickyOffsetBounds);
 #[cfg(feature = "webrender_api")]
 malloc_size_of_is_0!(webrender_api::TransformStyle);
 
 #[cfg(feature = "servo")]
 impl MallocSizeOf for xml5ever::QualName {
--- a/servo/components/style/Cargo.toml
+++ b/servo/components/style/Cargo.toml
@@ -73,12 +73,12 @@ unicode-segmentation = "1.0"
 void = "1.0.2"
 
 [target.'cfg(windows)'.dependencies]
 kernel32-sys = "0.2"
 
 [build-dependencies]
 lazy_static = "1"
 log = "0.4"
-bindgen = { version = "0.33.2", optional = true, default-features = false }
+bindgen = { version = "0.37", optional = true, default-features = false }
 regex = {version = "0.2", optional = true}
 walkdir = "2.1.4"
 toml = {version = "0.4.5", optional = true, default-features = false}
--- a/servo/components/style/element_state.rs
+++ b/servo/components/style/element_state.rs
@@ -66,17 +66,17 @@ bitflags! {
         /// Non-standard: https://developer.mozilla.org/en-US/docs/Web/CSS/:-moz-handler-crashed
         const IN_HANDLER_CRASHED_STATE = 1 << 20;
         /// <https://html.spec.whatwg.org/multipage/#selector-required>
         const IN_REQUIRED_STATE = 1 << 21;
         /// <https://html.spec.whatwg.org/multipage/#selector-optional>
         const IN_OPTIONAL_STATE = 1 << 22;
         /// <https://html.spec.whatwg.org/multipage/#selector-read-write>
         const IN_READ_WRITE_STATE = 1 << 22;
-        /// <https://html.spec.whatwg.org/multipage/semantics-other.html#selector-defined>
+        /// <https://html.spec.whatwg.org/multipage/#selector-defined>
         const IN_DEFINED_STATE = 1 << 23;
         /// <https://html.spec.whatwg.org/multipage/#selector-visited>
         const IN_VISITED_STATE = 1 << 24;
         /// <https://html.spec.whatwg.org/multipage/#selector-link>
         const IN_UNVISITED_STATE = 1 << 25;
         /// <https://drafts.csswg.org/selectors-4/#the-any-link-pseudo>
         const IN_VISITED_OR_UNVISITED_STATE = ElementState::IN_VISITED_STATE.bits |
                                               ElementState::IN_UNVISITED_STATE.bits;
--- a/servo/components/style/media_queries/media_condition.rs
+++ b/servo/components/style/media_queries/media_condition.rs
@@ -1,35 +1,34 @@
 /* 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/. */
 
 //! A media query condition:
 //!
 //! https://drafts.csswg.org/mediaqueries-4/#typedef-media-condition
 
+use context::QuirksMode;
 use cssparser::{Parser, Token};
-use context::QuirksMode;
 use parser::ParserContext;
 use std::fmt::{self, Write};
 use style_traits::{CssWriter, ParseError, StyleParseErrorKind, ToCss};
-
 use super::{Device, MediaFeatureExpression};
 
 
 /// A binary `and` or `or` operator.
-#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, Parse, ToCss)]
+#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq, ToCss)]
 #[allow(missing_docs)]
 pub enum Operator {
     And,
     Or,
 }
 
 /// Whether to allow an `or` condition or not during parsing.
-#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, Parse, ToCss)]
+#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, ToCss)]
 enum AllowOr {
     Yes,
     No,
 }
 
 /// Represents a media condition.
 #[derive(Clone, Debug, MallocSizeOf, PartialEq)]
 pub enum MediaCondition {
--- a/servo/components/style/servo/media_queries.rs
+++ b/servo/components/style/servo/media_queries.rs
@@ -211,17 +211,17 @@ impl MediaFeatureExpression {
                 ExpressionKind::Width(Range::Min(specified::Length::parse_non_negative(context, input)?))
             },
             "max-width" => {
                 ExpressionKind::Width(Range::Max(specified::Length::parse_non_negative(context, input)?))
             },
             "width" => {
                 ExpressionKind::Width(Range::Eq(specified::Length::parse_non_negative(context, input)?))
             },
-            _ => return Err(input.new_custom_error(SelectorParseErrorKind::UnexpectedIdent(name)))
+            _ => return Err(input.new_custom_error(SelectorParseErrorKind::UnexpectedIdent(name.clone())))
         }))
     }
 
     /// Evaluate this expression and return whether it matches the current
     /// device.
     pub fn matches(&self, device: &Device, quirks_mode: QuirksMode) -> bool {
         let viewport_size = device.au_viewport_size();
         let value = viewport_size.width;
--- a/servo/tests/unit/style/lib.rs
+++ b/servo/tests/unit/style/lib.rs
@@ -22,19 +22,17 @@ extern crate servo_url;
 extern crate style_traits;
 extern crate test;
 
 mod animated_properties;
 mod attr;
 mod custom_properties;
 mod keyframes;
 mod logical_geometry;
-mod media_queries;
 mod parsing;
 mod properties;
 mod rule_tree;
 mod size_of;
-#[path = "../../../ports/geckolib/tests/specified_values.rs"]
 mod specified_values;
 mod str;
 mod stylesheets;
 mod stylist;
 mod viewport;
--- a/servo/tests/unit/style/properties/serialization.rs
+++ b/servo/tests/unit/style/properties/serialization.rs
@@ -2,17 +2,17 @@
  * 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/. */
 
 use properties::{parse, parse_input};
 use style::computed_values::display::T as Display;
 use style::properties::{PropertyDeclaration, Importance};
 use style::properties::declaration_block::PropertyDeclarationBlock;
 use style::properties::parse_property_declaration_list;
-use style::values::{CustomIdent, RGBA};
+use style::values::RGBA;
 use style::values::specified::{BorderStyle, BorderSideWidth, Color};
 use style::values::specified::{Length, LengthOrPercentage, LengthOrPercentageOrAuto};
 use style::values::specified::NoCalcLength;
 use style::values::specified::url::SpecifiedUrl;
 use style_traits::ToCss;
 use stylesheets::block_from;
 
 trait ToCssString {
@@ -70,49 +70,16 @@ mod shorthand_serialization {
     pub use super::*;
 
     pub fn shorthand_properties_to_string(properties: Vec<PropertyDeclaration>) -> String {
         let block = block_from(properties.into_iter().map(|d| (d, Importance::Normal)));
 
         block.to_css_string()
     }
 
-    // Add Test to show error if a longhand property is missing!!!!!!
-
-    mod overflow {
-        pub use super::*;
-        use style::properties::longhands::overflow_x::SpecifiedValue as OverflowValue;
-
-        #[test]
-        fn equal_overflow_properties_should_serialize_to_single_value() {
-            let mut properties = Vec::new();
-
-            let overflow = OverflowValue::Auto;
-            properties.push(PropertyDeclaration::OverflowX(overflow));
-            properties.push(PropertyDeclaration::OverflowY(overflow));
-
-            let serialization = shorthand_properties_to_string(properties);
-            assert_eq!(serialization, "overflow: auto;");
-        }
-
-        #[test]
-        fn different_overflow_properties_should_serialize_to_two_values() {
-            let mut properties = Vec::new();
-
-            let overflow_x = OverflowValue::Scroll;
-            properties.push(PropertyDeclaration::OverflowX(overflow_x));
-
-            let overflow_y = OverflowValue::Auto;
-            properties.push(PropertyDeclaration::OverflowY(overflow_y));
-
-            let serialization = shorthand_properties_to_string(properties);
-            assert_eq!(serialization, "overflow-x: scroll; overflow-y: auto;");
-        }
-    }
-
     mod four_sides_shorthands {
         pub use super::*;
 
         // we can use margin as a base to test out the different combinations
         // but afterwards, we only need to to one test per "four sides shorthand"
         #[test]
         fn all_equal_properties_should_serialize_to_one_value() {
             let mut properties = Vec::new();
--- a/third_party/rust/bindgen/.cargo-checksum.json
+++ b/third_party/rust/bindgen/.cargo-checksum.json
@@ -1,1 +1,1 @@
-{"files":{"Cargo.toml":"d2d15d8518f87e50143184b13e14139095b0a6aa627d4d5d3a2d12893e765f50","build.rs":"032a1c51963894a421b0535f9227796d88768ac5f665a81d2edced69dc6d106a","src/callbacks.rs":"49f382ebdb94c8f0aba5496f5283ae3cdcf6666a5c41c604e6356e674f9a072b","src/clang.rs":"33d94fa699f052b52a2804b85f49fa5de3a2404ae05801ef9eae16016bc841f1","src/codegen/bitfield_unit.rs":"bd1a19701f1766d0bae3bcb97d7c3cb3881d4b182c56b8f4dfd24b7cc87b5338","src/codegen/bitfield_unit_tests.rs":"2073ac6a36e0bc9afaef5b1207966817c8fb7a1a9f6368c3b1b8f79822efbfba","src/codegen/error.rs":"2613af1d833377fd4a70719f4a09951d9d45dc9227827b9a2a938a1bcaaea2dd","src/codegen/helpers.rs":"bcb951f320fd0948e341d8eabdb58567296d77bf1ae5040c05d967e6435a15d5","src/codegen/impl_debug.rs":"e2ffd5b6ed936698aa4b9e7e3459d353383792707ad51f829a18a822f69cab0e","src/codegen/impl_partialeq.rs":"e86050b98f57fa4496dbde0beea319a89e46290309d274f626361779549b95bd","src/codegen/mod.rs":"74e818d857fb5147f623e9287632d23c4bd0cf87de840034809992b74ff88bdc","src/codegen/struct_layout.rs":"698ed7340242d1cbedd38d400c7c83c32e2fa043c35dbc9a2eea4022251ffdb0","src/extra_assertions.rs":"449549c4a7a50c3f0b06332452b2fb6c9b23f31ca8e5e1656fe6c7f21e8ef7fa","src/features.rs":"8c2148a6f922ca9cb0de2dd3ad77c4dd5734c4c219a5bea9d6b22c4367acb187","src/ir/analysis/derive_copy.rs":"14b53c53b337be00d59424371c07c6712d7cfc9a6735f9d913cda043fddce797","src/ir/analysis/derive_debug.rs":"1d6621c0fa5d899310cc175cb99703606ed34fd7f7ad77bb60f012f25ba504af","src/ir/analysis/derive_default.rs":"4fac04fc3019562cd213586680ecdcf8a3b3544ca3a5c5117f68e5c26e7ee0d9","src/ir/analysis/derive_hash.rs":"a50e849b4388115264c2d6afef5ab07e309d2469f4c3342fb683c799451e9e19","src/ir/analysis/derive_partialeq_or_partialord.rs":"46611c7f3caa0fe78243187742c4a36003dbc266de4c4390642e136bb889c43f","src/ir/analysis/has_destructor.rs":"d9aaaceba580b48eb0df4e5537b34b417c51ccdfeb8f6b72484f3bf4992317fe","src/ir/analysis/has_float.rs":"2a0465503d2c8247eaf916bd6a03594f3dc0370533d9a7c58cc5afb86693816c","src/ir/analysis/has_type_param_in_array.rs":"fcb1c78b6000f1f5eb8d8147e2afdaba9eb0e3a81b61e72537048dfdbeea7bcd","src/ir/analysis/has_vtable.rs":"37765e954ef792e369a58ccfe1d827a00fe9bce680466da1d6523671b94b6c92","src/ir/analysis/mod.rs":"ea5ace45c77e855674bb565ba0fef556f60e3293b0ddcf11d3a5a6ec15ab0648","src/ir/analysis/sizedness.rs":"3d3c8bde40604d53bb64273a3cbd8c55936a7dfe1de9b2ba92fc2c45572624b4","src/ir/analysis/template_params.rs":"5c6ee7a251a321ef5733e2e7ac3264621b4181268babcc008b69dbfc37691fb1","src/ir/annotations.rs":"ef106afcbe6084c18bd13a37ee3c1cdc9596bfb055db8c773d81f8f15fec3208","src/ir/comment.rs":"36f2a1d3970fdbf3d72c1f094043902747cde395215bdf7e9103926d9df011fd","src/ir/comp.rs":"b24e6ab76235b46bb5a262e3a3f2fc685c26bd7482aea113231a942eeffd0cf5","src/ir/context.rs":"ccd99c814f1a8ba1f3a30667a8d90db13a50adc26620be08f907283d1c5f08a3","src/ir/derive.rs":"1fd6ad621e3c60b950acbd51fbe386d1f0fadb7c1889c723245afff45e42e143","src/ir/dot.rs":"d01f1621ab67e368d854a82bd6bb0b8dd52f3c2c733de8eaf81aece9543818cb","src/ir/enum_ty.rs":"98a4aa58e598b31e4dc2c052c90029f37b53b5c5cfcbd216d4b0e8c73454813f","src/ir/function.rs":"cce97e7cd6ffb7d5ae40e6be1b82e7ae899d9ea9cf7c8f97380486ac7cc120e6","src/ir/int.rs":"1f61a472288afe489d9320bc8b13920333ece57891ae8570b4c4f25ab50688e6","src/ir/item.rs":"03477f4f4abfebc92ce4c9a202e33c86615dfffe3e6d1e0a201d2e85eecb9917","src/ir/item_kind.rs":"dbeae8c4fd0e5c9485d325aea040e056a1f2cd6d43fc927dee8fe1c0c59a7197","src/ir/layout.rs":"e3d1adf1ad2fa5bd96530cdd5097db3d9cc7b44d33ec23a04fcfccecd9cf4469","src/ir/mod.rs":"2eae90f207fad2e45957ec9287064992a419e3fc916aba84faff2ea25cbeb5ee","src/ir/module.rs":"c4d90bf38fe3672e01923734ccbdb7951ea929949d5f413a9c2aee12395a5094","src/ir/objc.rs":"05068c4fbf42429c4ac2a233c874f18ffcf7dc1744398e400a5a48d0e7a972f2","src/ir/template.rs":"bcd750450a4df0200a6e7958f9c96a09b91e3ccd29c60712f2b9d3458f1234aa","src/ir/traversal.rs":"da73d3fafa594fb12c13136f5c9d6e6ee0d6c7fa4b6e57863638d4ba5ef55dfa","src/ir/ty.rs":"7d16711a053f1b4e9d11d3c5665062a58278a869b196a24b7b2a62227eb3a38f","src/ir/var.rs":"57c8aa9f834c6f06418f7d471b1771bbb915821ef0d194b383be60092edca5f7","src/lib.rs":"99ed57a26e794ce724e434af0bf4f72b199bd0e1c42833324beb939acda9af33","src/log_stubs.rs":"6dfdd908b7c6453da416cf232893768f9480e551ca4add0858ef88bf71ee6ceb","src/main.rs":"e519053bcdde6bc88f60f955246a02d53b3db1cc5ccd1612e6675b790b7460b0","src/options.rs":"3df0214f428c221604420f8eb511b1c1e6d9326d1c6d3d2dea48278f833f9b77","src/parse.rs":"be7d13cc84fae79ec7b3aa9e77063fa475a48d74a854423e2c72d75006a25202","src/regex_set.rs":"a55241f2117f15729d174790f386e255fcb224b692325bbe6716dbb1d6874881","src/time.rs":"a02befb48d10dcc31e3f9571b2fa1c40f97fafe6f6ae7d7fc4f8fd01f1a169ba"},"package":"603ed8d8392ace9581e834e26bd09799bf1e989a79bd1aedbb893e72962bdc6e"}
\ No newline at end of file
+{"files":{"Cargo.toml":"3080fa2631c58e35cb1b32642139d8c303a609f8b554bfe69cd659a5374f18b9","LICENSE":"1d2e4bdb9d94ab020e9550136cae9ec73fc699c3c96a9d98078c542e9b93d294","README.md":"630d1a1d123c131bad0fec23173e263ba8ecc064b5cd8446d4cab7ffd197db45","build.rs":"032a1c51963894a421b0535f9227796d88768ac5f665a81d2edced69dc6d106a","src/callbacks.rs":"9d41b7848cea37e8741fa7bc947ba58a83647824b1a0bbe7ff75012c412eab13","src/clang.rs":"5ce27d0772e66f9f2f94a55afd18c98d4a57aed4c1d57da53b025fbbbb81a287","src/codegen/bitfield_unit.rs":"88b0604322dc449fc9284850eadc1f5d14b42fa747d4258bae0b6b9535f52dfd","src/codegen/bitfield_unit_tests.rs":"2073ac6a36e0bc9afaef5b1207966817c8fb7a1a9f6368c3b1b8f79822efbfba","src/codegen/error.rs":"2613af1d833377fd4a70719f4a09951d9d45dc9227827b9a2a938a1bcaaea2dd","src/codegen/helpers.rs":"8badd4b5ba38b83477c3ee3fc6f9ca79059b5650f5b489b2723c335037e27d92","src/codegen/impl_debug.rs":"e2ffd5b6ed936698aa4b9e7e3459d353383792707ad51f829a18a822f69cab0e","src/codegen/impl_partialeq.rs":"d69e2a9cdf2fdea74a60532109c0a1a75791f5a5ef931b28c5d447fa2915e5d3","src/codegen/mod.rs":"c923594d8d27dede9192dd1081acdedf97d67430f780e3dc4db39b8928a55d71","src/codegen/struct_layout.rs":"9bd0e3455e55e2a1faa4f332a327c2529a21bdfdd0fcb3a45bc5cdd7801d288f","src/extra_assertions.rs":"449549c4a7a50c3f0b06332452b2fb6c9b23f31ca8e5e1656fe6c7f21e8ef7fa","src/features.rs":"a437e6f736c8fba81ff74d90e7ddd142192ae5ffb9240d8c885eb84be6f2fe45","src/ir/analysis/derive_copy.rs":"59c21e299af3a36c6c82d4d16454700238269abd5929ec2d67c8414aebf82c3b","src/ir/analysis/derive_debug.rs":"3530e27ab0e260ec013cee3ad78a81497970c656a8eed589b755cce8caf53040","src/ir/analysis/derive_default.rs":"20e9dac151fadc59a7926ed9276ee8ced47e59c3f0c43f69fdafb75706045aca","src/ir/analysis/derive_hash.rs":"85c73c5660dc311ab6c15a21b69c4c5d2aa380d740decaf59ad594a6728cbe1f","src/ir/analysis/derive_partialeq_or_partialord.rs":"fb9540c324fdfcc9b0ae816e7713af000b11f5e2768c512c22a3082f263bb6bc","src/ir/analysis/has_destructor.rs":"d9aaaceba580b48eb0df4e5537b34b417c51ccdfeb8f6b72484f3bf4992317fe","src/ir/analysis/has_float.rs":"2a0465503d2c8247eaf916bd6a03594f3dc0370533d9a7c58cc5afb86693816c","src/ir/analysis/has_type_param_in_array.rs":"fcb1c78b6000f1f5eb8d8147e2afdaba9eb0e3a81b61e72537048dfdbeea7bcd","src/ir/analysis/has_vtable.rs":"37765e954ef792e369a58ccfe1d827a00fe9bce680466da1d6523671b94b6c92","src/ir/analysis/mod.rs":"ea5ace45c77e855674bb565ba0fef556f60e3293b0ddcf11d3a5a6ec15ab0648","src/ir/analysis/sizedness.rs":"3d3c8bde40604d53bb64273a3cbd8c55936a7dfe1de9b2ba92fc2c45572624b4","src/ir/analysis/template_params.rs":"6554dd1240142ec0e7299e678b696725f5cba99243d1c3d1cbf58d4764082fd6","src/ir/annotations.rs":"ef106afcbe6084c18bd13a37ee3c1cdc9596bfb055db8c773d81f8f15fec3208","src/ir/comment.rs":"000481754e5433d7c0886b9ce8b93b64c7ab1ae52867d211c73c7c4b336649a2","src/ir/comp.rs":"7b22f3ff19ca45a6fbfe7ea015109d43f4ddf65b33b47b1c37829fcb87cdff9b","src/ir/context.rs":"80679859b4efa52d74b0c7501bb5951b58c9705a97b96c9fc05134d1abe401c6","src/ir/derive.rs":"9550d01731ca66be28124c91fd0211a618743a065bec7b00e27c934afff82a84","src/ir/dot.rs":"d01f1621ab67e368d854a82bd6bb0b8dd52f3c2c733de8eaf81aece9543818cb","src/ir/enum_ty.rs":"3611100df8ddf01b010d2eae1d26a67df022e47b6236b0ed9d1b9b42340ebafd","src/ir/function.rs":"b86e665c6659c32bce39194240e7da6221c5a2ec51b362ad9f6e34f1bc396a6f","src/ir/int.rs":"1f61a472288afe489d9320bc8b13920333ece57891ae8570b4c4f25ab50688e6","src/ir/item.rs":"6f0d13615c6883b5e64c75f6d18d79b978b47aa3599ae1f4c196903d2d2cda68","src/ir/item_kind.rs":"dbeae8c4fd0e5c9485d325aea040e056a1f2cd6d43fc927dee8fe1c0c59a7197","src/ir/layout.rs":"17daab0a80564006de1f6b6190e7d9e6c5eb96990242fe707f8dc676f7110c18","src/ir/mod.rs":"2eae90f207fad2e45957ec9287064992a419e3fc916aba84faff2ea25cbeb5ee","src/ir/module.rs":"c4d90bf38fe3672e01923734ccbdb7951ea929949d5f413a9c2aee12395a5094","src/ir/objc.rs":"828a890acdc8b10c44e69e2ed4a4f5d8c0e734606d3a8cc71658dcf43a49acf4","src/ir/template.rs":"21ba4cbacafce39b4a8013bc97e8054a906a8bc2f45a51aeef3b007caadde221","src/ir/traversal.rs":"eaca9aa6deb3eea9b8d7adc696781c70038796ff43e536bda47e90f84fe87d61","src/ir/ty.rs":"daa95f757288e4bfe84f9724c5f5df127b6f3a4452330691a24a94369db7d993","src/ir/var.rs":"57c8aa9f834c6f06418f7d471b1771bbb915821ef0d194b383be60092edca5f7","src/lib.rs":"d4217ac878659794c5990b1612f1de12f94f975257ea14307fb7dc63ac3a76da","src/log_stubs.rs":"6dfdd908b7c6453da416cf232893768f9480e551ca4add0858ef88bf71ee6ceb","src/main.rs":"e519053bcdde6bc88f60f955246a02d53b3db1cc5ccd1612e6675b790b7460b0","src/options.rs":"f1be872e418a96582b048c095ceeeba012b92ffed8a9658cd1fd9ae0e192372d","src/parse.rs":"be7d13cc84fae79ec7b3aa9e77063fa475a48d74a854423e2c72d75006a25202","src/regex_set.rs":"a55241f2117f15729d174790f386e255fcb224b692325bbe6716dbb1d6874881","src/time.rs":"3b763e6fee51d0eb01228dfe28bc28a9f692aff73b2a7b90a030902e0238fca6"},"package":"1b25ab82877ea8fe6ce1ce1f8ac54361f0218bad900af9eb11803994bf67c221"}
\ No newline at end of file
--- a/third_party/rust/bindgen/Cargo.toml
+++ b/third_party/rust/bindgen/Cargo.toml
@@ -7,21 +7,22 @@
 #
 # If you believe there's an error in this file please file an
 # issue against the rust-lang/cargo repository. If you're
 # editing this file be aware that the upstream Cargo.toml
 # will likely look very different (and much more reasonable)
 
 [package]
 name = "bindgen"
-version = "0.33.2"
+version = "0.37.4"
 authors = ["Jyun-Yan You <jyyou.tw@gmail.com>", "Emilio Cobos Álvarez <emilio@crisal.io>", "Nick Fitzgerald <fitzgen@gmail.com>", "The Servo project developers"]
 build = "build.rs"
-include = ["Cargo.toml", "build.rs", "src/*.rs", "src/**/*.rs"]
+include = ["LICENSE", "README.md", "Cargo.toml", "build.rs", "src/*.rs", "src/**/*.rs"]
 description = "Automatically generates Rust FFI bindings to C and C++ libraries."
+homepage = "https://rust-lang-nursery.github.io/rust-bindgen/"
 documentation = "https://docs.rs/bindgen"
 readme = "README.md"
 keywords = ["bindings", "ffi", "code-generation"]
 categories = ["external-ffi-bindings", "development-tools::ffi"]
 license = "BSD-3-Clause"
 repository = "https://github.com/rust-lang-nursery/rust-bindgen"
 
 [lib]
@@ -33,18 +34,18 @@ path = "src/main.rs"
 doc = false
 [dependencies.cexpr]
 version = "0.2"
 
 [dependencies.cfg-if]
 version = "0.1.0"
 
 [dependencies.clang-sys]