Bug 1585234 - Part 2: Use smaller Variant for context. r=Yoric
authorTooru Fujisawa <arai_a@mac.com>
Mon, 07 Oct 2019 05:10:49 +0000
changeset 496476 8f3223ff55e267cb478968433c8f1cfa4e4fcb97
parent 496475 a384b2a67709945e40216aa08f4a4afbcd9a3b12
child 496477 8ea58e64530bb0fc2996d7f2a922eb67d1dabe78
push id97270
push userarai_a@mac.com
push dateMon, 07 Oct 2019 05:16:21 +0000
treeherderautoland@b7dd0f12d98b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersYoric
bugs1585234
milestone71.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1585234 - Part 2: Use smaller Variant for context. r=Yoric Part 2 addes smaller Variant types (FieldOrRootContext and FieldOrListContext), and modifies the code generator to use smaller Variant instead of Context. Differential Revision: https://phabricator.services.mozilla.com/D48012
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/BinASTTokenReaderBase.h
js/src/frontend/BinASTTokenReaderContext.cpp
js/src/frontend/BinASTTokenReaderContext.h
js/src/frontend/BinASTTokenReaderMultipart.cpp
js/src/frontend/BinASTTokenReaderMultipart.h
js/src/frontend/binast/src/main.rs
--- a/js/src/frontend/BinAST.yaml
+++ b/js/src/frontend/BinAST.yaml
@@ -117,20 +117,21 @@ hpp:
         using Base = BinASTParserPerTokenizer<Tok>;
 
         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;
+        using FieldOrRootContext = BinASTTokenReaderBase::FieldOrRootContext;
+        using FieldOrListContext = BinASTTokenReaderBase::FieldOrListContext;
 
        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/BinASTParser.cpp
+++ b/js/src/frontend/BinASTParser.cpp
@@ -238,26 +238,29 @@ JS::Result<ParseNode*> BinASTParser<Tok>
 
 template <typename Tok>
 JS::Result<ParseNode*> BinASTParser<Tok>::parseSumBinding(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
     const FieldContext& context) {
   ParseNode* result;
   switch (kind) {
     case BinASTKind::ArrayBinding:
-      MOZ_TRY_VAR(result, parseInterfaceArrayBinding(start, kind, fields,
-                                                     Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceArrayBinding(start, kind, fields,
+                                             FieldOrListContext(context)));
       break;
     case BinASTKind::BindingIdentifier:
-      MOZ_TRY_VAR(result, parseInterfaceBindingIdentifier(start, kind, fields,
-                                                          Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceBindingIdentifier(start, kind, fields,
+                                                  FieldOrListContext(context)));
       break;
     case BinASTKind::ObjectBinding:
-      MOZ_TRY_VAR(result, parseInterfaceObjectBinding(start, kind, fields,
-                                                      Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceObjectBinding(start, kind, fields,
+                                              FieldOrListContext(context)));
       break;
     default:
       return raiseInvalidKind("Binding", kind);
   }
   return result;
 }
 
 /*
@@ -312,142 +315,174 @@ JS::Result<ParseNode*> BinASTParser<Tok>
 
 template <typename Tok>
 JS::Result<ParseNode*> BinASTParser<Tok>::parseSumExpression(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
     const FieldContext& context) {
   ParseNode* result;
   switch (kind) {
     case BinASTKind::ArrayExpression:
-      MOZ_TRY_VAR(result, parseInterfaceArrayExpression(start, kind, fields,
-                                                        Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceArrayExpression(start, kind, fields,
+                                                FieldOrListContext(context)));
       break;
     case BinASTKind::AssignmentExpression:
-      MOZ_TRY_VAR(result, parseInterfaceAssignmentExpression(
-                              start, kind, fields, Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceAssignmentExpression(
+                      start, kind, fields, FieldOrListContext(context)));
       break;
     case BinASTKind::AwaitExpression:
-      MOZ_TRY_VAR(result, parseInterfaceAwaitExpression(start, kind, fields,
-                                                        Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceAwaitExpression(start, kind, fields,
+                                                FieldOrListContext(context)));
       break;
     case BinASTKind::BinaryExpression:
-      MOZ_TRY_VAR(result, parseInterfaceBinaryExpression(start, kind, fields,
-                                                         Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceBinaryExpression(start, kind, fields,
+                                                 FieldOrListContext(context)));
       break;
     case BinASTKind::CallExpression:
-      MOZ_TRY_VAR(result, parseInterfaceCallExpression(start, kind, fields,
-                                                       Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceCallExpression(start, kind, fields,
+                                               FieldOrListContext(context)));
       break;
     case BinASTKind::ClassExpression:
-      MOZ_TRY_VAR(result, parseInterfaceClassExpression(start, kind, fields,
-                                                        Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceClassExpression(start, kind, fields,
+                                                FieldOrListContext(context)));
       break;
     case BinASTKind::CompoundAssignmentExpression:
-      MOZ_TRY_VAR(result, parseInterfaceCompoundAssignmentExpression(
-                              start, kind, fields, Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceCompoundAssignmentExpression(
+                      start, kind, fields, FieldOrListContext(context)));
       break;
     case BinASTKind::ComputedMemberExpression:
-      MOZ_TRY_VAR(result, parseInterfaceComputedMemberExpression(
-                              start, kind, fields, Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceComputedMemberExpression(
+                      start, kind, fields, FieldOrListContext(context)));
       break;
     case BinASTKind::ConditionalExpression:
-      MOZ_TRY_VAR(result, parseInterfaceConditionalExpression(
-                              start, kind, fields, Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceConditionalExpression(
+                      start, kind, fields, FieldOrListContext(context)));
       break;
     case BinASTKind::EagerArrowExpressionWithExpression:
-      MOZ_TRY_VAR(result, parseInterfaceEagerArrowExpressionWithExpression(
-                              start, kind, fields, Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceEagerArrowExpressionWithExpression(
+                      start, kind, fields, FieldOrListContext(context)));
       break;
     case BinASTKind::EagerArrowExpressionWithFunctionBody:
-      MOZ_TRY_VAR(result, parseInterfaceEagerArrowExpressionWithFunctionBody(
-                              start, kind, fields, Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceEagerArrowExpressionWithFunctionBody(
+                      start, kind, fields, FieldOrListContext(context)));
       break;
     case BinASTKind::EagerFunctionExpression:
-      MOZ_TRY_VAR(result, parseInterfaceEagerFunctionExpression(
-                              start, kind, fields, Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceEagerFunctionExpression(
+                      start, kind, fields, FieldOrListContext(context)));
       break;
     case BinASTKind::IdentifierExpression:
-      MOZ_TRY_VAR(result, parseInterfaceIdentifierExpression(
-                              start, kind, fields, Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceIdentifierExpression(
+                      start, kind, fields, FieldOrListContext(context)));
       break;
     case BinASTKind::LazyArrowExpressionWithExpression:
-      MOZ_TRY_VAR(result, parseInterfaceLazyArrowExpressionWithExpression(
-                              start, kind, fields, Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceLazyArrowExpressionWithExpression(
+                      start, kind, fields, FieldOrListContext(context)));
       break;
     case BinASTKind::LazyArrowExpressionWithFunctionBody:
-      MOZ_TRY_VAR(result, parseInterfaceLazyArrowExpressionWithFunctionBody(
-                              start, kind, fields, Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceLazyArrowExpressionWithFunctionBody(
+                      start, kind, fields, FieldOrListContext(context)));
       break;
     case BinASTKind::LazyFunctionExpression:
-      MOZ_TRY_VAR(result, parseInterfaceLazyFunctionExpression(
-                              start, kind, fields, Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceLazyFunctionExpression(
+                      start, kind, fields, FieldOrListContext(context)));
       break;
     case BinASTKind::LiteralBooleanExpression:
-      MOZ_TRY_VAR(result, parseInterfaceLiteralBooleanExpression(
-                              start, kind, fields, Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceLiteralBooleanExpression(
+                      start, kind, fields, FieldOrListContext(context)));
       break;
     case BinASTKind::LiteralInfinityExpression:
-      MOZ_TRY_VAR(result, parseInterfaceLiteralInfinityExpression(
-                              start, kind, fields, Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceLiteralInfinityExpression(
+                      start, kind, fields, FieldOrListContext(context)));
       break;
     case BinASTKind::LiteralNullExpression:
-      MOZ_TRY_VAR(result, parseInterfaceLiteralNullExpression(
-                              start, kind, fields, Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceLiteralNullExpression(
+                      start, kind, fields, FieldOrListContext(context)));
       break;
     case BinASTKind::LiteralNumericExpression:
-      MOZ_TRY_VAR(result, parseInterfaceLiteralNumericExpression(
-                              start, kind, fields, Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceLiteralNumericExpression(
+                      start, kind, fields, FieldOrListContext(context)));
       break;
     case BinASTKind::LiteralRegExpExpression:
-      MOZ_TRY_VAR(result, parseInterfaceLiteralRegExpExpression(
-                              start, kind, fields, Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceLiteralRegExpExpression(
+                      start, kind, fields, FieldOrListContext(context)));
       break;
     case BinASTKind::LiteralStringExpression:
-      MOZ_TRY_VAR(result, parseInterfaceLiteralStringExpression(
-                              start, kind, fields, Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceLiteralStringExpression(
+                      start, kind, fields, FieldOrListContext(context)));
       break;
     case BinASTKind::NewExpression:
-      MOZ_TRY_VAR(result, parseInterfaceNewExpression(start, kind, fields,
-                                                      Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceNewExpression(start, kind, fields,
+                                              FieldOrListContext(context)));
       break;
     case BinASTKind::NewTargetExpression:
-      MOZ_TRY_VAR(result, parseInterfaceNewTargetExpression(start, kind, fields,
-                                                            Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceNewTargetExpression(
+                      start, kind, fields, FieldOrListContext(context)));
       break;
     case BinASTKind::ObjectExpression:
-      MOZ_TRY_VAR(result, parseInterfaceObjectExpression(start, kind, fields,
-                                                         Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceObjectExpression(start, kind, fields,
+                                                 FieldOrListContext(context)));
       break;
     case BinASTKind::StaticMemberExpression:
-      MOZ_TRY_VAR(result, parseInterfaceStaticMemberExpression(
-                              start, kind, fields, Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceStaticMemberExpression(
+                      start, kind, fields, FieldOrListContext(context)));
       break;
     case BinASTKind::TemplateExpression:
-      MOZ_TRY_VAR(result, parseInterfaceTemplateExpression(start, kind, fields,
-                                                           Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceTemplateExpression(
+                      start, kind, fields, FieldOrListContext(context)));
       break;
     case BinASTKind::ThisExpression:
-      MOZ_TRY_VAR(result, parseInterfaceThisExpression(start, kind, fields,
-                                                       Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceThisExpression(start, kind, fields,
+                                               FieldOrListContext(context)));
       break;
     case BinASTKind::UnaryExpression:
-      MOZ_TRY_VAR(result, parseInterfaceUnaryExpression(start, kind, fields,
-                                                        Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceUnaryExpression(start, kind, fields,
+                                                FieldOrListContext(context)));
       break;
     case BinASTKind::UpdateExpression:
-      MOZ_TRY_VAR(result, parseInterfaceUpdateExpression(start, kind, fields,
-                                                         Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceUpdateExpression(start, kind, fields,
+                                                 FieldOrListContext(context)));
       break;
     case BinASTKind::YieldExpression:
-      MOZ_TRY_VAR(result, parseInterfaceYieldExpression(start, kind, fields,
-                                                        Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceYieldExpression(start, kind, fields,
+                                                FieldOrListContext(context)));
       break;
     case BinASTKind::YieldStarExpression:
-      MOZ_TRY_VAR(result, parseInterfaceYieldStarExpression(start, kind, fields,
-                                                            Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceYieldStarExpression(
+                      start, kind, fields, FieldOrListContext(context)));
       break;
     default:
       return raiseInvalidKind("Expression", kind);
   }
   return result;
 }
 
 /*
@@ -504,146 +539,178 @@ JS::Result<ParseNode*> BinASTParser<Tok>
 
 template <typename Tok>
 JS::Result<ParseNode*> BinASTParser<Tok>::parseSumExpressionOrSpreadElement(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
     const ListContext& context) {
   ParseNode* result;
   switch (kind) {
     case BinASTKind::ArrayExpression:
-      MOZ_TRY_VAR(result, parseInterfaceArrayExpression(start, kind, fields,
-                                                        Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceArrayExpression(start, kind, fields,
+                                                FieldOrListContext(context)));
       break;
     case BinASTKind::AssignmentExpression:
-      MOZ_TRY_VAR(result, parseInterfaceAssignmentExpression(
-                              start, kind, fields, Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceAssignmentExpression(
+                      start, kind, fields, FieldOrListContext(context)));
       break;
     case BinASTKind::AwaitExpression:
-      MOZ_TRY_VAR(result, parseInterfaceAwaitExpression(start, kind, fields,
-                                                        Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceAwaitExpression(start, kind, fields,
+                                                FieldOrListContext(context)));
       break;
     case BinASTKind::BinaryExpression:
-      MOZ_TRY_VAR(result, parseInterfaceBinaryExpression(start, kind, fields,
-                                                         Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceBinaryExpression(start, kind, fields,
+                                                 FieldOrListContext(context)));
       break;
     case BinASTKind::CallExpression:
-      MOZ_TRY_VAR(result, parseInterfaceCallExpression(start, kind, fields,
-                                                       Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceCallExpression(start, kind, fields,
+                                               FieldOrListContext(context)));
       break;
     case BinASTKind::ClassExpression:
-      MOZ_TRY_VAR(result, parseInterfaceClassExpression(start, kind, fields,
-                                                        Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceClassExpression(start, kind, fields,
+                                                FieldOrListContext(context)));
       break;
     case BinASTKind::CompoundAssignmentExpression:
-      MOZ_TRY_VAR(result, parseInterfaceCompoundAssignmentExpression(
-                              start, kind, fields, Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceCompoundAssignmentExpression(
+                      start, kind, fields, FieldOrListContext(context)));
       break;
     case BinASTKind::ComputedMemberExpression:
-      MOZ_TRY_VAR(result, parseInterfaceComputedMemberExpression(
-                              start, kind, fields, Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceComputedMemberExpression(
+                      start, kind, fields, FieldOrListContext(context)));
       break;
     case BinASTKind::ConditionalExpression:
-      MOZ_TRY_VAR(result, parseInterfaceConditionalExpression(
-                              start, kind, fields, Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceConditionalExpression(
+                      start, kind, fields, FieldOrListContext(context)));
       break;
     case BinASTKind::EagerArrowExpressionWithExpression:
-      MOZ_TRY_VAR(result, parseInterfaceEagerArrowExpressionWithExpression(
-                              start, kind, fields, Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceEagerArrowExpressionWithExpression(
+                      start, kind, fields, FieldOrListContext(context)));
       break;
     case BinASTKind::EagerArrowExpressionWithFunctionBody:
-      MOZ_TRY_VAR(result, parseInterfaceEagerArrowExpressionWithFunctionBody(
-                              start, kind, fields, Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceEagerArrowExpressionWithFunctionBody(
+                      start, kind, fields, FieldOrListContext(context)));
       break;
     case BinASTKind::EagerFunctionExpression:
-      MOZ_TRY_VAR(result, parseInterfaceEagerFunctionExpression(
-                              start, kind, fields, Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceEagerFunctionExpression(
+                      start, kind, fields, FieldOrListContext(context)));
       break;
     case BinASTKind::IdentifierExpression:
-      MOZ_TRY_VAR(result, parseInterfaceIdentifierExpression(
-                              start, kind, fields, Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceIdentifierExpression(
+                      start, kind, fields, FieldOrListContext(context)));
       break;
     case BinASTKind::LazyArrowExpressionWithExpression:
-      MOZ_TRY_VAR(result, parseInterfaceLazyArrowExpressionWithExpression(
-                              start, kind, fields, Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceLazyArrowExpressionWithExpression(
+                      start, kind, fields, FieldOrListContext(context)));
       break;
     case BinASTKind::LazyArrowExpressionWithFunctionBody:
-      MOZ_TRY_VAR(result, parseInterfaceLazyArrowExpressionWithFunctionBody(
-                              start, kind, fields, Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceLazyArrowExpressionWithFunctionBody(
+                      start, kind, fields, FieldOrListContext(context)));
       break;
     case BinASTKind::LazyFunctionExpression:
-      MOZ_TRY_VAR(result, parseInterfaceLazyFunctionExpression(
-                              start, kind, fields, Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceLazyFunctionExpression(
+                      start, kind, fields, FieldOrListContext(context)));
       break;
     case BinASTKind::LiteralBooleanExpression:
-      MOZ_TRY_VAR(result, parseInterfaceLiteralBooleanExpression(
-                              start, kind, fields, Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceLiteralBooleanExpression(
+                      start, kind, fields, FieldOrListContext(context)));
       break;
     case BinASTKind::LiteralInfinityExpression:
-      MOZ_TRY_VAR(result, parseInterfaceLiteralInfinityExpression(
-                              start, kind, fields, Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceLiteralInfinityExpression(
+                      start, kind, fields, FieldOrListContext(context)));
       break;
     case BinASTKind::LiteralNullExpression:
-      MOZ_TRY_VAR(result, parseInterfaceLiteralNullExpression(
-                              start, kind, fields, Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceLiteralNullExpression(
+                      start, kind, fields, FieldOrListContext(context)));
       break;
     case BinASTKind::LiteralNumericExpression:
-      MOZ_TRY_VAR(result, parseInterfaceLiteralNumericExpression(
-                              start, kind, fields, Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceLiteralNumericExpression(
+                      start, kind, fields, FieldOrListContext(context)));
       break;
     case BinASTKind::LiteralRegExpExpression:
-      MOZ_TRY_VAR(result, parseInterfaceLiteralRegExpExpression(
-                              start, kind, fields, Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceLiteralRegExpExpression(
+                      start, kind, fields, FieldOrListContext(context)));
       break;
     case BinASTKind::LiteralStringExpression:
-      MOZ_TRY_VAR(result, parseInterfaceLiteralStringExpression(
-                              start, kind, fields, Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceLiteralStringExpression(
+                      start, kind, fields, FieldOrListContext(context)));
       break;
     case BinASTKind::NewExpression:
-      MOZ_TRY_VAR(result, parseInterfaceNewExpression(start, kind, fields,
-                                                      Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceNewExpression(start, kind, fields,
+                                              FieldOrListContext(context)));
       break;
     case BinASTKind::NewTargetExpression:
-      MOZ_TRY_VAR(result, parseInterfaceNewTargetExpression(start, kind, fields,
-                                                            Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceNewTargetExpression(
+                      start, kind, fields, FieldOrListContext(context)));
       break;
     case BinASTKind::ObjectExpression:
-      MOZ_TRY_VAR(result, parseInterfaceObjectExpression(start, kind, fields,
-                                                         Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceObjectExpression(start, kind, fields,
+                                                 FieldOrListContext(context)));
       break;
     case BinASTKind::SpreadElement:
       MOZ_TRY_VAR(result,
                   parseInterfaceSpreadElement(start, kind, fields, context));
       break;
     case BinASTKind::StaticMemberExpression:
-      MOZ_TRY_VAR(result, parseInterfaceStaticMemberExpression(
-                              start, kind, fields, Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceStaticMemberExpression(
+                      start, kind, fields, FieldOrListContext(context)));
       break;
     case BinASTKind::TemplateExpression:
-      MOZ_TRY_VAR(result, parseInterfaceTemplateExpression(start, kind, fields,
-                                                           Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceTemplateExpression(
+                      start, kind, fields, FieldOrListContext(context)));
       break;
     case BinASTKind::ThisExpression:
-      MOZ_TRY_VAR(result, parseInterfaceThisExpression(start, kind, fields,
-                                                       Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceThisExpression(start, kind, fields,
+                                               FieldOrListContext(context)));
       break;
     case BinASTKind::UnaryExpression:
-      MOZ_TRY_VAR(result, parseInterfaceUnaryExpression(start, kind, fields,
-                                                        Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceUnaryExpression(start, kind, fields,
+                                                FieldOrListContext(context)));
       break;
     case BinASTKind::UpdateExpression:
-      MOZ_TRY_VAR(result, parseInterfaceUpdateExpression(start, kind, fields,
-                                                         Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceUpdateExpression(start, kind, fields,
+                                                 FieldOrListContext(context)));
       break;
     case BinASTKind::YieldExpression:
-      MOZ_TRY_VAR(result, parseInterfaceYieldExpression(start, kind, fields,
-                                                        Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceYieldExpression(start, kind, fields,
+                                                FieldOrListContext(context)));
       break;
     case BinASTKind::YieldStarExpression:
-      MOZ_TRY_VAR(result, parseInterfaceYieldStarExpression(start, kind, fields,
-                                                            Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceYieldStarExpression(
+                      start, kind, fields, FieldOrListContext(context)));
       break;
     default:
       return raiseInvalidKind("ExpressionOrSpreadElement", kind);
   }
   return result;
 }
 
 /*
@@ -700,290 +767,355 @@ JS::Result<ParseNode*> BinASTParser<Tok>
 
 template <typename Tok>
 JS::Result<ParseNode*> BinASTParser<Tok>::parseSumExpressionOrSuper(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
     const FieldContext& context) {
   ParseNode* result;
   switch (kind) {
     case BinASTKind::ArrayExpression:
-      MOZ_TRY_VAR(result, parseInterfaceArrayExpression(start, kind, fields,
-                                                        Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceArrayExpression(start, kind, fields,
+                                                FieldOrListContext(context)));
       break;
     case BinASTKind::AssignmentExpression:
-      MOZ_TRY_VAR(result, parseInterfaceAssignmentExpression(
-                              start, kind, fields, Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceAssignmentExpression(
+                      start, kind, fields, FieldOrListContext(context)));
       break;
     case BinASTKind::AwaitExpression:
-      MOZ_TRY_VAR(result, parseInterfaceAwaitExpression(start, kind, fields,
-                                                        Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceAwaitExpression(start, kind, fields,
+                                                FieldOrListContext(context)));
       break;
     case BinASTKind::BinaryExpression:
-      MOZ_TRY_VAR(result, parseInterfaceBinaryExpression(start, kind, fields,
-                                                         Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceBinaryExpression(start, kind, fields,
+                                                 FieldOrListContext(context)));
       break;
     case BinASTKind::CallExpression:
-      MOZ_TRY_VAR(result, parseInterfaceCallExpression(start, kind, fields,
-                                                       Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceCallExpression(start, kind, fields,
+                                               FieldOrListContext(context)));
       break;
     case BinASTKind::ClassExpression:
-      MOZ_TRY_VAR(result, parseInterfaceClassExpression(start, kind, fields,
-                                                        Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceClassExpression(start, kind, fields,
+                                                FieldOrListContext(context)));
       break;
     case BinASTKind::CompoundAssignmentExpression:
-      MOZ_TRY_VAR(result, parseInterfaceCompoundAssignmentExpression(
-                              start, kind, fields, Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceCompoundAssignmentExpression(
+                      start, kind, fields, FieldOrListContext(context)));
       break;
     case BinASTKind::ComputedMemberExpression:
-      MOZ_TRY_VAR(result, parseInterfaceComputedMemberExpression(
-                              start, kind, fields, Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceComputedMemberExpression(
+                      start, kind, fields, FieldOrListContext(context)));
       break;
     case BinASTKind::ConditionalExpression:
-      MOZ_TRY_VAR(result, parseInterfaceConditionalExpression(
-                              start, kind, fields, Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceConditionalExpression(
+                      start, kind, fields, FieldOrListContext(context)));
       break;
     case BinASTKind::EagerArrowExpressionWithExpression:
-      MOZ_TRY_VAR(result, parseInterfaceEagerArrowExpressionWithExpression(
-                              start, kind, fields, Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceEagerArrowExpressionWithExpression(
+                      start, kind, fields, FieldOrListContext(context)));
       break;
     case BinASTKind::EagerArrowExpressionWithFunctionBody:
-      MOZ_TRY_VAR(result, parseInterfaceEagerArrowExpressionWithFunctionBody(
-                              start, kind, fields, Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceEagerArrowExpressionWithFunctionBody(
+                      start, kind, fields, FieldOrListContext(context)));
       break;
     case BinASTKind::EagerFunctionExpression:
-      MOZ_TRY_VAR(result, parseInterfaceEagerFunctionExpression(
-                              start, kind, fields, Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceEagerFunctionExpression(
+                      start, kind, fields, FieldOrListContext(context)));
       break;
     case BinASTKind::IdentifierExpression:
-      MOZ_TRY_VAR(result, parseInterfaceIdentifierExpression(
-                              start, kind, fields, Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceIdentifierExpression(
+                      start, kind, fields, FieldOrListContext(context)));
       break;
     case BinASTKind::LazyArrowExpressionWithExpression:
-      MOZ_TRY_VAR(result, parseInterfaceLazyArrowExpressionWithExpression(
-                              start, kind, fields, Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceLazyArrowExpressionWithExpression(
+                      start, kind, fields, FieldOrListContext(context)));
       break;
     case BinASTKind::LazyArrowExpressionWithFunctionBody:
-      MOZ_TRY_VAR(result, parseInterfaceLazyArrowExpressionWithFunctionBody(
-                              start, kind, fields, Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceLazyArrowExpressionWithFunctionBody(
+                      start, kind, fields, FieldOrListContext(context)));
       break;
     case BinASTKind::LazyFunctionExpression:
-      MOZ_TRY_VAR(result, parseInterfaceLazyFunctionExpression(
-                              start, kind, fields, Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceLazyFunctionExpression(
+                      start, kind, fields, FieldOrListContext(context)));
       break;
     case BinASTKind::LiteralBooleanExpression:
-      MOZ_TRY_VAR(result, parseInterfaceLiteralBooleanExpression(
-                              start, kind, fields, Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceLiteralBooleanExpression(
+                      start, kind, fields, FieldOrListContext(context)));
       break;
     case BinASTKind::LiteralInfinityExpression:
-      MOZ_TRY_VAR(result, parseInterfaceLiteralInfinityExpression(
-                              start, kind, fields, Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceLiteralInfinityExpression(
+                      start, kind, fields, FieldOrListContext(context)));
       break;
     case BinASTKind::LiteralNullExpression:
-      MOZ_TRY_VAR(result, parseInterfaceLiteralNullExpression(
-                              start, kind, fields, Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceLiteralNullExpression(
+                      start, kind, fields, FieldOrListContext(context)));
       break;
     case BinASTKind::LiteralNumericExpression:
-      MOZ_TRY_VAR(result, parseInterfaceLiteralNumericExpression(
-                              start, kind, fields, Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceLiteralNumericExpression(
+                      start, kind, fields, FieldOrListContext(context)));
       break;
     case BinASTKind::LiteralRegExpExpression:
-      MOZ_TRY_VAR(result, parseInterfaceLiteralRegExpExpression(
-                              start, kind, fields, Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceLiteralRegExpExpression(
+                      start, kind, fields, FieldOrListContext(context)));
       break;
     case BinASTKind::LiteralStringExpression:
-      MOZ_TRY_VAR(result, parseInterfaceLiteralStringExpression(
-                              start, kind, fields, Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceLiteralStringExpression(
+                      start, kind, fields, FieldOrListContext(context)));
       break;
     case BinASTKind::NewExpression:
-      MOZ_TRY_VAR(result, parseInterfaceNewExpression(start, kind, fields,
-                                                      Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceNewExpression(start, kind, fields,
+                                              FieldOrListContext(context)));
       break;
     case BinASTKind::NewTargetExpression:
-      MOZ_TRY_VAR(result, parseInterfaceNewTargetExpression(start, kind, fields,
-                                                            Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceNewTargetExpression(
+                      start, kind, fields, FieldOrListContext(context)));
       break;
     case BinASTKind::ObjectExpression:
-      MOZ_TRY_VAR(result, parseInterfaceObjectExpression(start, kind, fields,
-                                                         Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceObjectExpression(start, kind, fields,
+                                                 FieldOrListContext(context)));
       break;
     case BinASTKind::StaticMemberExpression:
-      MOZ_TRY_VAR(result, parseInterfaceStaticMemberExpression(
-                              start, kind, fields, Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceStaticMemberExpression(
+                      start, kind, fields, FieldOrListContext(context)));
       break;
     case BinASTKind::Super:
       MOZ_TRY_VAR(result, parseInterfaceSuper(start, kind, fields, context));
       break;
     case BinASTKind::TemplateExpression:
-      MOZ_TRY_VAR(result, parseInterfaceTemplateExpression(start, kind, fields,
-                                                           Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceTemplateExpression(
+                      start, kind, fields, FieldOrListContext(context)));
       break;
     case BinASTKind::ThisExpression:
-      MOZ_TRY_VAR(result, parseInterfaceThisExpression(start, kind, fields,
-                                                       Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceThisExpression(start, kind, fields,
+                                               FieldOrListContext(context)));
       break;
     case BinASTKind::UnaryExpression:
-      MOZ_TRY_VAR(result, parseInterfaceUnaryExpression(start, kind, fields,
-                                                        Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceUnaryExpression(start, kind, fields,
+                                                FieldOrListContext(context)));
       break;
     case BinASTKind::UpdateExpression:
-      MOZ_TRY_VAR(result, parseInterfaceUpdateExpression(start, kind, fields,
-                                                         Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceUpdateExpression(start, kind, fields,
+                                                 FieldOrListContext(context)));
       break;
     case BinASTKind::YieldExpression:
-      MOZ_TRY_VAR(result, parseInterfaceYieldExpression(start, kind, fields,
-                                                        Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceYieldExpression(start, kind, fields,
+                                                FieldOrListContext(context)));
       break;
     case BinASTKind::YieldStarExpression:
-      MOZ_TRY_VAR(result, parseInterfaceYieldStarExpression(start, kind, fields,
-                                                            Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceYieldStarExpression(
+                      start, kind, fields, FieldOrListContext(context)));
       break;
     default:
       return raiseInvalidKind("ExpressionOrSuper", kind);
   }
   return result;
 }
 
 template <typename Tok>
 JS::Result<ParseNode*>
 BinASTParser<Tok>::parseSumExpressionOrVariableDeclaration(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
     const FieldContext& context) {
   ParseNode* result;
   switch (kind) {
     case BinASTKind::ArrayExpression:
-      MOZ_TRY_VAR(result, parseInterfaceArrayExpression(start, kind, fields,
-                                                        Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceArrayExpression(start, kind, fields,
+                                                FieldOrListContext(context)));
       break;
     case BinASTKind::AssignmentExpression:
-      MOZ_TRY_VAR(result, parseInterfaceAssignmentExpression(
-                              start, kind, fields, Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceAssignmentExpression(
+                      start, kind, fields, FieldOrListContext(context)));
       break;
     case BinASTKind::AwaitExpression:
-      MOZ_TRY_VAR(result, parseInterfaceAwaitExpression(start, kind, fields,
-                                                        Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceAwaitExpression(start, kind, fields,
+                                                FieldOrListContext(context)));
       break;
     case BinASTKind::BinaryExpression:
-      MOZ_TRY_VAR(result, parseInterfaceBinaryExpression(start, kind, fields,
-                                                         Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceBinaryExpression(start, kind, fields,
+                                                 FieldOrListContext(context)));
       break;
     case BinASTKind::CallExpression:
-      MOZ_TRY_VAR(result, parseInterfaceCallExpression(start, kind, fields,
-                                                       Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceCallExpression(start, kind, fields,
+                                               FieldOrListContext(context)));
       break;
     case BinASTKind::ClassExpression:
-      MOZ_TRY_VAR(result, parseInterfaceClassExpression(start, kind, fields,
-                                                        Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceClassExpression(start, kind, fields,
+                                                FieldOrListContext(context)));
       break;
     case BinASTKind::CompoundAssignmentExpression:
-      MOZ_TRY_VAR(result, parseInterfaceCompoundAssignmentExpression(
-                              start, kind, fields, Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceCompoundAssignmentExpression(
+                      start, kind, fields, FieldOrListContext(context)));
       break;
     case BinASTKind::ComputedMemberExpression:
-      MOZ_TRY_VAR(result, parseInterfaceComputedMemberExpression(
-                              start, kind, fields, Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceComputedMemberExpression(
+                      start, kind, fields, FieldOrListContext(context)));
       break;
     case BinASTKind::ConditionalExpression:
-      MOZ_TRY_VAR(result, parseInterfaceConditionalExpression(
-                              start, kind, fields, Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceConditionalExpression(
+                      start, kind, fields, FieldOrListContext(context)));
       break;
     case BinASTKind::EagerArrowExpressionWithExpression:
-      MOZ_TRY_VAR(result, parseInterfaceEagerArrowExpressionWithExpression(
-                              start, kind, fields, Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceEagerArrowExpressionWithExpression(
+                      start, kind, fields, FieldOrListContext(context)));
       break;
     case BinASTKind::EagerArrowExpressionWithFunctionBody:
-      MOZ_TRY_VAR(result, parseInterfaceEagerArrowExpressionWithFunctionBody(
-                              start, kind, fields, Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceEagerArrowExpressionWithFunctionBody(
+                      start, kind, fields, FieldOrListContext(context)));
       break;
     case BinASTKind::EagerFunctionExpression:
-      MOZ_TRY_VAR(result, parseInterfaceEagerFunctionExpression(
-                              start, kind, fields, Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceEagerFunctionExpression(
+                      start, kind, fields, FieldOrListContext(context)));
       break;
     case BinASTKind::IdentifierExpression:
-      MOZ_TRY_VAR(result, parseInterfaceIdentifierExpression(
-                              start, kind, fields, Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceIdentifierExpression(
+                      start, kind, fields, FieldOrListContext(context)));
       break;
     case BinASTKind::LazyArrowExpressionWithExpression:
-      MOZ_TRY_VAR(result, parseInterfaceLazyArrowExpressionWithExpression(
-                              start, kind, fields, Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceLazyArrowExpressionWithExpression(
+                      start, kind, fields, FieldOrListContext(context)));
       break;
     case BinASTKind::LazyArrowExpressionWithFunctionBody:
-      MOZ_TRY_VAR(result, parseInterfaceLazyArrowExpressionWithFunctionBody(
-                              start, kind, fields, Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceLazyArrowExpressionWithFunctionBody(
+                      start, kind, fields, FieldOrListContext(context)));
       break;
     case BinASTKind::LazyFunctionExpression:
-      MOZ_TRY_VAR(result, parseInterfaceLazyFunctionExpression(
-                              start, kind, fields, Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceLazyFunctionExpression(
+                      start, kind, fields, FieldOrListContext(context)));
       break;
     case BinASTKind::LiteralBooleanExpression:
-      MOZ_TRY_VAR(result, parseInterfaceLiteralBooleanExpression(
-                              start, kind, fields, Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceLiteralBooleanExpression(
+                      start, kind, fields, FieldOrListContext(context)));
       break;
     case BinASTKind::LiteralInfinityExpression:
-      MOZ_TRY_VAR(result, parseInterfaceLiteralInfinityExpression(
-                              start, kind, fields, Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceLiteralInfinityExpression(
+                      start, kind, fields, FieldOrListContext(context)));
       break;
     case BinASTKind::LiteralNullExpression:
-      MOZ_TRY_VAR(result, parseInterfaceLiteralNullExpression(
-                              start, kind, fields, Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceLiteralNullExpression(
+                      start, kind, fields, FieldOrListContext(context)));
       break;
     case BinASTKind::LiteralNumericExpression:
-      MOZ_TRY_VAR(result, parseInterfaceLiteralNumericExpression(
-                              start, kind, fields, Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceLiteralNumericExpression(
+                      start, kind, fields, FieldOrListContext(context)));
       break;
     case BinASTKind::LiteralRegExpExpression:
-      MOZ_TRY_VAR(result, parseInterfaceLiteralRegExpExpression(
-                              start, kind, fields, Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceLiteralRegExpExpression(
+                      start, kind, fields, FieldOrListContext(context)));
       break;
     case BinASTKind::LiteralStringExpression:
-      MOZ_TRY_VAR(result, parseInterfaceLiteralStringExpression(
-                              start, kind, fields, Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceLiteralStringExpression(
+                      start, kind, fields, FieldOrListContext(context)));
       break;
     case BinASTKind::NewExpression:
-      MOZ_TRY_VAR(result, parseInterfaceNewExpression(start, kind, fields,
-                                                      Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceNewExpression(start, kind, fields,
+                                              FieldOrListContext(context)));
       break;
     case BinASTKind::NewTargetExpression:
-      MOZ_TRY_VAR(result, parseInterfaceNewTargetExpression(start, kind, fields,
-                                                            Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceNewTargetExpression(
+                      start, kind, fields, FieldOrListContext(context)));
       break;
     case BinASTKind::ObjectExpression:
-      MOZ_TRY_VAR(result, parseInterfaceObjectExpression(start, kind, fields,
-                                                         Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceObjectExpression(start, kind, fields,
+                                                 FieldOrListContext(context)));
       break;
     case BinASTKind::StaticMemberExpression:
-      MOZ_TRY_VAR(result, parseInterfaceStaticMemberExpression(
-                              start, kind, fields, Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceStaticMemberExpression(
+                      start, kind, fields, FieldOrListContext(context)));
       break;
     case BinASTKind::TemplateExpression:
-      MOZ_TRY_VAR(result, parseInterfaceTemplateExpression(start, kind, fields,
-                                                           Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceTemplateExpression(
+                      start, kind, fields, FieldOrListContext(context)));
       break;
     case BinASTKind::ThisExpression:
-      MOZ_TRY_VAR(result, parseInterfaceThisExpression(start, kind, fields,
-                                                       Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceThisExpression(start, kind, fields,
+                                               FieldOrListContext(context)));
       break;
     case BinASTKind::UnaryExpression:
-      MOZ_TRY_VAR(result, parseInterfaceUnaryExpression(start, kind, fields,
-                                                        Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceUnaryExpression(start, kind, fields,
+                                                FieldOrListContext(context)));
       break;
     case BinASTKind::UpdateExpression:
-      MOZ_TRY_VAR(result, parseInterfaceUpdateExpression(start, kind, fields,
-                                                         Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceUpdateExpression(start, kind, fields,
+                                                 FieldOrListContext(context)));
       break;
     case BinASTKind::VariableDeclaration:
-      MOZ_TRY_VAR(result, parseInterfaceVariableDeclaration(start, kind, fields,
-                                                            Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceVariableDeclaration(
+                      start, kind, fields, FieldOrListContext(context)));
       break;
     case BinASTKind::YieldExpression:
-      MOZ_TRY_VAR(result, parseInterfaceYieldExpression(start, kind, fields,
-                                                        Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceYieldExpression(start, kind, fields,
+                                                FieldOrListContext(context)));
       break;
     case BinASTKind::YieldStarExpression:
-      MOZ_TRY_VAR(result, parseInterfaceYieldStarExpression(start, kind, fields,
-                                                            Context(context)));
+      MOZ_TRY_VAR(result,
+                  parseInterfaceYieldStarExpression(
+                      start, kind, fields, FieldOrListContext(context)));
       break;
     default:
       return raiseInvalidKind("ExpressionOrVariableDeclaration", kind);
   }
   return result;
 }
 
 /*
@@ -1060,34 +1192,34 @@ JS::Result<ParseNode*> BinASTParser<Tok>
 /*
 Parameter ::= ArrayBinding
     BindingIdentifier
     BindingWithInitializer
     ObjectBinding
 */
 template <typename Tok>
 JS::Result<ParseNode*> BinASTParser<Tok>::parseParameter(
-    const Context& context) {
+    const FieldOrListContext& context) {
   BinASTKind kind;
   BinASTFields fields(cx_);
   AutoTaggedTuple guard(*tokenizer_);
   const auto start = tokenizer_->offset();
 
   MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, context, guard));
 
   BINJS_MOZ_TRY_DECL(result, parseSumParameter(start, kind, fields, context));
 
   MOZ_TRY(guard.done());
   return result;
 }
 
 template <typename Tok>
 JS::Result<ParseNode*> BinASTParser<Tok>::parseSumParameter(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
-    const Context& context) {
+    const FieldOrListContext& context) {
   ParseNode* result;
   switch (kind) {
     case BinASTKind::ArrayBinding:
       MOZ_TRY_VAR(result,
                   parseInterfaceArrayBinding(start, kind, fields, context));
       break;
     case BinASTKind::BindingIdentifier:
       MOZ_TRY_VAR(result, parseInterfaceBindingIdentifier(start, kind, fields,
@@ -1262,34 +1394,34 @@ Statement ::= Block
     TryCatchStatement
     TryFinallyStatement
     VariableDeclaration
     WhileStatement
     WithStatement
 */
 template <typename Tok>
 JS::Result<ParseNode*> BinASTParser<Tok>::parseStatement(
-    const Context& context) {
+    const FieldOrListContext& context) {
   BinASTKind kind;
   BinASTFields fields(cx_);
   AutoTaggedTuple guard(*tokenizer_);
   const auto start = tokenizer_->offset();
 
   MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, context, guard));
 
   BINJS_MOZ_TRY_DECL(result, parseSumStatement(start, kind, fields, context));
 
   MOZ_TRY(guard.done());
   return result;
 }
 
 template <typename Tok>
 JS::Result<ParseNode*> BinASTParser<Tok>::parseSumStatement(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
-    const Context& context) {
+    const FieldOrListContext& context) {
   ParseNode* result;
   switch (kind) {
     case BinASTKind::Block:
       MOZ_TRY_VAR(result, parseInterfaceBlock(start, kind, fields, context));
       break;
     case BinASTKind::BreakStatement:
       MOZ_TRY_VAR(result,
                   parseInterfaceBreakStatement(start, kind, fields, context));
@@ -1398,25 +1530,25 @@ JS::Result<ParseNode*> BinASTParser<Tok>
   return raiseError(
       "FIXME: Not implemented yet in this preview release "
       "(ArrayAssignmentTarget)");
 }
 
 template <typename Tok>
 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceArrayBinding(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
-    const Context& context) {
+    const FieldOrListContext& context) {
   return raiseError(
       "FIXME: Not implemented yet in this preview release (ArrayBinding)");
 }
 
 template <typename Tok>
 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceArrayExpression(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
-    const Context& context) {
+    const FieldOrListContext& context) {
   MOZ_ASSERT(kind == BinASTKind::ArrayExpression);
   BINJS_TRY(CheckRecursionLimit(cx_));
 
 #if defined(DEBUG)
   const BinASTField expected_fields[1] = {BinASTField::Elements};
   MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif  // defined(DEBUG)
 
@@ -1925,17 +2057,17 @@ JS::Result<Ok> BinASTParser<Tok>::parseI
   }
   auto result = Ok();
   return result;
 }
 
 template <typename Tok>
 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceAssignmentExpression(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
-    const Context& context) {
+    const FieldOrListContext& context) {
   MOZ_ASSERT(kind == BinASTKind::AssignmentExpression);
   BINJS_TRY(CheckRecursionLimit(cx_));
 
 #if defined(DEBUG)
   const BinASTField expected_fields[2] = {BinASTField::Binding,
                                           BinASTField::Expression};
   MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif  // defined(DEBUG)
@@ -1977,25 +2109,25 @@ BinASTParser<Tok>::parseInterfaceAssignm
   BINJS_TRY_DECL(result, handler_.newName(name->asPropertyName(),
                                           tokenizer_->pos(start), cx_));
   return result;
 }
 
 template <typename Tok>
 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceAwaitExpression(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
-    const Context& context) {
+    const FieldOrListContext& context) {
   return raiseError(
       "FIXME: Not implemented yet in this preview release (AwaitExpression)");
 }
 
 template <typename Tok>
 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceBinaryExpression(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
-    const Context& context) {
+    const FieldOrListContext& context) {
   MOZ_ASSERT(kind == BinASTKind::BinaryExpression);
   BINJS_TRY(CheckRecursionLimit(cx_));
 
 #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)
@@ -2109,17 +2241,17 @@ JS::Result<ParseNode*> BinASTParser<Tok>
 
 /*
  interface BindingIdentifier : Node {
     [IdentifierName] string name;
  }
 */
 template <typename Tok>
 JS::Result<ParseNode*> BinASTParser<Tok>::parseBindingIdentifier(
-    const Context& context) {
+    const FieldOrListContext& context) {
   BinASTKind kind;
   BinASTFields fields(cx_);
   AutoTaggedTuple guard(*tokenizer_);
 
   MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, context, guard));
   if (kind != BinASTKind::BindingIdentifier) {
     return raiseInvalidKind("BindingIdentifier", kind);
   }
@@ -2129,17 +2261,17 @@ JS::Result<ParseNode*> BinASTParser<Tok>
   MOZ_TRY(guard.done());
 
   return result;
 }
 
 template <typename Tok>
 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceBindingIdentifier(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
-    const Context& context) {
+    const FieldOrListContext& context) {
   MOZ_ASSERT(kind == BinASTKind::BindingIdentifier);
   BINJS_TRY(CheckRecursionLimit(cx_));
 
 #if defined(DEBUG)
   const BinASTField expected_fields[1] = {BinASTField::Name};
   MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif  // defined(DEBUG)
 
@@ -2150,30 +2282,31 @@ JS::Result<ParseNode*> BinASTParser<Tok>
   BINJS_TRY_DECL(result, handler_.newName(name->asPropertyName(),
                                           tokenizer_->pos(start), cx_));
   return result;
 }
 
 template <typename Tok>
 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceBindingWithInitializer(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
-    const Context& context) {
+    const FieldOrListContext& context) {
   return raiseError(
       "FIXME: Not implemented yet in this preview release "
       "(BindingWithInitializer)");
 }
 
 /*
  interface Block : Node {
     AssertedBlockScope scope;
     FrozenArray<Statement> statements;
  }
 */
 template <typename Tok>
-JS::Result<ParseNode*> BinASTParser<Tok>::parseBlock(const Context& context) {
+JS::Result<ParseNode*> BinASTParser<Tok>::parseBlock(
+    const FieldOrListContext& context) {
   BinASTKind kind;
   BinASTFields fields(cx_);
   AutoTaggedTuple guard(*tokenizer_);
 
   MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, context, guard));
   if (kind != BinASTKind::Block) {
     return raiseInvalidKind("Block", kind);
   }
@@ -2182,17 +2315,17 @@ JS::Result<ParseNode*> BinASTParser<Tok>
   MOZ_TRY(guard.done());
 
   return result;
 }
 
 template <typename Tok>
 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceBlock(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
-    const Context& context) {
+    const FieldOrListContext& context) {
   MOZ_ASSERT(kind == BinASTKind::Block);
   BINJS_TRY(CheckRecursionLimit(cx_));
 
 #if defined(DEBUG)
   const BinASTField expected_fields[2] = {BinASTField::Scope,
                                           BinASTField::Statements};
   MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif  // defined(DEBUG)
@@ -2211,17 +2344,17 @@ JS::Result<ParseNode*> BinASTParser<Tok>
   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) {
+    const FieldOrListContext& context) {
   MOZ_ASSERT(kind == BinASTKind::BreakStatement);
   BINJS_TRY(CheckRecursionLimit(cx_));
 
 #if defined(DEBUG)
   const BinASTField expected_fields[1] = {BinASTField::Label};
   MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif  // defined(DEBUG)
   RootedAtom label(cx_);
@@ -2251,17 +2384,17 @@ JS::Result<ParseNode*> BinASTParser<Tok>
                              label ? label->asPropertyName() : nullptr,
                              tokenizer_->pos(start)));
   return result;
 }
 
 template <typename Tok>
 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceCallExpression(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
-    const Context& context) {
+    const FieldOrListContext& context) {
   MOZ_ASSERT(kind == BinASTKind::CallExpression);
   BINJS_TRY(CheckRecursionLimit(cx_));
 
 #if defined(DEBUG)
   const BinASTField expected_fields[2] = {BinASTField::Callee,
                                           BinASTField::Arguments};
   MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif  // defined(DEBUG)
@@ -2352,47 +2485,47 @@ JS::Result<LexicalScopeNode*> BinASTPars
 
   BINJS_MOZ_TRY_DECL(binding,
                      parseBinding(FieldContext(
                          BinASTInterfaceAndField::CatchClause__Binding)));
   if (!currentScope.lookupDeclaredName(
           binding->template as<NameNode>().atom())) {
     return raiseError("Missing catch variable in scope");
   }
-  BINJS_MOZ_TRY_DECL(body, parseBlock(Context(FieldContext(
+  BINJS_MOZ_TRY_DECL(body, parseBlock(FieldOrListContext(FieldContext(
                                BinASTInterfaceAndField::CatchClause__Body))));
 
   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;
 }
 
 template <typename Tok>
 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceClassDeclaration(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
-    const Context& context) {
+    const FieldOrListContext& context) {
   return raiseError(
       "FIXME: Not implemented yet in this preview release (ClassDeclaration)");
 }
 
 template <typename Tok>
 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceClassExpression(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
-    const Context& context) {
+    const FieldOrListContext& context) {
   return raiseError(
       "FIXME: Not implemented yet in this preview release (ClassExpression)");
 }
 
 template <typename Tok>
 JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceCompoundAssignmentExpression(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
-    const Context& context) {
+    const FieldOrListContext& context) {
   MOZ_ASSERT(kind == BinASTKind::CompoundAssignmentExpression);
   BINJS_TRY(CheckRecursionLimit(cx_));
 
 #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)
@@ -2483,17 +2616,17 @@ BinASTParser<Tok>::parseInterfaceCompute
                                                      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) {
+    const FieldOrListContext& context) {
   MOZ_ASSERT(kind == BinASTKind::ComputedMemberExpression);
   BINJS_TRY(CheckRecursionLimit(cx_));
 
 #if defined(DEBUG)
   const BinASTField expected_fields[2] = {BinASTField::Object,
                                           BinASTField::Expression};
   MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif  // defined(DEBUG)
@@ -2519,17 +2652,17 @@ JS::Result<ParseNode*> BinASTParser<Tok>
   return raiseError(
       "FIXME: Not implemented yet in this preview release "
       "(ComputedPropertyName)");
 }
 
 template <typename Tok>
 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceConditionalExpression(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
-    const Context& context) {
+    const FieldOrListContext& context) {
   MOZ_ASSERT(kind == BinASTKind::ConditionalExpression);
   BINJS_TRY(CheckRecursionLimit(cx_));
 
 #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)
@@ -2550,17 +2683,17 @@ JS::Result<ParseNode*> BinASTParser<Tok>
 
   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) {
+    const FieldOrListContext& context) {
   MOZ_ASSERT(kind == BinASTKind::ContinueStatement);
   BINJS_TRY(CheckRecursionLimit(cx_));
 
 #if defined(DEBUG)
   const BinASTField expected_fields[1] = {BinASTField::Label};
   MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif  // defined(DEBUG)
   RootedAtom label(cx_);
@@ -2626,17 +2759,17 @@ JS::Result<ParseNode*> BinASTParser<Tok>
                               name, expression, AccessorType::None));
   }
   return result;
 }
 
 template <typename Tok>
 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceDebuggerStatement(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
-    const Context& context) {
+    const FieldOrListContext& context) {
   return raiseError(
       "FIXME: Not implemented yet in this preview release (DebuggerStatement)");
 }
 
 /*
  interface Directive : Node {
     string rawValue;
  }
@@ -2679,64 +2812,64 @@ JS::Result<ParseNode*> BinASTParser<Tok>
   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) {
+    const FieldOrListContext& context) {
   MOZ_ASSERT(kind == BinASTKind::DoWhileStatement);
   BINJS_TRY(CheckRecursionLimit(cx_));
 
 #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(
                 FieldContext(BinASTInterfaceAndField::DoWhileStatement__Test)));
 
   BINJS_MOZ_TRY_DECL(body,
-                     parseStatement(Context(FieldContext(
+                     parseStatement(FieldOrListContext(FieldContext(
                          BinASTInterfaceAndField::DoWhileStatement__Body))));
 
   BINJS_TRY_DECL(
       result, handler_.newDoWhileStatement(body, test, tokenizer_->pos(start)));
   return result;
 }
 
 template <typename Tok>
 JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceEagerArrowExpressionWithExpression(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
-    const Context& context) {
+    const FieldOrListContext& context) {
   return raiseError(
       "FIXME: Not implemented yet in this preview release "
       "(EagerArrowExpressionWithExpression)");
 }
 
 template <typename Tok>
 JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceEagerArrowExpressionWithFunctionBody(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
-    const Context& context) {
+    const FieldOrListContext& context) {
   return raiseError(
       "FIXME: Not implemented yet in this preview release "
       "(EagerArrowExpressionWithFunctionBody)");
 }
 
 template <typename Tok>
 JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceEagerFunctionDeclaration(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
-    const Context& context) {
+    const FieldOrListContext& context) {
   MOZ_ASSERT(kind == BinASTKind::EagerFunctionDeclaration);
   BINJS_TRY(CheckRecursionLimit(cx_));
 
 #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));
@@ -2754,17 +2887,17 @@ BinASTParser<Tok>::parseInterfaceEagerFu
   BINJS_MOZ_TRY_DECL(
       isGenerator,
       tokenizer_->readBool(FieldContext(
           BinASTInterfaceAndField::EagerFunctionDeclaration__IsGenerator)));
   if (isGenerator) {
     return raiseError("Generator is not supported in this preview release");
   }
   BINJS_MOZ_TRY_DECL(
-      name, parseBindingIdentifier(Context(FieldContext(
+      name, parseBindingIdentifier(FieldOrListContext(FieldContext(
                 BinASTInterfaceAndField::EagerFunctionDeclaration__Name))));
 
   BINJS_MOZ_TRY_DECL(
       length, tokenizer_->readUnsignedLong(FieldContext(
                   BinASTInterfaceAndField::EagerFunctionDeclaration__Length)));
 
   BINJS_MOZ_TRY_DECL(
       directives,
@@ -2792,34 +2925,34 @@ BinASTParser<Tok>::parseInterfaceEagerFu
   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(
+      FieldOrRootContext(FieldContext(
           BinASTInterfaceAndField::EagerFunctionDeclaration__Contents))));
   MOZ_TRY(prependDirectivesToBody(body, directives));
   uint32_t nargs = params->count();
 
   BINJS_TRY_DECL(lexicalScopeData,
                  NewLexicalScopeData(cx_, lexicalScope, alloc_, pc_));
   BINJS_TRY_DECL(bodyScope, handler_.newLexicalScope(*lexicalScopeData, body));
   BINJS_MOZ_TRY_DECL(result, makeEmptyFunctionNode(start, kind, funbox));
   MOZ_TRY(setFunctionParametersAndBody(result, params, bodyScope));
   MOZ_TRY(finishEagerFunction(funbox, nargs));
   return result;
 }
 
 template <typename Tok>
 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceEagerFunctionExpression(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
-    const Context& context) {
+    const FieldOrListContext& context) {
   MOZ_ASSERT(kind == BinASTKind::EagerFunctionExpression);
   BINJS_TRY(CheckRecursionLimit(cx_));
 
 #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));
@@ -2874,17 +3007,17 @@ JS::Result<ParseNode*> BinASTParser<Tok>
   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(
+      FieldOrRootContext(FieldContext(
           BinASTInterfaceAndField::EagerFunctionExpression__Contents))));
   MOZ_TRY(prependDirectivesToBody(body, directives));
   uint32_t nargs = params->count();
 
   BINJS_TRY_DECL(lexicalScopeData,
                  NewLexicalScopeData(cx_, lexicalScope, alloc_, pc_));
   BINJS_TRY_DECL(bodyScope, handler_.newLexicalScope(*lexicalScopeData, body));
   BINJS_MOZ_TRY_DECL(result, makeEmptyFunctionNode(start, kind, funbox));
@@ -3020,17 +3153,18 @@ JS::Result<ParseNode*> BinASTParser<Tok>
   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))));
+      FieldOrRootContext(
+          FieldContext(BinASTInterfaceAndField::EagerMethod__Contents))));
   MOZ_TRY(prependDirectivesToBody(body, directives));
   uint32_t nargs = params->count();
 
   BINJS_TRY_DECL(lexicalScopeData,
                  NewLexicalScopeData(cx_, lexicalScope, alloc_, pc_));
   BINJS_TRY_DECL(bodyScope, handler_.newLexicalScope(*lexicalScopeData, body));
   BINJS_MOZ_TRY_DECL(method, makeEmptyFunctionNode(start, kind, funbox));
   MOZ_TRY(setFunctionParametersAndBody(method, params, bodyScope));
@@ -3108,29 +3242,29 @@ JS::Result<ParseNode*> BinASTParser<Tok>
                              name, method, accessorType));
   MOZ_TRY(finishEagerFunction(funbox, nargs));
   return result;
 }
 
 template <typename Tok>
 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceEmptyStatement(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
-    const Context& context) {
+    const FieldOrListContext& context) {
   MOZ_ASSERT(kind == BinASTKind::EmptyStatement);
   BINJS_TRY(CheckRecursionLimit(cx_));
   MOZ_TRY(tokenizer_->checkFields0(kind, fields));
 
   BINJS_TRY_DECL(result, handler_.newEmptyStatement(tokenizer_->pos(start)));
   return result;
 }
 
 template <typename Tok>
 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceExpressionStatement(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
-    const Context& context) {
+    const FieldOrListContext& context) {
   MOZ_ASSERT(kind == BinASTKind::ExpressionStatement);
   BINJS_TRY(CheckRecursionLimit(cx_));
 
 #if defined(DEBUG)
   const BinASTField expected_fields[1] = {BinASTField::Expression};
   MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif  // defined(DEBUG)
 
@@ -3183,17 +3317,17 @@ JS::Result<ParseNode*> BinASTParser<Tok>
                  handler_.newDeclarationList(pnk, tokenizer_->pos(start)));
   handler_.addList(result, binding);
   return result;
 }
 
 template <typename Tok>
 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceForInStatement(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
-    const Context& context) {
+    const FieldOrListContext& context) {
   MOZ_ASSERT(kind == BinASTKind::ForInStatement);
   BINJS_TRY(CheckRecursionLimit(cx_));
 
 #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)
@@ -3208,17 +3342,17 @@ JS::Result<ParseNode*> BinASTParser<Tok>
   BINJS_MOZ_TRY_DECL(left, parseAssignmentTargetOrForInOfBinding(FieldContext(
                                BinASTInterfaceAndField::ForInStatement__Left)));
 
   BINJS_MOZ_TRY_DECL(
       right, parseExpression(
                  FieldContext(BinASTInterfaceAndField::ForInStatement__Right)));
 
   BINJS_MOZ_TRY_DECL(
-      body, parseStatement(Context(
+      body, parseStatement(FieldOrListContext(
                 FieldContext(BinASTInterfaceAndField::ForInStatement__Body))));
 
   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));
@@ -3228,25 +3362,25 @@ JS::Result<ParseNode*> BinASTParser<Tok>
     BINJS_TRY_VAR(result, handler_.newLexicalScope(*bindings, result));
   }
   return result;
 }
 
 template <typename Tok>
 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceForOfStatement(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
-    const Context& context) {
+    const FieldOrListContext& context) {
   return raiseError(
       "FIXME: Not implemented yet in this preview release (ForOfStatement)");
 }
 
 template <typename Tok>
 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceForStatement(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
-    const Context& context) {
+    const FieldOrListContext& context) {
   MOZ_ASSERT(kind == BinASTKind::ForStatement);
   BINJS_TRY(CheckRecursionLimit(cx_));
 
 #if defined(DEBUG)
   const BinASTField expected_fields[4] = {BinASTField::Init, BinASTField::Test,
                                           BinASTField::Update,
                                           BinASTField::Body};
   MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
@@ -3265,17 +3399,17 @@ JS::Result<ParseNode*> BinASTParser<Tok>
 
   BINJS_MOZ_TRY_DECL(test, parseOptionalExpression(FieldContext(
                                BinASTInterfaceAndField::ForStatement__Test)));
 
   BINJS_MOZ_TRY_DECL(
       update, parseOptionalExpression(
                   FieldContext(BinASTInterfaceAndField::ForStatement__Update)));
 
-  BINJS_MOZ_TRY_DECL(body, parseStatement(Context(FieldContext(
+  BINJS_MOZ_TRY_DECL(body, parseStatement(FieldOrListContext(FieldContext(
                                BinASTInterfaceAndField::ForStatement__Body))));
 
   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));
 
@@ -3348,17 +3482,17 @@ JS::Result<ListNode*> BinASTParser<Tok>:
     FormalParameters params;
     AssertedVarScope bodyScope;
     FunctionBody body;
  }
 */
 template <typename Tok>
 JS::Result<Ok> BinASTParser<Tok>::parseFunctionExpressionContents(
     uint32_t funLength, ListNode** paramsOut, ListNode** bodyOut,
-    const Context& context) {
+    const FieldOrRootContext& context) {
   BinASTKind kind;
   BinASTFields fields(cx_);
   AutoTaggedTuple guard(*tokenizer_);
 
   MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, context, guard));
   if (kind != BinASTKind::FunctionExpressionContents) {
     return raiseInvalidKind("FunctionExpressionContents", kind);
   }
@@ -3370,17 +3504,17 @@ JS::Result<Ok> BinASTParser<Tok>::parseF
 
   return result;
 }
 
 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) {
+    const FieldOrRootContext& context) {
   MOZ_ASSERT(kind == BinASTKind::FunctionExpressionContents);
   BINJS_TRY(CheckRecursionLimit(cx_));
 
 #if defined(DEBUG)
   const BinASTField expected_fields[6] = {BinASTField::IsFunctionNameCaptured,
                                           BinASTField::IsThisCaptured,
                                           BinASTField::ParameterScope,
                                           BinASTField::Params,
@@ -3438,17 +3572,17 @@ JS::Result<Ok> BinASTParser<Tok>::parseI
     FormalParameters params;
     AssertedVarScope bodyScope;
     FunctionBody body;
  }
 */
 template <typename Tok>
 JS::Result<Ok> BinASTParser<Tok>::parseFunctionOrMethodContents(
     uint32_t funLength, ListNode** paramsOut, ListNode** bodyOut,
-    const Context& context) {
+    const FieldOrRootContext& context) {
   BinASTKind kind;
   BinASTFields fields(cx_);
   AutoTaggedTuple guard(*tokenizer_);
 
   MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, context, guard));
   if (kind != BinASTKind::FunctionOrMethodContents) {
     return raiseInvalidKind("FunctionOrMethodContents", kind);
   }
@@ -3460,17 +3594,17 @@ JS::Result<Ok> BinASTParser<Tok>::parseF
 
   return result;
 }
 
 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) {
+    const FieldOrRootContext& context) {
   MOZ_ASSERT(kind == BinASTKind::FunctionOrMethodContents);
   BINJS_TRY(CheckRecursionLimit(cx_));
 
 #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));
@@ -3569,17 +3703,17 @@ JS::Result<Ok> BinASTParser<Tok>::parseI
 
 /*
  interface IdentifierExpression : Node {
     [IdentifierName] string name;
  }
 */
 template <typename Tok>
 JS::Result<ParseNode*> BinASTParser<Tok>::parseIdentifierExpression(
-    const Context& context) {
+    const FieldOrListContext& context) {
   BinASTKind kind;
   BinASTFields fields(cx_);
   AutoTaggedTuple guard(*tokenizer_);
 
   MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, context, guard));
   if (kind != BinASTKind::IdentifierExpression) {
     return raiseInvalidKind("IdentifierExpression", kind);
   }
@@ -3589,17 +3723,17 @@ JS::Result<ParseNode*> BinASTParser<Tok>
   MOZ_TRY(guard.done());
 
   return result;
 }
 
 template <typename Tok>
 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceIdentifierExpression(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
-    const Context& context) {
+    const FieldOrListContext& context) {
   MOZ_ASSERT(kind == BinASTKind::IdentifierExpression);
   BINJS_TRY(CheckRecursionLimit(cx_));
 
 #if defined(DEBUG)
   const BinASTField expected_fields[1] = {BinASTField::Name};
   MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif  // defined(DEBUG)
 
@@ -3612,46 +3746,46 @@ JS::Result<ParseNode*> BinASTParser<Tok>
   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) {
+    const FieldOrListContext& context) {
   MOZ_ASSERT(kind == BinASTKind::IfStatement);
   BINJS_TRY(CheckRecursionLimit(cx_));
 
 #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(FieldContext(
                                BinASTInterfaceAndField::IfStatement__Test)));
 
   BINJS_MOZ_TRY_DECL(consequent,
-                     parseStatement(Context(FieldContext(
+                     parseStatement(FieldOrListContext(FieldContext(
                          BinASTInterfaceAndField::IfStatement__Consequent))));
 
   BINJS_MOZ_TRY_DECL(alternate,
                      parseOptionalStatement(FieldContext(
                          BinASTInterfaceAndField::IfStatement__Alternate)));
 
   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) {
+    const FieldOrListContext& context) {
   MOZ_ASSERT(kind == BinASTKind::LabelledStatement);
   BINJS_TRY(CheckRecursionLimit(cx_));
 
 #if defined(DEBUG)
   const BinASTField expected_fields[2] = {BinASTField::Label,
                                           BinASTField::Body};
   MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif  // defined(DEBUG)
@@ -3659,48 +3793,48 @@ JS::Result<ParseNode*> BinASTParser<Tok>
   RootedAtom label(cx_);
   MOZ_TRY_VAR(label, tokenizer_->readAtom(FieldContext(
                          BinASTInterfaceAndField::LabelledStatement__Label)));
   if (!IsIdentifier(label)) {
     return raiseError("Invalid identifier");
   }
   ParseContext::LabelStatement stmt(pc_, label);
   BINJS_MOZ_TRY_DECL(body,
-                     parseStatement(Context(FieldContext(
+                     parseStatement(FieldOrListContext(FieldContext(
                          BinASTInterfaceAndField::LabelledStatement__Body))));
 
   BINJS_TRY_DECL(result, handler_.newLabeledStatement(label->asPropertyName(),
                                                       body, start));
   return result;
 }
 
 template <typename Tok>
 JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceLazyArrowExpressionWithExpression(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
-    const Context& context) {
+    const FieldOrListContext& context) {
   return raiseError(
       "FIXME: Not implemented yet in this preview release "
       "(LazyArrowExpressionWithExpression)");
 }
 
 template <typename Tok>
 JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceLazyArrowExpressionWithFunctionBody(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
-    const Context& context) {
+    const FieldOrListContext& context) {
   return raiseError(
       "FIXME: Not implemented yet in this preview release "
       "(LazyArrowExpressionWithFunctionBody)");
 }
 
 template <typename Tok>
 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceLazyFunctionDeclaration(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
-    const Context& context) {
+    const FieldOrListContext& context) {
   MOZ_ASSERT(kind == BinASTKind::LazyFunctionDeclaration);
   BINJS_TRY(CheckRecursionLimit(cx_));
 
 #if defined(DEBUG)
   const BinASTField expected_fields[7] = {
       BinASTField::IsAsync, BinASTField::IsGenerator, BinASTField::Name,
       BinASTField::Length,  BinASTField::Directives,  BinASTField::ContentsSkip,
       BinASTField::Contents};
@@ -3718,17 +3852,17 @@ JS::Result<ParseNode*> BinASTParser<Tok>
   BINJS_MOZ_TRY_DECL(
       isGenerator,
       tokenizer_->readBool(FieldContext(
           BinASTInterfaceAndField::LazyFunctionDeclaration__IsGenerator)));
   if (isGenerator) {
     return raiseError("Generator is not supported in this preview release");
   }
   BINJS_MOZ_TRY_DECL(
-      name, parseBindingIdentifier(Context(FieldContext(
+      name, parseBindingIdentifier(FieldOrListContext(FieldContext(
                 BinASTInterfaceAndField::LazyFunctionDeclaration__Name))));
 
   BINJS_MOZ_TRY_DECL(
       length, tokenizer_->readUnsignedLong(FieldContext(
                   BinASTInterfaceAndField::LazyFunctionDeclaration__Length)));
 
   BINJS_MOZ_TRY_DECL(
       directives,
@@ -3759,17 +3893,17 @@ JS::Result<ParseNode*> BinASTParser<Tok>
   auto skipEnd = skipStart + contentsSkip.length();
   MOZ_TRY(finishLazyFunction(funbox, nargs, skipStart, skipEnd));
   return result;
 }
 
 template <typename Tok>
 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceLazyFunctionExpression(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
-    const Context& context) {
+    const FieldOrListContext& context) {
   MOZ_ASSERT(kind == BinASTKind::LazyFunctionExpression);
   BINJS_TRY(CheckRecursionLimit(cx_));
 
 #if defined(DEBUG)
   const BinASTField expected_fields[7] = {
       BinASTField::IsAsync, BinASTField::IsGenerator, BinASTField::Name,
       BinASTField::Length,  BinASTField::Directives,  BinASTField::ContentsSkip,
       BinASTField::Contents};
@@ -3853,17 +3987,17 @@ JS::Result<ParseNode*> BinASTParser<Tok>
   return raiseError(
       "FIXME: Not implemented yet in this preview release (LazySetter)");
 }
 
 template <typename Tok>
 JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceLiteralBooleanExpression(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
-    const Context& context) {
+    const FieldOrListContext& context) {
   MOZ_ASSERT(kind == BinASTKind::LiteralBooleanExpression);
   BINJS_TRY(CheckRecursionLimit(cx_));
 
 #if defined(DEBUG)
   const BinASTField expected_fields[1] = {BinASTField::Value};
   MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif  // defined(DEBUG)
 
@@ -3875,39 +4009,39 @@ BinASTParser<Tok>::parseInterfaceLiteral
                  handler_.newBooleanLiteral(value, tokenizer_->pos(start)));
   return result;
 }
 
 template <typename Tok>
 JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceLiteralInfinityExpression(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
-    const Context& context) {
+    const FieldOrListContext& context) {
   return raiseError(
       "FIXME: Not implemented yet in this preview release "
       "(LiteralInfinityExpression)");
 }
 
 template <typename Tok>
 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceLiteralNullExpression(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
-    const Context& context) {
+    const FieldOrListContext& context) {
   MOZ_ASSERT(kind == BinASTKind::LiteralNullExpression);
   BINJS_TRY(CheckRecursionLimit(cx_));
   MOZ_TRY(tokenizer_->checkFields0(kind, fields));
 
   BINJS_TRY_DECL(result, handler_.newNullLiteral(tokenizer_->pos(start)));
   return result;
 }
 
 template <typename Tok>
 JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceLiteralNumericExpression(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
-    const Context& context) {
+    const FieldOrListContext& context) {
   MOZ_ASSERT(kind == BinASTKind::LiteralNumericExpression);
   BINJS_TRY(CheckRecursionLimit(cx_));
 
 #if defined(DEBUG)
   const BinASTField expected_fields[1] = {BinASTField::Value};
   MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif  // defined(DEBUG)
 
@@ -3947,17 +4081,17 @@ JS::Result<ParseNode*> BinASTParser<Tok>
                               value, tokenizer_->pos(start)));
   }
   return result;
 }
 
 template <typename Tok>
 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceLiteralRegExpExpression(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
-    const Context& context) {
+    const FieldOrListContext& context) {
   MOZ_ASSERT(kind == BinASTKind::LiteralRegExpExpression);
   BINJS_TRY(CheckRecursionLimit(cx_));
 
 #if defined(DEBUG)
   const BinASTField expected_fields[2] = {BinASTField::Pattern,
                                           BinASTField::Flags};
   MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif  // defined(DEBUG)
@@ -3992,17 +4126,17 @@ JS::Result<ParseNode*> BinASTParser<Tok>
   BINJS_TRY_DECL(result,
                  handler_.newRegExp(reobj, tokenizer_->pos(start), *this));
   return result;
 }
 
 template <typename Tok>
 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceLiteralStringExpression(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
-    const Context& context) {
+    const FieldOrListContext& context) {
   MOZ_ASSERT(kind == BinASTKind::LiteralStringExpression);
   BINJS_TRY(CheckRecursionLimit(cx_));
 
 #if defined(DEBUG)
   const BinASTField expected_fields[1] = {BinASTField::Value};
   MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif  // defined(DEBUG)
 
@@ -4022,17 +4156,17 @@ JS::Result<ParseNode*> BinASTParser<Tok>
     const RootContext& context) {
   return raiseError(
       "FIXME: Not implemented yet in this preview release (Module)");
 }
 
 template <typename Tok>
 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceNewExpression(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
-    const Context& context) {
+    const FieldOrListContext& context) {
   MOZ_ASSERT(kind == BinASTKind::NewExpression);
   BINJS_TRY(CheckRecursionLimit(cx_));
 
 #if defined(DEBUG)
   const BinASTField expected_fields[2] = {BinASTField::Callee,
                                           BinASTField::Arguments};
   MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif  // defined(DEBUG)
@@ -4049,17 +4183,17 @@ JS::Result<ParseNode*> BinASTParser<Tok>
                  handler_.newNewExpression(tokenizer_->pos(start).begin, callee,
                                            arguments, /* isSpread = */ false));
   return result;
 }
 
 template <typename Tok>
 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceNewTargetExpression(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
-    const Context& context) {
+    const FieldOrListContext& context) {
   return raiseError(
       "FIXME: Not implemented yet in this preview release "
       "(NewTargetExpression)");
 }
 
 template <typename Tok>
 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceObjectAssignmentTarget(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
@@ -4067,25 +4201,25 @@ JS::Result<ParseNode*> BinASTParser<Tok>
   return raiseError(
       "FIXME: Not implemented yet in this preview release "
       "(ObjectAssignmentTarget)");
 }
 
 template <typename Tok>
 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceObjectBinding(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
-    const Context& context) {
+    const FieldOrListContext& context) {
   return raiseError(
       "FIXME: Not implemented yet in this preview release (ObjectBinding)");
 }
 
 template <typename Tok>
 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceObjectExpression(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
-    const Context& context) {
+    const FieldOrListContext& context) {
   MOZ_ASSERT(kind == BinASTKind::ObjectExpression);
   BINJS_TRY(CheckRecursionLimit(cx_));
 
 #if defined(DEBUG)
   const BinASTField expected_fields[1] = {BinASTField::Properties};
   MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif  // defined(DEBUG)
 
@@ -4095,17 +4229,17 @@ JS::Result<ParseNode*> BinASTParser<Tok>
 
   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) {
+    const FieldOrListContext& context) {
   MOZ_ASSERT(kind == BinASTKind::ReturnStatement);
   BINJS_TRY(CheckRecursionLimit(cx_));
 
 #if defined(DEBUG)
   const BinASTField expected_fields[1] = {BinASTField::Expression};
   MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif  // defined(DEBUG)
   if (!pc_->isFunctionBox()) {
@@ -4206,17 +4340,17 @@ JS::Result<Ok> BinASTParser<Tok>::parseI
   // TODO: Use this in BinASTParser::buildFunction.
   (void)isThisCaptured;
   Rooted<GCVector<JSAtom*>> positionalParams(cx_, GCVector<JSAtom*>(cx_));
   MOZ_TRY(parseAssertedParameterScope(
       &positionalParams,
       FieldContext(BinASTInterfaceAndField::SetterContents__ParameterScope)));
 
   BINJS_MOZ_TRY_DECL(param,
-                     parseParameter(Context(FieldContext(
+                     parseParameter(FieldOrListContext(FieldContext(
                          BinASTInterfaceAndField::SetterContents__Param))));
   BINJS_TRY_DECL(params, handler_.newParamsBody(param->pn_pos));
   handler_.addList(params, param);
   MOZ_TRY(checkPositionalParameterIndices(positionalParams, params));
   MOZ_TRY(parseAssertedVarScope(
       FieldContext(BinASTInterfaceAndField::SetterContents__BodyScope)));
 
   BINJS_MOZ_TRY_DECL(body, parseFunctionBody(FieldContext(
@@ -4236,17 +4370,17 @@ JS::Result<ParseNode*> BinASTParser<Tok>
   BINJS_TRY(CheckRecursionLimit(cx_));
 
 #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(
+                     parseIdentifierExpression(FieldOrListContext(FieldContext(
                          BinASTInterfaceAndField::ShorthandProperty__Name))));
 
   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)));
 
@@ -4296,17 +4430,17 @@ BinASTParser<Tok>::parseInterfaceStaticM
                                                 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) {
+    const FieldOrListContext& context) {
   MOZ_ASSERT(kind == BinASTKind::StaticMemberExpression);
   BINJS_TRY(CheckRecursionLimit(cx_));
 
 #if defined(DEBUG)
   const BinASTField expected_fields[2] = {BinASTField::Object,
                                           BinASTField::Property};
   MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif  // defined(DEBUG)
@@ -4431,17 +4565,17 @@ JS::Result<ParseNode*> BinASTParser<Tok>
 
   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) {
+    const FieldOrListContext& context) {
   MOZ_ASSERT(kind == BinASTKind::SwitchStatement);
   BINJS_TRY(CheckRecursionLimit(cx_));
 
 #if defined(DEBUG)
   const BinASTField expected_fields[2] = {BinASTField::Discriminant,
                                           BinASTField::Cases};
   MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif  // defined(DEBUG)
@@ -4460,17 +4594,17 @@ JS::Result<ParseNode*> BinASTParser<Tok>
                                                      /* 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) {
+    const FieldOrListContext& context) {
   MOZ_ASSERT(kind == BinASTKind::SwitchStatementWithDefault);
   BINJS_TRY(CheckRecursionLimit(cx_));
 
 #if defined(DEBUG)
   const BinASTField expected_fields[4] = {
       BinASTField::Discriminant, BinASTField::PreDefaultCases,
       BinASTField::DefaultCase, BinASTField::PostDefaultCases};
   MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
@@ -4509,26 +4643,26 @@ BinASTParser<Tok>::parseInterfaceSwitchS
   BINJS_TRY_DECL(result, handler_.newSwitchStatement(start, discriminant, scope,
                                                      /* hasDefault = */ true));
   return result;
 }
 
 template <typename Tok>
 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceTemplateExpression(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
-    const Context& context) {
+    const FieldOrListContext& context) {
   return raiseError(
       "FIXME: Not implemented yet in this preview release "
       "(TemplateExpression)");
 }
 
 template <typename Tok>
 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceThisExpression(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
-    const Context& context) {
+    const FieldOrListContext& context) {
   MOZ_ASSERT(kind == BinASTKind::ThisExpression);
   BINJS_TRY(CheckRecursionLimit(cx_));
   MOZ_TRY(tokenizer_->checkFields0(kind, fields));
 
   if (pc_->isFunctionBox()) {
     pc_->functionBox()->usesThis = true;
   }
 
@@ -4543,17 +4677,17 @@ JS::Result<ParseNode*> BinASTParser<Tok>
 
   BINJS_TRY_DECL(result, handler_.newThisLiteral(pos, thisName));
   return result;
 }
 
 template <typename Tok>
 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceThrowStatement(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
-    const Context& context) {
+    const FieldOrListContext& context) {
   MOZ_ASSERT(kind == BinASTKind::ThrowStatement);
   BINJS_TRY(CheckRecursionLimit(cx_));
 
 #if defined(DEBUG)
   const BinASTField expected_fields[1] = {BinASTField::Expression};
   MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif  // defined(DEBUG)
 
@@ -4564,32 +4698,32 @@ JS::Result<ParseNode*> BinASTParser<Tok>
   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) {
+    const FieldOrListContext& context) {
   MOZ_ASSERT(kind == BinASTKind::TryCatchStatement);
   BINJS_TRY(CheckRecursionLimit(cx_));
 
 #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(
+    MOZ_TRY_VAR(body, parseBlock(FieldOrListContext(FieldContext(
                           BinASTInterfaceAndField::TryCatchStatement__Body))));
   }
 
   BINJS_MOZ_TRY_DECL(
       catchClause,
       parseCatchClause(FieldContext(
           BinASTInterfaceAndField::TryCatchStatement__CatchClause)));
 
@@ -4597,60 +4731,60 @@ JS::Result<ParseNode*> BinASTParser<Tok>
                  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) {
+    const FieldOrListContext& context) {
   MOZ_ASSERT(kind == BinASTKind::TryFinallyStatement);
   BINJS_TRY(CheckRecursionLimit(cx_));
 
 #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(
+                parseBlock(FieldOrListContext(FieldContext(
                     BinASTInterfaceAndField::TryFinallyStatement__Body))));
   }
 
   BINJS_MOZ_TRY_DECL(
       catchClause,
       parseOptionalCatchClause(FieldContext(
           BinASTInterfaceAndField::TryFinallyStatement__CatchClause)));
 
   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(
+                parseBlock(FieldOrListContext(FieldContext(
                     BinASTInterfaceAndField::TryFinallyStatement__Finalizer))));
   }
 
   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) {
+    const FieldOrListContext& context) {
   MOZ_ASSERT(kind == BinASTKind::UnaryExpression);
   BINJS_TRY(CheckRecursionLimit(cx_));
 
 #if defined(DEBUG)
   const BinASTField expected_fields[2] = {BinASTField::Operator,
                                           BinASTField::Operand};
   MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif  // defined(DEBUG)
@@ -4709,17 +4843,17 @@ JS::Result<ParseNode*> BinASTParser<Tok>
   }
   BINJS_TRY_DECL(result, handler_.newUnary(pnk, start, operand));
   return result;
 }
 
 template <typename Tok>
 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceUpdateExpression(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
-    const Context& context) {
+    const FieldOrListContext& context) {
   MOZ_ASSERT(kind == BinASTKind::UpdateExpression);
   BINJS_TRY(CheckRecursionLimit(cx_));
 
 #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)
@@ -4749,17 +4883,17 @@ JS::Result<ParseNode*> BinASTParser<Tok>
   }
   BINJS_TRY_DECL(result, handler_.newUnary(pnk, start, operand));
   return result;
 }
 
 template <typename Tok>
 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceVariableDeclaration(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
-    const Context& context) {
+    const FieldOrListContext& context) {
   MOZ_ASSERT(kind == BinASTKind::VariableDeclaration);
   BINJS_TRY(CheckRecursionLimit(cx_));
 
 #if defined(DEBUG)
   const BinASTField expected_fields[2] = {BinASTField::Kind,
                                           BinASTField::Declarators};
   MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif  // defined(DEBUG)
@@ -4868,75 +5002,75 @@ JS::Result<ParseNode*> BinASTParser<Tok>
                                                  binding, init));
   }
   return result;
 }
 
 template <typename Tok>
 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceWhileStatement(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
-    const Context& context) {
+    const FieldOrListContext& context) {
   MOZ_ASSERT(kind == BinASTKind::WhileStatement);
   BINJS_TRY(CheckRecursionLimit(cx_));
 
 #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(FieldContext(
                                BinASTInterfaceAndField::WhileStatement__Test)));
 
   BINJS_MOZ_TRY_DECL(
-      body, parseStatement(Context(
+      body, parseStatement(FieldOrListContext(
                 FieldContext(BinASTInterfaceAndField::WhileStatement__Body))));
 
   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) {
+    const FieldOrListContext& context) {
   MOZ_ASSERT(kind == BinASTKind::WithStatement);
   BINJS_TRY(CheckRecursionLimit(cx_));
 
 #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(FieldContext(
                          BinASTInterfaceAndField::WithStatement__Object)));
 
   ParseContext::Statement stmt(pc_, StatementKind::With);
-  BINJS_MOZ_TRY_DECL(body, parseStatement(Context(FieldContext(
+  BINJS_MOZ_TRY_DECL(body, parseStatement(FieldOrListContext(FieldContext(
                                BinASTInterfaceAndField::WithStatement__Body))));
 
   pc_->sc()->setBindingsAccessedDynamically();
   BINJS_TRY_DECL(result, handler_.newWithStatement(start, object, body));
   return result;
 }
 
 template <typename Tok>
 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceYieldExpression(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
-    const Context& context) {
+    const FieldOrListContext& context) {
   return raiseError(
       "FIXME: Not implemented yet in this preview release (YieldExpression)");
 }
 
 template <typename Tok>
 JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceYieldStarExpression(
     const size_t start, const BinASTKind kind, const BinASTFields& fields,
-    const Context& context) {
+    const FieldOrListContext& context) {
   return raiseError(
       "FIXME: Not implemented yet in this preview release "
       "(YieldStarExpression)");
 }
 
 // ----- String enums (autogenerated, by lexicographical order)
 /*
 enum AssertedDeclaredKind {
@@ -5217,17 +5351,17 @@ JS::Result<ListNode*> BinASTParser<Tok>:
 
   const auto start = tokenizer_->offset();
   const auto childContext =
       ListContext(context.position, BinASTList::ListOfStatement);
   MOZ_TRY(tokenizer_->enterList(length, childContext, guard));
   BINJS_TRY_DECL(result, handler_.newStatementList(tokenizer_->pos(start)));
 
   for (uint32_t i = 0; i < length; ++i) {
-    BINJS_MOZ_TRY_DECL(item, parseStatement(Context(childContext)));
+    BINJS_MOZ_TRY_DECL(item, parseStatement(FieldOrListContext(childContext)));
     handler_.addStatementToList(result, item);
   }
 
   MOZ_TRY(guard.done());
   return result;
 }
 
 template <typename Tok>
@@ -5386,17 +5520,17 @@ JS::Result<ListNode*> BinASTParser<Tok>:
 
   const auto start = tokenizer_->offset();
   const auto childContext =
       ListContext(context.position, BinASTList::ListOfParameter);
   MOZ_TRY(tokenizer_->enterList(length, childContext, guard));
   BINJS_TRY_DECL(result, handler_.newParamsBody(tokenizer_->pos(start)));
 
   for (uint32_t i = 0; i < length; ++i) {
-    BINJS_MOZ_TRY_DECL(item, parseParameter(Context(childContext)));
+    BINJS_MOZ_TRY_DECL(item, parseParameter(FieldOrListContext(childContext)));
     handler_.addList(/* list = */ result, /* kid = */ item);
   }
 
   MOZ_TRY(guard.done());
   return result;
 }
 
 template <typename Tok>
@@ -5407,17 +5541,17 @@ JS::Result<ListNode*> BinASTParser<Tok>:
 
   const auto start = tokenizer_->offset();
   const auto childContext =
       ListContext(context.position, BinASTList::ListOfStatement);
   MOZ_TRY(tokenizer_->enterList(length, childContext, guard));
   BINJS_TRY_DECL(result, handler_.newStatementList(tokenizer_->pos(start)));
 
   for (uint32_t i = 0; i < length; ++i) {
-    BINJS_MOZ_TRY_DECL(item, parseStatement(Context(childContext)));
+    BINJS_MOZ_TRY_DECL(item, parseStatement(FieldOrListContext(childContext)));
     handler_.addStatementToList(result, item);
   }
 
   MOZ_TRY(guard.done());
   return result;
 }
 
 template <typename Tok>
@@ -5492,18 +5626,18 @@ JS::Result<ParseNode*> BinASTParser<Tok>
   AutoTaggedTuple guard(*tokenizer_);
 
   MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, context, guard));
   ParseNode* result;
   if (kind == BinASTKind::_Null) {
     result = nullptr;
   } else if (kind == BinASTKind::BindingIdentifier) {
     const auto start = tokenizer_->offset();
-    MOZ_TRY_VAR(result, parseInterfaceBindingIdentifier(start, kind, fields,
-                                                        Context(context)));
+    MOZ_TRY_VAR(result, parseInterfaceBindingIdentifier(
+                            start, kind, fields, FieldOrListContext(context)));
   } else {
     return raiseInvalidKind("BindingIdentifier", kind);
   }
   MOZ_TRY(guard.done());
 
   return result;
 }
 
@@ -5602,18 +5736,18 @@ JS::Result<ParseNode*> BinASTParser<Tok>
   AutoTaggedTuple guard(*tokenizer_);
 
   MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, context, guard));
   ParseNode* result;
   if (kind == BinASTKind::_Null) {
     result = nullptr;
   } else {
     const auto start = tokenizer_->offset();
-    MOZ_TRY_VAR(result,
-                parseSumStatement(start, kind, fields, Context(context)));
+    MOZ_TRY_VAR(result, parseSumStatement(start, kind, fields,
+                                          FieldOrListContext(context)));
   }
   MOZ_TRY(guard.done());
 
   return result;
 }
 
 // Force class instantiation.
 // This ensures that the symbols are built, without having to export all our
--- a/js/src/frontend/BinASTParser.h
+++ b/js/src/frontend/BinASTParser.h
@@ -39,20 +39,21 @@ class BinASTParser : public BinASTParser
   using Base = BinASTParserPerTokenizer<Tok>;
 
   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;
+  using FieldOrRootContext = BinASTTokenReaderBase::FieldOrRootContext;
+  using FieldOrListContext = BinASTTokenReaderBase::FieldOrListContext;
 
  public:
   // Auto-generated types.
   using AssertedDeclaredKind = binast::AssertedDeclaredKind;
   using BinaryOperator = binast::BinaryOperator;
   using CompoundAssignmentOperator = binast::CompoundAssignmentOperator;
   using UnaryOperator = binast::UnaryOperator;
   using UpdateOperator = binast::UpdateOperator;
@@ -136,22 +137,22 @@ class BinASTParser : public BinASTParser
   JS::Result<ParseNode*> parseAssignmentTargetOrForInOfBinding(
       const FieldContext& context);
   JS::Result<ParseNode*> parseBinding(const FieldContext& context);
   JS::Result<ParseNode*> parseExpression(const FieldContext& context);
   JS::Result<ParseNode*> parseExpressionOrSpreadElement(
       const ListContext& context);
   JS::Result<ParseNode*> parseExpressionOrSuper(const FieldContext& context);
   JS::Result<ParseNode*> parseObjectProperty(const ListContext& context);
-  JS::Result<ParseNode*> parseParameter(const Context& context);
+  JS::Result<ParseNode*> parseParameter(const FieldOrListContext& context);
   JS::Result<ParseNode*> parseProgram(const RootContext& context);
   JS::Result<ParseNode*> parsePropertyName(const FieldContext& context);
   JS::Result<ParseNode*> parseSimpleAssignmentTarget(
       const FieldContext& context);
-  JS::Result<ParseNode*> parseStatement(const Context& context);
+  JS::Result<ParseNode*> parseStatement(const FieldOrListContext& context);
   JS::Result<Ok> parseSumAssertedMaybePositionalParameterName(
       const size_t start, const BinASTKind kind, const BinASTFields& fields,
       AssertedScopeKind scopeKind,
       MutableHandle<GCVector<JSAtom*>> positionalParams,
       const ListContext& context);
   JS::Result<ParseNode*> parseSumAssignmentTarget(const size_t start,
                                                   const BinASTKind kind,
                                                   const BinASTFields& fields,
@@ -179,79 +180,78 @@ class BinASTParser : public BinASTParser
       const FieldContext& context);
   JS::Result<ParseNode*> parseSumObjectProperty(const size_t start,
                                                 const BinASTKind kind,
                                                 const BinASTFields& fields,
                                                 const ListContext& context);
   JS::Result<ParseNode*> parseSumParameter(const size_t start,
                                            const BinASTKind kind,
                                            const BinASTFields& fields,
-                                           const Context& context);
+                                           const FieldOrListContext& context);
   JS::Result<ParseNode*> parseSumProgram(const size_t start,
                                          const BinASTKind kind,
                                          const BinASTFields& fields,
                                          const RootContext& context);
   JS::Result<ParseNode*> parseSumPropertyName(const size_t start,
                                               const BinASTKind kind,
                                               const BinASTFields& fields,
                                               const FieldContext& context);
   JS::Result<ParseNode*> parseSumSimpleAssignmentTarget(
       const size_t start, const BinASTKind kind, const BinASTFields& fields,
       const FieldContext& context);
   JS::Result<ParseNode*> parseSumStatement(const size_t start,
                                            const BinASTKind kind,
                                            const BinASTFields& fields,
-                                           const Context& context);
+                                           const FieldOrListContext& context);
 
   // ----- Interfaces (by lexicographical order)
   // `ParseNode*` may never be nullptr
   JS::Result<Ok> parseAssertedBlockScope(const FieldContext& context);
   JS::Result<Ok> parseAssertedBoundName(AssertedScopeKind scopeKind,
                                         const ListContext& context);
   JS::Result<Ok> parseAssertedBoundNamesScope(const FieldContext& context);
   JS::Result<Ok> parseAssertedDeclaredName(AssertedScopeKind scopeKind,
                                            const ListContext& context);
   JS::Result<Ok> parseAssertedParameterScope(
       MutableHandle<GCVector<JSAtom*>> positionalParams,
       const FieldContext& context);
   JS::Result<Ok> parseAssertedScriptGlobalScope(const FieldContext& context);
   JS::Result<Ok> parseAssertedVarScope(const FieldContext& context);
-  JS::Result<ParseNode*> parseBindingIdentifier(const Context& context);
-  JS::Result<ParseNode*> parseBlock(const Context& context);
+  JS::Result<ParseNode*> parseBindingIdentifier(
+      const FieldOrListContext& context);
+  JS::Result<ParseNode*> parseBlock(const FieldOrListContext& context);
   JS::Result<LexicalScopeNode*> parseCatchClause(const FieldContext& context);
   JS::Result<ParseNode*> parseDirective(const ListContext& context);
   JS::Result<ListNode*> parseFormalParameters(const FieldContext& context);
-  JS::Result<Ok> parseFunctionExpressionContents(uint32_t funLength,
-                                                 ListNode** paramsOut,
-                                                 ListNode** bodyOut,
-                                                 const Context& context);
-  JS::Result<Ok> parseFunctionOrMethodContents(uint32_t funLength,
-                                               ListNode** paramsOut,
-                                               ListNode** bodyOut,
-                                               const Context& context);
+  JS::Result<Ok> parseFunctionExpressionContents(
+      uint32_t funLength, ListNode** paramsOut, ListNode** bodyOut,
+      const FieldOrRootContext& context);
+  JS::Result<Ok> parseFunctionOrMethodContents(
+      uint32_t funLength, ListNode** paramsOut, ListNode** bodyOut,
+      const FieldOrRootContext& context);
   JS::Result<Ok> parseGetterContents(uint32_t funLength, ListNode** paramsOut,
                                      ListNode** bodyOut,
                                      const FieldContext& context);
-  JS::Result<ParseNode*> parseIdentifierExpression(const Context& context);
+  JS::Result<ParseNode*> parseIdentifierExpression(
+      const FieldOrListContext& context);
   JS::Result<Ok> parseSetterContents(uint32_t funLength, ListNode** paramsOut,
                                      ListNode** bodyOut,
                                      const FieldContext& context);
   JS::Result<CaseClause*> parseSwitchCase(const ListContext& context);
   JS::Result<ParseNode*> parseSwitchDefault(const FieldContext& context);
   JS::Result<ParseNode*> parseVariableDeclarator(const ListContext& context);
   JS::Result<ParseNode*> parseInterfaceArrayAssignmentTarget(
       const size_t start, const BinASTKind kind, const BinASTFields& fields,
       const FieldContext& context);
-  JS::Result<ParseNode*> parseInterfaceArrayBinding(const size_t start,
-                                                    const BinASTKind kind,
-                                                    const BinASTFields& fields,
-                                                    const Context& context);
+  JS::Result<ParseNode*> parseInterfaceArrayBinding(
+      const size_t start, const BinASTKind kind, const BinASTFields& fields,
+      const FieldOrListContext& context);
   JS::Result<ParseNode*> parseInterfaceArrayExpression(
       const size_t start, const BinASTKind kind, const BinASTFields& fields,
-      const Context& context);
+      const FieldOrListContext& context);
   JS::Result<Ok> parseInterfaceAssertedBlockScope(const size_t start,
                                                   const BinASTKind kind,
                                                   const BinASTFields& fields,
                                                   const FieldContext& context);
   JS::Result<Ok> parseInterfaceAssertedBoundName(const size_t start,
                                                  const BinASTKind kind,
                                                  const BinASTFields& fields,
                                                  AssertedScopeKind scopeKind,
@@ -277,220 +277,216 @@ class BinASTParser : public BinASTParser
       const size_t start, const BinASTKind kind, const BinASTFields& fields,
       const FieldContext& context);
   JS::Result<Ok> parseInterfaceAssertedVarScope(const size_t start,
                                                 const BinASTKind kind,
                                                 const BinASTFields& fields,
                                                 const FieldContext& context);
   JS::Result<ParseNode*> parseInterfaceAssignmentExpression(
       const size_t start, const BinASTKind kind, const BinASTFields& fields,
-      const Context& context);
+      const FieldOrListContext& context);
   JS::Result<ParseNode*> parseInterfaceAssignmentTargetIdentifier(
       const size_t start, const BinASTKind kind, const BinASTFields& fields,
       const FieldContext& context);
   JS::Result<ParseNode*> parseInterfaceAwaitExpression(
       const size_t start, const BinASTKind kind, const BinASTFields& fields,
-      const Context& context);
+      const FieldOrListContext& context);
   JS::Result<ParseNode*> parseInterfaceBinaryExpression(
       const size_t start, const BinASTKind kind, const BinASTFields& fields,
-      const Context& context);
+      const FieldOrListContext& context);
   JS::Result<ParseNode*> parseInterfaceBindingIdentifier(
       const size_t start, const BinASTKind kind, const BinASTFields& fields,
-      const Context& context);
+      const FieldOrListContext& context);
   JS::Result<ParseNode*> parseInterfaceBindingWithInitializer(
       const size_t start, const BinASTKind kind, const BinASTFields& fields,
-      const Context& context);
+      const FieldOrListContext& context);
   JS::Result<ParseNode*> parseInterfaceBlock(const size_t start,
                                              const BinASTKind kind,
                                              const BinASTFields& fields,
-                                             const Context& context);
+                                             const FieldOrListContext& context);
   JS::Result<ParseNode*> parseInterfaceBreakStatement(
       const size_t start, const BinASTKind kind, const BinASTFields& fields,
-      const Context& context);
+      const FieldOrListContext& context);
   JS::Result<ParseNode*> parseInterfaceCallExpression(
       const size_t start, const BinASTKind kind, const BinASTFields& fields,
-      const Context& context);
+      const FieldOrListContext& context);
   JS::Result<LexicalScopeNode*> parseInterfaceCatchClause(
       const size_t start, const BinASTKind kind, const BinASTFields& fields,
       const FieldContext& context);
   JS::Result<ParseNode*> parseInterfaceClassDeclaration(
       const size_t start, const BinASTKind kind, const BinASTFields& fields,
-      const Context& context);
+      const FieldOrListContext& context);
   JS::Result<ParseNode*> parseInterfaceClassExpression(
       const size_t start, const BinASTKind kind, const BinASTFields& fields,
-      const Context& context);
+      const FieldOrListContext& context);
   JS::Result<ParseNode*> parseInterfaceCompoundAssignmentExpression(
       const size_t start, const BinASTKind kind, const BinASTFields& fields,
-      const Context& context);
+      const FieldOrListContext& context);
   JS::Result<ParseNode*> parseInterfaceComputedMemberAssignmentTarget(
       const size_t start, const BinASTKind kind, const BinASTFields& fields,
       const FieldContext& context);
   JS::Result<ParseNode*> parseInterfaceComputedMemberExpression(
       const size_t start, const BinASTKind kind, const BinASTFields& fields,
-      const Context& context);
+      const FieldOrListContext& context);
   JS::Result<ParseNode*> parseInterfaceComputedPropertyName(
       const size_t start, const BinASTKind kind, const BinASTFields& fields,
       const FieldContext& context);
   JS::Result<ParseNode*> parseInterfaceConditionalExpression(
       const size_t start, const BinASTKind kind, const BinASTFields& fields,
-      const Context& context);
+      const FieldOrListContext& context);
   JS::Result<ParseNode*> parseInterfaceContinueStatement(
       const size_t start, const BinASTKind kind, const BinASTFields& fields,
-      const Context& context);
+      const FieldOrListContext& context);
   JS::Result<ParseNode*> parseInterfaceDataProperty(const size_t start,
                                                     const BinASTKind kind,
                                                     const BinASTFields& fields,
                                                     const ListContext& context);
   JS::Result<ParseNode*> parseInterfaceDebuggerStatement(
       const size_t start, const BinASTKind kind, const BinASTFields& fields,
-      const Context& context);
+      const FieldOrListContext& context);
   JS::Result<ParseNode*> parseInterfaceDirective(const size_t start,
                                                  const BinASTKind kind,
                                                  const BinASTFields& fields,
                                                  const ListContext& context);
   JS::Result<ParseNode*> parseInterfaceDoWhileStatement(
       const size_t start, const BinASTKind kind, const BinASTFields& fields,
-      const Context& context);
+      const FieldOrListContext& context);
   JS::Result<ParseNode*> parseInterfaceEagerArrowExpressionWithExpression(
       const size_t start, const BinASTKind kind, const BinASTFields& fields,
-      const Context& context);
+      const FieldOrListContext& context);
   JS::Result<ParseNode*> parseInterfaceEagerArrowExpressionWithFunctionBody(
       const size_t start, const BinASTKind kind, const BinASTFields& fields,
-      const Context& context);
+      const FieldOrListContext& context);
   JS::Result<ParseNode*> parseInterfaceEagerFunctionDeclaration(
       const size_t start, const BinASTKind kind, const BinASTFields& fields,
-      const Context& context);
+      const FieldOrListContext& context);
   JS::Result<ParseNode*> parseInterfaceEagerFunctionExpression(
       const size_t start, const BinASTKind kind, const BinASTFields& fields,
-      const Context& context);
+      const FieldOrListContext& context);
   JS::Result<ParseNode*> parseInterfaceEagerGetter(const size_t start,
                                                    const BinASTKind kind,
                                                    const BinASTFields& fields,
                                                    const ListContext& context);
   JS::Result<ParseNode*> parseInterfaceEagerMethod(const size_t start,
                                                    const BinASTKind kind,
                                                    const BinASTFields& fields,
                                                    const ListContext& context);
   JS::Result<ParseNode*> parseInterfaceEagerSetter(const size_t start,
                                                    const BinASTKind kind,
                                                    const BinASTFields& fields,
                                                    const ListContext& context);
   JS::Result<ParseNode*> parseInterfaceEmptyStatement(
       const size_t start, const BinASTKind kind, const BinASTFields& fields,
-      const Context& context);
+      const FieldOrListContext& context);
   JS::Result<ParseNode*> parseInterfaceExpressionStatement(
       const size_t start, const BinASTKind kind, const BinASTFields& fields,
-      const Context& context);
+      const FieldOrListContext& context);
   JS::Result<ParseNode*> parseInterfaceForInOfBinding(
       const size_t start, const BinASTKind kind, const BinASTFields& fields,
       const FieldContext& context);
   JS::Result<ParseNode*> parseInterfaceForInStatement(
       const size_t start, const BinASTKind kind, const BinASTFields& fields,
-      const Context& context);
+      const FieldOrListContext& context);
   JS::Result<ParseNode*> parseInterfaceForOfStatement(
       const size_t start, const BinASTKind kind, const BinASTFields& fields,
-      const Context& context);
-  JS::Result<ParseNode*> parseInterfaceForStatement(const size_t start,
-                                                    const BinASTKind kind,
-                                                    const BinASTFields& fields,
-                                                    const Context& context);
+      const FieldOrListContext& context);
+  JS::Result<ParseNode*> parseInterfaceForStatement(
+      const size_t start, const BinASTKind kind, const BinASTFields& fields,
+      const FieldOrListContext& context);
   JS::Result<ListNode*> parseInterfaceFormalParameters(
       const size_t start, const BinASTKind kind, const BinASTFields& fields,
       const FieldContext& context);
   JS::Result<Ok> parseInterfaceFunctionExpressionContents(
       const size_t start, const BinASTKind kind, const BinASTFields& fields,
       uint32_t funLength, ListNode** paramsOut, ListNode** bodyOut,
-      const Context& context);
+      const FieldOrRootContext& context);
   JS::Result<Ok> parseInterfaceFunctionOrMethodContents(
       const size_t start, const BinASTKind kind, const BinASTFields& fields,
       uint32_t funLength, ListNode** paramsOut, ListNode** bodyOut,
-      const Context& context);
+      const FieldOrRootContext& context);
   JS::Result<Ok> parseInterfaceGetterContents(
       const size_t start, const BinASTKind kind, const BinASTFields& fields,
       uint32_t funLength, ListNode** paramsOut, ListNode** bodyOut,
       const FieldContext& context);
   JS::Result<ParseNode*> parseInterfaceIdentifierExpression(
       const size_t start, const BinASTKind kind, const BinASTFields& fields,
-      const Context& context);
-  JS::Result<ParseNode*> parseInterfaceIfStatement(const size_t start,
-                                                   const BinASTKind kind,
-                                                   const BinASTFields& fields,
-                                                   const Context& context);
+      const FieldOrListContext& context);
+  JS::Result<ParseNode*> parseInterfaceIfStatement(
+      const size_t start, const BinASTKind kind, const BinASTFields& fields,
+      const FieldOrListContext& context);
   JS::Result<ParseNode*> parseInterfaceLabelledStatement(
       const size_t start, const BinASTKind kind, const BinASTFields& fields,
-      const Context& context);
+      const FieldOrListContext& context);
   JS::Result<ParseNode*> parseInterfaceLazyArrowExpressionWithExpression(
       const size_t start, const BinASTKind kind, const BinASTFields& fields,
-      const Context& context);
+      const FieldOrListContext& context);
   JS::Result<ParseNode*> parseInterfaceLazyArrowExpressionWithFunctionBody(
       const size_t start, const BinASTKind kind, const BinASTFields& fields,
-      const Context& context);
+      const FieldOrListContext& context);
   JS::Result<ParseNode*> parseInterfaceLazyFunctionDeclaration(
       const size_t start, const BinASTKind kind, const BinASTFields& fields,
-      const Context& context);
+      const FieldOrListContext& context);
   JS::Result<ParseNode*> parseInterfaceLazyFunctionExpression(
       const size_t start, const BinASTKind kind, const BinASTFields& fields,
-      const Context& context);
+      const FieldOrListContext& context);
   JS::Result<ParseNode*> parseInterfaceLazyGetter(const size_t start,
                                                   const BinASTKind kind,
                                                   const BinASTFields& fields,
                                                   const ListContext& context);
   JS::Result<ParseNode*> parseInterfaceLazyMethod(const size_t start,
                                                   const BinASTKind kind,
                                                   const BinASTFields& fields,
                                                   const ListContext& context);
   JS::Result<ParseNode*> parseInterfaceLazySetter(const size_t start,
                                                   const BinASTKind kind,
                                                   const BinASTFields& fields,
                                                   const ListContext& context);
   JS::Result<ParseNode*> parseInterfaceLiteralBooleanExpression(
       const size_t start, const BinASTKind kind, const BinASTFields& fields,
-      const Context& context);
+      const FieldOrListContext& context);
   JS::Result<ParseNode*> parseInterfaceLiteralInfinityExpression(
       const size_t start, const BinASTKind kind, const BinASTFields& fields,
-      const Context& context);
+      const FieldOrListContext& context);
   JS::Result<ParseNode*> parseInterfaceLiteralNullExpression(
       const size_t start, const BinASTKind kind, const BinASTFields& fields,
-      const Context& context);
+      const FieldOrListContext& context);
   JS::Result<ParseNode*> parseInterfaceLiteralNumericExpression(
       const size_t start, const BinASTKind kind, const BinASTFields& fields,
-      const Context& context);
+      const FieldOrListContext& context);
   JS::Result<ParseNode*> parseInterfaceLiteralPropertyName(
       const size_t start, const BinASTKind kind, const BinASTFields& fields,
       const FieldContext& context);
   JS::Result<ParseNode*> parseInterfaceLiteralRegExpExpression(
       const size_t start, const BinASTKind kind, const BinASTFields& fields,
-      const Context& context);
+      const FieldOrListContext& context);
   JS::Result<ParseNode*> parseInterfaceLiteralStringExpression(
       const size_t start, const BinASTKind kind, const BinASTFields& fields,
-      const Context& context);
+      const FieldOrListContext& context);
   JS::Result<ParseNode*> parseInterfaceModule(const size_t start,
                                               const BinASTKind kind,
                                               const BinASTFields& fields,
                                               const RootContext& context);
-  JS::Result<ParseNode*> parseInterfaceNewExpression(const size_t start,
-                                                     const BinASTKind kind,
-                                                     const BinASTFields& fields,
-                                                     const Context& context);
+  JS::Result<ParseNode*> parseInterfaceNewExpression(
+      const size_t start, const BinASTKind kind, const BinASTFields& fields,
+      const FieldOrListContext& context);
   JS::Result<ParseNode*> parseInterfaceNewTargetExpression(
       const size_t start, const BinASTKind kind, const BinASTFields& fields,
-      const Context& context);
+      const FieldOrListContext& context);
   JS::Result<ParseNode*> parseInterfaceObjectAssignmentTarget(
       const size_t start, const BinASTKind kind, const BinASTFields& fields,
       const FieldContext& context);
-  JS::Result<ParseNode*> parseInterfaceObjectBinding(const size_t start,
-                                                     const BinASTKind kind,
-                                                     const BinASTFields& fields,
-                                                     const Context& context);
+  JS::Result<ParseNode*> parseInterfaceObjectBinding(
+      const size_t start, const BinASTKind kind, const BinASTFields& fields,
+      const FieldOrListContext& context);
   JS::Result<ParseNode*> parseInterfaceObjectExpression(
       const size_t start, const BinASTKind kind, const BinASTFields& fields,
-      const Context& context);
+      const FieldOrListContext& context);
   JS::Result<ParseNode*> parseInterfaceReturnStatement(
       const size_t start, const BinASTKind kind, const BinASTFields& fields,
-      const Context& context);
+      const FieldOrListContext& context);
   JS::Result<ParseNode*> parseInterfaceScript(const size_t start,
                                               const BinASTKind kind,
                                               const BinASTFields& fields,
                                               const RootContext& context);
   JS::Result<Ok> parseInterfaceSetterContents(
       const size_t start, const BinASTKind kind, const BinASTFields& fields,
       uint32_t funLength, ListNode** paramsOut, ListNode** bodyOut,
       const FieldContext& context);
@@ -500,74 +496,73 @@ class BinASTParser : public BinASTParser
   JS::Result<ParseNode*> parseInterfaceSpreadElement(
       const size_t start, const BinASTKind kind, const BinASTFields& fields,
       const ListContext& context);
   JS::Result<ParseNode*> parseInterfaceStaticMemberAssignmentTarget(
       const size_t start, const BinASTKind kind, const BinASTFields& fields,
       const FieldContext& context);
   JS::Result<ParseNode*> parseInterfaceStaticMemberExpression(
       const size_t start, const BinASTKind kind, const BinASTFields& fields,
-      const Context& context);
+      const FieldOrListContext& context);
   JS::Result<ParseNode*> parseInterfaceSuper(const size_t start,
                                              const BinASTKind kind,
                                              const BinASTFields& fields,
                                              const FieldContext& context);
   JS::Result<CaseClause*> parseInterfaceSwitchCase(const size_t start,
                                                    const BinASTKind kind,
                                                    const BinASTFields& fields,
                                                    const ListContext& context);
   JS::Result<ParseNode*> parseInterfaceSwitchDefault(
       const size_t start, const BinASTKind kind, const BinASTFields& fields,
       const FieldContext& context);
   JS::Result<ParseNode*> parseInterfaceSwitchStatement(
       const size_t start, const BinASTKind kind, const BinASTFields& fields,
-      const Context& context);
+      const FieldOrListContext& context);
   JS::Result<ParseNode*> parseInterfaceSwitchStatementWithDefault(
       const size_t start, const BinASTKind kind, const BinASTFields& fields,
-      const Context& context);
+      const FieldOrListContext& context);
   JS::Result<ParseNode*> parseInterfaceTemplateExpression(
       const size_t start, const BinASTKind kind, const BinASTFields& fields,
-      const Context& context);
+      const FieldOrListContext& context);
   JS::Result<ParseNode*> parseInterfaceThisExpression(
       const size_t start, const BinASTKind kind, const BinASTFields& fields,
-      const Context& context);
+      const FieldOrListContext& context);
   JS::Result<ParseNode*> parseInterfaceThrowStatement(
       const size_t start, const BinASTKind kind, const BinASTFields& fields,
-      const Context& context);
+      const FieldOrListContext& context);
   JS::Result<ParseNode*> parseInterfaceTryCatchStatement(
       const size_t start, const BinASTKind kind, const BinASTFields& fields,
-      const Context& context);
+      const FieldOrListContext& context);
   JS::Result<ParseNode*> parseInterfaceTryFinallyStatement(
       const size_t start, const BinASTKind kind, const BinASTFields& fields,
-      const Context& context);
+      const FieldOrListContext& context);
   JS::Result<ParseNode*> parseInterfaceUnaryExpression(
       const size_t start, const BinASTKind kind, const BinASTFields& fields,
-      const Context& context);
+      const FieldOrListContext& context);
   JS::Result<ParseNode*> parseInterfaceUpdateExpression(
       const size_t start, const BinASTKind kind, const BinASTFields& fields,
-      const Context& context);
+      const FieldOrListContext& context);
   JS::Result<ParseNode*> parseInterfaceVariableDeclaration(
       const size_t start, const BinASTKind kind, const BinASTFields& fields,
-      const Context& context);
+      const FieldOrListContext& context);
   JS::Result<ParseNode*> parseInterfaceVariableDeclarator(
       const size_t start, const BinASTKind kind, const BinASTFields& fields,
       const ListContext& context);
   JS::Result<ParseNode*> parseInterfaceWhileStatement(
       const size_t start, const BinASTKind kind, const BinASTFields& fields,
-      const Context& context);
-  JS::Result<ParseNode*> parseInterfaceWithStatement(const size_t start,
-                                                     const BinASTKind kind,
-                                                     const BinASTFields& fields,
-                                                     const Context& context);
+      const FieldOrListContext& context);
+  JS::Result<ParseNode*> parseInterfaceWithStatement(
+      const size_t start, const BinASTKind kind, const BinASTFields& fields,
+      const FieldOrListContext& context);
   JS::Result<ParseNode*> parseInterfaceYieldExpression(
       const size_t start, const BinASTKind kind, const BinASTFields& fields,
-      const Context& context);
+      const FieldOrListContext& context);
   JS::Result<ParseNode*> parseInterfaceYieldStarExpression(
       const size_t start, const BinASTKind kind, const BinASTFields& fields,
-      const Context& context);
+      const FieldOrListContext& context);
 
   // ----- String enums (by lexicographical order)
   JS::Result<typename BinASTParser<Tok>::AssertedDeclaredKind>
   parseAssertedDeclaredKind(const FieldContext& context);
   JS::Result<typename BinASTParser<Tok>::BinaryOperator> parseBinaryOperator(
       const FieldContext& context);
   JS::Result<typename BinASTParser<Tok>::CompoundAssignmentOperator>
   parseCompoundAssignmentOperator(const FieldContext& context);
--- a/js/src/frontend/BinASTParserPerTokenizer.cpp
+++ b/js/src/frontend/BinASTParserPerTokenizer.cpp
@@ -192,17 +192,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 auto context = Context(RootContext());
+  const auto context = FieldOrRootContext(RootContext());
   MOZ_TRY(
       (asFinalParser()->*parseFunc)(func->nargs(), &params, &tmpBody, context));
 
   uint32_t nargs = params->count();
 
   BINJS_TRY_DECL(lexicalScopeData,
                  NewLexicalScopeData(cx_, lexicalScope, alloc_, pc_));
   BINJS_TRY_DECL(body, handler_.newLexicalScope(*lexicalScopeData, tmpBody));
--- a/js/src/frontend/BinASTParserPerTokenizer.h
+++ b/js/src/frontend/BinASTParserPerTokenizer.h
@@ -53,17 +53,17 @@ class BinASTParserPerTokenizer : public 
  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;
+  using FieldOrRootContext = BinASTTokenReaderBase::FieldOrRootContext;
 
  public:
   // Auto-generated types.
   using AssertedDeclaredKind = binast::AssertedDeclaredKind;
   using VariableDeclarationKind = binast::VariableDeclarationKind;
 
  public:
   BinASTParserPerTokenizer(JSContext* cx, ParseInfo& parseInfo,
--- a/js/src/frontend/BinASTTokenReaderBase.h
+++ b/js/src/frontend/BinASTTokenReaderBase.h
@@ -47,26 +47,33 @@ class MOZ_STACK_CLASS BinASTTokenReaderB
   // Reading a field from an interface.
   struct FieldContext {
     const BinASTInterfaceAndField position;
     explicit FieldContext(const BinASTInterfaceAndField position)
         : position(position) {}
   };
 
   // The context in which we read a token.
-  using Context = mozilla::Variant<RootContext, ListContext, FieldContext>;
+  using FieldOrRootContext = mozilla::Variant<FieldContext, RootContext>;
+  using FieldOrListContext = mozilla::Variant<FieldContext, ListContext>;
 
 #ifdef DEBUG
   // Utility matcher, used to print a `Context` during debugging.
   struct ContextPrinter {
-    static void print(const char* text, const Context& context) {
+    static void print(const char* text, const FieldOrRootContext& context) {
       fprintf(stderr, "%s ", text);
       context.match(ContextPrinter());
       fprintf(stderr, "\n");
     }
+    static void print(const char* text, const FieldOrListContext& context) {
+      fprintf(stderr, "%s ", text);
+      context.match(ContextPrinter());
+      fprintf(stderr, "\n");
+    }
+
     void operator()(const RootContext&) { fprintf(stderr, "<Root context>"); }
     void operator()(const ListContext& context) {
       fprintf(stderr, "<List context>: %s => %s",
               describeBinASTInterfaceAndField(context.position),
               describeBinASTList(context.content));
     }
     void operator()(const FieldContext& context) {
       fprintf(stderr, "<Field context>: %s",
--- a/js/src/frontend/BinASTTokenReaderContext.cpp
+++ b/js/src/frontend/BinASTTokenReaderContext.cpp
@@ -1520,34 +1520,46 @@ JS::Result<uint32_t> BinASTTokenReaderCo
 
 JS::Result<BinASTTokenReaderBase::SkippableSubTree>
 BinASTTokenReaderContext::readSkippableSubTree(const FieldContext&) {
   return raiseError("Not Yet Implemented");
 }
 
 JS::Result<Ok> BinASTTokenReaderContext::enterTaggedTuple(
     BinASTKind& tag, BinASTTokenReaderContext::BinASTFields&,
-    const Context& context, AutoTaggedTuple& guard) {
+    const FieldOrRootContext& context, AutoTaggedTuple& guard) {
   return context.match(
+      [this, &tag](const BinASTTokenReaderBase::FieldContext& asFieldContext)
+          -> JS::Result<Ok> {
+        // This tuple is the value of the field we're currently reading.
+        MOZ_TRY_VAR(tag, readTagFromTable(asFieldContext.position));
+        return Ok();
+      },
       [&tag](const BinASTTokenReaderBase::RootContext&) -> JS::Result<Ok> {
         // For the moment, the format hardcodes `Script` as root.
         tag = BinASTKind::Script;
         return Ok();
+      });
+}
+
+JS::Result<Ok> BinASTTokenReaderContext::enterTaggedTuple(
+    BinASTKind& tag, BinASTTokenReaderContext::BinASTFields&,
+    const FieldOrListContext& context, AutoTaggedTuple& guard) {
+  return context.match(
+      [this, &tag](const BinASTTokenReaderBase::FieldContext& asFieldContext)
+          -> JS::Result<Ok> {
+        // This tuple is the value of the field we're currently reading.
+        MOZ_TRY_VAR(tag, readTagFromTable(asFieldContext.position));
+        return Ok();
       },
       [this, &tag](const BinASTTokenReaderBase::ListContext& asListContext)
           -> JS::Result<Ok> {
         // This tuple is an element in a list we're currently reading.
         MOZ_TRY_VAR(tag, readTagFromTable(asListContext.position));
         return Ok();
-      },
-      [this, &tag](const BinASTTokenReaderBase::FieldContext& asFieldContext)
-          -> JS::Result<Ok> {
-        // This tuple is the value of the field we're currently reading.
-        MOZ_TRY_VAR(tag, readTagFromTable(asFieldContext.position));
-        return Ok();
       });
 }
 
 JS::Result<Ok> BinASTTokenReaderContext::enterTaggedTuple(
     BinASTKind& tag, BinASTTokenReaderContext::BinASTFields&,
     const RootContext& context, AutoTaggedTuple& guard) {
   // For the moment, the format hardcodes `Script` as root.
   tag = BinASTKind::Script;
--- a/js/src/frontend/BinASTTokenReaderContext.h
+++ b/js/src/frontend/BinASTTokenReaderContext.h
@@ -956,20 +956,21 @@ class HuffmanDictionary {
 class MOZ_STACK_CLASS BinASTTokenReaderContext : public BinASTTokenReaderBase {
   using Base = BinASTTokenReaderBase;
 
  public:
   class AutoList;
   class AutoTaggedTuple;
 
   using CharSlice = BinaryASTSupport::CharSlice;
-  using Context = BinASTTokenReaderBase::Context;
   using RootContext = BinASTTokenReaderBase::RootContext;
   using ListContext = BinASTTokenReaderBase::ListContext;
   using FieldContext = BinASTTokenReaderBase::FieldContext;
+  using FieldOrRootContext = BinASTTokenReaderBase::FieldOrRootContext;
+  using FieldOrListContext = BinASTTokenReaderBase::FieldOrListContext;
 
   // This implementation of `BinASTFields` is effectively `void`, as the format
   // does not embed field information.
   class BinASTFields {
    public:
     explicit BinASTFields(JSContext*) {}
   };
   using Chars = CharSlice;
@@ -1197,17 +1198,20 @@ class MOZ_STACK_CLASS BinASTTokenReaderC
    * destroyed at the point where the caller has reached the end of the tuple.
    * If the caller has consumed too few/too many bytes, this will be reported
    * in the call go `guard.done()`.
    *
    * @return out If the header of the tuple is invalid.
    */
   MOZ_MUST_USE JS::Result<Ok> enterTaggedTuple(
       BinASTKind& tag, BinASTTokenReaderContext::BinASTFields& fields,
-      const Context&, AutoTaggedTuple& guard);
+      const FieldOrRootContext&, AutoTaggedTuple& guard);
+  MOZ_MUST_USE JS::Result<Ok> enterTaggedTuple(
+      BinASTKind& tag, BinASTTokenReaderContext::BinASTFields& fields,
+      const FieldOrListContext&, AutoTaggedTuple& guard);
   MOZ_MUST_USE JS::Result<Ok> enterTaggedTuple(
       BinASTKind& tag, BinASTTokenReaderContext::BinASTFields& fields,
       const RootContext&, AutoTaggedTuple& guard);
   MOZ_MUST_USE JS::Result<Ok> enterTaggedTuple(
       BinASTKind& tag, BinASTTokenReaderContext::BinASTFields& fields,
       const ListContext&, AutoTaggedTuple& guard);
   MOZ_MUST_USE JS::Result<Ok> enterTaggedTuple(
       BinASTKind& tag, BinASTTokenReaderContext::BinASTFields& fields,
--- a/js/src/frontend/BinASTTokenReaderMultipart.cpp
+++ b/js/src/frontend/BinASTTokenReaderMultipart.cpp
@@ -371,46 +371,29 @@ BinASTTokenReaderMultipart::readSkippabl
 
   return BinASTTokenReaderBase::SkippableSubTree(start, byteLen);
 }
 
 // Tagged tuples:
 // - uint32_t index in table [grammar];
 // - content (specified by the higher-level grammar);
 JS::Result<Ok> BinASTTokenReaderMultipart::enterTaggedTuple(
-    BinASTKind& tag, BinASTTokenReaderMultipart::BinASTFields&, const Context&,
-    AutoTaggedTuple& guard) {
+    BinASTKind& tag, AutoTaggedTuple& guard) {
   BINJS_MOZ_TRY_DECL(index, readInternalUint32());
   if (index >= metadata_->numBinASTKinds()) {
     return raiseError("Invalid index to grammar table");
   }
 
   tag = metadata_->getBinASTKind(index);
 
   // Enter the body.
   guard.init();
   return Ok();
 }
 
-JS::Result<Ok> BinASTTokenReaderMultipart::enterTaggedTuple(
-    BinASTKind& tag, BinASTTokenReaderMultipart::BinASTFields& fields,
-    const RootContext& context, AutoTaggedTuple& guard) {
-  return enterTaggedTuple(tag, fields, Context(context), guard);
-}
-JS::Result<Ok> BinASTTokenReaderMultipart::enterTaggedTuple(
-    BinASTKind& tag, BinASTTokenReaderMultipart::BinASTFields& fields,
-    const ListContext& context, AutoTaggedTuple& guard) {
-  return enterTaggedTuple(tag, fields, Context(context), guard);
-}
-JS::Result<Ok> BinASTTokenReaderMultipart::enterTaggedTuple(
-    BinASTKind& tag, BinASTTokenReaderMultipart::BinASTFields& fields,
-    const FieldContext& context, AutoTaggedTuple& guard) {
-  return enterTaggedTuple(tag, fields, Context(context), guard);
-}
-
 // List:
 //
 // - uint32_t number of items;
 // - contents (specified by higher-level grammar);
 //
 // The total byte length of `number of items` + `contents` must be `byte
 // length`.
 JS::Result<Ok> BinASTTokenReaderMultipart::enterList(uint32_t& items,
--- a/js/src/frontend/BinASTTokenReaderMultipart.h
+++ b/js/src/frontend/BinASTTokenReaderMultipart.h
@@ -32,20 +32,21 @@ namespace frontend {
  */
 class MOZ_STACK_CLASS BinASTTokenReaderMultipart
     : public BinASTTokenReaderBase {
  public:
   class AutoList;
   class AutoTaggedTuple;
 
   using CharSlice = BinaryASTSupport::CharSlice;
-  using Context = BinASTTokenReaderBase::Context;
   using RootContext = BinASTTokenReaderBase::RootContext;
   using ListContext = BinASTTokenReaderBase::ListContext;
   using FieldContext = BinASTTokenReaderBase::FieldContext;
+  using FieldOrRootContext = BinASTTokenReaderBase::FieldOrRootContext;
+  using FieldOrListContext = BinASTTokenReaderBase::FieldOrListContext;
 
   // This implementation of `BinASTFields` is effectively `void`, as the format
   // does not embed field information.
   class BinASTFields {
    public:
     explicit BinASTFields(JSContext*) {}
   };
   using Chars = CharSlice;
@@ -180,28 +181,44 @@ class MOZ_STACK_CLASS BinASTTokenReaderM
    * The `guard` is dedicated to ensuring that reading the list has consumed
    * exactly all the bytes from that tuple. The `guard` MUST therefore be
    * destroyed at the point where the caller has reached the end of the tuple.
    * If the caller has consumed too few/too many bytes, this will be reported
    * in the call go `guard.done()`.
    *
    * @return out If the header of the tuple is invalid.
    */
+  MOZ_MUST_USE JS::Result<Ok> enterTaggedTuple(BinASTKind& tag,
+                                               AutoTaggedTuple& guard);
+
   MOZ_MUST_USE JS::Result<Ok> enterTaggedTuple(
       BinASTKind& tag, BinASTTokenReaderMultipart::BinASTFields& fields,
-      const Context&, AutoTaggedTuple& guard);
+      const FieldOrRootContext&, AutoTaggedTuple& guard) {
+    return enterTaggedTuple(tag, guard);
+  }
   MOZ_MUST_USE JS::Result<Ok> enterTaggedTuple(
       BinASTKind& tag, BinASTTokenReaderMultipart::BinASTFields& fields,
-      const RootContext&, AutoTaggedTuple& guard);
+      const FieldOrListContext&, AutoTaggedTuple& guard) {
+    return enterTaggedTuple(tag, guard);
+  }
   MOZ_MUST_USE JS::Result<Ok> enterTaggedTuple(
       BinASTKind& tag, BinASTTokenReaderMultipart::BinASTFields& fields,
-      const ListContext&, AutoTaggedTuple& guard);
+      const RootContext&, AutoTaggedTuple& guard) {
+    return enterTaggedTuple(tag, guard);
+  }
   MOZ_MUST_USE JS::Result<Ok> enterTaggedTuple(
       BinASTKind& tag, BinASTTokenReaderMultipart::BinASTFields& fields,
-      const FieldContext&, AutoTaggedTuple& guard);
+      const ListContext&, AutoTaggedTuple& guard) {
+    return enterTaggedTuple(tag, guard);
+  }
+  MOZ_MUST_USE JS::Result<Ok> enterTaggedTuple(
+      BinASTKind& tag, BinASTTokenReaderMultipart::BinASTFields& fields,
+      const FieldContext&, AutoTaggedTuple& guard) {
+    return enterTaggedTuple(tag, guard);
+  }
 
   /**
    * Read a single unsigned long.
    */
   MOZ_MUST_USE JS::Result<uint32_t> readUnsignedLong(const FieldContext&) {
     return readInternalUint32();
   }
 
--- a/js/src/frontend/binast/src/main.rs
+++ b/js/src/frontend/binast/src/main.rs
@@ -1112,20 +1112,20 @@ impl CPPExporter {
         }
         if context.is_list() {
             return "const ListContext& context".to_string();
         }
         if context.is_field() {
             return "const FieldContext& context".to_string();
         }
         if context.is_field_and_list() {
-            return "const Context& context".to_string();
+            return "const FieldOrListContext& context".to_string();
         }
         if context.is_field_and_root() {
-            return "const Context& context".to_string();
+            return "const FieldOrRootContext& context".to_string();
         }
 
         panic!("unexpected context");
     }
 
     fn get_method_signature(&self, name: &NodeName, prefix: &str, args: &str,
                             extra_params: &Option<Rc<String>>) -> String {
         let type_ok = self.get_type_ok(name);
@@ -1212,17 +1212,21 @@ impl CPPExporter {
 
         if sum_context == arm_context {
             return context.to_string();
         }
 
         assert!(sum_context.is_single());
         assert!(arm_context.is_valid_double());
 
-        return format!("Context({})", context);
+        if arm_context.is_field_and_root() {
+            return format!("FieldOrRootContext({})", context);
+        }
+
+        return format!("FieldOrListContext({})", context);
     }
 
     fn get_context_param_for_optional(&self, optional: &NodeName,
                                       body_prefix: &str, body: &NodeName,
                                       context: &str) -> String {
         let optional_name = optional.to_string().clone();
         let body_name = format!("{}{}", body_prefix, body);
 
@@ -1237,17 +1241,21 @@ impl CPPExporter {
 
         if optional_context == body_context {
             return context.to_string();
         }
 
         assert!(optional_context.is_single());
         assert!(body_context.is_valid_double());
 
-        return format!("Context({})", context);
+        if body_context.is_field_and_root() {
+            return format!("FieldOrRootContext({})", context);
+        }
+
+        return format!("FieldOrListContext({})", context);
     }
 
     fn get_context_param_for_list(&self, element: &NodeName,
                                   context: &str) -> String {
         let element_name = element.to_string().clone();
 
         let element_context = match self.context_map.get(&element_name) {
             Some(context) => context.clone(),
@@ -1255,17 +1263,17 @@ impl CPPExporter {
         };
 
         if element_context.is_list() {
             return context.to_string();
         }
 
         assert!(element_context.is_field_and_list());
 
-        return format!("Context({})", context);
+        return format!("FieldOrListContext({})", context);
     }
 
     fn get_context_param_for_field(&self, field: &NodeName,
                                   context: &str) -> String {
         let field_name = field.to_string().clone();
 
         let field_context = match self.context_map.get(&field_name) {
             Some(context) => context.clone(),
@@ -1273,17 +1281,21 @@ impl CPPExporter {
         };
 
         if field_context.is_field() {
             return context.to_string();
         }
 
         assert!(field_context.is_valid_double());
 
-        return format!("Context({})", context);
+        if field_context.is_field_and_root() {
+            return format!("FieldOrRootContext({})", context);
+        }
+
+        return format!("FieldOrListContext({})", context);
     }
 
     fn get_method_call(&self, var_name: &str, name: &NodeName,
                        prefix: &str, args: &str,
                        extra_params: &Option<Rc<String>>,
                        context_name: String,
                        call_kind: MethodCallKind) -> String {
         let type_ok_is_ok = match call_kind {