Backed out 4 changesets (bug 1553482) for causing build bustages in BinASTTokenReaderBase.h CLOSED TREE
authorNoemi Erli <nerli@mozilla.com>
Fri, 24 May 2019 13:05:09 +0300
changeset 475351 6eb35ce885410120018363f9b3ed0d360c13d2d7
parent 475350 a296439a25ffcafae35dda80b1ecc99e4e88cad3
child 475352 72078dd30a1a1064cc051efe7f713d4917305f12
push id36060
push usercbrindusan@mozilla.com
push dateFri, 24 May 2019 21:47:21 +0000
treeherdermozilla-central@ac95bdf3c0b3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1553482
milestone69.0a1
backs outdea9d20a1162715140612c9b76bf94fb3c6ce452
f6e6533c5db2505978749f998b58fd395edcab1b
82f5e463bcb55cf0c8934d62c49ee9b17b89563e
9db8b5eba797ce86243d18af8457b3fa76c757f7
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Backed out 4 changesets (bug 1553482) for causing build bustages in BinASTTokenReaderBase.h CLOSED TREE Backed out changeset dea9d20a1162 (bug 1553482) Backed out changeset f6e6533c5db2 (bug 1553482) Backed out changeset 82f5e463bcb5 (bug 1553482) Backed out changeset 9db8b5eba797 (bug 1553482)
Cargo.lock
js/src/frontend/BinAST.yaml
js/src/frontend/BinASTParser.cpp
js/src/frontend/BinASTParser.h
js/src/frontend/BinASTParserPerTokenizer.cpp
js/src/frontend/BinASTParserPerTokenizer.h
js/src/frontend/BinASTToken.cpp
js/src/frontend/BinASTToken.h
js/src/frontend/BinASTTokenReaderBase.h
js/src/frontend/binast/Cargo.toml
js/src/frontend/binast/src/main.rs
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -224,17 +224,16 @@ dependencies = [
 name = "binary-space-partition"
 version = "0.1.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "binast"
 version = "0.1.1"
 dependencies = [
- "Inflector 0.11.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "binjs_meta 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "clap 2.31.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "env_logger 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "itertools 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "webidl 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "yaml-rust 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
--- a/js/src/frontend/BinAST.yaml
+++ b/js/src/frontend/BinAST.yaml
@@ -86,17 +86,16 @@ hpp:
 
       // To generate this file, see the documentation in
       // js/src/frontend/binast/README.md.
 
       #ifndef frontend_BinASTParser_h
       #define frontend_BinASTParser_h
 
       #include "mozilla/Maybe.h"
-      #include "mozilla/Variant.h"
 
       #include "frontend/BCEParserHandle.h"
       #include "frontend/BinASTParserPerTokenizer.h"
       #include "frontend/BinASTToken.h"
       #include "frontend/BinASTTokenReaderContext.h"
       #include "frontend/BinASTTokenReaderMultipart.h"
       #include "frontend/FullParseHandler.h"
       #include "frontend/ParseContext.h"
@@ -118,19 +117,16 @@ hpp:
 
         using Tokenizer = Tok;
 
         using BinASTFields = typename Tokenizer::BinASTFields;
         using AutoList = typename Tokenizer::AutoList;
         using AutoTaggedTuple = typename Tokenizer::AutoTaggedTuple;
         using Chars = typename Tokenizer::Chars;
         using Context = typename BinASTTokenReaderBase::Context;
-        using ListContext = typename BinASTTokenReaderBase::ListContext;
-        using FieldContext = typename BinASTTokenReaderBase::FieldContext;
-        using RootContext = typename BinASTTokenReaderBase::RootContext;
 
        public:
         // Auto-generated types.
         using AssertedDeclaredKind = binast::AssertedDeclaredKind;
         using BinaryOperator = binast::BinaryOperator;
         using CompoundAssignmentOperator = binast::CompoundAssignmentOperator;
         using UnaryOperator = binast::UnaryOperator;
         using UpdateOperator = binast::UpdateOperator;
@@ -344,21 +340,16 @@ hpp:
       const char* describeBinASTKind(const BinASTKind& kind);
 
       /**
        * Return a string describing a `BinASTField`.
        */
       const char* describeBinASTField(const BinASTField& field);
 
       /**
-       * Return a string describing a `BinASTInterfaceAndField`.
-       */
-      const char* describeBinASTInterfaceAndField(const BinASTInterfaceAndField& field);
-
-      /**
        * Return a string describing a `BinASTVariant`.
        */
       const char* describeBinASTVariant(const BinASTVariant& variant);
 
       } // namespace frontend
       } // namespace js
 
       #endif // frontend_BinASTToken_h
@@ -636,17 +627,17 @@ Block:
     BINJS_TRY_DECL(result, handler_.newLexicalScope(*bindings, statements));
 
 BreakStatement:
   fields:
     label:
       block:
         replace: |
           RootedAtom label(cx_);
-          MOZ_TRY_VAR(label, tokenizer_->readMaybeAtom(Context(FieldContext(BinASTInterfaceAndField::BreakStatement__Label))));
+          MOZ_TRY_VAR(label, tokenizer_->readMaybeAtom(fieldContext++));
 
   build: |
     if (label) {
       if (!IsIdentifier(label)) {
         return raiseError("Invalid identifier");
       }
     }
 
@@ -780,17 +771,17 @@ ConditionalExpression:
                    handler_.newConditional(test, consequent, alternate));
 
 ContinueStatement:
   fields:
     label:
       block:
         replace: |
           RootedAtom label(cx_);
-          MOZ_TRY_VAR(label, tokenizer_->readMaybeAtom(Context(FieldContext(BinASTInterfaceAndField::ContinueStatement__Label))));
+          MOZ_TRY_VAR(label, tokenizer_->readMaybeAtom(fieldContext++));
 
   build: |
     if (label) {
       if (!IsIdentifier(label)) {
         return raiseError("ContinueStatement - Label MUST be an identifier");
       }
     }
 
@@ -1293,17 +1284,17 @@ LiteralPropertyName:
     }
 
 LiteralRegExpExpression:
   fields:
     flags:
       block:
         replace: |
           Chars flags(cx_);
-          MOZ_TRY(tokenizer_->readChars(flags, Context(FieldContext(BinASTInterfaceAndField::BreakStatement__Label))));
+          MOZ_TRY(tokenizer_->readChars(flags, fieldContext++));
   build: |
     RegExpFlags reflags = RegExpFlag::NoFlags;
     for (auto c : flags) {
       if (c == 'g' && !reflags.global()) {
         reflags |= RegExpFlag::Global;
       } else if (c == 'i' && !reflags.ignoreCase()) {
         reflags |= RegExpFlag::IgnoreCase;
       } else if (c == 'm' && !reflags.multiline()) {
--- a/js/src/frontend/BinASTParser.cpp
+++ b/js/src/frontend/BinASTParser.cpp
@@ -1405,26 +1405,25 @@ JS::Result<ParseNode*> BinASTParser<Tok>
 }
 
 template <typename Tok>
 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceArrayExpression(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
     const Context& context) {
   MOZ_ASSERT(kind == BinASTKind::ArrayExpression);
   BINJS_TRY(CheckRecursionLimit(cx_));
+  Context fieldContext = Context::firstField(kind);
 
 #if defined(DEBUG)
   const BinASTField expected_fields[1] = {BinASTField::Elements};
   MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif  // defined(DEBUG)
 
   BINJS_MOZ_TRY_DECL(
-      elements,
-      parseListOfOptionalSpreadElementOrExpression(Context(
-          FieldContext(BinASTInterfaceAndField::ArrayExpression__Elements))));
+      elements, parseListOfOptionalSpreadElementOrExpression(fieldContext++));
 
   if (elements->empty()) {
     elements->setHasNonConstInitializer();
   }
   auto result = elements;
   return result;
 }
 
@@ -1454,33 +1453,28 @@ JS::Result<Ok> BinASTParser<Tok>::parseA
 }
 
 template <typename Tok>
 JS::Result<Ok> BinASTParser<Tok>::parseInterfaceAssertedBlockScope(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
     const Context& context) {
   MOZ_ASSERT(kind == BinASTKind::AssertedBlockScope);
   BINJS_TRY(CheckRecursionLimit(cx_));
+  Context fieldContext = Context::firstField(kind);
 
 #if defined(DEBUG)
   const BinASTField expected_fields[2] = {BinASTField::DeclaredNames,
                                           BinASTField::HasDirectEval};
   MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif  // defined(DEBUG)
   const auto scopeKind = AssertedScopeKind::Block;
 
-  MOZ_TRY(parseListOfAssertedDeclaredName(
-      scopeKind,
-      Context(FieldContext(
-          BinASTInterfaceAndField::AssertedBlockScope__DeclaredNames))));
-
-  BINJS_MOZ_TRY_DECL(
-      hasDirectEval,
-      tokenizer_->readBool(Context(FieldContext(
-          BinASTInterfaceAndField::AssertedBlockScope__HasDirectEval))));
+  MOZ_TRY(parseListOfAssertedDeclaredName(scopeKind, fieldContext++));
+
+  BINJS_MOZ_TRY_DECL(hasDirectEval, tokenizer_->readBool(fieldContext++));
   if (hasDirectEval) {
     pc_->sc()->setHasDirectEval();
     pc_->sc()->setBindingsAccessedDynamically();
   }
   if (hasDirectEval && pc_->isFunctionBox() && !pc_->sc()->strict()) {
     // In non-strict mode code, direct calls to eval can
     // add variables to the call object.
     pc_->functionBox()->setHasExtensibleScope();
@@ -1515,32 +1509,29 @@ JS::Result<Ok> BinASTParser<Tok>::parseA
 }
 
 template <typename Tok>
 JS::Result<Ok> BinASTParser<Tok>::parseInterfaceAssertedBoundName(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
     AssertedScopeKind scopeKind, const Context& context) {
   MOZ_ASSERT(kind == BinASTKind::AssertedBoundName);
   BINJS_TRY(CheckRecursionLimit(cx_));
+  Context fieldContext = Context::firstField(kind);
 
 #if defined(DEBUG)
   const BinASTField expected_fields[2] = {BinASTField::Name,
                                           BinASTField::IsCaptured};
   MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif  // defined(DEBUG)
   const bool allowDuplicateName = false;
 
   RootedAtom name(cx_);
-  MOZ_TRY_VAR(name, tokenizer_->readIdentifierName(Context(FieldContext(
-                        BinASTInterfaceAndField::AssertedBoundName__Name))));
-
-  BINJS_MOZ_TRY_DECL(
-      isCaptured,
-      tokenizer_->readBool(Context(FieldContext(
-          BinASTInterfaceAndField::AssertedBoundName__IsCaptured))));
+  MOZ_TRY_VAR(name, tokenizer_->readIdentifierName(fieldContext++));
+
+  BINJS_MOZ_TRY_DECL(isCaptured, tokenizer_->readBool(fieldContext++));
   ParseContext::Scope* scope;
   DeclarationKind declKind;
   MOZ_TRY(getBoundScope(scopeKind, scope, declKind));
   MOZ_TRY(addScopeName(scopeKind, name, scope, declKind, isCaptured,
                        allowDuplicateName));
   auto result = Ok();
   return result;
 }
@@ -1571,33 +1562,28 @@ JS::Result<Ok> BinASTParser<Tok>::parseA
 }
 
 template <typename Tok>
 JS::Result<Ok> BinASTParser<Tok>::parseInterfaceAssertedBoundNamesScope(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
     const Context& context) {
   MOZ_ASSERT(kind == BinASTKind::AssertedBoundNamesScope);
   BINJS_TRY(CheckRecursionLimit(cx_));
+  Context fieldContext = Context::firstField(kind);
 
 #if defined(DEBUG)
   const BinASTField expected_fields[2] = {BinASTField::BoundNames,
                                           BinASTField::HasDirectEval};
   MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif  // defined(DEBUG)
   const auto scopeKind = AssertedScopeKind::Catch;
 
-  MOZ_TRY(parseListOfAssertedBoundName(
-      scopeKind,
-      Context(FieldContext(
-          BinASTInterfaceAndField::AssertedBoundNamesScope__BoundNames))));
-
-  BINJS_MOZ_TRY_DECL(
-      hasDirectEval,
-      tokenizer_->readBool(Context(FieldContext(
-          BinASTInterfaceAndField::AssertedBoundNamesScope__HasDirectEval))));
+  MOZ_TRY(parseListOfAssertedBoundName(scopeKind, fieldContext++));
+
+  BINJS_MOZ_TRY_DECL(hasDirectEval, tokenizer_->readBool(fieldContext++));
   if (hasDirectEval) {
     pc_->sc()->setHasDirectEval();
     pc_->sc()->setBindingsAccessedDynamically();
   }
   if (hasDirectEval && pc_->isFunctionBox() && !pc_->sc()->strict()) {
     // In non-strict mode code, direct calls to eval can
     // add variables to the call object.
     pc_->functionBox()->setHasExtensibleScope();
@@ -1633,41 +1619,36 @@ JS::Result<Ok> BinASTParser<Tok>::parseA
 }
 
 template <typename Tok>
 JS::Result<Ok> BinASTParser<Tok>::parseInterfaceAssertedDeclaredName(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
     AssertedScopeKind scopeKind, const Context& context) {
   MOZ_ASSERT(kind == BinASTKind::AssertedDeclaredName);
   BINJS_TRY(CheckRecursionLimit(cx_));
+  Context fieldContext = Context::firstField(kind);
 
 #if defined(DEBUG)
   const BinASTField expected_fields[3] = {BinASTField::Name, BinASTField::Kind,
                                           BinASTField::IsCaptured};
   MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif  // defined(DEBUG)
   const bool allowDuplicateName = false;
 
   RootedAtom name(cx_);
-  MOZ_TRY_VAR(name, tokenizer_->readIdentifierName(Context(FieldContext(
-                        BinASTInterfaceAndField::AssertedDeclaredName__Name))));
-
-  BINJS_MOZ_TRY_DECL(
-      kind_, parseAssertedDeclaredKind(Context(FieldContext(
-                 BinASTInterfaceAndField::AssertedDeclaredName__Kind))));
+  MOZ_TRY_VAR(name, tokenizer_->readIdentifierName(fieldContext++));
+
+  BINJS_MOZ_TRY_DECL(kind_, parseAssertedDeclaredKind(fieldContext++));
   if (kind_ == AssertedDeclaredKind::NonConstLexical) {
     return raiseError("Let is not supported in this preview release");
   }
   if (kind_ == AssertedDeclaredKind::ConstLexical) {
     return raiseError("Const is not supported in this preview release");
   }
-  BINJS_MOZ_TRY_DECL(
-      isCaptured,
-      tokenizer_->readBool(Context(FieldContext(
-          BinASTInterfaceAndField::AssertedDeclaredName__IsCaptured))));
+  BINJS_MOZ_TRY_DECL(isCaptured, tokenizer_->readBool(fieldContext++));
   ParseContext::Scope* scope;
   DeclarationKind declKind;
   MOZ_TRY(getDeclaredScope(scopeKind, kind_, scope, declKind));
   MOZ_TRY(addScopeName(scopeKind, name, scope, declKind, isCaptured,
                        allowDuplicateName));
   auto result = Ok();
   return result;
 }
@@ -1700,42 +1681,36 @@ JS::Result<Ok> BinASTParser<Tok>::parseA
 }
 
 template <typename Tok>
 JS::Result<Ok> BinASTParser<Tok>::parseInterfaceAssertedParameterScope(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
     MutableHandle<GCVector<JSAtom*>> positionalParams, const Context& context) {
   MOZ_ASSERT(kind == BinASTKind::AssertedParameterScope);
   BINJS_TRY(CheckRecursionLimit(cx_));
+  Context fieldContext = Context::firstField(kind);
 
 #if defined(DEBUG)
   const BinASTField expected_fields[3] = {BinASTField::ParamNames,
                                           BinASTField::HasDirectEval,
                                           BinASTField::IsSimpleParameterList};
   MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif  // defined(DEBUG)
   const auto scopeKind = AssertedScopeKind::Parameter;
 
   MOZ_TRY(parseListOfAssertedMaybePositionalParameterName(
-      scopeKind, positionalParams,
-      Context(FieldContext(
-          BinASTInterfaceAndField::AssertedParameterScope__ParamNames))));
-
-  BINJS_MOZ_TRY_DECL(
-      hasDirectEval,
-      tokenizer_->readBool(Context(FieldContext(
-          BinASTInterfaceAndField::AssertedParameterScope__HasDirectEval))));
+      scopeKind, positionalParams, fieldContext++));
+
+  BINJS_MOZ_TRY_DECL(hasDirectEval, tokenizer_->readBool(fieldContext++));
   if (hasDirectEval) {
     pc_->sc()->setHasDirectEval();
     pc_->sc()->setBindingsAccessedDynamically();
   }
   BINJS_MOZ_TRY_DECL(isSimpleParameterList,
-                     tokenizer_->readBool(Context(FieldContext(
-                         BinASTInterfaceAndField::
-                             AssertedParameterScope__IsSimpleParameterList))));
+                     tokenizer_->readBool(fieldContext++));
   (void)isSimpleParameterList;
   if (hasDirectEval && pc_->isFunctionBox() && !pc_->sc()->strict()) {
     // In non-strict mode code, direct calls to eval can
     // add variables to the call object.
     pc_->functionBox()->setHasExtensibleScope();
   }
   auto result = Ok();
   return result;
@@ -1743,34 +1718,29 @@ JS::Result<Ok> BinASTParser<Tok>::parseI
 
 template <typename Tok>
 JS::Result<Ok> BinASTParser<Tok>::parseInterfaceAssertedPositionalParameterName(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
     AssertedScopeKind scopeKind,
     MutableHandle<GCVector<JSAtom*>> positionalParams, const Context& context) {
   MOZ_ASSERT(kind == BinASTKind::AssertedPositionalParameterName);
   BINJS_TRY(CheckRecursionLimit(cx_));
+  Context fieldContext = Context::firstField(kind);
 
 #if defined(DEBUG)
   const BinASTField expected_fields[3] = {BinASTField::Index, BinASTField::Name,
                                           BinASTField::IsCaptured};
   MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif  // defined(DEBUG)
   bool allowDuplicateName = !pc_->sc()->strict();
 
-  BINJS_MOZ_TRY_DECL(
-      index,
-      tokenizer_->readUnsignedLong(Context(FieldContext(
-          BinASTInterfaceAndField::AssertedPositionalParameterName__Index))));
+  BINJS_MOZ_TRY_DECL(index, tokenizer_->readUnsignedLong(fieldContext++));
 
   RootedAtom name(cx_);
-  MOZ_TRY_VAR(
-      name,
-      tokenizer_->readIdentifierName(Context(FieldContext(
-          BinASTInterfaceAndField::AssertedPositionalParameterName__Name))));
+  MOZ_TRY_VAR(name, tokenizer_->readIdentifierName(fieldContext++));
   // `positionalParams` vector can be shorter than the actual
   // parameter length. Resize on demand.
   // (see also ListOfAssertedMaybePositionalParameterName)
   size_t prevLength = positionalParams.get().length();
   if (index >= prevLength) {
     // This is implementation limit, which is not in the spec.
     if (index >= ARGNO_LIMIT - 1) {
       return raiseError("AssertedPositionalParameterName.index is too big");
@@ -1783,20 +1753,17 @@ JS::Result<Ok> BinASTParser<Tok>::parseI
   }
 
   if (positionalParams.get()[index]) {
     return raiseError(
         "AssertedPositionalParameterName has duplicate entry for the same "
         "index");
   }
   positionalParams.get()[index] = name;
-  BINJS_MOZ_TRY_DECL(isCaptured,
-                     tokenizer_->readBool(Context(FieldContext(
-                         BinASTInterfaceAndField::
-                             AssertedPositionalParameterName__IsCaptured))));
+  BINJS_MOZ_TRY_DECL(isCaptured, tokenizer_->readBool(fieldContext++));
   ParseContext::Scope* scope;
   DeclarationKind declKind;
   MOZ_TRY(getBoundScope(scopeKind, scope, declKind));
   MOZ_TRY(addScopeName(scopeKind, name, scope, declKind, isCaptured,
                        allowDuplicateName));
   auto result = Ok();
   return result;
 }
@@ -1827,33 +1794,28 @@ JS::Result<Ok> BinASTParser<Tok>::parseA
 }
 
 template <typename Tok>
 JS::Result<Ok> BinASTParser<Tok>::parseInterfaceAssertedScriptGlobalScope(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
     const Context& context) {
   MOZ_ASSERT(kind == BinASTKind::AssertedScriptGlobalScope);
   BINJS_TRY(CheckRecursionLimit(cx_));
+  Context fieldContext = Context::firstField(kind);
 
 #if defined(DEBUG)
   const BinASTField expected_fields[2] = {BinASTField::DeclaredNames,
                                           BinASTField::HasDirectEval};
   MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif  // defined(DEBUG)
   const auto scopeKind = AssertedScopeKind::Global;
 
-  MOZ_TRY(parseListOfAssertedDeclaredName(
-      scopeKind,
-      Context(FieldContext(
-          BinASTInterfaceAndField::AssertedScriptGlobalScope__DeclaredNames))));
-
-  BINJS_MOZ_TRY_DECL(
-      hasDirectEval,
-      tokenizer_->readBool(Context(FieldContext(
-          BinASTInterfaceAndField::AssertedScriptGlobalScope__HasDirectEval))));
+  MOZ_TRY(parseListOfAssertedDeclaredName(scopeKind, fieldContext++));
+
+  BINJS_MOZ_TRY_DECL(hasDirectEval, tokenizer_->readBool(fieldContext++));
   if (hasDirectEval) {
     pc_->sc()->setHasDirectEval();
     pc_->sc()->setBindingsAccessedDynamically();
   }
   if (hasDirectEval && pc_->isFunctionBox() && !pc_->sc()->strict()) {
     // In non-strict mode code, direct calls to eval can
     // add variables to the call object.
     pc_->functionBox()->setHasExtensibleScope();
@@ -1888,33 +1850,28 @@ JS::Result<Ok> BinASTParser<Tok>::parseA
 }
 
 template <typename Tok>
 JS::Result<Ok> BinASTParser<Tok>::parseInterfaceAssertedVarScope(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
     const Context& context) {
   MOZ_ASSERT(kind == BinASTKind::AssertedVarScope);
   BINJS_TRY(CheckRecursionLimit(cx_));
+  Context fieldContext = Context::firstField(kind);
 
 #if defined(DEBUG)
   const BinASTField expected_fields[2] = {BinASTField::DeclaredNames,
                                           BinASTField::HasDirectEval};
   MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif  // defined(DEBUG)
   const auto scopeKind = AssertedScopeKind::Var;
 
-  MOZ_TRY(parseListOfAssertedDeclaredName(
-      scopeKind,
-      Context(FieldContext(
-          BinASTInterfaceAndField::AssertedVarScope__DeclaredNames))));
-
-  BINJS_MOZ_TRY_DECL(
-      hasDirectEval,
-      tokenizer_->readBool(Context(FieldContext(
-          BinASTInterfaceAndField::AssertedVarScope__HasDirectEval))));
+  MOZ_TRY(parseListOfAssertedDeclaredName(scopeKind, fieldContext++));
+
+  BINJS_MOZ_TRY_DECL(hasDirectEval, tokenizer_->readBool(fieldContext++));
   if (hasDirectEval) {
     pc_->sc()->setHasDirectEval();
     pc_->sc()->setBindingsAccessedDynamically();
   }
   if (hasDirectEval && pc_->isFunctionBox() && !pc_->sc()->strict()) {
     // In non-strict mode code, direct calls to eval can
     // add variables to the call object.
     pc_->functionBox()->setHasExtensibleScope();
@@ -1924,54 +1881,49 @@ JS::Result<Ok> BinASTParser<Tok>::parseI
 }
 
 template <typename Tok>
 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceAssignmentExpression(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
     const Context& context) {
   MOZ_ASSERT(kind == BinASTKind::AssignmentExpression);
   BINJS_TRY(CheckRecursionLimit(cx_));
+  Context fieldContext = Context::firstField(kind);
 
 #if defined(DEBUG)
   const BinASTField expected_fields[2] = {BinASTField::Binding,
                                           BinASTField::Expression};
   MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif  // defined(DEBUG)
 
-  BINJS_MOZ_TRY_DECL(
-      binding, parseAssignmentTarget(Context(FieldContext(
-                   BinASTInterfaceAndField::AssignmentExpression__Binding))));
-
-  BINJS_MOZ_TRY_DECL(
-      expression,
-      parseExpression(Context(FieldContext(
-          BinASTInterfaceAndField::AssignmentExpression__Expression))));
+  BINJS_MOZ_TRY_DECL(binding, parseAssignmentTarget(fieldContext++));
+
+  BINJS_MOZ_TRY_DECL(expression, parseExpression(fieldContext++));
 
   BINJS_TRY_DECL(result, handler_.newAssignment(ParseNodeKind::AssignExpr,
                                                 binding, expression));
   return result;
 }
 
 template <typename Tok>
 JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceAssignmentTargetIdentifier(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
     const Context& context) {
   MOZ_ASSERT(kind == BinASTKind::AssignmentTargetIdentifier);
   BINJS_TRY(CheckRecursionLimit(cx_));
+  Context fieldContext = Context::firstField(kind);
 
 #if defined(DEBUG)
   const BinASTField expected_fields[1] = {BinASTField::Name};
   MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif  // defined(DEBUG)
 
   RootedAtom name(cx_);
-  MOZ_TRY_VAR(name,
-              tokenizer_->readIdentifierName(Context(FieldContext(
-                  BinASTInterfaceAndField::AssignmentTargetIdentifier__Name))));
+  MOZ_TRY_VAR(name, tokenizer_->readIdentifierName(fieldContext++));
 
   BINJS_TRY(usedNames_.noteUse(cx_, name, pc_->scriptId(),
                                pc_->innermostScope()->id()));
   BINJS_TRY_DECL(result, handler_.newName(name->asPropertyName(),
                                           tokenizer_->pos(start), cx_));
   return result;
 }
 
@@ -1984,34 +1936,29 @@ JS::Result<ParseNode*> BinASTParser<Tok>
 }
 
 template <typename Tok>
 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceBinaryExpression(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
     const Context& context) {
   MOZ_ASSERT(kind == BinASTKind::BinaryExpression);
   BINJS_TRY(CheckRecursionLimit(cx_));
+  Context fieldContext = Context::firstField(kind);
 
 #if defined(DEBUG)
   const BinASTField expected_fields[3] = {
       BinASTField::Operator, BinASTField::Left, BinASTField::Right};
   MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif  // defined(DEBUG)
 
-  BINJS_MOZ_TRY_DECL(
-      operator_, parseBinaryOperator(Context(FieldContext(
-                     BinASTInterfaceAndField::BinaryExpression__Operator))));
-
-  BINJS_MOZ_TRY_DECL(left,
-                     parseExpression(Context(FieldContext(
-                         BinASTInterfaceAndField::BinaryExpression__Left))));
-
-  BINJS_MOZ_TRY_DECL(right,
-                     parseExpression(Context(FieldContext(
-                         BinASTInterfaceAndField::BinaryExpression__Right))));
+  BINJS_MOZ_TRY_DECL(operator_, parseBinaryOperator(fieldContext++));
+
+  BINJS_MOZ_TRY_DECL(left, parseExpression(fieldContext++));
+
+  BINJS_MOZ_TRY_DECL(right, parseExpression(fieldContext++));
 
   ParseNodeKind pnk;
   switch (operator_) {
     case BinaryOperator::Comma:
       pnk = ParseNodeKind::CommaExpr;
       break;
     case BinaryOperator::LogicalOr:
       pnk = ParseNodeKind::OrExpr;
@@ -2128,25 +2075,25 @@ JS::Result<ParseNode*> BinASTParser<Tok>
 }
 
 template <typename Tok>
 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceBindingIdentifier(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
     const Context& context) {
   MOZ_ASSERT(kind == BinASTKind::BindingIdentifier);
   BINJS_TRY(CheckRecursionLimit(cx_));
+  Context fieldContext = Context::firstField(kind);
 
 #if defined(DEBUG)
   const BinASTField expected_fields[1] = {BinASTField::Name};
   MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif  // defined(DEBUG)
 
   RootedAtom name(cx_);
-  MOZ_TRY_VAR(name, tokenizer_->readIdentifierName(Context(FieldContext(
-                        BinASTInterfaceAndField::BindingIdentifier__Name))));
+  MOZ_TRY_VAR(name, tokenizer_->readIdentifierName(fieldContext++));
 
   BINJS_TRY_DECL(result, handler_.newName(name->asPropertyName(),
                                           tokenizer_->pos(start), cx_));
   return result;
 }
 
 template <typename Tok>
 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceBindingWithInitializer(
@@ -2181,53 +2128,51 @@ JS::Result<ParseNode*> BinASTParser<Tok>
 }
 
 template <typename Tok>
 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceBlock(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
     const Context& context) {
   MOZ_ASSERT(kind == BinASTKind::Block);
   BINJS_TRY(CheckRecursionLimit(cx_));
+  Context fieldContext = Context::firstField(kind);
 
 #if defined(DEBUG)
   const BinASTField expected_fields[2] = {BinASTField::Scope,
                                           BinASTField::Statements};
   MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif  // defined(DEBUG)
   ParseContext::Statement stmt(pc_, StatementKind::Block);
   ParseContext::Scope currentScope(cx_, pc_, usedNames_);
   BINJS_TRY(currentScope.init(pc_));
 
-  MOZ_TRY(parseAssertedBlockScope(
-      Context(FieldContext(BinASTInterfaceAndField::Block__Scope))));
-
-  BINJS_MOZ_TRY_DECL(statements,
-                     parseListOfStatement(Context(FieldContext(
-                         BinASTInterfaceAndField::Block__Statements))));
+  MOZ_TRY(parseAssertedBlockScope(fieldContext++));
+
+  BINJS_MOZ_TRY_DECL(statements, parseListOfStatement(fieldContext++));
 
   MOZ_TRY(checkClosedVars(currentScope));
   BINJS_TRY_DECL(bindings, NewLexicalScopeData(cx_, currentScope, alloc_, pc_));
   BINJS_TRY_DECL(result, handler_.newLexicalScope(*bindings, statements));
   return result;
 }
 
 template <typename Tok>
 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceBreakStatement(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
     const Context& context) {
   MOZ_ASSERT(kind == BinASTKind::BreakStatement);
   BINJS_TRY(CheckRecursionLimit(cx_));
+  Context fieldContext = Context::firstField(kind);
 
 #if defined(DEBUG)
   const BinASTField expected_fields[1] = {BinASTField::Label};
   MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif  // defined(DEBUG)
   RootedAtom label(cx_);
-  MOZ_TRY_VAR(label, tokenizer_->readMaybeAtom(Context(FieldContext(
-                         BinASTInterfaceAndField::BreakStatement__Label))));
+  MOZ_TRY_VAR(label, tokenizer_->readMaybeAtom(fieldContext++));
 
   if (label) {
     if (!IsIdentifier(label)) {
       return raiseError("Invalid identifier");
     }
   }
 
   auto validity =
@@ -2250,30 +2195,27 @@ JS::Result<ParseNode*> BinASTParser<Tok>
 }
 
 template <typename Tok>
 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceCallExpression(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
     const Context& context) {
   MOZ_ASSERT(kind == BinASTKind::CallExpression);
   BINJS_TRY(CheckRecursionLimit(cx_));
+  Context fieldContext = Context::firstField(kind);
 
 #if defined(DEBUG)
   const BinASTField expected_fields[2] = {BinASTField::Callee,
                                           BinASTField::Arguments};
   MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif  // defined(DEBUG)
 
-  BINJS_MOZ_TRY_DECL(callee,
-                     parseExpressionOrSuper(Context(FieldContext(
-                         BinASTInterfaceAndField::CallExpression__Callee))));
-
-  BINJS_MOZ_TRY_DECL(arguments,
-                     parseArguments(Context(FieldContext(
-                         BinASTInterfaceAndField::CallExpression__Arguments))));
+  BINJS_MOZ_TRY_DECL(callee, parseExpressionOrSuper(fieldContext++));
+
+  BINJS_MOZ_TRY_DECL(arguments, parseArguments(fieldContext++));
 
   auto op = JSOP_CALL;
 
   // Try to optimize funcall and funapply at the bytecode level
   if (PropertyName* prop = handler_.maybeDottedProperty(callee)) {
     if (prop == cx_->names().apply) {
       op = JSOP_FUNAPPLY;
       if (pc_->isFunctionBox()) {
@@ -2328,38 +2270,35 @@ JS::Result<LexicalScopeNode*> BinASTPars
 }
 
 template <typename Tok>
 JS::Result<LexicalScopeNode*> BinASTParser<Tok>::parseInterfaceCatchClause(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
     const Context& context) {
   MOZ_ASSERT(kind == BinASTKind::CatchClause);
   BINJS_TRY(CheckRecursionLimit(cx_));
+  Context fieldContext = Context::firstField(kind);
 
 #if defined(DEBUG)
   const BinASTField expected_fields[3] = {
       BinASTField::BindingScope, BinASTField::Binding, BinASTField::Body};
   MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif  // defined(DEBUG)
   ParseContext::Statement stmt(pc_, StatementKind::Catch);
   ParseContext::Scope currentScope(cx_, pc_, usedNames_);
   BINJS_TRY(currentScope.init(pc_));
 
-  MOZ_TRY(parseAssertedBoundNamesScope(Context(
-      FieldContext(BinASTInterfaceAndField::CatchClause__BindingScope))));
-
-  BINJS_MOZ_TRY_DECL(binding,
-                     parseBinding(Context(FieldContext(
-                         BinASTInterfaceAndField::CatchClause__Binding))));
+  MOZ_TRY(parseAssertedBoundNamesScope(fieldContext++));
+
+  BINJS_MOZ_TRY_DECL(binding, parseBinding(fieldContext++));
   if (!currentScope.lookupDeclaredName(
           binding->template as<NameNode>().atom())) {
     return raiseError("Missing catch variable in scope");
   }
-  BINJS_MOZ_TRY_DECL(body, parseBlock(Context(FieldContext(
-                               BinASTInterfaceAndField::CatchClause__Body))));
+  BINJS_MOZ_TRY_DECL(body, parseBlock(fieldContext++));
 
   MOZ_TRY(checkClosedVars(currentScope));
   BINJS_TRY_DECL(bindings, NewLexicalScopeData(cx_, currentScope, alloc_, pc_));
   BINJS_TRY_DECL(result, handler_.newLexicalScope(*bindings, body));
   BINJS_TRY(handler_.setupCatchScope(result, binding, body));
   return result;
 }
 
@@ -2381,37 +2320,30 @@ JS::Result<ParseNode*> BinASTParser<Tok>
 
 template <typename Tok>
 JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceCompoundAssignmentExpression(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
     const Context& context) {
   MOZ_ASSERT(kind == BinASTKind::CompoundAssignmentExpression);
   BINJS_TRY(CheckRecursionLimit(cx_));
+  Context fieldContext = Context::firstField(kind);
 
 #if defined(DEBUG)
   const BinASTField expected_fields[3] = {
       BinASTField::Operator, BinASTField::Binding, BinASTField::Expression};
   MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif  // defined(DEBUG)
 
-  BINJS_MOZ_TRY_DECL(
-      operator_,
-      parseCompoundAssignmentOperator(Context(FieldContext(
-          BinASTInterfaceAndField::CompoundAssignmentExpression__Operator))));
-
-  BINJS_MOZ_TRY_DECL(
-      binding,
-      parseSimpleAssignmentTarget(Context(FieldContext(
-          BinASTInterfaceAndField::CompoundAssignmentExpression__Binding))));
-
-  BINJS_MOZ_TRY_DECL(
-      expression,
-      parseExpression(Context(FieldContext(
-          BinASTInterfaceAndField::CompoundAssignmentExpression__Expression))));
+  BINJS_MOZ_TRY_DECL(operator_,
+                     parseCompoundAssignmentOperator(fieldContext++));
+
+  BINJS_MOZ_TRY_DECL(binding, parseSimpleAssignmentTarget(fieldContext++));
+
+  BINJS_MOZ_TRY_DECL(expression, parseExpression(fieldContext++));
 
   ParseNodeKind pnk;
   switch (operator_) {
     case CompoundAssignmentOperator::PlusAssign:
       pnk = ParseNodeKind::AddAssignExpr;
       break;
     case CompoundAssignmentOperator::MinusAssign:
       pnk = ParseNodeKind::SubAssignExpr;
@@ -2453,60 +2385,51 @@ BinASTParser<Tok>::parseInterfaceCompoun
 
 template <typename Tok>
 JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceComputedMemberAssignmentTarget(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
     const Context& context) {
   MOZ_ASSERT(kind == BinASTKind::ComputedMemberAssignmentTarget);
   BINJS_TRY(CheckRecursionLimit(cx_));
+  Context fieldContext = Context::firstField(kind);
 
 #if defined(DEBUG)
   const BinASTField expected_fields[2] = {BinASTField::Object,
                                           BinASTField::Expression};
   MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif  // defined(DEBUG)
 
-  BINJS_MOZ_TRY_DECL(
-      object,
-      parseExpressionOrSuper(Context(FieldContext(
-          BinASTInterfaceAndField::ComputedMemberAssignmentTarget__Object))));
-
-  BINJS_MOZ_TRY_DECL(expression,
-                     parseExpression(Context(FieldContext(
-                         BinASTInterfaceAndField::
-                             ComputedMemberAssignmentTarget__Expression))));
+  BINJS_MOZ_TRY_DECL(object, parseExpressionOrSuper(fieldContext++));
+
+  BINJS_MOZ_TRY_DECL(expression, parseExpression(fieldContext++));
 
   BINJS_TRY_DECL(result, handler_.newPropertyByValue(object, expression,
                                                      tokenizer_->offset()));
   return result;
 }
 
 template <typename Tok>
 JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceComputedMemberExpression(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
     const Context& context) {
   MOZ_ASSERT(kind == BinASTKind::ComputedMemberExpression);
   BINJS_TRY(CheckRecursionLimit(cx_));
+  Context fieldContext = Context::firstField(kind);
 
 #if defined(DEBUG)
   const BinASTField expected_fields[2] = {BinASTField::Object,
                                           BinASTField::Expression};
   MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif  // defined(DEBUG)
 
-  BINJS_MOZ_TRY_DECL(
-      object, parseExpressionOrSuper(Context(FieldContext(
-                  BinASTInterfaceAndField::ComputedMemberExpression__Object))));
-
-  BINJS_MOZ_TRY_DECL(
-      expression,
-      parseExpression(Context(FieldContext(
-          BinASTInterfaceAndField::ComputedMemberExpression__Expression))));
+  BINJS_MOZ_TRY_DECL(object, parseExpressionOrSuper(fieldContext++));
+
+  BINJS_MOZ_TRY_DECL(expression, parseExpression(fieldContext++));
 
   BINJS_TRY_DECL(result, handler_.newPropertyByValue(object, expression,
                                                      tokenizer_->offset()));
   return result;
 }
 
 template <typename Tok>
 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceComputedPropertyName(
@@ -2518,55 +2441,48 @@ JS::Result<ParseNode*> BinASTParser<Tok>
 }
 
 template <typename Tok>
 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceConditionalExpression(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
     const Context& context) {
   MOZ_ASSERT(kind == BinASTKind::ConditionalExpression);
   BINJS_TRY(CheckRecursionLimit(cx_));
+  Context fieldContext = Context::firstField(kind);
 
 #if defined(DEBUG)
   const BinASTField expected_fields[3] = {
       BinASTField::Test, BinASTField::Consequent, BinASTField::Alternate};
   MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif  // defined(DEBUG)
 
-  BINJS_MOZ_TRY_DECL(
-      test, parseExpression(Context(FieldContext(
-                BinASTInterfaceAndField::ConditionalExpression__Test))));
-
-  BINJS_MOZ_TRY_DECL(
-      consequent,
-      parseExpression(Context(FieldContext(
-          BinASTInterfaceAndField::ConditionalExpression__Consequent))));
-
-  BINJS_MOZ_TRY_DECL(
-      alternate,
-      parseExpression(Context(FieldContext(
-          BinASTInterfaceAndField::ConditionalExpression__Alternate))));
+  BINJS_MOZ_TRY_DECL(test, parseExpression(fieldContext++));
+
+  BINJS_MOZ_TRY_DECL(consequent, parseExpression(fieldContext++));
+
+  BINJS_MOZ_TRY_DECL(alternate, parseExpression(fieldContext++));
 
   BINJS_TRY_DECL(result, handler_.newConditional(test, consequent, alternate));
   return result;
 }
 
 template <typename Tok>
 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceContinueStatement(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
     const Context& context) {
   MOZ_ASSERT(kind == BinASTKind::ContinueStatement);
   BINJS_TRY(CheckRecursionLimit(cx_));
+  Context fieldContext = Context::firstField(kind);
 
 #if defined(DEBUG)
   const BinASTField expected_fields[1] = {BinASTField::Label};
   MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif  // defined(DEBUG)
   RootedAtom label(cx_);
-  MOZ_TRY_VAR(label, tokenizer_->readMaybeAtom(Context(FieldContext(
-                         BinASTInterfaceAndField::ContinueStatement__Label))));
+  MOZ_TRY_VAR(label, tokenizer_->readMaybeAtom(fieldContext++));
 
   if (label) {
     if (!IsIdentifier(label)) {
       return raiseError("ContinueStatement - Label MUST be an identifier");
     }
   }
 
   auto validity =
@@ -2589,29 +2505,27 @@ JS::Result<ParseNode*> BinASTParser<Tok>
 }
 
 template <typename Tok>
 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceDataProperty(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
     const Context& context) {
   MOZ_ASSERT(kind == BinASTKind::DataProperty);
   BINJS_TRY(CheckRecursionLimit(cx_));
+  Context fieldContext = Context::firstField(kind);
 
 #if defined(DEBUG)
   const BinASTField expected_fields[2] = {BinASTField::Name,
                                           BinASTField::Expression};
   MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif  // defined(DEBUG)
 
-  BINJS_MOZ_TRY_DECL(name, parsePropertyName(Context(FieldContext(
-                               BinASTInterfaceAndField::DataProperty__Name))));
-
-  BINJS_MOZ_TRY_DECL(expression,
-                     parseExpression(Context(FieldContext(
-                         BinASTInterfaceAndField::DataProperty__Expression))));
+  BINJS_MOZ_TRY_DECL(name, parsePropertyName(fieldContext++));
+
+  BINJS_MOZ_TRY_DECL(expression, parseExpression(fieldContext++));
 
   if (!handler_.isUsableAsObjectPropertyName(name)) {
     return raiseError("DataProperty key kind");
   }
 
   ParseNode* result;
   if (name->template is<NameNode>() &&
       name->template as<NameNode>().atom() == cx_->names().proto) {
@@ -2657,51 +2571,48 @@ JS::Result<ParseNode*> BinASTParser<Tok>
 }
 
 template <typename Tok>
 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceDirective(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
     const Context& context) {
   MOZ_ASSERT(kind == BinASTKind::Directive);
   BINJS_TRY(CheckRecursionLimit(cx_));
+  Context fieldContext = Context::firstField(kind);
 
 #if defined(DEBUG)
   const BinASTField expected_fields[1] = {BinASTField::RawValue};
   MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif  // defined(DEBUG)
 
   RootedAtom rawValue(cx_);
-  MOZ_TRY_VAR(rawValue, tokenizer_->readAtom(Context(FieldContext(
-                            BinASTInterfaceAndField::Directive__RawValue))));
+  MOZ_TRY_VAR(rawValue, tokenizer_->readAtom(fieldContext++));
 
   TokenPos pos = tokenizer_->pos(start);
   BINJS_TRY_DECL(result, handler_.newStringLiteral(rawValue, pos));
   return result;
 }
 
 template <typename Tok>
 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceDoWhileStatement(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
     const Context& context) {
   MOZ_ASSERT(kind == BinASTKind::DoWhileStatement);
   BINJS_TRY(CheckRecursionLimit(cx_));
+  Context fieldContext = Context::firstField(kind);
 
 #if defined(DEBUG)
   const BinASTField expected_fields[2] = {BinASTField::Test, BinASTField::Body};
   MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif  // defined(DEBUG)
   ParseContext::Statement stmt(pc_, StatementKind::DoLoop);
 
-  BINJS_MOZ_TRY_DECL(test,
-                     parseExpression(Context(FieldContext(
-                         BinASTInterfaceAndField::DoWhileStatement__Test))));
-
-  BINJS_MOZ_TRY_DECL(body,
-                     parseStatement(Context(FieldContext(
-                         BinASTInterfaceAndField::DoWhileStatement__Body))));
+  BINJS_MOZ_TRY_DECL(test, parseExpression(fieldContext++));
+
+  BINJS_MOZ_TRY_DECL(body, parseStatement(fieldContext++));
 
   BINJS_TRY_DECL(
       result, handler_.newDoWhileStatement(body, test, tokenizer_->pos(start)));
   return result;
 }
 
 template <typename Tok>
 JS::Result<ParseNode*>
@@ -2725,52 +2636,40 @@ BinASTParser<Tok>::parseInterfaceEagerAr
 
 template <typename Tok>
 JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceEagerFunctionDeclaration(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
     const Context& context) {
   MOZ_ASSERT(kind == BinASTKind::EagerFunctionDeclaration);
   BINJS_TRY(CheckRecursionLimit(cx_));
+  Context fieldContext = Context::firstField(kind);
 
 #if defined(DEBUG)
   const BinASTField expected_fields[6] = {
       BinASTField::IsAsync, BinASTField::IsGenerator, BinASTField::Name,
       BinASTField::Length,  BinASTField::Directives,  BinASTField::Contents};
   MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif  // defined(DEBUG)
   const auto syntax = FunctionSyntaxKind::Statement;
 
-  BINJS_MOZ_TRY_DECL(
-      isAsync,
-      tokenizer_->readBool(Context(FieldContext(
-          BinASTInterfaceAndField::EagerFunctionDeclaration__IsAsync))));
+  BINJS_MOZ_TRY_DECL(isAsync, tokenizer_->readBool(fieldContext++));
   if (isAsync) {
     return raiseError(
         "Async function is not supported in this preview release");
   }
-  BINJS_MOZ_TRY_DECL(
-      isGenerator,
-      tokenizer_->readBool(Context(FieldContext(
-          BinASTInterfaceAndField::EagerFunctionDeclaration__IsGenerator))));
+  BINJS_MOZ_TRY_DECL(isGenerator, tokenizer_->readBool(fieldContext++));
   if (isGenerator) {
     return raiseError("Generator is not supported in this preview release");
   }
-  BINJS_MOZ_TRY_DECL(
-      name, parseBindingIdentifier(Context(FieldContext(
-                BinASTInterfaceAndField::EagerFunctionDeclaration__Name))));
-
-  BINJS_MOZ_TRY_DECL(
-      length, tokenizer_->readUnsignedLong(Context(FieldContext(
-                  BinASTInterfaceAndField::EagerFunctionDeclaration__Length))));
-
-  BINJS_MOZ_TRY_DECL(
-      directives,
-      parseListOfDirective(Context(FieldContext(
-          BinASTInterfaceAndField::EagerFunctionDeclaration__Directives))));
+  BINJS_MOZ_TRY_DECL(name, parseBindingIdentifier(fieldContext++));
+
+  BINJS_MOZ_TRY_DECL(length, tokenizer_->readUnsignedLong(fieldContext++));
+
+  BINJS_MOZ_TRY_DECL(directives, parseListOfDirective(fieldContext++));
 
   BINJS_MOZ_TRY_DECL(funbox,
                      buildFunctionBox(isGenerator ? GeneratorKind::Generator
                                                   : GeneratorKind::NotGenerator,
                                       isAsync ? FunctionAsyncKind::AsyncFunction
                                               : FunctionAsyncKind::SyncFunction,
                                       syntax,
                                       (syntax != FunctionSyntaxKind::Setter &&
@@ -2786,71 +2685,57 @@ BinASTParser<Tok>::parseInterfaceEagerFu
   BINJS_TRY(funpc.init());
   pc_->functionScope().useAsVarScope(pc_);
   MOZ_ASSERT(pc_->isFunctionBox());
 
   ParseContext::Scope lexicalScope(cx_, pc_, usedNames_);
   BINJS_TRY(lexicalScope.init(pc_));
   ListNode* params;
   ListNode* body;
-  MOZ_TRY(parseFunctionOrMethodContents(
-      length, &params, &body,
-      Context(FieldContext(
-          BinASTInterfaceAndField::EagerFunctionDeclaration__Contents))));
+  MOZ_TRY(
+      parseFunctionOrMethodContents(length, &params, &body, fieldContext++));
   MOZ_TRY(prependDirectivesToBody(body, directives));
   BINJS_TRY_DECL(lexicalScopeData,
                  NewLexicalScopeData(cx_, lexicalScope, alloc_, pc_));
   BINJS_TRY_DECL(bodyScope, handler_.newLexicalScope(*lexicalScopeData, body));
   BINJS_MOZ_TRY_DECL(result,
                      buildFunction(start, kind, name, params, bodyScope));
   return result;
 }
 
 template <typename Tok>
 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceEagerFunctionExpression(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
     const Context& context) {
   MOZ_ASSERT(kind == BinASTKind::EagerFunctionExpression);
   BINJS_TRY(CheckRecursionLimit(cx_));
+  Context fieldContext = Context::firstField(kind);
 
 #if defined(DEBUG)
   const BinASTField expected_fields[6] = {
       BinASTField::IsAsync, BinASTField::IsGenerator, BinASTField::Name,
       BinASTField::Length,  BinASTField::Directives,  BinASTField::Contents};
   MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif  // defined(DEBUG)
   const auto syntax = FunctionSyntaxKind::Expression;
 
-  BINJS_MOZ_TRY_DECL(
-      isAsync,
-      tokenizer_->readBool(Context(FieldContext(
-          BinASTInterfaceAndField::EagerFunctionExpression__IsAsync))));
+  BINJS_MOZ_TRY_DECL(isAsync, tokenizer_->readBool(fieldContext++));
   if (isAsync) {
     return raiseError(
         "Async function is not supported in this preview release");
   }
-  BINJS_MOZ_TRY_DECL(
-      isGenerator,
-      tokenizer_->readBool(Context(FieldContext(
-          BinASTInterfaceAndField::EagerFunctionExpression__IsGenerator))));
+  BINJS_MOZ_TRY_DECL(isGenerator, tokenizer_->readBool(fieldContext++));
   if (isGenerator) {
     return raiseError("Generator is not supported in this preview release");
   }
-  BINJS_MOZ_TRY_DECL(
-      name, parseOptionalBindingIdentifier(Context(FieldContext(
-                BinASTInterfaceAndField::EagerFunctionExpression__Name))));
-
-  BINJS_MOZ_TRY_DECL(
-      length, tokenizer_->readUnsignedLong(Context(FieldContext(
-                  BinASTInterfaceAndField::EagerFunctionExpression__Length))));
-
-  BINJS_MOZ_TRY_DECL(
-      directives,
-      parseListOfDirective(Context(FieldContext(
-          BinASTInterfaceAndField::EagerFunctionExpression__Directives))));
+  BINJS_MOZ_TRY_DECL(name, parseOptionalBindingIdentifier(fieldContext++));
+
+  BINJS_MOZ_TRY_DECL(length, tokenizer_->readUnsignedLong(fieldContext++));
+
+  BINJS_MOZ_TRY_DECL(directives, parseListOfDirective(fieldContext++));
 
   BINJS_MOZ_TRY_DECL(funbox,
                      buildFunctionBox(isGenerator ? GeneratorKind::Generator
                                                   : GeneratorKind::NotGenerator,
                                       isAsync ? FunctionAsyncKind::AsyncFunction
                                               : FunctionAsyncKind::SyncFunction,
                                       syntax,
                                       (syntax != FunctionSyntaxKind::Setter &&
@@ -2866,53 +2751,49 @@ JS::Result<ParseNode*> BinASTParser<Tok>
   BINJS_TRY(funpc.init());
   pc_->functionScope().useAsVarScope(pc_);
   MOZ_ASSERT(pc_->isFunctionBox());
 
   ParseContext::Scope lexicalScope(cx_, pc_, usedNames_);
   BINJS_TRY(lexicalScope.init(pc_));
   ListNode* params;
   ListNode* body;
-  MOZ_TRY(parseFunctionExpressionContents(
-      length, &params, &body,
-      Context(FieldContext(
-          BinASTInterfaceAndField::EagerFunctionExpression__Contents))));
+  MOZ_TRY(
+      parseFunctionExpressionContents(length, &params, &body, fieldContext++));
   MOZ_TRY(prependDirectivesToBody(body, directives));
   BINJS_TRY_DECL(lexicalScopeData,
                  NewLexicalScopeData(cx_, lexicalScope, alloc_, pc_));
   BINJS_TRY_DECL(bodyScope, handler_.newLexicalScope(*lexicalScopeData, body));
   BINJS_MOZ_TRY_DECL(result,
                      buildFunction(start, kind, name, params, bodyScope));
   return result;
 }
 
 template <typename Tok>
 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceEagerGetter(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
     const Context& context) {
   MOZ_ASSERT(kind == BinASTKind::EagerGetter);
   BINJS_TRY(CheckRecursionLimit(cx_));
+  Context fieldContext = Context::firstField(kind);
 
 #if defined(DEBUG)
   const BinASTField expected_fields[3] = {
       BinASTField::Name, BinASTField::Directives, BinASTField::Contents};
   MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif  // defined(DEBUG)
   const auto syntax = FunctionSyntaxKind::Setter;
   const bool isGenerator = false;
   const bool isAsync = false;
   const auto accessorType = AccessorType::Getter;
   const uint32_t length = 0;
 
-  BINJS_MOZ_TRY_DECL(name, parsePropertyName(Context(FieldContext(
-                               BinASTInterfaceAndField::EagerGetter__Name))));
-
-  BINJS_MOZ_TRY_DECL(directives,
-                     parseListOfDirective(Context(FieldContext(
-                         BinASTInterfaceAndField::EagerGetter__Directives))));
+  BINJS_MOZ_TRY_DECL(name, parsePropertyName(fieldContext++));
+
+  BINJS_MOZ_TRY_DECL(directives, parseListOfDirective(fieldContext++));
 
   BINJS_MOZ_TRY_DECL(funbox,
                      buildFunctionBox(isGenerator ? GeneratorKind::Generator
                                                   : GeneratorKind::NotGenerator,
                                       isAsync ? FunctionAsyncKind::AsyncFunction
                                               : FunctionAsyncKind::SyncFunction,
                                       syntax,
                                       (syntax != FunctionSyntaxKind::Setter &&
@@ -2928,19 +2809,17 @@ JS::Result<ParseNode*> BinASTParser<Tok>
   BINJS_TRY(funpc.init());
   pc_->functionScope().useAsVarScope(pc_);
   MOZ_ASSERT(pc_->isFunctionBox());
 
   ParseContext::Scope lexicalScope(cx_, pc_, usedNames_);
   BINJS_TRY(lexicalScope.init(pc_));
   ListNode* params;
   ListNode* body;
-  MOZ_TRY(parseGetterContents(
-      length, &params, &body,
-      Context(FieldContext(BinASTInterfaceAndField::EagerGetter__Contents))));
+  MOZ_TRY(parseGetterContents(length, &params, &body, fieldContext++));
   MOZ_TRY(prependDirectivesToBody(body, directives));
   BINJS_TRY_DECL(lexicalScopeData,
                  NewLexicalScopeData(cx_, lexicalScope, alloc_, pc_));
   BINJS_TRY_DECL(bodyScope, handler_.newLexicalScope(*lexicalScopeData, body));
   BINJS_MOZ_TRY_DECL(method,
                      buildFunction(start, kind, name, params, bodyScope));
   BINJS_TRY_DECL(result, handler_.newObjectMethodOrPropertyDefinition(
                              name, method, accessorType));
@@ -2948,49 +2827,41 @@ JS::Result<ParseNode*> BinASTParser<Tok>
 }
 
 template <typename Tok>
 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceEagerMethod(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
     const Context& context) {
   MOZ_ASSERT(kind == BinASTKind::EagerMethod);
   BINJS_TRY(CheckRecursionLimit(cx_));
+  Context fieldContext = Context::firstField(kind);
 
 #if defined(DEBUG)
   const BinASTField expected_fields[6] = {
       BinASTField::IsAsync, BinASTField::IsGenerator, BinASTField::Name,
       BinASTField::Length,  BinASTField::Directives,  BinASTField::Contents};
   MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif  // defined(DEBUG)
   const auto syntax = FunctionSyntaxKind::Method;
   const auto accessorType = AccessorType::None;
 
-  BINJS_MOZ_TRY_DECL(isAsync,
-                     tokenizer_->readBool(Context(FieldContext(
-                         BinASTInterfaceAndField::EagerMethod__IsAsync))));
+  BINJS_MOZ_TRY_DECL(isAsync, tokenizer_->readBool(fieldContext++));
   if (isAsync) {
     return raiseError(
         "Async function is not supported in this preview release");
   }
-  BINJS_MOZ_TRY_DECL(isGenerator,
-                     tokenizer_->readBool(Context(FieldContext(
-                         BinASTInterfaceAndField::EagerMethod__IsGenerator))));
+  BINJS_MOZ_TRY_DECL(isGenerator, tokenizer_->readBool(fieldContext++));
   if (isGenerator) {
     return raiseError("Generator is not supported in this preview release");
   }
-  BINJS_MOZ_TRY_DECL(name, parsePropertyName(Context(FieldContext(
-                               BinASTInterfaceAndField::EagerMethod__Name))));
-
-  BINJS_MOZ_TRY_DECL(
-      length, tokenizer_->readUnsignedLong(Context(
-                  FieldContext(BinASTInterfaceAndField::EagerMethod__Length))));
-
-  BINJS_MOZ_TRY_DECL(directives,
-                     parseListOfDirective(Context(FieldContext(
-                         BinASTInterfaceAndField::EagerMethod__Directives))));
+  BINJS_MOZ_TRY_DECL(name, parsePropertyName(fieldContext++));
+
+  BINJS_MOZ_TRY_DECL(length, tokenizer_->readUnsignedLong(fieldContext++));
+
+  BINJS_MOZ_TRY_DECL(directives, parseListOfDirective(fieldContext++));
 
   BINJS_MOZ_TRY_DECL(funbox,
                      buildFunctionBox(isGenerator ? GeneratorKind::Generator
                                                   : GeneratorKind::NotGenerator,
                                       isAsync ? FunctionAsyncKind::AsyncFunction
                                               : FunctionAsyncKind::SyncFunction,
                                       syntax,
                                       (syntax != FunctionSyntaxKind::Setter &&
@@ -3006,19 +2877,18 @@ JS::Result<ParseNode*> BinASTParser<Tok>
   BINJS_TRY(funpc.init());
   pc_->functionScope().useAsVarScope(pc_);
   MOZ_ASSERT(pc_->isFunctionBox());
 
   ParseContext::Scope lexicalScope(cx_, pc_, usedNames_);
   BINJS_TRY(lexicalScope.init(pc_));
   ListNode* params;
   ListNode* body;
-  MOZ_TRY(parseFunctionOrMethodContents(
-      length, &params, &body,
-      Context(FieldContext(BinASTInterfaceAndField::EagerMethod__Contents))));
+  MOZ_TRY(
+      parseFunctionOrMethodContents(length, &params, &body, fieldContext++));
   MOZ_TRY(prependDirectivesToBody(body, directives));
   BINJS_TRY_DECL(lexicalScopeData,
                  NewLexicalScopeData(cx_, lexicalScope, alloc_, pc_));
   BINJS_TRY_DECL(bodyScope, handler_.newLexicalScope(*lexicalScopeData, body));
   BINJS_MOZ_TRY_DECL(method,
                      buildFunction(start, kind, name, params, bodyScope));
   BINJS_TRY_DECL(result, handler_.newObjectMethodOrPropertyDefinition(
                              name, method, accessorType));
@@ -3026,38 +2896,34 @@ JS::Result<ParseNode*> BinASTParser<Tok>
 }
 
 template <typename Tok>
 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceEagerSetter(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
     const Context& context) {
   MOZ_ASSERT(kind == BinASTKind::EagerSetter);
   BINJS_TRY(CheckRecursionLimit(cx_));
+  Context fieldContext = Context::firstField(kind);
 
 #if defined(DEBUG)
   const BinASTField expected_fields[4] = {
       BinASTField::Name, BinASTField::Length, BinASTField::Directives,
       BinASTField::Contents};
   MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif  // defined(DEBUG)
   const auto syntax = FunctionSyntaxKind::Setter;
   const bool isGenerator = false;
   const bool isAsync = false;
   const auto accessorType = AccessorType::Setter;
 
-  BINJS_MOZ_TRY_DECL(name, parsePropertyName(Context(FieldContext(
-                               BinASTInterfaceAndField::EagerSetter__Name))));
-
-  BINJS_MOZ_TRY_DECL(
-      length, tokenizer_->readUnsignedLong(Context(
-                  FieldContext(BinASTInterfaceAndField::EagerSetter__Length))));
-
-  BINJS_MOZ_TRY_DECL(directives,
-                     parseListOfDirective(Context(FieldContext(
-                         BinASTInterfaceAndField::EagerSetter__Directives))));
+  BINJS_MOZ_TRY_DECL(name, parsePropertyName(fieldContext++));
+
+  BINJS_MOZ_TRY_DECL(length, tokenizer_->readUnsignedLong(fieldContext++));
+
+  BINJS_MOZ_TRY_DECL(directives, parseListOfDirective(fieldContext++));
 
   BINJS_MOZ_TRY_DECL(funbox,
                      buildFunctionBox(isGenerator ? GeneratorKind::Generator
                                                   : GeneratorKind::NotGenerator,
                                       isAsync ? FunctionAsyncKind::AsyncFunction
                                               : FunctionAsyncKind::SyncFunction,
                                       syntax,
                                       (syntax != FunctionSyntaxKind::Setter &&
@@ -3073,19 +2939,17 @@ JS::Result<ParseNode*> BinASTParser<Tok>
   BINJS_TRY(funpc.init());
   pc_->functionScope().useAsVarScope(pc_);
   MOZ_ASSERT(pc_->isFunctionBox());
 
   ParseContext::Scope lexicalScope(cx_, pc_, usedNames_);
   BINJS_TRY(lexicalScope.init(pc_));
   ListNode* params;
   ListNode* body;
-  MOZ_TRY(parseSetterContents(
-      length, &params, &body,
-      Context(FieldContext(BinASTInterfaceAndField::EagerSetter__Contents))));
+  MOZ_TRY(parseSetterContents(length, &params, &body, fieldContext++));
   MOZ_TRY(prependDirectivesToBody(body, directives));
   BINJS_TRY_DECL(lexicalScopeData,
                  NewLexicalScopeData(cx_, lexicalScope, alloc_, pc_));
   BINJS_TRY_DECL(bodyScope, handler_.newLexicalScope(*lexicalScopeData, body));
   BINJS_MOZ_TRY_DECL(method,
                      buildFunction(start, kind, name, params, bodyScope));
   BINJS_TRY_DECL(result, handler_.newObjectMethodOrPropertyDefinition(
                              name, method, accessorType));
@@ -3105,53 +2969,48 @@ JS::Result<ParseNode*> BinASTParser<Tok>
 }
 
 template <typename Tok>
 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceExpressionStatement(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
     const Context& context) {
   MOZ_ASSERT(kind == BinASTKind::ExpressionStatement);
   BINJS_TRY(CheckRecursionLimit(cx_));
+  Context fieldContext = Context::firstField(kind);
 
 #if defined(DEBUG)
   const BinASTField expected_fields[1] = {BinASTField::Expression};
   MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif  // defined(DEBUG)
 
-  BINJS_MOZ_TRY_DECL(
-      expression,
-      parseExpression(Context(FieldContext(
-          BinASTInterfaceAndField::ExpressionStatement__Expression))));
+  BINJS_MOZ_TRY_DECL(expression, parseExpression(fieldContext++));
 
   BINJS_TRY_DECL(result,
                  handler_.newExprStatement(expression, tokenizer_->offset()));
   return result;
 }
 
 template <typename Tok>
 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceForInOfBinding(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
     const Context& context) {
   MOZ_ASSERT(kind == BinASTKind::ForInOfBinding);
   BINJS_TRY(CheckRecursionLimit(cx_));
+  Context fieldContext = Context::firstField(kind);
 
 #if defined(DEBUG)
   const BinASTField expected_fields[2] = {BinASTField::Kind,
                                           BinASTField::Binding};
   MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif  // defined(DEBUG)
   AutoVariableDeclarationKind kindGuard(this);
 
-  BINJS_MOZ_TRY_DECL(
-      kind_, parseVariableDeclarationKind(Context(
-                 FieldContext(BinASTInterfaceAndField::ForInOfBinding__Kind))));
-
-  BINJS_MOZ_TRY_DECL(binding,
-                     parseBinding(Context(FieldContext(
-                         BinASTInterfaceAndField::ForInOfBinding__Binding))));
+  BINJS_MOZ_TRY_DECL(kind_, parseVariableDeclarationKind(fieldContext++));
+
+  BINJS_MOZ_TRY_DECL(binding, parseBinding(fieldContext++));
 
   // Restored by `kindGuard`.
   variableDeclarationKind_ = kind_;
   MOZ_TRY(
       checkBinding(binding->template as<NameNode>().atom()->asPropertyName()));
   ParseNodeKind pnk;
   switch (kind_) {
     case VariableDeclarationKind::Var:
@@ -3169,41 +3028,37 @@ JS::Result<ParseNode*> BinASTParser<Tok>
 }
 
 template <typename Tok>
 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceForInStatement(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
     const Context& context) {
   MOZ_ASSERT(kind == BinASTKind::ForInStatement);
   BINJS_TRY(CheckRecursionLimit(cx_));
+  Context fieldContext = Context::firstField(kind);
 
 #if defined(DEBUG)
   const BinASTField expected_fields[3] = {BinASTField::Left, BinASTField::Right,
                                           BinASTField::Body};
   MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif  // defined(DEBUG)
   ParseContext::Statement stmt(pc_, 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_, pc_, usedNames_);
   BINJS_TRY(scope.init(pc_));
 
-  BINJS_MOZ_TRY_DECL(
-      left, parseForInOfBindingOrAssignmentTarget(Context(
-                FieldContext(BinASTInterfaceAndField::ForInStatement__Left))));
-
-  BINJS_MOZ_TRY_DECL(right,
-                     parseExpression(Context(FieldContext(
-                         BinASTInterfaceAndField::ForInStatement__Right))));
-
-  BINJS_MOZ_TRY_DECL(
-      body, parseStatement(Context(
-                FieldContext(BinASTInterfaceAndField::ForInStatement__Body))));
+  BINJS_MOZ_TRY_DECL(left,
+                     parseForInOfBindingOrAssignmentTarget(fieldContext++));
+
+  BINJS_MOZ_TRY_DECL(right, parseExpression(fieldContext++));
+
+  BINJS_MOZ_TRY_DECL(body, parseStatement(fieldContext++));
 
   BINJS_TRY_DECL(forHead,
                  handler_.newForInOrOfHead(ParseNodeKind::ForIn, left, right,
                                            tokenizer_->pos(start)));
   ParseNode* result;
   BINJS_TRY_VAR(result, handler_.newForStatement(start, forHead, body,
                                                  /* iflags = */ 0));
 
@@ -3223,44 +3078,40 @@ JS::Result<ParseNode*> BinASTParser<Tok>
 }
 
 template <typename Tok>
 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceForStatement(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
     const Context& context) {
   MOZ_ASSERT(kind == BinASTKind::ForStatement);
   BINJS_TRY(CheckRecursionLimit(cx_));
+  Context fieldContext = Context::firstField(kind);
 
 #if defined(DEBUG)
   const BinASTField expected_fields[4] = {BinASTField::Init, BinASTField::Test,
                                           BinASTField::Update,
                                           BinASTField::Body};
   MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif  // defined(DEBUG)
   ParseContext::Statement stmt(pc_, 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_, pc_, usedNames_);
   BINJS_TRY(scope.init(pc_));
 
   BINJS_MOZ_TRY_DECL(
-      init, parseOptionalVariableDeclarationOrExpression(Context(
-                FieldContext(BinASTInterfaceAndField::ForStatement__Init))));
-
-  BINJS_MOZ_TRY_DECL(test, parseOptionalExpression(Context(FieldContext(
-                               BinASTInterfaceAndField::ForStatement__Test))));
-
-  BINJS_MOZ_TRY_DECL(update,
-                     parseOptionalExpression(Context(FieldContext(
-                         BinASTInterfaceAndField::ForStatement__Update))));
-
-  BINJS_MOZ_TRY_DECL(body, parseStatement(Context(FieldContext(
-                               BinASTInterfaceAndField::ForStatement__Body))));
+      init, parseOptionalVariableDeclarationOrExpression(fieldContext++));
+
+  BINJS_MOZ_TRY_DECL(test, parseOptionalExpression(fieldContext++));
+
+  BINJS_MOZ_TRY_DECL(update, parseOptionalExpression(fieldContext++));
+
+  BINJS_MOZ_TRY_DECL(body, parseStatement(fieldContext++));
 
   BINJS_TRY_DECL(
       forHead, handler_.newForHead(init, test, update, tokenizer_->pos(start)));
   ParseNode* result;
   BINJS_TRY_VAR(result, handler_.newForStatement(start, forHead, body,
                                                  /* iflags = */ 0));
 
   if (!scope.isEmpty()) {
@@ -3296,30 +3147,27 @@ JS::Result<ListNode*> BinASTParser<Tok>:
 }
 
 template <typename Tok>
 JS::Result<ListNode*> BinASTParser<Tok>::parseInterfaceFormalParameters(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
     const Context& context) {
   MOZ_ASSERT(kind == BinASTKind::FormalParameters);
   BINJS_TRY(CheckRecursionLimit(cx_));
+  Context fieldContext = Context::firstField(kind);
 
 #if defined(DEBUG)
   const BinASTField expected_fields[2] = {BinASTField::Items,
                                           BinASTField::Rest};
   MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif  // defined(DEBUG)
 
-  BINJS_MOZ_TRY_DECL(items,
-                     parseListOfParameter(Context(FieldContext(
-                         BinASTInterfaceAndField::FormalParameters__Items))));
-
-  BINJS_MOZ_TRY_DECL(rest,
-                     parseOptionalBinding(Context(FieldContext(
-                         BinASTInterfaceAndField::FormalParameters__Rest))));
+  BINJS_MOZ_TRY_DECL(items, parseListOfParameter(fieldContext++));
+
+  BINJS_MOZ_TRY_DECL(rest, parseOptionalBinding(fieldContext++));
 
   auto result = items;
   if (rest) {
     return raiseError(
         "Rest parameter is not supported in this preview release");
   }
   return result;
 }
@@ -3357,62 +3205,48 @@ JS::Result<Ok> BinASTParser<Tok>::parseF
 
 template <typename Tok>
 JS::Result<Ok> BinASTParser<Tok>::parseInterfaceFunctionExpressionContents(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
     uint32_t funLength, ListNode** paramsOut, ListNode** bodyOut,
     const Context& context) {
   MOZ_ASSERT(kind == BinASTKind::FunctionExpressionContents);
   BINJS_TRY(CheckRecursionLimit(cx_));
+  Context fieldContext = Context::firstField(kind);
 
 #if defined(DEBUG)
   const BinASTField expected_fields[6] = {BinASTField::IsFunctionNameCaptured,
                                           BinASTField::IsThisCaptured,
                                           BinASTField::ParameterScope,
                                           BinASTField::Params,
                                           BinASTField::BodyScope,
                                           BinASTField::Body};
   MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif  // defined(DEBUG)
 
-  BINJS_MOZ_TRY_DECL(
-      isFunctionNameCaptured,
-      tokenizer_->readBool(Context(FieldContext(
-          BinASTInterfaceAndField::
-              FunctionExpressionContents__IsFunctionNameCaptured))));
+  BINJS_MOZ_TRY_DECL(isFunctionNameCaptured,
+                     tokenizer_->readBool(fieldContext++));
   // Per spec, isFunctionNameCaptured can be true for anonymous
   // function.  Check isFunctionNameCaptured only for named
   // function.
   if (pc_->functionBox()->isNamedLambda() && isFunctionNameCaptured) {
     captureFunctionName();
   }
-  BINJS_MOZ_TRY_DECL(isThisCaptured,
-                     tokenizer_->readBool(Context(FieldContext(
-                         BinASTInterfaceAndField::
-                             FunctionExpressionContents__IsThisCaptured))));
+  BINJS_MOZ_TRY_DECL(isThisCaptured, tokenizer_->readBool(fieldContext++));
   // TODO: Use this in BinASTParser::buildFunction.
   (void)isThisCaptured;
   Rooted<GCVector<JSAtom*>> positionalParams(cx_, GCVector<JSAtom*>(cx_));
-  MOZ_TRY(parseAssertedParameterScope(
-      &positionalParams,
-      Context(FieldContext(BinASTInterfaceAndField::
-                               FunctionExpressionContents__ParameterScope))));
-
-  BINJS_MOZ_TRY_DECL(
-      params,
-      parseFormalParameters(Context(FieldContext(
-          BinASTInterfaceAndField::FunctionExpressionContents__Params))));
+  MOZ_TRY(parseAssertedParameterScope(&positionalParams, fieldContext++));
+
+  BINJS_MOZ_TRY_DECL(params, parseFormalParameters(fieldContext++));
   MOZ_TRY(checkFunctionLength(funLength));
   MOZ_TRY(checkPositionalParameterIndices(positionalParams, params));
-  MOZ_TRY(parseAssertedVarScope(Context(FieldContext(
-      BinASTInterfaceAndField::FunctionExpressionContents__BodyScope))));
-
-  BINJS_MOZ_TRY_DECL(
-      body, parseFunctionBody(Context(FieldContext(
-                BinASTInterfaceAndField::FunctionExpressionContents__Body))));
+  MOZ_TRY(parseAssertedVarScope(fieldContext++));
+
+  BINJS_MOZ_TRY_DECL(body, parseFunctionBody(fieldContext++));
 
   *paramsOut = params;
   *bodyOut = body;
   auto result = Ok();
   return result;
 }
 
 /*
@@ -3447,47 +3281,37 @@ JS::Result<Ok> BinASTParser<Tok>::parseF
 
 template <typename Tok>
 JS::Result<Ok> BinASTParser<Tok>::parseInterfaceFunctionOrMethodContents(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
     uint32_t funLength, ListNode** paramsOut, ListNode** bodyOut,
     const Context& context) {
   MOZ_ASSERT(kind == BinASTKind::FunctionOrMethodContents);
   BINJS_TRY(CheckRecursionLimit(cx_));
+  Context fieldContext = Context::firstField(kind);
 
 #if defined(DEBUG)
   const BinASTField expected_fields[5] = {
       BinASTField::IsThisCaptured, BinASTField::ParameterScope,
       BinASTField::Params, BinASTField::BodyScope, BinASTField::Body};
   MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif  // defined(DEBUG)
 
-  BINJS_MOZ_TRY_DECL(
-      isThisCaptured,
-      tokenizer_->readBool(Context(FieldContext(
-          BinASTInterfaceAndField::FunctionOrMethodContents__IsThisCaptured))));
+  BINJS_MOZ_TRY_DECL(isThisCaptured, tokenizer_->readBool(fieldContext++));
   // TODO: Use this in BinASTParser::buildFunction.
   (void)isThisCaptured;
   Rooted<GCVector<JSAtom*>> positionalParams(cx_, GCVector<JSAtom*>(cx_));
-  MOZ_TRY(parseAssertedParameterScope(
-      &positionalParams,
-      Context(FieldContext(
-          BinASTInterfaceAndField::FunctionOrMethodContents__ParameterScope))));
-
-  BINJS_MOZ_TRY_DECL(
-      params, parseFormalParameters(Context(FieldContext(
-                  BinASTInterfaceAndField::FunctionOrMethodContents__Params))));
+  MOZ_TRY(parseAssertedParameterScope(&positionalParams, fieldContext++));
+
+  BINJS_MOZ_TRY_DECL(params, parseFormalParameters(fieldContext++));
   MOZ_TRY(checkFunctionLength(funLength));
   MOZ_TRY(checkPositionalParameterIndices(positionalParams, params));
-  MOZ_TRY(parseAssertedVarScope(Context(FieldContext(
-      BinASTInterfaceAndField::FunctionOrMethodContents__BodyScope))));
-
-  BINJS_MOZ_TRY_DECL(
-      body, parseFunctionBody(Context(FieldContext(
-                BinASTInterfaceAndField::FunctionOrMethodContents__Body))));
+  MOZ_TRY(parseAssertedVarScope(fieldContext++));
+
+  BINJS_MOZ_TRY_DECL(body, parseFunctionBody(fieldContext++));
 
   *paramsOut = params;
   *bodyOut = body;
   auto result = Ok();
   return result;
 }
 
 /*
@@ -3521,36 +3345,31 @@ JS::Result<Ok> BinASTParser<Tok>::parseG
 
 template <typename Tok>
 JS::Result<Ok> BinASTParser<Tok>::parseInterfaceGetterContents(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
     uint32_t funLength, ListNode** paramsOut, ListNode** bodyOut,
     const Context& context) {
   MOZ_ASSERT(kind == BinASTKind::GetterContents);
   BINJS_TRY(CheckRecursionLimit(cx_));
+  Context fieldContext = Context::firstField(kind);
 
 #if defined(DEBUG)
   const BinASTField expected_fields[3] = {
       BinASTField::IsThisCaptured, BinASTField::BodyScope, BinASTField::Body};
   MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif  // defined(DEBUG)
 
-  BINJS_MOZ_TRY_DECL(
-      isThisCaptured,
-      tokenizer_->readBool(Context(FieldContext(
-          BinASTInterfaceAndField::GetterContents__IsThisCaptured))));
+  BINJS_MOZ_TRY_DECL(isThisCaptured, tokenizer_->readBool(fieldContext++));
   // TODO: Use this in BinASTParser::buildFunction.
   (void)isThisCaptured;
-  MOZ_TRY(parseAssertedVarScope(Context(
-      FieldContext(BinASTInterfaceAndField::GetterContents__BodyScope))));
+  MOZ_TRY(parseAssertedVarScope(fieldContext++));
 
   BINJS_TRY_DECL(params, handler_.newParamsBody(tokenizer_->pos(start)));
-  BINJS_MOZ_TRY_DECL(
-      body, parseFunctionBody(Context(
-                FieldContext(BinASTInterfaceAndField::GetterContents__Body))));
+  BINJS_MOZ_TRY_DECL(body, parseFunctionBody(fieldContext++));
 
   *paramsOut = params;
   *bodyOut = body;
   auto result = Ok();
   return result;
 }
 
 /*
@@ -3578,85 +3397,79 @@ JS::Result<ParseNode*> BinASTParser<Tok>
 }
 
 template <typename Tok>
 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceIdentifierExpression(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
     const Context& context) {
   MOZ_ASSERT(kind == BinASTKind::IdentifierExpression);
   BINJS_TRY(CheckRecursionLimit(cx_));
+  Context fieldContext = Context::firstField(kind);
 
 #if defined(DEBUG)
   const BinASTField expected_fields[1] = {BinASTField::Name};
   MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif  // defined(DEBUG)
 
   RootedAtom name(cx_);
-  MOZ_TRY_VAR(name, tokenizer_->readIdentifierName(Context(FieldContext(
-                        BinASTInterfaceAndField::IdentifierExpression__Name))));
+  MOZ_TRY_VAR(name, tokenizer_->readIdentifierName(fieldContext++));
 
   BINJS_TRY(usedNames_.noteUse(cx_, name, pc_->scriptId(),
                                pc_->innermostScope()->id()));
   BINJS_TRY_DECL(result, handler_.newName(name->asPropertyName(),
                                           tokenizer_->pos(start), cx_));
   return result;
 }
 
 template <typename Tok>
 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceIfStatement(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
     const Context& context) {
   MOZ_ASSERT(kind == BinASTKind::IfStatement);
   BINJS_TRY(CheckRecursionLimit(cx_));
+  Context fieldContext = Context::firstField(kind);
 
 #if defined(DEBUG)
   const BinASTField expected_fields[3] = {
       BinASTField::Test, BinASTField::Consequent, BinASTField::Alternate};
   MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif  // defined(DEBUG)
 
-  BINJS_MOZ_TRY_DECL(test, parseExpression(Context(FieldContext(
-                               BinASTInterfaceAndField::IfStatement__Test))));
-
-  BINJS_MOZ_TRY_DECL(consequent,
-                     parseStatement(Context(FieldContext(
-                         BinASTInterfaceAndField::IfStatement__Consequent))));
-
-  BINJS_MOZ_TRY_DECL(alternate,
-                     parseOptionalStatement(Context(FieldContext(
-                         BinASTInterfaceAndField::IfStatement__Alternate))));
+  BINJS_MOZ_TRY_DECL(test, parseExpression(fieldContext++));
+
+  BINJS_MOZ_TRY_DECL(consequent, parseStatement(fieldContext++));
+
+  BINJS_MOZ_TRY_DECL(alternate, parseOptionalStatement(fieldContext++));
 
   BINJS_TRY_DECL(result,
                  handler_.newIfStatement(start, test, consequent, alternate));
   return result;
 }
 
 template <typename Tok>
 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceLabelledStatement(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
     const Context& context) {
   MOZ_ASSERT(kind == BinASTKind::LabelledStatement);
   BINJS_TRY(CheckRecursionLimit(cx_));
+  Context fieldContext = Context::firstField(kind);
 
 #if defined(DEBUG)
   const BinASTField expected_fields[2] = {BinASTField::Label,
                                           BinASTField::Body};
   MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif  // defined(DEBUG)
 
   RootedAtom label(cx_);
-  MOZ_TRY_VAR(label, tokenizer_->readAtom(Context(FieldContext(
-                         BinASTInterfaceAndField::LabelledStatement__Label))));
+  MOZ_TRY_VAR(label, tokenizer_->readAtom(fieldContext++));
   if (!IsIdentifier(label)) {
     return raiseError("Invalid identifier");
   }
   ParseContext::LabelStatement stmt(pc_, label);
-  BINJS_MOZ_TRY_DECL(body,
-                     parseStatement(Context(FieldContext(
-                         BinASTInterfaceAndField::LabelledStatement__Body))));
+  BINJS_MOZ_TRY_DECL(body, parseStatement(fieldContext++));
 
   BINJS_TRY_DECL(result, handler_.newLabeledStatement(label->asPropertyName(),
                                                       body, start));
   return result;
 }
 
 template <typename Tok>
 JS::Result<ParseNode*>
@@ -3679,58 +3492,44 @@ BinASTParser<Tok>::parseInterfaceLazyArr
 }
 
 template <typename Tok>
 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceLazyFunctionDeclaration(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
     const Context& context) {
   MOZ_ASSERT(kind == BinASTKind::LazyFunctionDeclaration);
   BINJS_TRY(CheckRecursionLimit(cx_));
+  Context fieldContext = Context::firstField(kind);
 
 #if defined(DEBUG)
   const BinASTField expected_fields[7] = {
       BinASTField::IsAsync, BinASTField::IsGenerator, BinASTField::Name,
       BinASTField::Length,  BinASTField::Directives,  BinASTField::ContentsSkip,
       BinASTField::Contents};
   MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif  // defined(DEBUG)
   const auto syntax = FunctionSyntaxKind::Statement;
 
-  BINJS_MOZ_TRY_DECL(
-      isAsync,
-      tokenizer_->readBool(Context(FieldContext(
-          BinASTInterfaceAndField::LazyFunctionDeclaration__IsAsync))));
+  BINJS_MOZ_TRY_DECL(isAsync, tokenizer_->readBool(fieldContext++));
   if (isAsync) {
     return raiseError(
         "Async function is not supported in this preview release");
   }
-  BINJS_MOZ_TRY_DECL(
-      isGenerator,
-      tokenizer_->readBool(Context(FieldContext(
-          BinASTInterfaceAndField::LazyFunctionDeclaration__IsGenerator))));
+  BINJS_MOZ_TRY_DECL(isGenerator, tokenizer_->readBool(fieldContext++));
   if (isGenerator) {
     return raiseError("Generator is not supported in this preview release");
   }
-  BINJS_MOZ_TRY_DECL(
-      name, parseBindingIdentifier(Context(FieldContext(
-                BinASTInterfaceAndField::LazyFunctionDeclaration__Name))));
-
-  BINJS_MOZ_TRY_DECL(
-      length, tokenizer_->readUnsignedLong(Context(FieldContext(
-                  BinASTInterfaceAndField::LazyFunctionDeclaration__Length))));
-
-  BINJS_MOZ_TRY_DECL(
-      directives,
-      parseListOfDirective(Context(FieldContext(
-          BinASTInterfaceAndField::LazyFunctionDeclaration__Directives))));
-
-  BINJS_MOZ_TRY_DECL(
-      contentsSkip,
-      tokenizer_->readSkippableSubTree(Context(FieldContext(
-          BinASTInterfaceAndField::LazyFunctionDeclaration__ContentsSkip))));
+  BINJS_MOZ_TRY_DECL(name, parseBindingIdentifier(fieldContext++));
+
+  BINJS_MOZ_TRY_DECL(length, tokenizer_->readUnsignedLong(fieldContext++));
+
+  BINJS_MOZ_TRY_DECL(directives, parseListOfDirective(fieldContext++));
+
+  BINJS_MOZ_TRY_DECL(contentsSkip,
+                     tokenizer_->readSkippableSubTree(fieldContext++));
   // Don't parse the contents until we delazify.
 
   BINJS_MOZ_TRY_DECL(funbox,
                      buildFunctionBox(isGenerator ? GeneratorKind::Generator
                                                   : GeneratorKind::NotGenerator,
                                       isAsync ? FunctionAsyncKind::AsyncFunction
                                               : FunctionAsyncKind::SyncFunction,
                                       syntax, name));
@@ -3761,57 +3560,44 @@ JS::Result<ParseNode*> BinASTParser<Tok>
 }
 
 template <typename Tok>
 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceLazyFunctionExpression(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
     const Context& context) {
   MOZ_ASSERT(kind == BinASTKind::LazyFunctionExpression);
   BINJS_TRY(CheckRecursionLimit(cx_));
+  Context fieldContext = Context::firstField(kind);
 
 #if defined(DEBUG)
   const BinASTField expected_fields[7] = {
       BinASTField::IsAsync, BinASTField::IsGenerator, BinASTField::Name,
       BinASTField::Length,  BinASTField::Directives,  BinASTField::ContentsSkip,
       BinASTField::Contents};
   MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif  // defined(DEBUG)
   const auto syntax = FunctionSyntaxKind::Expression;
 
-  BINJS_MOZ_TRY_DECL(
-      isAsync, tokenizer_->readBool(Context(FieldContext(
-                   BinASTInterfaceAndField::LazyFunctionExpression__IsAsync))));
+  BINJS_MOZ_TRY_DECL(isAsync, tokenizer_->readBool(fieldContext++));
   if (isAsync) {
     return raiseError(
         "Async function is not supported in this preview release");
   }
-  BINJS_MOZ_TRY_DECL(
-      isGenerator,
-      tokenizer_->readBool(Context(FieldContext(
-          BinASTInterfaceAndField::LazyFunctionExpression__IsGenerator))));
+  BINJS_MOZ_TRY_DECL(isGenerator, tokenizer_->readBool(fieldContext++));
   if (isGenerator) {
     return raiseError("Generator is not supported in this preview release");
   }
-  BINJS_MOZ_TRY_DECL(
-      name, parseOptionalBindingIdentifier(Context(FieldContext(
-                BinASTInterfaceAndField::LazyFunctionExpression__Name))));
-
-  BINJS_MOZ_TRY_DECL(
-      length, tokenizer_->readUnsignedLong(Context(FieldContext(
-                  BinASTInterfaceAndField::LazyFunctionExpression__Length))));
-
-  BINJS_MOZ_TRY_DECL(
-      directives,
-      parseListOfDirective(Context(FieldContext(
-          BinASTInterfaceAndField::LazyFunctionExpression__Directives))));
-
-  BINJS_MOZ_TRY_DECL(
-      contentsSkip,
-      tokenizer_->readSkippableSubTree(Context(FieldContext(
-          BinASTInterfaceAndField::LazyFunctionExpression__ContentsSkip))));
+  BINJS_MOZ_TRY_DECL(name, parseOptionalBindingIdentifier(fieldContext++));
+
+  BINJS_MOZ_TRY_DECL(length, tokenizer_->readUnsignedLong(fieldContext++));
+
+  BINJS_MOZ_TRY_DECL(directives, parseListOfDirective(fieldContext++));
+
+  BINJS_MOZ_TRY_DECL(contentsSkip,
+                     tokenizer_->readSkippableSubTree(fieldContext++));
   // Don't parse the contents until we delazify.
 
   BINJS_MOZ_TRY_DECL(funbox,
                      buildFunctionBox(isGenerator ? GeneratorKind::Generator
                                                   : GeneratorKind::NotGenerator,
                                       isAsync ? FunctionAsyncKind::AsyncFunction
                                               : FunctionAsyncKind::SyncFunction,
                                       syntax, name));
@@ -3867,25 +3653,24 @@ JS::Result<ParseNode*> BinASTParser<Tok>
 
 template <typename Tok>
 JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceLiteralBooleanExpression(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
     const Context& context) {
   MOZ_ASSERT(kind == BinASTKind::LiteralBooleanExpression);
   BINJS_TRY(CheckRecursionLimit(cx_));
+  Context fieldContext = Context::firstField(kind);
 
 #if defined(DEBUG)
   const BinASTField expected_fields[1] = {BinASTField::Value};
   MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif  // defined(DEBUG)
 
-  BINJS_MOZ_TRY_DECL(
-      value, tokenizer_->readBool(Context(FieldContext(
-                 BinASTInterfaceAndField::LiteralBooleanExpression__Value))));
+  BINJS_MOZ_TRY_DECL(value, tokenizer_->readBool(fieldContext++));
 
   BINJS_TRY_DECL(result,
                  handler_.newBooleanLiteral(value, tokenizer_->pos(start)));
   return result;
 }
 
 template <typename Tok>
 JS::Result<ParseNode*>
@@ -3911,47 +3696,45 @@ JS::Result<ParseNode*> BinASTParser<Tok>
 
 template <typename Tok>
 JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceLiteralNumericExpression(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
     const Context& context) {
   MOZ_ASSERT(kind == BinASTKind::LiteralNumericExpression);
   BINJS_TRY(CheckRecursionLimit(cx_));
+  Context fieldContext = Context::firstField(kind);
 
 #if defined(DEBUG)
   const BinASTField expected_fields[1] = {BinASTField::Value};
   MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif  // defined(DEBUG)
 
-  BINJS_MOZ_TRY_DECL(
-      value, tokenizer_->readDouble(Context(FieldContext(
-                 BinASTInterfaceAndField::LiteralNumericExpression__Value))));
+  BINJS_MOZ_TRY_DECL(value, tokenizer_->readDouble(fieldContext++));
 
   BINJS_TRY_DECL(result, handler_.newNumber(value, DecimalPoint::HasDecimal,
                                             tokenizer_->pos(start)));
   return result;
 }
 
 template <typename Tok>
 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceLiteralPropertyName(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
     const Context& context) {
   MOZ_ASSERT(kind == BinASTKind::LiteralPropertyName);
   BINJS_TRY(CheckRecursionLimit(cx_));
+  Context fieldContext = Context::firstField(kind);
 
 #if defined(DEBUG)
   const BinASTField expected_fields[1] = {BinASTField::Value};
   MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif  // defined(DEBUG)
 
   RootedAtom value(cx_);
-  MOZ_TRY_VAR(value,
-              tokenizer_->readAtom(Context(FieldContext(
-                  BinASTInterfaceAndField::LiteralPropertyName__Value))));
+  MOZ_TRY_VAR(value, tokenizer_->readAtom(fieldContext++));
 
   ParseNode* result;
   uint32_t index;
   if (value->isIndex(&index)) {
     BINJS_TRY_VAR(result,
                   handler_.newNumber(index, NoDecimal,
                                      TokenPos(start, tokenizer_->offset())));
   } else {
@@ -3962,31 +3745,28 @@ JS::Result<ParseNode*> BinASTParser<Tok>
 }
 
 template <typename Tok>
 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceLiteralRegExpExpression(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
     const Context& context) {
   MOZ_ASSERT(kind == BinASTKind::LiteralRegExpExpression);
   BINJS_TRY(CheckRecursionLimit(cx_));
+  Context fieldContext = Context::firstField(kind);
 
 #if defined(DEBUG)
   const BinASTField expected_fields[2] = {BinASTField::Pattern,
                                           BinASTField::Flags};
   MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif  // defined(DEBUG)
 
   RootedAtom pattern(cx_);
-  MOZ_TRY_VAR(pattern,
-              tokenizer_->readAtom(Context(FieldContext(
-                  BinASTInterfaceAndField::LiteralRegExpExpression__Pattern))));
+  MOZ_TRY_VAR(pattern, tokenizer_->readAtom(fieldContext++));
   Chars flags(cx_);
-  MOZ_TRY(tokenizer_->readChars(
-      flags,
-      Context(FieldContext(BinASTInterfaceAndField::BreakStatement__Label))));
+  MOZ_TRY(tokenizer_->readChars(flags, fieldContext++));
 
   RegExpFlags reflags = RegExpFlag::NoFlags;
   for (auto c : flags) {
     if (c == 'g' && !reflags.global()) {
       reflags |= RegExpFlag::Global;
     } else if (c == 'i' && !reflags.ignoreCase()) {
       reflags |= RegExpFlag::IgnoreCase;
     } else if (c == 'm' && !reflags.multiline()) {
@@ -4010,26 +3790,25 @@ JS::Result<ParseNode*> BinASTParser<Tok>
 }
 
 template <typename Tok>
 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceLiteralStringExpression(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
     const Context& context) {
   MOZ_ASSERT(kind == BinASTKind::LiteralStringExpression);
   BINJS_TRY(CheckRecursionLimit(cx_));
+  Context fieldContext = Context::firstField(kind);
 
 #if defined(DEBUG)
   const BinASTField expected_fields[1] = {BinASTField::Value};
   MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif  // defined(DEBUG)
 
   RootedAtom value(cx_);
-  MOZ_TRY_VAR(value,
-              tokenizer_->readAtom(Context(FieldContext(
-                  BinASTInterfaceAndField::LiteralStringExpression__Value))));
+  MOZ_TRY_VAR(value, tokenizer_->readAtom(fieldContext++));
 
   BINJS_TRY_DECL(result,
                  handler_.newStringLiteral(value, tokenizer_->pos(start)));
   return result;
 }
 
 template <typename Tok>
 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceModule(
@@ -4040,30 +3819,27 @@ JS::Result<ParseNode*> BinASTParser<Tok>
 }
 
 template <typename Tok>
 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceNewExpression(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
     const Context& context) {
   MOZ_ASSERT(kind == BinASTKind::NewExpression);
   BINJS_TRY(CheckRecursionLimit(cx_));
+  Context fieldContext = Context::firstField(kind);
 
 #if defined(DEBUG)
   const BinASTField expected_fields[2] = {BinASTField::Callee,
                                           BinASTField::Arguments};
   MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif  // defined(DEBUG)
 
-  BINJS_MOZ_TRY_DECL(callee,
-                     parseExpression(Context(FieldContext(
-                         BinASTInterfaceAndField::NewExpression__Callee))));
-
-  BINJS_MOZ_TRY_DECL(arguments,
-                     parseArguments(Context(FieldContext(
-                         BinASTInterfaceAndField::NewExpression__Arguments))));
+  BINJS_MOZ_TRY_DECL(callee, parseExpression(fieldContext++));
+
+  BINJS_MOZ_TRY_DECL(arguments, parseArguments(fieldContext++));
 
   BINJS_TRY_DECL(result,
                  handler_.newNewExpression(tokenizer_->pos(start).begin, callee,
                                            arguments, /* isSpread = */ false));
   return result;
 }
 
 template <typename Tok>
@@ -4093,80 +3869,74 @@ JS::Result<ParseNode*> BinASTParser<Tok>
 }
 
 template <typename Tok>
 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceObjectExpression(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
     const Context& context) {
   MOZ_ASSERT(kind == BinASTKind::ObjectExpression);
   BINJS_TRY(CheckRecursionLimit(cx_));
+  Context fieldContext = Context::firstField(kind);
 
 #if defined(DEBUG)
   const BinASTField expected_fields[1] = {BinASTField::Properties};
   MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif  // defined(DEBUG)
 
-  BINJS_MOZ_TRY_DECL(
-      properties, parseListOfObjectProperty(Context(FieldContext(
-                      BinASTInterfaceAndField::ObjectExpression__Properties))));
+  BINJS_MOZ_TRY_DECL(properties, parseListOfObjectProperty(fieldContext++));
 
   auto result = properties;
   return result;
 }
 
 template <typename Tok>
 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceReturnStatement(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
     const Context& context) {
   MOZ_ASSERT(kind == BinASTKind::ReturnStatement);
   BINJS_TRY(CheckRecursionLimit(cx_));
+  Context fieldContext = Context::firstField(kind);
 
 #if defined(DEBUG)
   const BinASTField expected_fields[1] = {BinASTField::Expression};
   MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif  // defined(DEBUG)
   if (!pc_->isFunctionBox()) {
     // Return statements are permitted only inside functions.
     return raiseInvalidKind("Toplevel Statement", kind);
   }
 
   pc_->functionBox()->usesReturn = true;
 
-  BINJS_MOZ_TRY_DECL(
-      expression, parseOptionalExpression(Context(FieldContext(
-                      BinASTInterfaceAndField::ReturnStatement__Expression))));
+  BINJS_MOZ_TRY_DECL(expression, parseOptionalExpression(fieldContext++));
 
   BINJS_TRY_DECL(
       result, handler_.newReturnStatement(expression, tokenizer_->pos(start)));
   return result;
 }
 
 template <typename Tok>
 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceScript(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
     const Context& context) {
   MOZ_ASSERT(kind == BinASTKind::Script);
   BINJS_TRY(CheckRecursionLimit(cx_));
+  Context fieldContext = Context::firstField(kind);
 
 #if defined(DEBUG)
   const BinASTField expected_fields[3] = {
       BinASTField::Scope, BinASTField::Directives, BinASTField::Statements};
   MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif  // defined(DEBUG)
 
-  MOZ_TRY(parseAssertedScriptGlobalScope(
-      Context(FieldContext(BinASTInterfaceAndField::Script__Scope))));
-
-  BINJS_MOZ_TRY_DECL(directives,
-                     parseListOfDirective(Context(FieldContext(
-                         BinASTInterfaceAndField::Script__Directives))));
+  MOZ_TRY(parseAssertedScriptGlobalScope(fieldContext++));
+
+  BINJS_MOZ_TRY_DECL(directives, parseListOfDirective(fieldContext++));
   forceStrictIfNecessary(pc_->sc(), directives);
-  BINJS_MOZ_TRY_DECL(statements,
-                     parseListOfStatement(Context(FieldContext(
-                         BinASTInterfaceAndField::Script__Statements))));
+  BINJS_MOZ_TRY_DECL(statements, parseListOfStatement(fieldContext++));
 
   MOZ_TRY(checkClosedVars(pc_->varScope()));
   MOZ_TRY(prependDirectivesToBody(/* body = */ statements, directives));
   auto result = statements;
   return result;
 }
 
 /*
@@ -4202,70 +3972,59 @@ JS::Result<Ok> BinASTParser<Tok>::parseS
 
 template <typename Tok>
 JS::Result<Ok> BinASTParser<Tok>::parseInterfaceSetterContents(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
     uint32_t funLength, ListNode** paramsOut, ListNode** bodyOut,
     const Context& context) {
   MOZ_ASSERT(kind == BinASTKind::SetterContents);
   BINJS_TRY(CheckRecursionLimit(cx_));
+  Context fieldContext = Context::firstField(kind);
 
 #if defined(DEBUG)
   const BinASTField expected_fields[5] = {
       BinASTField::IsThisCaptured, BinASTField::ParameterScope,
       BinASTField::Param, BinASTField::BodyScope, BinASTField::Body};
   MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif  // defined(DEBUG)
 
-  BINJS_MOZ_TRY_DECL(
-      isThisCaptured,
-      tokenizer_->readBool(Context(FieldContext(
-          BinASTInterfaceAndField::SetterContents__IsThisCaptured))));
+  BINJS_MOZ_TRY_DECL(isThisCaptured, tokenizer_->readBool(fieldContext++));
   // TODO: Use this in BinASTParser::buildFunction.
   (void)isThisCaptured;
   Rooted<GCVector<JSAtom*>> positionalParams(cx_, GCVector<JSAtom*>(cx_));
-  MOZ_TRY(parseAssertedParameterScope(
-      &positionalParams,
-      Context(FieldContext(
-          BinASTInterfaceAndField::SetterContents__ParameterScope))));
-
-  BINJS_MOZ_TRY_DECL(param,
-                     parseParameter(Context(FieldContext(
-                         BinASTInterfaceAndField::SetterContents__Param))));
+  MOZ_TRY(parseAssertedParameterScope(&positionalParams, fieldContext++));
+
+  BINJS_MOZ_TRY_DECL(param, parseParameter(fieldContext++));
   BINJS_TRY_DECL(params, handler_.newParamsBody(param->pn_pos));
   handler_.addList(params, param);
   MOZ_TRY(checkPositionalParameterIndices(positionalParams, params));
-  MOZ_TRY(parseAssertedVarScope(Context(
-      FieldContext(BinASTInterfaceAndField::SetterContents__BodyScope))));
-
-  BINJS_MOZ_TRY_DECL(
-      body, parseFunctionBody(Context(
-                FieldContext(BinASTInterfaceAndField::SetterContents__Body))));
+  MOZ_TRY(parseAssertedVarScope(fieldContext++));
+
+  BINJS_MOZ_TRY_DECL(body, parseFunctionBody(fieldContext++));
 
   *paramsOut = params;
   *bodyOut = body;
   auto result = Ok();
   return result;
 }
 
 template <typename Tok>
 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceShorthandProperty(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
     const Context& context) {
   MOZ_ASSERT(kind == BinASTKind::ShorthandProperty);
   BINJS_TRY(CheckRecursionLimit(cx_));
+  Context fieldContext = Context::firstField(kind);
 
 #if defined(DEBUG)
   const BinASTField expected_fields[1] = {BinASTField::Name};
   MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif  // defined(DEBUG)
 
-  BINJS_MOZ_TRY_DECL(name,
-                     parseIdentifierExpression(Context(FieldContext(
-                         BinASTInterfaceAndField::ShorthandProperty__Name))));
+  BINJS_MOZ_TRY_DECL(name, parseIdentifierExpression(fieldContext++));
 
   MOZ_ASSERT(name->isKind(ParseNodeKind::Name));
   MOZ_ASSERT(!handler_.isUsableAsObjectPropertyName(name));
   BINJS_TRY_DECL(propName, handler_.newObjectLiteralPropertyName(
                                name->template as<NameNode>().name(),
                                tokenizer_->pos(start)));
 
   BINJS_TRY_DECL(result,
@@ -4283,69 +4042,60 @@ JS::Result<ParseNode*> BinASTParser<Tok>
 
 template <typename Tok>
 JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceStaticMemberAssignmentTarget(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
     const Context& context) {
   MOZ_ASSERT(kind == BinASTKind::StaticMemberAssignmentTarget);
   BINJS_TRY(CheckRecursionLimit(cx_));
+  Context fieldContext = Context::firstField(kind);
 
 #if defined(DEBUG)
   const BinASTField expected_fields[2] = {BinASTField::Object,
                                           BinASTField::Property};
   MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif  // defined(DEBUG)
   size_t nameStart;
 
-  BINJS_MOZ_TRY_DECL(
-      object,
-      parseExpressionOrSuper(Context(FieldContext(
-          BinASTInterfaceAndField::StaticMemberAssignmentTarget__Object))));
+  BINJS_MOZ_TRY_DECL(object, parseExpressionOrSuper(fieldContext++));
 
   RootedAtom property(cx_);
   {
     nameStart = tokenizer_->offset();
-    MOZ_TRY_VAR(
-        property,
-        tokenizer_->readPropertyKey(Context(FieldContext(
-            BinASTInterfaceAndField::StaticMemberAssignmentTarget__Property))));
+    MOZ_TRY_VAR(property, tokenizer_->readPropertyKey(fieldContext++));
   }
 
   BINJS_TRY_DECL(name, handler_.newPropertyName(property->asPropertyName(),
                                                 tokenizer_->pos(nameStart)));
   BINJS_TRY_DECL(result, handler_.newPropertyAccess(object, name));
   return result;
 }
 
 template <typename Tok>
 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceStaticMemberExpression(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
     const Context& context) {
   MOZ_ASSERT(kind == BinASTKind::StaticMemberExpression);
   BINJS_TRY(CheckRecursionLimit(cx_));
+  Context fieldContext = Context::firstField(kind);
 
 #if defined(DEBUG)
   const BinASTField expected_fields[2] = {BinASTField::Object,
                                           BinASTField::Property};
   MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif  // defined(DEBUG)
   size_t nameStart;
 
-  BINJS_MOZ_TRY_DECL(
-      object, parseExpressionOrSuper(Context(FieldContext(
-                  BinASTInterfaceAndField::StaticMemberExpression__Object))));
+  BINJS_MOZ_TRY_DECL(object, parseExpressionOrSuper(fieldContext++));
 
   RootedAtom property(cx_);
   {
     nameStart = tokenizer_->offset();
-    MOZ_TRY_VAR(
-        property,
-        tokenizer_->readPropertyKey(Context(FieldContext(
-            BinASTInterfaceAndField::StaticMemberExpression__Property))));
+    MOZ_TRY_VAR(property, tokenizer_->readPropertyKey(fieldContext++));
   }
 
   BINJS_TRY_DECL(name, handler_.newPropertyName(property->asPropertyName(),
                                                 tokenizer_->pos(nameStart)));
   BINJS_TRY_DECL(result, handler_.newPropertyAccess(object, name));
   return result;
 }
 
@@ -4383,29 +4133,27 @@ JS::Result<CaseClause*> BinASTParser<Tok
 }
 
 template <typename Tok>
 JS::Result<CaseClause*> BinASTParser<Tok>::parseInterfaceSwitchCase(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
     const Context& context) {
   MOZ_ASSERT(kind == BinASTKind::SwitchCase);
   BINJS_TRY(CheckRecursionLimit(cx_));
+  Context fieldContext = Context::firstField(kind);
 
 #if defined(DEBUG)
   const BinASTField expected_fields[2] = {BinASTField::Test,
                                           BinASTField::Consequent};
   MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif  // defined(DEBUG)
 
-  BINJS_MOZ_TRY_DECL(test, parseExpression(Context(FieldContext(
-                               BinASTInterfaceAndField::SwitchCase__Test))));
-
-  BINJS_MOZ_TRY_DECL(consequent,
-                     parseListOfStatement(Context(FieldContext(
-                         BinASTInterfaceAndField::SwitchCase__Consequent))));
+  BINJS_MOZ_TRY_DECL(test, parseExpression(fieldContext++));
+
+  BINJS_MOZ_TRY_DECL(consequent, parseListOfStatement(fieldContext++));
 
   BINJS_TRY_DECL(result, handler_.newCaseOrDefault(start, test, consequent));
   return result;
 }
 
 /*
  interface SwitchDefault : Node {
     FrozenArray<Statement> consequent;
@@ -4431,92 +4179,76 @@ JS::Result<ParseNode*> BinASTParser<Tok>
 }
 
 template <typename Tok>
 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceSwitchDefault(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
     const Context& context) {
   MOZ_ASSERT(kind == BinASTKind::SwitchDefault);
   BINJS_TRY(CheckRecursionLimit(cx_));
+  Context fieldContext = Context::firstField(kind);
 
 #if defined(DEBUG)
   const BinASTField expected_fields[1] = {BinASTField::Consequent};
   MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif  // defined(DEBUG)
 
-  BINJS_MOZ_TRY_DECL(consequent,
-                     parseListOfStatement(Context(FieldContext(
-                         BinASTInterfaceAndField::SwitchDefault__Consequent))));
+  BINJS_MOZ_TRY_DECL(consequent, parseListOfStatement(fieldContext++));
 
   BINJS_TRY_DECL(result, handler_.newCaseOrDefault(start, nullptr, consequent));
   return result;
 }
 
 template <typename Tok>
 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceSwitchStatement(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
     const Context& context) {
   MOZ_ASSERT(kind == BinASTKind::SwitchStatement);
   BINJS_TRY(CheckRecursionLimit(cx_));
+  Context fieldContext = Context::firstField(kind);
 
 #if defined(DEBUG)
   const BinASTField expected_fields[2] = {BinASTField::Discriminant,
                                           BinASTField::Cases};
   MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif  // defined(DEBUG)
 
-  BINJS_MOZ_TRY_DECL(
-      discriminant,
-      parseExpression(Context(FieldContext(
-          BinASTInterfaceAndField::SwitchStatement__Discriminant))));
+  BINJS_MOZ_TRY_DECL(discriminant, parseExpression(fieldContext++));
   ParseContext::Statement stmt(pc_, StatementKind::Switch);
-  BINJS_MOZ_TRY_DECL(cases,
-                     parseListOfSwitchCase(Context(FieldContext(
-                         BinASTInterfaceAndField::SwitchStatement__Cases))));
+  BINJS_MOZ_TRY_DECL(cases, parseListOfSwitchCase(fieldContext++));
 
   BINJS_TRY_DECL(scope, handler_.newLexicalScope(nullptr, cases));
   BINJS_TRY_DECL(result, handler_.newSwitchStatement(start, discriminant, scope,
                                                      /* hasDefault = */ false));
   return result;
 }
 
 template <typename Tok>
 JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceSwitchStatementWithDefault(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
     const Context& context) {
   MOZ_ASSERT(kind == BinASTKind::SwitchStatementWithDefault);
   BINJS_TRY(CheckRecursionLimit(cx_));
+  Context fieldContext = Context::firstField(kind);
 
 #if defined(DEBUG)
   const BinASTField expected_fields[4] = {
       BinASTField::Discriminant, BinASTField::PreDefaultCases,
       BinASTField::DefaultCase, BinASTField::PostDefaultCases};
   MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif  // defined(DEBUG)
 
-  BINJS_MOZ_TRY_DECL(
-      discriminant,
-      parseExpression(Context(FieldContext(
-          BinASTInterfaceAndField::SwitchStatementWithDefault__Discriminant))));
+  BINJS_MOZ_TRY_DECL(discriminant, parseExpression(fieldContext++));
   ParseContext::Statement stmt(pc_, StatementKind::Switch);
-  BINJS_MOZ_TRY_DECL(preDefaultCases,
-                     parseListOfSwitchCase(Context(FieldContext(
-                         BinASTInterfaceAndField::
-                             SwitchStatementWithDefault__PreDefaultCases))));
-
-  BINJS_MOZ_TRY_DECL(
-      defaultCase,
-      parseSwitchDefault(Context(FieldContext(
-          BinASTInterfaceAndField::SwitchStatementWithDefault__DefaultCase))));
-
-  BINJS_MOZ_TRY_DECL(postDefaultCases,
-                     parseListOfSwitchCase(Context(FieldContext(
-                         BinASTInterfaceAndField::
-                             SwitchStatementWithDefault__PostDefaultCases))));
+  BINJS_MOZ_TRY_DECL(preDefaultCases, parseListOfSwitchCase(fieldContext++));
+
+  BINJS_MOZ_TRY_DECL(defaultCase, parseSwitchDefault(fieldContext++));
+
+  BINJS_MOZ_TRY_DECL(postDefaultCases, parseListOfSwitchCase(fieldContext++));
 
   // Concatenate `preDefaultCase`, `defaultCase`, `postDefaultCase`
   auto cases = preDefaultCases;
   handler_.addList(cases, defaultCase);
   ParseNode* iter = postDefaultCases->head();
   while (iter) {
     ParseNode* next = iter->pn_next;
     handler_.addList(cases, iter);
@@ -4563,127 +4295,114 @@ JS::Result<ParseNode*> BinASTParser<Tok>
 }
 
 template <typename Tok>
 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceThrowStatement(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
     const Context& context) {
   MOZ_ASSERT(kind == BinASTKind::ThrowStatement);
   BINJS_TRY(CheckRecursionLimit(cx_));
+  Context fieldContext = Context::firstField(kind);
 
 #if defined(DEBUG)
   const BinASTField expected_fields[1] = {BinASTField::Expression};
   MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif  // defined(DEBUG)
 
-  BINJS_MOZ_TRY_DECL(
-      expression, parseExpression(Context(FieldContext(
-                      BinASTInterfaceAndField::ThrowStatement__Expression))));
+  BINJS_MOZ_TRY_DECL(expression, parseExpression(fieldContext++));
 
   BINJS_TRY_DECL(
       result, handler_.newThrowStatement(expression, tokenizer_->pos(start)));
   return result;
 }
 
 template <typename Tok>
 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceTryCatchStatement(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
     const Context& context) {
   MOZ_ASSERT(kind == BinASTKind::TryCatchStatement);
   BINJS_TRY(CheckRecursionLimit(cx_));
+  Context fieldContext = Context::firstField(kind);
 
 #if defined(DEBUG)
   const BinASTField expected_fields[2] = {BinASTField::Body,
                                           BinASTField::CatchClause};
   MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif  // defined(DEBUG)
 
   ParseNode* body;
   {
     ParseContext::Statement stmt(pc_, StatementKind::Try);
     ParseContext::Scope scope(cx_, pc_, usedNames_);
     BINJS_TRY(scope.init(pc_));
-    MOZ_TRY_VAR(body, parseBlock(Context(FieldContext(
-                          BinASTInterfaceAndField::TryCatchStatement__Body))));
+    MOZ_TRY_VAR(body, parseBlock(fieldContext++));
   }
 
-  BINJS_MOZ_TRY_DECL(
-      catchClause,
-      parseCatchClause(Context(FieldContext(
-          BinASTInterfaceAndField::TryCatchStatement__CatchClause))));
+  BINJS_MOZ_TRY_DECL(catchClause, parseCatchClause(fieldContext++));
 
   BINJS_TRY_DECL(result,
                  handler_.newTryStatement(start, body, catchClause,
                                           /* finallyBlock = */ nullptr));
   return result;
 }
 
 template <typename Tok>
 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceTryFinallyStatement(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
     const Context& context) {
   MOZ_ASSERT(kind == BinASTKind::TryFinallyStatement);
   BINJS_TRY(CheckRecursionLimit(cx_));
+  Context fieldContext = Context::firstField(kind);
 
 #if defined(DEBUG)
   const BinASTField expected_fields[3] = {
       BinASTField::Body, BinASTField::CatchClause, BinASTField::Finalizer};
   MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif  // defined(DEBUG)
 
   ParseNode* body;
   {
     ParseContext::Statement stmt(pc_, StatementKind::Try);
     ParseContext::Scope scope(cx_, pc_, usedNames_);
     BINJS_TRY(scope.init(pc_));
-    MOZ_TRY_VAR(body,
-                parseBlock(Context(FieldContext(
-                    BinASTInterfaceAndField::TryFinallyStatement__Body))));
+    MOZ_TRY_VAR(body, parseBlock(fieldContext++));
   }
 
-  BINJS_MOZ_TRY_DECL(
-      catchClause,
-      parseOptionalCatchClause(Context(FieldContext(
-          BinASTInterfaceAndField::TryFinallyStatement__CatchClause))));
+  BINJS_MOZ_TRY_DECL(catchClause, parseOptionalCatchClause(fieldContext++));
 
   ParseNode* finalizer;
   {
     ParseContext::Statement stmt(pc_, StatementKind::Finally);
     ParseContext::Scope scope(cx_, pc_, usedNames_);
     BINJS_TRY(scope.init(pc_));
-    MOZ_TRY_VAR(finalizer,
-                parseBlock(Context(FieldContext(
-                    BinASTInterfaceAndField::TryFinallyStatement__Finalizer))));
+    MOZ_TRY_VAR(finalizer, parseBlock(fieldContext++));
   }
 
   BINJS_TRY_DECL(result,
                  handler_.newTryStatement(start, body, catchClause, finalizer));
   return result;
 }
 
 template <typename Tok>
 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceUnaryExpression(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
     const Context& context) {
   MOZ_ASSERT(kind == BinASTKind::UnaryExpression);
   BINJS_TRY(CheckRecursionLimit(cx_));
+  Context fieldContext = Context::firstField(kind);
 
 #if defined(DEBUG)
   const BinASTField expected_fields[2] = {BinASTField::Operator,
                                           BinASTField::Operand};
   MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif  // defined(DEBUG)
 
-  BINJS_MOZ_TRY_DECL(operator_,
-                     parseUnaryOperator(Context(FieldContext(
-                         BinASTInterfaceAndField::UnaryExpression__Operator))));
-
-  BINJS_MOZ_TRY_DECL(operand,
-                     parseExpression(Context(FieldContext(
-                         BinASTInterfaceAndField::UnaryExpression__Operand))));
+  BINJS_MOZ_TRY_DECL(operator_, parseUnaryOperator(fieldContext++));
+
+  BINJS_MOZ_TRY_DECL(operand, parseExpression(fieldContext++));
 
   ParseNodeKind pnk;
   switch (operator_) {
     case UnaryOperator::Minus:
       pnk = ParseNodeKind::NegExpr;
       break;
     case UnaryOperator::Plus:
       pnk = ParseNodeKind::PosExpr;
@@ -4729,34 +4448,29 @@ JS::Result<ParseNode*> BinASTParser<Tok>
 }
 
 template <typename Tok>
 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceUpdateExpression(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
     const Context& context) {
   MOZ_ASSERT(kind == BinASTKind::UpdateExpression);
   BINJS_TRY(CheckRecursionLimit(cx_));
+  Context fieldContext = Context::firstField(kind);
 
 #if defined(DEBUG)
   const BinASTField expected_fields[3] = {
       BinASTField::IsPrefix, BinASTField::Operator, BinASTField::Operand};
   MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif  // defined(DEBUG)
 
-  BINJS_MOZ_TRY_DECL(
-      isPrefix, tokenizer_->readBool(Context(FieldContext(
-                    BinASTInterfaceAndField::UpdateExpression__IsPrefix))));
-
-  BINJS_MOZ_TRY_DECL(
-      operator_, parseUpdateOperator(Context(FieldContext(
-                     BinASTInterfaceAndField::UpdateExpression__Operator))));
-
-  BINJS_MOZ_TRY_DECL(operand,
-                     parseSimpleAssignmentTarget(Context(FieldContext(
-                         BinASTInterfaceAndField::UpdateExpression__Operand))));
+  BINJS_MOZ_TRY_DECL(isPrefix, tokenizer_->readBool(fieldContext++));
+
+  BINJS_MOZ_TRY_DECL(operator_, parseUpdateOperator(fieldContext++));
+
+  BINJS_MOZ_TRY_DECL(operand, parseSimpleAssignmentTarget(fieldContext++));
 
   ParseNodeKind pnk;
   switch (operator_) {
     case UpdateOperator::Incr:
       pnk = isPrefix ? ParseNodeKind::PreIncrementExpr
                      : ParseNodeKind::PostIncrementExpr;
       break;
     case UpdateOperator::Decr:
@@ -4769,45 +4483,40 @@ JS::Result<ParseNode*> BinASTParser<Tok>
 }
 
 template <typename Tok>
 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceVariableDeclaration(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
     const Context& context) {
   MOZ_ASSERT(kind == BinASTKind::VariableDeclaration);
   BINJS_TRY(CheckRecursionLimit(cx_));
+  Context fieldContext = Context::firstField(kind);
 
 #if defined(DEBUG)
   const BinASTField expected_fields[2] = {BinASTField::Kind,
                                           BinASTField::Declarators};
   MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif  // defined(DEBUG)
   AutoVariableDeclarationKind kindGuard(this);
 
-  BINJS_MOZ_TRY_DECL(kind_,
-                     parseVariableDeclarationKind(Context(FieldContext(
-                         BinASTInterfaceAndField::VariableDeclaration__Kind))));
+  BINJS_MOZ_TRY_DECL(kind_, parseVariableDeclarationKind(fieldContext++));
   // Restored by `kindGuard`.
   variableDeclarationKind_ = kind_;
   ParseNodeKind declarationListKind;
   switch (kind_) {
     case VariableDeclarationKind::Var:
       declarationListKind = ParseNodeKind::VarStmt;
       break;
     case VariableDeclarationKind::Let:
       return raiseError("Let is not supported in this preview release");
     case VariableDeclarationKind::Const:
       return raiseError("Const is not supported in this preview release");
   }
-  BINJS_MOZ_TRY_DECL(
-      declarators,
-      parseListOfVariableDeclarator(
-          declarationListKind,
-          Context(FieldContext(
-              BinASTInterfaceAndField::VariableDeclaration__Declarators))));
+  BINJS_MOZ_TRY_DECL(declarators, parseListOfVariableDeclarator(
+                                      declarationListKind, fieldContext++));
 
   // By specification, the list may not be empty.
   if (declarators->empty()) {
     return raiseEmpty("VariableDeclaration");
   }
 
   auto result = declarators;
   return result;
@@ -4839,30 +4548,27 @@ JS::Result<ParseNode*> BinASTParser<Tok>
 }
 
 template <typename Tok>
 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceVariableDeclarator(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
     const Context& context) {
   MOZ_ASSERT(kind == BinASTKind::VariableDeclarator);
   BINJS_TRY(CheckRecursionLimit(cx_));
+  Context fieldContext = Context::firstField(kind);
 
 #if defined(DEBUG)
   const BinASTField expected_fields[2] = {BinASTField::Binding,
                                           BinASTField::Init};
   MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif  // defined(DEBUG)
 
-  BINJS_MOZ_TRY_DECL(
-      binding, parseBinding(Context(FieldContext(
-                   BinASTInterfaceAndField::VariableDeclarator__Binding))));
-
-  BINJS_MOZ_TRY_DECL(init,
-                     parseOptionalExpression(Context(FieldContext(
-                         BinASTInterfaceAndField::VariableDeclarator__Init))));
+  BINJS_MOZ_TRY_DECL(binding, parseBinding(fieldContext++));
+
+  BINJS_MOZ_TRY_DECL(init, parseOptionalExpression(fieldContext++));
 
   ParseNode* result;
   if (binding->isKind(ParseNodeKind::Name)) {
     // `var foo [= bar]``
     NameNode* bindingNameNode = &binding->template as<NameNode>();
     MOZ_TRY(checkBinding(bindingNameNode->atom()->asPropertyName()));
     if (init) {
       BINJS_TRY_VAR(
@@ -4888,55 +4594,50 @@ JS::Result<ParseNode*> BinASTParser<Tok>
 }
 
 template <typename Tok>
 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceWhileStatement(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
     const Context& context) {
   MOZ_ASSERT(kind == BinASTKind::WhileStatement);
   BINJS_TRY(CheckRecursionLimit(cx_));
+  Context fieldContext = Context::firstField(kind);
 
 #if defined(DEBUG)
   const BinASTField expected_fields[2] = {BinASTField::Test, BinASTField::Body};
   MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif  // defined(DEBUG)
   ParseContext::Statement stmt(pc_, StatementKind::WhileLoop);
 
-  BINJS_MOZ_TRY_DECL(
-      test, parseExpression(Context(
-                FieldContext(BinASTInterfaceAndField::WhileStatement__Test))));
-
-  BINJS_MOZ_TRY_DECL(
-      body, parseStatement(Context(
-                FieldContext(BinASTInterfaceAndField::WhileStatement__Body))));
+  BINJS_MOZ_TRY_DECL(test, parseExpression(fieldContext++));
+
+  BINJS_MOZ_TRY_DECL(body, parseStatement(fieldContext++));
 
   BINJS_TRY_DECL(result, handler_.newWhileStatement(start, test, body));
   return result;
 }
 
 template <typename Tok>
 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceWithStatement(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
     const Context& context) {
   MOZ_ASSERT(kind == BinASTKind::WithStatement);
   BINJS_TRY(CheckRecursionLimit(cx_));
+  Context fieldContext = Context::firstField(kind);
 
 #if defined(DEBUG)
   const BinASTField expected_fields[2] = {BinASTField::Object,
                                           BinASTField::Body};
   MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif  // defined(DEBUG)
 
-  BINJS_MOZ_TRY_DECL(object,
-                     parseExpression(Context(FieldContext(
-                         BinASTInterfaceAndField::WithStatement__Object))));
+  BINJS_MOZ_TRY_DECL(object, parseExpression(fieldContext++));
 
   ParseContext::Statement stmt(pc_, StatementKind::With);
-  BINJS_MOZ_TRY_DECL(body, parseStatement(Context(FieldContext(
-                               BinASTInterfaceAndField::WithStatement__Body))));
+  BINJS_MOZ_TRY_DECL(body, parseStatement(fieldContext++));
 
   pc_->sc()->setBindingsAccessedDynamically();
   BINJS_TRY_DECL(result, handler_.newWithStatement(start, object, body));
   return result;
 }
 
 template <typename Tok>
 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceYieldExpression(
@@ -5210,19 +4911,18 @@ JS::Result<ParseNode*> BinASTParser<Tok>
   uint32_t length;
   AutoList guard(*tokenizer_);
 
   const auto start = tokenizer_->offset();
   MOZ_TRY(tokenizer_->enterList(length, context, guard));
   BINJS_TRY_DECL(result, handler_.newList(ParseNodeKind::Arguments,
                                           tokenizer_->pos(start)));
 
+  const Context childContext(context.arrayElement());
   for (uint32_t i = 0; i < length; ++i) {
-    const Context childContext(Context(ListContext(
-        context.as<FieldContext>().position, BinASTList::Arguments)));
     BINJS_MOZ_TRY_DECL(item, parseSpreadElementOrExpression(childContext));
     handler_.addList(/* list = */ result, /* kid = */ item);
   }
 
   MOZ_TRY(guard.done());
   return result;
 }
 
@@ -5231,19 +4931,18 @@ JS::Result<ListNode*> BinASTParser<Tok>:
     const Context& context) {
   uint32_t length;
   AutoList guard(*tokenizer_);
 
   const auto start = tokenizer_->offset();
   MOZ_TRY(tokenizer_->enterList(length, context, guard));
   BINJS_TRY_DECL(result, handler_.newStatementList(tokenizer_->pos(start)));
 
+  const Context childContext(context.arrayElement());
   for (uint32_t i = 0; i < length; ++i) {
-    const Context childContext(Context(ListContext(
-        context.as<FieldContext>().position, BinASTList::FunctionBody)));
     BINJS_MOZ_TRY_DECL(item, parseStatement(childContext));
     handler_.addStatementToList(result, item);
   }
 
   MOZ_TRY(guard.done());
   return result;
 }
 
@@ -5253,20 +4952,18 @@ JS::Result<Ok> BinASTParser<Tok>::parseL
   uint32_t length;
   AutoList guard(*tokenizer_);
 
   const auto start = tokenizer_->offset();
   MOZ_TRY(tokenizer_->enterList(length, context, guard));
   (void)start;
   auto result = Ok();
 
+  const Context childContext(context.arrayElement());
   for (uint32_t i = 0; i < length; ++i) {
-    const Context childContext(
-        Context(ListContext(context.as<FieldContext>().position,
-                            BinASTList::ListOfAssertedBoundName)));
     MOZ_TRY(parseAssertedBoundName(scopeKind, childContext));
     // Nothing to do here.
   }
 
   MOZ_TRY(guard.done());
   return result;
 }
 
@@ -5276,20 +4973,18 @@ JS::Result<Ok> BinASTParser<Tok>::parseL
   uint32_t length;
   AutoList guard(*tokenizer_);
 
   const auto start = tokenizer_->offset();
   MOZ_TRY(tokenizer_->enterList(length, context, guard));
   (void)start;
   auto result = Ok();
 
+  const Context childContext(context.arrayElement());
   for (uint32_t i = 0; i < length; ++i) {
-    const Context childContext(
-        Context(ListContext(context.as<FieldContext>().position,
-                            BinASTList::ListOfAssertedDeclaredName)));
     MOZ_TRY(parseAssertedDeclaredName(scopeKind, childContext));
     // Nothing to do here.
   }
 
   MOZ_TRY(guard.done());
   return result;
 }
 
@@ -5309,20 +5004,18 @@ BinASTParser<Tok>::parseListOfAssertedMa
   // list items can be greater than the actual parameters, or more than
   // ARGNO_LIMIT even if the number of parameters fits into ARGNO_LIMIT.
   // Also, the number of parameters can be greater than this list's length
   // if one of destructuring parameter is empty.
   //
   // We resize `positionalParams` vector on demand, to keep the vector
   // length match to the known maximum positional parameter index + 1.
 
+  const Context childContext(context.arrayElement());
   for (uint32_t i = 0; i < length; ++i) {
-    const Context childContext(Context(
-        ListContext(context.as<FieldContext>().position,
-                    BinASTList::ListOfAssertedMaybePositionalParameterName)));
     MOZ_TRY(parseAssertedMaybePositionalParameterName(
         scopeKind, positionalParams, childContext));
     // Nothing to do here.
   }
 
   MOZ_TRY(guard.done());
   return result;
 }
@@ -5332,19 +5025,18 @@ JS::Result<ListNode*> BinASTParser<Tok>:
     const Context& context) {
   uint32_t length;
   AutoList guard(*tokenizer_);
 
   const auto start = tokenizer_->offset();
   MOZ_TRY(tokenizer_->enterList(length, context, guard));
   BINJS_TRY_DECL(result, handler_.newStatementList(tokenizer_->pos(start)));
 
+  const Context childContext(context.arrayElement());
   for (uint32_t i = 0; i < length; ++i) {
-    const Context childContext(Context(ListContext(
-        context.as<FieldContext>().position, BinASTList::ListOfDirective)));
     BINJS_MOZ_TRY_DECL(item, parseDirective(childContext));
     handler_.addStatementToList(result, item);
   }
 
   MOZ_TRY(guard.done());
   return result;
 }
 
@@ -5353,20 +5045,18 @@ JS::Result<ListNode*> BinASTParser<Tok>:
     const Context& context) {
   uint32_t length;
   AutoList guard(*tokenizer_);
 
   const auto start = tokenizer_->offset();
   MOZ_TRY(tokenizer_->enterList(length, context, guard));
   BINJS_TRY_DECL(result, handler_.newObjectLiteral(start));
 
+  const Context childContext(context.arrayElement());
   for (uint32_t i = 0; i < length; ++i) {
-    const Context childContext(
-        Context(ListContext(context.as<FieldContext>().position,
-                            BinASTList::ListOfObjectProperty)));
     BINJS_MOZ_TRY_DECL(item, parseObjectProperty(childContext));
     if (!item->isConstant()) result->setHasNonConstInitializer();
     result->appendWithoutOrderAssumption(item);
   }
 
   MOZ_TRY(guard.done());
   return result;
 }
@@ -5377,20 +5067,18 @@ BinASTParser<Tok>::parseListOfOptionalSp
     const Context& context) {
   uint32_t length;
   AutoList guard(*tokenizer_);
 
   const auto start = tokenizer_->offset();
   MOZ_TRY(tokenizer_->enterList(length, context, guard));
   BINJS_TRY_DECL(result, handler_.newArrayLiteral(start));
 
+  const Context childContext(context.arrayElement());
   for (uint32_t i = 0; i < length; ++i) {
-    const Context childContext(Context(
-        ListContext(context.as<FieldContext>().position,
-                    BinASTList::ListOfOptionalSpreadElementOrExpression)));
     BINJS_MOZ_TRY_DECL(item,
                        parseOptionalSpreadElementOrExpression(childContext));
     if (item) {
       handler_.addArrayElement(result, item);  // Infallible.
     } else {
       BINJS_TRY(handler_.addElision(result, tokenizer_->pos(start)));
     }
   }
@@ -5404,19 +5092,18 @@ JS::Result<ListNode*> BinASTParser<Tok>:
     const Context& context) {
   uint32_t length;
   AutoList guard(*tokenizer_);
 
   const auto start = tokenizer_->offset();
   MOZ_TRY(tokenizer_->enterList(length, context, guard));
   BINJS_TRY_DECL(result, handler_.newParamsBody(tokenizer_->pos(start)));
 
+  const Context childContext(context.arrayElement());
   for (uint32_t i = 0; i < length; ++i) {
-    const Context childContext(Context(ListContext(
-        context.as<FieldContext>().position, BinASTList::ListOfParameter)));
     BINJS_MOZ_TRY_DECL(item, parseParameter(childContext));
     handler_.addList(/* list = */ result, /* kid = */ item);
   }
 
   MOZ_TRY(guard.done());
   return result;
 }
 
@@ -5425,19 +5112,18 @@ JS::Result<ListNode*> BinASTParser<Tok>:
     const Context& context) {
   uint32_t length;
   AutoList guard(*tokenizer_);
 
   const auto start = tokenizer_->offset();
   MOZ_TRY(tokenizer_->enterList(length, context, guard));
   BINJS_TRY_DECL(result, handler_.newStatementList(tokenizer_->pos(start)));
 
+  const Context childContext(context.arrayElement());
   for (uint32_t i = 0; i < length; ++i) {
-    const Context childContext(Context(ListContext(
-        context.as<FieldContext>().position, BinASTList::ListOfStatement)));
     BINJS_MOZ_TRY_DECL(item, parseStatement(childContext));
     handler_.addStatementToList(result, item);
   }
 
   MOZ_TRY(guard.done());
   return result;
 }
 
@@ -5446,19 +5132,18 @@ JS::Result<ListNode*> BinASTParser<Tok>:
     const Context& context) {
   uint32_t length;
   AutoList guard(*tokenizer_);
 
   const auto start = tokenizer_->offset();
   MOZ_TRY(tokenizer_->enterList(length, context, guard));
   BINJS_TRY_DECL(result, handler_.newStatementList(tokenizer_->pos(start)));
 
+  const Context childContext(context.arrayElement());
   for (uint32_t i = 0; i < length; ++i) {
-    const Context childContext(Context(ListContext(
-        context.as<FieldContext>().position, BinASTList::ListOfSwitchCase)));
     BINJS_MOZ_TRY_DECL(item, parseSwitchCase(childContext));
     handler_.addCaseStatementToList(result, item);
   }
 
   MOZ_TRY(guard.done());
   return result;
 }
 
@@ -5468,20 +5153,18 @@ JS::Result<ListNode*> BinASTParser<Tok>:
   uint32_t length;
   AutoList guard(*tokenizer_);
 
   const auto start = tokenizer_->offset();
   MOZ_TRY(tokenizer_->enterList(length, context, guard));
   BINJS_TRY_DECL(result, handler_.newDeclarationList(declarationListKind,
                                                      tokenizer_->pos(start)));
 
+  const Context childContext(context.arrayElement());
   for (uint32_t i = 0; i < length; ++i) {
-    const Context childContext(
-        Context(ListContext(context.as<FieldContext>().position,
-                            BinASTList::ListOfVariableDeclarator)));
     BINJS_MOZ_TRY_DECL(item, parseVariableDeclarator(childContext));
     result->appendWithoutOrderAssumption(item);
   }
 
   MOZ_TRY(guard.done());
   return result;
 }
 
--- a/js/src/frontend/BinASTParser.h
+++ b/js/src/frontend/BinASTParser.h
@@ -8,17 +8,16 @@
 
 // To generate this file, see the documentation in
 // js/src/frontend/binast/README.md.
 
 #ifndef frontend_BinASTParser_h
 #define frontend_BinASTParser_h
 
 #include "mozilla/Maybe.h"
-#include "mozilla/Variant.h"
 
 #include "frontend/BCEParserHandle.h"
 #include "frontend/BinASTParserPerTokenizer.h"
 #include "frontend/BinASTToken.h"
 #include "frontend/BinASTTokenReaderContext.h"
 #include "frontend/BinASTTokenReaderMultipart.h"
 #include "frontend/FullParseHandler.h"
 #include "frontend/ParseContext.h"
@@ -40,19 +39,16 @@ class BinASTParser : public BinASTParser
 
   using Tokenizer = Tok;
 
   using BinASTFields = typename Tokenizer::BinASTFields;
   using AutoList = typename Tokenizer::AutoList;
   using AutoTaggedTuple = typename Tokenizer::AutoTaggedTuple;
   using Chars = typename Tokenizer::Chars;
   using Context = typename BinASTTokenReaderBase::Context;
-  using ListContext = typename BinASTTokenReaderBase::ListContext;
-  using FieldContext = typename BinASTTokenReaderBase::FieldContext;
-  using RootContext = typename BinASTTokenReaderBase::RootContext;
 
  public:
   // Auto-generated types.
   using AssertedDeclaredKind = binast::AssertedDeclaredKind;
   using BinaryOperator = binast::BinaryOperator;
   using CompoundAssignmentOperator = binast::CompoundAssignmentOperator;
   using UnaryOperator = binast::UnaryOperator;
   using UpdateOperator = binast::UpdateOperator;
--- a/js/src/frontend/BinASTParserPerTokenizer.cpp
+++ b/js/src/frontend/BinASTParserPerTokenizer.cpp
@@ -128,17 +128,17 @@ JS::Result<ParseNode*> BinASTParserPerTo
   ParseContext::VarScope varScope(cx_, &globalpc, usedNames_);
   if (!varScope.init(&globalpc)) {
     return cx_->alreadyReportedError();
   }
 
   MOZ_TRY(tokenizer_->readHeader());
 
   ParseNode* result(nullptr);
-  const Context topContext((RootContext()));
+  const Context topContext(Context::topLevel());
   MOZ_TRY_VAR(result, asFinalParser()->parseProgram(topContext));
 
   mozilla::Maybe<GlobalScope::Data*> bindings =
       NewGlobalScopeData(cx_, varScope, alloc_, pc_);
   if (!bindings) {
     return cx_->alreadyReportedError();
   }
   globalsc->bindings = *bindings;
@@ -191,17 +191,17 @@ JS::Result<FunctionNode*> BinASTParserPe
   BINJS_TRY(lexicalScope.init(pc_));
   ListNode* params;
   ListNode* tmpBody;
   auto parseFunc = isExpr ? &FinalParser::parseFunctionExpressionContents
                           : &FinalParser::parseFunctionOrMethodContents;
 
   // Inject a toplevel context (i.e. no parent) to parse the lazy content.
   // In the future, we may move this to a more specific context.
-  const Context context((RootContext()));
+  const Context context(Context::topLevel());
   MOZ_TRY(
       (asFinalParser()->*parseFunc)(func->nargs(), &params, &tmpBody, context));
 
   BINJS_TRY_DECL(lexicalScopeData,
                  NewLexicalScopeData(cx_, lexicalScope, alloc_, pc_));
   BINJS_TRY_DECL(body, handler_.newLexicalScope(*lexicalScopeData, tmpBody));
 
   auto binASTKind = isExpr ? BinASTKind::LazyFunctionExpression
--- a/js/src/frontend/BinASTParserPerTokenizer.h
+++ b/js/src/frontend/BinASTParserPerTokenizer.h
@@ -52,17 +52,16 @@ class BinASTParserPerTokenizer : public 
                                  public BCEParserHandle {
  public:
   using Tokenizer = Tok;
 
   using AutoList = typename Tokenizer::AutoList;
   using AutoTaggedTuple = typename Tokenizer::AutoTaggedTuple;
   using BinASTFields = typename Tokenizer::BinASTFields;
   using Chars = typename Tokenizer::Chars;
-  using RootContext = BinASTTokenReaderBase::RootContext;
   using Context = BinASTTokenReaderBase::Context;
 
  public:
   // Auto-generated types.
   using AssertedDeclaredKind = binast::AssertedDeclaredKind;
   using VariableDeclarationKind = binast::VariableDeclarationKind;
 
  public:
--- a/js/src/frontend/BinASTToken.cpp
+++ b/js/src/frontend/BinASTToken.cpp
@@ -14,17 +14,17 @@
 #include "frontend/TokenStream.h"
 #include "js/Result.h"
 #include "vm/JSContext.h"
 
 namespace js {
 namespace frontend {
 
 const BinaryASTSupport::CharSlice BINASTKIND_DESCRIPTIONS[] = {
-#define WITH_VARIANT(_, SPEC_NAME, _2) \
+#define WITH_VARIANT(_, SPEC_NAME) \
   BinaryASTSupport::CharSlice(SPEC_NAME, sizeof(SPEC_NAME) - 1),
     FOR_EACH_BIN_KIND(WITH_VARIANT)
 #undef WITH_VARIANT
 };
 
 const BinaryASTSupport::CharSlice BINASTFIELD_DESCRIPTIONS[] = {
 #define WITH_VARIANT(_, SPEC_NAME) \
   BinaryASTSupport::CharSlice(SPEC_NAME, sizeof(SPEC_NAME) - 1),
--- a/js/src/frontend/BinASTToken.h
+++ b/js/src/frontend/BinASTToken.h
@@ -57,179 +57,143 @@ namespace frontend {
  * #define WITH_KIND(CPP_NAME, SPEC_NAME) ...
  * FOR_EACH_BIN_KIND(WITH_KIND)
  * ```
  *
  *
  * (sorted by alphabetical order)
  */
 #define FOR_EACH_BIN_KIND(F)                                                  \
-  F(_Null, "", NULL)                                                          \
-  F(ArrayAssignmentTarget, "ArrayAssignmentTarget", ARRAY_ASSIGNMENT_TARGET)  \
-  F(ArrayBinding, "ArrayBinding", ARRAY_BINDING)                              \
-  F(ArrayExpression, "ArrayExpression", ARRAY_EXPRESSION)                     \
+  F(_Null, "")                                                                \
+  F(ArrayAssignmentTarget, "ArrayAssignmentTarget")                           \
+  F(ArrayBinding, "ArrayBinding")                                             \
+  F(ArrayExpression, "ArrayExpression")                                       \
   F(ArrowExpressionContentsWithExpression,                                    \
-    "ArrowExpressionContentsWithExpression",                                  \
-    ARROW_EXPRESSION_CONTENTS_WITH_EXPRESSION)                                \
+    "ArrowExpressionContentsWithExpression")                                  \
   F(ArrowExpressionContentsWithFunctionBody,                                  \
-    "ArrowExpressionContentsWithFunctionBody",                                \
-    ARROW_EXPRESSION_CONTENTS_WITH_FUNCTION_BODY)                             \
-  F(AssertedBlockScope, "AssertedBlockScope", ASSERTED_BLOCK_SCOPE)           \
-  F(AssertedBoundName, "AssertedBoundName", ASSERTED_BOUND_NAME)              \
-  F(AssertedBoundNamesScope, "AssertedBoundNamesScope",                       \
-    ASSERTED_BOUND_NAMES_SCOPE)                                               \
-  F(AssertedDeclaredName, "AssertedDeclaredName", ASSERTED_DECLARED_NAME)     \
-  F(AssertedParameterName, "AssertedParameterName", ASSERTED_PARAMETER_NAME)  \
-  F(AssertedParameterScope, "AssertedParameterScope",                         \
-    ASSERTED_PARAMETER_SCOPE)                                                 \
-  F(AssertedPositionalParameterName, "AssertedPositionalParameterName",       \
-    ASSERTED_POSITIONAL_PARAMETER_NAME)                                       \
-  F(AssertedRestParameterName, "AssertedRestParameterName",                   \
-    ASSERTED_REST_PARAMETER_NAME)                                             \
-  F(AssertedScriptGlobalScope, "AssertedScriptGlobalScope",                   \
-    ASSERTED_SCRIPT_GLOBAL_SCOPE)                                             \
-  F(AssertedVarScope, "AssertedVarScope", ASSERTED_VAR_SCOPE)                 \
-  F(AssignmentExpression, "AssignmentExpression", ASSIGNMENT_EXPRESSION)      \
-  F(AssignmentTargetIdentifier, "AssignmentTargetIdentifier",                 \
-    ASSIGNMENT_TARGET_IDENTIFIER)                                             \
-  F(AssignmentTargetPropertyIdentifier, "AssignmentTargetPropertyIdentifier", \
-    ASSIGNMENT_TARGET_PROPERTY_IDENTIFIER)                                    \
-  F(AssignmentTargetPropertyProperty, "AssignmentTargetPropertyProperty",     \
-    ASSIGNMENT_TARGET_PROPERTY_PROPERTY)                                      \
-  F(AssignmentTargetWithInitializer, "AssignmentTargetWithInitializer",       \
-    ASSIGNMENT_TARGET_WITH_INITIALIZER)                                       \
-  F(AwaitExpression, "AwaitExpression", AWAIT_EXPRESSION)                     \
-  F(BinaryExpression, "BinaryExpression", BINARY_EXPRESSION)                  \
-  F(BindingIdentifier, "BindingIdentifier", BINDING_IDENTIFIER)               \
-  F(BindingPropertyIdentifier, "BindingPropertyIdentifier",                   \
-    BINDING_PROPERTY_IDENTIFIER)                                              \
-  F(BindingPropertyProperty, "BindingPropertyProperty",                       \
-    BINDING_PROPERTY_PROPERTY)                                                \
-  F(BindingWithInitializer, "BindingWithInitializer",                         \
-    BINDING_WITH_INITIALIZER)                                                 \
-  F(Block, "Block", BLOCK)                                                    \
-  F(BreakStatement, "BreakStatement", BREAK_STATEMENT)                        \
-  F(CallExpression, "CallExpression", CALL_EXPRESSION)                        \
-  F(CatchClause, "CatchClause", CATCH_CLAUSE)                                 \
-  F(ClassDeclaration, "ClassDeclaration", CLASS_DECLARATION)                  \
-  F(ClassElement, "ClassElement", CLASS_ELEMENT)                              \
-  F(ClassExpression, "ClassExpression", CLASS_EXPRESSION)                     \
-  F(CompoundAssignmentExpression, "CompoundAssignmentExpression",             \
-    COMPOUND_ASSIGNMENT_EXPRESSION)                                           \
-  F(ComputedMemberAssignmentTarget, "ComputedMemberAssignmentTarget",         \
-    COMPUTED_MEMBER_ASSIGNMENT_TARGET)                                        \
-  F(ComputedMemberExpression, "ComputedMemberExpression",                     \
-    COMPUTED_MEMBER_EXPRESSION)                                               \
-  F(ComputedPropertyName, "ComputedPropertyName", COMPUTED_PROPERTY_NAME)     \
-  F(ConditionalExpression, "ConditionalExpression", CONDITIONAL_EXPRESSION)   \
-  F(ContinueStatement, "ContinueStatement", CONTINUE_STATEMENT)               \
-  F(DataProperty, "DataProperty", DATA_PROPERTY)                              \
-  F(DebuggerStatement, "DebuggerStatement", DEBUGGER_STATEMENT)               \
-  F(Directive, "Directive", DIRECTIVE)                                        \
-  F(DoWhileStatement, "DoWhileStatement", DO_WHILE_STATEMENT)                 \
-  F(EagerArrowExpressionWithExpression, "EagerArrowExpressionWithExpression", \
-    EAGER_ARROW_EXPRESSION_WITH_EXPRESSION)                                   \
+    "ArrowExpressionContentsWithFunctionBody")                                \
+  F(AssertedBlockScope, "AssertedBlockScope")                                 \
+  F(AssertedBoundName, "AssertedBoundName")                                   \
+  F(AssertedBoundNamesScope, "AssertedBoundNamesScope")                       \
+  F(AssertedDeclaredName, "AssertedDeclaredName")                             \
+  F(AssertedParameterName, "AssertedParameterName")                           \
+  F(AssertedParameterScope, "AssertedParameterScope")                         \
+  F(AssertedPositionalParameterName, "AssertedPositionalParameterName")       \
+  F(AssertedRestParameterName, "AssertedRestParameterName")                   \
+  F(AssertedScriptGlobalScope, "AssertedScriptGlobalScope")                   \
+  F(AssertedVarScope, "AssertedVarScope")                                     \
+  F(AssignmentExpression, "AssignmentExpression")                             \
+  F(AssignmentTargetIdentifier, "AssignmentTargetIdentifier")                 \
+  F(AssignmentTargetPropertyIdentifier, "AssignmentTargetPropertyIdentifier") \
+  F(AssignmentTargetPropertyProperty, "AssignmentTargetPropertyProperty")     \
+  F(AssignmentTargetWithInitializer, "AssignmentTargetWithInitializer")       \
+  F(AwaitExpression, "AwaitExpression")                                       \
+  F(BinaryExpression, "BinaryExpression")                                     \
+  F(BindingIdentifier, "BindingIdentifier")                                   \
+  F(BindingPropertyIdentifier, "BindingPropertyIdentifier")                   \
+  F(BindingPropertyProperty, "BindingPropertyProperty")                       \
+  F(BindingWithInitializer, "BindingWithInitializer")                         \
+  F(Block, "Block")                                                           \
+  F(BreakStatement, "BreakStatement")                                         \
+  F(CallExpression, "CallExpression")                                         \
+  F(CatchClause, "CatchClause")                                               \
+  F(ClassDeclaration, "ClassDeclaration")                                     \
+  F(ClassElement, "ClassElement")                                             \
+  F(ClassExpression, "ClassExpression")                                       \
+  F(CompoundAssignmentExpression, "CompoundAssignmentExpression")             \
+  F(ComputedMemberAssignmentTarget, "ComputedMemberAssignmentTarget")         \
+  F(ComputedMemberExpression, "ComputedMemberExpression")                     \
+  F(ComputedPropertyName, "ComputedPropertyName")                             \
+  F(ConditionalExpression, "ConditionalExpression")                           \
+  F(ContinueStatement, "ContinueStatement")                                   \
+  F(DataProperty, "DataProperty")                                             \
+  F(DebuggerStatement, "DebuggerStatement")                                   \
+  F(Directive, "Directive")                                                   \
+  F(DoWhileStatement, "DoWhileStatement")                                     \
+  F(EagerArrowExpressionWithExpression, "EagerArrowExpressionWithExpression") \
   F(EagerArrowExpressionWithFunctionBody,                                     \
-    "EagerArrowExpressionWithFunctionBody",                                   \
-    EAGER_ARROW_EXPRESSION_WITH_FUNCTION_BODY)                                \
-  F(EagerFunctionDeclaration, "EagerFunctionDeclaration",                     \
-    EAGER_FUNCTION_DECLARATION)                                               \
-  F(EagerFunctionExpression, "EagerFunctionExpression",                       \
-    EAGER_FUNCTION_EXPRESSION)                                                \
-  F(EagerGetter, "EagerGetter", EAGER_GETTER)                                 \
-  F(EagerMethod, "EagerMethod", EAGER_METHOD)                                 \
-  F(EagerSetter, "EagerSetter", EAGER_SETTER)                                 \
-  F(EmptyStatement, "EmptyStatement", EMPTY_STATEMENT)                        \
-  F(Export, "Export", EXPORT)                                                 \
-  F(ExportAllFrom, "ExportAllFrom", EXPORT_ALL_FROM)                          \
-  F(ExportDefault, "ExportDefault", EXPORT_DEFAULT)                           \
-  F(ExportFrom, "ExportFrom", EXPORT_FROM)                                    \
-  F(ExportFromSpecifier, "ExportFromSpecifier", EXPORT_FROM_SPECIFIER)        \
-  F(ExportLocalSpecifier, "ExportLocalSpecifier", EXPORT_LOCAL_SPECIFIER)     \
-  F(ExportLocals, "ExportLocals", EXPORT_LOCALS)                              \
-  F(ExpressionStatement, "ExpressionStatement", EXPRESSION_STATEMENT)         \
-  F(ForInOfBinding, "ForInOfBinding", FOR_IN_OF_BINDING)                      \
-  F(ForInStatement, "ForInStatement", FOR_IN_STATEMENT)                       \
-  F(ForOfStatement, "ForOfStatement", FOR_OF_STATEMENT)                       \
-  F(ForStatement, "ForStatement", FOR_STATEMENT)                              \
-  F(FormalParameters, "FormalParameters", FORMAL_PARAMETERS)                  \
-  F(FunctionExpressionContents, "FunctionExpressionContents",                 \
-    FUNCTION_EXPRESSION_CONTENTS)                                             \
-  F(FunctionOrMethodContents, "FunctionOrMethodContents",                     \
-    FUNCTION_OR_METHOD_CONTENTS)                                              \
-  F(GetterContents, "GetterContents", GETTER_CONTENTS)                        \
-  F(IdentifierExpression, "IdentifierExpression", IDENTIFIER_EXPRESSION)      \
-  F(IfStatement, "IfStatement", IF_STATEMENT)                                 \
-  F(Import, "Import", IMPORT)                                                 \
-  F(ImportNamespace, "ImportNamespace", IMPORT_NAMESPACE)                     \
-  F(ImportSpecifier, "ImportSpecifier", IMPORT_SPECIFIER)                     \
-  F(LabelledStatement, "LabelledStatement", LABELLED_STATEMENT)               \
-  F(LazyArrowExpressionWithExpression, "LazyArrowExpressionWithExpression",   \
-    LAZY_ARROW_EXPRESSION_WITH_EXPRESSION)                                    \
+    "EagerArrowExpressionWithFunctionBody")                                   \
+  F(EagerFunctionDeclaration, "EagerFunctionDeclaration")                     \
+  F(EagerFunctionExpression, "EagerFunctionExpression")                       \
+  F(EagerGetter, "EagerGetter")                                               \
+  F(EagerMethod, "EagerMethod")                                               \
+  F(EagerSetter, "EagerSetter")                                               \
+  F(EmptyStatement, "EmptyStatement")                                         \
+  F(Export, "Export")                                                         \
+  F(ExportAllFrom, "ExportAllFrom")                                           \
+  F(ExportDefault, "ExportDefault")                                           \
+  F(ExportFrom, "ExportFrom")                                                 \
+  F(ExportFromSpecifier, "ExportFromSpecifier")                               \
+  F(ExportLocalSpecifier, "ExportLocalSpecifier")                             \
+  F(ExportLocals, "ExportLocals")                                             \
+  F(ExpressionStatement, "ExpressionStatement")                               \
+  F(ForInOfBinding, "ForInOfBinding")                                         \
+  F(ForInStatement, "ForInStatement")                                         \
+  F(ForOfStatement, "ForOfStatement")                                         \
+  F(ForStatement, "ForStatement")                                             \
+  F(FormalParameters, "FormalParameters")                                     \
+  F(FunctionExpressionContents, "FunctionExpressionContents")                 \
+  F(FunctionOrMethodContents, "FunctionOrMethodContents")                     \
+  F(GetterContents, "GetterContents")                                         \
+  F(IdentifierExpression, "IdentifierExpression")                             \
+  F(IfStatement, "IfStatement")                                               \
+  F(Import, "Import")                                                         \
+  F(ImportNamespace, "ImportNamespace")                                       \
+  F(ImportSpecifier, "ImportSpecifier")                                       \
+  F(LabelledStatement, "LabelledStatement")                                   \
+  F(LazyArrowExpressionWithExpression, "LazyArrowExpressionWithExpression")   \
   F(LazyArrowExpressionWithFunctionBody,                                      \
-    "LazyArrowExpressionWithFunctionBody",                                    \
-    LAZY_ARROW_EXPRESSION_WITH_FUNCTION_BODY)                                 \
-  F(LazyFunctionDeclaration, "LazyFunctionDeclaration",                       \
-    LAZY_FUNCTION_DECLARATION)                                                \
-  F(LazyFunctionExpression, "LazyFunctionExpression",                         \
-    LAZY_FUNCTION_EXPRESSION)                                                 \
-  F(LazyGetter, "LazyGetter", LAZY_GETTER)                                    \
-  F(LazyMethod, "LazyMethod", LAZY_METHOD)                                    \
-  F(LazySetter, "LazySetter", LAZY_SETTER)                                    \
-  F(LiteralBooleanExpression, "LiteralBooleanExpression",                     \
-    LITERAL_BOOLEAN_EXPRESSION)                                               \
-  F(LiteralInfinityExpression, "LiteralInfinityExpression",                   \
-    LITERAL_INFINITY_EXPRESSION)                                              \
-  F(LiteralNullExpression, "LiteralNullExpression", LITERAL_NULL_EXPRESSION)  \
-  F(LiteralNumericExpression, "LiteralNumericExpression",                     \
-    LITERAL_NUMERIC_EXPRESSION)                                               \
-  F(LiteralPropertyName, "LiteralPropertyName", LITERAL_PROPERTY_NAME)        \
-  F(LiteralRegExpExpression, "LiteralRegExpExpression",                       \
-    LITERAL_REG_EXP_EXPRESSION)                                               \
-  F(LiteralStringExpression, "LiteralStringExpression",                       \
-    LITERAL_STRING_EXPRESSION)                                                \
-  F(Module, "Module", MODULE)                                                 \
-  F(NewExpression, "NewExpression", NEW_EXPRESSION)                           \
-  F(NewTargetExpression, "NewTargetExpression", NEW_TARGET_EXPRESSION)        \
-  F(ObjectAssignmentTarget, "ObjectAssignmentTarget",                         \
-    OBJECT_ASSIGNMENT_TARGET)                                                 \
-  F(ObjectBinding, "ObjectBinding", OBJECT_BINDING)                           \
-  F(ObjectExpression, "ObjectExpression", OBJECT_EXPRESSION)                  \
-  F(ReturnStatement, "ReturnStatement", RETURN_STATEMENT)                     \
-  F(Script, "Script", SCRIPT)                                                 \
-  F(SetterContents, "SetterContents", SETTER_CONTENTS)                        \
-  F(ShorthandProperty, "ShorthandProperty", SHORTHAND_PROPERTY)               \
-  F(SpreadElement, "SpreadElement", SPREAD_ELEMENT)                           \
-  F(StaticMemberAssignmentTarget, "StaticMemberAssignmentTarget",             \
-    STATIC_MEMBER_ASSIGNMENT_TARGET)                                          \
-  F(StaticMemberExpression, "StaticMemberExpression",                         \
-    STATIC_MEMBER_EXPRESSION)                                                 \
-  F(Super, "Super", SUPER)                                                    \
-  F(SwitchCase, "SwitchCase", SWITCH_CASE)                                    \
-  F(SwitchDefault, "SwitchDefault", SWITCH_DEFAULT)                           \
-  F(SwitchStatement, "SwitchStatement", SWITCH_STATEMENT)                     \
-  F(SwitchStatementWithDefault, "SwitchStatementWithDefault",                 \
-    SWITCH_STATEMENT_WITH_DEFAULT)                                            \
-  F(TemplateElement, "TemplateElement", TEMPLATE_ELEMENT)                     \
-  F(TemplateExpression, "TemplateExpression", TEMPLATE_EXPRESSION)            \
-  F(ThisExpression, "ThisExpression", THIS_EXPRESSION)                        \
-  F(ThrowStatement, "ThrowStatement", THROW_STATEMENT)                        \
-  F(TryCatchStatement, "TryCatchStatement", TRY_CATCH_STATEMENT)              \
-  F(TryFinallyStatement, "TryFinallyStatement", TRY_FINALLY_STATEMENT)        \
-  F(UnaryExpression, "UnaryExpression", UNARY_EXPRESSION)                     \
-  F(UpdateExpression, "UpdateExpression", UPDATE_EXPRESSION)                  \
-  F(VariableDeclaration, "VariableDeclaration", VARIABLE_DECLARATION)         \
-  F(VariableDeclarator, "VariableDeclarator", VARIABLE_DECLARATOR)            \
-  F(WhileStatement, "WhileStatement", WHILE_STATEMENT)                        \
-  F(WithStatement, "WithStatement", WITH_STATEMENT)                           \
-  F(YieldExpression, "YieldExpression", YIELD_EXPRESSION)                     \
-  F(YieldStarExpression, "YieldStarExpression", YIELD_STAR_EXPRESSION)
+    "LazyArrowExpressionWithFunctionBody")                                    \
+  F(LazyFunctionDeclaration, "LazyFunctionDeclaration")                       \
+  F(LazyFunctionExpression, "LazyFunctionExpression")                         \
+  F(LazyGetter, "LazyGetter")                                                 \
+  F(LazyMethod, "LazyMethod")                                                 \
+  F(LazySetter, "LazySetter")                                                 \
+  F(LiteralBooleanExpression, "LiteralBooleanExpression")                     \
+  F(LiteralInfinityExpression, "LiteralInfinityExpression")                   \
+  F(LiteralNullExpression, "LiteralNullExpression")                           \
+  F(LiteralNumericExpression, "LiteralNumericExpression")                     \
+  F(LiteralPropertyName, "LiteralPropertyName")                               \
+  F(LiteralRegExpExpression, "LiteralRegExpExpression")                       \
+  F(LiteralStringExpression, "LiteralStringExpression")                       \
+  F(Module, "Module")                                                         \
+  F(NewExpression, "NewExpression")                                           \
+  F(NewTargetExpression, "NewTargetExpression")                               \
+  F(ObjectAssignmentTarget, "ObjectAssignmentTarget")                         \
+  F(ObjectBinding, "ObjectBinding")                                           \
+  F(ObjectExpression, "ObjectExpression")                                     \
+  F(ReturnStatement, "ReturnStatement")                                       \
+  F(Script, "Script")                                                         \
+  F(SetterContents, "SetterContents")                                         \
+  F(ShorthandProperty, "ShorthandProperty")                                   \
+  F(SpreadElement, "SpreadElement")                                           \
+  F(StaticMemberAssignmentTarget, "StaticMemberAssignmentTarget")             \
+  F(StaticMemberExpression, "StaticMemberExpression")                         \
+  F(Super, "Super")                                                           \
+  F(SwitchCase, "SwitchCase")                                                 \
+  F(SwitchDefault, "SwitchDefault")                                           \
+  F(SwitchStatement, "SwitchStatement")                                       \
+  F(SwitchStatementWithDefault, "SwitchStatementWithDefault")                 \
+  F(TemplateElement, "TemplateElement")                                       \
+  F(TemplateExpression, "TemplateExpression")                                 \
+  F(ThisExpression, "ThisExpression")                                         \
+  F(ThrowStatement, "ThrowStatement")                                         \
+  F(TryCatchStatement, "TryCatchStatement")                                   \
+  F(TryFinallyStatement, "TryFinallyStatement")                               \
+  F(UnaryExpression, "UnaryExpression")                                       \
+  F(UpdateExpression, "UpdateExpression")                                     \
+  F(VariableDeclaration, "VariableDeclaration")                               \
+  F(VariableDeclarator, "VariableDeclarator")                                 \
+  F(WhileStatement, "WhileStatement")                                         \
+  F(WithStatement, "WithStatement")                                           \
+  F(YieldExpression, "YieldExpression")                                       \
+  F(YieldStarExpression, "YieldStarExpression")
 
 enum class BinASTKind : uint16_t {
-#define EMIT_ENUM(name, _1, _2) name,
+#define EMIT_ENUM(name, _) name,
   FOR_EACH_BIN_KIND(EMIT_ENUM)
 #undef EMIT_ENUM
 };
 
 // The number of distinct values of BinASTKind.
 const size_t BINASTKIND_LIMIT = 120;
 
 /**
@@ -320,1968 +284,16 @@ enum class BinASTField : uint16_t {
 #define EMIT_ENUM(name, _) name,
   FOR_EACH_BIN_FIELD(EMIT_ENUM)
 #undef EMIT_ENUM
 };
 
 // The number of distinct values of BinASTField.
 const size_t BINASTFIELD_LIMIT = 69;
 
-#define FOR_EACH_BIN_INTERFACE_AND_FIELD(F)                                   \
-  F(ArrayAssignmentTarget__Elements, "ArrayAssignmentTarget::elements")       \
-  F(ArrayAssignmentTarget__Rest, "ArrayAssignmentTarget::rest")               \
-  F(ArrayBinding__Elements, "ArrayBinding::elements")                         \
-  F(ArrayBinding__Rest, "ArrayBinding::rest")                                 \
-  F(ArrayExpression__Elements, "ArrayExpression::elements")                   \
-  F(ArrowExpressionContentsWithExpression__ParameterScope,                    \
-    "ArrowExpressionContentsWithExpression::parameterScope")                  \
-  F(ArrowExpressionContentsWithExpression__Params,                            \
-    "ArrowExpressionContentsWithExpression::params")                          \
-  F(ArrowExpressionContentsWithExpression__BodyScope,                         \
-    "ArrowExpressionContentsWithExpression::bodyScope")                       \
-  F(ArrowExpressionContentsWithExpression__Body,                              \
-    "ArrowExpressionContentsWithExpression::body")                            \
-  F(ArrowExpressionContentsWithFunctionBody__ParameterScope,                  \
-    "ArrowExpressionContentsWithFunctionBody::parameterScope")                \
-  F(ArrowExpressionContentsWithFunctionBody__Params,                          \
-    "ArrowExpressionContentsWithFunctionBody::params")                        \
-  F(ArrowExpressionContentsWithFunctionBody__BodyScope,                       \
-    "ArrowExpressionContentsWithFunctionBody::bodyScope")                     \
-  F(ArrowExpressionContentsWithFunctionBody__Body,                            \
-    "ArrowExpressionContentsWithFunctionBody::body")                          \
-  F(AssertedBlockScope__DeclaredNames, "AssertedBlockScope::declaredNames")   \
-  F(AssertedBlockScope__HasDirectEval, "AssertedBlockScope::hasDirectEval")   \
-  F(AssertedBoundName__Name, "AssertedBoundName::name")                       \
-  F(AssertedBoundName__IsCaptured, "AssertedBoundName::isCaptured")           \
-  F(AssertedBoundNamesScope__BoundNames,                                      \
-    "AssertedBoundNamesScope::boundNames")                                    \
-  F(AssertedBoundNamesScope__HasDirectEval,                                   \
-    "AssertedBoundNamesScope::hasDirectEval")                                 \
-  F(AssertedDeclaredName__Name, "AssertedDeclaredName::name")                 \
-  F(AssertedDeclaredName__Kind, "AssertedDeclaredName::kind")                 \
-  F(AssertedDeclaredName__IsCaptured, "AssertedDeclaredName::isCaptured")     \
-  F(AssertedParameterName__Name, "AssertedParameterName::name")               \
-  F(AssertedParameterName__IsCaptured, "AssertedParameterName::isCaptured")   \
-  F(AssertedParameterScope__ParamNames, "AssertedParameterScope::paramNames") \
-  F(AssertedParameterScope__HasDirectEval,                                    \
-    "AssertedParameterScope::hasDirectEval")                                  \
-  F(AssertedParameterScope__IsSimpleParameterList,                            \
-    "AssertedParameterScope::isSimpleParameterList")                          \
-  F(AssertedPositionalParameterName__Index,                                   \
-    "AssertedPositionalParameterName::index")                                 \
-  F(AssertedPositionalParameterName__Name,                                    \
-    "AssertedPositionalParameterName::name")                                  \
-  F(AssertedPositionalParameterName__IsCaptured,                              \
-    "AssertedPositionalParameterName::isCaptured")                            \
-  F(AssertedRestParameterName__Name, "AssertedRestParameterName::name")       \
-  F(AssertedRestParameterName__IsCaptured,                                    \
-    "AssertedRestParameterName::isCaptured")                                  \
-  F(AssertedScriptGlobalScope__DeclaredNames,                                 \
-    "AssertedScriptGlobalScope::declaredNames")                               \
-  F(AssertedScriptGlobalScope__HasDirectEval,                                 \
-    "AssertedScriptGlobalScope::hasDirectEval")                               \
-  F(AssertedVarScope__DeclaredNames, "AssertedVarScope::declaredNames")       \
-  F(AssertedVarScope__HasDirectEval, "AssertedVarScope::hasDirectEval")       \
-  F(AssignmentExpression__Binding, "AssignmentExpression::binding")           \
-  F(AssignmentExpression__Expression, "AssignmentExpression::expression")     \
-  F(AssignmentTargetIdentifier__Name, "AssignmentTargetIdentifier::name")     \
-  F(AssignmentTargetPropertyIdentifier__Binding,                              \
-    "AssignmentTargetPropertyIdentifier::binding")                            \
-  F(AssignmentTargetPropertyIdentifier__Init,                                 \
-    "AssignmentTargetPropertyIdentifier::init")                               \
-  F(AssignmentTargetPropertyProperty__Name,                                   \
-    "AssignmentTargetPropertyProperty::name")                                 \
-  F(AssignmentTargetPropertyProperty__Binding,                                \
-    "AssignmentTargetPropertyProperty::binding")                              \
-  F(AssignmentTargetWithInitializer__Binding,                                 \
-    "AssignmentTargetWithInitializer::binding")                               \
-  F(AssignmentTargetWithInitializer__Init,                                    \
-    "AssignmentTargetWithInitializer::init")                                  \
-  F(AwaitExpression__Expression, "AwaitExpression::expression")               \
-  F(BinaryExpression__Operator, "BinaryExpression::operator")                 \
-  F(BinaryExpression__Left, "BinaryExpression::left")                         \
-  F(BinaryExpression__Right, "BinaryExpression::right")                       \
-  F(BindingIdentifier__Name, "BindingIdentifier::name")                       \
-  F(BindingPropertyIdentifier__Binding, "BindingPropertyIdentifier::binding") \
-  F(BindingPropertyIdentifier__Init, "BindingPropertyIdentifier::init")       \
-  F(BindingPropertyProperty__Name, "BindingPropertyProperty::name")           \
-  F(BindingPropertyProperty__Binding, "BindingPropertyProperty::binding")     \
-  F(BindingWithInitializer__Binding, "BindingWithInitializer::binding")       \
-  F(BindingWithInitializer__Init, "BindingWithInitializer::init")             \
-  F(Block__Scope, "Block::scope")                                             \
-  F(Block__Statements, "Block::statements")                                   \
-  F(BreakStatement__Label, "BreakStatement::label")                           \
-  F(CallExpression__Callee, "CallExpression::callee")                         \
-  F(CallExpression__Arguments, "CallExpression::arguments")                   \
-  F(CatchClause__BindingScope, "CatchClause::bindingScope")                   \
-  F(CatchClause__Binding, "CatchClause::binding")                             \
-  F(CatchClause__Body, "CatchClause::body")                                   \
-  F(ClassDeclaration__Name, "ClassDeclaration::name")                         \
-  F(ClassDeclaration__Super, "ClassDeclaration::super")                       \
-  F(ClassDeclaration__Elements, "ClassDeclaration::elements")                 \
-  F(ClassElement__IsStatic, "ClassElement::isStatic")                         \
-  F(ClassElement__Method, "ClassElement::method")                             \
-  F(ClassExpression__Name, "ClassExpression::name")                           \
-  F(ClassExpression__Super, "ClassExpression::super")                         \
-  F(ClassExpression__Elements, "ClassExpression::elements")                   \
-  F(CompoundAssignmentExpression__Operator,                                   \
-    "CompoundAssignmentExpression::operator")                                 \
-  F(CompoundAssignmentExpression__Binding,                                    \
-    "CompoundAssignmentExpression::binding")                                  \
-  F(CompoundAssignmentExpression__Expression,                                 \
-    "CompoundAssignmentExpression::expression")                               \
-  F(ComputedMemberAssignmentTarget__Object,                                   \
-    "ComputedMemberAssignmentTarget::object")                                 \
-  F(ComputedMemberAssignmentTarget__Expression,                               \
-    "ComputedMemberAssignmentTarget::expression")                             \
-  F(ComputedMemberExpression__Object, "ComputedMemberExpression::object")     \
-  F(ComputedMemberExpression__Expression,                                     \
-    "ComputedMemberExpression::expression")                                   \
-  F(ComputedPropertyName__Expression, "ComputedPropertyName::expression")     \
-  F(ConditionalExpression__Test, "ConditionalExpression::test")               \
-  F(ConditionalExpression__Consequent, "ConditionalExpression::consequent")   \
-  F(ConditionalExpression__Alternate, "ConditionalExpression::alternate")     \
-  F(ContinueStatement__Label, "ContinueStatement::label")                     \
-  F(DataProperty__Name, "DataProperty::name")                                 \
-  F(DataProperty__Expression, "DataProperty::expression")                     \
-  F(Directive__RawValue, "Directive::rawValue")                               \
-  F(DoWhileStatement__Test, "DoWhileStatement::test")                         \
-  F(DoWhileStatement__Body, "DoWhileStatement::body")                         \
-  F(EagerArrowExpressionWithExpression__IsAsync,                              \
-    "EagerArrowExpressionWithExpression::isAsync")                            \
-  F(EagerArrowExpressionWithExpression__Length,                               \
-    "EagerArrowExpressionWithExpression::length")                             \
-  F(EagerArrowExpressionWithExpression__Contents,                             \
-    "EagerArrowExpressionWithExpression::contents")                           \
-  F(EagerArrowExpressionWithFunctionBody__IsAsync,                            \
-    "EagerArrowExpressionWithFunctionBody::isAsync")                          \
-  F(EagerArrowExpressionWithFunctionBody__Length,                             \
-    "EagerArrowExpressionWithFunctionBody::length")                           \
-  F(EagerArrowExpressionWithFunctionBody__Directives,                         \
-    "EagerArrowExpressionWithFunctionBody::directives")                       \
-  F(EagerArrowExpressionWithFunctionBody__Contents,                           \
-    "EagerArrowExpressionWithFunctionBody::contents")                         \
-  F(EagerFunctionDeclaration__IsAsync, "EagerFunctionDeclaration::isAsync")   \
-  F(EagerFunctionDeclaration__IsGenerator,                                    \
-    "EagerFunctionDeclaration::isGenerator")                                  \
-  F(EagerFunctionDeclaration__Name, "EagerFunctionDeclaration::name")         \
-  F(EagerFunctionDeclaration__Length, "EagerFunctionDeclaration::length")     \
-  F(EagerFunctionDeclaration__Directives,                                     \
-    "EagerFunctionDeclaration::directives")                                   \
-  F(EagerFunctionDeclaration__Contents, "EagerFunctionDeclaration::contents") \
-  F(EagerFunctionExpression__IsAsync, "EagerFunctionExpression::isAsync")     \
-  F(EagerFunctionExpression__IsGenerator,                                     \
-    "EagerFunctionExpression::isGenerator")                                   \
-  F(EagerFunctionExpression__Name, "EagerFunctionExpression::name")           \
-  F(EagerFunctionExpression__Length, "EagerFunctionExpression::length")       \
-  F(EagerFunctionExpression__Directives,                                      \
-    "EagerFunctionExpression::directives")                                    \
-  F(EagerFunctionExpression__Contents, "EagerFunctionExpression::contents")   \
-  F(EagerGetter__Name, "EagerGetter::name")                                   \
-  F(EagerGetter__Directives, "EagerGetter::directives")                       \
-  F(EagerGetter__Contents, "EagerGetter::contents")                           \
-  F(EagerMethod__IsAsync, "EagerMethod::isAsync")                             \
-  F(EagerMethod__IsGenerator, "EagerMethod::isGenerator")                     \
-  F(EagerMethod__Name, "EagerMethod::name")                                   \
-  F(EagerMethod__Length, "EagerMethod::length")                               \
-  F(EagerMethod__Directives, "EagerMethod::directives")                       \
-  F(EagerMethod__Contents, "EagerMethod::contents")                           \
-  F(EagerSetter__Name, "EagerSetter::name")                                   \
-  F(EagerSetter__Length, "EagerSetter::length")                               \
-  F(EagerSetter__Directives, "EagerSetter::directives")                       \
-  F(EagerSetter__Contents, "EagerSetter::contents")                           \
-  F(Export__Declaration, "Export::declaration")                               \
-  F(ExportAllFrom__ModuleSpecifier, "ExportAllFrom::moduleSpecifier")         \
-  F(ExportDefault__Body, "ExportDefault::body")                               \
-  F(ExportFrom__NamedExports, "ExportFrom::namedExports")                     \
-  F(ExportFrom__ModuleSpecifier, "ExportFrom::moduleSpecifier")               \
-  F(ExportFromSpecifier__Name, "ExportFromSpecifier::name")                   \
-  F(ExportFromSpecifier__ExportedName, "ExportFromSpecifier::exportedName")   \
-  F(ExportLocalSpecifier__Name, "ExportLocalSpecifier::name")                 \
-  F(ExportLocalSpecifier__ExportedName, "ExportLocalSpecifier::exportedName") \
-  F(ExportLocals__NamedExports, "ExportLocals::namedExports")                 \
-  F(ExpressionStatement__Expression, "ExpressionStatement::expression")       \
-  F(ForInOfBinding__Kind, "ForInOfBinding::kind")                             \
-  F(ForInOfBinding__Binding, "ForInOfBinding::binding")                       \
-  F(ForInStatement__Left, "ForInStatement::left")                             \
-  F(ForInStatement__Right, "ForInStatement::right")                           \
-  F(ForInStatement__Body, "ForInStatement::body")                             \
-  F(ForOfStatement__Left, "ForOfStatement::left")                             \
-  F(ForOfStatement__Right, "ForOfStatement::right")                           \
-  F(ForOfStatement__Body, "ForOfStatement::body")                             \
-  F(ForStatement__Init, "ForStatement::init")                                 \
-  F(ForStatement__Test, "ForStatement::test")                                 \
-  F(ForStatement__Update, "ForStatement::update")                             \
-  F(ForStatement__Body, "ForStatement::body")                                 \
-  F(FormalParameters__Items, "FormalParameters::items")                       \
-  F(FormalParameters__Rest, "FormalParameters::rest")                         \
-  F(FunctionExpressionContents__IsFunctionNameCaptured,                       \
-    "FunctionExpressionContents::isFunctionNameCaptured")                     \
-  F(FunctionExpressionContents__IsThisCaptured,                               \
-    "FunctionExpressionContents::isThisCaptured")                             \
-  F(FunctionExpressionContents__ParameterScope,                               \
-    "FunctionExpressionContents::parameterScope")                             \
-  F(FunctionExpressionContents__Params, "FunctionExpressionContents::params") \
-  F(FunctionExpressionContents__BodyScope,                                    \
-    "FunctionExpressionContents::bodyScope")                                  \
-  F(FunctionExpressionContents__Body, "FunctionExpressionContents::body")     \
-  F(FunctionOrMethodContents__IsThisCaptured,                                 \
-    "FunctionOrMethodContents::isThisCaptured")                               \
-  F(FunctionOrMethodContents__ParameterScope,                                 \
-    "FunctionOrMethodContents::parameterScope")                               \
-  F(FunctionOrMethodContents__Params, "FunctionOrMethodContents::params")     \
-  F(FunctionOrMethodContents__BodyScope,                                      \
-    "FunctionOrMethodContents::bodyScope")                                    \
-  F(FunctionOrMethodContents__Body, "FunctionOrMethodContents::body")         \
-  F(GetterContents__IsThisCaptured, "GetterContents::isThisCaptured")         \
-  F(GetterContents__BodyScope, "GetterContents::bodyScope")                   \
-  F(GetterContents__Body, "GetterContents::body")                             \
-  F(IdentifierExpression__Name, "IdentifierExpression::name")                 \
-  F(IfStatement__Test, "IfStatement::test")                                   \
-  F(IfStatement__Consequent, "IfStatement::consequent")                       \
-  F(IfStatement__Alternate, "IfStatement::alternate")                         \
-  F(Import__ModuleSpecifier, "Import::moduleSpecifier")                       \
-  F(Import__DefaultBinding, "Import::defaultBinding")                         \
-  F(Import__NamedImports, "Import::namedImports")                             \
-  F(ImportNamespace__ModuleSpecifier, "ImportNamespace::moduleSpecifier")     \
-  F(ImportNamespace__DefaultBinding, "ImportNamespace::defaultBinding")       \
-  F(ImportNamespace__NamespaceBinding, "ImportNamespace::namespaceBinding")   \
-  F(ImportSpecifier__Name, "ImportSpecifier::name")                           \
-  F(ImportSpecifier__Binding, "ImportSpecifier::binding")                     \
-  F(LabelledStatement__Label, "LabelledStatement::label")                     \
-  F(LabelledStatement__Body, "LabelledStatement::body")                       \
-  F(LazyArrowExpressionWithExpression__IsAsync,                               \
-    "LazyArrowExpressionWithExpression::isAsync")                             \
-  F(LazyArrowExpressionWithExpression__Length,                                \
-    "LazyArrowExpressionWithExpression::length")                              \
-  F(LazyArrowExpressionWithExpression__ContentsSkip,                          \
-    "LazyArrowExpressionWithExpression::contents_skip")                       \
-  F(LazyArrowExpressionWithExpression__Contents,                              \
-    "LazyArrowExpressionWithExpression::contents")                            \
-  F(LazyArrowExpressionWithFunctionBody__IsAsync,                             \
-    "LazyArrowExpressionWithFunctionBody::isAsync")                           \
-  F(LazyArrowExpressionWithFunctionBody__Length,                              \
-    "LazyArrowExpressionWithFunctionBody::length")                            \
-  F(LazyArrowExpressionWithFunctionBody__Directives,                          \
-    "LazyArrowExpressionWithFunctionBody::directives")                        \
-  F(LazyArrowExpressionWithFunctionBody__ContentsSkip,                        \
-    "LazyArrowExpressionWithFunctionBody::contents_skip")                     \
-  F(LazyArrowExpressionWithFunctionBody__Contents,                            \
-    "LazyArrowExpressionWithFunctionBody::contents")                          \
-  F(LazyFunctionDeclaration__IsAsync, "LazyFunctionDeclaration::isAsync")     \
-  F(LazyFunctionDeclaration__IsGenerator,                                     \
-    "LazyFunctionDeclaration::isGenerator")                                   \
-  F(LazyFunctionDeclaration__Name, "LazyFunctionDeclaration::name")           \
-  F(LazyFunctionDeclaration__Length, "LazyFunctionDeclaration::length")       \
-  F(LazyFunctionDeclaration__Directives,                                      \
-    "LazyFunctionDeclaration::directives")                                    \
-  F(LazyFunctionDeclaration__ContentsSkip,                                    \
-    "LazyFunctionDeclaration::contents_skip")                                 \
-  F(LazyFunctionDeclaration__Contents, "LazyFunctionDeclaration::contents")   \
-  F(LazyFunctionExpression__IsAsync, "LazyFunctionExpression::isAsync")       \
-  F(LazyFunctionExpression__IsGenerator,                                      \
-    "LazyFunctionExpression::isGenerator")                                    \
-  F(LazyFunctionExpression__Name, "LazyFunctionExpression::name")             \
-  F(LazyFunctionExpression__Length, "LazyFunctionExpression::length")         \
-  F(LazyFunctionExpression__Directives, "LazyFunctionExpression::directives") \
-  F(LazyFunctionExpression__ContentsSkip,                                     \
-    "LazyFunctionExpression::contents_skip")                                  \
-  F(LazyFunctionExpression__Contents, "LazyFunctionExpression::contents")     \
-  F(LazyGetter__Name, "LazyGetter::name")                                     \
-  F(LazyGetter__Directives, "LazyGetter::directives")                         \
-  F(LazyGetter__ContentsSkip, "LazyGetter::contents_skip")                    \
-  F(LazyGetter__Contents, "LazyGetter::contents")                             \
-  F(LazyMethod__IsAsync, "LazyMethod::isAsync")                               \
-  F(LazyMethod__IsGenerator, "LazyMethod::isGenerator")                       \
-  F(LazyMethod__Name, "LazyMethod::name")                                     \
-  F(LazyMethod__Length, "LazyMethod::length")                                 \
-  F(LazyMethod__Directives, "LazyMethod::directives")                         \
-  F(LazyMethod__ContentsSkip, "LazyMethod::contents_skip")                    \
-  F(LazyMethod__Contents, "LazyMethod::contents")                             \
-  F(LazySetter__Name, "LazySetter::name")                                     \
-  F(LazySetter__Length, "LazySetter::length")                                 \
-  F(LazySetter__Directives, "LazySetter::directives")                         \
-  F(LazySetter__ContentsSkip, "LazySetter::contents_skip")                    \
-  F(LazySetter__Contents, "LazySetter::contents")                             \
-  F(LiteralBooleanExpression__Value, "LiteralBooleanExpression::value")       \
-  F(LiteralNumericExpression__Value, "LiteralNumericExpression::value")       \
-  F(LiteralPropertyName__Value, "LiteralPropertyName::value")                 \
-  F(LiteralRegExpExpression__Pattern, "LiteralRegExpExpression::pattern")     \
-  F(LiteralRegExpExpression__Flags, "LiteralRegExpExpression::flags")         \
-  F(LiteralStringExpression__Value, "LiteralStringExpression::value")         \
-  F(Module__Scope, "Module::scope")                                           \
-  F(Module__Directives, "Module::directives")                                 \
-  F(Module__Items, "Module::items")                                           \
-  F(NewExpression__Callee, "NewExpression::callee")                           \
-  F(NewExpression__Arguments, "NewExpression::arguments")                     \
-  F(ObjectAssignmentTarget__Properties, "ObjectAssignmentTarget::properties") \
-  F(ObjectBinding__Properties, "ObjectBinding::properties")                   \
-  F(ObjectExpression__Properties, "ObjectExpression::properties")             \
-  F(ReturnStatement__Expression, "ReturnStatement::expression")               \
-  F(Script__Scope, "Script::scope")                                           \
-  F(Script__Directives, "Script::directives")                                 \
-  F(Script__Statements, "Script::statements")                                 \
-  F(SetterContents__IsThisCaptured, "SetterContents::isThisCaptured")         \
-  F(SetterContents__ParameterScope, "SetterContents::parameterScope")         \
-  F(SetterContents__Param, "SetterContents::param")                           \
-  F(SetterContents__BodyScope, "SetterContents::bodyScope")                   \
-  F(SetterContents__Body, "SetterContents::body")                             \
-  F(ShorthandProperty__Name, "ShorthandProperty::name")                       \
-  F(SpreadElement__Expression, "SpreadElement::expression")                   \
-  F(StaticMemberAssignmentTarget__Object,                                     \
-    "StaticMemberAssignmentTarget::object")                                   \
-  F(StaticMemberAssignmentTarget__Property,                                   \
-    "StaticMemberAssignmentTarget::property")                                 \
-  F(StaticMemberExpression__Object, "StaticMemberExpression::object")         \
-  F(StaticMemberExpression__Property, "StaticMemberExpression::property")     \
-  F(SwitchCase__Test, "SwitchCase::test")                                     \
-  F(SwitchCase__Consequent, "SwitchCase::consequent")                         \
-  F(SwitchDefault__Consequent, "SwitchDefault::consequent")                   \
-  F(SwitchStatement__Discriminant, "SwitchStatement::discriminant")           \
-  F(SwitchStatement__Cases, "SwitchStatement::cases")                         \
-  F(SwitchStatementWithDefault__Discriminant,                                 \
-    "SwitchStatementWithDefault::discriminant")                               \
-  F(SwitchStatementWithDefault__PreDefaultCases,                              \
-    "SwitchStatementWithDefault::preDefaultCases")                            \
-  F(SwitchStatementWithDefault__DefaultCase,                                  \
-    "SwitchStatementWithDefault::defaultCase")                                \
-  F(SwitchStatementWithDefault__PostDefaultCases,                             \
-    "SwitchStatementWithDefault::postDefaultCases")                           \
-  F(TemplateElement__RawValue, "TemplateElement::rawValue")                   \
-  F(TemplateExpression__Tag, "TemplateExpression::tag")                       \
-  F(TemplateExpression__Elements, "TemplateExpression::elements")             \
-  F(ThrowStatement__Expression, "ThrowStatement::expression")                 \
-  F(TryCatchStatement__Body, "TryCatchStatement::body")                       \
-  F(TryCatchStatement__CatchClause, "TryCatchStatement::catchClause")         \
-  F(TryFinallyStatement__Body, "TryFinallyStatement::body")                   \
-  F(TryFinallyStatement__CatchClause, "TryFinallyStatement::catchClause")     \
-  F(TryFinallyStatement__Finalizer, "TryFinallyStatement::finalizer")         \
-  F(UnaryExpression__Operator, "UnaryExpression::operator")                   \
-  F(UnaryExpression__Operand, "UnaryExpression::operand")                     \
-  F(UpdateExpression__IsPrefix, "UpdateExpression::isPrefix")                 \
-  F(UpdateExpression__Operator, "UpdateExpression::operator")                 \
-  F(UpdateExpression__Operand, "UpdateExpression::operand")                   \
-  F(VariableDeclaration__Kind, "VariableDeclaration::kind")                   \
-  F(VariableDeclaration__Declarators, "VariableDeclaration::declarators")     \
-  F(VariableDeclarator__Binding, "VariableDeclarator::binding")               \
-  F(VariableDeclarator__Init, "VariableDeclarator::init")                     \
-  F(WhileStatement__Test, "WhileStatement::test")                             \
-  F(WhileStatement__Body, "WhileStatement::body")                             \
-  F(WithStatement__Object, "WithStatement::object")                           \
-  F(WithStatement__Body, "WithStatement::body")                               \
-  F(YieldExpression__Expression, "YieldExpression::expression")               \
-  F(YieldStarExpression__Expression, "YieldStarExpression::expression")
-
-enum class BinASTInterfaceAndField : uint16_t {
-#define EMIT_ENUM(name, _) name,
-  FOR_EACH_BIN_INTERFACE_AND_FIELD(EMIT_ENUM)
-#undef EMIT_ENUM
-};
-
-// Strongly typed iterations through the fields of interfaces.
-//
-// Each of these macros accepts the following arguments:
-// - F: callback
-// - PRIMITIVE: wrapper for primitive type names - called as
-// `PRIMITIVE(typename)`
-// - INTERFACE: wrapper for non-optional interface type names - called as
-// `INTERFACE(typename)`
-// - OPTIONAL_INTERFACE: wrapper for optional interface type names - called as
-// `OPTIONAL_INTERFACE(typename)` where
-//      `typename` is the name of the interface (e.g. no `Maybe` prefix)
-// - LIST: wrapper for list types - called as `LIST(list_typename,
-// element_typename)`
-// - SUM: wrapper for non-optional type names - called as `SUM(typename)`
-// - OPTIONAL_SUM: wrapper for optional sum type names - called as
-// `OPTIONAL_SUM(typename)` where
-//      `typename` is the name of the sum (e.g. no `Maybe` prefix)
-// - STRING_ENUM: wrapper for non-optional string enum types - called as
-// `STRING_ENUNM(typename)`
-// - OPTIONAL_STRING_ENUM: wrapper for optional string enum type names - called
-// as `OPTIONAL_STRING_ENUM(typename)` where
-//      `typename` is the name of the string enum (e.g. no `Maybe` prefix)
-
-// Strongly typed iteration through the fields of interface _Null.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_NULL(                             \
-    F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM, \
-    STRING_ENUM, OPTIONAL_STRING_ENUM)
-
-// The number of fields of interface .
-const size_t BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_NULL = 0;
-
-// Strongly typed iteration through the fields of interface
-// ArrayAssignmentTarget.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_ARRAY_ASSIGNMENT_TARGET(          \
-    F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM, \
-    STRING_ENUM, OPTIONAL_STRING_ENUM)                                    \
-  F(ArrayAssignmentTarget, Elements, 0,                                   \
-    LIST(ListOfAssignmentTargetOrAssignmentTargetWithInitializer,         \
-         AssignmentTargetOrAssignmentTargetWithInitializer),              \
-    "ArrayAssignmentTarget::elements")                                    \
-  F(ArrayAssignmentTarget, Rest, 1, OPTIONAL_SUM(AssignmentTarget),       \
-    "ArrayAssignmentTarget::rest")
-
-// The number of fields of interface ArrayAssignmentTarget.
-const size_t BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_ARRAY_ASSIGNMENT_TARGET = 2;
-
-// Strongly typed iteration through the fields of interface ArrayBinding.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_ARRAY_BINDING(                    \
-    F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM, \
-    STRING_ENUM, OPTIONAL_STRING_ENUM)                                    \
-  F(ArrayBinding, Elements, 0,                                            \
-    LIST(ListOfOptionalBindingOrBindingWithInitializer,                   \
-         OptionalBindingOrBindingWithInitializer),                        \
-    "ArrayBinding::elements")                                             \
-  F(ArrayBinding, Rest, 1, OPTIONAL_SUM(Binding), "ArrayBinding::rest")
-
-// The number of fields of interface ArrayBinding.
-const size_t BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_ARRAY_BINDING = 2;
-
-// Strongly typed iteration through the fields of interface ArrayExpression.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_ARRAY_EXPRESSION(                 \
-    F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM, \
-    STRING_ENUM, OPTIONAL_STRING_ENUM)                                    \
-  F(ArrayExpression, Elements, 0,                                         \
-    LIST(ListOfOptionalSpreadElementOrExpression,                         \
-         OptionalSpreadElementOrExpression),                              \
-    "ArrayExpression::elements")
-
-// The number of fields of interface ArrayExpression.
-const size_t BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_ARRAY_EXPRESSION = 1;
-
-// Strongly typed iteration through the fields of interface
-// ArrowExpressionContentsWithExpression.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_ARROW_EXPRESSION_CONTENTS_WITH_EXPRESSION( \
-    F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM,          \
-    STRING_ENUM, OPTIONAL_STRING_ENUM)                                             \
-  F(ArrowExpressionContentsWithExpression, ParameterScope, 0,                      \
-    INTERFACE(AssertedParameterScope),                                             \
-    "ArrowExpressionContentsWithExpression::parameterScope")                       \
-  F(ArrowExpressionContentsWithExpression, Params, 1,                              \
-    INTERFACE(FormalParameters),                                                   \
-    "ArrowExpressionContentsWithExpression::params")                               \
-  F(ArrowExpressionContentsWithExpression, BodyScope, 2,                           \
-    INTERFACE(AssertedVarScope),                                                   \
-    "ArrowExpressionContentsWithExpression::bodyScope")                            \
-  F(ArrowExpressionContentsWithExpression, Body, 3, SUM(Expression),               \
-    "ArrowExpressionContentsWithExpression::body")
-
-// The number of fields of interface ArrowExpressionContentsWithExpression.
-const size_t
-    BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_ARROW_EXPRESSION_CONTENTS_WITH_EXPRESSION =
-        4;
-
-// Strongly typed iteration through the fields of interface
-// ArrowExpressionContentsWithFunctionBody.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_ARROW_EXPRESSION_CONTENTS_WITH_FUNCTION_BODY( \
-    F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM,             \
-    STRING_ENUM, OPTIONAL_STRING_ENUM)                                                \
-  F(ArrowExpressionContentsWithFunctionBody, ParameterScope, 0,                       \
-    INTERFACE(AssertedParameterScope),                                                \
-    "ArrowExpressionContentsWithFunctionBody::parameterScope")                        \
-  F(ArrowExpressionContentsWithFunctionBody, Params, 1,                               \
-    INTERFACE(FormalParameters),                                                      \
-    "ArrowExpressionContentsWithFunctionBody::params")                                \
-  F(ArrowExpressionContentsWithFunctionBody, BodyScope, 2,                            \
-    INTERFACE(AssertedVarScope),                                                      \
-    "ArrowExpressionContentsWithFunctionBody::bodyScope")                             \
-  F(ArrowExpressionContentsWithFunctionBody, Body, 3,                                 \
-    LIST(FunctionBody, Statement),                                                    \
-    "ArrowExpressionContentsWithFunctionBody::body")
-
-// The number of fields of interface ArrowExpressionContentsWithFunctionBody.
-const size_t
-    BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_ARROW_EXPRESSION_CONTENTS_WITH_FUNCTION_BODY =
-        4;
-
-// Strongly typed iteration through the fields of interface AssertedBlockScope.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_ASSERTED_BLOCK_SCOPE(             \
-    F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM, \
-    STRING_ENUM, OPTIONAL_STRING_ENUM)                                    \
-  F(AssertedBlockScope, DeclaredNames, 0,                                 \
-    LIST(ListOfAssertedDeclaredName, AssertedDeclaredName),               \
-    "AssertedBlockScope::declaredNames")                                  \
-  F(AssertedBlockScope, HasDirectEval, 1, PRIMITIVE(Boolean),             \
-    "AssertedBlockScope::hasDirectEval")
-
-// The number of fields of interface AssertedBlockScope.
-const size_t BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_ASSERTED_BLOCK_SCOPE = 2;
-
-// Strongly typed iteration through the fields of interface AssertedBoundName.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_ASSERTED_BOUND_NAME(              \
-    F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM, \
-    STRING_ENUM, OPTIONAL_STRING_ENUM)                                    \
-  F(AssertedBoundName, Name, 0, PRIMITIVE(IdentifierName),                \
-    "AssertedBoundName::name")                                            \
-  F(AssertedBoundName, IsCaptured, 1, PRIMITIVE(Boolean),                 \
-    "AssertedBoundName::isCaptured")
-
-// The number of fields of interface AssertedBoundName.
-const size_t BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_ASSERTED_BOUND_NAME = 2;
-
-// Strongly typed iteration through the fields of interface
-// AssertedBoundNamesScope.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_ASSERTED_BOUND_NAMES_SCOPE(       \
-    F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM, \
-    STRING_ENUM, OPTIONAL_STRING_ENUM)                                    \
-  F(AssertedBoundNamesScope, BoundNames, 0,                               \
-    LIST(ListOfAssertedBoundName, AssertedBoundName),                     \
-    "AssertedBoundNamesScope::boundNames")                                \
-  F(AssertedBoundNamesScope, HasDirectEval, 1, PRIMITIVE(Boolean),        \
-    "AssertedBoundNamesScope::hasDirectEval")
-
-// The number of fields of interface AssertedBoundNamesScope.
-const size_t BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_ASSERTED_BOUND_NAMES_SCOPE =
-    2;
-
-// Strongly typed iteration through the fields of interface
-// AssertedDeclaredName.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_ASSERTED_DECLARED_NAME(           \
-    F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM, \
-    STRING_ENUM, OPTIONAL_STRING_ENUM)                                    \
-  F(AssertedDeclaredName, Name, 0, PRIMITIVE(IdentifierName),             \
-    "AssertedDeclaredName::name")                                         \
-  F(AssertedDeclaredName, Kind, 1, STRING_ENUM(AssertedDeclaredKind),     \
-    "AssertedDeclaredName::kind")                                         \
-  F(AssertedDeclaredName, IsCaptured, 2, PRIMITIVE(Boolean),              \
-    "AssertedDeclaredName::isCaptured")
-
-// The number of fields of interface AssertedDeclaredName.
-const size_t BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_ASSERTED_DECLARED_NAME = 3;
-
-// Strongly typed iteration through the fields of interface
-// AssertedParameterName.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_ASSERTED_PARAMETER_NAME(          \
-    F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM, \
-    STRING_ENUM, OPTIONAL_STRING_ENUM)                                    \
-  F(AssertedParameterName, Name, 0, PRIMITIVE(IdentifierName),            \
-    "AssertedParameterName::name")                                        \
-  F(AssertedParameterName, IsCaptured, 1, PRIMITIVE(Boolean),             \
-    "AssertedParameterName::isCaptured")
-
-// The number of fields of interface AssertedParameterName.
-const size_t BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_ASSERTED_PARAMETER_NAME = 2;
-
-// Strongly typed iteration through the fields of interface
-// AssertedParameterScope.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_ASSERTED_PARAMETER_SCOPE(         \
-    F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM, \
-    STRING_ENUM, OPTIONAL_STRING_ENUM)                                    \
-  F(AssertedParameterScope, ParamNames, 0,                                \
-    LIST(ListOfAssertedMaybePositionalParameterName,                      \
-         AssertedMaybePositionalParameterName),                           \
-    "AssertedParameterScope::paramNames")                                 \
-  F(AssertedParameterScope, HasDirectEval, 1, PRIMITIVE(Boolean),         \
-    "AssertedParameterScope::hasDirectEval")                              \
-  F(AssertedParameterScope, IsSimpleParameterList, 2, PRIMITIVE(Boolean), \
-    "AssertedParameterScope::isSimpleParameterList")
-
-// The number of fields of interface AssertedParameterScope.
-const size_t BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_ASSERTED_PARAMETER_SCOPE = 3;
-
-// Strongly typed iteration through the fields of interface
-// AssertedPositionalParameterName.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_ASSERTED_POSITIONAL_PARAMETER_NAME( \
-    F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM,   \
-    STRING_ENUM, OPTIONAL_STRING_ENUM)                                      \
-  F(AssertedPositionalParameterName, Index, 0, PRIMITIVE(UnsignedLong),     \
-    "AssertedPositionalParameterName::index")                               \
-  F(AssertedPositionalParameterName, Name, 1, PRIMITIVE(IdentifierName),    \
-    "AssertedPositionalParameterName::name")                                \
-  F(AssertedPositionalParameterName, IsCaptured, 2, PRIMITIVE(Boolean),     \
-    "AssertedPositionalParameterName::isCaptured")
-
-// The number of fields of interface AssertedPositionalParameterName.
-const size_t
-    BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_ASSERTED_POSITIONAL_PARAMETER_NAME = 3;
-
-// Strongly typed iteration through the fields of interface
-// AssertedRestParameterName.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_ASSERTED_REST_PARAMETER_NAME(     \
-    F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM, \
-    STRING_ENUM, OPTIONAL_STRING_ENUM)                                    \
-  F(AssertedRestParameterName, Name, 0, PRIMITIVE(IdentifierName),        \
-    "AssertedRestParameterName::name")                                    \
-  F(AssertedRestParameterName, IsCaptured, 1, PRIMITIVE(Boolean),         \
-    "AssertedRestParameterName::isCaptured")
-
-// The number of fields of interface AssertedRestParameterName.
-const size_t BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_ASSERTED_REST_PARAMETER_NAME =
-    2;
-
-// Strongly typed iteration through the fields of interface
-// AssertedScriptGlobalScope.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_ASSERTED_SCRIPT_GLOBAL_SCOPE(     \
-    F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM, \
-    STRING_ENUM, OPTIONAL_STRING_ENUM)                                    \
-  F(AssertedScriptGlobalScope, DeclaredNames, 0,                          \
-    LIST(ListOfAssertedDeclaredName, AssertedDeclaredName),               \
-    "AssertedScriptGlobalScope::declaredNames")                           \
-  F(AssertedScriptGlobalScope, HasDirectEval, 1, PRIMITIVE(Boolean),      \
-    "AssertedScriptGlobalScope::hasDirectEval")
-
-// The number of fields of interface AssertedScriptGlobalScope.
-const size_t BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_ASSERTED_SCRIPT_GLOBAL_SCOPE =
-    2;
-
-// Strongly typed iteration through the fields of interface AssertedVarScope.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_ASSERTED_VAR_SCOPE(               \
-    F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM, \
-    STRING_ENUM, OPTIONAL_STRING_ENUM)                                    \
-  F(AssertedVarScope, DeclaredNames, 0,                                   \
-    LIST(ListOfAssertedDeclaredName, AssertedDeclaredName),               \
-    "AssertedVarScope::declaredNames")                                    \
-  F(AssertedVarScope, HasDirectEval, 1, PRIMITIVE(Boolean),               \
-    "AssertedVarScope::hasDirectEval")
-
-// The number of fields of interface AssertedVarScope.
-const size_t BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_ASSERTED_VAR_SCOPE = 2;
-
-// Strongly typed iteration through the fields of interface
-// AssignmentExpression.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_ASSIGNMENT_EXPRESSION(            \
-    F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM, \
-    STRING_ENUM, OPTIONAL_STRING_ENUM)                                    \
-  F(AssignmentExpression, Binding, 0, SUM(AssignmentTarget),              \
-    "AssignmentExpression::binding")                                      \
-  F(AssignmentExpression, Expression, 1, SUM(Expression),                 \
-    "AssignmentExpression::expression")
-
-// The number of fields of interface AssignmentExpression.
-const size_t BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_ASSIGNMENT_EXPRESSION = 2;
-
-// Strongly typed iteration through the fields of interface
-// AssignmentTargetIdentifier.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_ASSIGNMENT_TARGET_IDENTIFIER(     \
-    F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM, \
-    STRING_ENUM, OPTIONAL_STRING_ENUM)                                    \
-  F(AssignmentTargetIdentifier, Name, 0, PRIMITIVE(IdentifierName),       \
-    "AssignmentTargetIdentifier::name")
-
-// The number of fields of interface AssignmentTargetIdentifier.
-const size_t BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_ASSIGNMENT_TARGET_IDENTIFIER =
-    1;
-
-// Strongly typed iteration through the fields of interface
-// AssignmentTargetPropertyIdentifier.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_ASSIGNMENT_TARGET_PROPERTY_IDENTIFIER( \
-    F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM,      \
-    STRING_ENUM, OPTIONAL_STRING_ENUM)                                         \
-  F(AssignmentTargetPropertyIdentifier, Binding, 0,                            \
-    INTERFACE(AssignmentTargetIdentifier),                                     \
-    "AssignmentTargetPropertyIdentifier::binding")                             \
-  F(AssignmentTargetPropertyIdentifier, Init, 1, OPTIONAL_SUM(Expression),     \
-    "AssignmentTargetPropertyIdentifier::init")
-
-// The number of fields of interface AssignmentTargetPropertyIdentifier.
-const size_t
-    BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_ASSIGNMENT_TARGET_PROPERTY_IDENTIFIER =
-        2;
-
-// Strongly typed iteration through the fields of interface
-// AssignmentTargetPropertyProperty.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_ASSIGNMENT_TARGET_PROPERTY_PROPERTY( \
-    F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM,    \
-    STRING_ENUM, OPTIONAL_STRING_ENUM)                                       \
-  F(AssignmentTargetPropertyProperty, Name, 0, SUM(PropertyName),            \
-    "AssignmentTargetPropertyProperty::name")                                \
-  F(AssignmentTargetPropertyProperty, Binding, 1,                            \
-    SUM(AssignmentTargetOrAssignmentTargetWithInitializer),                  \
-    "AssignmentTargetPropertyProperty::binding")
-
-// The number of fields of interface AssignmentTargetPropertyProperty.
-const size_t
-    BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_ASSIGNMENT_TARGET_PROPERTY_PROPERTY =
-        2;
-
-// Strongly typed iteration through the fields of interface
-// AssignmentTargetWithInitializer.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_ASSIGNMENT_TARGET_WITH_INITIALIZER( \
-    F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM,   \
-    STRING_ENUM, OPTIONAL_STRING_ENUM)                                      \
-  F(AssignmentTargetWithInitializer, Binding, 0, SUM(AssignmentTarget),     \
-    "AssignmentTargetWithInitializer::binding")                             \
-  F(AssignmentTargetWithInitializer, Init, 1, SUM(Expression),              \
-    "AssignmentTargetWithInitializer::init")
-
-// The number of fields of interface AssignmentTargetWithInitializer.
-const size_t
-    BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_ASSIGNMENT_TARGET_WITH_INITIALIZER = 2;
-
-// Strongly typed iteration through the fields of interface AwaitExpression.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_AWAIT_EXPRESSION(                 \
-    F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM, \
-    STRING_ENUM, OPTIONAL_STRING_ENUM)                                    \
-  F(AwaitExpression, Expression, 0, SUM(Expression),                      \
-    "AwaitExpression::expression")
-
-// The number of fields of interface AwaitExpression.
-const size_t BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_AWAIT_EXPRESSION = 1;
-
-// Strongly typed iteration through the fields of interface BinaryExpression.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_BINARY_EXPRESSION(                \
-    F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM, \
-    STRING_ENUM, OPTIONAL_STRING_ENUM)                                    \
-  F(BinaryExpression, Operator, 0, STRING_ENUM(BinaryOperator),           \
-    "BinaryExpression::operator")                                         \
-  F(BinaryExpression, Left, 1, SUM(Expression), "BinaryExpression::left") \
-  F(BinaryExpression, Right, 2, SUM(Expression), "BinaryExpression::right")
-
-// The number of fields of interface BinaryExpression.
-const size_t BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_BINARY_EXPRESSION = 3;
-
-// Strongly typed iteration through the fields of interface BindingIdentifier.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_BINDING_IDENTIFIER(               \
-    F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM, \
-    STRING_ENUM, OPTIONAL_STRING_ENUM)                                    \
-  F(BindingIdentifier, Name, 0, PRIMITIVE(IdentifierName),                \
-    "BindingIdentifier::name")
-
-// The number of fields of interface BindingIdentifier.
-const size_t BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_BINDING_IDENTIFIER = 1;
-
-// Strongly typed iteration through the fields of interface
-// BindingPropertyIdentifier.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_BINDING_PROPERTY_IDENTIFIER(      \
-    F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM, \
-    STRING_ENUM, OPTIONAL_STRING_ENUM)                                    \
-  F(BindingPropertyIdentifier, Binding, 0, INTERFACE(BindingIdentifier),  \
-    "BindingPropertyIdentifier::binding")                                 \
-  F(BindingPropertyIdentifier, Init, 1, OPTIONAL_SUM(Expression),         \
-    "BindingPropertyIdentifier::init")
-
-// The number of fields of interface BindingPropertyIdentifier.
-const size_t BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_BINDING_PROPERTY_IDENTIFIER =
-    2;
-
-// Strongly typed iteration through the fields of interface
-// BindingPropertyProperty.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_BINDING_PROPERTY_PROPERTY(             \
-    F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM,      \
-    STRING_ENUM, OPTIONAL_STRING_ENUM)                                         \
-  F(BindingPropertyProperty, Name, 0, SUM(PropertyName),                       \
-    "BindingPropertyProperty::name")                                           \
-  F(BindingPropertyProperty, Binding, 1, SUM(BindingOrBindingWithInitializer), \
-    "BindingPropertyProperty::binding")
-
-// The number of fields of interface BindingPropertyProperty.
-const size_t BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_BINDING_PROPERTY_PROPERTY = 2;
-
-// Strongly typed iteration through the fields of interface
-// BindingWithInitializer.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_BINDING_WITH_INITIALIZER(         \
-    F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM, \
-    STRING_ENUM, OPTIONAL_STRING_ENUM)                                    \
-  F(BindingWithInitializer, Binding, 0, SUM(Binding),                     \
-    "BindingWithInitializer::binding")                                    \
-  F(BindingWithInitializer, Init, 1, SUM(Expression),                     \
-    "BindingWithInitializer::init")
-
-// The number of fields of interface BindingWithInitializer.
-const size_t BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_BINDING_WITH_INITIALIZER = 2;
-
-// Strongly typed iteration through the fields of interface Block.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_BLOCK(                            \
-    F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM, \
-    STRING_ENUM, OPTIONAL_STRING_ENUM)                                    \
-  F(Block, Scope, 0, INTERFACE(AssertedBlockScope), "Block::scope")       \
-  F(Block, Statements, 1, LIST(ListOfStatement, Statement), "Block::statements")
-
-// The number of fields of interface Block.
-const size_t BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_BLOCK = 2;
-
-// Strongly typed iteration through the fields of interface BreakStatement.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_BREAK_STATEMENT(                  \
-    F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM, \
-    STRING_ENUM, OPTIONAL_STRING_ENUM)                                    \
-  F(BreakStatement, Label, 0, PRIMITIVE(MaybeString), "BreakStatement::label")
-
-// The number of fields of interface BreakStatement.
-const size_t BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_BREAK_STATEMENT = 1;
-
-// Strongly typed iteration through the fields of interface CallExpression.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_CALL_EXPRESSION(                      \
-    F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM,     \
-    STRING_ENUM, OPTIONAL_STRING_ENUM)                                        \
-  F(CallExpression, Callee, 0, SUM(ExpressionOrSuper),                        \
-    "CallExpression::callee")                                                 \
-  F(CallExpression, Arguments, 1, LIST(Arguments, SpreadElementOrExpression), \
-    "CallExpression::arguments")
-
-// The number of fields of interface CallExpression.
-const size_t BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_CALL_EXPRESSION = 2;
-
-// Strongly typed iteration through the fields of interface CatchClause.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_CATCH_CLAUSE(                     \
-    F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM, \
-    STRING_ENUM, OPTIONAL_STRING_ENUM)                                    \
-  F(CatchClause, BindingScope, 0, INTERFACE(AssertedBoundNamesScope),     \
-    "CatchClause::bindingScope")                                          \
-  F(CatchClause, Binding, 1, SUM(Binding), "CatchClause::binding")        \
-  F(CatchClause, Body, 2, INTERFACE(Block), "CatchClause::body")
-
-// The number of fields of interface CatchClause.
-const size_t BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_CATCH_CLAUSE = 3;
-
-// Strongly typed iteration through the fields of interface ClassDeclaration.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_CLASS_DECLARATION(                 \
-    F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM,  \
-    STRING_ENUM, OPTIONAL_STRING_ENUM)                                     \
-  F(ClassDeclaration, Name, 0, INTERFACE(BindingIdentifier),               \
-    "ClassDeclaration::name")                                              \
-  F(ClassDeclaration, Super, 1, OPTIONAL_SUM(Expression),                  \
-    "ClassDeclaration::super")                                             \
-  F(ClassDeclaration, Elements, 2, LIST(ListOfClassElement, ClassElement), \
-    "ClassDeclaration::elements")
-
-// The number of fields of interface ClassDeclaration.
-const size_t BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_CLASS_DECLARATION = 3;
-
-// Strongly typed iteration through the fields of interface ClassElement.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_CLASS_ELEMENT(                       \
-    F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM,    \
-    STRING_ENUM, OPTIONAL_STRING_ENUM)                                       \
-  F(ClassElement, IsStatic, 0, PRIMITIVE(Boolean), "ClassElement::isStatic") \
-  F(ClassElement, Method, 1, SUM(MethodDefinition), "ClassElement::method")
-
-// The number of fields of interface ClassElement.
-const size_t BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_CLASS_ELEMENT = 2;
-
-// Strongly typed iteration through the fields of interface ClassExpression.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_CLASS_EXPRESSION(                 \
-    F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM, \
-    STRING_ENUM, OPTIONAL_STRING_ENUM)                                    \
-  F(ClassExpression, Name, 0, OPTIONAL_INTERFACE(BindingIdentifier),      \
-    "ClassExpression::name")                                              \
-  F(ClassExpression, Super, 1, OPTIONAL_SUM(Expression),                  \
-    "ClassExpression::super")                                             \
-  F(ClassExpression, Elements, 2, LIST(ListOfClassElement, ClassElement), \
-    "ClassExpression::elements")
-
-// The number of fields of interface ClassExpression.
-const size_t BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_CLASS_EXPRESSION = 3;
-
-// Strongly typed iteration through the fields of interface
-// CompoundAssignmentExpression.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_COMPOUND_ASSIGNMENT_EXPRESSION(    \
-    F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM,  \
-    STRING_ENUM, OPTIONAL_STRING_ENUM)                                     \
-  F(CompoundAssignmentExpression, Operator, 0,                             \
-    STRING_ENUM(CompoundAssignmentOperator),                               \
-    "CompoundAssignmentExpression::operator")                              \
-  F(CompoundAssignmentExpression, Binding, 1, SUM(SimpleAssignmentTarget), \
-    "CompoundAssignmentExpression::binding")                               \
-  F(CompoundAssignmentExpression, Expression, 2, SUM(Expression),          \
-    "CompoundAssignmentExpression::expression")
-
-// The number of fields of interface CompoundAssignmentExpression.
-const size_t
-    BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_COMPOUND_ASSIGNMENT_EXPRESSION = 3;
-
-// Strongly typed iteration through the fields of interface
-// ComputedMemberAssignmentTarget.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_COMPUTED_MEMBER_ASSIGNMENT_TARGET( \
-    F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM,  \
-    STRING_ENUM, OPTIONAL_STRING_ENUM)                                     \
-  F(ComputedMemberAssignmentTarget, Object, 0, SUM(ExpressionOrSuper),     \
-    "ComputedMemberAssignmentTarget::object")                              \
-  F(ComputedMemberAssignmentTarget, Expression, 1, SUM(Expression),        \
-    "ComputedMemberAssignmentTarget::expression")
-
-// The number of fields of interface ComputedMemberAssignmentTarget.
-const size_t
-    BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_COMPUTED_MEMBER_ASSIGNMENT_TARGET = 2;
-
-// Strongly typed iteration through the fields of interface
-// ComputedMemberExpression.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_COMPUTED_MEMBER_EXPRESSION(       \
-    F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM, \
-    STRING_ENUM, OPTIONAL_STRING_ENUM)                                    \
-  F(ComputedMemberExpression, Object, 0, SUM(ExpressionOrSuper),          \
-    "ComputedMemberExpression::object")                                   \
-  F(ComputedMemberExpression, Expression, 1, SUM(Expression),             \
-    "ComputedMemberExpression::expression")
-
-// The number of fields of interface ComputedMemberExpression.
-const size_t BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_COMPUTED_MEMBER_EXPRESSION =
-    2;
-
-// Strongly typed iteration through the fields of interface
-// ComputedPropertyName.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_COMPUTED_PROPERTY_NAME(           \
-    F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM, \
-    STRING_ENUM, OPTIONAL_STRING_ENUM)                                    \
-  F(ComputedPropertyName, Expression, 0, SUM(Expression),                 \
-    "ComputedPropertyName::expression")
-
-// The number of fields of interface ComputedPropertyName.
-const size_t BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_COMPUTED_PROPERTY_NAME = 1;
-
-// Strongly typed iteration through the fields of interface
-// ConditionalExpression.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_CONDITIONAL_EXPRESSION(           \
-    F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM, \
-    STRING_ENUM, OPTIONAL_STRING_ENUM)                                    \
-  F(ConditionalExpression, Test, 0, SUM(Expression),                      \
-    "ConditionalExpression::test")                                        \
-  F(ConditionalExpression, Consequent, 1, SUM(Expression),                \
-    "ConditionalExpression::consequent")                                  \
-  F(ConditionalExpression, Alternate, 2, SUM(Expression),                 \
-    "ConditionalExpression::alternate")
-
-// The number of fields of interface ConditionalExpression.
-const size_t BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_CONDITIONAL_EXPRESSION = 3;
-
-// Strongly typed iteration through the fields of interface ContinueStatement.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_CONTINUE_STATEMENT(               \
-    F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM, \
-    STRING_ENUM, OPTIONAL_STRING_ENUM)                                    \
-  F(ContinueStatement, Label, 0, PRIMITIVE(MaybeString),                  \
-    "ContinueStatement::label")
-
-// The number of fields of interface ContinueStatement.
-const size_t BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_CONTINUE_STATEMENT = 1;
-
-// Strongly typed iteration through the fields of interface DataProperty.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_DATA_PROPERTY(                    \
-    F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM, \
-    STRING_ENUM, OPTIONAL_STRING_ENUM)                                    \
-  F(DataProperty, Name, 0, SUM(PropertyName), "DataProperty::name")       \
-  F(DataProperty, Expression, 1, SUM(Expression), "DataProperty::expression")
-
-// The number of fields of interface DataProperty.
-const size_t BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_DATA_PROPERTY = 2;
-
-// Strongly typed iteration through the fields of interface DebuggerStatement.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_DEBUGGER_STATEMENT(               \
-    F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM, \
-    STRING_ENUM, OPTIONAL_STRING_ENUM)
-
-// The number of fields of interface DebuggerStatement.
-const size_t BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_DEBUGGER_STATEMENT = 0;
-
-// Strongly typed iteration through the fields of interface Directive.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_DIRECTIVE(                        \
-    F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM, \
-    STRING_ENUM, OPTIONAL_STRING_ENUM)                                    \
-  F(Directive, RawValue, 0, PRIMITIVE(String), "Directive::rawValue")
-
-// The number of fields of interface Directive.
-const size_t BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_DIRECTIVE = 1;
-
-// Strongly typed iteration through the fields of interface DoWhileStatement.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_DO_WHILE_STATEMENT(               \
-    F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM, \
-    STRING_ENUM, OPTIONAL_STRING_ENUM)                                    \
-  F(DoWhileStatement, Test, 0, SUM(Expression), "DoWhileStatement::test") \
-  F(DoWhileStatement, Body, 1, SUM(Statement), "DoWhileStatement::body")
-
-// The number of fields of interface DoWhileStatement.
-const size_t BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_DO_WHILE_STATEMENT = 2;
-
-// Strongly typed iteration through the fields of interface
-// EagerArrowExpressionWithExpression.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_EAGER_ARROW_EXPRESSION_WITH_EXPRESSION( \
-    F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM,       \
-    STRING_ENUM, OPTIONAL_STRING_ENUM)                                          \
-  F(EagerArrowExpressionWithExpression, IsAsync, 0, PRIMITIVE(Boolean),         \
-    "EagerArrowExpressionWithExpression::isAsync")                              \
-  F(EagerArrowExpressionWithExpression, Length, 1, PRIMITIVE(UnsignedLong),     \
-    "EagerArrowExpressionWithExpression::length")                               \
-  F(EagerArrowExpressionWithExpression, Contents, 2,                            \
-    INTERFACE(ArrowExpressionContentsWithExpression),                           \
-    "EagerArrowExpressionWithExpression::contents")
-
-// The number of fields of interface EagerArrowExpressionWithExpression.
-const size_t
-    BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_EAGER_ARROW_EXPRESSION_WITH_EXPRESSION =
-        3;
-
-// Strongly typed iteration through the fields of interface
-// EagerArrowExpressionWithFunctionBody.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_EAGER_ARROW_EXPRESSION_WITH_FUNCTION_BODY( \
-    F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM,          \
-    STRING_ENUM, OPTIONAL_STRING_ENUM)                                             \
-  F(EagerArrowExpressionWithFunctionBody, IsAsync, 0, PRIMITIVE(Boolean),          \
-    "EagerArrowExpressionWithFunctionBody::isAsync")                               \
-  F(EagerArrowExpressionWithFunctionBody, Length, 1, PRIMITIVE(UnsignedLong),      \
-    "EagerArrowExpressionWithFunctionBody::length")                                \
-  F(EagerArrowExpressionWithFunctionBody, Directives, 2,                           \
-    LIST(ListOfDirective, Directive),                                              \
-    "EagerArrowExpressionWithFunctionBody::directives")                            \
-  F(EagerArrowExpressionWithFunctionBody, Contents, 3,                             \
-    INTERFACE(ArrowExpressionContentsWithFunctionBody),                            \
-    "EagerArrowExpressionWithFunctionBody::contents")
-
-// The number of fields of interface EagerArrowExpressionWithFunctionBody.
-const size_t
-    BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_EAGER_ARROW_EXPRESSION_WITH_FUNCTION_BODY =
-        4;
-
-// Strongly typed iteration through the fields of interface
-// EagerFunctionDeclaration.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_EAGER_FUNCTION_DECLARATION(            \
-    F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM,      \
-    STRING_ENUM, OPTIONAL_STRING_ENUM)                                         \
-  F(EagerFunctionDeclaration, IsAsync, 0, PRIMITIVE(Boolean),                  \
-    "EagerFunctionDeclaration::isAsync")                                       \
-  F(EagerFunctionDeclaration, IsGenerator, 1, PRIMITIVE(Boolean),              \
-    "EagerFunctionDeclaration::isGenerator")                                   \
-  F(EagerFunctionDeclaration, Name, 2, INTERFACE(BindingIdentifier),           \
-    "EagerFunctionDeclaration::name")                                          \
-  F(EagerFunctionDeclaration, Length, 3, PRIMITIVE(UnsignedLong),              \
-    "EagerFunctionDeclaration::length")                                        \
-  F(EagerFunctionDeclaration, Directives, 4, LIST(ListOfDirective, Directive), \
-    "EagerFunctionDeclaration::directives")                                    \
-  F(EagerFunctionDeclaration, Contents, 5,                                     \
-    INTERFACE(FunctionOrMethodContents), "EagerFunctionDeclaration::contents")
-
-// The number of fields of interface EagerFunctionDeclaration.
-const size_t BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_EAGER_FUNCTION_DECLARATION =
-    6;
-
-// Strongly typed iteration through the fields of interface
-// EagerFunctionExpression.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_EAGER_FUNCTION_EXPRESSION(            \
-    F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM,     \
-    STRING_ENUM, OPTIONAL_STRING_ENUM)                                        \
-  F(EagerFunctionExpression, IsAsync, 0, PRIMITIVE(Boolean),                  \
-    "EagerFunctionExpression::isAsync")                                       \
-  F(EagerFunctionExpression, IsGenerator, 1, PRIMITIVE(Boolean),              \
-    "EagerFunctionExpression::isGenerator")                                   \
-  F(EagerFunctionExpression, Name, 2, OPTIONAL_INTERFACE(BindingIdentifier),  \
-    "EagerFunctionExpression::name")                                          \
-  F(EagerFunctionExpression, Length, 3, PRIMITIVE(UnsignedLong),              \
-    "EagerFunctionExpression::length")                                        \
-  F(EagerFunctionExpression, Directives, 4, LIST(ListOfDirective, Directive), \
-    "EagerFunctionExpression::directives")                                    \
-  F(EagerFunctionExpression, Contents, 5,                                     \
-    INTERFACE(FunctionExpressionContents),                                    \
-    "EagerFunctionExpression::contents")
-
-// The number of fields of interface EagerFunctionExpression.
-const size_t BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_EAGER_FUNCTION_EXPRESSION = 6;
-
-// Strongly typed iteration through the fields of interface EagerGetter.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_EAGER_GETTER(                     \
-    F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM, \
-    STRING_ENUM, OPTIONAL_STRING_ENUM)                                    \
-  F(EagerGetter, Name, 0, SUM(PropertyName), "EagerGetter::name")         \
-  F(EagerGetter, Directives, 1, LIST(ListOfDirective, Directive),         \
-    "EagerGetter::directives")                                            \
-  F(EagerGetter, Contents, 2, INTERFACE(GetterContents),                  \
-    "EagerGetter::contents")
-
-// The number of fields of interface EagerGetter.
-const size_t BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_EAGER_GETTER = 3;
-
-// Strongly typed iteration through the fields of interface EagerMethod.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_EAGER_METHOD(                       \
-    F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM,   \
-    STRING_ENUM, OPTIONAL_STRING_ENUM)                                      \
-  F(EagerMethod, IsAsync, 0, PRIMITIVE(Boolean), "EagerMethod::isAsync")    \
-  F(EagerMethod, IsGenerator, 1, PRIMITIVE(Boolean),                        \
-    "EagerMethod::isGenerator")                                             \
-  F(EagerMethod, Name, 2, SUM(PropertyName), "EagerMethod::name")           \
-  F(EagerMethod, Length, 3, PRIMITIVE(UnsignedLong), "EagerMethod::length") \
-  F(EagerMethod, Directives, 4, LIST(ListOfDirective, Directive),           \
-    "EagerMethod::directives")                                              \
-  F(EagerMethod, Contents, 5, INTERFACE(FunctionOrMethodContents),          \
-    "EagerMethod::contents")
-
-// The number of fields of interface EagerMethod.
-const size_t BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_EAGER_METHOD = 6;
-
-// Strongly typed iteration through the fields of interface EagerSetter.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_EAGER_SETTER(                       \
-    F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM,   \
-    STRING_ENUM, OPTIONAL_STRING_ENUM)                                      \
-  F(EagerSetter, Name, 0, SUM(PropertyName), "EagerSetter::name")           \
-  F(EagerSetter, Length, 1, PRIMITIVE(UnsignedLong), "EagerSetter::length") \
-  F(EagerSetter, Directives, 2, LIST(ListOfDirective, Directive),           \
-    "EagerSetter::directives")                                              \
-  F(EagerSetter, Contents, 3, INTERFACE(SetterContents),                    \
-    "EagerSetter::contents")
-
-// The number of fields of interface EagerSetter.
-const size_t BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_EAGER_SETTER = 4;
-
-// Strongly typed iteration through the fields of interface EmptyStatement.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_EMPTY_STATEMENT(                  \
-    F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM, \
-    STRING_ENUM, OPTIONAL_STRING_ENUM)
-
-// The number of fields of interface EmptyStatement.
-const size_t BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_EMPTY_STATEMENT = 0;
-
-// Strongly typed iteration through the fields of interface Export.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_EXPORT(                           \
-    F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM, \
-    STRING_ENUM, OPTIONAL_STRING_ENUM)                                    \
-  F(Export, Declaration, 0,                                               \
-    SUM(FunctionDeclarationOrClassDeclarationOrVariableDeclaration),      \
-    "Export::declaration")
-
-// The number of fields of interface Export.
-const size_t BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_EXPORT = 1;
-
-// Strongly typed iteration through the fields of interface ExportAllFrom.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_EXPORT_ALL_FROM(                  \
-    F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM, \
-    STRING_ENUM, OPTIONAL_STRING_ENUM)                                    \
-  F(ExportAllFrom, ModuleSpecifier, 0, PRIMITIVE(String),                 \
-    "ExportAllFrom::moduleSpecifier")
-
-// The number of fields of interface ExportAllFrom.
-const size_t BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_EXPORT_ALL_FROM = 1;
-
-// Strongly typed iteration through the fields of interface ExportDefault.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_EXPORT_DEFAULT(                   \
-    F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM, \
-    STRING_ENUM, OPTIONAL_STRING_ENUM)                                    \
-  F(ExportDefault, Body, 0,                                               \
-    SUM(FunctionDeclarationOrClassDeclarationOrExpression),               \
-    "ExportDefault::body")
-
-// The number of fields of interface ExportDefault.
-const size_t BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_EXPORT_DEFAULT = 1;
-
-// Strongly typed iteration through the fields of interface ExportFrom.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_EXPORT_FROM(                      \
-    F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM, \
-    STRING_ENUM, OPTIONAL_STRING_ENUM)                                    \
-  F(ExportFrom, NamedExports, 0,                                          \
-    LIST(ListOfExportFromSpecifier, ExportFromSpecifier),                 \
-    "ExportFrom::namedExports")                                           \
-  F(ExportFrom, ModuleSpecifier, 1, PRIMITIVE(String),                    \
-    "ExportFrom::moduleSpecifier")
-
-// The number of fields of interface ExportFrom.
-const size_t BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_EXPORT_FROM = 2;
-
-// Strongly typed iteration through the fields of interface ExportFromSpecifier.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_EXPORT_FROM_SPECIFIER(            \
-    F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM, \
-    STRING_ENUM, OPTIONAL_STRING_ENUM)                                    \
-  F(ExportFromSpecifier, Name, 0, PRIMITIVE(IdentifierName),              \
-    "ExportFromSpecifier::name")                                          \
-  F(ExportFromSpecifier, ExportedName, 1, PRIMITIVE(MaybeIdentifierName), \
-    "ExportFromSpecifier::exportedName")
-
-// The number of fields of interface ExportFromSpecifier.
-const size_t BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_EXPORT_FROM_SPECIFIER = 2;
-
-// Strongly typed iteration through the fields of interface
-// ExportLocalSpecifier.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_EXPORT_LOCAL_SPECIFIER(           \
-    F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM, \
-    STRING_ENUM, OPTIONAL_STRING_ENUM)                                    \
-  F(ExportLocalSpecifier, Name, 0, INTERFACE(IdentifierExpression),       \
-    "ExportLocalSpecifier::name")                                         \
-  F(ExportLocalSpecifier, ExportedName, 1, PRIMITIVE(MaybePropertyKey),   \
-    "ExportLocalSpecifier::exportedName")
-
-// The number of fields of interface ExportLocalSpecifier.
-const size_t BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_EXPORT_LOCAL_SPECIFIER = 2;
-
-// Strongly typed iteration through the fields of interface ExportLocals.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_EXPORT_LOCALS(                    \
-    F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM, \
-    STRING_ENUM, OPTIONAL_STRING_ENUM)                                    \
-  F(ExportLocals, NamedExports, 0,                                        \
-    LIST(ListOfExportLocalSpecifier, ExportLocalSpecifier),               \
-    "ExportLocals::namedExports")
-
-// The number of fields of interface ExportLocals.
-const size_t BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_EXPORT_LOCALS = 1;
-
-// Strongly typed iteration through the fields of interface ExpressionStatement.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_EXPRESSION_STATEMENT(             \
-    F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM, \
-    STRING_ENUM, OPTIONAL_STRING_ENUM)                                    \
-  F(ExpressionStatement, Expression, 0, SUM(Expression),                  \
-    "ExpressionStatement::expression")
-
-// The number of fields of interface ExpressionStatement.
-const size_t BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_EXPRESSION_STATEMENT = 1;
-
-// Strongly typed iteration through the fields of interface ForInOfBinding.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_FOR_IN_OF_BINDING(                \
-    F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM, \
-    STRING_ENUM, OPTIONAL_STRING_ENUM)                                    \
-  F(ForInOfBinding, Kind, 0, STRING_ENUM(VariableDeclarationKind),        \
-    "ForInOfBinding::kind")                                               \
-  F(ForInOfBinding, Binding, 1, SUM(Binding), "ForInOfBinding::binding")
-
-// The number of fields of interface ForInOfBinding.
-const size_t BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_FOR_IN_OF_BINDING = 2;
-
-// Strongly typed iteration through the fields of interface ForInStatement.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_FOR_IN_STATEMENT(                 \
-    F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM, \
-    STRING_ENUM, OPTIONAL_STRING_ENUM)                                    \
-  F(ForInStatement, Left, 0, SUM(ForInOfBindingOrAssignmentTarget),       \
-    "ForInStatement::left")                                               \
-  F(ForInStatement, Right, 1, SUM(Expression), "ForInStatement::right")   \
-  F(ForInStatement, Body, 2, SUM(Statement), "ForInStatement::body")
-
-// The number of fields of interface ForInStatement.
-const size_t BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_FOR_IN_STATEMENT = 3;
-
-// Strongly typed iteration through the fields of interface ForOfStatement.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_FOR_OF_STATEMENT(                 \
-    F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM, \
-    STRING_ENUM, OPTIONAL_STRING_ENUM)                                    \
-  F(ForOfStatement, Left, 0, SUM(ForInOfBindingOrAssignmentTarget),       \
-    "ForOfStatement::left")                                               \
-  F(ForOfStatement, Right, 1, SUM(Expression), "ForOfStatement::right")   \
-  F(ForOfStatement, Body, 2, SUM(Statement), "ForOfStatement::body")
-
-// The number of fields of interface ForOfStatement.
-const size_t BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_FOR_OF_STATEMENT = 3;
-
-// Strongly typed iteration through the fields of interface ForStatement.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_FOR_STATEMENT(                         \
-    F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM,      \
-    STRING_ENUM, OPTIONAL_STRING_ENUM)                                         \
-  F(ForStatement, Init, 0, OPTIONAL_SUM(VariableDeclarationOrExpression),      \
-    "ForStatement::init")                                                      \
-  F(ForStatement, Test, 1, OPTIONAL_SUM(Expression), "ForStatement::test")     \
-  F(ForStatement, Update, 2, OPTIONAL_SUM(Expression), "ForStatement::update") \
-  F(ForStatement, Body, 3, SUM(Statement), "ForStatement::body")
-
-// The number of fields of interface ForStatement.
-const size_t BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_FOR_STATEMENT = 4;
-
-// Strongly typed iteration through the fields of interface FormalParameters.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_FORMAL_PARAMETERS(                \
-    F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM, \
-    STRING_ENUM, OPTIONAL_STRING_ENUM)                                    \
-  F(FormalParameters, Items, 0, LIST(ListOfParameter, Parameter),         \
-    "FormalParameters::items")                                            \
-  F(FormalParameters, Rest, 1, OPTIONAL_SUM(Binding), "FormalParameters::rest")
-
-// The number of fields of interface FormalParameters.
-const size_t BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_FORMAL_PARAMETERS = 2;
-
-// Strongly typed iteration through the fields of interface
-// FunctionExpressionContents.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_FUNCTION_EXPRESSION_CONTENTS(          \
-    F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM,      \
-    STRING_ENUM, OPTIONAL_STRING_ENUM)                                         \
-  F(FunctionExpressionContents, IsFunctionNameCaptured, 0, PRIMITIVE(Boolean), \
-    "FunctionExpressionContents::isFunctionNameCaptured")                      \
-  F(FunctionExpressionContents, IsThisCaptured, 1, PRIMITIVE(Boolean),         \
-    "FunctionExpressionContents::isThisCaptured")                              \
-  F(FunctionExpressionContents, ParameterScope, 2,                             \
-    INTERFACE(AssertedParameterScope),                                         \
-    "FunctionExpressionContents::parameterScope")                              \
-  F(FunctionExpressionContents, Params, 3, INTERFACE(FormalParameters),        \
-    "FunctionExpressionContents::params")                                      \
-  F(FunctionExpressionContents, BodyScope, 4, INTERFACE(AssertedVarScope),     \
-    "FunctionExpressionContents::bodyScope")                                   \
-  F(FunctionExpressionContents, Body, 5, LIST(FunctionBody, Statement),        \
-    "FunctionExpressionContents::body")
-
-// The number of fields of interface FunctionExpressionContents.
-const size_t BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_FUNCTION_EXPRESSION_CONTENTS =
-    6;
-
-// Strongly typed iteration through the fields of interface
-// FunctionOrMethodContents.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_FUNCTION_OR_METHOD_CONTENTS(      \
-    F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM, \
-    STRING_ENUM, OPTIONAL_STRING_ENUM)                                    \
-  F(FunctionOrMethodContents, IsThisCaptured, 0, PRIMITIVE(Boolean),      \
-    "FunctionOrMethodContents::isThisCaptured")                           \
-  F(FunctionOrMethodContents, ParameterScope, 1,                          \
-    INTERFACE(AssertedParameterScope),                                    \
-    "FunctionOrMethodContents::parameterScope")                           \
-  F(FunctionOrMethodContents, Params, 2, INTERFACE(FormalParameters),     \
-    "FunctionOrMethodContents::params")                                   \
-  F(FunctionOrMethodContents, BodyScope, 3, INTERFACE(AssertedVarScope),  \
-    "FunctionOrMethodContents::bodyScope")                                \
-  F(FunctionOrMethodContents, Body, 4, LIST(FunctionBody, Statement),     \
-    "FunctionOrMethodContents::body")
-
-// The number of fields of interface FunctionOrMethodContents.
-const size_t BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_FUNCTION_OR_METHOD_CONTENTS =
-    5;
-
-// Strongly typed iteration through the fields of interface GetterContents.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_GETTER_CONTENTS(                  \
-    F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM, \
-    STRING_ENUM, OPTIONAL_STRING_ENUM)                                    \
-  F(GetterContents, IsThisCaptured, 0, PRIMITIVE(Boolean),                \
-    "GetterContents::isThisCaptured")                                     \
-  F(GetterContents, BodyScope, 1, INTERFACE(AssertedVarScope),            \
-    "GetterContents::bodyScope")                                          \
-  F(GetterContents, Body, 2, LIST(FunctionBody, Statement),               \
-    "GetterContents::body")
-
-// The number of fields of interface GetterContents.
-const size_t BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_GETTER_CONTENTS = 3;
-
-// Strongly typed iteration through the fields of interface
-// IdentifierExpression.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_IDENTIFIER_EXPRESSION(            \
-    F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM, \
-    STRING_ENUM, OPTIONAL_STRING_ENUM)                                    \
-  F(IdentifierExpression, Name, 0, PRIMITIVE(IdentifierName),             \
-    "IdentifierExpression::name")
-
-// The number of fields of interface IdentifierExpression.
-const size_t BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_IDENTIFIER_EXPRESSION = 1;
-
-// Strongly typed iteration through the fields of interface IfStatement.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_IF_STATEMENT(                      \
-    F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM,  \
-    STRING_ENUM, OPTIONAL_STRING_ENUM)                                     \
-  F(IfStatement, Test, 0, SUM(Expression), "IfStatement::test")            \
-  F(IfStatement, Consequent, 1, SUM(Statement), "IfStatement::consequent") \
-  F(IfStatement, Alternate, 2, OPTIONAL_SUM(Statement),                    \
-    "IfStatement::alternate")
-
-// The number of fields of interface IfStatement.
-const size_t BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_IF_STATEMENT = 3;
-
-// Strongly typed iteration through the fields of interface Import.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_IMPORT(                               \
-    F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM,     \
-    STRING_ENUM, OPTIONAL_STRING_ENUM)                                        \
-  F(Import, ModuleSpecifier, 0, PRIMITIVE(String), "Import::moduleSpecifier") \
-  F(Import, DefaultBinding, 1, OPTIONAL_INTERFACE(BindingIdentifier),         \
-    "Import::defaultBinding")                                                 \
-  F(Import, NamedImports, 2, LIST(ListOfImportSpecifier, ImportSpecifier),    \
-    "Import::namedImports")
-
-// The number of fields of interface Import.
-const size_t BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_IMPORT = 3;
-
-// Strongly typed iteration through the fields of interface ImportNamespace.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_IMPORT_NAMESPACE(                      \
-    F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM,      \
-    STRING_ENUM, OPTIONAL_STRING_ENUM)                                         \
-  F(ImportNamespace, ModuleSpecifier, 0, PRIMITIVE(String),                    \
-    "ImportNamespace::moduleSpecifier")                                        \
-  F(ImportNamespace, DefaultBinding, 1, OPTIONAL_INTERFACE(BindingIdentifier), \
-    "ImportNamespace::defaultBinding")                                         \
-  F(ImportNamespace, NamespaceBinding, 2, INTERFACE(BindingIdentifier),        \
-    "ImportNamespace::namespaceBinding")
-
-// The number of fields of interface ImportNamespace.
-const size_t BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_IMPORT_NAMESPACE = 3;
-
-// Strongly typed iteration through the fields of interface ImportSpecifier.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_IMPORT_SPECIFIER(                 \
-    F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM, \
-    STRING_ENUM, OPTIONAL_STRING_ENUM)                                    \
-  F(ImportSpecifier, Name, 0, PRIMITIVE(MaybePropertyKey),                \
-    "ImportSpecifier::name")                                              \
-  F(ImportSpecifier, Binding, 1, INTERFACE(BindingIdentifier),            \
-    "ImportSpecifier::binding")
-
-// The number of fields of interface ImportSpecifier.
-const size_t BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_IMPORT_SPECIFIER = 2;
-
-// Strongly typed iteration through the fields of interface LabelledStatement.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_LABELLED_STATEMENT(               \
-    F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM, \
-    STRING_ENUM, OPTIONAL_STRING_ENUM)                                    \
-  F(LabelledStatement, Label, 0, PRIMITIVE(String),                       \
-    "LabelledStatement::label")                                           \
-  F(LabelledStatement, Body, 1, SUM(Statement), "LabelledStatement::body")
-
-// The number of fields of interface LabelledStatement.
-const size_t BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_LABELLED_STATEMENT = 2;
-
-// Strongly typed iteration through the fields of interface
-// LazyArrowExpressionWithExpression.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_LAZY_ARROW_EXPRESSION_WITH_EXPRESSION( \
-    F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM,      \
-    STRING_ENUM, OPTIONAL_STRING_ENUM)                                         \
-  F(LazyArrowExpressionWithExpression, IsAsync, 0, PRIMITIVE(Boolean),         \
-    "LazyArrowExpressionWithExpression::isAsync")                              \
-  F(LazyArrowExpressionWithExpression, Length, 1, PRIMITIVE(UnsignedLong),     \
-    "LazyArrowExpressionWithExpression::length")                               \
-  F(LazyArrowExpressionWithExpression, ContentsSkip, 2, PRIMITIVE(Lazy),       \
-    "LazyArrowExpressionWithExpression::contents_skip")                        \
-  F(LazyArrowExpressionWithExpression, Contents, 3,                            \
-    INTERFACE(ArrowExpressionContentsWithExpression),                          \
-    "LazyArrowExpressionWithExpression::contents")
-
-// The number of fields of interface LazyArrowExpressionWithExpression.
-const size_t
-    BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_LAZY_ARROW_EXPRESSION_WITH_EXPRESSION =
-        4;
-
-// Strongly typed iteration through the fields of interface
-// LazyArrowExpressionWithFunctionBody.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_LAZY_ARROW_EXPRESSION_WITH_FUNCTION_BODY( \
-    F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM,         \
-    STRING_ENUM, OPTIONAL_STRING_ENUM)                                            \
-  F(LazyArrowExpressionWithFunctionBody, IsAsync, 0, PRIMITIVE(Boolean),          \
-    "LazyArrowExpressionWithFunctionBody::isAsync")                               \
-  F(LazyArrowExpressionWithFunctionBody, Length, 1, PRIMITIVE(UnsignedLong),      \
-    "LazyArrowExpressionWithFunctionBody::length")                                \
-  F(LazyArrowExpressionWithFunctionBody, Directives, 2,                           \
-    LIST(ListOfDirective, Directive),                                             \
-    "LazyArrowExpressionWithFunctionBody::directives")                            \
-  F(LazyArrowExpressionWithFunctionBody, ContentsSkip, 3, PRIMITIVE(Lazy),        \
-    "LazyArrowExpressionWithFunctionBody::contents_skip")                         \
-  F(LazyArrowExpressionWithFunctionBody, Contents, 4,                             \
-    INTERFACE(ArrowExpressionContentsWithFunctionBody),                           \
-    "LazyArrowExpressionWithFunctionBody::contents")
-
-// The number of fields of interface LazyArrowExpressionWithFunctionBody.
-const size_t
-    BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_LAZY_ARROW_EXPRESSION_WITH_FUNCTION_BODY =
-        5;
-
-// Strongly typed iteration through the fields of interface
-// LazyFunctionDeclaration.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_LAZY_FUNCTION_DECLARATION(             \
-    F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM,      \
-    STRING_ENUM, OPTIONAL_STRING_ENUM)                                         \
-  F(LazyFunctionDeclaration, IsAsync, 0, PRIMITIVE(Boolean),                   \
-    "LazyFunctionDeclaration::isAsync")                                        \
-  F(LazyFunctionDeclaration, IsGenerator, 1, PRIMITIVE(Boolean),               \
-    "LazyFunctionDeclaration::isGenerator")                                    \
-  F(LazyFunctionDeclaration, Name, 2, INTERFACE(BindingIdentifier),            \
-    "LazyFunctionDeclaration::name")                                           \
-  F(LazyFunctionDeclaration, Length, 3, PRIMITIVE(UnsignedLong),               \
-    "LazyFunctionDeclaration::length")                                         \
-  F(LazyFunctionDeclaration, Directives, 4, LIST(ListOfDirective, Directive),  \
-    "LazyFunctionDeclaration::directives")                                     \
-  F(LazyFunctionDeclaration, ContentsSkip, 5, PRIMITIVE(Lazy),                 \
-    "LazyFunctionDeclaration::contents_skip")                                  \
-  F(LazyFunctionDeclaration, Contents, 6, INTERFACE(FunctionOrMethodContents), \
-    "LazyFunctionDeclaration::contents")
-
-// The number of fields of interface LazyFunctionDeclaration.
-const size_t BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_LAZY_FUNCTION_DECLARATION = 7;
-
-// Strongly typed iteration through the fields of interface
-// LazyFunctionExpression.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_LAZY_FUNCTION_EXPRESSION(            \
-    F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM,    \
-    STRING_ENUM, OPTIONAL_STRING_ENUM)                                       \
-  F(LazyFunctionExpression, IsAsync, 0, PRIMITIVE(Boolean),                  \
-    "LazyFunctionExpression::isAsync")                                       \
-  F(LazyFunctionExpression, IsGenerator, 1, PRIMITIVE(Boolean),              \
-    "LazyFunctionExpression::isGenerator")                                   \
-  F(LazyFunctionExpression, Name, 2, OPTIONAL_INTERFACE(BindingIdentifier),  \
-    "LazyFunctionExpression::name")                                          \
-  F(LazyFunctionExpression, Length, 3, PRIMITIVE(UnsignedLong),              \
-    "LazyFunctionExpression::length")                                        \
-  F(LazyFunctionExpression, Directives, 4, LIST(ListOfDirective, Directive), \
-    "LazyFunctionExpression::directives")                                    \
-  F(LazyFunctionExpression, ContentsSkip, 5, PRIMITIVE(Lazy),                \
-    "LazyFunctionExpression::contents_skip")                                 \
-  F(LazyFunctionExpression, Contents, 6,                                     \
-    INTERFACE(FunctionExpressionContents), "LazyFunctionExpression::contents")
-
-// The number of fields of interface LazyFunctionExpression.
-const size_t BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_LAZY_FUNCTION_EXPRESSION = 7;
-
-// Strongly typed iteration through the fields of interface LazyGetter.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_LAZY_GETTER(                           \
-    F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM,      \
-    STRING_ENUM, OPTIONAL_STRING_ENUM)                                         \
-  F(LazyGetter, Name, 0, SUM(PropertyName), "LazyGetter::name")                \
-  F(LazyGetter, Directives, 1, LIST(ListOfDirective, Directive),               \
-    "LazyGetter::directives")                                                  \
-  F(LazyGetter, ContentsSkip, 2, PRIMITIVE(Lazy), "LazyGetter::contents_skip") \
-  F(LazyGetter, Contents, 3, INTERFACE(GetterContents), "LazyGetter::contents")
-
-// The number of fields of interface LazyGetter.
-const size_t BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_LAZY_GETTER = 4;
-
-// Strongly typed iteration through the fields of interface LazyMethod.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_LAZY_METHOD(                           \
-    F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM,      \
-    STRING_ENUM, OPTIONAL_STRING_ENUM)                                         \
-  F(LazyMethod, IsAsync, 0, PRIMITIVE(Boolean), "LazyMethod::isAsync")         \
-  F(LazyMethod, IsGenerator, 1, PRIMITIVE(Boolean), "LazyMethod::isGenerator") \
-  F(LazyMethod, Name, 2, SUM(PropertyName), "LazyMethod::name")                \
-  F(LazyMethod, Length, 3, PRIMITIVE(UnsignedLong), "LazyMethod::length")      \
-  F(LazyMethod, Directives, 4, LIST(ListOfDirective, Directive),               \
-    "LazyMethod::directives")                                                  \
-  F(LazyMethod, ContentsSkip, 5, PRIMITIVE(Lazy), "LazyMethod::contents_skip") \
-  F(LazyMethod, Contents, 6, INTERFACE(FunctionOrMethodContents),              \
-    "LazyMethod::contents")
-
-// The number of fields of interface LazyMethod.
-const size_t BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_LAZY_METHOD = 7;
-
-// Strongly typed iteration through the fields of interface LazySetter.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_LAZY_SETTER(                           \
-    F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM,      \
-    STRING_ENUM, OPTIONAL_STRING_ENUM)                                         \
-  F(LazySetter, Name, 0, SUM(PropertyName), "LazySetter::name")                \
-  F(LazySetter, Length, 1, PRIMITIVE(UnsignedLong), "LazySetter::length")      \
-  F(LazySetter, Directives, 2, LIST(ListOfDirective, Directive),               \
-    "LazySetter::directives")                                                  \
-  F(LazySetter, ContentsSkip, 3, PRIMITIVE(Lazy), "LazySetter::contents_skip") \
-  F(LazySetter, Contents, 4, INTERFACE(SetterContents), "LazySetter::contents")
-
-// The number of fields of interface LazySetter.
-const size_t BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_LAZY_SETTER = 5;
-
-// Strongly typed iteration through the fields of interface
-// LiteralBooleanExpression.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_LITERAL_BOOLEAN_EXPRESSION(       \
-    F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM, \
-    STRING_ENUM, OPTIONAL_STRING_ENUM)                                    \
-  F(LiteralBooleanExpression, Value, 0, PRIMITIVE(Boolean),               \
-    "LiteralBooleanExpression::value")
-
-// The number of fields of interface LiteralBooleanExpression.
-const size_t BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_LITERAL_BOOLEAN_EXPRESSION =
-    1;
-
-// Strongly typed iteration through the fields of interface
-// LiteralInfinityExpression.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_LITERAL_INFINITY_EXPRESSION(      \
-    F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM, \
-    STRING_ENUM, OPTIONAL_STRING_ENUM)
-
-// The number of fields of interface LiteralInfinityExpression.
-const size_t BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_LITERAL_INFINITY_EXPRESSION =
-    0;
-
-// Strongly typed iteration through the fields of interface
-// LiteralNullExpression.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_LITERAL_NULL_EXPRESSION(          \
-    F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM, \
-    STRING_ENUM, OPTIONAL_STRING_ENUM)
-
-// The number of fields of interface LiteralNullExpression.
-const size_t BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_LITERAL_NULL_EXPRESSION = 0;
-
-// Strongly typed iteration through the fields of interface
-// LiteralNumericExpression.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_LITERAL_NUMERIC_EXPRESSION(       \
-    F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM, \
-    STRING_ENUM, OPTIONAL_STRING_ENUM)                                    \
-  F(LiteralNumericExpression, Value, 0, PRIMITIVE(Number),                \
-    "LiteralNumericExpression::value")
-
-// The number of fields of interface LiteralNumericExpression.
-const size_t BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_LITERAL_NUMERIC_EXPRESSION =
-    1;
-
-// Strongly typed iteration through the fields of interface LiteralPropertyName.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_LITERAL_PROPERTY_NAME(            \
-    F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM, \
-    STRING_ENUM, OPTIONAL_STRING_ENUM)                                    \
-  F(LiteralPropertyName, Value, 0, PRIMITIVE(String),                     \
-    "LiteralPropertyName::value")
-
-// The number of fields of interface LiteralPropertyName.
-const size_t BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_LITERAL_PROPERTY_NAME = 1;
-
-// Strongly typed iteration through the fields of interface
-// LiteralRegExpExpression.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_LITERAL_REG_EXP_EXPRESSION(       \
-    F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM, \
-    STRING_ENUM, OPTIONAL_STRING_ENUM)                                    \
-  F(LiteralRegExpExpression, Pattern, 0, PRIMITIVE(String),               \
-    "LiteralRegExpExpression::pattern")                                   \
-  F(LiteralRegExpExpression, Flags, 1, PRIMITIVE(String),                 \
-    "LiteralRegExpExpression::flags")
-
-// The number of fields of interface LiteralRegExpExpression.
-const size_t BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_LITERAL_REG_EXP_EXPRESSION =
-    2;
-
-// Strongly typed iteration through the fields of interface
-// LiteralStringExpression.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_LITERAL_STRING_EXPRESSION(        \
-    F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM, \
-    STRING_ENUM, OPTIONAL_STRING_ENUM)                                    \
-  F(LiteralStringExpression, Value, 0, PRIMITIVE(String),                 \
-    "LiteralStringExpression::value")
-
-// The number of fields of interface LiteralStringExpression.
-const size_t BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_LITERAL_STRING_EXPRESSION = 1;
-
-// Strongly typed iteration through the fields of interface Module.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_MODULE(                           \
-    F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM, \
-    STRING_ENUM, OPTIONAL_STRING_ENUM)                                    \
-  F(Module, Scope, 0, INTERFACE(AssertedVarScope), "Module::scope")       \
-  F(Module, Directives, 1, LIST(ListOfDirective, Directive),              \
-    "Module::directives")                                                 \
-  F(Module, Items, 2,                                                     \
-    LIST(ListOfImportDeclarationOrExportDeclarationOrStatement,           \
-         ImportDeclarationOrExportDeclarationOrStatement),                \
-    "Module::items")
-
-// The number of fields of interface Module.
-const size_t BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_MODULE = 3;
-
-// Strongly typed iteration through the fields of interface NewExpression.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_NEW_EXPRESSION(                      \
-    F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM,    \
-    STRING_ENUM, OPTIONAL_STRING_ENUM)                                       \
-  F(NewExpression, Callee, 0, SUM(Expression), "NewExpression::callee")      \
-  F(NewExpression, Arguments, 1, LIST(Arguments, SpreadElementOrExpression), \
-    "NewExpression::arguments")
-
-// The number of fields of interface NewExpression.
-const size_t BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_NEW_EXPRESSION = 2;
-
-// Strongly typed iteration through the fields of interface NewTargetExpression.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_NEW_TARGET_EXPRESSION(            \
-    F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM, \
-    STRING_ENUM, OPTIONAL_STRING_ENUM)
-
-// The number of fields of interface NewTargetExpression.
-const size_t BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_NEW_TARGET_EXPRESSION = 0;
-
-// Strongly typed iteration through the fields of interface
-// ObjectAssignmentTarget.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_OBJECT_ASSIGNMENT_TARGET(         \
-    F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM, \
-    STRING_ENUM, OPTIONAL_STRING_ENUM)                                    \
-  F(ObjectAssignmentTarget, Properties, 0,                                \
-    LIST(ListOfAssignmentTargetProperty, AssignmentTargetProperty),       \
-    "ObjectAssignmentTarget::properties")
-
-// The number of fields of interface ObjectAssignmentTarget.
-const size_t BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_OBJECT_ASSIGNMENT_TARGET = 1;
-
-// Strongly typed iteration through the fields of interface ObjectBinding.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_OBJECT_BINDING(                   \
-    F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM, \
-    STRING_ENUM, OPTIONAL_STRING_ENUM)                                    \
-  F(ObjectBinding, Properties, 0,                                         \
-    LIST(ListOfBindingProperty, BindingProperty), "ObjectBinding::properties")
-
-// The number of fields of interface ObjectBinding.
-const size_t BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_OBJECT_BINDING = 1;
-
-// Strongly typed iteration through the fields of interface ObjectExpression.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_OBJECT_EXPRESSION(                \
-    F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM, \
-    STRING_ENUM, OPTIONAL_STRING_ENUM)                                    \
-  F(ObjectExpression, Properties, 0,                                      \
-    LIST(ListOfObjectProperty, ObjectProperty),                           \
-    "ObjectExpression::properties")
-
-// The number of fields of interface ObjectExpression.
-const size_t BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_OBJECT_EXPRESSION = 1;
-
-// Strongly typed iteration through the fields of interface ReturnStatement.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_RETURN_STATEMENT(                 \
-    F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM, \
-    STRING_ENUM, OPTIONAL_STRING_ENUM)                                    \
-  F(ReturnStatement, Expression, 0, OPTIONAL_SUM(Expression),             \
-    "ReturnStatement::expression")
-
-// The number of fields of interface ReturnStatement.
-const size_t BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_RETURN_STATEMENT = 1;
-
-// Strongly typed iteration through the fields of interface Script.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_SCRIPT(                              \
-    F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM,    \
-    STRING_ENUM, OPTIONAL_STRING_ENUM)                                       \
-  F(Script, Scope, 0, INTERFACE(AssertedScriptGlobalScope), "Script::scope") \
-  F(Script, Directives, 1, LIST(ListOfDirective, Directive),                 \
-    "Script::directives")                                                    \
-  F(Script, Statements, 2, LIST(ListOfStatement, Statement),                 \
-    "Script::statements")
-
-// The number of fields of interface Script.
-const size_t BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_SCRIPT = 3;
-
-// Strongly typed iteration through the fields of interface SetterContents.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_SETTER_CONTENTS(                  \
-    F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM, \
-    STRING_ENUM, OPTIONAL_STRING_ENUM)                                    \
-  F(SetterContents, IsThisCaptured, 0, PRIMITIVE(Boolean),                \
-    "SetterContents::isThisCaptured")                                     \
-  F(SetterContents, ParameterScope, 1, INTERFACE(AssertedParameterScope), \
-    "SetterContents::parameterScope")                                     \
-  F(SetterContents, Param, 2, SUM(Parameter), "SetterContents::param")    \
-  F(SetterContents, BodyScope, 3, INTERFACE(AssertedVarScope),            \
-    "SetterContents::bodyScope")                                          \
-  F(SetterContents, Body, 4, LIST(FunctionBody, Statement),               \
-    "SetterContents::body")
-
-// The number of fields of interface SetterContents.
-const size_t BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_SETTER_CONTENTS = 5;
-
-// Strongly typed iteration through the fields of interface ShorthandProperty.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_SHORTHAND_PROPERTY(               \
-    F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM, \
-    STRING_ENUM, OPTIONAL_STRING_ENUM)                                    \
-  F(ShorthandProperty, Name, 0, INTERFACE(IdentifierExpression),          \
-    "ShorthandProperty::name")
-
-// The number of fields of interface ShorthandProperty.
-const size_t BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_SHORTHAND_PROPERTY = 1;
-
-// Strongly typed iteration through the fields of interface SpreadElement.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_SPREAD_ELEMENT(                   \
-    F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM, \
-    STRING_ENUM, OPTIONAL_STRING_ENUM)                                    \
-  F(SpreadElement, Expression, 0, SUM(Expression), "SpreadElement::expression")
-
-// The number of fields of interface SpreadElement.
-const size_t BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_SPREAD_ELEMENT = 1;
-
-// Strongly typed iteration through the fields of interface
-// StaticMemberAssignmentTarget.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_STATIC_MEMBER_ASSIGNMENT_TARGET(  \
-    F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM, \
-    STRING_ENUM, OPTIONAL_STRING_ENUM)                                    \
-  F(StaticMemberAssignmentTarget, Object, 0, SUM(ExpressionOrSuper),      \
-    "StaticMemberAssignmentTarget::object")                               \
-  F(StaticMemberAssignmentTarget, Property, 1, PRIMITIVE(PropertyKey),    \
-    "StaticMemberAssignmentTarget::property")
-
-// The number of fields of interface StaticMemberAssignmentTarget.
-const size_t
-    BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_STATIC_MEMBER_ASSIGNMENT_TARGET = 2;
-
-// Strongly typed iteration through the fields of interface
-// StaticMemberExpression.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_STATIC_MEMBER_EXPRESSION(         \
-    F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM, \
-    STRING_ENUM, OPTIONAL_STRING_ENUM)                                    \
-  F(StaticMemberExpression, Object, 0, SUM(ExpressionOrSuper),            \
-    "StaticMemberExpression::object")                                     \
-  F(StaticMemberExpression, Property, 1, PRIMITIVE(PropertyKey),          \
-    "StaticMemberExpression::property")
-
-// The number of fields of interface StaticMemberExpression.
-const size_t BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_STATIC_MEMBER_EXPRESSION = 2;
-
-// Strongly typed iteration through the fields of interface Super.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_SUPER(                            \
-    F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM, \
-    STRING_ENUM, OPTIONAL_STRING_ENUM)
-
-// The number of fields of interface Super.
-const size_t BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_SUPER = 0;
-
-// Strongly typed iteration through the fields of interface SwitchCase.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_SWITCH_CASE(                      \
-    F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM, \
-    STRING_ENUM, OPTIONAL_STRING_ENUM)                                    \
-  F(SwitchCase, Test, 0, SUM(Expression), "SwitchCase::test")             \
-  F(SwitchCase, Consequent, 1, LIST(ListOfStatement, Statement),          \
-    "SwitchCase::consequent")
-
-// The number of fields of interface SwitchCase.
-const size_t BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_SWITCH_CASE = 2;
-
-// Strongly typed iteration through the fields of interface SwitchDefault.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_SWITCH_DEFAULT(                   \
-    F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM, \
-    STRING_ENUM, OPTIONAL_STRING_ENUM)                                    \
-  F(SwitchDefault, Consequent, 0, LIST(ListOfStatement, Statement),       \
-    "SwitchDefault::consequent")
-
-// The number of fields of interface SwitchDefault.
-const size_t BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_SWITCH_DEFAULT = 1;
-
-// Strongly typed iteration through the fields of interface SwitchStatement.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_SWITCH_STATEMENT(                 \
-    F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM, \
-    STRING_ENUM, OPTIONAL_STRING_ENUM)                                    \
-  F(SwitchStatement, Discriminant, 0, SUM(Expression),                    \
-    "SwitchStatement::discriminant")                                      \
-  F(SwitchStatement, Cases, 1, LIST(ListOfSwitchCase, SwitchCase),        \
-    "SwitchStatement::cases")
-
-// The number of fields of interface SwitchStatement.
-const size_t BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_SWITCH_STATEMENT = 2;
-
-// Strongly typed iteration through the fields of interface
-// SwitchStatementWithDefault.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_SWITCH_STATEMENT_WITH_DEFAULT(    \
-    F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM, \
-    STRING_ENUM, OPTIONAL_STRING_ENUM)                                    \
-  F(SwitchStatementWithDefault, Discriminant, 0, SUM(Expression),         \
-    "SwitchStatementWithDefault::discriminant")                           \
-  F(SwitchStatementWithDefault, PreDefaultCases, 1,                       \
-    LIST(ListOfSwitchCase, SwitchCase),                                   \
-    "SwitchStatementWithDefault::preDefaultCases")                        \
-  F(SwitchStatementWithDefault, DefaultCase, 2, INTERFACE(SwitchDefault), \
-    "SwitchStatementWithDefault::defaultCase")                            \
-  F(SwitchStatementWithDefault, PostDefaultCases, 3,                      \
-    LIST(ListOfSwitchCase, SwitchCase),                                   \
-    "SwitchStatementWithDefault::postDefaultCases")
-
-// The number of fields of interface SwitchStatementWithDefault.
-const size_t
-    BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_SWITCH_STATEMENT_WITH_DEFAULT = 4;
-
-// Strongly typed iteration through the fields of interface TemplateElement.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_TEMPLATE_ELEMENT(                 \
-    F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM, \
-    STRING_ENUM, OPTIONAL_STRING_ENUM)                                    \
-  F(TemplateElement, RawValue, 0, PRIMITIVE(String),                      \
-    "TemplateElement::rawValue")
-
-// The number of fields of interface TemplateElement.
-const size_t BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_TEMPLATE_ELEMENT = 1;
-
-// Strongly typed iteration through the fields of interface TemplateExpression.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_TEMPLATE_EXPRESSION(              \
-    F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM, \
-    STRING_ENUM, OPTIONAL_STRING_ENUM)                                    \
-  F(TemplateExpression, Tag, 0, OPTIONAL_SUM(Expression),                 \
-    "TemplateExpression::tag")                                            \
-  F(TemplateExpression, Elements, 1,                                      \
-    LIST(ListOfExpressionOrTemplateElement, ExpressionOrTemplateElement), \
-    "TemplateExpression::elements")
-
-// The number of fields of interface TemplateExpression.
-const size_t BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_TEMPLATE_EXPRESSION = 2;
-
-// Strongly typed iteration through the fields of interface ThisExpression.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_THIS_EXPRESSION(                  \
-    F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM, \
-    STRING_ENUM, OPTIONAL_STRING_ENUM)
-
-// The number of fields of interface ThisExpression.
-const size_t BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_THIS_EXPRESSION = 0;
-
-// Strongly typed iteration through the fields of interface ThrowStatement.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_THROW_STATEMENT(                  \
-    F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM, \
-    STRING_ENUM, OPTIONAL_STRING_ENUM)                                    \
-  F(ThrowStatement, Expression, 0, SUM(Expression),                       \
-    "ThrowStatement::expression")
-
-// The number of fields of interface ThrowStatement.
-const size_t BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_THROW_STATEMENT = 1;
-
-// Strongly typed iteration through the fields of interface TryCatchStatement.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_TRY_CATCH_STATEMENT(                 \
-    F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM,    \
-    STRING_ENUM, OPTIONAL_STRING_ENUM)                                       \
-  F(TryCatchStatement, Body, 0, INTERFACE(Block), "TryCatchStatement::body") \
-  F(TryCatchStatement, CatchClause, 1, INTERFACE(CatchClause),               \
-    "TryCatchStatement::catchClause")
-
-// The number of fields of interface TryCatchStatement.
-const size_t BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_TRY_CATCH_STATEMENT = 2;
-
-// Strongly typed iteration through the fields of interface TryFinallyStatement.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_TRY_FINALLY_STATEMENT(            \
-    F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM, \
-    STRING_ENUM, OPTIONAL_STRING_ENUM)                                    \
-  F(TryFinallyStatement, Body, 0, INTERFACE(Block),                       \
-    "TryFinallyStatement::body")                                          \
-  F(TryFinallyStatement, CatchClause, 1, OPTIONAL_INTERFACE(CatchClause), \
-    "TryFinallyStatement::catchClause")                                   \
-  F(TryFinallyStatement, Finalizer, 2, INTERFACE(Block),                  \
-    "TryFinallyStatement::finalizer")
-
-// The number of fields of interface TryFinallyStatement.
-const size_t BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_TRY_FINALLY_STATEMENT = 3;
-
-// Strongly typed iteration through the fields of interface UnaryExpression.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_UNARY_EXPRESSION(                 \
-    F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM, \
-    STRING_ENUM, OPTIONAL_STRING_ENUM)                                    \
-  F(UnaryExpression, Operator, 0, STRING_ENUM(UnaryOperator),             \
-    "UnaryExpression::operator")                                          \
-  F(UnaryExpression, Operand, 1, SUM(Expression), "UnaryExpression::operand")
-
-// The number of fields of interface UnaryExpression.
-const size_t BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_UNARY_EXPRESSION = 2;
-
-// Strongly typed iteration through the fields of interface UpdateExpression.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_UPDATE_EXPRESSION(                \
-    F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM, \
-    STRING_ENUM, OPTIONAL_STRING_ENUM)                                    \
-  F(UpdateExpression, IsPrefix, 0, PRIMITIVE(Boolean),                    \
-    "UpdateExpression::isPrefix")                                         \
-  F(UpdateExpression, Operator, 1, STRING_ENUM(UpdateOperator),           \
-    "UpdateExpression::operator")                                         \
-  F(UpdateExpression, Operand, 2, SUM(SimpleAssignmentTarget),            \
-    "UpdateExpression::operand")
-
-// The number of fields of interface UpdateExpression.
-const size_t BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_UPDATE_EXPRESSION = 3;
-
-// Strongly typed iteration through the fields of interface VariableDeclaration.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_VARIABLE_DECLARATION(             \
-    F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM, \
-    STRING_ENUM, OPTIONAL_STRING_ENUM)                                    \
-  F(VariableDeclaration, Kind, 0, STRING_ENUM(VariableDeclarationKind),   \
-    "VariableDeclaration::kind")                                          \
-  F(VariableDeclaration, Declarators, 1,                                  \
-    LIST(ListOfVariableDeclarator, VariableDeclarator),                   \
-    "VariableDeclaration::declarators")
-
-// The number of fields of interface VariableDeclaration.
-const size_t BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_VARIABLE_DECLARATION = 2;
-
-// Strongly typed iteration through the fields of interface VariableDeclarator.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_VARIABLE_DECLARATOR(              \
-    F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM, \
-    STRING_ENUM, OPTIONAL_STRING_ENUM)                                    \
-  F(VariableDeclarator, Binding, 0, SUM(Binding),                         \
-    "VariableDeclarator::binding")                                        \
-  F(VariableDeclarator, Init, 1, OPTIONAL_SUM(Expression),                \
-    "VariableDeclarator::init")
-
-// The number of fields of interface VariableDeclarator.
-const size_t BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_VARIABLE_DECLARATOR = 2;
-
-// Strongly typed iteration through the fields of interface WhileStatement.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_WHILE_STATEMENT(                  \
-    F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM, \
-    STRING_ENUM, OPTIONAL_STRING_ENUM)                                    \
-  F(WhileStatement, Test, 0, SUM(Expression), "WhileStatement::test")     \
-  F(WhileStatement, Body, 1, SUM(Statement), "WhileStatement::body")
-
-// The number of fields of interface WhileStatement.
-const size_t BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_WHILE_STATEMENT = 2;
-
-// Strongly typed iteration through the fields of interface WithStatement.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_WITH_STATEMENT(                   \
-    F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM, \
-    STRING_ENUM, OPTIONAL_STRING_ENUM)                                    \
-  F(WithStatement, Object, 0, SUM(Expression), "WithStatement::object")   \
-  F(WithStatement, Body, 1, SUM(Statement), "WithStatement::body")
-
-// The number of fields of interface WithStatement.
-const size_t BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_WITH_STATEMENT = 2;
-
-// Strongly typed iteration through the fields of interface YieldExpression.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_YIELD_EXPRESSION(                 \
-    F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM, \
-    STRING_ENUM, OPTIONAL_STRING_ENUM)                                    \
-  F(YieldExpression, Expression, 0, OPTIONAL_SUM(Expression),             \
-    "YieldExpression::expression")
-
-// The number of fields of interface YieldExpression.
-const size_t BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_YIELD_EXPRESSION = 1;
-
-// Strongly typed iteration through the fields of interface YieldStarExpression.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_YIELD_STAR_EXPRESSION(            \
-    F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM, \
-    STRING_ENUM, OPTIONAL_STRING_ENUM)                                    \
-  F(YieldStarExpression, Expression, 0, SUM(Expression),                  \
-    "YieldStarExpression::expression")
-
-// The number of fields of interface YieldStarExpression.
-const size_t BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_YIELD_STAR_EXPRESSION = 1;
-// The total number of fields across all interfaces. Used typically to maintain
-// a probability table per field.
-const size_t BINAST_INTERFACE_AND_FIELD_LIMIT = 275;
-
 /**
  * The different variants of Binary AST string enums, as per
  * the specifications of Binary AST, as a single macro and
  * `enum class`.
  *
  * Separate enum classes are also defined in BinASTParser.h.
  *
  * Usage:
@@ -2348,147 +360,27 @@ enum class BinASTVariant : uint16_t {
 #define EMIT_ENUM(name, _) name,
   FOR_EACH_BIN_VARIANT(EMIT_ENUM)
 #undef EMIT_ENUM
 };
 
 // The number of distinct values of BinASTVariant.
 const size_t BINASTVARIANT_LIMIT = 49;
 
-#define FOR_EACH_BIN_STRING_ENUM(F)                           \
-  F(AssertedDeclaredKind, "AssertedDeclaredKind")             \
-  F(BinaryOperator, "BinaryOperator")                         \
-  F(CompoundAssignmentOperator, "CompoundAssignmentOperator") \
-  F(UnaryOperator, "UnaryOperator")                           \
-  F(UpdateOperator, "UpdateOperator")                         \
-  F(VariableDeclarationKind, "VariableDeclarationKind")
-
-enum class BinASTStringEnum : uint16_t {
-#define EMIT_ENUM(name, _) name,
-  FOR_EACH_BIN_STRING_ENUM(EMIT_ENUM)
-#undef EMIT_ENUM
-};
-
-// The number of distinct values of BinASTStringEnum.
-const size_t BINASTSTRINGENUM_LIMIT = 6;
-
-#define FOR_EACH_BIN_LIST(F)                                               \
-  F(Arguments, SpreadElementOrExpression, "Arguments")                     \
-  F(FunctionBody, Statement, "FunctionBody")                               \
-  F(ListOfAssertedBoundName, AssertedBoundName, "ListOfAssertedBoundName") \
-  F(ListOfAssertedDeclaredName, AssertedDeclaredName,                      \
-    "ListOfAssertedDeclaredName")                                          \
-  F(ListOfAssertedMaybePositionalParameterName,                            \
-    AssertedMaybePositionalParameterName,                                  \
-    "ListOfAssertedMaybePositionalParameterName")                          \
-  F(ListOfAssignmentTargetOrAssignmentTargetWithInitializer,               \
-    AssignmentTargetOrAssignmentTargetWithInitializer,                     \
-    "ListOfAssignmentTargetOrAssignmentTargetWithInitializer")             \
-  F(ListOfAssignmentTargetProperty, AssignmentTargetProperty,              \
-    "ListOfAssignmentTargetProperty")                                      \
-  F(ListOfBindingProperty, BindingProperty, "ListOfBindingProperty")       \
-  F(ListOfClassElement, ClassElement, "ListOfClassElement")                \
-  F(ListOfDirective, Directive, "ListOfDirective")                         \
-  F(ListOfExportFromSpecifier, ExportFromSpecifier,                        \
-    "ListOfExportFromSpecifier")                                           \
-  F(ListOfExportLocalSpecifier, ExportLocalSpecifier,                      \
-    "ListOfExportLocalSpecifier")                                          \
-  F(ListOfExpressionOrTemplateElement, ExpressionOrTemplateElement,        \
-    "ListOfExpressionOrTemplateElement")                                   \
-  F(ListOfImportDeclarationOrExportDeclarationOrStatement,                 \
-    ImportDeclarationOrExportDeclarationOrStatement,                       \
-    "ListOfImportDeclarationOrExportDeclarationOrStatement")               \
-  F(ListOfImportSpecifier, ImportSpecifier, "ListOfImportSpecifier")       \
-  F(ListOfObjectProperty, ObjectProperty, "ListOfObjectProperty")          \
-  F(ListOfOptionalBindingOrBindingWithInitializer,                         \
-    OptionalBindingOrBindingWithInitializer,                               \
-    "ListOfOptionalBindingOrBindingWithInitializer")                       \
-  F(ListOfOptionalSpreadElementOrExpression,                               \
-    OptionalSpreadElementOrExpression,                                     \
-    "ListOfOptionalSpreadElementOrExpression")                             \
-  F(ListOfParameter, Parameter, "ListOfParameter")                         \
-  F(ListOfStatement, Statement, "ListOfStatement")                         \
-  F(ListOfSwitchCase, SwitchCase, "ListOfSwitchCase")                      \
-  F(ListOfVariableDeclarator, VariableDeclarator, "ListOfVariableDeclarator")
-
-enum class BinASTList : uint16_t {
-#define EMIT_ENUM(name, _content, _user) name,
-  FOR_EACH_BIN_LIST(EMIT_ENUM)
-#undef EMIT_ENUM
-};
-
-// The number of distinct list types in the grammar. Used typically to maintain
-// a probability table per list type.
-const size_t BINAST_NUMBER_OF_LIST_TYPES = 22;
-
-#define FOR_EACH_BIN_SUM(F)                                               \
-  F(ArrowExpression, "ArrowExpression")                                   \
-  F(AssertedMaybePositionalParameterName,                                 \
-    "AssertedMaybePositionalParameterName")                               \
-  F(AssignmentTarget, "AssignmentTarget")                                 \
-  F(AssignmentTargetOrAssignmentTargetWithInitializer,                    \
-    "AssignmentTargetOrAssignmentTargetWithInitializer")                  \
-  F(AssignmentTargetPattern, "AssignmentTargetPattern")                   \
-  F(AssignmentTargetProperty, "AssignmentTargetProperty")                 \
-  F(Binding, "Binding")                                                   \
-  F(BindingOrBindingWithInitializer, "BindingOrBindingWithInitializer")   \
-  F(BindingPattern, "BindingPattern")                                     \
-  F(BindingProperty, "BindingProperty")                                   \
-  F(ExportDeclaration, "ExportDeclaration")                               \
-  F(Expression, "Expression")                                             \
-  F(ExpressionOrSuper, "ExpressionOrSuper")                               \
-  F(ExpressionOrTemplateElement, "ExpressionOrTemplateElement")           \
-  F(ForInOfBindingOrAssignmentTarget, "ForInOfBindingOrAssignmentTarget") \
-  F(FunctionDeclaration, "FunctionDeclaration")                           \
-  F(FunctionDeclarationOrClassDeclarationOrExpression,                    \
-    "FunctionDeclarationOrClassDeclarationOrExpression")                  \
-  F(FunctionDeclarationOrClassDeclarationOrVariableDeclaration,           \
-    "FunctionDeclarationOrClassDeclarationOrVariableDeclaration")         \
-  F(FunctionExpression, "FunctionExpression")                             \
-  F(Getter, "Getter")                                                     \
-  F(ImportDeclaration, "ImportDeclaration")                               \
-  F(ImportDeclarationOrExportDeclarationOrStatement,                      \
-    "ImportDeclarationOrExportDeclarationOrStatement")                    \
-  F(IterationStatement, "IterationStatement")                             \
-  F(Literal, "Literal")                                                   \
-  F(Method, "Method")                                                     \
-  F(MethodDefinition, "MethodDefinition")                                 \
-  F(ObjectProperty, "ObjectProperty")                                     \
-  F(Parameter, "Parameter")                                               \
-  F(Program, "Program")                                                   \
-  F(PropertyName, "PropertyName")                                         \
-  F(Setter, "Setter")                                                     \
-  F(SimpleAssignmentTarget, "SimpleAssignmentTarget")                     \
-  F(SpreadElementOrExpression, "SpreadElementOrExpression")               \
-  F(Statement, "Statement")                                               \
-  F(VariableDeclarationOrExpression, "VariableDeclarationOrExpression")
-
-enum class BinASTSum : uint16_t {
-#define EMIT_ENUM(name, _user) name,
-  FOR_EACH_BIN_SUM(EMIT_ENUM)
-#undef EMIT_ENUM
-};
-
 /**
  * Return a string describing a `BinASTKind`.
  */
 const char* describeBinASTKind(const BinASTKind& kind);
 
 /**
  * Return a string describing a `BinASTField`.
  */
 const char* describeBinASTField(const BinASTField& field);
 
 /**
- * Return a string describing a `BinASTInterfaceAndField`.
- */
-const char* describeBinASTInterfaceAndField(
-    const BinASTInterfaceAndField& field);
-
-/**
  * Return a string describing a `BinASTVariant`.
  */
 const char* describeBinASTVariant(const BinASTVariant& variant);
 
 }  // namespace frontend
 }  // namespace js
 
 #endif  // frontend_BinASTToken_h
--- a/js/src/frontend/BinASTTokenReaderBase.h
+++ b/js/src/frontend/BinASTTokenReaderBase.h
@@ -4,18 +4,16 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef frontend_BinASTTokenReaderBase_h
 #define frontend_BinASTTokenReaderBase_h
 
 #include <string.h>
 
-#include "mozilla/Variant.h"
-
 #include "frontend/BinASTToken.h"
 #include "frontend/ErrorReporter.h"
 #include "frontend/TokenStream.h"
 
 #include "js/Result.h"
 #include "js/TypeDecls.h"
 
 namespace js {
@@ -24,40 +22,64 @@ namespace frontend {
 // A constant used by tokenizers to represent a null float.
 extern const uint64_t NULL_FLOAT_REPRESENTATION;
 
 class MOZ_STACK_CLASS BinASTTokenReaderBase {
  public:
   template <typename T>
   using ErrorResult = mozilla::GenericErrorResult<T>;
 
-  // Part of variant `Context`
-  // Reading the root of the tree, before we enter any tagged tuple.
-  struct RootContext {};
+  // The context in which we read a token.
+  struct Context {
+    // Construct a context for a root node.
+    constexpr static Context topLevel() {
+      return Context(BinASTKind::_Null, 0, ElementOf::TaggedTuple);
+    }
+
+    Context arrayElement() const {
+      return Context(kind, fieldIndex, ElementOf::Array);
+    }
+
+    // Construct a context for a field of a tagged tuple.
+    constexpr static Context firstField(BinASTKind kind) {
+      return Context(kind, 0, ElementOf::TaggedTuple);
+    }
+
+    const Context operator++(int) {
+      MOZ_ASSERT(elementOf == ElementOf::TaggedTuple);
+      Context result = *this;
+      fieldIndex++;
+      return result;
+    }
 
-  // Part of variant `Context`
-  // Reading an element from a list.
-  struct ListContext {
-    const BinASTInterfaceAndField position;
-    const BinASTList content;
-    ListContext(const BinASTInterfaceAndField position,
-                const BinASTList content)
-        : position(position), content(content) {}
-  };
+    // The kind of the tagged tuple containing the token.
+    //
+    // If the parent is the root, use `BinASTKind::_Null`.
+    BinASTKind kind;
+
+    // The index of the token as a field of the parent.
+    uint8_t fieldIndex;
+
+    enum class ElementOf {
+      // This token is an element of an array.
+      Array,
 
-  // Part of variant `Context`
-  // Reading a field from an interface.
-  struct FieldContext {
-    const BinASTInterfaceAndField position;
-    FieldContext(const BinASTInterfaceAndField position) : position(position) {}
+      // This token is a field of a tagged tuple.
+      TaggedTuple,
+    };
+    ElementOf elementOf;
+
+    Context() = delete;
+
+   private:
+    constexpr Context(BinASTKind kind_, uint8_t fieldIndex_,
+                      ElementOf elementOf_)
+        : kind(kind_), fieldIndex(fieldIndex_), elementOf(elementOf_) {}
   };
 
-  // The context in which we read a token.
-  typedef mozilla::Variant<RootContext, ListContext, FieldContext> Context;
-
   // The information needed to skip a subtree.
   class SkippableSubTree {
    public:
     SkippableSubTree(const size_t startOffset, const size_t length)
         : startOffset_(startOffset), length_(length) {}
 
     // The position in the source buffer at which the subtree starts.
     //
--- a/js/src/frontend/binast/Cargo.toml
+++ b/js/src/frontend/binast/Cargo.toml
@@ -3,17 +3,16 @@ name = "binast"
 version = "0.1.1"
 authors = ["David Teller <D.O.Teller@gmail.com>"]
 autobins = false
 
 [dependencies]
 binjs_meta = "^0.4.3"
 clap = "^2"
 env_logger = "^0.5.6"
-Inflector = "^0.11"
 itertools = "^0.7.6"
 log = "0.4"
 yaml-rust = "^0.4.2"
 webidl = "^0.8"
 
 [[bin]]
 name = "binast"
 path = "src/main.rs"
--- a/js/src/frontend/binast/src/main.rs
+++ b/js/src/frontend/binast/src/main.rs
@@ -1,12 +1,11 @@
 extern crate binjs_meta;
 extern crate clap;
 extern crate env_logger;
-extern crate inflector;
 extern crate itertools;
 #[macro_use] extern crate log;
 extern crate webidl;
 extern crate yaml_rust;
 
 use binjs_meta::export::{ ToWebidl, TypeDeanonymizer, TypeName };
 use binjs_meta::import::Importer;
 use binjs_meta::spec::*;
@@ -20,26 +19,16 @@ use std::collections::{ HashMap, HashSet
 use std::fs::*;
 use std::io::{ Read, Write };
 use std::rc::Rc;
 
 use clap::{ App, Arg };
 
 use itertools::Itertools;
 
-/// An extension of `ToCases` to produce macro-style names, e.g. `FOO_BAR`
-/// from `FooBar` or `foo_bar`.
-trait ToCases2: ToCases {
-    fn to_cpp_macro_case(&self) -> String {
-        use inflector::cases::screamingsnakecase::to_screaming_snake_case;
-        to_screaming_snake_case(&self.to_cpp_enum_case())
-    }
-}
-impl<T: ToCases> ToCases2 for T {}
-
 /// 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>,
@@ -965,24 +954,23 @@ impl CPPExporter {
 
         let node_names = self.syntax.interfaces_by_name()
             .keys()
             .map(|n| n.to_string())
             .sorted();
         let kind_limit = node_names.len();
         buffer.push_str(&format!("\n#define FOR_EACH_BIN_KIND(F) \\\n{nodes}\n",
             nodes = node_names.iter()
-                .map(|name| format!("    F({enum_name}, \"{spec_name}\", {macro_name})",
+                .map(|name| format!("    F({enum_name}, \"{spec_name}\")",
                     enum_name = name.to_cpp_enum_case(),
-                    spec_name = name,
-                    macro_name = name.to_cpp_macro_case()))
+                    spec_name = name))
                 .format(" \\\n")));
         buffer.push_str("
 enum class BinASTKind: uint16_t {
-#define EMIT_ENUM(name, _1, _2) name,
+#define EMIT_ENUM(name, _) name,
     FOR_EACH_BIN_KIND(EMIT_ENUM)
 #undef EMIT_ENUM
 };
 ");
 
         buffer.push_str(&format!("\n// The number of distinct values of BinASTKind.\nconst size_t BINASTKIND_LIMIT = {};\n\n\n", kind_limit));
         buffer.push_str("\n\n");
         if self.rules.hpp_tokens_field_doc.is_some() {
@@ -1001,179 +989,17 @@ enum class BinASTKind: uint16_t {
                 .format(" \\\n")));
         buffer.push_str("
 enum class BinASTField: uint16_t {
 #define EMIT_ENUM(name, _) name,
     FOR_EACH_BIN_FIELD(EMIT_ENUM)
 #undef EMIT_ENUM
 };
 ");
-        buffer.push_str(&format!("\n// The number of distinct values of BinASTField.\nconst size_t BINASTFIELD_LIMIT = {};\n", field_limit));
-
-        buffer.push_str(&format!("\n#define FOR_EACH_BIN_INTERFACE_AND_FIELD(F) \\\n{nodes}\n",
-            nodes = self.syntax.interfaces_by_name()
-                .iter()
-                .sorted_by_key(|a| a.0)
-                .into_iter()
-                .flat_map(|(interface_name, interface)| {
-                    let interface_enum_name = interface_name.to_cpp_enum_case();
-                    let interface_spec_name = interface_name.clone();
-                    interface.contents().fields()
-                        .iter()
-                        .map(move |field| format!("    F({interface_enum_name}__{field_enum_name}, \"{interface_spec_name}::{field_spec_name}\")",
-                                interface_enum_name = interface_enum_name,
-                                field_enum_name = field.name().to_cpp_enum_case(),
-                                interface_spec_name = interface_spec_name,
-                                field_spec_name = field.name().to_str(),
-                            )
-                        )
-                })
-                .format(" \\\n")));
-        buffer.push_str("
-enum class BinASTInterfaceAndField: uint16_t {
-#define EMIT_ENUM(name, _) name,
-    FOR_EACH_BIN_INTERFACE_AND_FIELD(EMIT_ENUM)
-#undef EMIT_ENUM
-};
-");
-
-        buffer.push_str("
-// Strongly typed iterations through the fields of interfaces.
-//
-// Each of these macros accepts the following arguments:
-// - F: callback
-// - PRIMITIVE: wrapper for primitive type names - called as `PRIMITIVE(typename)`
-// - INTERFACE: wrapper for non-optional interface type names - called as `INTERFACE(typename)`
-// - OPTIONAL_INTERFACE: wrapper for optional interface type names - called as `OPTIONAL_INTERFACE(typename)` where
-//      `typename` is the name of the interface (e.g. no `Maybe` prefix)
-// - LIST: wrapper for list types - called as `LIST(list_typename, element_typename)`
-// - SUM: wrapper for non-optional type names - called as `SUM(typename)`
-// - OPTIONAL_SUM: wrapper for optional sum type names - called as `OPTIONAL_SUM(typename)` where
-//      `typename` is the name of the sum (e.g. no `Maybe` prefix)
-// - STRING_ENUM: wrapper for non-optional string enum types - called as `STRING_ENUNM(typename)`
-// - OPTIONAL_STRING_ENUM: wrapper for optional string enum type names - called as `OPTIONAL_STRING_ENUM(typename)` where
-//      `typename` is the name of the string enum (e.g. no `Maybe` prefix)
-");
-        for (interface_name, interface) in self.syntax.interfaces_by_name().iter().sorted_by_key(|a| a.0) {
-            use std::borrow::Cow;
-            let interface_enum_name = interface_name.to_cpp_enum_case();
-            let interface_spec_name = interface_name.clone();
-            let interface_macro_name = interface.name().to_cpp_macro_case();
-            buffer.push_str(&format!("\n\n
-// Strongly typed iteration through the fields of interface {interface_enum_name}.
-#define FOR_EACH_BIN_FIELD_IN_INTERFACE_{interface_macro_name}(F, PRIMITIVE, INTERFACE, OPTIONAL_INTERFACE, LIST, SUM, OPTIONAL_SUM, STRING_ENUM, OPTIONAL_STRING_ENUM) \\\n{nodes}\n",
-                interface_macro_name = interface_macro_name,
-                interface_enum_name = interface_enum_name.clone(),
-                nodes = interface.contents().fields()
-                    .iter()
-                    .enumerate()
-                    .map(|(i, field)| {
-                        fn get_field_type_name(spec: &Spec, type_: &Type, make_optional: bool) -> Cow<'static, str> {
-                            let optional = make_optional || type_.is_optional();
-                            match *type_.spec() {
-                                TypeSpec::Boolean if optional => Cow::from("PRIMITIVE(MaybeBoolean)"),
-                                TypeSpec::Boolean => Cow::from("PRIMITIVE(Boolean)"),
-                                TypeSpec::String if optional => Cow::from("PRIMITIVE(MaybeString)"),
-                                TypeSpec::String => Cow::from("PRIMITIVE(String)"),
-                                TypeSpec::Number if optional => Cow::from("PRIMITIVE(MaybeNumber)"),
-                                TypeSpec::Number => Cow::from("PRIMITIVE(Number)"),
-                                TypeSpec::UnsignedLong if optional => Cow::from("PRIMITIVE(MaybeUnsignedLong)"),
-                                TypeSpec::UnsignedLong => Cow::from("PRIMITIVE(UnsignedLong)"),
-                                TypeSpec::Offset if optional => Cow::from("PRIMITIVE(MaybeLazy)"),
-                                TypeSpec::Offset => Cow::from("PRIMITIVE(Lazy)"),
-                                TypeSpec::Void if optional => Cow::from("PRIMITIVE(MaybeVoid)"),
-                                TypeSpec::Void => Cow::from("PRIMITIVE(Void)"),
-                                TypeSpec::IdentifierName if optional => Cow::from("PRIMITIVE(MaybeIdentifierName)"),
-                                TypeSpec::IdentifierName => Cow::from("PRIMITIVE(IdentifierName)"),
-                                TypeSpec::PropertyKey if optional => Cow::from("PRIMITIVE(MaybePropertyKey)"),
-                                TypeSpec::PropertyKey => Cow::from("PRIMITIVE(PropertyKey)"),
-                                TypeSpec::Array { ref contents, .. } => Cow::from(
-                                    format!("LIST({name}, {contents})",
-                                        name = TypeName::type_(type_),
-                                        contents = TypeName::type_(contents),
-                                )),
-                                TypeSpec::NamedType(ref name) => match spec.get_type_by_name(name).expect("By now, all types MUST exist") {
-                                    NamedType::Typedef(alias_type) => {
-                                        if alias_type.is_optional() {
-                                            return get_field_type_name(spec, alias_type.as_ref(), true)
-                                        }
-                                        // Keep the simple name of sums and lists if there is one.
-                                        match *alias_type.spec() {
-                                            TypeSpec::TypeSum(_) => {
-                                                if optional {
-                                                    Cow::from(format!("OPTIONAL_SUM({name})", name = name.to_cpp_enum_case()))
-                                                } else {
-                                                    Cow::from(format!("SUM({name})", name = name.to_cpp_enum_case()))
-                                                }
-                                            }
-                                            TypeSpec::Array { ref contents, .. } => {
-                                                let contents = TypeName::type_(contents);
-                                                if optional {
-                                                    Cow::from(format!("OPTIONAL_LIST({name}, {contents})",
-                                                        name = name.to_cpp_enum_case(),
-                                                        contents = contents))
-                                                } else {
-                                                    Cow::from(format!("LIST({name}, {contents})",
-                                                        name = name.to_cpp_enum_case(),
-                                                        contents = contents))
-                                                }
-                                            }
-                                            _ => {
-                                                get_field_type_name(spec, alias_type.as_ref(), optional)
-                                            }
-                                        }
-                                    }
-                                    NamedType::StringEnum(_) if type_.is_optional() => Cow::from(
-                                        format!("OPTIONAL_STRING_ENUM({name})",
-                                            name = TypeName::type_(type_))),
-                                    NamedType::StringEnum(_) => Cow::from(
-                                        format!("STRING_ENUM({name})",
-                                            name = TypeName::type_(type_))),
-                                    NamedType::Interface(ref interface) if type_.is_optional() => Cow::from(
-                                        format!("OPTIONAL_INTERFACE({name})",
-                                            name = interface.name().to_class_cases())),
-                                    NamedType::Interface(ref interface) => Cow::from(
-                                        format!("INTERFACE({name})",
-                                            name = interface.name().to_class_cases())),
-                                }
-                                TypeSpec::TypeSum(ref contents) if type_.is_optional() => {
-                                    // We need to make sure that we don't count the `optional` part twice.
-                                    // FIXME: The problem seems to only show up in this branch, but it looks like
-                                    // it might (should?) appear in other branches, too.
-                                    let non_optional_type = Type::sum(contents.types()).required();
-                                    let name = TypeName::type_(&non_optional_type);
-                                    Cow::from(format!("OPTIONAL_SUM({name})", name = name))
-                                }
-                                TypeSpec::TypeSum(_) => Cow::from(format!("SUM({name})", name = TypeName::type_(type_))),
-                            }
-                        }
-                        let field_type_name = get_field_type_name(&self.syntax, field.type_(), false);
-                        format!("    F({interface_enum_name}, {field_enum_name}, {field_index}, {field_type}, \"{interface_spec_name}::{field_spec_name}\")",
-                            interface_enum_name = interface_enum_name,
-                            field_enum_name = field.name().to_cpp_enum_case(),
-                            field_index = i,
-                            interface_spec_name = interface_spec_name,
-                            field_spec_name = field.name().to_str(),
-                            field_type = field_type_name
-                        )
-                    })
-                    .format(" \\\n")));
-            buffer.push_str(&format!("
-// The number of fields of interface {interface_spec_name}.
-const size_t BINAST_NUMBER_OF_FIELDS_IN_INTERFACE_{interface_macro_name} = {len};",
-                interface_spec_name = interface_spec_name,
-                interface_macro_name = interface_macro_name,
-                len = interface.contents().fields().len()));
-        }
-
-        let total_number_of_fields: usize = self.syntax.interfaces_by_name()
-            .values()
-            .map(|interface| interface.contents().fields().len())
-            .sum();
-        buffer.push_str(&format!("\n// The total number of fields across all interfaces. Used typically to maintain a probability table per field.\nconst size_t BINAST_INTERFACE_AND_FIELD_LIMIT = {};\n\n\n", total_number_of_fields));
+        buffer.push_str(&format!("\n// The number of distinct values of BinASTField.\nconst size_t BINASTFIELD_LIMIT = {};\n\n\n", field_limit));
 
         if self.rules.hpp_tokens_variants_doc.is_some() {
             buffer.push_str(&self.rules.hpp_tokens_variants_doc.reindent(""));
         }
         let enum_variants : Vec<_> = self.variants_by_symbol
             .iter()
             .sorted_by(|&(ref symbol_1, ref name_1), &(ref symbol_2, ref name_2)| {
                 Ord::cmp(name_1, name_2)
@@ -1193,71 +1019,16 @@ enum class BinASTVariant: uint16_t {
 #define EMIT_ENUM(name, _) name,
     FOR_EACH_BIN_VARIANT(EMIT_ENUM)
 #undef EMIT_ENUM
 };
 ");
         buffer.push_str(&format!("\n// The number of distinct values of BinASTVariant.\nconst size_t BINASTVARIANT_LIMIT = {};\n\n\n",
             variants_limit));
 
-        buffer.push_str(&format!("\n#define FOR_EACH_BIN_STRING_ENUM(F) \\\n{nodes}\n",
-            nodes = self.syntax.string_enums_by_name()
-                .keys()
-                .sorted()
-                .into_iter()
-                .map(|name| format!("    F({enum_name}, \"{spec_name}\")",
-                    enum_name = name.to_cpp_enum_case(),
-                    spec_name = name.to_str()))
-                .format(" \\\n")));
-
-        buffer.push_str("
-enum class BinASTStringEnum: uint16_t {
-#define EMIT_ENUM(name, _) name,
-    FOR_EACH_BIN_STRING_ENUM(EMIT_ENUM)
-#undef EMIT_ENUM
-};
-");
-        buffer.push_str(&format!("\n// The number of distinct values of BinASTStringEnum.\nconst size_t BINASTSTRINGENUM_LIMIT = {};\n\n\n",
-            self.syntax.string_enums_by_name().len()));
-
-       buffer.push_str(&format!("\n#define FOR_EACH_BIN_LIST(F) \\\n{nodes}\n",
-            nodes = self.list_parsers_to_generate.iter()
-                .sorted_by_key(|data| &data.name)
-                .into_iter()
-                .map(|data| format!("    F({list_name}, {content_name}, \"{spec_name}\")",
-                    list_name = data.name.to_cpp_enum_case(),
-                    content_name = data.elements.to_cpp_enum_case(),
-                    spec_name = data.name.to_str()))
-                .format(" \\\n")));
-        buffer.push_str("
-enum class BinASTList: uint16_t {
-#define EMIT_ENUM(name, _content, _user) name,
-    FOR_EACH_BIN_LIST(EMIT_ENUM)
-#undef EMIT_ENUM
-};
-");
-        buffer.push_str(&format!("\n// The number of distinct list types in the grammar. Used typically to maintain a probability table per list type.\nconst size_t BINAST_NUMBER_OF_LIST_TYPES = {};\n\n\n", self.list_parsers_to_generate.len()));
-
-        buffer.push_str(&format!("\n#define FOR_EACH_BIN_SUM(F) \\\n{nodes}\n",
-            nodes = self.syntax.resolved_sums_of_interfaces_by_name()
-                .iter()
-                .sorted_by(|a, b| a.0.cmp(&b.0))
-                .into_iter()
-                .map(|(name, _)| format!("    F({name}, \"{spec_name}\")",
-                    name = name.to_cpp_enum_case(),
-                    spec_name = name.to_str()))
-                .format(" \\\n")));
-        buffer.push_str("
-enum class BinASTSum: uint16_t {
-#define EMIT_ENUM(name, _user) name,
-    FOR_EACH_BIN_SUM(EMIT_ENUM)
-#undef EMIT_ENUM
-};
-");
-
         buffer.push_str(&self.rules.hpp_tokens_footer.reindent(""));
         buffer.push_str("\n");
     }
 
     /// Declare string enums
     fn export_declare_string_enums(&self, buffer: &mut String) {
         buffer.push_str("
 // ----- Declaring string enums (by lexicographical order)
@@ -1627,26 +1398,25 @@ impl CPPExporter {
 {{
     uint32_t length;
     AutoList guard(*tokenizer_);
 
     const auto start = tokenizer_->offset();
     MOZ_TRY(tokenizer_->enterList(length, context, guard));{empty_check}
 {init}
 
+    const Context childContext(context.arrayElement());
     for (uint32_t i = 0; i < length; ++i) {{
-        const Context childContext(Context(ListContext(context.as<FieldContext>().position, BinASTList::{content_kind})));
 {call}
 {append}    }}
 
     MOZ_TRY(guard.done());
     return result;
 }}\n",
             first_line = first_line,
-            content_kind = parser.name.to_class_cases(),
             empty_check =
                 if parser.supports_empty {
                     "".to_string()
                 } else {
                     format!("
     if (length == 0) {{
         return raiseEmpty(\"{kind}\");
     }}
@@ -1959,19 +1729,17 @@ impl CPPExporter {
         let fields_type_list = format!("{{ {} }}", interface.contents()
             .fields()
             .iter()
             .map(|field| format!("BinASTField::{}", field.name().to_cpp_enum_case()))
             .format(", "));
 
         let mut fields_implem = String::new();
         for field in interface.contents().fields() {
-            let context = format!("Context(FieldContext(BinASTInterfaceAndField::{kind}__{field}))",
-                kind = name.to_cpp_enum_case(),
-                field = field.name().to_cpp_enum_case());
+            let context = "fieldContext++";
 
             let rules_for_this_field = rules_for_this_interface.by_field.get(field.name())
                 .cloned()
                 .unwrap_or_default();
             let needs_block = rules_for_this_field.block_before_field.is_some() || rules_for_this_field.block_after_field.is_some();
 
             let var_name = field.name().to_cpp_field_case();
             let (decl_var, parse_var) = match field.type_().get_primitive(&self.syntax) {
@@ -2163,28 +1931,33 @@ impl CPPExporter {
 #endif // defined(DEBUG)",
                     fields_type_list = fields_type_list,
                     number_of_fields = number_of_fields)
             };
             buffer.push_str(&format!("{first_line}
 {{
     MOZ_ASSERT(kind == BinASTKind::{kind});
     BINJS_TRY(CheckRecursionLimit(cx_));
-{check_fields}
+{maybe_field_context}{check_fields}
 {pre}{fields_implem}
 {post}    return result;
 }}
 
 ",
                 check_fields = check_fields,
                 fields_implem = fields_implem,
                 pre = init.newline_if_not_empty(),
                 post = build_result.newline_if_not_empty(),
                 kind = name.to_cpp_enum_case(),
                 first_line = first_line,
+                maybe_field_context = if interface.contents().fields().len() > 0 {
+                    "    Context fieldContext = Context::firstField(kind);\n"
+                } else {
+                    ""
+                },
             ));
         }
     }
 
     /// Generate C++ code for SpiderMonkey
     fn to_spidermonkey_cpp(&self) -> String {
         let mut buffer = String::new();