Bug 1508063 - Part 4: Rename BinSource-auto.{cpp,h} to BinASTParser.{cpp,h}, and BinSource.{cpp,h} to BinASTParserPerTokenizer.{cpp,h}. r=Yoric
authorTooru Fujisawa <arai_a@mac.com>
Thu, 29 Nov 2018 01:03:45 +0900
changeset 507730 02386132c1e9bfa3ef88b9ae7d967f90b6e1045e
parent 507729 f96f280927ff0bc9340a7726d28851f884998126
child 507731 44cd6ec4fbd5da73777883f4faf9fe822f7de513
push id1905
push userffxbld-merge
push dateMon, 21 Jan 2019 12:33:13 +0000
treeherdermozilla-release@c2fca1944d8c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersYoric
bugs1508063
milestone65.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1508063 - Part 4: Rename BinSource-auto.{cpp,h} to BinASTParser.{cpp,h}, and BinSource.{cpp,h} to BinASTParserPerTokenizer.{cpp,h}. r=Yoric
config/check_spidermonkey_style.py
js/src/frontend/BinASTParser.cpp
js/src/frontend/BinASTParser.h
js/src/frontend/BinASTParserPerTokenizer.cpp
js/src/frontend/BinASTParserPerTokenizer.h
js/src/frontend/BinSource-auto.cpp
js/src/frontend/BinSource-auto.h
js/src/frontend/BinSource.cpp
js/src/frontend/BinSource.h
js/src/frontend/BinSource.yaml
js/src/frontend/BinToken.h
js/src/frontend/BytecodeCompiler.cpp
js/src/frontend/BytecodeCompiler.h
js/src/frontend/FullParseHandler.h
js/src/frontend/binsource/build.sh
js/src/frontend/moz.build
js/src/fuzz-tests/testBinASTReader.cpp
js/src/jsapi-tests/testBinASTReader.cpp
js/src/shell/js.cpp
--- a/config/check_spidermonkey_style.py
+++ b/config/check_spidermonkey_style.py
@@ -108,17 +108,17 @@ included_inclnames_to_ignore = set([
     'unicode/uversion.h',       # ICU
     'vtune/VTuneWrapper.h'      # VTune
 ])
 
 # These files have additional constraints on where they are #included, so we
 # ignore #includes of them when checking #include ordering.
 oddly_ordered_inclnames = set([
     'ctypes/typedefs.h',        # Included multiple times in the body of ctypes/CTypes.h
-    'frontend/BinSource-auto.h',  # Included in the body of frontend/BinSource.h
+    'frontend/BinASTParser.h',  # Included in the body of frontend/BinSource.h
     # Included in the body of frontend/TokenStream.h
     'frontend/ReservedWordsGenerated.h',
     'gc/StatsPhasesGenerated.h',         # Included in the body of gc/Statistics.h
     'gc/StatsPhasesGenerated.cpp',       # Included in the body of gc/Statistics.cpp
     'psapi.h',                  # Must be included after "util/Windows.h" on Windows
     'machine/endian.h',         # Must be included after <sys/types.h> on BSD
     'winbase.h',                # Must precede other system headers(?)
     'windef.h'                  # Must precede other system headers(?)
new file mode 100644
--- /dev/null
+++ b/js/src/frontend/BinASTParser.cpp
@@ -0,0 +1,4743 @@
+// This file was autogenerated by binjs_generate_spidermonkey,
+// please DO NOT EDIT BY HAND.
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+* vim: set ts=8 sts=4 et sw=4 tw=99:
+* This Source Code Form is subject to the terms of the Mozilla Public
+* License, v. 2.0. If a copy of the MPL was not distributed with this
+* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// To generate this file, see the documentation in
+// js/src/frontend/binsource/README.md.
+
+#include "mozilla/ArrayUtils.h"
+#include "mozilla/Casting.h"
+#include "mozilla/Maybe.h"
+#include "mozilla/Move.h"
+#include "mozilla/PodOperations.h"
+#include "mozilla/Vector.h"
+
+#include "frontend/BinASTParserPerTokenizer.h"
+#include "frontend/BinSource-macros.h"
+#include "frontend/BinTokenReaderTester.h"
+#include "frontend/FullParseHandler.h"
+#include "frontend/ParseNode.h"
+#include "frontend/Parser.h"
+#include "frontend/SharedContext.h"
+
+#include "vm/RegExpObject.h"
+
+#include "frontend/ParseContext-inl.h"
+
+namespace js {
+namespace frontend {
+
+// Compare a bunch of `uint8_t` values (as returned by the tokenizer_) with
+// a string literal (and ONLY a string literal).
+template<typename Tok, size_t N>
+bool operator==(const typename Tok::Chars& left, const char (&right)[N]) {
+    return Tok::equals(left, right);
+}
+
+
+// ----- Sums of interfaces (autogenerated, by lexicographical order)
+// Sums of sums are flattened.
+/*
+AssertedMaybePositionalParameterName ::= AssertedParameterName
+    AssertedPositionalParameterName
+    AssertedRestParameterName
+*/
+template<typename Tok> JS::Result<Ok>
+BinASTParser<Tok>::parseAssertedMaybePositionalParameterName(
+        AssertedScopeKind scopeKind,
+        MutableHandle<GCVector<JSAtom*>> positionalParams)
+{
+    BinKind kind;
+    BinFields fields(cx_);
+    AutoTaggedTuple guard(*tokenizer_);
+    const auto start = tokenizer_->offset();
+
+    MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+
+    BINJS_MOZ_TRY_DECL(result, parseSumAssertedMaybePositionalParameterName(start, kind, fields,
+        scopeKind, positionalParams));
+
+    MOZ_TRY(guard.done());
+    return result;
+}
+
+template<typename Tok> JS::Result<Ok>
+BinASTParser<Tok>::parseSumAssertedMaybePositionalParameterName(const size_t start, const BinKind kind, const BinFields& fields,
+        AssertedScopeKind scopeKind,
+        MutableHandle<GCVector<JSAtom*>> positionalParams)
+{
+    Ok result;
+    switch (kind) {
+      case BinKind::AssertedParameterName:
+        return raiseError("FIXME: Not implemented yet in this preview release (AssertedParameterName)");
+      case BinKind::AssertedPositionalParameterName:
+        MOZ_TRY_VAR(result, parseInterfaceAssertedPositionalParameterName(start, kind, fields,
+            scopeKind, positionalParams));
+        break;
+      case BinKind::AssertedRestParameterName:
+        return raiseError("FIXME: Not implemented yet in this preview release (AssertedRestParameterName)");
+      default:
+        return raiseInvalidKind("AssertedMaybePositionalParameterName", kind);
+    }
+    return result;
+}
+
+/*
+AssignmentTarget ::= ArrayAssignmentTarget
+    AssignmentTargetIdentifier
+    ComputedMemberAssignmentTarget
+    ObjectAssignmentTarget
+    StaticMemberAssignmentTarget
+*/
+template<typename Tok> JS::Result<ParseNode*>
+BinASTParser<Tok>::parseAssignmentTarget()
+{
+    BinKind kind;
+    BinFields fields(cx_);
+    AutoTaggedTuple guard(*tokenizer_);
+    const auto start = tokenizer_->offset();
+
+    MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+
+    BINJS_MOZ_TRY_DECL(result, parseSumAssignmentTarget(start, kind, fields));
+
+    MOZ_TRY(guard.done());
+    return result;
+}
+
+template<typename Tok> JS::Result<ParseNode*>
+BinASTParser<Tok>::parseSumAssignmentTarget(const size_t start, const BinKind kind, const BinFields& fields)
+{
+    ParseNode* result;
+    switch (kind) {
+      case BinKind::ArrayAssignmentTarget:
+        MOZ_TRY_VAR(result, parseInterfaceArrayAssignmentTarget(start, kind, fields));
+        break;
+      case BinKind::AssignmentTargetIdentifier:
+        MOZ_TRY_VAR(result, parseInterfaceAssignmentTargetIdentifier(start, kind, fields));
+        break;
+      case BinKind::ComputedMemberAssignmentTarget:
+        MOZ_TRY_VAR(result, parseInterfaceComputedMemberAssignmentTarget(start, kind, fields));
+        break;
+      case BinKind::ObjectAssignmentTarget:
+        MOZ_TRY_VAR(result, parseInterfaceObjectAssignmentTarget(start, kind, fields));
+        break;
+      case BinKind::StaticMemberAssignmentTarget:
+        MOZ_TRY_VAR(result, parseInterfaceStaticMemberAssignmentTarget(start, kind, fields));
+        break;
+      default:
+        return raiseInvalidKind("AssignmentTarget", kind);
+    }
+    return result;
+}
+
+/*
+Binding ::= ArrayBinding
+    BindingIdentifier
+    ObjectBinding
+*/
+template<typename Tok> JS::Result<ParseNode*>
+BinASTParser<Tok>::parseBinding()
+{
+    BinKind kind;
+    BinFields fields(cx_);
+    AutoTaggedTuple guard(*tokenizer_);
+    const auto start = tokenizer_->offset();
+
+    MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+
+    BINJS_MOZ_TRY_DECL(result, parseSumBinding(start, kind, fields));
+
+    MOZ_TRY(guard.done());
+    return result;
+}
+
+template<typename Tok> JS::Result<ParseNode*>
+BinASTParser<Tok>::parseSumBinding(const size_t start, const BinKind kind, const BinFields& fields)
+{
+    ParseNode* result;
+    switch (kind) {
+      case BinKind::ArrayBinding:
+        MOZ_TRY_VAR(result, parseInterfaceArrayBinding(start, kind, fields));
+        break;
+      case BinKind::BindingIdentifier:
+        MOZ_TRY_VAR(result, parseInterfaceBindingIdentifier(start, kind, fields));
+        break;
+      case BinKind::ObjectBinding:
+        MOZ_TRY_VAR(result, parseInterfaceObjectBinding(start, kind, fields));
+        break;
+      default:
+        return raiseInvalidKind("Binding", kind);
+    }
+    return result;
+}
+
+/*
+Expression ::= ArrayExpression
+    AssignmentExpression
+    AwaitExpression
+    BinaryExpression
+    CallExpression
+    ClassExpression
+    CompoundAssignmentExpression
+    ComputedMemberExpression
+    ConditionalExpression
+    EagerArrowExpressionWithExpression
+    EagerArrowExpressionWithFunctionBody
+    EagerFunctionExpression
+    IdentifierExpression
+    LazyArrowExpressionWithExpression
+    LazyArrowExpressionWithFunctionBody
+    LazyFunctionExpression
+    LiteralBooleanExpression
+    LiteralInfinityExpression
+    LiteralNullExpression
+    LiteralNumericExpression
+    LiteralRegExpExpression
+    LiteralStringExpression
+    NewExpression
+    NewTargetExpression
+    ObjectExpression
+    StaticMemberExpression
+    TemplateExpression
+    ThisExpression
+    UnaryExpression
+    UpdateExpression
+    YieldExpression
+    YieldStarExpression
+*/
+template<typename Tok> JS::Result<ParseNode*>
+BinASTParser<Tok>::parseExpression()
+{
+    BinKind kind;
+    BinFields fields(cx_);
+    AutoTaggedTuple guard(*tokenizer_);
+    const auto start = tokenizer_->offset();
+
+    MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+
+    BINJS_MOZ_TRY_DECL(result, parseSumExpression(start, kind, fields));
+
+    MOZ_TRY(guard.done());
+    return result;
+}
+
+template<typename Tok> JS::Result<ParseNode*>
+BinASTParser<Tok>::parseSumExpression(const size_t start, const BinKind kind, const BinFields& fields)
+{
+    ParseNode* result;
+    switch (kind) {
+      case BinKind::ArrayExpression:
+        MOZ_TRY_VAR(result, parseInterfaceArrayExpression(start, kind, fields));
+        break;
+      case BinKind::AssignmentExpression:
+        MOZ_TRY_VAR(result, parseInterfaceAssignmentExpression(start, kind, fields));
+        break;
+      case BinKind::AwaitExpression:
+        MOZ_TRY_VAR(result, parseInterfaceAwaitExpression(start, kind, fields));
+        break;
+      case BinKind::BinaryExpression:
+        MOZ_TRY_VAR(result, parseInterfaceBinaryExpression(start, kind, fields));
+        break;
+      case BinKind::CallExpression:
+        MOZ_TRY_VAR(result, parseInterfaceCallExpression(start, kind, fields));
+        break;
+      case BinKind::ClassExpression:
+        MOZ_TRY_VAR(result, parseInterfaceClassExpression(start, kind, fields));
+        break;
+      case BinKind::CompoundAssignmentExpression:
+        MOZ_TRY_VAR(result, parseInterfaceCompoundAssignmentExpression(start, kind, fields));
+        break;
+      case BinKind::ComputedMemberExpression:
+        MOZ_TRY_VAR(result, parseInterfaceComputedMemberExpression(start, kind, fields));
+        break;
+      case BinKind::ConditionalExpression:
+        MOZ_TRY_VAR(result, parseInterfaceConditionalExpression(start, kind, fields));
+        break;
+      case BinKind::EagerArrowExpressionWithExpression:
+        MOZ_TRY_VAR(result, parseInterfaceEagerArrowExpressionWithExpression(start, kind, fields));
+        break;
+      case BinKind::EagerArrowExpressionWithFunctionBody:
+        MOZ_TRY_VAR(result, parseInterfaceEagerArrowExpressionWithFunctionBody(start, kind, fields));
+        break;
+      case BinKind::EagerFunctionExpression:
+        MOZ_TRY_VAR(result, parseInterfaceEagerFunctionExpression(start, kind, fields));
+        break;
+      case BinKind::IdentifierExpression:
+        MOZ_TRY_VAR(result, parseInterfaceIdentifierExpression(start, kind, fields));
+        break;
+      case BinKind::LazyArrowExpressionWithExpression:
+        MOZ_TRY_VAR(result, parseInterfaceLazyArrowExpressionWithExpression(start, kind, fields));
+        break;
+      case BinKind::LazyArrowExpressionWithFunctionBody:
+        MOZ_TRY_VAR(result, parseInterfaceLazyArrowExpressionWithFunctionBody(start, kind, fields));
+        break;
+      case BinKind::LazyFunctionExpression:
+        MOZ_TRY_VAR(result, parseInterfaceLazyFunctionExpression(start, kind, fields));
+        break;
+      case BinKind::LiteralBooleanExpression:
+        MOZ_TRY_VAR(result, parseInterfaceLiteralBooleanExpression(start, kind, fields));
+        break;
+      case BinKind::LiteralInfinityExpression:
+        MOZ_TRY_VAR(result, parseInterfaceLiteralInfinityExpression(start, kind, fields));
+        break;
+      case BinKind::LiteralNullExpression:
+        MOZ_TRY_VAR(result, parseInterfaceLiteralNullExpression(start, kind, fields));
+        break;
+      case BinKind::LiteralNumericExpression:
+        MOZ_TRY_VAR(result, parseInterfaceLiteralNumericExpression(start, kind, fields));
+        break;
+      case BinKind::LiteralRegExpExpression:
+        MOZ_TRY_VAR(result, parseInterfaceLiteralRegExpExpression(start, kind, fields));
+        break;
+      case BinKind::LiteralStringExpression:
+        MOZ_TRY_VAR(result, parseInterfaceLiteralStringExpression(start, kind, fields));
+        break;
+      case BinKind::NewExpression:
+        MOZ_TRY_VAR(result, parseInterfaceNewExpression(start, kind, fields));
+        break;
+      case BinKind::NewTargetExpression:
+        MOZ_TRY_VAR(result, parseInterfaceNewTargetExpression(start, kind, fields));
+        break;
+      case BinKind::ObjectExpression:
+        MOZ_TRY_VAR(result, parseInterfaceObjectExpression(start, kind, fields));
+        break;
+      case BinKind::StaticMemberExpression:
+        MOZ_TRY_VAR(result, parseInterfaceStaticMemberExpression(start, kind, fields));
+        break;
+      case BinKind::TemplateExpression:
+        MOZ_TRY_VAR(result, parseInterfaceTemplateExpression(start, kind, fields));
+        break;
+      case BinKind::ThisExpression:
+        MOZ_TRY_VAR(result, parseInterfaceThisExpression(start, kind, fields));
+        break;
+      case BinKind::UnaryExpression:
+        MOZ_TRY_VAR(result, parseInterfaceUnaryExpression(start, kind, fields));
+        break;
+      case BinKind::UpdateExpression:
+        MOZ_TRY_VAR(result, parseInterfaceUpdateExpression(start, kind, fields));
+        break;
+      case BinKind::YieldExpression:
+        MOZ_TRY_VAR(result, parseInterfaceYieldExpression(start, kind, fields));
+        break;
+      case BinKind::YieldStarExpression:
+        MOZ_TRY_VAR(result, parseInterfaceYieldStarExpression(start, kind, fields));
+        break;
+      default:
+        return raiseInvalidKind("Expression", kind);
+    }
+    return result;
+}
+
+/*
+ExpressionOrSuper ::= ArrayExpression
+    AssignmentExpression
+    AwaitExpression
+    BinaryExpression
+    CallExpression
+    ClassExpression
+    CompoundAssignmentExpression
+    ComputedMemberExpression
+    ConditionalExpression
+    EagerArrowExpressionWithExpression
+    EagerArrowExpressionWithFunctionBody
+    EagerFunctionExpression
+    IdentifierExpression
+    LazyArrowExpressionWithExpression
+    LazyArrowExpressionWithFunctionBody
+    LazyFunctionExpression
+    LiteralBooleanExpression
+    LiteralInfinityExpression
+    LiteralNullExpression
+    LiteralNumericExpression
+    LiteralRegExpExpression
+    LiteralStringExpression
+    NewExpression
+    NewTargetExpression
+    ObjectExpression
+    StaticMemberExpression
+    Super
+    TemplateExpression
+    ThisExpression
+    UnaryExpression
+    UpdateExpression
+    YieldExpression
+    YieldStarExpression
+*/
+template<typename Tok> JS::Result<ParseNode*>
+BinASTParser<Tok>::parseExpressionOrSuper()
+{
+    BinKind kind;
+    BinFields fields(cx_);
+    AutoTaggedTuple guard(*tokenizer_);
+    const auto start = tokenizer_->offset();
+
+    MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+
+    BINJS_MOZ_TRY_DECL(result, parseSumExpressionOrSuper(start, kind, fields));
+
+    MOZ_TRY(guard.done());
+    return result;
+}
+
+template<typename Tok> JS::Result<ParseNode*>
+BinASTParser<Tok>::parseSumExpressionOrSuper(const size_t start, const BinKind kind, const BinFields& fields)
+{
+    ParseNode* result;
+    switch (kind) {
+      case BinKind::ArrayExpression:
+        MOZ_TRY_VAR(result, parseInterfaceArrayExpression(start, kind, fields));
+        break;
+      case BinKind::AssignmentExpression:
+        MOZ_TRY_VAR(result, parseInterfaceAssignmentExpression(start, kind, fields));
+        break;
+      case BinKind::AwaitExpression:
+        MOZ_TRY_VAR(result, parseInterfaceAwaitExpression(start, kind, fields));
+        break;
+      case BinKind::BinaryExpression:
+        MOZ_TRY_VAR(result, parseInterfaceBinaryExpression(start, kind, fields));
+        break;
+      case BinKind::CallExpression:
+        MOZ_TRY_VAR(result, parseInterfaceCallExpression(start, kind, fields));
+        break;
+      case BinKind::ClassExpression:
+        MOZ_TRY_VAR(result, parseInterfaceClassExpression(start, kind, fields));
+        break;
+      case BinKind::CompoundAssignmentExpression:
+        MOZ_TRY_VAR(result, parseInterfaceCompoundAssignmentExpression(start, kind, fields));
+        break;
+      case BinKind::ComputedMemberExpression:
+        MOZ_TRY_VAR(result, parseInterfaceComputedMemberExpression(start, kind, fields));
+        break;
+      case BinKind::ConditionalExpression:
+        MOZ_TRY_VAR(result, parseInterfaceConditionalExpression(start, kind, fields));
+        break;
+      case BinKind::EagerArrowExpressionWithExpression:
+        MOZ_TRY_VAR(result, parseInterfaceEagerArrowExpressionWithExpression(start, kind, fields));
+        break;
+      case BinKind::EagerArrowExpressionWithFunctionBody:
+        MOZ_TRY_VAR(result, parseInterfaceEagerArrowExpressionWithFunctionBody(start, kind, fields));
+        break;
+      case BinKind::EagerFunctionExpression:
+        MOZ_TRY_VAR(result, parseInterfaceEagerFunctionExpression(start, kind, fields));
+        break;
+      case BinKind::IdentifierExpression:
+        MOZ_TRY_VAR(result, parseInterfaceIdentifierExpression(start, kind, fields));
+        break;
+      case BinKind::LazyArrowExpressionWithExpression:
+        MOZ_TRY_VAR(result, parseInterfaceLazyArrowExpressionWithExpression(start, kind, fields));
+        break;
+      case BinKind::LazyArrowExpressionWithFunctionBody:
+        MOZ_TRY_VAR(result, parseInterfaceLazyArrowExpressionWithFunctionBody(start, kind, fields));
+        break;
+      case BinKind::LazyFunctionExpression:
+        MOZ_TRY_VAR(result, parseInterfaceLazyFunctionExpression(start, kind, fields));
+        break;
+      case BinKind::LiteralBooleanExpression:
+        MOZ_TRY_VAR(result, parseInterfaceLiteralBooleanExpression(start, kind, fields));
+        break;
+      case BinKind::LiteralInfinityExpression:
+        MOZ_TRY_VAR(result, parseInterfaceLiteralInfinityExpression(start, kind, fields));
+        break;
+      case BinKind::LiteralNullExpression:
+        MOZ_TRY_VAR(result, parseInterfaceLiteralNullExpression(start, kind, fields));
+        break;
+      case BinKind::LiteralNumericExpression:
+        MOZ_TRY_VAR(result, parseInterfaceLiteralNumericExpression(start, kind, fields));
+        break;
+      case BinKind::LiteralRegExpExpression:
+        MOZ_TRY_VAR(result, parseInterfaceLiteralRegExpExpression(start, kind, fields));
+        break;
+      case BinKind::LiteralStringExpression:
+        MOZ_TRY_VAR(result, parseInterfaceLiteralStringExpression(start, kind, fields));
+        break;
+      case BinKind::NewExpression:
+        MOZ_TRY_VAR(result, parseInterfaceNewExpression(start, kind, fields));
+        break;
+      case BinKind::NewTargetExpression:
+        MOZ_TRY_VAR(result, parseInterfaceNewTargetExpression(start, kind, fields));
+        break;
+      case BinKind::ObjectExpression:
+        MOZ_TRY_VAR(result, parseInterfaceObjectExpression(start, kind, fields));
+        break;
+      case BinKind::StaticMemberExpression:
+        MOZ_TRY_VAR(result, parseInterfaceStaticMemberExpression(start, kind, fields));
+        break;
+      case BinKind::Super:
+        MOZ_TRY_VAR(result, parseInterfaceSuper(start, kind, fields));
+        break;
+      case BinKind::TemplateExpression:
+        MOZ_TRY_VAR(result, parseInterfaceTemplateExpression(start, kind, fields));
+        break;
+      case BinKind::ThisExpression:
+        MOZ_TRY_VAR(result, parseInterfaceThisExpression(start, kind, fields));
+        break;
+      case BinKind::UnaryExpression:
+        MOZ_TRY_VAR(result, parseInterfaceUnaryExpression(start, kind, fields));
+        break;
+      case BinKind::UpdateExpression:
+        MOZ_TRY_VAR(result, parseInterfaceUpdateExpression(start, kind, fields));
+        break;
+      case BinKind::YieldExpression:
+        MOZ_TRY_VAR(result, parseInterfaceYieldExpression(start, kind, fields));
+        break;
+      case BinKind::YieldStarExpression:
+        MOZ_TRY_VAR(result, parseInterfaceYieldStarExpression(start, kind, fields));
+        break;
+      default:
+        return raiseInvalidKind("ExpressionOrSuper", kind);
+    }
+    return result;
+}
+
+/*
+ForInOfBindingOrAssignmentTarget ::= ArrayAssignmentTarget
+    AssignmentTargetIdentifier
+    ComputedMemberAssignmentTarget
+    ForInOfBinding
+    ObjectAssignmentTarget
+    StaticMemberAssignmentTarget
+*/
+template<typename Tok> JS::Result<ParseNode*>
+BinASTParser<Tok>::parseForInOfBindingOrAssignmentTarget()
+{
+    BinKind kind;
+    BinFields fields(cx_);
+    AutoTaggedTuple guard(*tokenizer_);
+    const auto start = tokenizer_->offset();
+
+    MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+
+    BINJS_MOZ_TRY_DECL(result, parseSumForInOfBindingOrAssignmentTarget(start, kind, fields));
+
+    MOZ_TRY(guard.done());
+    return result;
+}
+
+template<typename Tok> JS::Result<ParseNode*>
+BinASTParser<Tok>::parseSumForInOfBindingOrAssignmentTarget(const size_t start, const BinKind kind, const BinFields& fields)
+{
+    ParseNode* result;
+    switch (kind) {
+      case BinKind::ArrayAssignmentTarget:
+        MOZ_TRY_VAR(result, parseInterfaceArrayAssignmentTarget(start, kind, fields));
+        break;
+      case BinKind::AssignmentTargetIdentifier:
+        MOZ_TRY_VAR(result, parseInterfaceAssignmentTargetIdentifier(start, kind, fields));
+        break;
+      case BinKind::ComputedMemberAssignmentTarget:
+        MOZ_TRY_VAR(result, parseInterfaceComputedMemberAssignmentTarget(start, kind, fields));
+        break;
+      case BinKind::ForInOfBinding:
+        MOZ_TRY_VAR(result, parseInterfaceForInOfBinding(start, kind, fields));
+        break;
+      case BinKind::ObjectAssignmentTarget:
+        MOZ_TRY_VAR(result, parseInterfaceObjectAssignmentTarget(start, kind, fields));
+        break;
+      case BinKind::StaticMemberAssignmentTarget:
+        MOZ_TRY_VAR(result, parseInterfaceStaticMemberAssignmentTarget(start, kind, fields));
+        break;
+      default:
+        return raiseInvalidKind("ForInOfBindingOrAssignmentTarget", kind);
+    }
+    return result;
+}
+
+/*
+ObjectProperty ::= DataProperty
+    EagerGetter
+    EagerMethod
+    EagerSetter
+    LazyGetter
+    LazyMethod
+    LazySetter
+    ShorthandProperty
+*/
+template<typename Tok> JS::Result<ParseNode*>
+BinASTParser<Tok>::parseObjectProperty()
+{
+    BinKind kind;
+    BinFields fields(cx_);
+    AutoTaggedTuple guard(*tokenizer_);
+    const auto start = tokenizer_->offset();
+
+    MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+
+    BINJS_MOZ_TRY_DECL(result, parseSumObjectProperty(start, kind, fields));
+
+    MOZ_TRY(guard.done());
+    return result;
+}
+
+template<typename Tok> JS::Result<ParseNode*>
+BinASTParser<Tok>::parseSumObjectProperty(const size_t start, const BinKind kind, const BinFields& fields)
+{
+    ParseNode* result;
+    switch (kind) {
+      case BinKind::DataProperty:
+        MOZ_TRY_VAR(result, parseInterfaceDataProperty(start, kind, fields));
+        break;
+      case BinKind::EagerGetter:
+        MOZ_TRY_VAR(result, parseInterfaceEagerGetter(start, kind, fields));
+        break;
+      case BinKind::EagerMethod:
+        MOZ_TRY_VAR(result, parseInterfaceEagerMethod(start, kind, fields));
+        break;
+      case BinKind::EagerSetter:
+        MOZ_TRY_VAR(result, parseInterfaceEagerSetter(start, kind, fields));
+        break;
+      case BinKind::LazyGetter:
+        MOZ_TRY_VAR(result, parseInterfaceLazyGetter(start, kind, fields));
+        break;
+      case BinKind::LazyMethod:
+        MOZ_TRY_VAR(result, parseInterfaceLazyMethod(start, kind, fields));
+        break;
+      case BinKind::LazySetter:
+        MOZ_TRY_VAR(result, parseInterfaceLazySetter(start, kind, fields));
+        break;
+      case BinKind::ShorthandProperty:
+        MOZ_TRY_VAR(result, parseInterfaceShorthandProperty(start, kind, fields));
+        break;
+      default:
+        return raiseInvalidKind("ObjectProperty", kind);
+    }
+    return result;
+}
+
+/*
+Parameter ::= ArrayBinding
+    BindingIdentifier
+    BindingWithInitializer
+    ObjectBinding
+*/
+template<typename Tok> JS::Result<ParseNode*>
+BinASTParser<Tok>::parseParameter()
+{
+    BinKind kind;
+    BinFields fields(cx_);
+    AutoTaggedTuple guard(*tokenizer_);
+    const auto start = tokenizer_->offset();
+
+    MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+
+    BINJS_MOZ_TRY_DECL(result, parseSumParameter(start, kind, fields));
+
+    MOZ_TRY(guard.done());
+    return result;
+}
+
+template<typename Tok> JS::Result<ParseNode*>
+BinASTParser<Tok>::parseSumParameter(const size_t start, const BinKind kind, const BinFields& fields)
+{
+    ParseNode* result;
+    switch (kind) {
+      case BinKind::ArrayBinding:
+        MOZ_TRY_VAR(result, parseInterfaceArrayBinding(start, kind, fields));
+        break;
+      case BinKind::BindingIdentifier:
+        MOZ_TRY_VAR(result, parseInterfaceBindingIdentifier(start, kind, fields));
+        if (!parseContext_->positionalFormalParameterNames().append(result->template as<NameNode>().atom())) {
+            return raiseOOM();
+        }
+        if (parseContext_->isFunctionBox()) {
+            parseContext_->functionBox()->length++;
+        }
+        break;
+      case BinKind::BindingWithInitializer:
+        MOZ_TRY_VAR(result, parseInterfaceBindingWithInitializer(start, kind, fields));
+        break;
+      case BinKind::ObjectBinding:
+        MOZ_TRY_VAR(result, parseInterfaceObjectBinding(start, kind, fields));
+        break;
+      default:
+        return raiseInvalidKind("Parameter", kind);
+    }
+    return result;
+}
+
+/*
+Program ::= Module
+    Script
+*/
+template<typename Tok> JS::Result<ParseNode*>
+BinASTParser<Tok>::parseProgram()
+{
+    BinKind kind;
+    BinFields fields(cx_);
+    AutoTaggedTuple guard(*tokenizer_);
+    const auto start = tokenizer_->offset();
+
+    MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+
+    BINJS_MOZ_TRY_DECL(result, parseSumProgram(start, kind, fields));
+
+    MOZ_TRY(guard.done());
+    return result;
+}
+
+template<typename Tok> JS::Result<ParseNode*>
+BinASTParser<Tok>::parseSumProgram(const size_t start, const BinKind kind, const BinFields& fields)
+{
+    ParseNode* result;
+    switch (kind) {
+      case BinKind::Module:
+        MOZ_TRY_VAR(result, parseInterfaceModule(start, kind, fields));
+        break;
+      case BinKind::Script:
+        MOZ_TRY_VAR(result, parseInterfaceScript(start, kind, fields));
+        break;
+      default:
+        return raiseInvalidKind("Program", kind);
+    }
+    return result;
+}
+
+/*
+PropertyName ::= ComputedPropertyName
+    LiteralPropertyName
+*/
+template<typename Tok> JS::Result<ParseNode*>
+BinASTParser<Tok>::parsePropertyName()
+{
+    BinKind kind;
+    BinFields fields(cx_);
+    AutoTaggedTuple guard(*tokenizer_);
+    const auto start = tokenizer_->offset();
+
+    MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+
+    BINJS_MOZ_TRY_DECL(result, parseSumPropertyName(start, kind, fields));
+
+    MOZ_TRY(guard.done());
+    return result;
+}
+
+template<typename Tok> JS::Result<ParseNode*>
+BinASTParser<Tok>::parseSumPropertyName(const size_t start, const BinKind kind, const BinFields& fields)
+{
+    ParseNode* result;
+    switch (kind) {
+      case BinKind::ComputedPropertyName:
+        MOZ_TRY_VAR(result, parseInterfaceComputedPropertyName(start, kind, fields));
+        break;
+      case BinKind::LiteralPropertyName:
+        MOZ_TRY_VAR(result, parseInterfaceLiteralPropertyName(start, kind, fields));
+        break;
+      default:
+        return raiseInvalidKind("PropertyName", kind);
+    }
+    return result;
+}
+
+/*
+SimpleAssignmentTarget ::= AssignmentTargetIdentifier
+    ComputedMemberAssignmentTarget
+    StaticMemberAssignmentTarget
+*/
+template<typename Tok> JS::Result<ParseNode*>
+BinASTParser<Tok>::parseSimpleAssignmentTarget()
+{
+    BinKind kind;
+    BinFields fields(cx_);
+    AutoTaggedTuple guard(*tokenizer_);
+    const auto start = tokenizer_->offset();
+
+    MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+
+    BINJS_MOZ_TRY_DECL(result, parseSumSimpleAssignmentTarget(start, kind, fields));
+
+    MOZ_TRY(guard.done());
+    return result;
+}
+
+template<typename Tok> JS::Result<ParseNode*>
+BinASTParser<Tok>::parseSumSimpleAssignmentTarget(const size_t start, const BinKind kind, const BinFields& fields)
+{
+    ParseNode* result;
+    switch (kind) {
+      case BinKind::AssignmentTargetIdentifier:
+        MOZ_TRY_VAR(result, parseInterfaceAssignmentTargetIdentifier(start, kind, fields));
+        break;
+      case BinKind::ComputedMemberAssignmentTarget:
+        MOZ_TRY_VAR(result, parseInterfaceComputedMemberAssignmentTarget(start, kind, fields));
+        break;
+      case BinKind::StaticMemberAssignmentTarget:
+        MOZ_TRY_VAR(result, parseInterfaceStaticMemberAssignmentTarget(start, kind, fields));
+        break;
+      default:
+        return raiseInvalidKind("SimpleAssignmentTarget", kind);
+    }
+    return result;
+}
+
+/*
+SpreadElementOrExpression ::= ArrayExpression
+    AssignmentExpression
+    AwaitExpression
+    BinaryExpression
+    CallExpression
+    ClassExpression
+    CompoundAssignmentExpression
+    ComputedMemberExpression
+    ConditionalExpression
+    EagerArrowExpressionWithExpression
+    EagerArrowExpressionWithFunctionBody
+    EagerFunctionExpression
+    IdentifierExpression
+    LazyArrowExpressionWithExpression
+    LazyArrowExpressionWithFunctionBody
+    LazyFunctionExpression
+    LiteralBooleanExpression
+    LiteralInfinityExpression
+    LiteralNullExpression
+    LiteralNumericExpression
+    LiteralRegExpExpression
+    LiteralStringExpression
+    NewExpression
+    NewTargetExpression
+    ObjectExpression
+    SpreadElement
+    StaticMemberExpression
+    TemplateExpression
+    ThisExpression
+    UnaryExpression
+    UpdateExpression
+    YieldExpression
+    YieldStarExpression
+*/
+template<typename Tok> JS::Result<ParseNode*>
+BinASTParser<Tok>::parseSpreadElementOrExpression()
+{
+    BinKind kind;
+    BinFields fields(cx_);
+    AutoTaggedTuple guard(*tokenizer_);
+    const auto start = tokenizer_->offset();
+
+    MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+
+    BINJS_MOZ_TRY_DECL(result, parseSumSpreadElementOrExpression(start, kind, fields));
+
+    MOZ_TRY(guard.done());
+    return result;
+}
+
+template<typename Tok> JS::Result<ParseNode*>
+BinASTParser<Tok>::parseSumSpreadElementOrExpression(const size_t start, const BinKind kind, const BinFields& fields)
+{
+    ParseNode* result;
+    switch (kind) {
+      case BinKind::ArrayExpression:
+        MOZ_TRY_VAR(result, parseInterfaceArrayExpression(start, kind, fields));
+        break;
+      case BinKind::AssignmentExpression:
+        MOZ_TRY_VAR(result, parseInterfaceAssignmentExpression(start, kind, fields));
+        break;
+      case BinKind::AwaitExpression:
+        MOZ_TRY_VAR(result, parseInterfaceAwaitExpression(start, kind, fields));
+        break;
+      case BinKind::BinaryExpression:
+        MOZ_TRY_VAR(result, parseInterfaceBinaryExpression(start, kind, fields));
+        break;
+      case BinKind::CallExpression:
+        MOZ_TRY_VAR(result, parseInterfaceCallExpression(start, kind, fields));
+        break;
+      case BinKind::ClassExpression:
+        MOZ_TRY_VAR(result, parseInterfaceClassExpression(start, kind, fields));
+        break;
+      case BinKind::CompoundAssignmentExpression:
+        MOZ_TRY_VAR(result, parseInterfaceCompoundAssignmentExpression(start, kind, fields));
+        break;
+      case BinKind::ComputedMemberExpression:
+        MOZ_TRY_VAR(result, parseInterfaceComputedMemberExpression(start, kind, fields));
+        break;
+      case BinKind::ConditionalExpression:
+        MOZ_TRY_VAR(result, parseInterfaceConditionalExpression(start, kind, fields));
+        break;
+      case BinKind::EagerArrowExpressionWithExpression:
+        MOZ_TRY_VAR(result, parseInterfaceEagerArrowExpressionWithExpression(start, kind, fields));
+        break;
+      case BinKind::EagerArrowExpressionWithFunctionBody:
+        MOZ_TRY_VAR(result, parseInterfaceEagerArrowExpressionWithFunctionBody(start, kind, fields));
+        break;
+      case BinKind::EagerFunctionExpression:
+        MOZ_TRY_VAR(result, parseInterfaceEagerFunctionExpression(start, kind, fields));
+        break;
+      case BinKind::IdentifierExpression:
+        MOZ_TRY_VAR(result, parseInterfaceIdentifierExpression(start, kind, fields));
+        break;
+      case BinKind::LazyArrowExpressionWithExpression:
+        MOZ_TRY_VAR(result, parseInterfaceLazyArrowExpressionWithExpression(start, kind, fields));
+        break;
+      case BinKind::LazyArrowExpressionWithFunctionBody:
+        MOZ_TRY_VAR(result, parseInterfaceLazyArrowExpressionWithFunctionBody(start, kind, fields));
+        break;
+      case BinKind::LazyFunctionExpression:
+        MOZ_TRY_VAR(result, parseInterfaceLazyFunctionExpression(start, kind, fields));
+        break;
+      case BinKind::LiteralBooleanExpression:
+        MOZ_TRY_VAR(result, parseInterfaceLiteralBooleanExpression(start, kind, fields));
+        break;
+      case BinKind::LiteralInfinityExpression:
+        MOZ_TRY_VAR(result, parseInterfaceLiteralInfinityExpression(start, kind, fields));
+        break;
+      case BinKind::LiteralNullExpression:
+        MOZ_TRY_VAR(result, parseInterfaceLiteralNullExpression(start, kind, fields));
+        break;
+      case BinKind::LiteralNumericExpression:
+        MOZ_TRY_VAR(result, parseInterfaceLiteralNumericExpression(start, kind, fields));
+        break;
+      case BinKind::LiteralRegExpExpression:
+        MOZ_TRY_VAR(result, parseInterfaceLiteralRegExpExpression(start, kind, fields));
+        break;
+      case BinKind::LiteralStringExpression:
+        MOZ_TRY_VAR(result, parseInterfaceLiteralStringExpression(start, kind, fields));
+        break;
+      case BinKind::NewExpression:
+        MOZ_TRY_VAR(result, parseInterfaceNewExpression(start, kind, fields));
+        break;
+      case BinKind::NewTargetExpression:
+        MOZ_TRY_VAR(result, parseInterfaceNewTargetExpression(start, kind, fields));
+        break;
+      case BinKind::ObjectExpression:
+        MOZ_TRY_VAR(result, parseInterfaceObjectExpression(start, kind, fields));
+        break;
+      case BinKind::SpreadElement:
+        MOZ_TRY_VAR(result, parseInterfaceSpreadElement(start, kind, fields));
+        break;
+      case BinKind::StaticMemberExpression:
+        MOZ_TRY_VAR(result, parseInterfaceStaticMemberExpression(start, kind, fields));
+        break;
+      case BinKind::TemplateExpression:
+        MOZ_TRY_VAR(result, parseInterfaceTemplateExpression(start, kind, fields));
+        break;
+      case BinKind::ThisExpression:
+        MOZ_TRY_VAR(result, parseInterfaceThisExpression(start, kind, fields));
+        break;
+      case BinKind::UnaryExpression:
+        MOZ_TRY_VAR(result, parseInterfaceUnaryExpression(start, kind, fields));
+        break;
+      case BinKind::UpdateExpression:
+        MOZ_TRY_VAR(result, parseInterfaceUpdateExpression(start, kind, fields));
+        break;
+      case BinKind::YieldExpression:
+        MOZ_TRY_VAR(result, parseInterfaceYieldExpression(start, kind, fields));
+        break;
+      case BinKind::YieldStarExpression:
+        MOZ_TRY_VAR(result, parseInterfaceYieldStarExpression(start, kind, fields));
+        break;
+      default:
+        return raiseInvalidKind("SpreadElementOrExpression", kind);
+    }
+    return result;
+}
+
+/*
+Statement ::= Block
+    BreakStatement
+    ClassDeclaration
+    ContinueStatement
+    DebuggerStatement
+    DoWhileStatement
+    EagerFunctionDeclaration
+    EmptyStatement
+    ExpressionStatement
+    ForInStatement
+    ForOfStatement
+    ForStatement
+    IfStatement
+    LabelledStatement
+    LazyFunctionDeclaration
+    ReturnStatement
+    SwitchStatement
+    SwitchStatementWithDefault
+    ThrowStatement
+    TryCatchStatement
+    TryFinallyStatement
+    VariableDeclaration
+    WhileStatement
+    WithStatement
+*/
+template<typename Tok> JS::Result<ParseNode*>
+BinASTParser<Tok>::parseStatement()
+{
+    BinKind kind;
+    BinFields fields(cx_);
+    AutoTaggedTuple guard(*tokenizer_);
+    const auto start = tokenizer_->offset();
+
+    MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+
+    BINJS_MOZ_TRY_DECL(result, parseSumStatement(start, kind, fields));
+
+    MOZ_TRY(guard.done());
+    return result;
+}
+
+template<typename Tok> JS::Result<ParseNode*>
+BinASTParser<Tok>::parseSumStatement(const size_t start, const BinKind kind, const BinFields& fields)
+{
+    ParseNode* result;
+    switch (kind) {
+      case BinKind::Block:
+        MOZ_TRY_VAR(result, parseInterfaceBlock(start, kind, fields));
+        break;
+      case BinKind::BreakStatement:
+        MOZ_TRY_VAR(result, parseInterfaceBreakStatement(start, kind, fields));
+        break;
+      case BinKind::ClassDeclaration:
+        MOZ_TRY_VAR(result, parseInterfaceClassDeclaration(start, kind, fields));
+        break;
+      case BinKind::ContinueStatement:
+        MOZ_TRY_VAR(result, parseInterfaceContinueStatement(start, kind, fields));
+        break;
+      case BinKind::DebuggerStatement:
+        MOZ_TRY_VAR(result, parseInterfaceDebuggerStatement(start, kind, fields));
+        break;
+      case BinKind::DoWhileStatement:
+        MOZ_TRY_VAR(result, parseInterfaceDoWhileStatement(start, kind, fields));
+        break;
+      case BinKind::EagerFunctionDeclaration:
+        MOZ_TRY_VAR(result, parseInterfaceEagerFunctionDeclaration(start, kind, fields));
+        break;
+      case BinKind::EmptyStatement:
+        MOZ_TRY_VAR(result, parseInterfaceEmptyStatement(start, kind, fields));
+        break;
+      case BinKind::ExpressionStatement:
+        MOZ_TRY_VAR(result, parseInterfaceExpressionStatement(start, kind, fields));
+        break;
+      case BinKind::ForInStatement:
+        MOZ_TRY_VAR(result, parseInterfaceForInStatement(start, kind, fields));
+        break;
+      case BinKind::ForOfStatement:
+        MOZ_TRY_VAR(result, parseInterfaceForOfStatement(start, kind, fields));
+        break;
+      case BinKind::ForStatement:
+        MOZ_TRY_VAR(result, parseInterfaceForStatement(start, kind, fields));
+        break;
+      case BinKind::IfStatement:
+        MOZ_TRY_VAR(result, parseInterfaceIfStatement(start, kind, fields));
+        break;
+      case BinKind::LabelledStatement:
+        MOZ_TRY_VAR(result, parseInterfaceLabelledStatement(start, kind, fields));
+        break;
+      case BinKind::LazyFunctionDeclaration:
+        MOZ_TRY_VAR(result, parseInterfaceLazyFunctionDeclaration(start, kind, fields));
+        break;
+      case BinKind::ReturnStatement:
+        MOZ_TRY_VAR(result, parseInterfaceReturnStatement(start, kind, fields));
+        break;
+      case BinKind::SwitchStatement:
+        MOZ_TRY_VAR(result, parseInterfaceSwitchStatement(start, kind, fields));
+        break;
+      case BinKind::SwitchStatementWithDefault:
+        MOZ_TRY_VAR(result, parseInterfaceSwitchStatementWithDefault(start, kind, fields));
+        break;
+      case BinKind::ThrowStatement:
+        MOZ_TRY_VAR(result, parseInterfaceThrowStatement(start, kind, fields));
+        break;
+      case BinKind::TryCatchStatement:
+        MOZ_TRY_VAR(result, parseInterfaceTryCatchStatement(start, kind, fields));
+        break;
+      case BinKind::TryFinallyStatement:
+        MOZ_TRY_VAR(result, parseInterfaceTryFinallyStatement(start, kind, fields));
+        break;
+      case BinKind::VariableDeclaration:
+        MOZ_TRY_VAR(result, parseInterfaceVariableDeclaration(start, kind, fields));
+        break;
+      case BinKind::WhileStatement:
+        MOZ_TRY_VAR(result, parseInterfaceWhileStatement(start, kind, fields));
+        break;
+      case BinKind::WithStatement:
+        MOZ_TRY_VAR(result, parseInterfaceWithStatement(start, kind, fields));
+        break;
+      default:
+        return raiseInvalidKind("Statement", kind);
+    }
+    return result;
+}
+
+
+template<typename Tok> JS::Result<ParseNode*>
+BinASTParser<Tok>::parseSumVariableDeclarationOrExpression(const size_t start, const BinKind kind, const BinFields& fields)
+{
+    ParseNode* result;
+    switch (kind) {
+      case BinKind::ArrayExpression:
+        MOZ_TRY_VAR(result, parseInterfaceArrayExpression(start, kind, fields));
+        break;
+      case BinKind::AssignmentExpression:
+        MOZ_TRY_VAR(result, parseInterfaceAssignmentExpression(start, kind, fields));
+        break;
+      case BinKind::AwaitExpression:
+        MOZ_TRY_VAR(result, parseInterfaceAwaitExpression(start, kind, fields));
+        break;
+      case BinKind::BinaryExpression:
+        MOZ_TRY_VAR(result, parseInterfaceBinaryExpression(start, kind, fields));
+        break;
+      case BinKind::CallExpression:
+        MOZ_TRY_VAR(result, parseInterfaceCallExpression(start, kind, fields));
+        break;
+      case BinKind::ClassExpression:
+        MOZ_TRY_VAR(result, parseInterfaceClassExpression(start, kind, fields));
+        break;
+      case BinKind::CompoundAssignmentExpression:
+        MOZ_TRY_VAR(result, parseInterfaceCompoundAssignmentExpression(start, kind, fields));
+        break;
+      case BinKind::ComputedMemberExpression:
+        MOZ_TRY_VAR(result, parseInterfaceComputedMemberExpression(start, kind, fields));
+        break;
+      case BinKind::ConditionalExpression:
+        MOZ_TRY_VAR(result, parseInterfaceConditionalExpression(start, kind, fields));
+        break;
+      case BinKind::EagerArrowExpressionWithExpression:
+        MOZ_TRY_VAR(result, parseInterfaceEagerArrowExpressionWithExpression(start, kind, fields));
+        break;
+      case BinKind::EagerArrowExpressionWithFunctionBody:
+        MOZ_TRY_VAR(result, parseInterfaceEagerArrowExpressionWithFunctionBody(start, kind, fields));
+        break;
+      case BinKind::EagerFunctionExpression:
+        MOZ_TRY_VAR(result, parseInterfaceEagerFunctionExpression(start, kind, fields));
+        break;
+      case BinKind::IdentifierExpression:
+        MOZ_TRY_VAR(result, parseInterfaceIdentifierExpression(start, kind, fields));
+        break;
+      case BinKind::LazyArrowExpressionWithExpression:
+        MOZ_TRY_VAR(result, parseInterfaceLazyArrowExpressionWithExpression(start, kind, fields));
+        break;
+      case BinKind::LazyArrowExpressionWithFunctionBody:
+        MOZ_TRY_VAR(result, parseInterfaceLazyArrowExpressionWithFunctionBody(start, kind, fields));
+        break;
+      case BinKind::LazyFunctionExpression:
+        MOZ_TRY_VAR(result, parseInterfaceLazyFunctionExpression(start, kind, fields));
+        break;
+      case BinKind::LiteralBooleanExpression:
+        MOZ_TRY_VAR(result, parseInterfaceLiteralBooleanExpression(start, kind, fields));
+        break;
+      case BinKind::LiteralInfinityExpression:
+        MOZ_TRY_VAR(result, parseInterfaceLiteralInfinityExpression(start, kind, fields));
+        break;
+      case BinKind::LiteralNullExpression:
+        MOZ_TRY_VAR(result, parseInterfaceLiteralNullExpression(start, kind, fields));
+        break;
+      case BinKind::LiteralNumericExpression:
+        MOZ_TRY_VAR(result, parseInterfaceLiteralNumericExpression(start, kind, fields));
+        break;
+      case BinKind::LiteralRegExpExpression:
+        MOZ_TRY_VAR(result, parseInterfaceLiteralRegExpExpression(start, kind, fields));
+        break;
+      case BinKind::LiteralStringExpression:
+        MOZ_TRY_VAR(result, parseInterfaceLiteralStringExpression(start, kind, fields));
+        break;
+      case BinKind::NewExpression:
+        MOZ_TRY_VAR(result, parseInterfaceNewExpression(start, kind, fields));
+        break;
+      case BinKind::NewTargetExpression:
+        MOZ_TRY_VAR(result, parseInterfaceNewTargetExpression(start, kind, fields));
+        break;
+      case BinKind::ObjectExpression:
+        MOZ_TRY_VAR(result, parseInterfaceObjectExpression(start, kind, fields));
+        break;
+      case BinKind::StaticMemberExpression:
+        MOZ_TRY_VAR(result, parseInterfaceStaticMemberExpression(start, kind, fields));
+        break;
+      case BinKind::TemplateExpression:
+        MOZ_TRY_VAR(result, parseInterfaceTemplateExpression(start, kind, fields));
+        break;
+      case BinKind::ThisExpression:
+        MOZ_TRY_VAR(result, parseInterfaceThisExpression(start, kind, fields));
+        break;
+      case BinKind::UnaryExpression:
+        MOZ_TRY_VAR(result, parseInterfaceUnaryExpression(start, kind, fields));
+        break;
+      case BinKind::UpdateExpression:
+        MOZ_TRY_VAR(result, parseInterfaceUpdateExpression(start, kind, fields));
+        break;
+      case BinKind::VariableDeclaration:
+        MOZ_TRY_VAR(result, parseInterfaceVariableDeclaration(start, kind, fields));
+        break;
+      case BinKind::YieldExpression:
+        MOZ_TRY_VAR(result, parseInterfaceYieldExpression(start, kind, fields));
+        break;
+      case BinKind::YieldStarExpression:
+        MOZ_TRY_VAR(result, parseInterfaceYieldStarExpression(start, kind, fields));
+        break;
+      default:
+        return raiseInvalidKind("VariableDeclarationOrExpression", kind);
+    }
+    return result;
+}
+
+
+
+// ----- Interfaces (autogenerated, by lexicographical order)
+// When fields have a non-trivial type, implementation is deanonymized and delegated to another parser.
+template<typename Tok> JS::Result<ParseNode*>
+BinASTParser<Tok>::parseInterfaceArrayAssignmentTarget(const size_t start, const BinKind kind, const BinFields& fields)
+{
+    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 BinKind kind, const BinFields& fields)
+{
+    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 BinKind kind, const BinFields& fields)
+{
+    MOZ_ASSERT(kind == BinKind::ArrayExpression);
+    BINJS_TRY(CheckRecursionLimit(cx_));
+
+#if defined(DEBUG)
+    const BinField expected_fields[1] = { BinField::Elements };
+    MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
+#endif // defined(DEBUG)
+
+    BINJS_MOZ_TRY_DECL(elements, parseListOfOptionalSpreadElementOrExpression());
+
+    if (elements->empty()) {
+        elements->setHasNonConstInitializer();
+    }
+    auto result = elements;
+    return result;
+}
+
+
+/*
+ interface AssertedBlockScope : Node {
+    FrozenArray<AssertedDeclaredName> declaredNames;
+    bool hasDirectEval;
+ }
+*/
+template<typename Tok> JS::Result<Ok>
+BinASTParser<Tok>::parseAssertedBlockScope()
+{
+    BinKind kind;
+    BinFields fields(cx_);
+    AutoTaggedTuple guard(*tokenizer_);
+
+    MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+    if (kind != BinKind::AssertedBlockScope) {
+        return raiseInvalidKind("AssertedBlockScope", kind);
+    }
+    const auto start = tokenizer_->offset();
+    BINJS_MOZ_TRY_DECL(result, parseInterfaceAssertedBlockScope(start, kind, fields));
+    MOZ_TRY(guard.done());
+
+    return result;
+}
+
+template<typename Tok> JS::Result<Ok>
+BinASTParser<Tok>::parseInterfaceAssertedBlockScope(const size_t start, const BinKind kind, const BinFields& fields)
+{
+    MOZ_ASSERT(kind == BinKind::AssertedBlockScope);
+    BINJS_TRY(CheckRecursionLimit(cx_));
+
+#if defined(DEBUG)
+    const BinField expected_fields[2] = { BinField::DeclaredNames, BinField::HasDirectEval };
+    MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
+#endif // defined(DEBUG)
+    const auto scopeKind = AssertedScopeKind::Block;
+
+    MOZ_TRY(parseListOfAssertedDeclaredName(
+        scopeKind));
+
+    BINJS_MOZ_TRY_DECL(hasDirectEval, tokenizer_->readBool());
+    if (hasDirectEval) {
+        parseContext_->sc()->setHasDirectEval();
+        parseContext_->sc()->setBindingsAccessedDynamically();
+    }
+    if (hasDirectEval && parseContext_->isFunctionBox() && !parseContext_->sc()->strict()) {
+        // In non-strict mode code, direct calls to eval can
+        // add variables to the call object.
+        parseContext_->functionBox()->setHasExtensibleScope();
+    }
+    auto result = Ok();
+    return result;
+}
+
+
+/*
+ interface AssertedBoundName : Node {
+    [IdentifierName] string name;
+    bool isCaptured;
+ }
+*/
+template<typename Tok> JS::Result<Ok>
+BinASTParser<Tok>::parseAssertedBoundName(
+        AssertedScopeKind scopeKind)
+{
+    BinKind kind;
+    BinFields fields(cx_);
+    AutoTaggedTuple guard(*tokenizer_);
+
+    MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+    if (kind != BinKind::AssertedBoundName) {
+        return raiseInvalidKind("AssertedBoundName", kind);
+    }
+    const auto start = tokenizer_->offset();
+    BINJS_MOZ_TRY_DECL(result, parseInterfaceAssertedBoundName(start, kind, fields,
+        scopeKind));
+    MOZ_TRY(guard.done());
+
+    return result;
+}
+
+template<typename Tok> JS::Result<Ok>
+BinASTParser<Tok>::parseInterfaceAssertedBoundName(const size_t start, const BinKind kind, const BinFields& fields,
+        AssertedScopeKind scopeKind)
+{
+    MOZ_ASSERT(kind == BinKind::AssertedBoundName);
+    BINJS_TRY(CheckRecursionLimit(cx_));
+
+#if defined(DEBUG)
+    const BinField expected_fields[2] = { BinField::Name, BinField::IsCaptured };
+    MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
+#endif // defined(DEBUG)
+    const bool allowDuplicateName = false;
+
+    RootedAtom name(cx_);
+    MOZ_TRY_VAR(name, tokenizer_->readIdentifierName());
+
+    BINJS_MOZ_TRY_DECL(isCaptured, tokenizer_->readBool());
+    ParseContext::Scope* scope;
+    DeclarationKind declKind;
+    MOZ_TRY(getBoundScope(scopeKind, scope, declKind));
+    MOZ_TRY(addScopeName(scopeKind, name, scope, declKind, isCaptured, allowDuplicateName));
+    auto result = Ok();
+    return result;
+}
+
+
+/*
+ interface AssertedBoundNamesScope : Node {
+    FrozenArray<AssertedBoundName> boundNames;
+    bool hasDirectEval;
+ }
+*/
+template<typename Tok> JS::Result<Ok>
+BinASTParser<Tok>::parseAssertedBoundNamesScope()
+{
+    BinKind kind;
+    BinFields fields(cx_);
+    AutoTaggedTuple guard(*tokenizer_);
+
+    MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+    if (kind != BinKind::AssertedBoundNamesScope) {
+        return raiseInvalidKind("AssertedBoundNamesScope", kind);
+    }
+    const auto start = tokenizer_->offset();
+    BINJS_MOZ_TRY_DECL(result, parseInterfaceAssertedBoundNamesScope(start, kind, fields));
+    MOZ_TRY(guard.done());
+
+    return result;
+}
+
+template<typename Tok> JS::Result<Ok>
+BinASTParser<Tok>::parseInterfaceAssertedBoundNamesScope(const size_t start, const BinKind kind, const BinFields& fields)
+{
+    MOZ_ASSERT(kind == BinKind::AssertedBoundNamesScope);
+    BINJS_TRY(CheckRecursionLimit(cx_));
+
+#if defined(DEBUG)
+    const BinField expected_fields[2] = { BinField::BoundNames, BinField::HasDirectEval };
+    MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
+#endif // defined(DEBUG)
+    const auto scopeKind = AssertedScopeKind::Catch;
+
+    MOZ_TRY(parseListOfAssertedBoundName(
+        scopeKind));
+
+    BINJS_MOZ_TRY_DECL(hasDirectEval, tokenizer_->readBool());
+    if (hasDirectEval) {
+        parseContext_->sc()->setHasDirectEval();
+        parseContext_->sc()->setBindingsAccessedDynamically();
+    }
+    if (hasDirectEval && parseContext_->isFunctionBox() && !parseContext_->sc()->strict()) {
+        // In non-strict mode code, direct calls to eval can
+        // add variables to the call object.
+        parseContext_->functionBox()->setHasExtensibleScope();
+    }
+    auto result = Ok();
+    return result;
+}
+
+
+/*
+ interface AssertedDeclaredName : Node {
+    [IdentifierName] string name;
+    AssertedDeclaredKind kind;
+    bool isCaptured;
+ }
+*/
+template<typename Tok> JS::Result<Ok>
+BinASTParser<Tok>::parseAssertedDeclaredName(
+        AssertedScopeKind scopeKind)
+{
+    BinKind kind;
+    BinFields fields(cx_);
+    AutoTaggedTuple guard(*tokenizer_);
+
+    MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+    if (kind != BinKind::AssertedDeclaredName) {
+        return raiseInvalidKind("AssertedDeclaredName", kind);
+    }
+    const auto start = tokenizer_->offset();
+    BINJS_MOZ_TRY_DECL(result, parseInterfaceAssertedDeclaredName(start, kind, fields,
+        scopeKind));
+    MOZ_TRY(guard.done());
+
+    return result;
+}
+
+template<typename Tok> JS::Result<Ok>
+BinASTParser<Tok>::parseInterfaceAssertedDeclaredName(const size_t start, const BinKind kind, const BinFields& fields,
+        AssertedScopeKind scopeKind)
+{
+    MOZ_ASSERT(kind == BinKind::AssertedDeclaredName);
+    BINJS_TRY(CheckRecursionLimit(cx_));
+
+#if defined(DEBUG)
+    const BinField expected_fields[3] = { BinField::Name, BinField::Kind, BinField::IsCaptured };
+    MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
+#endif // defined(DEBUG)
+    const bool allowDuplicateName = false;
+
+    RootedAtom name(cx_);
+    MOZ_TRY_VAR(name, tokenizer_->readIdentifierName());
+
+    BINJS_MOZ_TRY_DECL(kind_, parseAssertedDeclaredKind());
+
+    BINJS_MOZ_TRY_DECL(isCaptured, tokenizer_->readBool());
+    ParseContext::Scope* scope;
+    DeclarationKind declKind;
+    MOZ_TRY(getDeclaredScope(scopeKind, kind_, scope, declKind));
+    MOZ_TRY(addScopeName(scopeKind, name, scope, declKind, isCaptured, allowDuplicateName));
+    auto result = Ok();
+    return result;
+}
+
+
+/*
+ interface AssertedParameterScope : Node {
+    FrozenArray<AssertedMaybePositionalParameterName> paramNames;
+    bool hasDirectEval;
+    bool isSimpleParameterList;
+ }
+*/
+template<typename Tok> JS::Result<Ok>
+BinASTParser<Tok>::parseAssertedParameterScope(
+        MutableHandle<GCVector<JSAtom*>> positionalParams)
+{
+    BinKind kind;
+    BinFields fields(cx_);
+    AutoTaggedTuple guard(*tokenizer_);
+
+    MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+    if (kind != BinKind::AssertedParameterScope) {
+        return raiseInvalidKind("AssertedParameterScope", kind);
+    }
+    const auto start = tokenizer_->offset();
+    BINJS_MOZ_TRY_DECL(result, parseInterfaceAssertedParameterScope(start, kind, fields,
+        positionalParams));
+    MOZ_TRY(guard.done());
+
+    return result;
+}
+
+template<typename Tok> JS::Result<Ok>
+BinASTParser<Tok>::parseInterfaceAssertedParameterScope(const size_t start, const BinKind kind, const BinFields& fields,
+        MutableHandle<GCVector<JSAtom*>> positionalParams)
+{
+    MOZ_ASSERT(kind == BinKind::AssertedParameterScope);
+    BINJS_TRY(CheckRecursionLimit(cx_));
+
+#if defined(DEBUG)
+    const BinField expected_fields[3] = { BinField::ParamNames, BinField::HasDirectEval, BinField::IsSimpleParameterList };
+    MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
+#endif // defined(DEBUG)
+    const auto scopeKind = AssertedScopeKind::Parameter;
+
+    MOZ_TRY(parseListOfAssertedMaybePositionalParameterName(
+        scopeKind, positionalParams));
+
+    BINJS_MOZ_TRY_DECL(hasDirectEval, tokenizer_->readBool());
+    if (hasDirectEval) {
+        parseContext_->sc()->setHasDirectEval();
+        parseContext_->sc()->setBindingsAccessedDynamically();
+    }
+    BINJS_MOZ_TRY_DECL(isSimpleParameterList, tokenizer_->readBool());
+    (void) isSimpleParameterList;
+    if (hasDirectEval && parseContext_->isFunctionBox() && !parseContext_->sc()->strict()) {
+        // In non-strict mode code, direct calls to eval can
+        // add variables to the call object.
+        parseContext_->functionBox()->setHasExtensibleScope();
+    }
+    auto result = Ok();
+    return result;
+}
+
+template<typename Tok> JS::Result<Ok>
+BinASTParser<Tok>::parseInterfaceAssertedPositionalParameterName(const size_t start, const BinKind kind, const BinFields& fields,
+        AssertedScopeKind scopeKind,
+        MutableHandle<GCVector<JSAtom*>> positionalParams)
+{
+    MOZ_ASSERT(kind == BinKind::AssertedPositionalParameterName);
+    BINJS_TRY(CheckRecursionLimit(cx_));
+
+#if defined(DEBUG)
+    const BinField expected_fields[3] = { BinField::Index, BinField::Name, BinField::IsCaptured };
+    MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
+#endif // defined(DEBUG)
+    bool allowDuplicateName = !parseContext_->sc()->strict();
+
+    BINJS_MOZ_TRY_DECL(index, tokenizer_->readUnsignedLong());
+
+    RootedAtom name(cx_);
+    MOZ_TRY_VAR(name, tokenizer_->readIdentifierName());
+    // `positionalParams` vector can be shorter than the actual
+    // parameter length. Resize on demand.
+    // (see also ListOfAssertedMaybePositionalParameterName)
+    size_t prevLength = positionalParams.get().length();
+    if (index >= prevLength) {
+        // This is implementation limit, which is not in the spec.
+        if (index >= ARGNO_LIMIT - 1) {
+            return raiseError("AssertedPositionalParameterName.index is too big");
+        }
+        size_t newLength = index + 1;
+        BINJS_TRY(positionalParams.get().resize(newLength));
+        for (uint32_t i = prevLength; i < newLength; i++) {
+            positionalParams.get()[i] = nullptr;
+        }
+    }
+
+    if (positionalParams.get()[index]) {
+        return raiseError("AssertedPositionalParameterName has duplicate entry for the same index");
+    }
+    positionalParams.get()[index] = name;
+    BINJS_MOZ_TRY_DECL(isCaptured, tokenizer_->readBool());
+    ParseContext::Scope* scope;
+    DeclarationKind declKind;
+    MOZ_TRY(getBoundScope(scopeKind, scope, declKind));
+    MOZ_TRY(addScopeName(scopeKind, name, scope, declKind, isCaptured, allowDuplicateName));
+    auto result = Ok();
+    return result;
+}
+
+
+/*
+ interface AssertedScriptGlobalScope : Node {
+    FrozenArray<AssertedDeclaredName> declaredNames;
+    bool hasDirectEval;
+ }
+*/
+template<typename Tok> JS::Result<Ok>
+BinASTParser<Tok>::parseAssertedScriptGlobalScope()
+{
+    BinKind kind;
+    BinFields fields(cx_);
+    AutoTaggedTuple guard(*tokenizer_);
+
+    MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+    if (kind != BinKind::AssertedScriptGlobalScope) {
+        return raiseInvalidKind("AssertedScriptGlobalScope", kind);
+    }
+    const auto start = tokenizer_->offset();
+    BINJS_MOZ_TRY_DECL(result, parseInterfaceAssertedScriptGlobalScope(start, kind, fields));
+    MOZ_TRY(guard.done());
+
+    return result;
+}
+
+template<typename Tok> JS::Result<Ok>
+BinASTParser<Tok>::parseInterfaceAssertedScriptGlobalScope(const size_t start, const BinKind kind, const BinFields& fields)
+{
+    MOZ_ASSERT(kind == BinKind::AssertedScriptGlobalScope);
+    BINJS_TRY(CheckRecursionLimit(cx_));
+
+#if defined(DEBUG)
+    const BinField expected_fields[2] = { BinField::DeclaredNames, BinField::HasDirectEval };
+    MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
+#endif // defined(DEBUG)
+    const auto scopeKind = AssertedScopeKind::Global;
+
+    MOZ_TRY(parseListOfAssertedDeclaredName(
+        scopeKind));
+
+    BINJS_MOZ_TRY_DECL(hasDirectEval, tokenizer_->readBool());
+    if (hasDirectEval) {
+        parseContext_->sc()->setHasDirectEval();
+        parseContext_->sc()->setBindingsAccessedDynamically();
+    }
+    if (hasDirectEval && parseContext_->isFunctionBox() && !parseContext_->sc()->strict()) {
+        // In non-strict mode code, direct calls to eval can
+        // add variables to the call object.
+        parseContext_->functionBox()->setHasExtensibleScope();
+    }
+    auto result = Ok();
+    return result;
+}
+
+
+/*
+ interface AssertedVarScope : Node {
+    FrozenArray<AssertedDeclaredName> declaredNames;
+    bool hasDirectEval;
+ }
+*/
+template<typename Tok> JS::Result<Ok>
+BinASTParser<Tok>::parseAssertedVarScope()
+{
+    BinKind kind;
+    BinFields fields(cx_);
+    AutoTaggedTuple guard(*tokenizer_);
+
+    MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+    if (kind != BinKind::AssertedVarScope) {
+        return raiseInvalidKind("AssertedVarScope", kind);
+    }
+    const auto start = tokenizer_->offset();
+    BINJS_MOZ_TRY_DECL(result, parseInterfaceAssertedVarScope(start, kind, fields));
+    MOZ_TRY(guard.done());
+
+    return result;
+}
+
+template<typename Tok> JS::Result<Ok>
+BinASTParser<Tok>::parseInterfaceAssertedVarScope(const size_t start, const BinKind kind, const BinFields& fields)
+{
+    MOZ_ASSERT(kind == BinKind::AssertedVarScope);
+    BINJS_TRY(CheckRecursionLimit(cx_));
+
+#if defined(DEBUG)
+    const BinField expected_fields[2] = { BinField::DeclaredNames, BinField::HasDirectEval };
+    MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
+#endif // defined(DEBUG)
+    const auto scopeKind = AssertedScopeKind::Var;
+
+    MOZ_TRY(parseListOfAssertedDeclaredName(
+        scopeKind));
+
+    BINJS_MOZ_TRY_DECL(hasDirectEval, tokenizer_->readBool());
+    if (hasDirectEval) {
+        parseContext_->sc()->setHasDirectEval();
+        parseContext_->sc()->setBindingsAccessedDynamically();
+    }
+    if (hasDirectEval && parseContext_->isFunctionBox() && !parseContext_->sc()->strict()) {
+        // In non-strict mode code, direct calls to eval can
+        // add variables to the call object.
+        parseContext_->functionBox()->setHasExtensibleScope();
+    }
+    auto result = Ok();
+    return result;
+}
+
+template<typename Tok> JS::Result<ParseNode*>
+BinASTParser<Tok>::parseInterfaceAssignmentExpression(const size_t start, const BinKind kind, const BinFields& fields)
+{
+    MOZ_ASSERT(kind == BinKind::AssignmentExpression);
+    BINJS_TRY(CheckRecursionLimit(cx_));
+
+#if defined(DEBUG)
+    const BinField expected_fields[2] = { BinField::Binding, BinField::Expression };
+    MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
+#endif // defined(DEBUG)
+
+    BINJS_MOZ_TRY_DECL(binding, parseAssignmentTarget());
+
+    BINJS_MOZ_TRY_DECL(expression, parseExpression());
+
+    BINJS_TRY_DECL(result, factory_.newAssignment(ParseNodeKind::Assign, binding, expression));
+    return result;
+}
+
+template<typename Tok> JS::Result<ParseNode*>
+BinASTParser<Tok>::parseInterfaceAssignmentTargetIdentifier(const size_t start, const BinKind kind, const BinFields& fields)
+{
+    MOZ_ASSERT(kind == BinKind::AssignmentTargetIdentifier);
+    BINJS_TRY(CheckRecursionLimit(cx_));
+
+#if defined(DEBUG)
+    const BinField expected_fields[1] = { BinField::Name };
+    MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
+#endif // defined(DEBUG)
+
+    RootedAtom name(cx_);
+    MOZ_TRY_VAR(name, tokenizer_->readIdentifierName());
+
+    if (!IsIdentifier(name)) {
+        return raiseError("Invalid identifier");
+    }
+    BINJS_TRY(usedNames_.noteUse(cx_, name, parseContext_->scriptId(), parseContext_->innermostScope()->id()));
+    BINJS_TRY_DECL(result, factory_.newName(name->asPropertyName(), tokenizer_->pos(start), cx_));
+    return result;
+}
+
+template<typename Tok> JS::Result<ParseNode*>
+BinASTParser<Tok>::parseInterfaceAwaitExpression(const size_t start, const BinKind kind, const BinFields& fields)
+{
+    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 BinKind kind, const BinFields& fields)
+{
+    MOZ_ASSERT(kind == BinKind::BinaryExpression);
+    BINJS_TRY(CheckRecursionLimit(cx_));
+
+#if defined(DEBUG)
+    const BinField expected_fields[3] = { BinField::Operator, BinField::Left, BinField::Right };
+    MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
+#endif // defined(DEBUG)
+
+    BINJS_MOZ_TRY_DECL(operator_, parseBinaryOperator());
+
+    BINJS_MOZ_TRY_DECL(left, parseExpression());
+
+    BINJS_MOZ_TRY_DECL(right, parseExpression());
+
+    ParseNodeKind pnk;
+    switch (operator_) {
+      case BinaryOperator::Comma:
+        pnk = ParseNodeKind::Comma;
+        break;
+      case BinaryOperator::LogicalOr:
+        pnk = ParseNodeKind::Or;
+        break;
+      case BinaryOperator::LogicalAnd:
+        pnk = ParseNodeKind::And;
+        break;
+      case BinaryOperator::BitOr:
+        pnk = ParseNodeKind::BitOr;
+        break;
+      case BinaryOperator::BitXor:
+        pnk = ParseNodeKind::BitXor;
+        break;
+      case BinaryOperator::BitAnd:
+        pnk = ParseNodeKind::BitAnd;
+        break;
+      case BinaryOperator::Eq:
+        pnk = ParseNodeKind::Eq;
+        break;
+      case BinaryOperator::Neq:
+        pnk = ParseNodeKind::Ne;
+        break;
+      case BinaryOperator::StrictEq:
+        pnk = ParseNodeKind::StrictEq;
+        break;
+      case BinaryOperator::StrictNeq:
+        pnk = ParseNodeKind::StrictNe;
+        break;
+      case BinaryOperator::LessThan:
+        pnk = ParseNodeKind::Lt;
+        break;
+      case BinaryOperator::LeqThan:
+        pnk = ParseNodeKind::Le;
+        break;
+      case BinaryOperator::GreaterThan:
+        pnk = ParseNodeKind::Gt;
+        break;
+      case BinaryOperator::GeqThan:
+        pnk = ParseNodeKind::Ge;
+        break;
+      case BinaryOperator::In:
+        pnk = ParseNodeKind::In;
+        break;
+      case BinaryOperator::Instanceof:
+        pnk = ParseNodeKind::InstanceOf;
+        break;
+      case BinaryOperator::Lsh:
+        pnk = ParseNodeKind::Lsh;
+        break;
+      case BinaryOperator::Rsh:
+        pnk = ParseNodeKind::Rsh;
+        break;
+      case BinaryOperator::Ursh:
+        pnk = ParseNodeKind::Ursh;
+        break;
+      case BinaryOperator::Plus:
+        pnk = ParseNodeKind::Add;
+        break;
+      case BinaryOperator::Minus:
+        pnk = ParseNodeKind::Sub;
+        break;
+      case BinaryOperator::Mul:
+        pnk = ParseNodeKind::Star;
+        break;
+      case BinaryOperator::Div:
+        pnk = ParseNodeKind::Div;
+        break;
+      case BinaryOperator::Mod:
+        pnk = ParseNodeKind::Mod;
+        break;
+      case BinaryOperator::Pow:
+        pnk = ParseNodeKind::Pow;
+        break;
+    }
+
+    ParseNode* result;
+    if (left->isKind(pnk) &&
+        pnk != ParseNodeKind::Pow /* ParseNodeKind::Pow is not left-associative */)
+    {
+        // Regroup left-associative operations into lists.
+        left->template as<ListNode>().appendWithoutOrderAssumption(right);
+        result = left;
+    } else {
+        BINJS_TRY_DECL(list, factory_.newList(pnk, tokenizer_->pos(start)));
+
+        list->appendWithoutOrderAssumption(left);
+        list->appendWithoutOrderAssumption(right);
+        result = list;
+    }
+    return result;
+}
+
+
+/*
+ interface BindingIdentifier : Node {
+    [IdentifierName] string name;
+ }
+*/
+template<typename Tok> JS::Result<ParseNode*>
+BinASTParser<Tok>::parseBindingIdentifier()
+{
+    BinKind kind;
+    BinFields fields(cx_);
+    AutoTaggedTuple guard(*tokenizer_);
+
+    MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+    if (kind != BinKind::BindingIdentifier) {
+        return raiseInvalidKind("BindingIdentifier", kind);
+    }
+    const auto start = tokenizer_->offset();
+    BINJS_MOZ_TRY_DECL(result, parseInterfaceBindingIdentifier(start, kind, fields));
+    MOZ_TRY(guard.done());
+
+    return result;
+}
+
+template<typename Tok> JS::Result<ParseNode*>
+BinASTParser<Tok>::parseInterfaceBindingIdentifier(const size_t start, const BinKind kind, const BinFields& fields)
+{
+    MOZ_ASSERT(kind == BinKind::BindingIdentifier);
+    BINJS_TRY(CheckRecursionLimit(cx_));
+
+#if defined(DEBUG)
+    const BinField expected_fields[1] = { BinField::Name };
+    MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
+#endif // defined(DEBUG)
+
+    RootedAtom name(cx_);
+    MOZ_TRY_VAR(name, tokenizer_->readIdentifierName());
+
+    if (!IsIdentifier(name)) {
+        return raiseError("Invalid identifier");
+    }
+    BINJS_TRY_DECL(result, factory_.newName(name->asPropertyName(), tokenizer_->pos(start), cx_));
+    return result;
+}
+
+template<typename Tok> JS::Result<ParseNode*>
+BinASTParser<Tok>::parseInterfaceBindingWithInitializer(const size_t start, const BinKind kind, const BinFields& fields)
+{
+    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()
+{
+    BinKind kind;
+    BinFields fields(cx_);
+    AutoTaggedTuple guard(*tokenizer_);
+
+    MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+    if (kind != BinKind::Block) {
+        return raiseInvalidKind("Block", kind);
+    }
+    const auto start = tokenizer_->offset();
+    BINJS_MOZ_TRY_DECL(result, parseInterfaceBlock(start, kind, fields));
+    MOZ_TRY(guard.done());
+
+    return result;
+}
+
+template<typename Tok> JS::Result<ParseNode*>
+BinASTParser<Tok>::parseInterfaceBlock(const size_t start, const BinKind kind, const BinFields& fields)
+{
+    MOZ_ASSERT(kind == BinKind::Block);
+    BINJS_TRY(CheckRecursionLimit(cx_));
+
+#if defined(DEBUG)
+    const BinField expected_fields[2] = { BinField::Scope, BinField::Statements };
+    MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
+#endif // defined(DEBUG)
+    ParseContext::Statement stmt(parseContext_, StatementKind::Block);
+    ParseContext::Scope currentScope(cx_, parseContext_, usedNames_);
+    BINJS_TRY(currentScope.init(parseContext_));
+
+    MOZ_TRY(parseAssertedBlockScope());
+
+    BINJS_MOZ_TRY_DECL(statements, parseListOfStatement());
+
+    MOZ_TRY(checkClosedVars(currentScope));
+    BINJS_TRY_DECL(bindings, NewLexicalScopeData(cx_, currentScope, alloc_, parseContext_));
+    BINJS_TRY_DECL(result, factory_.newLexicalScope(*bindings, statements));
+    return result;
+}
+
+template<typename Tok> JS::Result<ParseNode*>
+BinASTParser<Tok>::parseInterfaceBreakStatement(const size_t start, const BinKind kind, const BinFields& fields)
+{
+    MOZ_ASSERT(kind == BinKind::BreakStatement);
+    BINJS_TRY(CheckRecursionLimit(cx_));
+
+#if defined(DEBUG)
+    const BinField expected_fields[1] = { BinField::Label };
+    MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
+#endif // defined(DEBUG)
+    RootedAtom label(cx_);
+    MOZ_TRY_VAR(label, tokenizer_->readMaybeAtom());
+
+    if (label) {
+        if (!IsIdentifier(label)) {
+            return raiseError("Invalid identifier");
+        }
+
+        auto validity = parseContext_->checkBreakStatement(label->asPropertyName());
+
+        if (validity.isErr()) {
+            switch (validity.unwrapErr()) {
+            case ParseContext::BreakStatementError::ToughBreak:
+                return raiseError(kind, "Not in a loop");
+            case ParseContext::BreakStatementError::LabelNotFound:
+                return raiseError(kind, "Label not found");
+            }
+        }
+    }
+    BINJS_TRY_DECL(result, factory_.newBreakStatement(label ? label->asPropertyName() : nullptr, tokenizer_->pos(start)));
+    return result;
+}
+
+template<typename Tok> JS::Result<ParseNode*>
+BinASTParser<Tok>::parseInterfaceCallExpression(const size_t start, const BinKind kind, const BinFields& fields)
+{
+    MOZ_ASSERT(kind == BinKind::CallExpression);
+    BINJS_TRY(CheckRecursionLimit(cx_));
+
+#if defined(DEBUG)
+    const BinField expected_fields[2] = { BinField::Callee, BinField::Arguments };
+    MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
+#endif // defined(DEBUG)
+
+    BINJS_MOZ_TRY_DECL(callee, parseExpressionOrSuper());
+
+    BINJS_MOZ_TRY_DECL(arguments, parseArguments());
+
+    auto op = JSOP_CALL;
+
+    // Try to optimize funcall and funapply at the bytecode level
+    if (PropertyName* prop = factory_.maybeDottedProperty(callee)) {
+        if (prop == cx_->names().apply) {
+            op = JSOP_FUNAPPLY;
+            if (parseContext_->isFunctionBox())
+                parseContext_->functionBox()->usesApply = true;
+        } else if (prop == cx_->names().call) {
+            op = JSOP_FUNCALL;
+        }
+    }
+
+    // Check for direct calls to `eval`.
+    if (factory_.isEvalName(callee, cx_)) {
+        if (!parseContext_->varScope().lookupDeclaredNameForAdd(cx_->names().eval)
+         && !parseContext_->innermostScope()->lookupDeclaredNameForAdd(cx_->names().eval))
+        {
+            // This is a direct call to `eval`.
+            if (!parseContext_->sc()->hasDirectEval()) {
+                return raiseMissingDirectEvalInAssertedScope();
+            }
+
+            op = parseContext_->sc()->strict() ? JSOP_STRICTEVAL : JSOP_EVAL;
+        }
+    }
+
+    BINJS_TRY_DECL(result, factory_.newCall(callee, arguments));
+    result->setOp(op);
+    return result;
+}
+
+
+/*
+ interface CatchClause : Node {
+    AssertedBoundNamesScope bindingScope;
+    Binding binding;
+    Block body;
+ }
+*/
+template<typename Tok> JS::Result<LexicalScopeNode*>
+BinASTParser<Tok>::parseCatchClause()
+{
+    BinKind kind;
+    BinFields fields(cx_);
+    AutoTaggedTuple guard(*tokenizer_);
+
+    MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+    if (kind != BinKind::CatchClause) {
+        return raiseInvalidKind("CatchClause", kind);
+    }
+    const auto start = tokenizer_->offset();
+    BINJS_MOZ_TRY_DECL(result, parseInterfaceCatchClause(start, kind, fields));
+    MOZ_TRY(guard.done());
+
+    return result;
+}
+
+template<typename Tok> JS::Result<LexicalScopeNode*>
+BinASTParser<Tok>::parseInterfaceCatchClause(const size_t start, const BinKind kind, const BinFields& fields)
+{
+    MOZ_ASSERT(kind == BinKind::CatchClause);
+    BINJS_TRY(CheckRecursionLimit(cx_));
+
+#if defined(DEBUG)
+    const BinField expected_fields[3] = { BinField::BindingScope, BinField::Binding, BinField::Body };
+    MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
+#endif // defined(DEBUG)
+    ParseContext::Statement stmt(parseContext_, StatementKind::Catch);
+    ParseContext::Scope currentScope(cx_, parseContext_, usedNames_);
+    BINJS_TRY(currentScope.init(parseContext_));
+
+    MOZ_TRY(parseAssertedBoundNamesScope());
+
+    BINJS_MOZ_TRY_DECL(binding, parseBinding());
+
+    BINJS_MOZ_TRY_DECL(body, parseBlock());
+
+    MOZ_TRY(checkClosedVars(currentScope));
+    BINJS_TRY_DECL(bindings, NewLexicalScopeData(cx_, currentScope, alloc_, parseContext_));
+    BINJS_TRY_DECL(result, factory_.newLexicalScope(*bindings, body));
+    BINJS_TRY(factory_.setupCatchScope(result, binding, body));
+    return result;
+}
+
+template<typename Tok> JS::Result<ParseNode*>
+BinASTParser<Tok>::parseInterfaceClassDeclaration(const size_t start, const BinKind kind, const BinFields& fields)
+{
+    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 BinKind kind, const BinFields& fields)
+{
+    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 BinKind kind, const BinFields& fields)
+{
+    MOZ_ASSERT(kind == BinKind::CompoundAssignmentExpression);
+    BINJS_TRY(CheckRecursionLimit(cx_));
+
+#if defined(DEBUG)
+    const BinField expected_fields[3] = { BinField::Operator, BinField::Binding, BinField::Expression };
+    MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
+#endif // defined(DEBUG)
+
+    BINJS_MOZ_TRY_DECL(operator_, parseCompoundAssignmentOperator());
+
+    BINJS_MOZ_TRY_DECL(binding, parseSimpleAssignmentTarget());
+
+    BINJS_MOZ_TRY_DECL(expression, parseExpression());
+
+    ParseNodeKind pnk;
+    switch (operator_){
+      case CompoundAssignmentOperator::PlusAssign:
+        pnk = ParseNodeKind::AddAssign;
+        break;
+      case CompoundAssignmentOperator::MinusAssign:
+        pnk = ParseNodeKind::SubAssign;
+        break;
+      case CompoundAssignmentOperator::MulAssign:
+        pnk = ParseNodeKind::MulAssign;
+        break;
+      case CompoundAssignmentOperator::DivAssign:
+        pnk = ParseNodeKind::DivAssign;
+        break;
+      case CompoundAssignmentOperator::ModAssign:
+        pnk = ParseNodeKind::ModAssign;
+        break;
+      case CompoundAssignmentOperator::PowAssign:
+        pnk = ParseNodeKind::PowAssign;
+        break;
+      case CompoundAssignmentOperator::LshAssign:
+        pnk = ParseNodeKind::LshAssign;
+        break;
+      case CompoundAssignmentOperator::RshAssign:
+        pnk = ParseNodeKind::RshAssign;
+        break;
+      case CompoundAssignmentOperator::UrshAssign:
+        pnk = ParseNodeKind::UrshAssign;
+        break;
+      case CompoundAssignmentOperator::BitOrAssign:
+        pnk = ParseNodeKind::BitOrAssign;
+        break;
+      case CompoundAssignmentOperator::BitXorAssign:
+        pnk = ParseNodeKind::BitXorAssign;
+        break;
+      case CompoundAssignmentOperator::BitAndAssign:
+        pnk = ParseNodeKind::BitAndAssign;
+        break;
+    }
+    BINJS_TRY_DECL(result, factory_.newAssignment(pnk, binding, expression));
+    return result;
+}
+
+template<typename Tok> JS::Result<ParseNode*>
+BinASTParser<Tok>::parseInterfaceComputedMemberAssignmentTarget(const size_t start, const BinKind kind, const BinFields& fields)
+{
+    MOZ_ASSERT(kind == BinKind::ComputedMemberAssignmentTarget);
+    BINJS_TRY(CheckRecursionLimit(cx_));
+
+#if defined(DEBUG)
+    const BinField expected_fields[2] = { BinField::Object, BinField::Expression };
+    MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
+#endif // defined(DEBUG)
+
+    BINJS_MOZ_TRY_DECL(object, parseExpressionOrSuper());
+
+    BINJS_MOZ_TRY_DECL(expression, parseExpression());
+
+    BINJS_TRY_DECL(result, factory_.newPropertyByValue(object, expression, tokenizer_->offset()));
+    return result;
+}
+
+template<typename Tok> JS::Result<ParseNode*>
+BinASTParser<Tok>::parseInterfaceComputedMemberExpression(const size_t start, const BinKind kind, const BinFields& fields)
+{
+    MOZ_ASSERT(kind == BinKind::ComputedMemberExpression);
+    BINJS_TRY(CheckRecursionLimit(cx_));
+
+#if defined(DEBUG)
+    const BinField expected_fields[2] = { BinField::Object, BinField::Expression };
+    MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
+#endif // defined(DEBUG)
+
+    BINJS_MOZ_TRY_DECL(object, parseExpressionOrSuper());
+
+    BINJS_MOZ_TRY_DECL(expression, parseExpression());
+
+    BINJS_TRY_DECL(result, factory_.newPropertyByValue(object, expression, tokenizer_->offset()));
+    return result;
+}
+
+template<typename Tok> JS::Result<ParseNode*>
+BinASTParser<Tok>::parseInterfaceComputedPropertyName(const size_t start, const BinKind kind, const BinFields& fields)
+{
+    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 BinKind kind, const BinFields& fields)
+{
+    MOZ_ASSERT(kind == BinKind::ConditionalExpression);
+    BINJS_TRY(CheckRecursionLimit(cx_));
+
+#if defined(DEBUG)
+    const BinField expected_fields[3] = { BinField::Test, BinField::Consequent, BinField::Alternate };
+    MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
+#endif // defined(DEBUG)
+
+    BINJS_MOZ_TRY_DECL(test, parseExpression());
+
+    BINJS_MOZ_TRY_DECL(consequent, parseExpression());
+
+    BINJS_MOZ_TRY_DECL(alternate, parseExpression());
+
+    BINJS_TRY_DECL(result, factory_.newConditional(test, consequent, alternate));
+    return result;
+}
+
+template<typename Tok> JS::Result<ParseNode*>
+BinASTParser<Tok>::parseInterfaceContinueStatement(const size_t start, const BinKind kind, const BinFields& fields)
+{
+    MOZ_ASSERT(kind == BinKind::ContinueStatement);
+    BINJS_TRY(CheckRecursionLimit(cx_));
+
+#if defined(DEBUG)
+    const BinField expected_fields[1] = { BinField::Label };
+    MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
+#endif // defined(DEBUG)
+    RootedAtom label(cx_);
+    MOZ_TRY_VAR(label, tokenizer_->readMaybeAtom());
+
+    if (label) {
+        if (!IsIdentifier(label)) {
+            return raiseError("ContinueStatement - Label MUST be an identifier");
+        }
+
+        auto validity = parseContext_->checkContinueStatement(label ? label->asPropertyName() : nullptr);
+        if (validity.isErr()) {
+            switch (validity.unwrapErr()) {
+              case ParseContext::ContinueStatementError::NotInALoop:
+                return raiseError(kind, "Not in a loop");
+              case ParseContext::ContinueStatementError::LabelNotFound:
+                return raiseError(kind, "Label not found");
+            }
+        }
+    }
+
+    BINJS_TRY_DECL(result, factory_.newContinueStatement(label ? label->asPropertyName() : nullptr, tokenizer_->pos(start)));
+    return result;
+}
+
+template<typename Tok> JS::Result<ParseNode*>
+BinASTParser<Tok>::parseInterfaceDataProperty(const size_t start, const BinKind kind, const BinFields& fields)
+{
+    MOZ_ASSERT(kind == BinKind::DataProperty);
+    BINJS_TRY(CheckRecursionLimit(cx_));
+
+#if defined(DEBUG)
+    const BinField expected_fields[2] = { BinField::Name, BinField::Expression };
+    MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
+#endif // defined(DEBUG)
+
+    BINJS_MOZ_TRY_DECL(name, parsePropertyName());
+
+    BINJS_MOZ_TRY_DECL(expression, parseExpression());
+
+    if (!factory_.isUsableAsObjectPropertyName(name)) {
+        return raiseError("DataProperty key kind");
+    }
+
+    ParseNode* result;
+    if (name->template is<NameNode>() && name->template as<NameNode>().atom() == cx_->names().proto) {
+        BINJS_TRY_VAR(result, factory_.newUnary(ParseNodeKind::MutateProto, start, expression));
+    } else {
+        BINJS_TRY_VAR(result, factory_.newObjectMethodOrPropertyDefinition(name, expression, AccessorType::None));
+    }
+    return result;
+}
+
+template<typename Tok> JS::Result<ParseNode*>
+BinASTParser<Tok>::parseInterfaceDebuggerStatement(const size_t start, const BinKind kind, const BinFields& fields)
+{
+    return raiseError("FIXME: Not implemented yet in this preview release (DebuggerStatement)");
+}
+
+
+/*
+ interface Directive : Node {
+    string rawValue;
+ }
+*/
+template<typename Tok> JS::Result<ParseNode*>
+BinASTParser<Tok>::parseDirective()
+{
+    BinKind kind;
+    BinFields fields(cx_);
+    AutoTaggedTuple guard(*tokenizer_);
+
+    MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+    if (kind != BinKind::Directive) {
+        return raiseInvalidKind("Directive", kind);
+    }
+    const auto start = tokenizer_->offset();
+    BINJS_MOZ_TRY_DECL(result, parseInterfaceDirective(start, kind, fields));
+    MOZ_TRY(guard.done());
+
+    return result;
+}
+
+template<typename Tok> JS::Result<ParseNode*>
+BinASTParser<Tok>::parseInterfaceDirective(const size_t start, const BinKind kind, const BinFields& fields)
+{
+    MOZ_ASSERT(kind == BinKind::Directive);
+    BINJS_TRY(CheckRecursionLimit(cx_));
+
+#if defined(DEBUG)
+    const BinField expected_fields[1] = { BinField::RawValue };
+    MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
+#endif // defined(DEBUG)
+
+    RootedAtom rawValue(cx_);
+    MOZ_TRY_VAR(rawValue, tokenizer_->readAtom());
+
+    TokenPos pos = tokenizer_->pos(start);
+    BINJS_TRY_DECL(result, factory_.newStringLiteral(rawValue, pos));
+    return result;
+}
+
+template<typename Tok> JS::Result<ParseNode*>
+BinASTParser<Tok>::parseInterfaceDoWhileStatement(const size_t start, const BinKind kind, const BinFields& fields)
+{
+    MOZ_ASSERT(kind == BinKind::DoWhileStatement);
+    BINJS_TRY(CheckRecursionLimit(cx_));
+
+#if defined(DEBUG)
+    const BinField expected_fields[2] = { BinField::Test, BinField::Body };
+    MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
+#endif // defined(DEBUG)
+    ParseContext::Statement stmt(parseContext_, StatementKind::DoLoop);
+
+    BINJS_MOZ_TRY_DECL(test, parseExpression());
+
+    BINJS_MOZ_TRY_DECL(body, parseStatement());
+
+    BINJS_TRY_DECL(result, factory_.newDoWhileStatement(body, test, tokenizer_->pos(start)));
+    return result;
+}
+
+template<typename Tok> JS::Result<ParseNode*>
+BinASTParser<Tok>::parseInterfaceEagerArrowExpressionWithExpression(const size_t start, const BinKind kind, const BinFields& fields)
+{
+    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 BinKind kind, const BinFields& fields)
+{
+    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 BinKind kind, const BinFields& fields)
+{
+    MOZ_ASSERT(kind == BinKind::EagerFunctionDeclaration);
+    BINJS_TRY(CheckRecursionLimit(cx_));
+
+#if defined(DEBUG)
+    const BinField expected_fields[6] = { BinField::IsAsync, BinField::IsGenerator, BinField::Name, BinField::Length, BinField::Directives, BinField::Contents };
+    MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
+#endif // defined(DEBUG)
+    const auto syntax = FunctionSyntaxKind::Statement;
+
+    BINJS_MOZ_TRY_DECL(isAsync, tokenizer_->readBool());
+    if (isAsync) {
+        return raiseError("Async function is not supported in this preview release");
+    }
+    BINJS_MOZ_TRY_DECL(isGenerator, tokenizer_->readBool());
+    if (isGenerator) {
+        return raiseError("Generator is not supported in this preview release");
+    }
+    BINJS_MOZ_TRY_DECL(name, parseBindingIdentifier());
+
+    BINJS_MOZ_TRY_DECL(length, tokenizer_->readUnsignedLong());
+
+    BINJS_MOZ_TRY_DECL(directives, parseListOfDirective());
+
+    BINJS_MOZ_TRY_DECL(funbox, buildFunctionBox(
+        isGenerator ? GeneratorKind::Generator
+                    : GeneratorKind::NotGenerator,
+        isAsync ? FunctionAsyncKind::AsyncFunction
+                : FunctionAsyncKind::SyncFunction,
+        syntax,
+        (syntax != FunctionSyntaxKind::Setter &&
+         syntax != FunctionSyntaxKind::Getter) ? name : nullptr));
+
+    forceStrictIfNecessary(funbox, directives);
+
+    // Push a new ParseContext. It will be used to parse `scope`, the arguments, the function.
+    BinParseContext funpc(cx_, this, funbox, /* newDirectives = */ nullptr);
+    BINJS_TRY(funpc.init());
+    parseContext_->functionScope().useAsVarScope(parseContext_);
+    MOZ_ASSERT(parseContext_->isFunctionBox());
+
+    ParseContext::Scope lexicalScope(cx_, parseContext_, usedNames_);
+    BINJS_TRY(lexicalScope.init(parseContext_));
+    ListNode* params;
+    ListNode* body;
+    MOZ_TRY(parseFunctionOrMethodContents(
+        length, &params, &body));
+    MOZ_TRY(prependDirectivesToBody(body, directives));
+    BINJS_TRY_DECL(lexicalScopeData, NewLexicalScopeData(cx_, lexicalScope, alloc_, parseContext_));
+    BINJS_TRY_DECL(bodyScope, factory_.newLexicalScope(*lexicalScopeData, body));
+    BINJS_MOZ_TRY_DECL(result, buildFunction(start, kind, name, params, bodyScope, funbox));
+    return result;
+}
+
+template<typename Tok> JS::Result<ParseNode*>
+BinASTParser<Tok>::parseInterfaceEagerFunctionExpression(const size_t start, const BinKind kind, const BinFields& fields)
+{
+    MOZ_ASSERT(kind == BinKind::EagerFunctionExpression);
+    BINJS_TRY(CheckRecursionLimit(cx_));
+
+#if defined(DEBUG)
+    const BinField expected_fields[6] = { BinField::IsAsync, BinField::IsGenerator, BinField::Name, BinField::Length, BinField::Directives, BinField::Contents };
+    MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
+#endif // defined(DEBUG)
+    const auto syntax = FunctionSyntaxKind::Expression;
+
+    BINJS_MOZ_TRY_DECL(isAsync, tokenizer_->readBool());
+    if (isAsync) {
+        return raiseError("Async function is not supported in this preview release");
+    }
+    BINJS_MOZ_TRY_DECL(isGenerator, tokenizer_->readBool());
+    if (isGenerator) {
+        return raiseError("Generator is not supported in this preview release");
+    }
+    BINJS_MOZ_TRY_DECL(name, parseOptionalBindingIdentifier());
+
+    BINJS_MOZ_TRY_DECL(length, tokenizer_->readUnsignedLong());
+
+    BINJS_MOZ_TRY_DECL(directives, parseListOfDirective());
+
+    BINJS_MOZ_TRY_DECL(funbox, buildFunctionBox(
+        isGenerator ? GeneratorKind::Generator
+                    : GeneratorKind::NotGenerator,
+        isAsync ? FunctionAsyncKind::AsyncFunction
+                : FunctionAsyncKind::SyncFunction,
+        syntax,
+        (syntax != FunctionSyntaxKind::Setter &&
+         syntax != FunctionSyntaxKind::Getter) ? name : nullptr));
+
+    forceStrictIfNecessary(funbox, directives);
+
+    // Push a new ParseContext. It will be used to parse `scope`, the arguments, the function.
+    BinParseContext funpc(cx_, this, funbox, /* newDirectives = */ nullptr);
+    BINJS_TRY(funpc.init());
+    parseContext_->functionScope().useAsVarScope(parseContext_);
+    MOZ_ASSERT(parseContext_->isFunctionBox());
+
+    ParseContext::Scope lexicalScope(cx_, parseContext_, usedNames_);
+    BINJS_TRY(lexicalScope.init(parseContext_));
+    ListNode* params;
+    ListNode* body;
+    MOZ_TRY(parseFunctionExpressionContents(
+        length, &params, &body));
+    MOZ_TRY(prependDirectivesToBody(body, directives));
+    BINJS_TRY_DECL(lexicalScopeData, NewLexicalScopeData(cx_, lexicalScope, alloc_, parseContext_));
+    BINJS_TRY_DECL(bodyScope, factory_.newLexicalScope(*lexicalScopeData, body));
+    BINJS_MOZ_TRY_DECL(result, buildFunction(start, kind, name, params, bodyScope, funbox));
+    return result;
+}
+
+template<typename Tok> JS::Result<ParseNode*>
+BinASTParser<Tok>::parseInterfaceEagerGetter(const size_t start, const BinKind kind, const BinFields& fields)
+{
+    MOZ_ASSERT(kind == BinKind::EagerGetter);
+    BINJS_TRY(CheckRecursionLimit(cx_));
+
+#if defined(DEBUG)
+    const BinField expected_fields[3] = { BinField::Name, BinField::Directives, BinField::Contents };
+    MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
+#endif // defined(DEBUG)
+    const auto syntax = FunctionSyntaxKind::Setter;
+    const bool isGenerator = false;
+    const bool isAsync = false;
+    const auto accessorType = AccessorType::Getter;
+    const uint32_t length = 0;
+
+    BINJS_MOZ_TRY_DECL(name, parsePropertyName());
+
+    BINJS_MOZ_TRY_DECL(directives, parseListOfDirective());
+
+    BINJS_MOZ_TRY_DECL(funbox, buildFunctionBox(
+        isGenerator ? GeneratorKind::Generator
+                    : GeneratorKind::NotGenerator,
+        isAsync ? FunctionAsyncKind::AsyncFunction
+                : FunctionAsyncKind::SyncFunction,
+        syntax,
+        (syntax != FunctionSyntaxKind::Setter &&
+         syntax != FunctionSyntaxKind::Getter) ? name : nullptr));
+
+    forceStrictIfNecessary(funbox, directives);
+
+    // Push a new ParseContext. It will be used to parse `scope`, the arguments, the function.
+    BinParseContext funpc(cx_, this, funbox, /* newDirectives = */ nullptr);
+    BINJS_TRY(funpc.init());
+    parseContext_->functionScope().useAsVarScope(parseContext_);
+    MOZ_ASSERT(parseContext_->isFunctionBox());
+
+    ParseContext::Scope lexicalScope(cx_, parseContext_, usedNames_);
+    BINJS_TRY(lexicalScope.init(parseContext_));
+    ListNode* params;
+    ListNode* body;
+    MOZ_TRY(parseGetterContents(
+        length, &params, &body));
+    MOZ_TRY(prependDirectivesToBody(body, directives));
+    BINJS_MOZ_TRY_DECL(method, buildFunction(start, kind, name, params, body, funbox));
+    BINJS_TRY_DECL(result, factory_.newObjectMethodOrPropertyDefinition(name, method, accessorType));
+    return result;
+}
+
+template<typename Tok> JS::Result<ParseNode*>
+BinASTParser<Tok>::parseInterfaceEagerMethod(const size_t start, const BinKind kind, const BinFields& fields)
+{
+    MOZ_ASSERT(kind == BinKind::EagerMethod);
+    BINJS_TRY(CheckRecursionLimit(cx_));
+
+#if defined(DEBUG)
+    const BinField expected_fields[6] = { BinField::IsAsync, BinField::IsGenerator, BinField::Name, BinField::Length, BinField::Directives, BinField::Contents };
+    MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
+#endif // defined(DEBUG)
+    const auto syntax = FunctionSyntaxKind::Method;
+    const auto accessorType = AccessorType::None;
+
+    BINJS_MOZ_TRY_DECL(isAsync, tokenizer_->readBool());
+    if (isAsync) {
+        return raiseError("Async function is not supported in this preview release");
+    }
+    BINJS_MOZ_TRY_DECL(isGenerator, tokenizer_->readBool());
+    if (isGenerator) {
+        return raiseError("Generator is not supported in this preview release");
+    }
+    BINJS_MOZ_TRY_DECL(name, parsePropertyName());
+
+    BINJS_MOZ_TRY_DECL(length, tokenizer_->readUnsignedLong());
+
+    BINJS_MOZ_TRY_DECL(directives, parseListOfDirective());
+
+    BINJS_MOZ_TRY_DECL(funbox, buildFunctionBox(
+        isGenerator ? GeneratorKind::Generator
+                    : GeneratorKind::NotGenerator,
+        isAsync ? FunctionAsyncKind::AsyncFunction
+                : FunctionAsyncKind::SyncFunction,
+        syntax,
+        (syntax != FunctionSyntaxKind::Setter &&
+         syntax != FunctionSyntaxKind::Getter) ? name : nullptr));
+
+    forceStrictIfNecessary(funbox, directives);
+
+    // Push a new ParseContext. It will be used to parse `scope`, the arguments, the function.
+    BinParseContext funpc(cx_, this, funbox, /* newDirectives = */ nullptr);
+    BINJS_TRY(funpc.init());
+    parseContext_->functionScope().useAsVarScope(parseContext_);
+    MOZ_ASSERT(parseContext_->isFunctionBox());
+
+    ParseContext::Scope lexicalScope(cx_, parseContext_, usedNames_);
+    BINJS_TRY(lexicalScope.init(parseContext_));
+    ListNode* params;
+    ListNode* body;
+    MOZ_TRY(parseFunctionOrMethodContents(
+        length, &params, &body));
+    MOZ_TRY(prependDirectivesToBody(body, directives));
+    BINJS_MOZ_TRY_DECL(method, buildFunction(start, kind, name, params, body, funbox));
+    BINJS_TRY_DECL(result, factory_.newObjectMethodOrPropertyDefinition(name, method, accessorType));
+    return result;
+}
+
+template<typename Tok> JS::Result<ParseNode*>
+BinASTParser<Tok>::parseInterfaceEagerSetter(const size_t start, const BinKind kind, const BinFields& fields)
+{
+    MOZ_ASSERT(kind == BinKind::EagerSetter);
+    BINJS_TRY(CheckRecursionLimit(cx_));
+
+#if defined(DEBUG)
+    const BinField expected_fields[4] = { BinField::Name, BinField::Length, BinField::Directives, BinField::Contents };
+    MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
+#endif // defined(DEBUG)
+    const auto syntax = FunctionSyntaxKind::Setter;
+    const bool isGenerator = false;
+    const bool isAsync = false;
+    const auto accessorType = AccessorType::Setter;
+
+    BINJS_MOZ_TRY_DECL(name, parsePropertyName());
+
+    BINJS_MOZ_TRY_DECL(length, tokenizer_->readUnsignedLong());
+
+    BINJS_MOZ_TRY_DECL(directives, parseListOfDirective());
+
+    BINJS_MOZ_TRY_DECL(funbox, buildFunctionBox(
+        isGenerator ? GeneratorKind::Generator
+                    : GeneratorKind::NotGenerator,
+        isAsync ? FunctionAsyncKind::AsyncFunction
+                : FunctionAsyncKind::SyncFunction,
+        syntax,
+        (syntax != FunctionSyntaxKind::Setter &&
+         syntax != FunctionSyntaxKind::Getter) ? name : nullptr));
+
+    forceStrictIfNecessary(funbox, directives);
+
+    // Push a new ParseContext. It will be used to parse `scope`, the arguments, the function.
+    BinParseContext funpc(cx_, this, funbox, /* newDirectives = */ nullptr);
+    BINJS_TRY(funpc.init());
+    parseContext_->functionScope().useAsVarScope(parseContext_);
+    MOZ_ASSERT(parseContext_->isFunctionBox());
+
+    ParseContext::Scope lexicalScope(cx_, parseContext_, usedNames_);
+    BINJS_TRY(lexicalScope.init(parseContext_));
+    ListNode* params;
+    ListNode* body;
+    MOZ_TRY(parseSetterContents(
+        length, &params, &body));
+    MOZ_TRY(prependDirectivesToBody(body, directives));
+    BINJS_MOZ_TRY_DECL(method, buildFunction(start, kind, name, params, body, funbox));
+    BINJS_TRY_DECL(result, factory_.newObjectMethodOrPropertyDefinition(name, method, accessorType));
+    return result;
+}
+
+template<typename Tok> JS::Result<ParseNode*>
+BinASTParser<Tok>::parseInterfaceEmptyStatement(const size_t start, const BinKind kind, const BinFields& fields)
+{
+    MOZ_ASSERT(kind == BinKind::EmptyStatement);
+    BINJS_TRY(CheckRecursionLimit(cx_));
+MOZ_TRY(tokenizer_->checkFields0(kind, fields));
+
+    BINJS_TRY_DECL(result, factory_.newEmptyStatement(tokenizer_->pos(start)));
+    return result;
+}
+
+template<typename Tok> JS::Result<ParseNode*>
+BinASTParser<Tok>::parseInterfaceExpressionStatement(const size_t start, const BinKind kind, const BinFields& fields)
+{
+    MOZ_ASSERT(kind == BinKind::ExpressionStatement);
+    BINJS_TRY(CheckRecursionLimit(cx_));
+
+#if defined(DEBUG)
+    const BinField expected_fields[1] = { BinField::Expression };
+    MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
+#endif // defined(DEBUG)
+
+    BINJS_MOZ_TRY_DECL(expression, parseExpression());
+
+    BINJS_TRY_DECL(result, factory_.newExprStatement(expression, tokenizer_->offset()));
+    return result;
+}
+
+template<typename Tok> JS::Result<ParseNode*>
+BinASTParser<Tok>::parseInterfaceForInOfBinding(const size_t start, const BinKind kind, const BinFields& fields)
+{
+    MOZ_ASSERT(kind == BinKind::ForInOfBinding);
+    BINJS_TRY(CheckRecursionLimit(cx_));
+
+#if defined(DEBUG)
+    const BinField expected_fields[2] = { BinField::Kind, BinField::Binding };
+    MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
+#endif // defined(DEBUG)
+    AutoVariableDeclarationKind kindGuard(this);
+
+    BINJS_MOZ_TRY_DECL(kind_, parseVariableDeclarationKind());
+
+    BINJS_MOZ_TRY_DECL(binding, parseBinding());
+
+    // Restored by `kindGuard`.
+    variableDeclarationKind_ = kind_;
+    MOZ_TRY(checkBinding(binding->template as<NameNode>().atom()->asPropertyName()));
+    ParseNodeKind pnk;
+    switch (kind_) {
+      case VariableDeclarationKind::Var:
+        pnk = ParseNodeKind::Var;
+        break;
+      case VariableDeclarationKind::Let:
+        return raiseError("Let is not supported in this preview release");
+      case VariableDeclarationKind::Const:
+        return raiseError("Const is not supported in this preview release");
+    }
+    BINJS_TRY_DECL(result, factory_.newDeclarationList(pnk, tokenizer_->pos(start)));
+    factory_.addList(result, binding);
+    return result;
+}
+
+template<typename Tok> JS::Result<ParseNode*>
+BinASTParser<Tok>::parseInterfaceForInStatement(const size_t start, const BinKind kind, const BinFields& fields)
+{
+    MOZ_ASSERT(kind == BinKind::ForInStatement);
+    BINJS_TRY(CheckRecursionLimit(cx_));
+
+#if defined(DEBUG)
+    const BinField expected_fields[3] = { BinField::Left, BinField::Right, BinField::Body };
+    MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
+#endif // defined(DEBUG)
+    ParseContext::Statement stmt(parseContext_, StatementKind::ForInLoop);
+
+    // Implicit scope around the `for`, used to store `for (let x in  ...)`
+    // or `for (const x in ...)`-style declarations. Detail on the
+    // declaration is stored as part of `scope`.
+    ParseContext::Scope scope(cx_, parseContext_, usedNames_);
+    BINJS_TRY(scope.init(parseContext_));
+
+    BINJS_MOZ_TRY_DECL(left, parseForInOfBindingOrAssignmentTarget());
+
+    BINJS_MOZ_TRY_DECL(right, parseExpression());
+
+    BINJS_MOZ_TRY_DECL(body, parseStatement());
+
+    BINJS_TRY_DECL(forHead, factory_.newForInOrOfHead(ParseNodeKind::ForIn, left, right, tokenizer_->pos(start)));
+    ParseNode* result;
+    BINJS_TRY_VAR(result, factory_.newForStatement(start, forHead, body, /*flags*/ 0));
+
+    if (!scope.isEmpty()) {
+        BINJS_TRY_DECL(bindings, NewLexicalScopeData(cx_, scope, alloc_, parseContext_));
+        BINJS_TRY_VAR(result, factory_.newLexicalScope(*bindings, result));
+    }
+    return result;
+}
+
+template<typename Tok> JS::Result<ParseNode*>
+BinASTParser<Tok>::parseInterfaceForOfStatement(const size_t start, const BinKind kind, const BinFields& fields)
+{
+    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 BinKind kind, const BinFields& fields)
+{
+    MOZ_ASSERT(kind == BinKind::ForStatement);
+    BINJS_TRY(CheckRecursionLimit(cx_));
+
+#if defined(DEBUG)
+    const BinField expected_fields[4] = { BinField::Init, BinField::Test, BinField::Update, BinField::Body };
+    MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
+#endif // defined(DEBUG)
+    ParseContext::Statement stmt(parseContext_, StatementKind::ForLoop);
+
+    // Implicit scope around the `for`, used to store `for (let x; ...; ...)`
+    // or `for (const x; ...; ...)`-style declarations. Detail on the
+    // declaration is stored as part of `BINJS_Scope`.
+    ParseContext::Scope scope(cx_, parseContext_, usedNames_);
+    BINJS_TRY(scope.init(parseContext_));
+
+    BINJS_MOZ_TRY_DECL(init, parseOptionalVariableDeclarationOrExpression());
+
+    BINJS_MOZ_TRY_DECL(test, parseOptionalExpression());
+
+    BINJS_MOZ_TRY_DECL(update, parseOptionalExpression());
+
+    BINJS_MOZ_TRY_DECL(body, parseStatement());
+
+    BINJS_TRY_DECL(forHead, factory_.newForHead(init, test, update, tokenizer_->pos(start)));
+    ParseNode* result;
+    BINJS_TRY_VAR(result, factory_.newForStatement(start, forHead, body, /* iflags = */ 0));
+
+    if (!scope.isEmpty()) {
+        BINJS_TRY_DECL(bindings, NewLexicalScopeData(cx_, scope, alloc_, parseContext_));
+        BINJS_TRY_VAR(result, factory_.newLexicalScope(*bindings, result));
+    }
+    return result;
+}
+
+
+/*
+ interface FormalParameters : Node {
+    FrozenArray<Parameter> items;
+    Binding? rest;
+ }
+*/
+template<typename Tok> JS::Result<ListNode*>
+BinASTParser<Tok>::parseFormalParameters()
+{
+    BinKind kind;
+    BinFields fields(cx_);
+    AutoTaggedTuple guard(*tokenizer_);
+
+    MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+    if (kind != BinKind::FormalParameters) {
+        return raiseInvalidKind("FormalParameters", kind);
+    }
+    const auto start = tokenizer_->offset();
+    BINJS_MOZ_TRY_DECL(result, parseInterfaceFormalParameters(start, kind, fields));
+    MOZ_TRY(guard.done());
+
+    return result;
+}
+
+template<typename Tok> JS::Result<ListNode*>
+BinASTParser<Tok>::parseInterfaceFormalParameters(const size_t start, const BinKind kind, const BinFields& fields)
+{
+    MOZ_ASSERT(kind == BinKind::FormalParameters);
+    BINJS_TRY(CheckRecursionLimit(cx_));
+
+#if defined(DEBUG)
+    const BinField expected_fields[2] = { BinField::Items, BinField::Rest };
+    MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
+#endif // defined(DEBUG)
+
+    BINJS_MOZ_TRY_DECL(items, parseListOfParameter());
+
+    BINJS_MOZ_TRY_DECL(rest, parseOptionalBinding());
+
+    auto result = items;
+    if (rest) {
+        return raiseError("Rest parameter is not supported in this preview release");
+    }
+    return result;
+}
+
+
+/*
+ interface FunctionExpressionContents : Node {
+    bool isFunctionNameCaptured;
+    bool isThisCaptured;
+    AssertedParameterScope parameterScope;
+    FormalParameters params;
+    AssertedVarScope bodyScope;
+    FunctionBody body;
+ }
+*/
+template<typename Tok> JS::Result<Ok>
+BinASTParser<Tok>::parseFunctionExpressionContents(
+        uint32_t funLength,
+        ListNode** paramsOut,
+        ListNode** bodyOut)
+{
+    BinKind kind;
+    BinFields fields(cx_);
+    AutoTaggedTuple guard(*tokenizer_);
+
+    MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+    if (kind != BinKind::FunctionExpressionContents) {
+        return raiseInvalidKind("FunctionExpressionContents", kind);
+    }
+    const auto start = tokenizer_->offset();
+    BINJS_MOZ_TRY_DECL(result, parseInterfaceFunctionExpressionContents(start, kind, fields,
+        funLength, paramsOut, bodyOut));
+    MOZ_TRY(guard.done());
+
+    return result;
+}
+
+template<typename Tok> JS::Result<Ok>
+BinASTParser<Tok>::parseInterfaceFunctionExpressionContents(const size_t start, const BinKind kind, const BinFields& fields,
+        uint32_t funLength,
+        ListNode** paramsOut,
+        ListNode** bodyOut)
+{
+    MOZ_ASSERT(kind == BinKind::FunctionExpressionContents);
+    BINJS_TRY(CheckRecursionLimit(cx_));
+
+#if defined(DEBUG)
+    const BinField expected_fields[6] = { BinField::IsFunctionNameCaptured, BinField::IsThisCaptured, BinField::ParameterScope, BinField::Params, BinField::BodyScope, BinField::Body };
+    MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
+#endif // defined(DEBUG)
+
+    BINJS_MOZ_TRY_DECL(isFunctionNameCaptured, tokenizer_->readBool());
+    // Per spec, isFunctionNameCaptured can be true for anonymous
+    // function.  Check isFunctionNameCaptured only for named
+    // function.
+    if (parseContext_->functionBox()->function()->isNamedLambda() &&
+        isFunctionNameCaptured)
+    {
+        captureFunctionName();
+    }
+    BINJS_MOZ_TRY_DECL(isThisCaptured, tokenizer_->readBool());
+    // TODO: Use this in BinASTParser::buildFunction.
+    (void) isThisCaptured;
+    Rooted<GCVector<JSAtom*>> positionalParams(cx_, GCVector<JSAtom*>(cx_));
+    MOZ_TRY(parseAssertedParameterScope(
+        &positionalParams));
+
+    BINJS_MOZ_TRY_DECL(params, parseFormalParameters());
+    MOZ_TRY(checkFunctionLength(funLength));
+    MOZ_TRY(checkPositionalParameterIndices(positionalParams, params));
+    MOZ_TRY(parseAssertedVarScope());
+
+    BINJS_MOZ_TRY_DECL(body, parseFunctionBody());
+
+    *paramsOut = params;
+    *bodyOut = body;
+    auto result = Ok();
+    return result;
+}
+
+
+/*
+ interface FunctionOrMethodContents : Node {
+    bool isThisCaptured;
+    AssertedParameterScope parameterScope;
+    FormalParameters params;
+    AssertedVarScope bodyScope;
+    FunctionBody body;
+ }
+*/
+template<typename Tok> JS::Result<Ok>
+BinASTParser<Tok>::parseFunctionOrMethodContents(
+        uint32_t funLength,
+        ListNode** paramsOut,
+        ListNode** bodyOut)
+{
+    BinKind kind;
+    BinFields fields(cx_);
+    AutoTaggedTuple guard(*tokenizer_);
+
+    MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+    if (kind != BinKind::FunctionOrMethodContents) {
+        return raiseInvalidKind("FunctionOrMethodContents", kind);
+    }
+    const auto start = tokenizer_->offset();
+    BINJS_MOZ_TRY_DECL(result, parseInterfaceFunctionOrMethodContents(start, kind, fields,
+        funLength, paramsOut, bodyOut));
+    MOZ_TRY(guard.done());
+
+    return result;
+}
+
+template<typename Tok> JS::Result<Ok>
+BinASTParser<Tok>::parseInterfaceFunctionOrMethodContents(const size_t start, const BinKind kind, const BinFields& fields,
+        uint32_t funLength,
+        ListNode** paramsOut,
+        ListNode** bodyOut)
+{
+    MOZ_ASSERT(kind == BinKind::FunctionOrMethodContents);
+    BINJS_TRY(CheckRecursionLimit(cx_));
+
+#if defined(DEBUG)
+    const BinField expected_fields[5] = { BinField::IsThisCaptured, BinField::ParameterScope, BinField::Params, BinField::BodyScope, BinField::Body };
+    MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
+#endif // defined(DEBUG)
+
+    BINJS_MOZ_TRY_DECL(isThisCaptured, tokenizer_->readBool());
+    // TODO: Use this in BinASTParser::buildFunction.
+    (void) isThisCaptured;
+    Rooted<GCVector<JSAtom*>> positionalParams(cx_, GCVector<JSAtom*>(cx_));
+    MOZ_TRY(parseAssertedParameterScope(
+        &positionalParams));
+
+    BINJS_MOZ_TRY_DECL(params, parseFormalParameters());
+    MOZ_TRY(checkFunctionLength(funLength));
+    MOZ_TRY(checkPositionalParameterIndices(positionalParams, params));
+    MOZ_TRY(parseAssertedVarScope());
+
+    BINJS_MOZ_TRY_DECL(body, parseFunctionBody());
+
+    *paramsOut = params;
+    *bodyOut = body;
+    auto result = Ok();
+    return result;
+}
+
+
+/*
+ interface GetterContents : Node {
+    bool isThisCaptured;
+    AssertedVarScope bodyScope;
+    FunctionBody body;
+ }
+*/
+template<typename Tok> JS::Result<Ok>
+BinASTParser<Tok>::parseGetterContents(
+        uint32_t funLength,
+        ListNode** paramsOut,
+        ListNode** bodyOut)
+{
+    BinKind kind;
+    BinFields fields(cx_);
+    AutoTaggedTuple guard(*tokenizer_);
+
+    MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+    if (kind != BinKind::GetterContents) {
+        return raiseInvalidKind("GetterContents", kind);
+    }
+    const auto start = tokenizer_->offset();
+    BINJS_MOZ_TRY_DECL(result, parseInterfaceGetterContents(start, kind, fields,
+        funLength, paramsOut, bodyOut));
+    MOZ_TRY(guard.done());
+
+    return result;
+}
+
+template<typename Tok> JS::Result<Ok>
+BinASTParser<Tok>::parseInterfaceGetterContents(const size_t start, const BinKind kind, const BinFields& fields,
+        uint32_t funLength,
+        ListNode** paramsOut,
+        ListNode** bodyOut)
+{
+    MOZ_ASSERT(kind == BinKind::GetterContents);
+    BINJS_TRY(CheckRecursionLimit(cx_));
+
+#if defined(DEBUG)
+    const BinField expected_fields[3] = { BinField::IsThisCaptured, BinField::BodyScope, BinField::Body };
+    MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
+#endif // defined(DEBUG)
+
+    BINJS_MOZ_TRY_DECL(isThisCaptured, tokenizer_->readBool());
+    // TODO: Use this in BinASTParser::buildFunction.
+    (void) isThisCaptured;
+    MOZ_TRY(parseAssertedVarScope());
+
+    BINJS_TRY_DECL(params, new_<ListNode>(ParseNodeKind::ParamsBody, tokenizer_->pos(start)));
+    BINJS_MOZ_TRY_DECL(body, parseFunctionBody());
+
+    *paramsOut = params;
+    *bodyOut = body;
+    auto result = Ok();
+    return result;
+}
+
+
+/*
+ interface IdentifierExpression : Node {
+    [IdentifierName] string name;
+ }
+*/
+template<typename Tok> JS::Result<ParseNode*>
+BinASTParser<Tok>::parseIdentifierExpression()
+{
+    BinKind kind;
+    BinFields fields(cx_);
+    AutoTaggedTuple guard(*tokenizer_);
+
+    MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+    if (kind != BinKind::IdentifierExpression) {
+        return raiseInvalidKind("IdentifierExpression", kind);
+    }
+    const auto start = tokenizer_->offset();
+    BINJS_MOZ_TRY_DECL(result, parseInterfaceIdentifierExpression(start, kind, fields));
+    MOZ_TRY(guard.done());
+
+    return result;
+}
+
+template<typename Tok> JS::Result<ParseNode*>
+BinASTParser<Tok>::parseInterfaceIdentifierExpression(const size_t start, const BinKind kind, const BinFields& fields)
+{
+    MOZ_ASSERT(kind == BinKind::IdentifierExpression);
+    BINJS_TRY(CheckRecursionLimit(cx_));
+
+#if defined(DEBUG)
+    const BinField expected_fields[1] = { BinField::Name };
+    MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
+#endif // defined(DEBUG)
+
+    RootedAtom name(cx_);
+    MOZ_TRY_VAR(name, tokenizer_->readIdentifierName());
+
+    if (!IsIdentifier(name)) {
+        return raiseError("Invalid identifier");
+    }
+    BINJS_TRY(usedNames_.noteUse(cx_, name, parseContext_->scriptId(), parseContext_->innermostScope()->id()));
+    BINJS_TRY_DECL(result, factory_.newName(name->asPropertyName(), tokenizer_->pos(start), cx_));
+    return result;
+}
+
+template<typename Tok> JS::Result<ParseNode*>
+BinASTParser<Tok>::parseInterfaceIfStatement(const size_t start, const BinKind kind, const BinFields& fields)
+{
+    MOZ_ASSERT(kind == BinKind::IfStatement);
+    BINJS_TRY(CheckRecursionLimit(cx_));
+
+#if defined(DEBUG)
+    const BinField expected_fields[3] = { BinField::Test, BinField::Consequent, BinField::Alternate };
+    MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
+#endif // defined(DEBUG)
+
+    BINJS_MOZ_TRY_DECL(test, parseExpression());
+
+    BINJS_MOZ_TRY_DECL(consequent, parseStatement());
+
+    BINJS_MOZ_TRY_DECL(alternate, parseOptionalStatement());
+
+    BINJS_TRY_DECL(result, factory_.newIfStatement(start, test, consequent, alternate));
+    return result;
+}
+
+template<typename Tok> JS::Result<ParseNode*>
+BinASTParser<Tok>::parseInterfaceLabelledStatement(const size_t start, const BinKind kind, const BinFields& fields)
+{
+    MOZ_ASSERT(kind == BinKind::LabelledStatement);
+    BINJS_TRY(CheckRecursionLimit(cx_));
+
+#if defined(DEBUG)
+    const BinField expected_fields[2] = { BinField::Label, BinField::Body };
+    MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
+#endif // defined(DEBUG)
+
+    RootedAtom label(cx_);
+    MOZ_TRY_VAR(label, tokenizer_->readAtom());
+    if (!IsIdentifier(label)) {
+        return raiseError("Invalid identifier");
+    }
+    ParseContext::LabelStatement stmt(parseContext_, label);
+    BINJS_MOZ_TRY_DECL(body, parseStatement());
+
+    BINJS_TRY_DECL(result, factory_.newLabeledStatement(label->asPropertyName(), body, start));
+    return result;
+}
+
+template<typename Tok> JS::Result<ParseNode*>
+BinASTParser<Tok>::parseInterfaceLazyArrowExpressionWithExpression(const size_t start, const BinKind kind, const BinFields& fields)
+{
+    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 BinKind kind, const BinFields& fields)
+{
+    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 BinKind kind, const BinFields& fields)
+{
+    MOZ_ASSERT(kind == BinKind::LazyFunctionDeclaration);
+    BINJS_TRY(CheckRecursionLimit(cx_));
+
+#if defined(DEBUG)
+    const BinField expected_fields[7] = { BinField::IsAsync, BinField::IsGenerator, BinField::Name, BinField::Length, BinField::Directives, BinField::ContentsSkip, BinField::Contents };
+    MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
+#endif // defined(DEBUG)
+    const auto syntax = FunctionSyntaxKind::Statement;
+
+    BINJS_MOZ_TRY_DECL(isAsync, tokenizer_->readBool());
+    if (isAsync) {
+        return raiseError("Async function is not supported in this preview release");
+    }
+    BINJS_MOZ_TRY_DECL(isGenerator, tokenizer_->readBool());
+    if (isGenerator) {
+        return raiseError("Generator is not supported in this preview release");
+    }
+    BINJS_MOZ_TRY_DECL(name, parseBindingIdentifier());
+
+    BINJS_MOZ_TRY_DECL(length, tokenizer_->readUnsignedLong());
+
+    BINJS_MOZ_TRY_DECL(directives, parseListOfDirective());
+
+    BINJS_MOZ_TRY_DECL(contentsSkip, tokenizer_->readSkippableSubTree());
+    // Don't parse the contents until we delazify.
+
+    BINJS_MOZ_TRY_DECL(funbox, buildFunctionBox(
+        isGenerator ? GeneratorKind::Generator
+                    : GeneratorKind::NotGenerator,
+        isAsync ? FunctionAsyncKind::AsyncFunction
+                : FunctionAsyncKind::SyncFunction,
+        syntax, name));
+
+    forceStrictIfNecessary(funbox, directives);
+
+    RootedFunction fun(cx_, funbox->function());
+
+    // TODO: This will become incorrect in the face of ES6 features.
+    fun->setArgCount(length);
+
+    auto skipStart = contentsSkip.startOffset();
+    BINJS_TRY_DECL(lazy, LazyScript::Create(cx_, fun, sourceObject_, parseContext_->closedOverBindingsForLazy(), parseContext_->innerFunctionsForLazy,
+                                            skipStart, skipStart + contentsSkip.length(),
+                                            skipStart, 0, skipStart, ParseGoal::Script));
+
+    if (funbox->strict()) {
+        lazy->setStrict();
+    }
+    lazy->setIsBinAST();
+    funbox->function()->initLazyScript(lazy);
+
+    BINJS_MOZ_TRY_DECL(result, makeEmptyFunctionNode(skipStart, kind, funbox));
+    return result;
+}
+
+template<typename Tok> JS::Result<ParseNode*>
+BinASTParser<Tok>::parseInterfaceLazyFunctionExpression(const size_t start, const BinKind kind, const BinFields& fields)
+{
+    MOZ_ASSERT(kind == BinKind::LazyFunctionExpression);
+    BINJS_TRY(CheckRecursionLimit(cx_));
+
+#if defined(DEBUG)
+    const BinField expected_fields[7] = { BinField::IsAsync, BinField::IsGenerator, BinField::Name, BinField::Length, BinField::Directives, BinField::ContentsSkip, BinField::Contents };
+    MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
+#endif // defined(DEBUG)
+    const auto syntax = FunctionSyntaxKind::Expression;
+
+    BINJS_MOZ_TRY_DECL(isAsync, tokenizer_->readBool());
+    if (isAsync) {
+        return raiseError("Async function is not supported in this preview release");
+    }
+    BINJS_MOZ_TRY_DECL(isGenerator, tokenizer_->readBool());
+    if (isGenerator) {
+        return raiseError("Generator is not supported in this preview release");
+    }
+    BINJS_MOZ_TRY_DECL(name, parseOptionalBindingIdentifier());
+
+    BINJS_MOZ_TRY_DECL(length, tokenizer_->readUnsignedLong());
+
+    BINJS_MOZ_TRY_DECL(directives, parseListOfDirective());
+
+    BINJS_MOZ_TRY_DECL(contentsSkip, tokenizer_->readSkippableSubTree());
+    // Don't parse the contents until we delazify.
+
+    BINJS_MOZ_TRY_DECL(funbox, buildFunctionBox(
+        isGenerator ? GeneratorKind::Generator
+                    : GeneratorKind::NotGenerator,
+        isAsync ? FunctionAsyncKind::AsyncFunction
+                : FunctionAsyncKind::SyncFunction,
+        syntax, name));
+
+    forceStrictIfNecessary(funbox, directives);
+
+    RootedFunction fun(cx_, funbox->function());
+
+    // TODO: This will become incorrect in the face of ES6 features.
+    fun->setArgCount(length);
+
+    auto skipStart = contentsSkip.startOffset();
+    BINJS_TRY_DECL(lazy, LazyScript::Create(cx_, fun, sourceObject_, parseContext_->closedOverBindingsForLazy(), parseContext_->innerFunctionsForLazy,
+                                            skipStart, skipStart + contentsSkip.length(),
+                                            skipStart, 0, skipStart, ParseGoal::Script));
+
+    if (funbox->strict()) {
+        lazy->setStrict();
+    }
+    lazy->setIsBinAST();
+    funbox->function()->initLazyScript(lazy);
+
+    BINJS_MOZ_TRY_DECL(result, makeEmptyFunctionNode(skipStart, kind, funbox));
+    return result;
+}
+
+template<typename Tok> JS::Result<ParseNode*>
+BinASTParser<Tok>::parseInterfaceLazyGetter(const size_t start, const BinKind kind, const BinFields& fields)
+{
+    return raiseError("FIXME: Not implemented yet in this preview release (LazyGetter)");
+}
+
+template<typename Tok> JS::Result<ParseNode*>
+BinASTParser<Tok>::parseInterfaceLazyMethod(const size_t start, const BinKind kind, const BinFields& fields)
+{
+    return raiseError("FIXME: Not implemented yet in this preview release (LazyMethod)");
+}
+
+template<typename Tok> JS::Result<ParseNode*>
+BinASTParser<Tok>::parseInterfaceLazySetter(const size_t start, const BinKind kind, const BinFields& fields)
+{
+    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 BinKind kind, const BinFields& fields)
+{
+    MOZ_ASSERT(kind == BinKind::LiteralBooleanExpression);
+    BINJS_TRY(CheckRecursionLimit(cx_));
+
+#if defined(DEBUG)
+    const BinField expected_fields[1] = { BinField::Value };
+    MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
+#endif // defined(DEBUG)
+
+    BINJS_MOZ_TRY_DECL(value, tokenizer_->readBool());
+
+    BINJS_TRY_DECL(result, factory_.newBooleanLiteral(value, tokenizer_->pos(start)));
+    return result;
+}
+
+template<typename Tok> JS::Result<ParseNode*>
+BinASTParser<Tok>::parseInterfaceLiteralInfinityExpression(const size_t start, const BinKind kind, const BinFields& fields)
+{
+    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 BinKind kind, const BinFields& fields)
+{
+    MOZ_ASSERT(kind == BinKind::LiteralNullExpression);
+    BINJS_TRY(CheckRecursionLimit(cx_));
+MOZ_TRY(tokenizer_->checkFields0(kind, fields));
+
+    BINJS_TRY_DECL(result, factory_.newNullLiteral(tokenizer_->pos(start)));
+    return result;
+}
+
+template<typename Tok> JS::Result<ParseNode*>
+BinASTParser<Tok>::parseInterfaceLiteralNumericExpression(const size_t start, const BinKind kind, const BinFields& fields)
+{
+    MOZ_ASSERT(kind == BinKind::LiteralNumericExpression);
+    BINJS_TRY(CheckRecursionLimit(cx_));
+
+#if defined(DEBUG)
+    const BinField expected_fields[1] = { BinField::Value };
+    MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
+#endif // defined(DEBUG)
+
+    BINJS_MOZ_TRY_DECL(value, tokenizer_->readDouble());
+
+    BINJS_TRY_DECL(result, factory_.newNumber(value, DecimalPoint::HasDecimal, tokenizer_->pos(start)));
+    return result;
+}
+
+template<typename Tok> JS::Result<ParseNode*>
+BinASTParser<Tok>::parseInterfaceLiteralPropertyName(const size_t start, const BinKind kind, const BinFields& fields)
+{
+    MOZ_ASSERT(kind == BinKind::LiteralPropertyName);
+    BINJS_TRY(CheckRecursionLimit(cx_));
+
+#if defined(DEBUG)
+    const BinField expected_fields[1] = { BinField::Value };
+    MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
+#endif // defined(DEBUG)
+
+    RootedAtom value(cx_);
+    MOZ_TRY_VAR(value, tokenizer_->readAtom());
+
+    ParseNode* result;
+    uint32_t index;
+    if (value->isIndex(&index)) {
+        BINJS_TRY_VAR(result, factory_.newNumber(index, NoDecimal, TokenPos(start, tokenizer_->offset())));
+    } else {
+        BINJS_TRY_VAR(result, factory_.newObjectLiteralPropertyName(value, tokenizer_->pos(start)));
+    }
+    return result;
+}
+
+template<typename Tok> JS::Result<ParseNode*>
+BinASTParser<Tok>::parseInterfaceLiteralRegExpExpression(const size_t start, const BinKind kind, const BinFields& fields)
+{
+    MOZ_ASSERT(kind == BinKind::LiteralRegExpExpression);
+    BINJS_TRY(CheckRecursionLimit(cx_));
+
+#if defined(DEBUG)
+    const BinField expected_fields[2] = { BinField::Pattern, BinField::Flags };
+    MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
+#endif // defined(DEBUG)
+
+    RootedAtom pattern(cx_);
+    MOZ_TRY_VAR(pattern, tokenizer_->readAtom());
+    Chars flags(cx_);
+    MOZ_TRY(tokenizer_->readChars(flags));
+
+    RegExpFlag reflags = NoFlags;
+    for (auto c : flags) {
+        if (c == 'g' && !(reflags & GlobalFlag)) {
+            reflags = RegExpFlag(reflags | GlobalFlag);
+        } else if (c == 'i' && !(reflags & IgnoreCaseFlag)) {
+            reflags = RegExpFlag(reflags | IgnoreCaseFlag);
+        } else if (c == 'm' && !(reflags & MultilineFlag)) {
+            reflags = RegExpFlag(reflags | MultilineFlag);
+        } else if (c == 'y' && !(reflags & StickyFlag)) {
+            reflags = RegExpFlag(reflags | StickyFlag);
+        } else if (c == 'u' && !(reflags & UnicodeFlag)) {
+            reflags = RegExpFlag(reflags | UnicodeFlag);
+        } else {
+            return raiseError("Invalid regexp flags");
+        }
+    }
+
+
+    Rooted<RegExpObject*> reobj(cx_);
+    BINJS_TRY_VAR(reobj, RegExpObject::create(cx_,
+        pattern,
+        reflags,
+        TenuredObject));
+
+    BINJS_TRY_DECL(result, factory_.newRegExp(reobj, tokenizer_->pos(start), *this));
+    return result;
+}
+
+template<typename Tok> JS::Result<ParseNode*>
+BinASTParser<Tok>::parseInterfaceLiteralStringExpression(const size_t start, const BinKind kind, const BinFields& fields)
+{
+    MOZ_ASSERT(kind == BinKind::LiteralStringExpression);
+    BINJS_TRY(CheckRecursionLimit(cx_));
+
+#if defined(DEBUG)
+    const BinField expected_fields[1] = { BinField::Value };
+    MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
+#endif // defined(DEBUG)
+
+    RootedAtom value(cx_);
+    MOZ_TRY_VAR(value, tokenizer_->readAtom());
+
+    BINJS_TRY_DECL(result, factory_.newStringLiteral(value, tokenizer_->pos(start)));
+    return result;
+}
+
+template<typename Tok> JS::Result<ParseNode*>
+BinASTParser<Tok>::parseInterfaceModule(const size_t start, const BinKind kind, const BinFields& fields)
+{
+    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 BinKind kind, const BinFields& fields)
+{
+    MOZ_ASSERT(kind == BinKind::NewExpression);
+    BINJS_TRY(CheckRecursionLimit(cx_));
+
+#if defined(DEBUG)
+    const BinField expected_fields[2] = { BinField::Callee, BinField::Arguments };
+    MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
+#endif // defined(DEBUG)
+
+    BINJS_MOZ_TRY_DECL(callee, parseExpression());
+
+    BINJS_MOZ_TRY_DECL(arguments, parseArguments());
+
+    BINJS_TRY_DECL(result, factory_.newNewExpression(tokenizer_->pos(start).begin, callee, arguments));
+    return result;
+}
+
+template<typename Tok> JS::Result<ParseNode*>
+BinASTParser<Tok>::parseInterfaceNewTargetExpression(const size_t start, const BinKind kind, const BinFields& fields)
+{
+    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 BinKind kind, const BinFields& fields)
+{
+    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 BinKind kind, const BinFields& fields)
+{
+    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 BinKind kind, const BinFields& fields)
+{
+    MOZ_ASSERT(kind == BinKind::ObjectExpression);
+    BINJS_TRY(CheckRecursionLimit(cx_));
+
+#if defined(DEBUG)
+    const BinField expected_fields[1] = { BinField::Properties };
+    MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
+#endif // defined(DEBUG)
+
+    BINJS_MOZ_TRY_DECL(properties, parseListOfObjectProperty());
+
+    auto result = properties;
+    return result;
+}
+
+template<typename Tok> JS::Result<ParseNode*>
+BinASTParser<Tok>::parseInterfaceReturnStatement(const size_t start, const BinKind kind, const BinFields& fields)
+{
+    MOZ_ASSERT(kind == BinKind::ReturnStatement);
+    BINJS_TRY(CheckRecursionLimit(cx_));
+
+#if defined(DEBUG)
+    const BinField expected_fields[1] = { BinField::Expression };
+    MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
+#endif // defined(DEBUG)
+    if (!parseContext_->isFunctionBox()) {
+        // Return statements are permitted only inside functions.
+        return raiseInvalidKind("Toplevel Statement", kind);
+    }
+
+    parseContext_->functionBox()->usesReturn = true;
+
+    BINJS_MOZ_TRY_DECL(expression, parseOptionalExpression());
+
+    BINJS_TRY_DECL(result, factory_.newReturnStatement(expression, tokenizer_->pos(start)));
+    return result;
+}
+
+template<typename Tok> JS::Result<ParseNode*>
+BinASTParser<Tok>::parseInterfaceScript(const size_t start, const BinKind kind, const BinFields& fields)
+{
+    MOZ_ASSERT(kind == BinKind::Script);
+    BINJS_TRY(CheckRecursionLimit(cx_));
+
+#if defined(DEBUG)
+    const BinField expected_fields[3] = { BinField::Scope, BinField::Directives, BinField::Statements };
+    MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
+#endif // defined(DEBUG)
+
+    MOZ_TRY(parseAssertedScriptGlobalScope());
+
+    BINJS_MOZ_TRY_DECL(directives, parseListOfDirective());
+    forceStrictIfNecessary(parseContext_->sc(), directives);
+    BINJS_MOZ_TRY_DECL(statements, parseListOfStatement());
+
+    MOZ_TRY(checkClosedVars(parseContext_->varScope())); MOZ_TRY(prependDirectivesToBody(/* body = */ statements, directives)); auto result = statements;
+    return result;
+}
+
+
+/*
+ interface SetterContents : Node {
+    bool isThisCaptured;
+    AssertedParameterScope parameterScope;
+    Parameter param;
+    AssertedVarScope bodyScope;
+    FunctionBody body;
+ }
+*/
+template<typename Tok> JS::Result<Ok>
+BinASTParser<Tok>::parseSetterContents(
+        uint32_t funLength,
+        ListNode** paramsOut,
+        ListNode** bodyOut)
+{
+    BinKind kind;
+    BinFields fields(cx_);
+    AutoTaggedTuple guard(*tokenizer_);
+
+    MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+    if (kind != BinKind::SetterContents) {
+        return raiseInvalidKind("SetterContents", kind);
+    }
+    const auto start = tokenizer_->offset();
+    BINJS_MOZ_TRY_DECL(result, parseInterfaceSetterContents(start, kind, fields,
+        funLength, paramsOut, bodyOut));
+    MOZ_TRY(guard.done());
+
+    return result;
+}
+
+template<typename Tok> JS::Result<Ok>
+BinASTParser<Tok>::parseInterfaceSetterContents(const size_t start, const BinKind kind, const BinFields& fields,
+        uint32_t funLength,
+        ListNode** paramsOut,
+        ListNode** bodyOut)
+{
+    MOZ_ASSERT(kind == BinKind::SetterContents);
+    BINJS_TRY(CheckRecursionLimit(cx_));
+
+#if defined(DEBUG)
+    const BinField expected_fields[5] = { BinField::IsThisCaptured, BinField::ParameterScope, BinField::Param, BinField::BodyScope, BinField::Body };
+    MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
+#endif // defined(DEBUG)
+
+    BINJS_MOZ_TRY_DECL(isThisCaptured, tokenizer_->readBool());
+    // TODO: Use this in BinASTParser::buildFunction.
+    (void) isThisCaptured;
+    Rooted<GCVector<JSAtom*>> positionalParams(cx_, GCVector<JSAtom*>(cx_));
+    MOZ_TRY(parseAssertedParameterScope(
+        &positionalParams));
+
+    BINJS_MOZ_TRY_DECL(param, parseParameter());
+    BINJS_TRY_DECL(params, new_<ListNode>(ParseNodeKind::ParamsBody, param->pn_pos));
+    factory_.addList(params, param);
+    MOZ_TRY(checkPositionalParameterIndices(positionalParams, params));
+    MOZ_TRY(parseAssertedVarScope());
+
+    BINJS_MOZ_TRY_DECL(body, parseFunctionBody());
+
+    *paramsOut = params;
+    *bodyOut = body;
+    auto result = Ok();
+    return result;
+}
+
+template<typename Tok> JS::Result<ParseNode*>
+BinASTParser<Tok>::parseInterfaceShorthandProperty(const size_t start, const BinKind kind, const BinFields& fields)
+{
+    MOZ_ASSERT(kind == BinKind::ShorthandProperty);
+    BINJS_TRY(CheckRecursionLimit(cx_));
+
+#if defined(DEBUG)
+    const BinField expected_fields[1] = { BinField::Name };
+    MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
+#endif // defined(DEBUG)
+
+    BINJS_MOZ_TRY_DECL(name, parseIdentifierExpression());
+
+    MOZ_ASSERT(name->isKind(ParseNodeKind::Name));
+    MOZ_ASSERT(!factory_.isUsableAsObjectPropertyName(name));
+    BINJS_TRY_DECL(propName, factory_.newObjectLiteralPropertyName(name->template as<NameNode>().name(), tokenizer_->pos(start)));
+
+    BINJS_TRY_DECL(result, factory_.newObjectMethodOrPropertyDefinition(propName, name, AccessorType::None));
+    result->setKind(ParseNodeKind::Shorthand);
+    return result;
+}
+
+template<typename Tok> JS::Result<ParseNode*>
+BinASTParser<Tok>::parseInterfaceSpreadElement(const size_t start, const BinKind kind, const BinFields& fields)
+{
+    return raiseError("FIXME: Not implemented yet in this preview release (SpreadElement)");
+}
+
+template<typename Tok> JS::Result<ParseNode*>
+BinASTParser<Tok>::parseInterfaceStaticMemberAssignmentTarget(const size_t start, const BinKind kind, const BinFields& fields)
+{
+    MOZ_ASSERT(kind == BinKind::StaticMemberAssignmentTarget);
+    BINJS_TRY(CheckRecursionLimit(cx_));
+
+#if defined(DEBUG)
+    const BinField expected_fields[2] = { BinField::Object, BinField::Property };
+    MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
+#endif // defined(DEBUG)
+    size_t nameStart;
+
+    BINJS_MOZ_TRY_DECL(object, parseExpressionOrSuper());
+    RootedAtom property(cx_);
+    {
+        nameStart = tokenizer_->offset();
+        MOZ_TRY_VAR(property, tokenizer_->readPropertyKey());
+
+    }
+
+    BINJS_TRY_DECL(name, factory_.newPropertyName(property->asPropertyName(), tokenizer_->pos(nameStart)));
+    BINJS_TRY_DECL(result, factory_.newPropertyAccess(object, name));
+    return result;
+}
+
+template<typename Tok> JS::Result<ParseNode*>
+BinASTParser<Tok>::parseInterfaceStaticMemberExpression(const size_t start, const BinKind kind, const BinFields& fields)
+{
+    MOZ_ASSERT(kind == BinKind::StaticMemberExpression);
+    BINJS_TRY(CheckRecursionLimit(cx_));
+
+#if defined(DEBUG)
+    const BinField expected_fields[2] = { BinField::Object, BinField::Property };
+    MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
+#endif // defined(DEBUG)
+    size_t nameStart;
+
+    BINJS_MOZ_TRY_DECL(object, parseExpressionOrSuper());
+    RootedAtom property(cx_);
+    {
+        nameStart = tokenizer_->offset();
+        MOZ_TRY_VAR(property, tokenizer_->readPropertyKey());
+
+    }
+
+    BINJS_TRY_DECL(name, factory_.newPropertyName(property->asPropertyName(), tokenizer_->pos(nameStart)));
+    BINJS_TRY_DECL(result, factory_.newPropertyAccess(object, name));
+    return result;
+}
+
+template<typename Tok> JS::Result<ParseNode*>
+BinASTParser<Tok>::parseInterfaceSuper(const size_t start, const BinKind kind, const BinFields& fields)
+{
+    return raiseError("FIXME: Not implemented yet in this preview release (Super)");
+}
+
+
+/*
+ interface SwitchCase : Node {
+    Expression test;
+    FrozenArray<Statement> consequent;
+ }
+*/
+template<typename Tok> JS::Result<CaseClause*>
+BinASTParser<Tok>::parseSwitchCase()
+{
+    BinKind kind;
+    BinFields fields(cx_);
+    AutoTaggedTuple guard(*tokenizer_);
+
+    MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+    if (kind != BinKind::SwitchCase) {
+        return raiseInvalidKind("SwitchCase", kind);
+    }
+    const auto start = tokenizer_->offset();
+    BINJS_MOZ_TRY_DECL(result, parseInterfaceSwitchCase(start, kind, fields));
+    MOZ_TRY(guard.done());
+
+    return result;
+}
+
+template<typename Tok> JS::Result<CaseClause*>
+BinASTParser<Tok>::parseInterfaceSwitchCase(const size_t start, const BinKind kind, const BinFields& fields)
+{
+    MOZ_ASSERT(kind == BinKind::SwitchCase);
+    BINJS_TRY(CheckRecursionLimit(cx_));
+
+#if defined(DEBUG)
+    const BinField expected_fields[2] = { BinField::Test, BinField::Consequent };
+    MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
+#endif // defined(DEBUG)
+
+    BINJS_MOZ_TRY_DECL(test, parseExpression());
+
+    BINJS_MOZ_TRY_DECL(consequent, parseListOfStatement());
+
+    BINJS_TRY_DECL(result, factory_.newCaseOrDefault(start, test, consequent));
+    return result;
+}
+
+
+/*
+ interface SwitchDefault : Node {
+    FrozenArray<Statement> consequent;
+ }
+*/
+template<typename Tok> JS::Result<ParseNode*>
+BinASTParser<Tok>::parseSwitchDefault()
+{
+    BinKind kind;
+    BinFields fields(cx_);
+    AutoTaggedTuple guard(*tokenizer_);
+
+    MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+    if (kind != BinKind::SwitchDefault) {
+        return raiseInvalidKind("SwitchDefault", kind);
+    }
+    const auto start = tokenizer_->offset();
+    BINJS_MOZ_TRY_DECL(result, parseInterfaceSwitchDefault(start, kind, fields));
+    MOZ_TRY(guard.done());
+
+    return result;
+}
+
+template<typename Tok> JS::Result<ParseNode*>
+BinASTParser<Tok>::parseInterfaceSwitchDefault(const size_t start, const BinKind kind, const BinFields& fields)
+{
+    MOZ_ASSERT(kind == BinKind::SwitchDefault);
+    BINJS_TRY(CheckRecursionLimit(cx_));
+
+#if defined(DEBUG)
+    const BinField expected_fields[1] = { BinField::Consequent };
+    MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
+#endif // defined(DEBUG)
+
+    BINJS_MOZ_TRY_DECL(consequent, parseListOfStatement());
+
+    BINJS_TRY_DECL(result, factory_.newCaseOrDefault(start, nullptr, consequent));
+    return result;
+}
+
+template<typename Tok> JS::Result<ParseNode*>
+BinASTParser<Tok>::parseInterfaceSwitchStatement(const size_t start, const BinKind kind, const BinFields& fields)
+{
+    MOZ_ASSERT(kind == BinKind::SwitchStatement);
+    BINJS_TRY(CheckRecursionLimit(cx_));
+
+#if defined(DEBUG)
+    const BinField expected_fields[2] = { BinField::Discriminant, BinField::Cases };
+    MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
+#endif // defined(DEBUG)
+
+    BINJS_MOZ_TRY_DECL(discriminant, parseExpression());
+
+    BINJS_MOZ_TRY_DECL(cases, parseListOfSwitchCase());
+
+    BINJS_TRY_DECL(scope, factory_.newLexicalScope(nullptr, cases));
+    BINJS_TRY_DECL(result, factory_.newSwitchStatement(start, discriminant, scope, false));
+    return result;
+}
+
+template<typename Tok> JS::Result<ParseNode*>
+BinASTParser<Tok>::parseInterfaceSwitchStatementWithDefault(const size_t start, const BinKind kind, const BinFields& fields)
+{
+    MOZ_ASSERT(kind == BinKind::SwitchStatementWithDefault);
+    BINJS_TRY(CheckRecursionLimit(cx_));
+
+#if defined(DEBUG)
+    const BinField expected_fields[4] = { BinField::Discriminant, BinField::PreDefaultCases, BinField::DefaultCase, BinField::PostDefaultCases };
+    MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
+#endif // defined(DEBUG)
+
+    BINJS_MOZ_TRY_DECL(discriminant, parseExpression());
+
+    BINJS_MOZ_TRY_DECL(preDefaultCases, parseListOfSwitchCase());
+
+    BINJS_MOZ_TRY_DECL(defaultCase, parseSwitchDefault());
+
+    BINJS_MOZ_TRY_DECL(postDefaultCases, parseListOfSwitchCase());
+
+    // Concatenate `preDefaultCase`, `defaultCase`, `postDefaultCase`
+    auto cases = preDefaultCases;
+    factory_.addList(cases, defaultCase);
+    ParseNode* iter = postDefaultCases->head();
+    while (iter) {
+        ParseNode* next = iter->pn_next;
+        factory_.addList(cases, iter);
+        iter = next;
+    }
+    BINJS_TRY_DECL(scope, factory_.newLexicalScope(nullptr, cases));
+    BINJS_TRY_DECL(result, factory_.newSwitchStatement(start, discriminant, scope, true));
+    return result;
+}
+
+template<typename Tok> JS::Result<ParseNode*>
+BinASTParser<Tok>::parseInterfaceTemplateExpression(const size_t start, const BinKind kind, const BinFields& fields)
+{
+    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 BinKind kind, const BinFields& fields)
+{
+    MOZ_ASSERT(kind == BinKind::ThisExpression);
+    BINJS_TRY(CheckRecursionLimit(cx_));
+MOZ_TRY(tokenizer_->checkFields0(kind, fields));
+
+    if (parseContext_->isFunctionBox()) {
+        parseContext_->functionBox()->usesThis = true;
+    }
+
+    TokenPos pos = tokenizer_->pos(start);
+    ParseNode* thisName(nullptr);
+    if (parseContext_->sc()->thisBinding() == ThisBinding::Function) {
+        HandlePropertyName dotThis = cx_->names().dotThis;
+        BINJS_TRY(usedNames_.noteUse(cx_, dotThis, parseContext_->scriptId(), parseContext_->innermostScope()->id()));
+        BINJS_TRY_VAR(thisName, factory_.newName(dotThis, pos, cx_));
+    }
+
+    BINJS_TRY_DECL(result, factory_.newThisLiteral(pos, thisName));
+    return result;
+}
+
+template<typename Tok> JS::Result<ParseNode*>
+BinASTParser<Tok>::parseInterfaceThrowStatement(const size_t start, const BinKind kind, const BinFields& fields)
+{
+    MOZ_ASSERT(kind == BinKind::ThrowStatement);
+    BINJS_TRY(CheckRecursionLimit(cx_));
+
+#if defined(DEBUG)
+    const BinField expected_fields[1] = { BinField::Expression };
+    MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
+#endif // defined(DEBUG)
+
+    BINJS_MOZ_TRY_DECL(expression, parseExpression());
+
+    BINJS_TRY_DECL(result, factory_.newThrowStatement(expression, tokenizer_->pos(start)));
+    return result;
+}
+
+template<typename Tok> JS::Result<ParseNode*>
+BinASTParser<Tok>::parseInterfaceTryCatchStatement(const size_t start, const BinKind kind, const BinFields& fields)
+{
+    MOZ_ASSERT(kind == BinKind::TryCatchStatement);
+    BINJS_TRY(CheckRecursionLimit(cx_));
+
+#if defined(DEBUG)
+    const BinField expected_fields[2] = { BinField::Body, BinField::CatchClause };
+    MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
+#endif // defined(DEBUG)
+    ParseNode* body;
+    {
+        ParseContext::Statement stmt(parseContext_, StatementKind::Try);
+        ParseContext::Scope scope(cx_, parseContext_, usedNames_);
+        BINJS_TRY(scope.init(parseContext_));
+        MOZ_TRY_VAR(body, parseBlock());
+
+    }
+
+    BINJS_MOZ_TRY_DECL(catchClause, parseCatchClause());
+
+    BINJS_TRY_DECL(result, factory_.newTryStatement(start, body, catchClause, /* finallyBlock = */ nullptr));
+    return result;
+}
+
+template<typename Tok> JS::Result<ParseNode*>
+BinASTParser<Tok>::parseInterfaceTryFinallyStatement(const size_t start, const BinKind kind, const BinFields& fields)
+{
+    MOZ_ASSERT(kind == BinKind::TryFinallyStatement);
+    BINJS_TRY(CheckRecursionLimit(cx_));
+
+#if defined(DEBUG)
+    const BinField expected_fields[3] = { BinField::Body, BinField::CatchClause, BinField::Finalizer };
+    MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
+#endif // defined(DEBUG)
+    ParseNode* body;
+    {
+        ParseContext::Statement stmt(parseContext_, StatementKind::Try);
+        ParseContext::Scope scope(cx_, parseContext_, usedNames_);
+        BINJS_TRY(scope.init(parseContext_));
+        MOZ_TRY_VAR(body, parseBlock());
+
+    }
+
+    BINJS_MOZ_TRY_DECL(catchClause, parseOptionalCatchClause());
+    ParseNode* finalizer;
+    {
+        ParseContext::Statement stmt(parseContext_, StatementKind::Finally);
+        ParseContext::Scope scope(cx_, parseContext_, usedNames_);
+        BINJS_TRY(scope.init(parseContext_));
+        MOZ_TRY_VAR(finalizer, parseBlock());
+
+    }
+
+    BINJS_TRY_DECL(result, factory_.newTryStatement(start, body, catchClause, finalizer));
+    return result;
+}
+
+template<typename Tok> JS::Result<ParseNode*>
+BinASTParser<Tok>::parseInterfaceUnaryExpression(const size_t start, const BinKind kind, const BinFields& fields)
+{
+    MOZ_ASSERT(kind == BinKind::UnaryExpression);
+    BINJS_TRY(CheckRecursionLimit(cx_));
+
+#if defined(DEBUG)
+    const BinField expected_fields[2] = { BinField::Operator, BinField::Operand };
+    MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
+#endif // defined(DEBUG)
+
+    BINJS_MOZ_TRY_DECL(operator_, parseUnaryOperator());
+
+    BINJS_MOZ_TRY_DECL(operand, parseExpression());
+
+    ParseNodeKind pnk;
+    switch (operator_) {
+      case UnaryOperator::Minus:
+        pnk = ParseNodeKind::Neg;
+        break;
+      case UnaryOperator::Plus:
+        pnk = ParseNodeKind::Pos;
+        break;
+      case UnaryOperator::Not:
+        pnk = ParseNodeKind::Not;
+        break;
+      case UnaryOperator::BitNot:
+        pnk = ParseNodeKind::BitNot;
+        break;
+      case UnaryOperator::Typeof: {
+        if (operand->isKind(ParseNodeKind::Name)) {
+            pnk = ParseNodeKind::TypeOfName;
+        } else {
+            pnk = ParseNodeKind::TypeOfExpr;
+        }
+        break;
+      }
+      case UnaryOperator::Void:
+        pnk = ParseNodeKind::Void;
+        break;
+      case UnaryOperator::Delete: {
+        switch (operand->getKind()) {
+          case ParseNodeKind::Name:
+            operand->setOp(JSOP_DELNAME);
+            pnk = ParseNodeKind::DeleteName;
+            break;
+          case ParseNodeKind::Dot:
+            pnk = ParseNodeKind::DeleteProp;
+            break;
+          case ParseNodeKind::Elem:
+            pnk = ParseNodeKind::DeleteElem;
+            break;
+          default:
+            pnk = ParseNodeKind::DeleteExpr;
+        }
+        break;
+      }
+    }
+    BINJS_TRY_DECL(result, factory_.newUnary(pnk, start, operand));
+    return result;
+}
+
+template<typename Tok> JS::Result<ParseNode*>
+BinASTParser<Tok>::parseInterfaceUpdateExpression(const size_t start, const BinKind kind, const BinFields& fields)
+{
+    MOZ_ASSERT(kind == BinKind::UpdateExpression);
+    BINJS_TRY(CheckRecursionLimit(cx_));
+
+#if defined(DEBUG)
+    const BinField expected_fields[3] = { BinField::IsPrefix, BinField::Operator, BinField::Operand };
+    MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
+#endif // defined(DEBUG)
+
+    BINJS_MOZ_TRY_DECL(isPrefix, tokenizer_->readBool());
+
+    BINJS_MOZ_TRY_DECL(operator_, parseUpdateOperator());
+
+    BINJS_MOZ_TRY_DECL(operand, parseSimpleAssignmentTarget());
+
+    ParseNodeKind pnk;
+    switch (operator_) {
+      case UpdateOperator::Incr:
+        pnk = isPrefix ? ParseNodeKind::PreIncrement
+                       : ParseNodeKind::PostIncrement;
+        break;
+      case UpdateOperator::Decr:
+        pnk = isPrefix ? ParseNodeKind::PreDecrement
+                       : ParseNodeKind::PostDecrement;
+        break;
+    }
+    BINJS_TRY_DECL(result, factory_.newUnary(pnk, start, operand));
+    return result;
+}
+
+template<typename Tok> JS::Result<ParseNode*>
+BinASTParser<Tok>::parseInterfaceVariableDeclaration(const size_t start, const BinKind kind, const BinFields& fields)
+{
+    MOZ_ASSERT(kind == BinKind::VariableDeclaration);
+    BINJS_TRY(CheckRecursionLimit(cx_));
+
+#if defined(DEBUG)
+    const BinField expected_fields[2] = { BinField::Kind, BinField::Declarators };
+    MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
+#endif // defined(DEBUG)
+    AutoVariableDeclarationKind kindGuard(this);
+
+    BINJS_MOZ_TRY_DECL(kind_, parseVariableDeclarationKind());
+    // Restored by `kindGuard`.
+    variableDeclarationKind_ = kind_;
+    BINJS_MOZ_TRY_DECL(declarators, parseListOfVariableDeclarator());
+
+    // By specification, the list may not be empty.
+    if (declarators->empty()) {
+        return raiseEmpty("VariableDeclaration");
+    }
+
+    ParseNodeKind pnk;
+    switch (kind_) {
+      case VariableDeclarationKind::Var:
+        pnk = ParseNodeKind::Var;
+        break;
+      case VariableDeclarationKind::Let:
+        return raiseError("Let is not supported in this preview release");
+      case VariableDeclarationKind::Const:
+        return raiseError("Const is not supported in this preview release");
+    }
+    declarators->setKind(pnk);
+    auto result = declarators;
+    return result;
+}
+
+
+/*
+ interface VariableDeclarator : Node {
+    Binding binding;
+    Expression? init;
+ }
+*/
+template<typename Tok> JS::Result<ParseNode*>
+BinASTParser<Tok>::parseVariableDeclarator()
+{
+    BinKind kind;
+    BinFields fields(cx_);
+    AutoTaggedTuple guard(*tokenizer_);
+
+    MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+    if (kind != BinKind::VariableDeclarator) {
+        return raiseInvalidKind("VariableDeclarator", kind);
+    }
+    const auto start = tokenizer_->offset();
+    BINJS_MOZ_TRY_DECL(result, parseInterfaceVariableDeclarator(start, kind, fields));
+    MOZ_TRY(guard.done());
+
+    return result;
+}
+
+template<typename Tok> JS::Result<ParseNode*>
+BinASTParser<Tok>::parseInterfaceVariableDeclarator(const size_t start, const BinKind kind, const BinFields& fields)
+{
+    MOZ_ASSERT(kind == BinKind::VariableDeclarator);
+    BINJS_TRY(CheckRecursionLimit(cx_));
+
+#if defined(DEBUG)
+    const BinField expected_fields[2] = { BinField::Binding, BinField::Init };
+    MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
+#endif // defined(DEBUG)
+
+    BINJS_MOZ_TRY_DECL(binding, parseBinding());
+
+    BINJS_MOZ_TRY_DECL(init, parseOptionalExpression());
+
+    ParseNode* result;
+    if (binding->isKind(ParseNodeKind::Name)) {
+        // `var foo [= bar]``
+        NameNode* bindingNameNode = &binding->template as<NameNode>();
+        MOZ_TRY(checkBinding(bindingNameNode->atom()->asPropertyName()));
+        result = bindingNameNode;
+        if (init) {
+            BINJS_TRY(factory_.finishInitializerAssignment(bindingNameNode, init));
+        }
+    } else {
+        // `var pattern = bar`
+        if (!init) {
+            // Here, `init` is required.
+            return raiseMissingField("VariableDeclarator (with non-trivial pattern)", BinField::Init);
+        }
+
+        MOZ_CRASH("Unimplemented: AssertedScope check for BindingPattern variable declaration");
+        BINJS_TRY_VAR(result, factory_.newAssignment(ParseNodeKind::Assign, binding, init));
+    }
+    return result;
+}
+
+template<typename Tok> JS::Result<ParseNode*>
+BinASTParser<Tok>::parseInterfaceWhileStatement(const size_t start, const BinKind kind, const BinFields& fields)
+{
+    MOZ_ASSERT(kind == BinKind::WhileStatement);
+    BINJS_TRY(CheckRecursionLimit(cx_));
+
+#if defined(DEBUG)
+    const BinField expected_fields[2] = { BinField::Test, BinField::Body };
+    MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
+#endif // defined(DEBUG)
+    ParseContext::Statement stmt(parseContext_, StatementKind::WhileLoop);
+
+    BINJS_MOZ_TRY_DECL(test, parseExpression());
+
+    BINJS_MOZ_TRY_DECL(body, parseStatement());
+
+    BINJS_TRY_DECL(result, factory_.newWhileStatement(start, test, body));
+    return result;
+}
+
+template<typename Tok> JS::Result<ParseNode*>
+BinASTParser<Tok>::parseInterfaceWithStatement(const size_t start, const BinKind kind, const BinFields& fields)
+{
+    MOZ_ASSERT(kind == BinKind::WithStatement);
+    BINJS_TRY(CheckRecursionLimit(cx_));
+
+#if defined(DEBUG)
+    const BinField expected_fields[2] = { BinField::Object, BinField::Body };
+    MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
+#endif // defined(DEBUG)
+
+    BINJS_MOZ_TRY_DECL(object, parseExpression());
+
+    ParseContext::Statement stmt(parseContext_, StatementKind::With);
+    BINJS_MOZ_TRY_DECL(body, parseStatement());
+
+    parseContext_->sc()->setBindingsAccessedDynamically();
+    BINJS_TRY_DECL(result, factory_.newWithStatement(start, object, body));
+    return result;
+}
+
+template<typename Tok> JS::Result<ParseNode*>
+BinASTParser<Tok>::parseInterfaceYieldExpression(const size_t start, const BinKind kind, const BinFields& fields)
+{
+    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 BinKind kind, const BinFields& fields)
+{
+    return raiseError("FIXME: Not implemented yet in this preview release (YieldStarExpression)");
+}
+
+
+
+// ----- String enums (autogenerated, by lexicographical order)
+/*
+enum AssertedDeclaredKind {
+    "var",
+    "non-const lexical",
+    "const lexical"
+};
+*/
+template<typename Tok> JS::Result<typename BinASTParser<Tok>::AssertedDeclaredKind>
+BinASTParser<Tok>::parseAssertedDeclaredKind()
+{
+    BINJS_MOZ_TRY_DECL(variant, tokenizer_->readVariant());
+
+    switch (variant) {
+    case BinVariant::AssertedDeclaredKindOrVariableDeclarationKindVar:
+        return AssertedDeclaredKind::Var;
+    case BinVariant::AssertedDeclaredKindNonConstLexical:
+        return AssertedDeclaredKind::NonConstLexical;
+    case BinVariant::AssertedDeclaredKindConstLexical:
+        return AssertedDeclaredKind::ConstLexical;
+      default:
+        return raiseInvalidVariant("AssertedDeclaredKind", variant);
+    }
+}
+
+/*
+enum BinaryOperator {
+    ",",
+    "||",
+    "&&",
+    "|",
+    "^",
+    "&",
+    "==",
+    "!=",
+    "===",
+    "!==",
+    "<",
+    "<=",
+    ">",
+    ">=",
+    "in",
+    "instanceof",
+    "<<",
+    ">>",
+    ">>>",
+    "+",
+    "-",
+    "*",
+    "/",
+    "%",
+    "**"
+};
+*/
+template<typename Tok> JS::Result<typename BinASTParser<Tok>::BinaryOperator>
+BinASTParser<Tok>::parseBinaryOperator()
+{
+    BINJS_MOZ_TRY_DECL(variant, tokenizer_->readVariant());
+
+    switch (variant) {
+    case BinVariant::BinaryOperatorComma:
+        return BinaryOperator::Comma;
+    case BinVariant::BinaryOperatorLogicalOr:
+        return BinaryOperator::LogicalOr;
+    case BinVariant::BinaryOperatorLogicalAnd:
+        return BinaryOperator::LogicalAnd;
+    case BinVariant::BinaryOperatorBitOr:
+        return BinaryOperator::BitOr;
+    case BinVariant::BinaryOperatorBitXor:
+        return BinaryOperator::BitXor;
+    case BinVariant::BinaryOperatorBitAnd:
+        return BinaryOperator::BitAnd;
+    case BinVariant::BinaryOperatorEq:
+        return BinaryOperator::Eq;
+    case BinVariant::BinaryOperatorNeq:
+        return BinaryOperator::Neq;
+    case BinVariant::BinaryOperatorStrictEq:
+        return BinaryOperator::StrictEq;
+    case BinVariant::BinaryOperatorStrictNeq:
+        return BinaryOperator::StrictNeq;
+    case BinVariant::BinaryOperatorLessThan:
+        return BinaryOperator::LessThan;
+    case BinVariant::BinaryOperatorLeqThan:
+        return BinaryOperator::LeqThan;
+    case BinVariant::BinaryOperatorGreaterThan:
+        return BinaryOperator::GreaterThan;
+    case BinVariant::BinaryOperatorGeqThan:
+        return BinaryOperator::GeqThan;
+    case BinVariant::BinaryOperatorIn:
+        return BinaryOperator::In;
+    case BinVariant::BinaryOperatorInstanceof:
+        return BinaryOperator::Instanceof;
+    case BinVariant::BinaryOperatorLsh:
+        return BinaryOperator::Lsh;
+    case BinVariant::BinaryOperatorRsh:
+        return BinaryOperator::Rsh;
+    case BinVariant::BinaryOperatorUrsh:
+        return BinaryOperator::Ursh;
+    case BinVariant::BinaryOperatorOrUnaryOperatorPlus:
+        return BinaryOperator::Plus;
+    case BinVariant::BinaryOperatorOrUnaryOperatorMinus:
+        return BinaryOperator::Minus;
+    case BinVariant::BinaryOperatorMul:
+        return BinaryOperator::Mul;
+    case BinVariant::BinaryOperatorDiv:
+        return BinaryOperator::Div;
+    case BinVariant::BinaryOperatorMod:
+        return BinaryOperator::Mod;
+    case BinVariant::BinaryOperatorPow:
+        return BinaryOperator::Pow;
+      default:
+        return raiseInvalidVariant("BinaryOperator", variant);
+    }
+}
+
+/*
+enum CompoundAssignmentOperator {
+    "+=",
+    "-=",
+    "*=",
+    "/=",
+    "%=",
+    "**=",
+    "<<=",
+    ">>=",
+    ">>>=",
+    "|=",
+    "^=",
+    "&="
+};
+*/
+template<typename Tok> JS::Result<typename BinASTParser<Tok>::CompoundAssignmentOperator>
+BinASTParser<Tok>::parseCompoundAssignmentOperator()
+{
+    BINJS_MOZ_TRY_DECL(variant, tokenizer_->readVariant());
+
+    switch (variant) {
+    case BinVariant::CompoundAssignmentOperatorPlusAssign:
+        return CompoundAssignmentOperator::PlusAssign;
+    case BinVariant::CompoundAssignmentOperatorMinusAssign:
+        return CompoundAssignmentOperator::MinusAssign;
+    case BinVariant::CompoundAssignmentOperatorMulAssign:
+        return CompoundAssignmentOperator::MulAssign;
+    case BinVariant::CompoundAssignmentOperatorDivAssign:
+        return CompoundAssignmentOperator::DivAssign;
+    case BinVariant::CompoundAssignmentOperatorModAssign:
+        return CompoundAssignmentOperator::ModAssign;
+    case BinVariant::CompoundAssignmentOperatorPowAssign:
+        return CompoundAssignmentOperator::PowAssign;
+    case BinVariant::CompoundAssignmentOperatorLshAssign:
+        return CompoundAssignmentOperator::LshAssign;
+    case BinVariant::CompoundAssignmentOperatorRshAssign:
+        return CompoundAssignmentOperator::RshAssign;
+    case BinVariant::CompoundAssignmentOperatorUrshAssign:
+        return CompoundAssignmentOperator::UrshAssign;
+    case BinVariant::CompoundAssignmentOperatorBitOrAssign:
+        return CompoundAssignmentOperator::BitOrAssign;
+    case BinVariant::CompoundAssignmentOperatorBitXorAssign:
+        return CompoundAssignmentOperator::BitXorAssign;
+    case BinVariant::CompoundAssignmentOperatorBitAndAssign:
+        return CompoundAssignmentOperator::BitAndAssign;
+      default:
+        return raiseInvalidVariant("CompoundAssignmentOperator", variant);
+    }
+}
+
+/*
+enum UnaryOperator {
+    "+",
+    "-",
+    "!",
+    "~",
+    "typeof",
+    "void",
+    "delete"
+};
+*/
+template<typename Tok> JS::Result<typename BinASTParser<Tok>::UnaryOperator>
+BinASTParser<Tok>::parseUnaryOperator()
+{
+    BINJS_MOZ_TRY_DECL(variant, tokenizer_->readVariant());
+
+    switch (variant) {
+    case BinVariant::BinaryOperatorOrUnaryOperatorPlus:
+        return UnaryOperator::Plus;
+    case BinVariant::BinaryOperatorOrUnaryOperatorMinus:
+        return UnaryOperator::Minus;
+    case BinVariant::UnaryOperatorNot:
+        return UnaryOperator::Not;
+    case BinVariant::UnaryOperatorBitNot:
+        return UnaryOperator::BitNot;
+    case BinVariant::UnaryOperatorTypeof:
+        return UnaryOperator::Typeof;
+    case BinVariant::UnaryOperatorVoid:
+        return UnaryOperator::Void;
+    case BinVariant::UnaryOperatorDelete:
+        return UnaryOperator::Delete;
+      default:
+        return raiseInvalidVariant("UnaryOperator", variant);
+    }
+}
+
+/*
+enum UpdateOperator {
+    "++",
+    "--"
+};
+*/
+template<typename Tok> JS::Result<typename BinASTParser<Tok>::UpdateOperator>
+BinASTParser<Tok>::parseUpdateOperator()
+{
+    BINJS_MOZ_TRY_DECL(variant, tokenizer_->readVariant());
+
+    switch (variant) {
+    case BinVariant::UpdateOperatorIncr:
+        return UpdateOperator::Incr;
+    case BinVariant::UpdateOperatorDecr:
+        return UpdateOperator::Decr;
+      default:
+        return raiseInvalidVariant("UpdateOperator", variant);
+    }
+}
+
+/*
+enum VariableDeclarationKind {
+    "var",
+    "let",
+    "const"
+};
+*/
+template<typename Tok> JS::Result<typename BinASTParser<Tok>::VariableDeclarationKind>
+BinASTParser<Tok>::parseVariableDeclarationKind()
+{
+    BINJS_MOZ_TRY_DECL(variant, tokenizer_->readVariant());
+
+    switch (variant) {
+    case BinVariant::AssertedDeclaredKindOrVariableDeclarationKindVar:
+        return VariableDeclarationKind::Var;
+    case BinVariant::VariableDeclarationKindLet:
+        return VariableDeclarationKind::Let;
+    case BinVariant::VariableDeclarationKindConst:
+        return VariableDeclarationKind::Const;
+      default:
+        return raiseInvalidVariant("VariableDeclarationKind", variant);
+    }
+}
+
+
+
+// ----- Lists (autogenerated, by lexicographical order)
+
+template<typename Tok> JS::Result<ParseNode*>
+BinASTParser<Tok>::parseArguments()
+{
+    uint32_t length;
+    AutoList guard(*tokenizer_);
+
+    const auto start = tokenizer_->offset();
+    MOZ_TRY(tokenizer_->enterList(length, guard));
+    BINJS_TRY_DECL(result, factory_.newList(ParseNodeKind::Arguments, tokenizer_->pos(start)));
+
+    for (uint32_t i = 0; i < length; ++i) {
+        BINJS_MOZ_TRY_DECL(item, parseSpreadElementOrExpression());
+        factory_.addList(/* list = */ result, /* kid = */ item);
+    }
+
+    MOZ_TRY(guard.done());
+    return result;
+}
+
+template<typename Tok> JS::Result<ListNode*>
+BinASTParser<Tok>::parseFunctionBody()
+{
+    uint32_t length;
+    AutoList guard(*tokenizer_);
+
+    const auto start = tokenizer_->offset();
+    MOZ_TRY(tokenizer_->enterList(length, guard));
+    BINJS_TRY_DECL(result, factory_.newStatementList(tokenizer_->pos(start)));
+
+    for (uint32_t i = 0; i < length; ++i) {
+        BINJS_MOZ_TRY_DECL(item, parseStatement());
+        factory_.addStatementToList(result, item);
+    }
+
+    MOZ_TRY(guard.done());
+    return result;
+}
+
+template<typename Tok> JS::Result<Ok>
+BinASTParser<Tok>::parseListOfAssertedBoundName(
+        AssertedScopeKind scopeKind)
+{
+    uint32_t length;
+    AutoList guard(*tokenizer_);
+
+    const auto start = tokenizer_->offset();
+    MOZ_TRY(tokenizer_->enterList(length, guard));
+    (void) start;
+    auto result = Ok();
+
+    for (uint32_t i = 0; i < length; ++i) {
+        MOZ_TRY(parseAssertedBoundName(
+            scopeKind));
+        // Nothing to do here.
+    }
+
+    MOZ_TRY(guard.done());
+    return result;
+}
+
+template<typename Tok> JS::Result<Ok>
+BinASTParser<Tok>::parseListOfAssertedDeclaredName(
+        AssertedScopeKind scopeKind)
+{
+    uint32_t length;
+    AutoList guard(*tokenizer_);
+
+    const auto start = tokenizer_->offset();
+    MOZ_TRY(tokenizer_->enterList(length, guard));
+    (void) start;
+    auto result = Ok();
+
+    for (uint32_t i = 0; i < length; ++i) {
+        MOZ_TRY(parseAssertedDeclaredName(
+            scopeKind));
+        // Nothing to do here.
+    }
+
+    MOZ_TRY(guard.done());
+    return result;
+}
+
+template<typename Tok> JS::Result<Ok>
+BinASTParser<Tok>::parseListOfAssertedMaybePositionalParameterName(
+        AssertedScopeKind scopeKind,
+        MutableHandle<GCVector<JSAtom*>> positionalParams)
+{
+    uint32_t length;
+    AutoList guard(*tokenizer_);
+
+    const auto start = tokenizer_->offset();
+    MOZ_TRY(tokenizer_->enterList(length, guard));
+    (void) start;
+    auto result = Ok();
+    // This list contains also destructuring parameters, and the number of
+    // list items can be greater than the actual parameters, or more than
+    // ARGNO_LIMIT even if the number of parameters fits into ARGNO_LIMIT.
+    // Also, the number of parameters can be greater than this list's length
+    // if one of destructuring parameter is empty.
+    //
+    // We resize `positionalParams` vector on demand, to keep the vector
+    // length match to the known maximum positional parameter index + 1.
+
+    for (uint32_t i = 0; i < length; ++i) {
+        MOZ_TRY(parseAssertedMaybePositionalParameterName(
+            scopeKind, positionalParams));
+        // Nothing to do here.
+    }
+
+    MOZ_TRY(guard.done());
+    return result;
+}
+
+template<typename Tok> JS::Result<ListNode*>
+BinASTParser<Tok>::parseListOfDirective()
+{
+    uint32_t length;
+    AutoList guard(*tokenizer_);
+
+    const auto start = tokenizer_->offset();
+    MOZ_TRY(tokenizer_->enterList(length, guard));
+    BINJS_TRY_DECL(result, factory_.newStatementList(tokenizer_->pos(start)));
+
+    for (uint32_t i = 0; i < length; ++i) {
+        BINJS_MOZ_TRY_DECL(item, parseDirective());
+        factory_.addStatementToList(result, item);
+    }
+
+    MOZ_TRY(guard.done());
+    return result;
+}
+
+template<typename Tok> JS::Result<ListNode*>
+BinASTParser<Tok>::parseListOfObjectProperty()
+{
+    uint32_t length;
+    AutoList guard(*tokenizer_);
+
+    const auto start = tokenizer_->offset();
+    MOZ_TRY(tokenizer_->enterList(length, guard));
+    BINJS_TRY_DECL(result, factory_.newObjectLiteral(start));
+
+    for (uint32_t i = 0; i < length; ++i) {
+        BINJS_MOZ_TRY_DECL(item, parseObjectProperty());
+        if (!item->isConstant())
+            result->setHasNonConstInitializer();
+        result->appendWithoutOrderAssumption(item);
+    }
+
+    MOZ_TRY(guard.done());
+    return result;
+}
+
+template<typename Tok> JS::Result<ListNode*>
+BinASTParser<Tok>::parseListOfOptionalSpreadElementOrExpression()
+{
+    uint32_t length;
+    AutoList guard(*tokenizer_);
+
+    const auto start = tokenizer_->offset();
+    MOZ_TRY(tokenizer_->enterList(length, guard));
+    BINJS_TRY_DECL(result, factory_.newArrayLiteral(start));
+
+    for (uint32_t i = 0; i < length; ++i) {
+        BINJS_MOZ_TRY_DECL(item, parseOptionalSpreadElementOrExpression());
+        if (item) {
+            factory_.addArrayElement(result, item); // Infallible.
+        } else {
+            BINJS_TRY(factory_.addElision(result, tokenizer_->pos(start)));
+        }
+    }
+
+    MOZ_TRY(guard.done());
+    return result;
+}
+
+template<typename Tok> JS::Result<ListNode*>
+BinASTParser<Tok>::parseListOfParameter()
+{
+    uint32_t length;
+    AutoList guard(*tokenizer_);
+
+    const auto start = tokenizer_->offset();
+    MOZ_TRY(tokenizer_->enterList(length, guard));
+    BINJS_TRY_DECL(result, new_<ListNode>(ParseNodeKind::ParamsBody, tokenizer_->pos(start)));
+
+    for (uint32_t i = 0; i < length; ++i) {
+        BINJS_MOZ_TRY_DECL(item, parseParameter());
+        factory_.addList(/* list = */ result, /* kid = */ item);
+    }
+
+    MOZ_TRY(guard.done());
+    return result;
+}
+
+template<typename Tok> JS::Result<ListNode*>
+BinASTParser<Tok>::parseListOfStatement()
+{
+    uint32_t length;
+    AutoList guard(*tokenizer_);
+
+    const auto start = tokenizer_->offset();
+    MOZ_TRY(tokenizer_->enterList(length, guard));
+    BINJS_TRY_DECL(result, factory_.newStatementList(tokenizer_->pos(start)));
+
+    for (uint32_t i = 0; i < length; ++i) {
+        BINJS_MOZ_TRY_DECL(item, parseStatement());
+        factory_.addStatementToList(result, item);
+    }
+
+    MOZ_TRY(guard.done());
+    return result;
+}
+
+template<typename Tok> JS::Result<ListNode*>
+BinASTParser<Tok>::parseListOfSwitchCase()
+{
+    uint32_t length;
+    AutoList guard(*tokenizer_);
+
+    const auto start = tokenizer_->offset();
+    MOZ_TRY(tokenizer_->enterList(length, guard));
+    BINJS_TRY_DECL(result, factory_.newStatementList(tokenizer_->pos(start)));
+
+    for (uint32_t i = 0; i < length; ++i) {
+        BINJS_MOZ_TRY_DECL(item, parseSwitchCase());
+        factory_.addCaseStatementToList(result, item);
+    }
+
+    MOZ_TRY(guard.done());
+    return result;
+}
+
+template<typename Tok> JS::Result<ListNode*>
+BinASTParser<Tok>::parseListOfVariableDeclarator()
+{
+    uint32_t length;
+    AutoList guard(*tokenizer_);
+
+    const auto start = tokenizer_->offset();
+    MOZ_TRY(tokenizer_->enterList(length, guard));
+    BINJS_TRY_DECL(result, factory_.newDeclarationList(ParseNodeKind::Const /*Placeholder*/,
+        tokenizer_->pos(start)));
+
+    for (uint32_t i = 0; i < length; ++i) {
+        BINJS_MOZ_TRY_DECL(item, parseVariableDeclarator());
+        result->appendWithoutOrderAssumption(item);
+    }
+
+    MOZ_TRY(guard.done());
+    return result;
+}
+
+
+    // ----- Default values (by lexicographical order)
+template<typename Tok> JS::Result<ParseNode*>
+BinASTParser<Tok>::parseOptionalBinding()
+{
+    BinKind kind;
+    BinFields fields(cx_);
+    AutoTaggedTuple guard(*tokenizer_);
+
+    MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+    ParseNode* result;
+    if (kind == BinKind::_Null) {
+        result = nullptr;
+    } else {
+        const auto start = tokenizer_->offset();
+        MOZ_TRY_VAR(result, parseSumBinding(start, kind, fields));
+    }
+    MOZ_TRY(guard.done());
+
+    return result;
+}
+
+template<typename Tok> JS::Result<ParseNode*>
+BinASTParser<Tok>::parseOptionalBindingIdentifier()
+{
+    BinKind kind;
+    BinFields fields(cx_);
+    AutoTaggedTuple guard(*tokenizer_);
+
+    MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+    ParseNode* result;
+    if (kind == BinKind::_Null) {
+        result = nullptr;
+    } else if (kind == BinKind::BindingIdentifier) {
+        const auto start = tokenizer_->offset();
+        MOZ_TRY_VAR(result, parseInterfaceBindingIdentifier(start, kind, fields));
+    } else {
+        return raiseInvalidKind("BindingIdentifier", kind);
+    }
+    MOZ_TRY(guard.done());
+
+    return result;
+}
+
+template<typename Tok> JS::Result<LexicalScopeNode*>
+BinASTParser<Tok>::parseOptionalCatchClause()
+{
+    BinKind kind;
+    BinFields fields(cx_);
+    AutoTaggedTuple guard(*tokenizer_);
+
+    MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+    LexicalScopeNode* result;
+    if (kind == BinKind::_Null) {
+        result = nullptr;
+    } else if (kind == BinKind::CatchClause) {
+        const auto start = tokenizer_->offset();
+        MOZ_TRY_VAR(result, parseInterfaceCatchClause(start, kind, fields));
+    } else {
+        return raiseInvalidKind("CatchClause", kind);
+    }
+    MOZ_TRY(guard.done());
+
+    return result;
+}
+
+template<typename Tok> JS::Result<ParseNode*>
+BinASTParser<Tok>::parseOptionalExpression()
+{
+    BinKind kind;
+    BinFields fields(cx_);
+    AutoTaggedTuple guard(*tokenizer_);
+
+    MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+    ParseNode* result;
+    if (kind == BinKind::_Null) {
+        result = nullptr;
+    } else {
+        const auto start = tokenizer_->offset();
+        MOZ_TRY_VAR(result, parseSumExpression(start, kind, fields));
+    }
+    MOZ_TRY(guard.done());
+
+    return result;
+}
+
+template<typename Tok> JS::Result<ParseNode*>
+BinASTParser<Tok>::parseOptionalSpreadElementOrExpression()
+{
+    BinKind kind;
+    BinFields fields(cx_);
+    AutoTaggedTuple guard(*tokenizer_);
+
+    MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+    ParseNode* result;
+    if (kind == BinKind::_Null) {
+        result = nullptr;
+    } else {
+        const auto start = tokenizer_->offset();
+        MOZ_TRY_VAR(result, parseSumSpreadElementOrExpression(start, kind, fields));
+    }
+    MOZ_TRY(guard.done());
+
+    return result;
+}
+
+template<typename Tok> JS::Result<ParseNode*>
+BinASTParser<Tok>::parseOptionalStatement()
+{
+    BinKind kind;
+    BinFields fields(cx_);
+    AutoTaggedTuple guard(*tokenizer_);
+
+    MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+    ParseNode* result;
+    if (kind == BinKind::_Null) {
+        result = nullptr;
+    } else {
+        const auto start = tokenizer_->offset();
+        MOZ_TRY_VAR(result, parseSumStatement(start, kind, fields));
+    }
+    MOZ_TRY(guard.done());
+
+    return result;
+}
+
+template<typename Tok> JS::Result<ParseNode*>
+BinASTParser<Tok>::parseOptionalVariableDeclarationOrExpression()
+{
+    BinKind kind;
+    BinFields fields(cx_);
+    AutoTaggedTuple guard(*tokenizer_);
+
+    MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+    ParseNode* result;
+    if (kind == BinKind::_Null) {
+        result = nullptr;
+    } else {
+        const auto start = tokenizer_->offset();
+        MOZ_TRY_VAR(result, parseSumVariableDeclarationOrExpression(start, kind, fields));
+    }
+    MOZ_TRY(guard.done());
+
+    return result;
+}
+
+
+
+// Force class instantiation.
+// This ensures that the symbols are built, without having to export all our
+// code (and its baggage of #include and macros) in the header.
+template class BinASTParser<BinTokenReaderMultipart>;
+template class BinASTParser<BinTokenReaderTester>;
+
+} // namespace frontend
+} // namespace js
new file mode 100644
--- /dev/null
+++ b/js/src/frontend/BinASTParser.h
@@ -0,0 +1,246 @@
+// This file was autogenerated by binjs_generate_spidermonkey,
+// please DO NOT EDIT BY HAND.
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+* vim: set ts=8 sts=4 et sw=4 tw=99:
+* This Source Code Form is subject to the terms of the Mozilla Public
+* License, v. 2.0. If a copy of the MPL was not distributed with this
+* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// To generate this file, see the documentation in
+// js/src/frontend/binsource/README.md.
+
+// This file is meant to be included from the declaration
+// of class `BinASTParser`. The include may be public or private.
+
+
+// ----- Sums of interfaces (by lexicographical order)
+// Implementations are autogenerated
+// `ParseNode*` may never be nullptr
+JS::Result<Ok> parseAssertedMaybePositionalParameterName(
+    AssertedScopeKind scopeKind,
+    MutableHandle<GCVector<JSAtom*>> positionalParams);
+JS::Result<ParseNode*> parseAssignmentTarget();
+JS::Result<ParseNode*> parseBinding();
+JS::Result<ParseNode*> parseExpression();
+JS::Result<ParseNode*> parseExpressionOrSuper();
+JS::Result<ParseNode*> parseForInOfBindingOrAssignmentTarget();
+JS::Result<ParseNode*> parseObjectProperty();
+JS::Result<ParseNode*> parseParameter();
+JS::Result<ParseNode*> parseProgram();
+JS::Result<ParseNode*> parsePropertyName();
+JS::Result<ParseNode*> parseSimpleAssignmentTarget();
+JS::Result<ParseNode*> parseSpreadElementOrExpression();
+JS::Result<ParseNode*> parseStatement();
+JS::Result<Ok> parseSumAssertedMaybePositionalParameterName(const size_t start, const BinKind kind, const BinFields& fields,
+    AssertedScopeKind scopeKind,
+    MutableHandle<GCVector<JSAtom*>> positionalParams);
+JS::Result<ParseNode*> parseSumAssignmentTarget(const size_t start, const BinKind kind, const BinFields& fields);
+JS::Result<ParseNode*> parseSumBinding(const size_t start, const BinKind kind, const BinFields& fields);
+JS::Result<ParseNode*> parseSumExpression(const size_t start, const BinKind kind, const BinFields& fields);
+JS::Result<ParseNode*> parseSumExpressionOrSuper(const size_t start, const BinKind kind, const BinFields& fields);
+JS::Result<ParseNode*> parseSumForInOfBindingOrAssignmentTarget(const size_t start, const BinKind kind, const BinFields& fields);
+JS::Result<ParseNode*> parseSumObjectProperty(const size_t start, const BinKind kind, const BinFields& fields);
+JS::Result<ParseNode*> parseSumParameter(const size_t start, const BinKind kind, const BinFields& fields);
+JS::Result<ParseNode*> parseSumProgram(const size_t start, const BinKind kind, const BinFields& fields);
+JS::Result<ParseNode*> parseSumPropertyName(const size_t start, const BinKind kind, const BinFields& fields);
+JS::Result<ParseNode*> parseSumSimpleAssignmentTarget(const size_t start, const BinKind kind, const BinFields& fields);
+JS::Result<ParseNode*> parseSumSpreadElementOrExpression(const size_t start, const BinKind kind, const BinFields& fields);
+JS::Result<ParseNode*> parseSumStatement(const size_t start, const BinKind kind, const BinFields& fields);
+JS::Result<ParseNode*> parseSumVariableDeclarationOrExpression(const size_t start, const BinKind kind, const BinFields& fields);
+
+
+// ----- Interfaces (by lexicographical order)
+// Implementations are autogenerated
+// `ParseNode*` may never be nullptr
+JS::Result<Ok> parseAssertedBlockScope();
+JS::Result<Ok> parseAssertedBoundName(
+    AssertedScopeKind scopeKind);
+JS::Result<Ok> parseAssertedBoundNamesScope();
+JS::Result<Ok> parseAssertedDeclaredName(
+    AssertedScopeKind scopeKind);
+JS::Result<Ok> parseAssertedParameterScope(
+    MutableHandle<GCVector<JSAtom*>> positionalParams);
+JS::Result<Ok> parseAssertedScriptGlobalScope();
+JS::Result<Ok> parseAssertedVarScope();
+JS::Result<ParseNode*> parseBindingIdentifier();
+JS::Result<ParseNode*> parseBlock();
+JS::Result<LexicalScopeNode*> parseCatchClause();
+JS::Result<ParseNode*> parseDirective();
+JS::Result<ListNode*> parseFormalParameters();
+JS::Result<Ok> parseFunctionExpressionContents(
+    uint32_t funLength,
+    ListNode** paramsOut,
+    ListNode** bodyOut);
+JS::Result<Ok> parseFunctionOrMethodContents(
+    uint32_t funLength,
+    ListNode** paramsOut,
+    ListNode** bodyOut);
+JS::Result<Ok> parseGetterContents(
+    uint32_t funLength,
+    ListNode** paramsOut,
+    ListNode** bodyOut);
+JS::Result<ParseNode*> parseIdentifierExpression();
+JS::Result<Ok> parseSetterContents(
+    uint32_t funLength,
+    ListNode** paramsOut,
+    ListNode** bodyOut);
+JS::Result<CaseClause*> parseSwitchCase();
+JS::Result<ParseNode*> parseSwitchDefault();
+JS::Result<ParseNode*> parseVariableDeclarator();
+JS::Result<ParseNode*> parseInterfaceArrayAssignmentTarget(const size_t start, const BinKind kind, const BinFields& fields);
+JS::Result<ParseNode*> parseInterfaceArrayBinding(const size_t start, const BinKind kind, const BinFields& fields);
+JS::Result<ParseNode*> parseInterfaceArrayExpression(const size_t start, const BinKind kind, const BinFields& fields);
+JS::Result<Ok> parseInterfaceAssertedBlockScope(const size_t start, const BinKind kind, const BinFields& fields);
+JS::Result<Ok> parseInterfaceAssertedBoundName(const size_t start, const BinKind kind, const BinFields& fields,
+    AssertedScopeKind scopeKind);
+JS::Result<Ok> parseInterfaceAssertedBoundNamesScope(const size_t start, const BinKind kind, const BinFields& fields);
+JS::Result<Ok> parseInterfaceAssertedDeclaredName(const size_t start, const BinKind kind, const BinFields& fields,
+    AssertedScopeKind scopeKind);
+JS::Result<Ok> parseInterfaceAssertedParameterScope(const size_t start, const BinKind kind, const BinFields& fields,
+    MutableHandle<GCVector<JSAtom*>> positionalParams);
+JS::Result<Ok> parseInterfaceAssertedPositionalParameterName(const size_t start, const BinKind kind, const BinFields& fields,
+    AssertedScopeKind scopeKind,
+    MutableHandle<GCVector<JSAtom*>> positionalParams);
+JS::Result<Ok> parseInterfaceAssertedScriptGlobalScope(const size_t start, const BinKind kind, const BinFields& fields);
+JS::Result<Ok> parseInterfaceAssertedVarScope(const size_t start, const BinKind kind, const BinFields& fields);
+JS::Result<ParseNode*> parseInterfaceAssignmentExpression(const size_t start, const BinKind kind, const BinFields& fields);
+JS::Result<ParseNode*> parseInterfaceAssignmentTargetIdentifier(const size_t start, const BinKind kind, const BinFields& fields);
+JS::Result<ParseNode*> parseInterfaceAwaitExpression(const size_t start, const BinKind kind, const BinFields& fields);
+JS::Result<ParseNode*> parseInterfaceBinaryExpression(const size_t start, const BinKind kind, const BinFields& fields);
+JS::Result<ParseNode*> parseInterfaceBindingIdentifier(const size_t start, const BinKind kind, const BinFields& fields);
+JS::Result<ParseNode*> parseInterfaceBindingWithInitializer(const size_t start, const BinKind kind, const BinFields& fields);
+JS::Result<ParseNode*> parseInterfaceBlock(const size_t start, const BinKind kind, const BinFields& fields);
+JS::Result<ParseNode*> parseInterfaceBreakStatement(const size_t start, const BinKind kind, const BinFields& fields);
+JS::Result<ParseNode*> parseInterfaceCallExpression(const size_t start, const BinKind kind, const BinFields& fields);
+JS::Result<LexicalScopeNode*> parseInterfaceCatchClause(const size_t start, const BinKind kind, const BinFields& fields);
+JS::Result<ParseNode*> parseInterfaceClassDeclaration(const size_t start, const BinKind kind, const BinFields& fields);
+JS::Result<ParseNode*> parseInterfaceClassExpression(const size_t start, const BinKind kind, const BinFields& fields);
+JS::Result<ParseNode*> parseInterfaceCompoundAssignmentExpression(const size_t start, const BinKind kind, const BinFields& fields);
+JS::Result<ParseNode*> parseInterfaceComputedMemberAssignmentTarget(const size_t start, const BinKind kind, const BinFields& fields);
+JS::Result<ParseNode*> parseInterfaceComputedMemberExpression(const size_t start, const BinKind kind, const BinFields& fields);
+JS::Result<ParseNode*> parseInterfaceComputedPropertyName(const size_t start, const BinKind kind, const BinFields& fields);
+JS::Result<ParseNode*> parseInterfaceConditionalExpression(const size_t start, const BinKind kind, const BinFields& fields);
+JS::Result<ParseNode*> parseInterfaceContinueStatement(const size_t start, const BinKind kind, const BinFields& fields);
+JS::Result<ParseNode*> parseInterfaceDataProperty(const size_t start, const BinKind kind, const BinFields& fields);
+JS::Result<ParseNode*> parseInterfaceDebuggerStatement(const size_t start, const BinKind kind, const BinFields& fields);
+JS::Result<ParseNode*> parseInterfaceDirective(const size_t start, const BinKind kind, const BinFields& fields);
+JS::Result<ParseNode*> parseInterfaceDoWhileStatement(const size_t start, const BinKind kind, const BinFields& fields);
+JS::Result<ParseNode*> parseInterfaceEagerArrowExpressionWithExpression(const size_t start, const BinKind kind, const BinFields& fields);
+JS::Result<ParseNode*> parseInterfaceEagerArrowExpressionWithFunctionBody(const size_t start, const BinKind kind, const BinFields& fields);
+JS::Result<ParseNode*> parseInterfaceEagerFunctionDeclaration(const size_t start, const BinKind kind, const BinFields& fields);
+JS::Result<ParseNode*> parseInterfaceEagerFunctionExpression(const size_t start, const BinKind kind, const BinFields& fields);
+JS::Result<ParseNode*> parseInterfaceEagerGetter(const size_t start, const BinKind kind, const BinFields& fields);
+JS::Result<ParseNode*> parseInterfaceEagerMethod(const size_t start, const BinKind kind, const BinFields& fields);
+JS::Result<ParseNode*> parseInterfaceEagerSetter(const size_t start, const BinKind kind, const BinFields& fields);
+JS::Result<ParseNode*> parseInterfaceEmptyStatement(const size_t start, const BinKind kind, const BinFields& fields);
+JS::Result<ParseNode*> parseInterfaceExpressionStatement(const size_t start, const BinKind kind, const BinFields& fields);
+JS::Result<ParseNode*> parseInterfaceForInOfBinding(const size_t start, const BinKind kind, const BinFields& fields);
+JS::Result<ParseNode*> parseInterfaceForInStatement(const size_t start, const BinKind kind, const BinFields& fields);
+JS::Result<ParseNode*> parseInterfaceForOfStatement(const size_t start, const BinKind kind, const BinFields& fields);
+JS::Result<ParseNode*> parseInterfaceForStatement(const size_t start, const BinKind kind, const BinFields& fields);
+JS::Result<ListNode*> parseInterfaceFormalParameters(const size_t start, const BinKind kind, const BinFields& fields);
+JS::Result<Ok> parseInterfaceFunctionExpressionContents(const size_t start, const BinKind kind, const BinFields& fields,
+    uint32_t funLength,
+    ListNode** paramsOut,
+    ListNode** bodyOut);
+JS::Result<Ok> parseInterfaceFunctionOrMethodContents(const size_t start, const BinKind kind, const BinFields& fields,
+    uint32_t funLength,
+    ListNode** paramsOut,
+    ListNode** bodyOut);
+JS::Result<Ok> parseInterfaceGetterContents(const size_t start, const BinKind kind, const BinFields& fields,
+    uint32_t funLength,
+    ListNode** paramsOut,
+    ListNode** bodyOut);
+JS::Result<ParseNode*> parseInterfaceIdentifierExpression(const size_t start, const BinKind kind, const BinFields& fields);
+JS::Result<ParseNode*> parseInterfaceIfStatement(const size_t start, const BinKind kind, const BinFields& fields);
+JS::Result<ParseNode*> parseInterfaceLabelledStatement(const size_t start, const BinKind kind, const BinFields& fields);
+JS::Result<ParseNode*> parseInterfaceLazyArrowExpressionWithExpression(const size_t start, const BinKind kind, const BinFields& fields);
+JS::Result<ParseNode*> parseInterfaceLazyArrowExpressionWithFunctionBody(const size_t start, const BinKind kind, const BinFields& fields);
+JS::Result<ParseNode*> parseInterfaceLazyFunctionDeclaration(const size_t start, const BinKind kind, const BinFields& fields);
+JS::Result<ParseNode*> parseInterfaceLazyFunctionExpression(const size_t start, const BinKind kind, const BinFields& fields);
+JS::Result<ParseNode*> parseInterfaceLazyGetter(const size_t start, const BinKind kind, const BinFields& fields);
+JS::Result<ParseNode*> parseInterfaceLazyMethod(const size_t start, const BinKind kind, const BinFields& fields);
+JS::Result<ParseNode*> parseInterfaceLazySetter(const size_t start, const BinKind kind, const BinFields& fields);
+JS::Result<ParseNode*> parseInterfaceLiteralBooleanExpression(const size_t start, const BinKind kind, const BinFields& fields);
+JS::Result<ParseNode*> parseInterfaceLiteralInfinityExpression(const size_t start, const BinKind kind, const BinFields& fields);
+JS::Result<ParseNode*> parseInterfaceLiteralNullExpression(const size_t start, const BinKind kind, const BinFields& fields);
+JS::Result<ParseNode*> parseInterfaceLiteralNumericExpression(const size_t start, const BinKind kind, const BinFields& fields);
+JS::Result<ParseNode*> parseInterfaceLiteralPropertyName(const size_t start, const BinKind kind, const BinFields& fields);
+JS::Result<ParseNode*> parseInterfaceLiteralRegExpExpression(const size_t start, const BinKind kind, const BinFields& fields);
+JS::Result<ParseNode*> parseInterfaceLiteralStringExpression(const size_t start, const BinKind kind, const BinFields& fields);
+JS::Result<ParseNode*> parseInterfaceModule(const size_t start, const BinKind kind, const BinFields& fields);
+JS::Result<ParseNode*> parseInterfaceNewExpression(const size_t start, const BinKind kind, const BinFields& fields);
+JS::Result<ParseNode*> parseInterfaceNewTargetExpression(const size_t start, const BinKind kind, const BinFields& fields);
+JS::Result<ParseNode*> parseInterfaceObjectAssignmentTarget(const size_t start, const BinKind kind, const BinFields& fields);
+JS::Result<ParseNode*> parseInterfaceObjectBinding(const size_t start, const BinKind kind, const BinFields& fields);
+JS::Result<ParseNode*> parseInterfaceObjectExpression(const size_t start, const BinKind kind, const BinFields& fields);
+JS::Result<ParseNode*> parseInterfaceReturnStatement(const size_t start, const BinKind kind, const BinFields& fields);
+JS::Result<ParseNode*> parseInterfaceScript(const size_t start, const BinKind kind, const BinFields& fields);
+JS::Result<Ok> parseInterfaceSetterContents(const size_t start, const BinKind kind, const BinFields& fields,
+    uint32_t funLength,
+    ListNode** paramsOut,
+    ListNode** bodyOut);
+JS::Result<ParseNode*> parseInterfaceShorthandProperty(const size_t start, const BinKind kind, const BinFields& fields);
+JS::Result<ParseNode*> parseInterfaceSpreadElement(const size_t start, const BinKind kind, const BinFields& fields);
+JS::Result<ParseNode*> parseInterfaceStaticMemberAssignmentTarget(const size_t start, const BinKind kind, const BinFields& fields);
+JS::Result<ParseNode*> parseInterfaceStaticMemberExpression(const size_t start, const BinKind kind, const BinFields& fields);
+JS::Result<ParseNode*> parseInterfaceSuper(const size_t start, const BinKind kind, const BinFields& fields);
+JS::Result<CaseClause*> parseInterfaceSwitchCase(const size_t start, const BinKind kind, const BinFields& fields);
+JS::Result<ParseNode*> parseInterfaceSwitchDefault(const size_t start, const BinKind kind, const BinFields& fields);
+JS::Result<ParseNode*> parseInterfaceSwitchStatement(const size_t start, const BinKind kind, const BinFields& fields);
+JS::Result<ParseNode*> parseInterfaceSwitchStatementWithDefault(const size_t start, const BinKind kind, const BinFields& fields);
+JS::Result<ParseNode*> parseInterfaceTemplateExpression(const size_t start, const BinKind kind, const BinFields& fields);
+JS::Result<ParseNode*> parseInterfaceThisExpression(const size_t start, const BinKind kind, const BinFields& fields);
+JS::Result<ParseNode*> parseInterfaceThrowStatement(const size_t start, const BinKind kind, const BinFields& fields);
+JS::Result<ParseNode*> parseInterfaceTryCatchStatement(const size_t start, const BinKind kind, const BinFields& fields);
+JS::Result<ParseNode*> parseInterfaceTryFinallyStatement(const size_t start, const BinKind kind, const BinFields& fields);
+JS::Result<ParseNode*> parseInterfaceUnaryExpression(const size_t start, const BinKind kind, const BinFields& fields);
+JS::Result<ParseNode*> parseInterfaceUpdateExpression(const size_t start, const BinKind kind, const BinFields& fields);
+JS::Result<ParseNode*> parseInterfaceVariableDeclaration(const size_t start, const BinKind kind, const BinFields& fields);
+JS::Result<ParseNode*> parseInterfaceVariableDeclarator(const size_t start, const BinKind kind, const BinFields& fields);
+JS::Result<ParseNode*> parseInterfaceWhileStatement(const size_t start, const BinKind kind, const BinFields& fields);
+JS::Result<ParseNode*> parseInterfaceWithStatement(const size_t start, const BinKind kind, const BinFields& fields);
+JS::Result<ParseNode*> parseInterfaceYieldExpression(const size_t start, const BinKind kind, const BinFields& fields);
+JS::Result<ParseNode*> parseInterfaceYieldStarExpression(const size_t start, const BinKind kind, const BinFields& fields);
+
+
+// ----- String enums (by lexicographical order)
+// Implementations are autogenerated
+JS::Result<typename BinASTParser<Tok>::AssertedDeclaredKind> parseAssertedDeclaredKind();
+JS::Result<typename BinASTParser<Tok>::BinaryOperator> parseBinaryOperator();
+JS::Result<typename BinASTParser<Tok>::CompoundAssignmentOperator> parseCompoundAssignmentOperator();
+JS::Result<typename BinASTParser<Tok>::UnaryOperator> parseUnaryOperator();
+JS::Result<typename BinASTParser<Tok>::UpdateOperator> parseUpdateOperator();
+JS::Result<typename BinASTParser<Tok>::VariableDeclarationKind> parseVariableDeclarationKind();
+
+
+// ----- Lists (by lexicographical order)
+// Implementations are autogenerated
+JS::Result<ParseNode*> parseArguments();
+JS::Result<ListNode*> parseFunctionBody();
+JS::Result<Ok> parseListOfAssertedBoundName(
+    AssertedScopeKind scopeKind);
+JS::Result<Ok> parseListOfAssertedDeclaredName(
+    AssertedScopeKind scopeKind);
+JS::Result<Ok> parseListOfAssertedMaybePositionalParameterName(
+    AssertedScopeKind scopeKind,
+    MutableHandle<GCVector<JSAtom*>> positionalParams);
+JS::Result<ListNode*> parseListOfDirective();
+JS::Result<ListNode*> parseListOfObjectProperty();
+JS::Result<ListNode*> parseListOfOptionalSpreadElementOrExpression();
+JS::Result<ListNode*> parseListOfParameter();
+JS::Result<ListNode*> parseListOfStatement();
+JS::Result<ListNode*> parseListOfSwitchCase();
+JS::Result<ListNode*> parseListOfVariableDeclarator();
+
+
+// ----- Default values (by lexicographical order)
+// Implementations are autogenerated
+JS::Result<ParseNode*> parseOptionalBinding();
+JS::Result<ParseNode*> parseOptionalBindingIdentifier();
+JS::Result<LexicalScopeNode*> parseOptionalCatchClause();
+JS::Result<ParseNode*> parseOptionalExpression();
+JS::Result<ParseNode*> parseOptionalSpreadElementOrExpression();
+JS::Result<ParseNode*> parseOptionalStatement();
+JS::Result<ParseNode*> parseOptionalVariableDeclarationOrExpression();
+
new file mode 100644
--- /dev/null
+++ b/js/src/frontend/BinASTParserPerTokenizer.cpp
@@ -0,0 +1,794 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sts=4 et sw=4 tw=99:
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "frontend/BinASTParserPerTokenizer.h"
+
+#include "mozilla/ArrayUtils.h"
+#include "mozilla/Casting.h"
+#include "mozilla/Maybe.h"
+#include "mozilla/Move.h"
+#include "mozilla/PodOperations.h"
+#include "mozilla/ScopeExit.h"
+#include "mozilla/Vector.h"
+
+#include "frontend/BinSource-macros.h"
+#include "frontend/BinTokenReaderTester.h"
+#include "frontend/FullParseHandler.h"
+#include "frontend/ParseNode.h"
+#include "frontend/Parser.h"
+#include "frontend/SharedContext.h"
+
+#include "js/Result.h"
+#include "vm/RegExpObject.h"
+
+#include "frontend/ParseContext-inl.h"
+#include "frontend/SharedContext-inl.h"
+#include "vm/JSContext-inl.h"
+
+// # About compliance with EcmaScript
+//
+// For the moment, this parser implements ES5. Future versions will be extended
+// to ES6 and further on.
+//
+// By design, it does NOT implement Annex B.3.3. If possible, we would like
+// to avoid going down that rabbit hole.
+//
+//
+// # About the AST
+//
+// At this stage of experimentation, the AST specifications change often. This
+// version of the parser attempts to implement
+// https://gist.github.com/Yoric/2390f0367515c079172be2526349b294
+//
+//
+// # About validating the AST
+//
+// Normally, this implementation validates all properties of the AST *except* the
+// order of fields, which is partially constrained by the AST spec (e.g. in a block,
+// field `scope` must appear before field `body`, etc.).
+//
+//
+// # About names and scopes
+//
+// One of the key objectives of the BinAST syntax is to be able to entirely skip
+// parsing inner functions until they are needed. With a purely syntactic AST,
+// this is generally impossible, as we would need to walk the AST to find
+// lexically-bound/var-bound variables, instances of direct eval, etc.
+//
+// To achieve this, BinAST files contain scope data, as instances of
+// `BinJS:Scope` nodes. Rather than walking the AST to assign bindings
+// to scopes, we extract data from the `BinJS:Scope` and check it lazily,
+// once we actually need to walk the AST.
+//
+// WARNING: The current implementation DOES NOT perform the check yet. It
+// is therefore unsafe.
+//
+// # About directives
+//
+// Currently, directives are ignored and treated as regular strings.
+//
+// They should be treated lazily (whenever we open a subscope), like bindings.
+
+namespace js {
+namespace frontend {
+
+using UsedNamePtr = UsedNameTracker::UsedNameMap::Ptr;
+
+// ------------- Toplevel constructions
+
+template<typename Tok> JS::Result<ParseNode*>
+BinASTParser<Tok>::parse(GlobalSharedContext* globalsc, const Vector<uint8_t>& data,
+                         BinASTSourceMetadata** metadataPtr)
+{
+    return parse(globalsc, data.begin(), data.length(), metadataPtr);
+}
+
+template<typename Tok> JS::Result<ParseNode*>
+BinASTParser<Tok>::parse(GlobalSharedContext* globalsc, const uint8_t* start, const size_t length,
+                         BinASTSourceMetadata** metadataPtr)
+{
+    auto result = parseAux(globalsc, start, length, metadataPtr);
+    poison(); // Make sure that the parser is never used again accidentally.
+    return result;
+}
+
+
+template<typename Tok> JS::Result<ParseNode*>
+BinASTParser<Tok>::parseAux(GlobalSharedContext* globalsc,
+                            const uint8_t* start, const size_t length,
+                            BinASTSourceMetadata** metadataPtr)
+{
+    MOZ_ASSERT(globalsc);
+
+    tokenizer_.emplace(cx_, this, start, length);
+
+    BinParseContext globalpc(cx_, this, globalsc, /* newDirectives = */ nullptr);
+    if (!globalpc.init()) {
+        return cx_->alreadyReportedError();
+    }
+
+    ParseContext::VarScope varScope(cx_, &globalpc, usedNames_);
+    if (!varScope.init(&globalpc)) {
+        return cx_->alreadyReportedError();
+    }
+
+    MOZ_TRY(tokenizer_->readHeader());
+
+    ParseNode* result(nullptr);
+    MOZ_TRY_VAR(result, parseProgram());
+
+    mozilla::Maybe<GlobalScope::Data*> bindings = NewGlobalScopeData(cx_, varScope, alloc_,
+                                                                     parseContext_);
+    if (!bindings) {
+        return cx_->alreadyReportedError();
+    }
+    globalsc->bindings = *bindings;
+
+    if (metadataPtr) {
+        *metadataPtr = tokenizer_->takeMetadata();
+    }
+
+    return result; // Magic conversion to Ok.
+}
+
+template<typename Tok> JS::Result<ParseNode*>
+BinASTParser<Tok>::parseLazyFunction(ScriptSource* scriptSource, const size_t firstOffset)
+{
+    MOZ_ASSERT(lazyScript_);
+    MOZ_ASSERT(scriptSource->length() > firstOffset);
+
+    tokenizer_.emplace(cx_, this, scriptSource->binASTSource(), scriptSource->length());
+
+    MOZ_TRY(tokenizer_->initFromScriptSource(scriptSource));
+
+    tokenizer_->seek(firstOffset);
+
+    // For now, only function declarations and function expression are supported.
+    RootedFunction func(cx_, lazyScript_->functionNonDelazifying());
+    bool isExpr = func->isLambda();
+    MOZ_ASSERT(func->kind() == JSFunction::FunctionKind::NormalFunction);
+
+    // Poison the tokenizer when we leave to ensure that it's not used again by accident.
+    auto onExit = mozilla::MakeScopeExit([&]() { poison(); });
+
+    // TODO: This should be actually shared with the auto-generated version.
+
+    auto syntaxKind = isExpr ? FunctionSyntaxKind::Expression : FunctionSyntaxKind::Statement;
+    BINJS_MOZ_TRY_DECL(funbox, buildFunctionBox(lazyScript_->generatorKind(),
+                                                lazyScript_->asyncKind(), syntaxKind, nullptr));
+
+    // Push a new ParseContext. It will be used to parse `scope`, the arguments, the function.
+    BinParseContext funpc(cx_, this, funbox, /* newDirectives = */ nullptr);
+    BINJS_TRY(funpc.init());
+    parseContext_->functionScope().useAsVarScope(parseContext_);
+    MOZ_ASSERT(parseContext_->isFunctionBox());
+
+    ParseContext::Scope lexicalScope(cx_, parseContext_, usedNames_);
+    BINJS_TRY(lexicalScope.init(parseContext_));
+    ListNode* params;
+    ListNode* tmpBody;
+    auto parseFunc = isExpr ? &BinASTParser::parseFunctionExpressionContents
+                            : &BinASTParser::parseFunctionOrMethodContents;
+    MOZ_TRY((this->*parseFunc)(func->nargs(), &params, &tmpBody));
+
+    BINJS_TRY_DECL(lexicalScopeData, NewLexicalScopeData(cx_, lexicalScope, alloc_, parseContext_));
+    BINJS_TRY_DECL(body, factory_.newLexicalScope(*lexicalScopeData, tmpBody));
+
+    auto binKind = isExpr ? BinKind::LazyFunctionExpression : BinKind::LazyFunctionDeclaration;
+    return buildFunction(firstOffset, binKind, nullptr, params, body, funbox);
+}
+
+template<typename Tok> void
+BinASTParser<Tok>::forceStrictIfNecessary(SharedContext* sc, ListNode* directives)
+{
+    JSAtom* useStrict = cx_->names().useStrict;
+
+    for (const ParseNode* directive : directives->contents()) {
+        if (directive->as<NameNode>().atom() == useStrict) {
+            sc->strictScript = true;
+            break;
+        }
+    }
+}
+
+template<typename Tok> JS::Result<FunctionBox*>
+BinASTParser<Tok>::buildFunctionBox(GeneratorKind generatorKind,
+    FunctionAsyncKind functionAsyncKind,
+    FunctionSyntaxKind syntax,
+    ParseNode* name)
+{
+    MOZ_ASSERT_IF(!parseContext_, lazyScript_);
+
+    RootedAtom atom(cx_);
+
+    // Name might be any of {Identifier,ComputedPropertyName,LiteralPropertyName}
+    if (name && name->is<NameNode>()) {
+        atom = name->as<NameNode>().atom();
+    }
+
+    if (parseContext_ && syntax == FunctionSyntaxKind::Statement) {
+        auto ptr = parseContext_->varScope().lookupDeclaredName(atom);
+        if (!ptr) {
+            return raiseError("FunctionDeclaration without corresponding AssertedDeclaredName.");
+        }
+
+        // FIXME: Should be merged with ParseContext::tryDeclareVarHelper
+        //        (bug 1499044).
+        DeclarationKind declaredKind = ptr->value()->kind();
+        if (DeclarationKindIsVar(declaredKind)) {
+            MOZ_ASSERT(declaredKind != DeclarationKind::VarForAnnexBLexicalFunction);
+            ptr->value()->alterKind(DeclarationKind::BodyLevelFunction);
+        }
+    }
+
+    // Allocate the function before walking down the tree.
+    RootedFunction fun(cx_);
+    BINJS_TRY_VAR(fun, !parseContext_
+        ? lazyScript_->functionNonDelazifying()
+        : AllocNewFunction(cx_, atom, syntax, generatorKind, functionAsyncKind, nullptr));
+    MOZ_ASSERT_IF(parseContext_, fun->explicitName() == atom);
+
+    mozilla::Maybe<Directives> directives;
+    if (parseContext_) {
+        directives.emplace(parseContext_);
+    } else {
+        directives.emplace(lazyScript_->strict());
+    }
+
+    auto* funbox = alloc_.new_<FunctionBox>(cx_, traceListHead_, fun, /* toStringStart = */ 0,
+                                            *directives, /* extraWarning = */ false,
+                                            generatorKind, functionAsyncKind);
+    if (!funbox) {
+        return raiseOOM();
+    }
+
+    traceListHead_ = funbox;
+    if (parseContext_) {
+        funbox->initWithEnclosingParseContext(parseContext_, syntax);
+    } else {
+        funbox->initFromLazyFunction();
+    }
+    return funbox;
+}
+
+template<typename Tok> JS::Result<CodeNode*>
+BinASTParser<Tok>::makeEmptyFunctionNode(const size_t start, const BinKind kind, FunctionBox* funbox)
+{
+    // LazyScript compilation requires basically none of the fields filled out.
+    TokenPos pos = tokenizer_->pos(start);
+    bool isStatement = kind == BinKind::EagerFunctionDeclaration ||
+                       kind == BinKind::LazyFunctionDeclaration;
+
+    BINJS_TRY_DECL(result, isStatement
+                     ? factory_.newFunctionStatement(pos)
+                     : factory_.newFunctionExpression(pos));
+
+    factory_.setFunctionBox(result, funbox);
+
+    return result;
+}
+
+template<typename Tok> JS::Result<ParseNode*>
+BinASTParser<Tok>::buildFunction(const size_t start, const BinKind kind, ParseNode* name,
+                                 ListNode* params, ParseNode* body, FunctionBox* funbox)
+{
+    // Set the argument count for building argument packets. Function.length is handled
+    // by setting the appropriate funbox field during argument parsing.
+    if (!lazyScript_ || lazyScript_->functionNonDelazifying() != funbox->function()) {
+        funbox->function()->setArgCount(params ? uint16_t(params->count()) : 0);
+    }
+
+    // ParseNode represents the body as concatenated after the params.
+    params->appendWithoutOrderAssumption(body);
+
+    BINJS_MOZ_TRY_DECL(result, makeEmptyFunctionNode(start, kind, funbox));
+
+    factory_.setFunctionFormalParametersAndBody(result, params);
+
+    HandlePropertyName dotThis = cx_->names().dotThis;
+    const bool declareThis = hasUsedName(dotThis) ||
+                             funbox->bindingsAccessedDynamically() ||
+                             funbox->isDerivedClassConstructor();
+
+    if (declareThis) {
+        ParseContext::Scope& funScope = parseContext_->functionScope();
+        ParseContext::Scope::AddDeclaredNamePtr p = funScope.lookupDeclaredNameForAdd(dotThis);
+        MOZ_ASSERT(!p);
+        BINJS_TRY(funScope.addDeclaredName(parseContext_, p, dotThis, DeclarationKind::Var,
+                                     DeclaredNameInfo::npos));
+        funbox->setHasThisBinding();
+
+        // TODO (efaust): This capture will have to come from encoder side for arrow functions.
+    }
+
+    // This models PerHandlerParser::declaeFunctionArgumentsObject, with some subtleties removed,
+    // as they don't yet apply to us.
+    HandlePropertyName arguments = cx_->names().arguments;
+    if (hasUsedName(arguments) || parseContext_->functionBox()->bindingsAccessedDynamically()) {
+        funbox->usesArguments = true;
+
+        ParseContext::Scope& funScope = parseContext_->functionScope();
+        ParseContext::Scope::AddDeclaredNamePtr p = funScope.lookupDeclaredNameForAdd(arguments);
+        if (!p) {
+            BINJS_TRY(funScope.addDeclaredName(parseContext_, p, arguments, DeclarationKind::Var,
+                                               DeclaredNameInfo::npos));
+            funbox->declaredArguments = true;
+        } else if (p->value()->kind() != DeclarationKind::Var) {
+            // Lexicals, formal parameters, and body level functions shadow.
+            funbox->usesArguments = false;
+        }
+
+        if (funbox->usesArguments) {
+            funbox->setArgumentsHasLocalBinding();
+
+            if (parseContext_->sc()->bindingsAccessedDynamically() ||
+                parseContext_->sc()->hasDebuggerStatement())
+            {
+                funbox->setDefinitelyNeedsArgsObj();
+            }
+        }
+    }
+
+    if (funbox->needsDotGeneratorName()) {
+        ParseContext::Scope& funScope = parseContext_->functionScope();
+        HandlePropertyName dotGenerator = cx_->names().dotGenerator;
+        ParseContext::Scope::AddDeclaredNamePtr p = funScope.lookupDeclaredNameForAdd(dotGenerator);
+        if (!p) {
+            BINJS_TRY(funScope.addDeclaredName(parseContext_, p, dotGenerator, DeclarationKind::Var,
+                                               DeclaredNameInfo::npos));
+        }
+
+        BINJS_TRY(usedNames_.noteUse(cx_, dotGenerator, parseContext_->scriptId(),
+                                     parseContext_->innermostScope()->id()));
+
+        BINJS_TRY_DECL(dotGen, factory_.newName(dotGenerator,
+                                                tokenizer_->pos(tokenizer_->offset()), cx_));
+
+        ListNode* stmtList = &body->as<LexicalScopeNode>().scopeBody()->as<ListNode>();
+        BINJS_TRY(factory_.prependInitialYield(stmtList, dotGen));
+    }
+
+    // Check all our bindings after maybe adding function metavars.
+    MOZ_TRY(checkFunctionClosedVars());
+
+    BINJS_TRY_DECL(bindings,
+             NewFunctionScopeData(cx_, parseContext_->functionScope(),
+                                  /* hasParameterExprs = */ false, alloc_, parseContext_));
+
+    funbox->functionScopeBindings().set(*bindings);
+
+    if (funbox->function()->isNamedLambda()) {
+        BINJS_TRY_DECL(recursiveBinding,
+                 NewLexicalScopeData(cx_, parseContext_->namedLambdaScope(), alloc_, parseContext_));
+
+        funbox->namedLambdaBindings().set(*recursiveBinding);
+    }
+
+    return result;
+}
+
+template<typename Tok> JS::Result<Ok>
+BinASTParser<Tok>::addScopeName(AssertedScopeKind scopeKind, HandleAtom name,
+                                ParseContext::Scope* scope, DeclarationKind declKind,
+                                bool isCaptured, bool allowDuplicateName)
+{
+    auto ptr = scope->lookupDeclaredNameForAdd(name);
+    if (ptr) {
+        if (allowDuplicateName) {
+            return Ok();
+        }
+        return raiseError("Variable redeclaration");
+    }
+
+    BINJS_TRY(scope->addDeclaredName(parseContext_, ptr, name.get(), declKind,
+                                     tokenizer_->offset()));
+
+    if (isCaptured) {
+        auto declaredPtr = scope->lookupDeclaredName(name);
+        MOZ_ASSERT(declaredPtr);
+        declaredPtr->value()->setClosedOver();
+    }
+
+    return Ok();
+}
+
+template<typename Tok> void
+BinASTParser<Tok>::captureFunctionName()
+{
+    MOZ_ASSERT(parseContext_->isFunctionBox());
+    MOZ_ASSERT(parseContext_->functionBox()->function()->isNamedLambda());
+
+    RootedAtom funName(cx_, parseContext_->functionBox()->function()->explicitName());
+    MOZ_ASSERT(funName);
+
+    auto ptr = parseContext_->namedLambdaScope().lookupDeclaredName(funName);
+    MOZ_ASSERT(ptr);
+    ptr->value()->setClosedOver();
+}
+
+template<typename Tok> JS::Result<Ok>
+BinASTParser<Tok>::getDeclaredScope(AssertedScopeKind scopeKind, AssertedDeclaredKind kind,
+                                    ParseContext::Scope*& scope, DeclarationKind& declKind)
+{
+    MOZ_ASSERT(scopeKind == AssertedScopeKind::Block ||
+               scopeKind == AssertedScopeKind::Global ||
+               scopeKind == AssertedScopeKind::Var);
+    switch (kind) {
+      case AssertedDeclaredKind::Var:
+        if (scopeKind == AssertedScopeKind::Block) {
+            return raiseError("AssertedBlockScope cannot contain 'var' binding");
+        }
+        declKind = DeclarationKind::Var;
+        scope = &parseContext_->varScope();
+        break;
+      case AssertedDeclaredKind::NonConstLexical:
+        declKind = DeclarationKind::Let;
+        scope = parseContext_->innermostScope();
+        break;
+      case AssertedDeclaredKind::ConstLexical:
+        declKind = DeclarationKind::Const;
+        scope = parseContext_->innermostScope();
+        break;
+    }
+
+    return Ok();
+}
+
+template<typename Tok> JS::Result<Ok>
+BinASTParser<Tok>::getBoundScope(AssertedScopeKind scopeKind,
+                                 ParseContext::Scope*& scope, DeclarationKind& declKind)
+{
+    MOZ_ASSERT(scopeKind == AssertedScopeKind::Catch ||
+               scopeKind == AssertedScopeKind::Parameter);
+    switch (scopeKind) {
+      case AssertedScopeKind::Catch:
+        declKind = DeclarationKind::CatchParameter;
+        scope = parseContext_->innermostScope();
+        break;
+      case AssertedScopeKind::Parameter:
+        MOZ_ASSERT(parseContext_->isFunctionBox());
+        declKind = DeclarationKind::PositionalFormalParameter;
+        scope = &parseContext_->functionScope();
+        break;
+      default:
+        MOZ_ASSERT_UNREACHABLE("Unexpected AssertedScopeKind");
+        break;
+    }
+
+    return Ok();
+}
+
+template<typename Tok> JS::Result<Ok>
+BinASTParser<Tok>::checkBinding(JSAtom* name)
+{
+    // Check that the variable appears in the corresponding scope.
+    ParseContext::Scope& scope =
+        variableDeclarationKind_ == VariableDeclarationKind::Var
+        ? parseContext_->varScope()
+        : *parseContext_->innermostScope();
+
+    auto ptr = scope.lookupDeclaredName(name->asPropertyName());
+    if (!ptr) {
+        return raiseMissingVariableInAssertedScope(name);
+    }
+
+    return Ok();
+}
+
+// Binary AST (revision 8eab67e0c434929a66ff6abe99ff790bca087dda)
+// 3.1.5 CheckPositionalParameterIndices.
+template<typename Tok> JS::Result<Ok>
+BinASTParser<Tok>::checkPositionalParameterIndices(Handle<GCVector<JSAtom*>> positionalParams,
+                                                   ListNode* params)
+{
+    // positionalParams should have the corresponding entry up to the last
+    // positional parameter.
+
+    // `positionalParams` corresponds to `expectedParams` parameter in the spec.
+    // `params` corresponds to `parseTree` in 3.1.9 CheckAssertedScope, and
+    // `positionalParamNames` parameter
+
+    // Steps 1-3.
+    // PositionalParameterNames (3.1.9 CheckAssertedScope step 5.d) and
+    // CreatePositionalParameterIndices (3.1.5 CheckPositionalParameterIndices
+    // step 1) are done implicitly.
+    uint32_t i = 0;
+    const bool hasRest = parseContext_->functionBox()->hasRest();
+    for (ParseNode* param : params->contents()) {
+        if (param->isKind(ParseNodeKind::Assign)) {
+            param = param->as<AssignmentNode>().left();
+        }
+
+        // At this point, function body is not part of params list.
+        const bool isRest = hasRest && !param->pn_next;
+        if (isRest) {
+            // Rest parameter
+
+            // Step 3.
+            if (i >= positionalParams.get().length()) {
+                continue;
+            }
+
+            if (positionalParams.get()[i]) {
+                return raiseError("Expected positional parameter per AssertedParameterScope.paramNames, got rest parameter");
+            }
+        } else if (param->isKind(ParseNodeKind::Name)) {
+            // Simple or default parameter.
+
+            // Step 2.a.
+            if (i >= positionalParams.get().length()) {
+                return raiseError("AssertedParameterScope.paramNames doesn't have corresponding entry to positional parameter");
+            }
+
+            JSAtom* name = positionalParams.get()[i];
+            if (!name) {
+                // Step 2.a.ii.1.
+                return raiseError("Expected destructuring/rest parameter per AssertedParameterScope.paramNames, got positional parameter");
+            }
+
+            // Step 2.a.i.
+            if (param->as<NameNode>().name() != name) {
+                // Step 2.a.ii.1.
+                return raiseError("Name mismatch between AssertedPositionalParameterName in AssertedParameterScope.paramNames and actual parameter");
+            }
+
+            // Step 2.a.i.1.
+            // Implicitly done.
+        } else {
+            // Destructuring parameter.
+
+            MOZ_ASSERT(param->isKind(ParseNodeKind::Object) ||
+                       param->isKind(ParseNodeKind::Array));
+
+            // Step 3.
+            if (i >= positionalParams.get().length()) {
+                continue;
+            }
+
+            if (positionalParams.get()[i]) {
+                return raiseError("Expected positional parameter per AssertedParameterScope.paramNames, got destructuring parameter");
+            }
+        }
+
+        i++;
+    }
+
+    // Step 3.
+    if (positionalParams.get().length() > params->count()) {
+        // `positionalParams` has unchecked entries.
+        return raiseError("AssertedParameterScope.paramNames has unmatching items than the actual parameters");
+    }
+
+    return Ok();
+}
+
+// Binary AST (revision 8eab67e0c434929a66ff6abe99ff790bca087dda)
+// 3.1.13 CheckFunctionLength.
+template<typename Tok> JS::Result<Ok>
+BinASTParser<Tok>::checkFunctionLength(uint32_t expectedLength)
+{
+    if (parseContext_->functionBox()->length != expectedLength) {
+        return raiseError("Function length does't match");
+    }
+    return Ok();
+}
+
+template<typename Tok> JS::Result<Ok>
+BinASTParser<Tok>::checkClosedVars(ParseContext::Scope& scope)
+{
+    for (ParseContext::Scope::BindingIter bi = scope.bindings(parseContext_); bi; bi++) {
+        if (UsedNamePtr p = usedNames_.lookup(bi.name())) {
+            bool closedOver;
+            p->value().noteBoundInScope(parseContext_->scriptId(), scope.id(), &closedOver);
+            if (closedOver && !bi.closedOver()) {
+                return raiseInvalidClosedVar(bi.name());
+            }
+        }
+    }
+
+    return Ok();
+}
+
+template<typename Tok> JS::Result<Ok>
+BinASTParser<Tok>::checkFunctionClosedVars()
+{
+    MOZ_ASSERT(parseContext_->isFunctionBox());
+
+    MOZ_TRY(checkClosedVars(*parseContext_->innermostScope()));
+    MOZ_TRY(checkClosedVars(parseContext_->functionScope()));
+    if (parseContext_->functionBox()->function()->isNamedLambda()) {
+        MOZ_TRY(checkClosedVars(parseContext_->namedLambdaScope()));
+    }
+
+    return Ok();
+}
+
+template<typename Tok> JS::Result<Ok>
+BinASTParser<Tok>::prependDirectivesToBody(ListNode* body, ListNode* directives)
+{
+    if (!directives) {
+        return Ok();
+    }
+
+    if (directives->empty()) {
+        return Ok();
+    }
+
+    MOZ_TRY(prependDirectivesImpl(body, directives->head()));
+
+    return Ok();
+}
+
+template<typename Tok> JS::Result<Ok>
+BinASTParser<Tok>::prependDirectivesImpl(ListNode* body, ParseNode* directive)
+{
+    BINJS_TRY(CheckRecursionLimit(cx_));
+
+    // Prepend in the reverse order by using stack, so that the directives are
+    // prepended in the original order.
+    if (ParseNode* next = directive->pn_next) {
+        MOZ_TRY(prependDirectivesImpl(body, next));
+    }
+
+    BINJS_TRY_DECL(statement, factory_.newExprStatement(directive, directive->pn_pos.end));
+    body->prependAndUpdatePos(statement);
+
+    return Ok();
+}
+
+template<typename Tok> mozilla::GenericErrorResult<JS::Error&>
+BinASTParser<Tok>::raiseInvalidClosedVar(JSAtom* name)
+{
+    return raiseError("Captured variable was not declared as captured");
+}
+
+template<typename Tok> mozilla::GenericErrorResult<JS::Error&>
+BinASTParser<Tok>::raiseMissingVariableInAssertedScope(JSAtom* name)
+{
+    // For the moment, we don't trust inputs sufficiently to put the name
+    // in an error message.
+    return raiseError("Missing variable in AssertedScope");
+}
+
+template<typename Tok> mozilla::GenericErrorResult<JS::Error&>
+BinASTParser<Tok>::raiseMissingDirectEvalInAssertedScope()
+{
+    return raiseError("Direct call to `eval` was not declared in AssertedScope");
+}
+
+template<typename Tok> mozilla::GenericErrorResult<JS::Error&>
+BinASTParser<Tok>::raiseInvalidKind(const char* superKind, const BinKind kind)
+{
+    Sprinter out(cx_);
+    BINJS_TRY(out.init());
+    BINJS_TRY(out.printf("In %s, invalid kind %s", superKind, describeBinKind(kind)));
+    return raiseError(out.string());
+}
+
+template<typename Tok> mozilla::GenericErrorResult<JS::Error&>
+BinASTParser<Tok>::raiseInvalidVariant(const char* kind, const BinVariant value)
+{
+    Sprinter out(cx_);
+    BINJS_TRY(out.init());
+    BINJS_TRY(out.printf("In %s, invalid variant '%s'", kind, describeBinVariant(value)));
+
+    return raiseError(out.string());
+}
+
+template<typename Tok> mozilla::GenericErrorResult<JS::Error&>
+BinASTParser<Tok>::raiseMissingField(const char* kind, const BinField field)
+{
+    Sprinter out(cx_);
+    BINJS_TRY(out.init());
+    BINJS_TRY(out.printf("In %s, missing field '%s'", kind, describeBinField(field)));
+
+    return raiseError(out.string());
+}
+
+template<typename Tok> mozilla::GenericErrorResult<JS::Error&>
+BinASTParser<Tok>::raiseEmpty(const char* description)
+{
+    Sprinter out(cx_);
+    BINJS_TRY(out.init());
+    BINJS_TRY(out.printf("Empty %s", description));
+
+    return raiseError(out.string());
+}
+
+template<typename Tok> mozilla::GenericErrorResult<JS::Error&>
+BinASTParser<Tok>::raiseOOM()
+{
+    return tokenizer_->raiseOOM();
+}
+
+template<typename Tok> mozilla::GenericErrorResult<JS::Error&>
+BinASTParser<Tok>::raiseError(BinKind kind, const char* description)
+{
+    Sprinter out(cx_);
+    BINJS_TRY(out.init());
+    BINJS_TRY(out.printf("In %s, ", description));
+    return tokenizer_->raiseError(out.string());
+}
+
+template<typename Tok> mozilla::GenericErrorResult<JS::Error&>
+BinASTParser<Tok>::raiseError(const char* description)
+{
+    return tokenizer_->raiseError(description);
+}
+
+template<typename Tok> void
+BinASTParser<Tok>::poison()
+{
+    tokenizer_.reset();
+}
+
+template<typename Tok> void
+BinASTParser<Tok>::reportErrorNoOffsetVA(unsigned errorNumber, va_list args)
+{
+    ErrorMetadata metadata;
+    metadata.filename = getFilename();
+    metadata.lineNumber = 0;
+    metadata.columnNumber = offset();
+    metadata.isMuted = options().mutedErrors();
+    ReportCompileError(cx_, std::move(metadata), nullptr, JSREPORT_ERROR, errorNumber, args);
+}
+
+template<typename Tok> void
+BinASTParser<Tok>::errorAtVA(uint32_t offset, unsigned errorNumber, va_list* args)
+{
+    ErrorMetadata metadata;
+    metadata.filename = getFilename();
+    metadata.lineNumber = 0;
+    metadata.columnNumber = offset;
+    metadata.isMuted = options().mutedErrors();
+    ReportCompileError(cx_, std::move(metadata), nullptr, JSREPORT_ERROR, errorNumber, *args);
+}
+
+template<typename Tok> bool
+BinASTParser<Tok>::reportExtraWarningErrorNumberVA(UniquePtr<JSErrorNotes> notes, uint32_t offset, unsigned errorNumber, va_list* args)
+{
+    if (!options().extraWarningsOption) {
+        return true;
+    }
+
+    ErrorMetadata metadata;
+    metadata.filename = getFilename();
+    metadata.lineNumber = 0;
+    metadata.columnNumber = offset;
+    metadata.isMuted = options().mutedErrors();
+
+    if (options().werrorOption) {
+        ReportCompileError(cx_, std::move(metadata), std::move(notes), JSREPORT_STRICT, errorNumber, *args);
+        return false;
+    }
+
+    return ReportCompileWarning(cx_, std::move(metadata), std::move(notes), JSREPORT_STRICT | JSREPORT_WARNING, errorNumber, *args);
+}
+
+void
+TraceBinParser(JSTracer* trc, JS::AutoGCRooter* parser)
+{
+    static_cast<BinASTParserBase*>(parser)->trace(trc);
+}
+
+template<typename Tok>
+void
+BinASTParser<Tok>::doTrace(JSTracer* trc)
+{
+    if (tokenizer_) {
+        tokenizer_->traceMetadata(trc);
+    }
+}
+
+// Force class instantiation.
+// This ensures that the symbols are built, without having to export all our
+// code (and its baggage of #include and macros) in the header.
+template class BinASTParser<BinTokenReaderMultipart>;
+template class BinASTParser<BinTokenReaderTester>;
+
+} // namespace frontend
+} // namespace js
+
new file mode 100644
--- /dev/null
+++ b/js/src/frontend/BinASTParserPerTokenizer.h
@@ -0,0 +1,319 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sts=4 et sw=4 tw=99:
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef frontend_BinASTParserPerTokenizer_h
+#define frontend_BinASTParserPerTokenizer_h
+
+/**
+ * A Binary AST parser.
+ *
+ * At the time of this writing, this parser implements the grammar of ES5
+ * and trusts its input (in particular, variable declarations).
+ */
+
+#include "mozilla/Maybe.h"
+
+#include "frontend/BCEParserHandle.h"
+#include "frontend/BinASTEnum.h"
+#include "frontend/BinASTParserBase.h"
+#include "frontend/BinToken.h"
+#include "frontend/BinTokenReaderMultipart.h"
+#include "frontend/BinTokenReaderTester.h"
+#include "frontend/FullParseHandler.h"
+#include "frontend/ParseContext.h"
+#include "frontend/ParseNode.h"
+#include "frontend/SharedContext.h"
+
+#include "js/CompileOptions.h"
+#include "js/GCHashTable.h"
+#include "js/GCVector.h"
+#include "js/Result.h"
+
+namespace js {
+namespace frontend {
+
+/**
+ * The parser for a Binary AST.
+ *
+ * By design, this parser never needs to backtrack or look ahead. Errors are not
+ * recoverable.
+ */
+template<typename Tok>
+class BinASTParser : public BinASTParserBase, public ErrorReporter, public BCEParserHandle
+{
+  public:
+    using Tokenizer = Tok;
+
+    using AutoList = typename Tokenizer::AutoList;
+    using AutoTaggedTuple = typename Tokenizer::AutoTaggedTuple;
+    using AutoTuple = typename Tokenizer::AutoTuple;
+    using BinFields = typename Tokenizer::BinFields;
+    using Chars = typename Tokenizer::Chars;
+
+  public:
+    // Auto-generated types.
+    using AssertedDeclaredKind = binast::AssertedDeclaredKind;
+    using BinaryOperator = binast::BinaryOperator;
+    using CompoundAssignmentOperator = binast::CompoundAssignmentOperator;
+    using UnaryOperator = binast::UnaryOperator;
+    using UpdateOperator = binast::UpdateOperator;
+    using VariableDeclarationKind = binast::VariableDeclarationKind;
+
+  public:
+    BinASTParser(JSContext* cx, LifoAlloc& alloc, UsedNameTracker& usedNames, const JS::ReadOnlyCompileOptions& options,
+                 HandleScriptSourceObject sourceObject, Handle<LazyScript*> lazyScript = nullptr)
+        : BinASTParserBase(cx, alloc, usedNames, sourceObject, lazyScript)
+        , options_(options)
+        , variableDeclarationKind_(VariableDeclarationKind::Var)
+    {
+    }
+    ~BinASTParser()
+    {
+    }
+
+    /**
+     * Parse a buffer, returning a node (which may be nullptr) in case of success
+     * or Nothing() in case of error.
+     *
+     * The instance of `ParseNode` MAY NOT survive the `BinASTParser`. Indeed,
+     * destruction of the `BinASTParser` will also destroy the `ParseNode`.
+     *
+     * In case of error, the parser reports the JS error.
+     */
+    JS::Result<ParseNode*> parse(GlobalSharedContext* globalsc,
+                                 const uint8_t* start, const size_t length,
+                                 BinASTSourceMetadata** metadataPtr = nullptr);
+    JS::Result<ParseNode*> parse(GlobalSharedContext* globalsc, const Vector<uint8_t>& data,
+                                 BinASTSourceMetadata** metadataPtr = nullptr);
+
+    JS::Result<ParseNode*> parseLazyFunction(ScriptSource* src, const size_t firstOffset);
+
+  private:
+    MOZ_MUST_USE JS::Result<ParseNode*> parseAux(GlobalSharedContext* globalsc,
+                                                 const uint8_t* start, const size_t length,
+                                                 BinASTSourceMetadata** metadataPtr = nullptr);
+
+    // --- Raise errors.
+    //
+    // These methods return a (failed) JS::Result for convenience.
+
+    MOZ_MUST_USE mozilla::GenericErrorResult<JS::Error&> raiseInvalidClosedVar(JSAtom* name);
+    MOZ_MUST_USE mozilla::GenericErrorResult<JS::Error&> raiseMissingVariableInAssertedScope(JSAtom* name);
+    MOZ_MUST_USE mozilla::GenericErrorResult<JS::Error&> raiseMissingDirectEvalInAssertedScope();
+    MOZ_MUST_USE mozilla::GenericErrorResult<JS::Error&> raiseInvalidKind(const char* superKind,
+        const BinKind kind);
+    MOZ_MUST_USE mozilla::GenericErrorResult<JS::Error&> raiseInvalidVariant(const char* kind,
+        const BinVariant value);
+    MOZ_MUST_USE mozilla::GenericErrorResult<JS::Error&> raiseMissingField(const char* kind,
+        const BinField field);
+    MOZ_MUST_USE mozilla::GenericErrorResult<JS::Error&> raiseEmpty(const char* description);
+    MOZ_MUST_USE mozilla::GenericErrorResult<JS::Error&> raiseOOM();
+    MOZ_MUST_USE mozilla::GenericErrorResult<JS::Error&> raiseError(const char* description);
+    MOZ_MUST_USE mozilla::GenericErrorResult<JS::Error&> raiseError(BinKind kind,
+        const char* description);
+
+
+    // Ensure that this parser will never be used again.
+    void poison();
+
+    // The owner or the target of Asserted*Scope.
+    enum class AssertedScopeKind {
+        Block,
+        Catch,
+        Global,
+        Parameter,
+        Var,
+    };
+
+    // Auto-generated methods
+#include "frontend/BinASTParser.h"
+
+    // --- Auxiliary parsing functions
+
+    // Build a function object for a function-producing production. Called AFTER creating the scope.
+    JS::Result<CodeNode*>
+    makeEmptyFunctionNode(const size_t start, const BinKind kind, FunctionBox* funbox);
+    JS::Result<ParseNode*>
+    buildFunction(const size_t start, const BinKind kind, ParseNode* name, ListNode* params,
+                  ParseNode* body, FunctionBox* funbox);
+    JS::Result<FunctionBox*>
+    buildFunctionBox(GeneratorKind generatorKind, FunctionAsyncKind functionAsyncKind, FunctionSyntaxKind syntax, ParseNode* name);
+
+    // Add name to a given scope.
+    MOZ_MUST_USE JS::Result<Ok> addScopeName(AssertedScopeKind scopeKind, HandleAtom name,
+                                             ParseContext::Scope* scope,
+                                             DeclarationKind declKind,
+                                             bool isCaptured,
+                                             bool allowDuplicateName);
+
+    void captureFunctionName();
+
+    // Map AssertedScopeKind and AssertedDeclaredKind for single binding to
+    // corresponding ParseContext::Scope to store the binding, and
+    // DeclarationKind for the binding.
+    MOZ_MUST_USE JS::Result<Ok> getDeclaredScope(AssertedScopeKind scopeKind,
+                                                 AssertedDeclaredKind kind,
+                                                 ParseContext::Scope*& scope,
+                                                 DeclarationKind& declKind);
+    MOZ_MUST_USE JS::Result<Ok> getBoundScope(AssertedScopeKind scopeKind,
+                                              ParseContext::Scope*& scope,
+                                              DeclarationKind& declKind);
+
+    MOZ_MUST_USE JS::Result<Ok> checkBinding(JSAtom* name);
+
+    MOZ_MUST_USE JS::Result<Ok> checkPositionalParameterIndices(Handle<GCVector<JSAtom*>> positionalParams,
+                                                                ListNode* params);
+
+    MOZ_MUST_USE JS::Result<Ok> checkFunctionLength(uint32_t expectedLength);
+
+    // When leaving a scope, check that none of its bindings are known closed over and un-marked.
+    MOZ_MUST_USE JS::Result<Ok> checkClosedVars(ParseContext::Scope& scope);
+
+    // As a convenience, a helper that checks the body, parameter, and recursive binding scopes.
+    MOZ_MUST_USE JS::Result<Ok> checkFunctionClosedVars();
+
+    // --- Utilities.
+
+    MOZ_MUST_USE JS::Result<Ok> prependDirectivesToBody(ListNode* body,
+        ListNode* directives);
+
+    MOZ_MUST_USE JS::Result<Ok> prependDirectivesImpl(ListNode* body,
+        ParseNode* directive);
+
+    // Optionally force a strict context without restarting the parse when we see a strict
+    // directive.
+    void forceStrictIfNecessary(SharedContext* sc, ListNode* directives);
+
+  private: // Implement ErrorReporter
+    const JS::ReadOnlyCompileOptions& options_;
+
+    const JS::ReadOnlyCompileOptions& options() const override {
+        return this->options_;
+    }
+
+    void doTrace(JSTracer* trc) final;
+
+  public:
+    virtual ObjectBox* newObjectBox(JSObject* obj) override {
+        MOZ_ASSERT(obj);
+
+        /*
+         * We use JSContext.tempLifoAlloc to allocate parsed objects and place them
+         * on a list in this Parser to ensure GC safety. Thus the tempLifoAlloc
+         * arenas containing the entries must be alive until we are done with
+         * scanning, parsing and code generation for the whole script or top-level
+         * function.
+         */
+
+        ObjectBox* objbox = alloc_.new_<ObjectBox>(obj, traceListHead_);
+        if (!objbox) {
+            ReportOutOfMemory(cx_);
+            return nullptr;
+        }
+
+        traceListHead_ = objbox;
+
+        return objbox;
+    }
+
+
+    virtual ErrorReporter& errorReporter() override {
+        return *this;
+    }
+    virtual const ErrorReporter& errorReporter() const override {
+        return *this;
+    }
+
+    virtual FullParseHandler& astGenerator() override {
+        return factory_;
+    }
+
+    virtual void lineAndColumnAt(size_t offset, uint32_t* line, uint32_t* column) const override {
+        *line = lineAt(offset);
+        *column = columnAt(offset);
+    }
+    virtual uint32_t lineAt(size_t offset) const override {
+        return 0;
+    }
+    virtual uint32_t columnAt(size_t offset) const override {
+        return offset;
+    }
+
+    virtual bool isOnThisLine(size_t offset, uint32_t lineNum, bool *isOnSameLine) const override {
+        if (lineNum != 0) {
+            return false;
+        }
+        *isOnSameLine = true;
+        return true;
+    }
+
+    virtual void currentLineAndColumn(uint32_t* line, uint32_t* column) const override {
+        *line = 0;
+        *column = offset();
+    }
+    size_t offset() const {
+        if (tokenizer_.isSome()) {
+            return tokenizer_->offset();
+        }
+
+        return 0;
+    }
+    virtual bool hasTokenizationStarted() const override {
+        return tokenizer_.isSome();
+    }
+    virtual void reportErrorNoOffsetVA(unsigned errorNumber, va_list args) override;
+    virtual void errorAtVA(uint32_t offset, unsigned errorNumber, va_list* args) override;
+    virtual bool reportExtraWarningErrorNumberVA(UniquePtr<JSErrorNotes> notes, uint32_t offset, unsigned errorNumber, va_list* args) override;
+    virtual const char* getFilename() const override {
+        return this->options_.filename();
+    }
+
+  private: // Implement ErrorReporter
+    mozilla::Maybe<Tokenizer> tokenizer_;
+    VariableDeclarationKind variableDeclarationKind_;
+
+    friend class BinParseContext;
+    friend class AutoVariableDeclarationKind;
+
+    // Helper class: Restore field `variableDeclarationKind` upon leaving a scope.
+    class MOZ_RAII AutoVariableDeclarationKind {
+      public:
+        explicit AutoVariableDeclarationKind(BinASTParser<Tok>* parser
+                                             MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
+            : parser_(parser)
+            , kind(parser->variableDeclarationKind_)
+        {
+            MOZ_GUARD_OBJECT_NOTIFIER_INIT;
+        }
+        ~AutoVariableDeclarationKind() {
+            parser_->variableDeclarationKind_ = kind;
+        }
+        private:
+        BinASTParser<Tok>* parser_;
+        BinASTParser<Tok>::VariableDeclarationKind kind;
+        MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
+    };
+};
+
+class BinParseContext : public ParseContext
+{
+  public:
+    template<typename Tok>
+    BinParseContext(JSContext* cx, BinASTParser<Tok>* parser, SharedContext* sc,
+        Directives* newDirectives)
+        : ParseContext(cx, parser->parseContext_, sc, *parser,
+                       parser->usedNames_, newDirectives, /* isFull = */ true)
+    { }
+};
+
+
+extern template class BinASTParser<BinTokenReaderMultipart>;
+extern template class BinASTParser<BinTokenReaderTester>;
+
+} // namespace frontend
+} // namespace js
+
+#endif // frontend_BinASTParserPerTokenizer_h
deleted file mode 100644
--- a/js/src/frontend/BinSource-auto.cpp
+++ /dev/null
@@ -1,4743 +0,0 @@
-// This file was autogenerated by binjs_generate_spidermonkey,
-// please DO NOT EDIT BY HAND.
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
-* vim: set ts=8 sts=4 et sw=4 tw=99:
-* This Source Code Form is subject to the terms of the Mozilla Public
-* License, v. 2.0. If a copy of the MPL was not distributed with this
-* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-// To generate this file, see the documentation in
-// js/src/frontend/binsource/README.md.
-
-#include "mozilla/ArrayUtils.h"
-#include "mozilla/Casting.h"
-#include "mozilla/Maybe.h"
-#include "mozilla/Move.h"
-#include "mozilla/PodOperations.h"
-#include "mozilla/Vector.h"
-
-#include "frontend/BinSource-macros.h"
-#include "frontend/BinSource.h"
-#include "frontend/BinTokenReaderTester.h"
-#include "frontend/FullParseHandler.h"
-#include "frontend/ParseNode.h"
-#include "frontend/Parser.h"
-#include "frontend/SharedContext.h"
-
-#include "vm/RegExpObject.h"
-
-#include "frontend/ParseContext-inl.h"
-
-namespace js {
-namespace frontend {
-
-// Compare a bunch of `uint8_t` values (as returned by the tokenizer_) with
-// a string literal (and ONLY a string literal).
-template<typename Tok, size_t N>
-bool operator==(const typename Tok::Chars& left, const char (&right)[N]) {
-    return Tok::equals(left, right);
-}
-
-
-// ----- Sums of interfaces (autogenerated, by lexicographical order)
-// Sums of sums are flattened.
-/*
-AssertedMaybePositionalParameterName ::= AssertedParameterName
-    AssertedPositionalParameterName
-    AssertedRestParameterName
-*/
-template<typename Tok> JS::Result<Ok>
-BinASTParser<Tok>::parseAssertedMaybePositionalParameterName(
-        AssertedScopeKind scopeKind,
-        MutableHandle<GCVector<JSAtom*>> positionalParams)
-{
-    BinKind kind;
-    BinFields fields(cx_);
-    AutoTaggedTuple guard(*tokenizer_);
-    const auto start = tokenizer_->offset();
-
-    MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-
-    BINJS_MOZ_TRY_DECL(result, parseSumAssertedMaybePositionalParameterName(start, kind, fields,
-        scopeKind, positionalParams));
-
-    MOZ_TRY(guard.done());
-    return result;
-}
-
-template<typename Tok> JS::Result<Ok>
-BinASTParser<Tok>::parseSumAssertedMaybePositionalParameterName(const size_t start, const BinKind kind, const BinFields& fields,
-        AssertedScopeKind scopeKind,
-        MutableHandle<GCVector<JSAtom*>> positionalParams)
-{
-    Ok result;
-    switch (kind) {
-      case BinKind::AssertedParameterName:
-        return raiseError("FIXME: Not implemented yet in this preview release (AssertedParameterName)");
-      case BinKind::AssertedPositionalParameterName:
-        MOZ_TRY_VAR(result, parseInterfaceAssertedPositionalParameterName(start, kind, fields,
-            scopeKind, positionalParams));
-        break;
-      case BinKind::AssertedRestParameterName:
-        return raiseError("FIXME: Not implemented yet in this preview release (AssertedRestParameterName)");
-      default:
-        return raiseInvalidKind("AssertedMaybePositionalParameterName", kind);
-    }
-    return result;
-}
-
-/*
-AssignmentTarget ::= ArrayAssignmentTarget
-    AssignmentTargetIdentifier
-    ComputedMemberAssignmentTarget
-    ObjectAssignmentTarget
-    StaticMemberAssignmentTarget
-*/
-template<typename Tok> JS::Result<ParseNode*>
-BinASTParser<Tok>::parseAssignmentTarget()
-{
-    BinKind kind;
-    BinFields fields(cx_);
-    AutoTaggedTuple guard(*tokenizer_);
-    const auto start = tokenizer_->offset();
-
-    MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-
-    BINJS_MOZ_TRY_DECL(result, parseSumAssignmentTarget(start, kind, fields));
-
-    MOZ_TRY(guard.done());
-    return result;
-}
-
-template<typename Tok> JS::Result<ParseNode*>
-BinASTParser<Tok>::parseSumAssignmentTarget(const size_t start, const BinKind kind, const BinFields& fields)
-{
-    ParseNode* result;
-    switch (kind) {
-      case BinKind::ArrayAssignmentTarget:
-        MOZ_TRY_VAR(result, parseInterfaceArrayAssignmentTarget(start, kind, fields));
-        break;
-      case BinKind::AssignmentTargetIdentifier:
-        MOZ_TRY_VAR(result, parseInterfaceAssignmentTargetIdentifier(start, kind, fields));
-        break;
-      case BinKind::ComputedMemberAssignmentTarget:
-        MOZ_TRY_VAR(result, parseInterfaceComputedMemberAssignmentTarget(start, kind, fields));
-        break;
-      case BinKind::ObjectAssignmentTarget:
-        MOZ_TRY_VAR(result, parseInterfaceObjectAssignmentTarget(start, kind, fields));
-        break;
-      case BinKind::StaticMemberAssignmentTarget:
-        MOZ_TRY_VAR(result, parseInterfaceStaticMemberAssignmentTarget(start, kind, fields));
-        break;
-      default:
-        return raiseInvalidKind("AssignmentTarget", kind);
-    }
-    return result;
-}
-
-/*
-Binding ::= ArrayBinding
-    BindingIdentifier
-    ObjectBinding
-*/
-template<typename Tok> JS::Result<ParseNode*>
-BinASTParser<Tok>::parseBinding()
-{
-    BinKind kind;
-    BinFields fields(cx_);
-    AutoTaggedTuple guard(*tokenizer_);
-    const auto start = tokenizer_->offset();
-
-    MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-
-    BINJS_MOZ_TRY_DECL(result, parseSumBinding(start, kind, fields));
-
-    MOZ_TRY(guard.done());
-    return result;
-}
-
-template<typename Tok> JS::Result<ParseNode*>
-BinASTParser<Tok>::parseSumBinding(const size_t start, const BinKind kind, const BinFields& fields)
-{
-    ParseNode* result;
-    switch (kind) {
-      case BinKind::ArrayBinding:
-        MOZ_TRY_VAR(result, parseInterfaceArrayBinding(start, kind, fields));
-        break;
-      case BinKind::BindingIdentifier:
-        MOZ_TRY_VAR(result, parseInterfaceBindingIdentifier(start, kind, fields));
-        break;
-      case BinKind::ObjectBinding:
-        MOZ_TRY_VAR(result, parseInterfaceObjectBinding(start, kind, fields));
-        break;
-      default:
-        return raiseInvalidKind("Binding", kind);
-    }
-    return result;
-}
-
-/*
-Expression ::= ArrayExpression
-    AssignmentExpression
-    AwaitExpression
-    BinaryExpression
-    CallExpression
-    ClassExpression
-    CompoundAssignmentExpression
-    ComputedMemberExpression
-    ConditionalExpression
-    EagerArrowExpressionWithExpression
-    EagerArrowExpressionWithFunctionBody
-    EagerFunctionExpression
-    IdentifierExpression
-    LazyArrowExpressionWithExpression
-    LazyArrowExpressionWithFunctionBody
-    LazyFunctionExpression
-    LiteralBooleanExpression
-    LiteralInfinityExpression
-    LiteralNullExpression
-    LiteralNumericExpression
-    LiteralRegExpExpression
-    LiteralStringExpression
-    NewExpression
-    NewTargetExpression
-    ObjectExpression
-    StaticMemberExpression
-    TemplateExpression
-    ThisExpression
-    UnaryExpression
-    UpdateExpression
-    YieldExpression
-    YieldStarExpression
-*/
-template<typename Tok> JS::Result<ParseNode*>
-BinASTParser<Tok>::parseExpression()
-{
-    BinKind kind;
-    BinFields fields(cx_);
-    AutoTaggedTuple guard(*tokenizer_);
-    const auto start = tokenizer_->offset();
-
-    MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-
-    BINJS_MOZ_TRY_DECL(result, parseSumExpression(start, kind, fields));
-
-    MOZ_TRY(guard.done());
-    return result;
-}
-
-template<typename Tok> JS::Result<ParseNode*>
-BinASTParser<Tok>::parseSumExpression(const size_t start, const BinKind kind, const BinFields& fields)
-{
-    ParseNode* result;
-    switch (kind) {
-      case BinKind::ArrayExpression:
-        MOZ_TRY_VAR(result, parseInterfaceArrayExpression(start, kind, fields));
-        break;
-      case BinKind::AssignmentExpression:
-        MOZ_TRY_VAR(result, parseInterfaceAssignmentExpression(start, kind, fields));
-        break;
-      case BinKind::AwaitExpression:
-        MOZ_TRY_VAR(result, parseInterfaceAwaitExpression(start, kind, fields));
-        break;
-      case BinKind::BinaryExpression:
-        MOZ_TRY_VAR(result, parseInterfaceBinaryExpression(start, kind, fields));
-        break;
-      case BinKind::CallExpression:
-        MOZ_TRY_VAR(result, parseInterfaceCallExpression(start, kind, fields));
-        break;
-      case BinKind::ClassExpression:
-        MOZ_TRY_VAR(result, parseInterfaceClassExpression(start, kind, fields));
-        break;
-      case BinKind::CompoundAssignmentExpression:
-        MOZ_TRY_VAR(result, parseInterfaceCompoundAssignmentExpression(start, kind, fields));
-        break;
-      case BinKind::ComputedMemberExpression:
-        MOZ_TRY_VAR(result, parseInterfaceComputedMemberExpression(start, kind, fields));
-        break;
-      case BinKind::ConditionalExpression:
-        MOZ_TRY_VAR(result, parseInterfaceConditionalExpression(start, kind, fields));
-        break;
-      case BinKind::EagerArrowExpressionWithExpression:
-        MOZ_TRY_VAR(result, parseInterfaceEagerArrowExpressionWithExpression(start, kind, fields));
-        break;
-      case BinKind::EagerArrowExpressionWithFunctionBody:
-        MOZ_TRY_VAR(result, parseInterfaceEagerArrowExpressionWithFunctionBody(start, kind, fields));
-        break;
-      case BinKind::EagerFunctionExpression:
-        MOZ_TRY_VAR(result, parseInterfaceEagerFunctionExpression(start, kind, fields));
-        break;
-      case BinKind::IdentifierExpression:
-        MOZ_TRY_VAR(result, parseInterfaceIdentifierExpression(start, kind, fields));
-        break;
-      case BinKind::LazyArrowExpressionWithExpression:
-        MOZ_TRY_VAR(result, parseInterfaceLazyArrowExpressionWithExpression(start, kind, fields));
-        break;
-      case BinKind::LazyArrowExpressionWithFunctionBody:
-        MOZ_TRY_VAR(result, parseInterfaceLazyArrowExpressionWithFunctionBody(start, kind, fields));
-        break;
-      case BinKind::LazyFunctionExpression:
-        MOZ_TRY_VAR(result, parseInterfaceLazyFunctionExpression(start, kind, fields));
-        break;
-      case BinKind::LiteralBooleanExpression:
-        MOZ_TRY_VAR(result, parseInterfaceLiteralBooleanExpression(start, kind, fields));
-        break;
-      case BinKind::LiteralInfinityExpression:
-        MOZ_TRY_VAR(result, parseInterfaceLiteralInfinityExpression(start, kind, fields));
-        break;
-      case BinKind::LiteralNullExpression:
-        MOZ_TRY_VAR(result, parseInterfaceLiteralNullExpression(start, kind, fields));
-        break;
-      case BinKind::LiteralNumericExpression:
-        MOZ_TRY_VAR(result, parseInterfaceLiteralNumericExpression(start, kind, fields));
-        break;
-      case BinKind::LiteralRegExpExpression:
-        MOZ_TRY_VAR(result, parseInterfaceLiteralRegExpExpression(start, kind, fields));
-        break;
-      case BinKind::LiteralStringExpression:
-        MOZ_TRY_VAR(result, parseInterfaceLiteralStringExpression(start, kind, fields));
-        break;
-      case BinKind::NewExpression:
-        MOZ_TRY_VAR(result, parseInterfaceNewExpression(start, kind, fields));
-        break;
-      case BinKind::NewTargetExpression:
-        MOZ_TRY_VAR(result, parseInterfaceNewTargetExpression(start, kind, fields));
-        break;
-      case BinKind::ObjectExpression:
-        MOZ_TRY_VAR(result, parseInterfaceObjectExpression(start, kind, fields));
-        break;
-      case BinKind::StaticMemberExpression:
-        MOZ_TRY_VAR(result, parseInterfaceStaticMemberExpression(start, kind, fields));
-        break;
-      case BinKind::TemplateExpression:
-        MOZ_TRY_VAR(result, parseInterfaceTemplateExpression(start, kind, fields));
-        break;
-      case BinKind::ThisExpression:
-        MOZ_TRY_VAR(result, parseInterfaceThisExpression(start, kind, fields));
-        break;
-      case BinKind::UnaryExpression:
-        MOZ_TRY_VAR(result, parseInterfaceUnaryExpression(start, kind, fields));
-        break;
-      case BinKind::UpdateExpression:
-        MOZ_TRY_VAR(result, parseInterfaceUpdateExpression(start, kind, fields));
-        break;
-      case BinKind::YieldExpression:
-        MOZ_TRY_VAR(result, parseInterfaceYieldExpression(start, kind, fields));
-        break;
-      case BinKind::YieldStarExpression:
-        MOZ_TRY_VAR(result, parseInterfaceYieldStarExpression(start, kind, fields));
-        break;
-      default:
-        return raiseInvalidKind("Expression", kind);
-    }
-    return result;
-}
-
-/*
-ExpressionOrSuper ::= ArrayExpression
-    AssignmentExpression
-    AwaitExpression
-    BinaryExpression
-    CallExpression
-    ClassExpression
-    CompoundAssignmentExpression
-    ComputedMemberExpression
-    ConditionalExpression
-    EagerArrowExpressionWithExpression
-    EagerArrowExpressionWithFunctionBody
-    EagerFunctionExpression
-    IdentifierExpression
-    LazyArrowExpressionWithExpression
-    LazyArrowExpressionWithFunctionBody
-    LazyFunctionExpression
-    LiteralBooleanExpression
-    LiteralInfinityExpression
-    LiteralNullExpression
-    LiteralNumericExpression
-    LiteralRegExpExpression
-    LiteralStringExpression
-    NewExpression
-    NewTargetExpression
-    ObjectExpression
-    StaticMemberExpression
-    Super
-    TemplateExpression
-    ThisExpression
-    UnaryExpression
-    UpdateExpression
-    YieldExpression
-    YieldStarExpression
-*/
-template<typename Tok> JS::Result<ParseNode*>
-BinASTParser<Tok>::parseExpressionOrSuper()
-{
-    BinKind kind;
-    BinFields fields(cx_);
-    AutoTaggedTuple guard(*tokenizer_);
-    const auto start = tokenizer_->offset();
-
-    MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-
-    BINJS_MOZ_TRY_DECL(result, parseSumExpressionOrSuper(start, kind, fields));
-
-    MOZ_TRY(guard.done());
-    return result;
-}
-
-template<typename Tok> JS::Result<ParseNode*>
-BinASTParser<Tok>::parseSumExpressionOrSuper(const size_t start, const BinKind kind, const BinFields& fields)
-{
-    ParseNode* result;
-    switch (kind) {
-      case BinKind::ArrayExpression:
-        MOZ_TRY_VAR(result, parseInterfaceArrayExpression(start, kind, fields));
-        break;
-      case BinKind::AssignmentExpression:
-        MOZ_TRY_VAR(result, parseInterfaceAssignmentExpression(start, kind, fields));
-        break;
-      case BinKind::AwaitExpression:
-        MOZ_TRY_VAR(result, parseInterfaceAwaitExpression(start, kind, fields));
-        break;
-      case BinKind::BinaryExpression:
-        MOZ_TRY_VAR(result, parseInterfaceBinaryExpression(start, kind, fields));
-        break;
-      case BinKind::CallExpression:
-        MOZ_TRY_VAR(result, parseInterfaceCallExpression(start, kind, fields));
-        break;
-      case BinKind::ClassExpression:
-        MOZ_TRY_VAR(result, parseInterfaceClassExpression(start, kind, fields));
-        break;
-      case BinKind::CompoundAssignmentExpression:
-        MOZ_TRY_VAR(result, parseInterfaceCompoundAssignmentExpression(start, kind, fields));
-        break;
-      case BinKind::ComputedMemberExpression:
-        MOZ_TRY_VAR(result, parseInterfaceComputedMemberExpression(start, kind, fields));
-        break;
-      case BinKind::ConditionalExpression:
-        MOZ_TRY_VAR(result, parseInterfaceConditionalExpression(start, kind, fields));
-        break;
-      case BinKind::EagerArrowExpressionWithExpression:
-        MOZ_TRY_VAR(result, parseInterfaceEagerArrowExpressionWithExpression(start, kind, fields));
-        break;
-      case BinKind::EagerArrowExpressionWithFunctionBody:
-        MOZ_TRY_VAR(result, parseInterfaceEagerArrowExpressionWithFunctionBody(start, kind, fields));
-        break;
-      case BinKind::EagerFunctionExpression:
-        MOZ_TRY_VAR(result, parseInterfaceEagerFunctionExpression(start, kind, fields));
-        break;
-      case BinKind::IdentifierExpression:
-        MOZ_TRY_VAR(result, parseInterfaceIdentifierExpression(start, kind, fields));
-        break;
-      case BinKind::LazyArrowExpressionWithExpression:
-        MOZ_TRY_VAR(result, parseInterfaceLazyArrowExpressionWithExpression(start, kind, fields));
-        break;
-      case BinKind::LazyArrowExpressionWithFunctionBody:
-        MOZ_TRY_VAR(result, parseInterfaceLazyArrowExpressionWithFunctionBody(start, kind, fields));
-        break;
-      case BinKind::LazyFunctionExpression:
-        MOZ_TRY_VAR(result, parseInterfaceLazyFunctionExpression(start, kind, fields));
-        break;
-      case BinKind::LiteralBooleanExpression:
-        MOZ_TRY_VAR(result, parseInterfaceLiteralBooleanExpression(start, kind, fields));
-        break;
-      case BinKind::LiteralInfinityExpression:
-        MOZ_TRY_VAR(result, parseInterfaceLiteralInfinityExpression(start, kind, fields));
-        break;
-      case BinKind::LiteralNullExpression:
-        MOZ_TRY_VAR(result, parseInterfaceLiteralNullExpression(start, kind, fields));
-        break;
-      case BinKind::LiteralNumericExpression:
-        MOZ_TRY_VAR(result, parseInterfaceLiteralNumericExpression(start, kind, fields));
-        break;
-      case BinKind::LiteralRegExpExpression:
-        MOZ_TRY_VAR(result, parseInterfaceLiteralRegExpExpression(start, kind, fields));
-        break;
-      case BinKind::LiteralStringExpression:
-        MOZ_TRY_VAR(result, parseInterfaceLiteralStringExpression(start, kind, fields));
-        break;
-      case BinKind::NewExpression:
-        MOZ_TRY_VAR(result, parseInterfaceNewExpression(start, kind, fields));
-        break;
-      case BinKind::NewTargetExpression:
-        MOZ_TRY_VAR(result, parseInterfaceNewTargetExpression(start, kind, fields));
-        break;
-      case BinKind::ObjectExpression:
-        MOZ_TRY_VAR(result, parseInterfaceObjectExpression(start, kind, fields));
-        break;
-      case BinKind::StaticMemberExpression:
-        MOZ_TRY_VAR(result, parseInterfaceStaticMemberExpression(start, kind, fields));
-        break;
-      case BinKind::Super:
-        MOZ_TRY_VAR(result, parseInterfaceSuper(start, kind, fields));
-        break;
-      case BinKind::TemplateExpression:
-        MOZ_TRY_VAR(result, parseInterfaceTemplateExpression(start, kind, fields));
-        break;
-      case BinKind::ThisExpression:
-        MOZ_TRY_VAR(result, parseInterfaceThisExpression(start, kind, fields));
-        break;
-      case BinKind::UnaryExpression:
-        MOZ_TRY_VAR(result, parseInterfaceUnaryExpression(start, kind, fields));
-        break;
-      case BinKind::UpdateExpression:
-        MOZ_TRY_VAR(result, parseInterfaceUpdateExpression(start, kind, fields));
-        break;
-      case BinKind::YieldExpression:
-        MOZ_TRY_VAR(result, parseInterfaceYieldExpression(start, kind, fields));
-        break;
-      case BinKind::YieldStarExpression:
-        MOZ_TRY_VAR(result, parseInterfaceYieldStarExpression(start, kind, fields));
-        break;
-      default:
-        return raiseInvalidKind("ExpressionOrSuper", kind);
-    }
-    return result;
-}
-
-/*
-ForInOfBindingOrAssignmentTarget ::= ArrayAssignmentTarget
-    AssignmentTargetIdentifier
-    ComputedMemberAssignmentTarget
-    ForInOfBinding
-    ObjectAssignmentTarget
-    StaticMemberAssignmentTarget
-*/
-template<typename Tok> JS::Result<ParseNode*>
-BinASTParser<Tok>::parseForInOfBindingOrAssignmentTarget()
-{
-    BinKind kind;
-    BinFields fields(cx_);
-    AutoTaggedTuple guard(*tokenizer_);
-    const auto start = tokenizer_->offset();
-
-    MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-
-    BINJS_MOZ_TRY_DECL(result, parseSumForInOfBindingOrAssignmentTarget(start, kind, fields));
-
-    MOZ_TRY(guard.done());
-    return result;
-}
-
-template<typename Tok> JS::Result<ParseNode*>
-BinASTParser<Tok>::parseSumForInOfBindingOrAssignmentTarget(const size_t start, const BinKind kind, const BinFields& fields)
-{
-    ParseNode* result;
-    switch (kind) {
-      case BinKind::ArrayAssignmentTarget:
-        MOZ_TRY_VAR(result, parseInterfaceArrayAssignmentTarget(start, kind, fields));
-        break;
-      case BinKind::AssignmentTargetIdentifier:
-        MOZ_TRY_VAR(result, parseInterfaceAssignmentTargetIdentifier(start, kind, fields));
-        break;
-      case BinKind::ComputedMemberAssignmentTarget:
-        MOZ_TRY_VAR(result, parseInterfaceComputedMemberAssignmentTarget(start, kind, fields));
-        break;
-      case BinKind::ForInOfBinding:
-        MOZ_TRY_VAR(result, parseInterfaceForInOfBinding(start, kind, fields));
-        break;
-      case BinKind::ObjectAssignmentTarget:
-        MOZ_TRY_VAR(result, parseInterfaceObjectAssignmentTarget(start, kind, fields));
-        break;
-      case BinKind::StaticMemberAssignmentTarget:
-        MOZ_TRY_VAR(result, parseInterfaceStaticMemberAssignmentTarget(start, kind, fields));
-        break;
-      default:
-        return raiseInvalidKind("ForInOfBindingOrAssignmentTarget", kind);
-    }
-    return result;
-}
-
-/*
-ObjectProperty ::= DataProperty
-    EagerGetter
-    EagerMethod
-    EagerSetter
-    LazyGetter
-    LazyMethod
-    LazySetter
-    ShorthandProperty
-*/
-template<typename Tok> JS::Result<ParseNode*>
-BinASTParser<Tok>::parseObjectProperty()
-{
-    BinKind kind;
-    BinFields fields(cx_);
-    AutoTaggedTuple guard(*tokenizer_);
-    const auto start = tokenizer_->offset();
-
-    MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-
-    BINJS_MOZ_TRY_DECL(result, parseSumObjectProperty(start, kind, fields));
-
-    MOZ_TRY(guard.done());
-    return result;
-}
-
-template<typename Tok> JS::Result<ParseNode*>
-BinASTParser<Tok>::parseSumObjectProperty(const size_t start, const BinKind kind, const BinFields& fields)
-{
-    ParseNode* result;
-    switch (kind) {
-      case BinKind::DataProperty:
-        MOZ_TRY_VAR(result, parseInterfaceDataProperty(start, kind, fields));
-        break;
-      case BinKind::EagerGetter:
-        MOZ_TRY_VAR(result, parseInterfaceEagerGetter(start, kind, fields));
-        break;
-      case BinKind::EagerMethod:
-        MOZ_TRY_VAR(result, parseInterfaceEagerMethod(start, kind, fields));
-        break;
-      case BinKind::EagerSetter:
-        MOZ_TRY_VAR(result, parseInterfaceEagerSetter(start, kind, fields));
-        break;
-      case BinKind::LazyGetter:
-        MOZ_TRY_VAR(result, parseInterfaceLazyGetter(start, kind, fields));
-        break;
-      case BinKind::LazyMethod:
-        MOZ_TRY_VAR(result, parseInterfaceLazyMethod(start, kind, fields));
-        break;
-      case BinKind::LazySetter:
-        MOZ_TRY_VAR(result, parseInterfaceLazySetter(start, kind, fields));
-        break;
-      case BinKind::ShorthandProperty:
-        MOZ_TRY_VAR(result, parseInterfaceShorthandProperty(start, kind, fields));
-        break;
-      default:
-        return raiseInvalidKind("ObjectProperty", kind);
-    }
-    return result;
-}
-
-/*
-Parameter ::= ArrayBinding
-    BindingIdentifier
-    BindingWithInitializer
-    ObjectBinding
-*/
-template<typename Tok> JS::Result<ParseNode*>
-BinASTParser<Tok>::parseParameter()
-{
-    BinKind kind;
-    BinFields fields(cx_);
-    AutoTaggedTuple guard(*tokenizer_);
-    const auto start = tokenizer_->offset();
-
-    MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-
-    BINJS_MOZ_TRY_DECL(result, parseSumParameter(start, kind, fields));
-
-    MOZ_TRY(guard.done());
-    return result;
-}
-
-template<typename Tok> JS::Result<ParseNode*>
-BinASTParser<Tok>::parseSumParameter(const size_t start, const BinKind kind, const BinFields& fields)
-{
-    ParseNode* result;
-    switch (kind) {
-      case BinKind::ArrayBinding:
-        MOZ_TRY_VAR(result, parseInterfaceArrayBinding(start, kind, fields));
-        break;
-      case BinKind::BindingIdentifier:
-        MOZ_TRY_VAR(result, parseInterfaceBindingIdentifier(start, kind, fields));
-        if (!parseContext_->positionalFormalParameterNames().append(result->template as<NameNode>().atom())) {
-            return raiseOOM();
-        }
-        if (parseContext_->isFunctionBox()) {
-            parseContext_->functionBox()->length++;
-        }
-        break;
-      case BinKind::BindingWithInitializer:
-        MOZ_TRY_VAR(result, parseInterfaceBindingWithInitializer(start, kind, fields));
-        break;
-      case BinKind::ObjectBinding:
-        MOZ_TRY_VAR(result, parseInterfaceObjectBinding(start, kind, fields));
-        break;
-      default:
-        return raiseInvalidKind("Parameter", kind);
-    }
-    return result;
-}
-
-/*
-Program ::= Module
-    Script
-*/
-template<typename Tok> JS::Result<ParseNode*>
-BinASTParser<Tok>::parseProgram()
-{
-    BinKind kind;
-    BinFields fields(cx_);
-    AutoTaggedTuple guard(*tokenizer_);
-    const auto start = tokenizer_->offset();
-
-    MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-
-    BINJS_MOZ_TRY_DECL(result, parseSumProgram(start, kind, fields));
-
-    MOZ_TRY(guard.done());
-    return result;
-}
-
-template<typename Tok> JS::Result<ParseNode*>
-BinASTParser<Tok>::parseSumProgram(const size_t start, const BinKind kind, const BinFields& fields)
-{
-    ParseNode* result;
-    switch (kind) {
-      case BinKind::Module:
-        MOZ_TRY_VAR(result, parseInterfaceModule(start, kind, fields));
-        break;
-      case BinKind::Script:
-        MOZ_TRY_VAR(result, parseInterfaceScript(start, kind, fields));
-        break;
-      default:
-        return raiseInvalidKind("Program", kind);
-    }
-    return result;
-}
-
-/*
-PropertyName ::= ComputedPropertyName
-    LiteralPropertyName
-*/
-template<typename Tok> JS::Result<ParseNode*>
-BinASTParser<Tok>::parsePropertyName()
-{
-    BinKind kind;
-    BinFields fields(cx_);
-    AutoTaggedTuple guard(*tokenizer_);
-    const auto start = tokenizer_->offset();
-
-    MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-
-    BINJS_MOZ_TRY_DECL(result, parseSumPropertyName(start, kind, fields));
-
-    MOZ_TRY(guard.done());
-    return result;
-}
-
-template<typename Tok> JS::Result<ParseNode*>
-BinASTParser<Tok>::parseSumPropertyName(const size_t start, const BinKind kind, const BinFields& fields)
-{
-    ParseNode* result;
-    switch (kind) {
-      case BinKind::ComputedPropertyName:
-        MOZ_TRY_VAR(result, parseInterfaceComputedPropertyName(start, kind, fields));
-        break;
-      case BinKind::LiteralPropertyName:
-        MOZ_TRY_VAR(result, parseInterfaceLiteralPropertyName(start, kind, fields));
-        break;
-      default:
-        return raiseInvalidKind("PropertyName", kind);
-    }
-    return result;
-}
-
-/*
-SimpleAssignmentTarget ::= AssignmentTargetIdentifier
-    ComputedMemberAssignmentTarget
-    StaticMemberAssignmentTarget
-*/
-template<typename Tok> JS::Result<ParseNode*>
-BinASTParser<Tok>::parseSimpleAssignmentTarget()
-{
-    BinKind kind;
-    BinFields fields(cx_);
-    AutoTaggedTuple guard(*tokenizer_);
-    const auto start = tokenizer_->offset();
-
-    MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-
-    BINJS_MOZ_TRY_DECL(result, parseSumSimpleAssignmentTarget(start, kind, fields));
-
-    MOZ_TRY(guard.done());
-    return result;
-}
-
-template<typename Tok> JS::Result<ParseNode*>
-BinASTParser<Tok>::parseSumSimpleAssignmentTarget(const size_t start, const BinKind kind, const BinFields& fields)
-{
-    ParseNode* result;
-    switch (kind) {
-      case BinKind::AssignmentTargetIdentifier:
-        MOZ_TRY_VAR(result, parseInterfaceAssignmentTargetIdentifier(start, kind, fields));
-        break;
-      case BinKind::ComputedMemberAssignmentTarget:
-        MOZ_TRY_VAR(result, parseInterfaceComputedMemberAssignmentTarget(start, kind, fields));
-        break;
-      case BinKind::StaticMemberAssignmentTarget:
-        MOZ_TRY_VAR(result, parseInterfaceStaticMemberAssignmentTarget(start, kind, fields));
-        break;
-      default:
-        return raiseInvalidKind("SimpleAssignmentTarget", kind);
-    }
-    return result;
-}
-
-/*
-SpreadElementOrExpression ::= ArrayExpression
-    AssignmentExpression
-    AwaitExpression
-    BinaryExpression
-    CallExpression
-    ClassExpression
-    CompoundAssignmentExpression
-    ComputedMemberExpression
-    ConditionalExpression
-    EagerArrowExpressionWithExpression
-    EagerArrowExpressionWithFunctionBody
-    EagerFunctionExpression
-    IdentifierExpression
-    LazyArrowExpressionWithExpression
-    LazyArrowExpressionWithFunctionBody
-    LazyFunctionExpression
-    LiteralBooleanExpression
-    LiteralInfinityExpression
-    LiteralNullExpression
-    LiteralNumericExpression
-    LiteralRegExpExpression
-    LiteralStringExpression
-    NewExpression
-    NewTargetExpression
-    ObjectExpression
-    SpreadElement
-    StaticMemberExpression
-    TemplateExpression
-    ThisExpression
-    UnaryExpression
-    UpdateExpression
-    YieldExpression
-    YieldStarExpression
-*/
-template<typename Tok> JS::Result<ParseNode*>
-BinASTParser<Tok>::parseSpreadElementOrExpression()
-{
-    BinKind kind;
-    BinFields fields(cx_);
-    AutoTaggedTuple guard(*tokenizer_);
-    const auto start = tokenizer_->offset();
-
-    MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-
-    BINJS_MOZ_TRY_DECL(result, parseSumSpreadElementOrExpression(start, kind, fields));
-
-    MOZ_TRY(guard.done());
-    return result;
-}
-
-template<typename Tok> JS::Result<ParseNode*>
-BinASTParser<Tok>::parseSumSpreadElementOrExpression(const size_t start, const BinKind kind, const BinFields& fields)
-{
-    ParseNode* result;
-    switch (kind) {
-      case BinKind::ArrayExpression:
-        MOZ_TRY_VAR(result, parseInterfaceArrayExpression(start, kind, fields));
-        break;
-      case BinKind::AssignmentExpression:
-        MOZ_TRY_VAR(result, parseInterfaceAssignmentExpression(start, kind, fields));
-        break;
-      case BinKind::AwaitExpression:
-        MOZ_TRY_VAR(result, parseInterfaceAwaitExpression(start, kind, fields));
-        break;
-      case BinKind::BinaryExpression:
-        MOZ_TRY_VAR(result, parseInterfaceBinaryExpression(start, kind, fields));
-        break;
-      case BinKind::CallExpression:
-        MOZ_TRY_VAR(result, parseInterfaceCallExpression(start, kind, fields));
-        break;
-      case BinKind::ClassExpression:
-        MOZ_TRY_VAR(result, parseInterfaceClassExpression(start, kind, fields));
-        break;
-      case BinKind::CompoundAssignmentExpression:
-        MOZ_TRY_VAR(result, parseInterfaceCompoundAssignmentExpression(start, kind, fields));
-        break;
-      case BinKind::ComputedMemberExpression:
-        MOZ_TRY_VAR(result, parseInterfaceComputedMemberExpression(start, kind, fields));
-        break;
-      case BinKind::ConditionalExpression:
-        MOZ_TRY_VAR(result, parseInterfaceConditionalExpression(start, kind, fields));
-        break;
-      case BinKind::EagerArrowExpressionWithExpression:
-        MOZ_TRY_VAR(result, parseInterfaceEagerArrowExpressionWithExpression(start, kind, fields));
-        break;
-      case BinKind::EagerArrowExpressionWithFunctionBody:
-        MOZ_TRY_VAR(result, parseInterfaceEagerArrowExpressionWithFunctionBody(start, kind, fields));
-        break;
-      case BinKind::EagerFunctionExpression:
-        MOZ_TRY_VAR(result, parseInterfaceEagerFunctionExpression(start, kind, fields));
-        break;
-      case BinKind::IdentifierExpression:
-        MOZ_TRY_VAR(result, parseInterfaceIdentifierExpression(start, kind, fields));
-        break;
-      case BinKind::LazyArrowExpressionWithExpression:
-        MOZ_TRY_VAR(result, parseInterfaceLazyArrowExpressionWithExpression(start, kind, fields));
-        break;
-      case BinKind::LazyArrowExpressionWithFunctionBody:
-        MOZ_TRY_VAR(result, parseInterfaceLazyArrowExpressionWithFunctionBody(start, kind, fields));
-        break;
-      case BinKind::LazyFunctionExpression:
-        MOZ_TRY_VAR(result, parseInterfaceLazyFunctionExpression(start, kind, fields));
-        break;
-      case BinKind::LiteralBooleanExpression:
-        MOZ_TRY_VAR(result, parseInterfaceLiteralBooleanExpression(start, kind, fields));
-        break;
-      case BinKind::LiteralInfinityExpression:
-        MOZ_TRY_VAR(result, parseInterfaceLiteralInfinityExpression(start, kind, fields));
-        break;
-      case BinKind::LiteralNullExpression:
-        MOZ_TRY_VAR(result, parseInterfaceLiteralNullExpression(start, kind, fields));
-        break;
-      case BinKind::LiteralNumericExpression:
-        MOZ_TRY_VAR(result, parseInterfaceLiteralNumericExpression(start, kind, fields));
-        break;
-      case BinKind::LiteralRegExpExpression:
-        MOZ_TRY_VAR(result, parseInterfaceLiteralRegExpExpression(start, kind, fields));
-        break;
-      case BinKind::LiteralStringExpression:
-        MOZ_TRY_VAR(result, parseInterfaceLiteralStringExpression(start, kind, fields));
-        break;
-      case BinKind::NewExpression:
-        MOZ_TRY_VAR(result, parseInterfaceNewExpression(start, kind, fields));
-        break;
-      case BinKind::NewTargetExpression:
-        MOZ_TRY_VAR(result, parseInterfaceNewTargetExpression(start, kind, fields));
-        break;
-      case BinKind::ObjectExpression:
-        MOZ_TRY_VAR(result, parseInterfaceObjectExpression(start, kind, fields));
-        break;
-      case BinKind::SpreadElement:
-        MOZ_TRY_VAR(result, parseInterfaceSpreadElement(start, kind, fields));
-        break;
-      case BinKind::StaticMemberExpression:
-        MOZ_TRY_VAR(result, parseInterfaceStaticMemberExpression(start, kind, fields));
-        break;
-      case BinKind::TemplateExpression:
-        MOZ_TRY_VAR(result, parseInterfaceTemplateExpression(start, kind, fields));
-        break;
-      case BinKind::ThisExpression:
-        MOZ_TRY_VAR(result, parseInterfaceThisExpression(start, kind, fields));
-        break;
-      case BinKind::UnaryExpression:
-        MOZ_TRY_VAR(result, parseInterfaceUnaryExpression(start, kind, fields));
-        break;
-      case BinKind::UpdateExpression:
-        MOZ_TRY_VAR(result, parseInterfaceUpdateExpression(start, kind, fields));
-        break;
-      case BinKind::YieldExpression:
-        MOZ_TRY_VAR(result, parseInterfaceYieldExpression(start, kind, fields));
-        break;
-      case BinKind::YieldStarExpression:
-        MOZ_TRY_VAR(result, parseInterfaceYieldStarExpression(start, kind, fields));
-        break;
-      default:
-        return raiseInvalidKind("SpreadElementOrExpression", kind);
-    }
-    return result;
-}
-
-/*
-Statement ::= Block
-    BreakStatement
-    ClassDeclaration
-    ContinueStatement
-    DebuggerStatement
-    DoWhileStatement
-    EagerFunctionDeclaration
-    EmptyStatement
-    ExpressionStatement
-    ForInStatement
-    ForOfStatement
-    ForStatement
-    IfStatement
-    LabelledStatement
-    LazyFunctionDeclaration
-    ReturnStatement
-    SwitchStatement
-    SwitchStatementWithDefault
-    ThrowStatement
-    TryCatchStatement
-    TryFinallyStatement
-    VariableDeclaration
-    WhileStatement
-    WithStatement
-*/
-template<typename Tok> JS::Result<ParseNode*>
-BinASTParser<Tok>::parseStatement()
-{
-    BinKind kind;
-    BinFields fields(cx_);
-    AutoTaggedTuple guard(*tokenizer_);
-    const auto start = tokenizer_->offset();
-
-    MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-
-    BINJS_MOZ_TRY_DECL(result, parseSumStatement(start, kind, fields));
-
-    MOZ_TRY(guard.done());
-    return result;
-}
-
-template<typename Tok> JS::Result<ParseNode*>
-BinASTParser<Tok>::parseSumStatement(const size_t start, const BinKind kind, const BinFields& fields)
-{
-    ParseNode* result;
-    switch (kind) {
-      case BinKind::Block:
-        MOZ_TRY_VAR(result, parseInterfaceBlock(start, kind, fields));
-        break;
-      case BinKind::BreakStatement:
-        MOZ_TRY_VAR(result, parseInterfaceBreakStatement(start, kind, fields));
-        break;
-      case BinKind::ClassDeclaration:
-        MOZ_TRY_VAR(result, parseInterfaceClassDeclaration(start, kind, fields));
-        break;
-      case BinKind::ContinueStatement:
-        MOZ_TRY_VAR(result, parseInterfaceContinueStatement(start, kind, fields));
-        break;
-      case BinKind::DebuggerStatement:
-        MOZ_TRY_VAR(result, parseInterfaceDebuggerStatement(start, kind, fields));
-        break;
-      case BinKind::DoWhileStatement:
-        MOZ_TRY_VAR(result, parseInterfaceDoWhileStatement(start, kind, fields));
-        break;
-      case BinKind::EagerFunctionDeclaration:
-        MOZ_TRY_VAR(result, parseInterfaceEagerFunctionDeclaration(start, kind, fields));
-        break;
-      case BinKind::EmptyStatement:
-        MOZ_TRY_VAR(result, parseInterfaceEmptyStatement(start, kind, fields));
-        break;
-      case BinKind::ExpressionStatement:
-        MOZ_TRY_VAR(result, parseInterfaceExpressionStatement(start, kind, fields));
-        break;
-      case BinKind::ForInStatement:
-        MOZ_TRY_VAR(result, parseInterfaceForInStatement(start, kind, fields));
-        break;
-      case BinKind::ForOfStatement:
-        MOZ_TRY_VAR(result, parseInterfaceForOfStatement(start, kind, fields));
-        break;
-      case BinKind::ForStatement:
-        MOZ_TRY_VAR(result, parseInterfaceForStatement(start, kind, fields));
-        break;
-      case BinKind::IfStatement:
-        MOZ_TRY_VAR(result, parseInterfaceIfStatement(start, kind, fields));
-        break;
-      case BinKind::LabelledStatement:
-        MOZ_TRY_VAR(result, parseInterfaceLabelledStatement(start, kind, fields));
-        break;
-      case BinKind::LazyFunctionDeclaration:
-        MOZ_TRY_VAR(result, parseInterfaceLazyFunctionDeclaration(start, kind, fields));
-        break;
-      case BinKind::ReturnStatement:
-        MOZ_TRY_VAR(result, parseInterfaceReturnStatement(start, kind, fields));
-        break;
-      case BinKind::SwitchStatement:
-        MOZ_TRY_VAR(result, parseInterfaceSwitchStatement(start, kind, fields));
-        break;
-      case BinKind::SwitchStatementWithDefault:
-        MOZ_TRY_VAR(result, parseInterfaceSwitchStatementWithDefault(start, kind, fields));
-        break;
-      case BinKind::ThrowStatement:
-        MOZ_TRY_VAR(result, parseInterfaceThrowStatement(start, kind, fields));
-        break;
-      case BinKind::TryCatchStatement:
-        MOZ_TRY_VAR(result, parseInterfaceTryCatchStatement(start, kind, fields));
-        break;
-      case BinKind::TryFinallyStatement:
-        MOZ_TRY_VAR(result, parseInterfaceTryFinallyStatement(start, kind, fields));
-        break;
-      case BinKind::VariableDeclaration:
-        MOZ_TRY_VAR(result, parseInterfaceVariableDeclaration(start, kind, fields));
-        break;
-      case BinKind::WhileStatement:
-        MOZ_TRY_VAR(result, parseInterfaceWhileStatement(start, kind, fields));
-        break;
-      case BinKind::WithStatement:
-        MOZ_TRY_VAR(result, parseInterfaceWithStatement(start, kind, fields));
-        break;
-      default:
-        return raiseInvalidKind("Statement", kind);
-    }
-    return result;
-}
-
-
-template<typename Tok> JS::Result<ParseNode*>
-BinASTParser<Tok>::parseSumVariableDeclarationOrExpression(const size_t start, const BinKind kind, const BinFields& fields)
-{
-    ParseNode* result;
-    switch (kind) {
-      case BinKind::ArrayExpression:
-        MOZ_TRY_VAR(result, parseInterfaceArrayExpression(start, kind, fields));
-        break;
-      case BinKind::AssignmentExpression:
-        MOZ_TRY_VAR(result, parseInterfaceAssignmentExpression(start, kind, fields));
-        break;
-      case BinKind::AwaitExpression:
-        MOZ_TRY_VAR(result, parseInterfaceAwaitExpression(start, kind, fields));
-        break;
-      case BinKind::BinaryExpression:
-        MOZ_TRY_VAR(result, parseInterfaceBinaryExpression(start, kind, fields));
-        break;
-      case BinKind::CallExpression:
-        MOZ_TRY_VAR(result, parseInterfaceCallExpression(start, kind, fields));
-        break;
-      case BinKind::ClassExpression:
-        MOZ_TRY_VAR(result, parseInterfaceClassExpression(start, kind, fields));
-        break;
-      case BinKind::CompoundAssignmentExpression:
-        MOZ_TRY_VAR(result, parseInterfaceCompoundAssignmentExpression(start, kind, fields));
-        break;
-      case BinKind::ComputedMemberExpression:
-        MOZ_TRY_VAR(result, parseInterfaceComputedMemberExpression(start, kind, fields));
-        break;
-      case BinKind::ConditionalExpression:
-        MOZ_TRY_VAR(result, parseInterfaceConditionalExpression(start, kind, fields));
-        break;
-      case BinKind::EagerArrowExpressionWithExpression:
-        MOZ_TRY_VAR(result, parseInterfaceEagerArrowExpressionWithExpression(start, kind, fields));
-        break;
-      case BinKind::EagerArrowExpressionWithFunctionBody:
-        MOZ_TRY_VAR(result, parseInterfaceEagerArrowExpressionWithFunctionBody(start, kind, fields));
-        break;
-      case BinKind::EagerFunctionExpression:
-        MOZ_TRY_VAR(result, parseInterfaceEagerFunctionExpression(start, kind, fields));
-        break;
-      case BinKind::IdentifierExpression:
-        MOZ_TRY_VAR(result, parseInterfaceIdentifierExpression(start, kind, fields));
-        break;
-      case BinKind::LazyArrowExpressionWithExpression:
-        MOZ_TRY_VAR(result, parseInterfaceLazyArrowExpressionWithExpression(start, kind, fields));
-        break;
-      case BinKind::LazyArrowExpressionWithFunctionBody:
-        MOZ_TRY_VAR(result, parseInterfaceLazyArrowExpressionWithFunctionBody(start, kind, fields));
-        break;
-      case BinKind::LazyFunctionExpression:
-        MOZ_TRY_VAR(result, parseInterfaceLazyFunctionExpression(start, kind, fields));
-        break;
-      case BinKind::LiteralBooleanExpression:
-        MOZ_TRY_VAR(result, parseInterfaceLiteralBooleanExpression(start, kind, fields));
-        break;
-      case BinKind::LiteralInfinityExpression:
-        MOZ_TRY_VAR(result, parseInterfaceLiteralInfinityExpression(start, kind, fields));
-        break;
-      case BinKind::LiteralNullExpression:
-        MOZ_TRY_VAR(result, parseInterfaceLiteralNullExpression(start, kind, fields));
-        break;
-      case BinKind::LiteralNumericExpression:
-        MOZ_TRY_VAR(result, parseInterfaceLiteralNumericExpression(start, kind, fields));
-        break;
-      case BinKind::LiteralRegExpExpression:
-        MOZ_TRY_VAR(result, parseInterfaceLiteralRegExpExpression(start, kind, fields));
-        break;
-      case BinKind::LiteralStringExpression:
-        MOZ_TRY_VAR(result, parseInterfaceLiteralStringExpression(start, kind, fields));
-        break;
-      case BinKind::NewExpression:
-        MOZ_TRY_VAR(result, parseInterfaceNewExpression(start, kind, fields));
-        break;
-      case BinKind::NewTargetExpression:
-        MOZ_TRY_VAR(result, parseInterfaceNewTargetExpression(start, kind, fields));
-        break;
-      case BinKind::ObjectExpression:
-        MOZ_TRY_VAR(result, parseInterfaceObjectExpression(start, kind, fields));
-        break;
-      case BinKind::StaticMemberExpression:
-        MOZ_TRY_VAR(result, parseInterfaceStaticMemberExpression(start, kind, fields));
-        break;
-      case BinKind::TemplateExpression:
-        MOZ_TRY_VAR(result, parseInterfaceTemplateExpression(start, kind, fields));
-        break;
-      case BinKind::ThisExpression:
-        MOZ_TRY_VAR(result, parseInterfaceThisExpression(start, kind, fields));
-        break;
-      case BinKind::UnaryExpression:
-        MOZ_TRY_VAR(result, parseInterfaceUnaryExpression(start, kind, fields));
-        break;
-      case BinKind::UpdateExpression:
-        MOZ_TRY_VAR(result, parseInterfaceUpdateExpression(start, kind, fields));
-        break;
-      case BinKind::VariableDeclaration:
-        MOZ_TRY_VAR(result, parseInterfaceVariableDeclaration(start, kind, fields));
-        break;
-      case BinKind::YieldExpression:
-        MOZ_TRY_VAR(result, parseInterfaceYieldExpression(start, kind, fields));
-        break;
-      case BinKind::YieldStarExpression:
-        MOZ_TRY_VAR(result, parseInterfaceYieldStarExpression(start, kind, fields));
-        break;
-      default:
-        return raiseInvalidKind("VariableDeclarationOrExpression", kind);
-    }
-    return result;
-}
-
-
-
-// ----- Interfaces (autogenerated, by lexicographical order)
-// When fields have a non-trivial type, implementation is deanonymized and delegated to another parser.
-template<typename Tok> JS::Result<ParseNode*>
-BinASTParser<Tok>::parseInterfaceArrayAssignmentTarget(const size_t start, const BinKind kind, const BinFields& fields)
-{
-    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 BinKind kind, const BinFields& fields)
-{
-    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 BinKind kind, const BinFields& fields)
-{
-    MOZ_ASSERT(kind == BinKind::ArrayExpression);
-    BINJS_TRY(CheckRecursionLimit(cx_));
-
-#if defined(DEBUG)
-    const BinField expected_fields[1] = { BinField::Elements };
-    MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
-#endif // defined(DEBUG)
-
-    BINJS_MOZ_TRY_DECL(elements, parseListOfOptionalSpreadElementOrExpression());
-
-    if (elements->empty()) {
-        elements->setHasNonConstInitializer();
-    }
-    auto result = elements;
-    return result;
-}
-
-
-/*
- interface AssertedBlockScope : Node {
-    FrozenArray<AssertedDeclaredName> declaredNames;
-    bool hasDirectEval;
- }
-*/
-template<typename Tok> JS::Result<Ok>
-BinASTParser<Tok>::parseAssertedBlockScope()
-{
-    BinKind kind;
-    BinFields fields(cx_);
-    AutoTaggedTuple guard(*tokenizer_);
-
-    MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    if (kind != BinKind::AssertedBlockScope) {
-        return raiseInvalidKind("AssertedBlockScope", kind);
-    }
-    const auto start = tokenizer_->offset();
-    BINJS_MOZ_TRY_DECL(result, parseInterfaceAssertedBlockScope(start, kind, fields));
-    MOZ_TRY(guard.done());
-
-    return result;
-}
-
-template<typename Tok> JS::Result<Ok>
-BinASTParser<Tok>::parseInterfaceAssertedBlockScope(const size_t start, const BinKind kind, const BinFields& fields)
-{
-    MOZ_ASSERT(kind == BinKind::AssertedBlockScope);
-    BINJS_TRY(CheckRecursionLimit(cx_));
-
-#if defined(DEBUG)
-    const BinField expected_fields[2] = { BinField::DeclaredNames, BinField::HasDirectEval };
-    MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
-#endif // defined(DEBUG)
-    const auto scopeKind = AssertedScopeKind::Block;
-
-    MOZ_TRY(parseListOfAssertedDeclaredName(
-        scopeKind));
-
-    BINJS_MOZ_TRY_DECL(hasDirectEval, tokenizer_->readBool());
-    if (hasDirectEval) {
-        parseContext_->sc()->setHasDirectEval();
-        parseContext_->sc()->setBindingsAccessedDynamically();
-    }
-    if (hasDirectEval && parseContext_->isFunctionBox() && !parseContext_->sc()->strict()) {
-        // In non-strict mode code, direct calls to eval can
-        // add variables to the call object.
-        parseContext_->functionBox()->setHasExtensibleScope();
-    }
-    auto result = Ok();
-    return result;
-}
-
-
-/*
- interface AssertedBoundName : Node {
-    [IdentifierName] string name;
-    bool isCaptured;
- }
-*/
-template<typename Tok> JS::Result<Ok>
-BinASTParser<Tok>::parseAssertedBoundName(
-        AssertedScopeKind scopeKind)
-{
-    BinKind kind;
-    BinFields fields(cx_);
-    AutoTaggedTuple guard(*tokenizer_);
-
-    MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    if (kind != BinKind::AssertedBoundName) {
-        return raiseInvalidKind("AssertedBoundName", kind);
-    }
-    const auto start = tokenizer_->offset();
-    BINJS_MOZ_TRY_DECL(result, parseInterfaceAssertedBoundName(start, kind, fields,
-        scopeKind));
-    MOZ_TRY(guard.done());
-
-    return result;
-}
-
-template<typename Tok> JS::Result<Ok>
-BinASTParser<Tok>::parseInterfaceAssertedBoundName(const size_t start, const BinKind kind, const BinFields& fields,
-        AssertedScopeKind scopeKind)
-{
-    MOZ_ASSERT(kind == BinKind::AssertedBoundName);
-    BINJS_TRY(CheckRecursionLimit(cx_));
-
-#if defined(DEBUG)
-    const BinField expected_fields[2] = { BinField::Name, BinField::IsCaptured };
-    MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
-#endif // defined(DEBUG)
-    const bool allowDuplicateName = false;
-
-    RootedAtom name(cx_);
-    MOZ_TRY_VAR(name, tokenizer_->readIdentifierName());
-
-    BINJS_MOZ_TRY_DECL(isCaptured, tokenizer_->readBool());
-    ParseContext::Scope* scope;
-    DeclarationKind declKind;
-    MOZ_TRY(getBoundScope(scopeKind, scope, declKind));
-    MOZ_TRY(addScopeName(scopeKind, name, scope, declKind, isCaptured, allowDuplicateName));
-    auto result = Ok();
-    return result;
-}
-
-
-/*
- interface AssertedBoundNamesScope : Node {
-    FrozenArray<AssertedBoundName> boundNames;
-    bool hasDirectEval;
- }
-*/
-template<typename Tok> JS::Result<Ok>
-BinASTParser<Tok>::parseAssertedBoundNamesScope()
-{
-    BinKind kind;
-    BinFields fields(cx_);
-    AutoTaggedTuple guard(*tokenizer_);
-
-    MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    if (kind != BinKind::AssertedBoundNamesScope) {
-        return raiseInvalidKind("AssertedBoundNamesScope", kind);
-    }
-    const auto start = tokenizer_->offset();
-    BINJS_MOZ_TRY_DECL(result, parseInterfaceAssertedBoundNamesScope(start, kind, fields));
-    MOZ_TRY(guard.done());
-
-    return result;
-}
-
-template<typename Tok> JS::Result<Ok>
-BinASTParser<Tok>::parseInterfaceAssertedBoundNamesScope(const size_t start, const BinKind kind, const BinFields& fields)
-{
-    MOZ_ASSERT(kind == BinKind::AssertedBoundNamesScope);
-    BINJS_TRY(CheckRecursionLimit(cx_));
-
-#if defined(DEBUG)
-    const BinField expected_fields[2] = { BinField::BoundNames, BinField::HasDirectEval };
-    MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
-#endif // defined(DEBUG)
-    const auto scopeKind = AssertedScopeKind::Catch;
-
-    MOZ_TRY(parseListOfAssertedBoundName(
-        scopeKind));
-
-    BINJS_MOZ_TRY_DECL(hasDirectEval, tokenizer_->readBool());
-    if (hasDirectEval) {
-        parseContext_->sc()->setHasDirectEval();
-        parseContext_->sc()->setBindingsAccessedDynamically();
-    }
-    if (hasDirectEval && parseContext_->isFunctionBox() && !parseContext_->sc()->strict()) {
-        // In non-strict mode code, direct calls to eval can
-        // add variables to the call object.
-        parseContext_->functionBox()->setHasExtensibleScope();
-    }
-    auto result = Ok();
-    return result;
-}
-
-
-/*
- interface AssertedDeclaredName : Node {
-    [IdentifierName] string name;
-    AssertedDeclaredKind kind;
-    bool isCaptured;
- }
-*/
-template<typename Tok> JS::Result<Ok>
-BinASTParser<Tok>::parseAssertedDeclaredName(
-        AssertedScopeKind scopeKind)
-{
-    BinKind kind;
-    BinFields fields(cx_);
-    AutoTaggedTuple guard(*tokenizer_);
-
-    MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    if (kind != BinKind::AssertedDeclaredName) {
-        return raiseInvalidKind("AssertedDeclaredName", kind);
-    }
-    const auto start = tokenizer_->offset();
-    BINJS_MOZ_TRY_DECL(result, parseInterfaceAssertedDeclaredName(start, kind, fields,
-        scopeKind));
-    MOZ_TRY(guard.done());
-
-    return result;
-}
-
-template<typename Tok> JS::Result<Ok>
-BinASTParser<Tok>::parseInterfaceAssertedDeclaredName(const size_t start, const BinKind kind, const BinFields& fields,
-        AssertedScopeKind scopeKind)
-{
-    MOZ_ASSERT(kind == BinKind::AssertedDeclaredName);
-    BINJS_TRY(CheckRecursionLimit(cx_));
-
-#if defined(DEBUG)
-    const BinField expected_fields[3] = { BinField::Name, BinField::Kind, BinField::IsCaptured };
-    MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
-#endif // defined(DEBUG)
-    const bool allowDuplicateName = false;
-
-    RootedAtom name(cx_);
-    MOZ_TRY_VAR(name, tokenizer_->readIdentifierName());
-
-    BINJS_MOZ_TRY_DECL(kind_, parseAssertedDeclaredKind());
-
-    BINJS_MOZ_TRY_DECL(isCaptured, tokenizer_->readBool());
-    ParseContext::Scope* scope;
-    DeclarationKind declKind;
-    MOZ_TRY(getDeclaredScope(scopeKind, kind_, scope, declKind));
-    MOZ_TRY(addScopeName(scopeKind, name, scope, declKind, isCaptured, allowDuplicateName));
-    auto result = Ok();
-    return result;
-}
-
-
-/*
- interface AssertedParameterScope : Node {
-    FrozenArray<AssertedMaybePositionalParameterName> paramNames;
-    bool hasDirectEval;
-    bool isSimpleParameterList;
- }
-*/
-template<typename Tok> JS::Result<Ok>
-BinASTParser<Tok>::parseAssertedParameterScope(
-        MutableHandle<GCVector<JSAtom*>> positionalParams)
-{
-    BinKind kind;
-    BinFields fields(cx_);
-    AutoTaggedTuple guard(*tokenizer_);
-
-    MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    if (kind != BinKind::AssertedParameterScope) {
-        return raiseInvalidKind("AssertedParameterScope", kind);
-    }
-    const auto start = tokenizer_->offset();
-    BINJS_MOZ_TRY_DECL(result, parseInterfaceAssertedParameterScope(start, kind, fields,
-        positionalParams));
-    MOZ_TRY(guard.done());
-
-    return result;
-}
-
-template<typename Tok> JS::Result<Ok>
-BinASTParser<Tok>::parseInterfaceAssertedParameterScope(const size_t start, const BinKind kind, const BinFields& fields,
-        MutableHandle<GCVector<JSAtom*>> positionalParams)
-{
-    MOZ_ASSERT(kind == BinKind::AssertedParameterScope);
-    BINJS_TRY(CheckRecursionLimit(cx_));
-
-#if defined(DEBUG)
-    const BinField expected_fields[3] = { BinField::ParamNames, BinField::HasDirectEval, BinField::IsSimpleParameterList };
-    MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
-#endif // defined(DEBUG)
-    const auto scopeKind = AssertedScopeKind::Parameter;
-
-    MOZ_TRY(parseListOfAssertedMaybePositionalParameterName(
-        scopeKind, positionalParams));
-
-    BINJS_MOZ_TRY_DECL(hasDirectEval, tokenizer_->readBool());
-    if (hasDirectEval) {
-        parseContext_->sc()->setHasDirectEval();
-        parseContext_->sc()->setBindingsAccessedDynamically();
-    }
-    BINJS_MOZ_TRY_DECL(isSimpleParameterList, tokenizer_->readBool());
-    (void) isSimpleParameterList;
-    if (hasDirectEval && parseContext_->isFunctionBox() && !parseContext_->sc()->strict()) {
-        // In non-strict mode code, direct calls to eval can
-        // add variables to the call object.
-        parseContext_->functionBox()->setHasExtensibleScope();
-    }
-    auto result = Ok();
-    return result;
-}
-
-template<typename Tok> JS::Result<Ok>
-BinASTParser<Tok>::parseInterfaceAssertedPositionalParameterName(const size_t start, const BinKind kind, const BinFields& fields,
-        AssertedScopeKind scopeKind,
-        MutableHandle<GCVector<JSAtom*>> positionalParams)
-{
-    MOZ_ASSERT(kind == BinKind::AssertedPositionalParameterName);
-    BINJS_TRY(CheckRecursionLimit(cx_));
-
-#if defined(DEBUG)
-    const BinField expected_fields[3] = { BinField::Index, BinField::Name, BinField::IsCaptured };
-    MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
-#endif // defined(DEBUG)
-    bool allowDuplicateName = !parseContext_->sc()->strict();
-
-    BINJS_MOZ_TRY_DECL(index, tokenizer_->readUnsignedLong());
-
-    RootedAtom name(cx_);
-    MOZ_TRY_VAR(name, tokenizer_->readIdentifierName());
-    // `positionalParams` vector can be shorter than the actual
-    // parameter length. Resize on demand.
-    // (see also ListOfAssertedMaybePositionalParameterName)
-    size_t prevLength = positionalParams.get().length();
-    if (index >= prevLength) {
-        // This is implementation limit, which is not in the spec.
-        if (index >= ARGNO_LIMIT - 1) {
-            return raiseError("AssertedPositionalParameterName.index is too big");
-        }
-        size_t newLength = index + 1;
-        BINJS_TRY(positionalParams.get().resize(newLength));
-        for (uint32_t i = prevLength; i < newLength; i++) {
-            positionalParams.get()[i] = nullptr;
-        }
-    }
-
-    if (positionalParams.get()[index]) {
-        return raiseError("AssertedPositionalParameterName has duplicate entry for the same index");
-    }
-    positionalParams.get()[index] = name;
-    BINJS_MOZ_TRY_DECL(isCaptured, tokenizer_->readBool());
-    ParseContext::Scope* scope;
-    DeclarationKind declKind;
-    MOZ_TRY(getBoundScope(scopeKind, scope, declKind));
-    MOZ_TRY(addScopeName(scopeKind, name, scope, declKind, isCaptured, allowDuplicateName));
-    auto result = Ok();
-    return result;
-}
-
-
-/*
- interface AssertedScriptGlobalScope : Node {
-    FrozenArray<AssertedDeclaredName> declaredNames;
-    bool hasDirectEval;
- }
-*/
-template<typename Tok> JS::Result<Ok>
-BinASTParser<Tok>::parseAssertedScriptGlobalScope()
-{
-    BinKind kind;
-    BinFields fields(cx_);
-    AutoTaggedTuple guard(*tokenizer_);
-
-    MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    if (kind != BinKind::AssertedScriptGlobalScope) {
-        return raiseInvalidKind("AssertedScriptGlobalScope", kind);
-    }
-    const auto start = tokenizer_->offset();
-    BINJS_MOZ_TRY_DECL(result, parseInterfaceAssertedScriptGlobalScope(start, kind, fields));
-    MOZ_TRY(guard.done());
-
-    return result;
-}
-
-template<typename Tok> JS::Result<Ok>
-BinASTParser<Tok>::parseInterfaceAssertedScriptGlobalScope(const size_t start, const BinKind kind, const BinFields& fields)
-{
-    MOZ_ASSERT(kind == BinKind::AssertedScriptGlobalScope);
-    BINJS_TRY(CheckRecursionLimit(cx_));
-
-#if defined(DEBUG)
-    const BinField expected_fields[2] = { BinField::DeclaredNames, BinField::HasDirectEval };
-    MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
-#endif // defined(DEBUG)
-    const auto scopeKind = AssertedScopeKind::Global;
-
-    MOZ_TRY(parseListOfAssertedDeclaredName(
-        scopeKind));
-
-    BINJS_MOZ_TRY_DECL(hasDirectEval, tokenizer_->readBool());
-    if (hasDirectEval) {
-        parseContext_->sc()->setHasDirectEval();
-        parseContext_->sc()->setBindingsAccessedDynamically();
-    }
-    if (hasDirectEval && parseContext_->isFunctionBox() && !parseContext_->sc()->strict()) {
-        // In non-strict mode code, direct calls to eval can
-        // add variables to the call object.
-        parseContext_->functionBox()->setHasExtensibleScope();
-    }
-    auto result = Ok();
-    return result;
-}
-
-
-/*
- interface AssertedVarScope : Node {
-    FrozenArray<AssertedDeclaredName> declaredNames;
-    bool hasDirectEval;
- }
-*/
-template<typename Tok> JS::Result<Ok>
-BinASTParser<Tok>::parseAssertedVarScope()
-{
-    BinKind kind;
-    BinFields fields(cx_);
-    AutoTaggedTuple guard(*tokenizer_);
-
-    MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    if (kind != BinKind::AssertedVarScope) {
-        return raiseInvalidKind("AssertedVarScope", kind);
-    }
-    const auto start = tokenizer_->offset();
-    BINJS_MOZ_TRY_DECL(result, parseInterfaceAssertedVarScope(start, kind, fields));
-    MOZ_TRY(guard.done());
-
-    return result;
-}
-
-template<typename Tok> JS::Result<Ok>
-BinASTParser<Tok>::parseInterfaceAssertedVarScope(const size_t start, const BinKind kind, const BinFields& fields)
-{
-    MOZ_ASSERT(kind == BinKind::AssertedVarScope);
-    BINJS_TRY(CheckRecursionLimit(cx_));
-
-#if defined(DEBUG)
-    const BinField expected_fields[2] = { BinField::DeclaredNames, BinField::HasDirectEval };
-    MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
-#endif // defined(DEBUG)
-    const auto scopeKind = AssertedScopeKind::Var;
-
-    MOZ_TRY(parseListOfAssertedDeclaredName(
-        scopeKind));
-
-    BINJS_MOZ_TRY_DECL(hasDirectEval, tokenizer_->readBool());
-    if (hasDirectEval) {
-        parseContext_->sc()->setHasDirectEval();
-        parseContext_->sc()->setBindingsAccessedDynamically();
-    }
-    if (hasDirectEval && parseContext_->isFunctionBox() && !parseContext_->sc()->strict()) {
-        // In non-strict mode code, direct calls to eval can
-        // add variables to the call object.
-        parseContext_->functionBox()->setHasExtensibleScope();
-    }
-    auto result = Ok();
-    return result;
-}
-
-template<typename Tok> JS::Result<ParseNode*>
-BinASTParser<Tok>::parseInterfaceAssignmentExpression(const size_t start, const BinKind kind, const BinFields& fields)
-{
-    MOZ_ASSERT(kind == BinKind::AssignmentExpression);
-    BINJS_TRY(CheckRecursionLimit(cx_));
-
-#if defined(DEBUG)
-    const BinField expected_fields[2] = { BinField::Binding, BinField::Expression };
-    MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
-#endif // defined(DEBUG)
-
-    BINJS_MOZ_TRY_DECL(binding, parseAssignmentTarget());
-
-    BINJS_MOZ_TRY_DECL(expression, parseExpression());
-
-    BINJS_TRY_DECL(result, factory_.newAssignment(ParseNodeKind::Assign, binding, expression));
-    return result;
-}
-
-template<typename Tok> JS::Result<ParseNode*>
-BinASTParser<Tok>::parseInterfaceAssignmentTargetIdentifier(const size_t start, const BinKind kind, const BinFields& fields)
-{
-    MOZ_ASSERT(kind == BinKind::AssignmentTargetIdentifier);
-    BINJS_TRY(CheckRecursionLimit(cx_));
-
-#if defined(DEBUG)
-    const BinField expected_fields[1] = { BinField::Name };
-    MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
-#endif // defined(DEBUG)
-
-    RootedAtom name(cx_);
-    MOZ_TRY_VAR(name, tokenizer_->readIdentifierName());
-
-    if (!IsIdentifier(name)) {
-        return raiseError("Invalid identifier");
-    }
-    BINJS_TRY(usedNames_.noteUse(cx_, name, parseContext_->scriptId(), parseContext_->innermostScope()->id()));
-    BINJS_TRY_DECL(result, factory_.newName(name->asPropertyName(), tokenizer_->pos(start), cx_));
-    return result;
-}
-
-template<typename Tok> JS::Result<ParseNode*>
-BinASTParser<Tok>::parseInterfaceAwaitExpression(const size_t start, const BinKind kind, const BinFields& fields)
-{
-    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 BinKind kind, const BinFields& fields)
-{
-    MOZ_ASSERT(kind == BinKind::BinaryExpression);
-    BINJS_TRY(CheckRecursionLimit(cx_));
-
-#if defined(DEBUG)
-    const BinField expected_fields[3] = { BinField::Operator, BinField::Left, BinField::Right };
-    MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
-#endif // defined(DEBUG)
-
-    BINJS_MOZ_TRY_DECL(operator_, parseBinaryOperator());
-
-    BINJS_MOZ_TRY_DECL(left, parseExpression());
-
-    BINJS_MOZ_TRY_DECL(right, parseExpression());
-
-    ParseNodeKind pnk;
-    switch (operator_) {
-      case BinaryOperator::Comma:
-        pnk = ParseNodeKind::Comma;
-        break;
-      case BinaryOperator::LogicalOr:
-        pnk = ParseNodeKind::Or;
-        break;
-      case BinaryOperator::LogicalAnd:
-        pnk = ParseNodeKind::And;
-        break;
-      case BinaryOperator::BitOr:
-        pnk = ParseNodeKind::BitOr;
-        break;
-      case BinaryOperator::BitXor:
-        pnk = ParseNodeKind::BitXor;
-        break;
-      case BinaryOperator::BitAnd:
-        pnk = ParseNodeKind::BitAnd;
-        break;
-      case BinaryOperator::Eq:
-        pnk = ParseNodeKind::Eq;
-        break;
-      case BinaryOperator::Neq:
-        pnk = ParseNodeKind::Ne;
-        break;
-      case BinaryOperator::StrictEq:
-        pnk = ParseNodeKind::StrictEq;
-        break;
-      case BinaryOperator::StrictNeq:
-        pnk = ParseNodeKind::StrictNe;
-        break;
-      case BinaryOperator::LessThan:
-        pnk = ParseNodeKind::Lt;
-        break;
-      case BinaryOperator::LeqThan:
-        pnk = ParseNodeKind::Le;
-        break;
-      case BinaryOperator::GreaterThan:
-        pnk = ParseNodeKind::Gt;
-        break;
-      case BinaryOperator::GeqThan:
-        pnk = ParseNodeKind::Ge;
-        break;
-      case BinaryOperator::In:
-        pnk = ParseNodeKind::In;
-        break;
-      case BinaryOperator::Instanceof:
-        pnk = ParseNodeKind::InstanceOf;
-        break;
-      case BinaryOperator::Lsh:
-        pnk = ParseNodeKind::Lsh;
-        break;
-      case BinaryOperator::Rsh:
-        pnk = ParseNodeKind::Rsh;
-        break;
-      case BinaryOperator::Ursh:
-        pnk = ParseNodeKind::Ursh;
-        break;
-      case BinaryOperator::Plus:
-        pnk = ParseNodeKind::Add;
-        break;
-      case BinaryOperator::Minus:
-        pnk = ParseNodeKind::Sub;
-        break;
-      case BinaryOperator::Mul:
-        pnk = ParseNodeKind::Star;
-        break;
-      case BinaryOperator::Div:
-        pnk = ParseNodeKind::Div;
-        break;
-      case BinaryOperator::Mod:
-        pnk = ParseNodeKind::Mod;
-        break;
-      case BinaryOperator::Pow:
-        pnk = ParseNodeKind::Pow;
-        break;
-    }
-
-    ParseNode* result;
-    if (left->isKind(pnk) &&
-        pnk != ParseNodeKind::Pow /* ParseNodeKind::Pow is not left-associative */)
-    {
-        // Regroup left-associative operations into lists.
-        left->template as<ListNode>().appendWithoutOrderAssumption(right);
-        result = left;
-    } else {
-        BINJS_TRY_DECL(list, factory_.newList(pnk, tokenizer_->pos(start)));
-
-        list->appendWithoutOrderAssumption(left);
-        list->appendWithoutOrderAssumption(right);
-        result = list;
-    }
-    return result;
-}
-
-
-/*
- interface BindingIdentifier : Node {
-    [IdentifierName] string name;
- }
-*/
-template<typename Tok> JS::Result<ParseNode*>
-BinASTParser<Tok>::parseBindingIdentifier()
-{
-    BinKind kind;
-    BinFields fields(cx_);
-    AutoTaggedTuple guard(*tokenizer_);
-
-    MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    if (kind != BinKind::BindingIdentifier) {
-        return raiseInvalidKind("BindingIdentifier", kind);
-    }
-    const auto start = tokenizer_->offset();
-    BINJS_MOZ_TRY_DECL(result, parseInterfaceBindingIdentifier(start, kind, fields));
-    MOZ_TRY(guard.done());
-
-    return result;
-}
-
-template<typename Tok> JS::Result<ParseNode*>
-BinASTParser<Tok>::parseInterfaceBindingIdentifier(const size_t start, const BinKind kind, const BinFields& fields)
-{
-    MOZ_ASSERT(kind == BinKind::BindingIdentifier);
-    BINJS_TRY(CheckRecursionLimit(cx_));
-
-#if defined(DEBUG)
-    const BinField expected_fields[1] = { BinField::Name };
-    MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
-#endif // defined(DEBUG)
-
-    RootedAtom name(cx_);
-    MOZ_TRY_VAR(name, tokenizer_->readIdentifierName());
-
-    if (!IsIdentifier(name)) {
-        return raiseError("Invalid identifier");
-    }
-    BINJS_TRY_DECL(result, factory_.newName(name->asPropertyName(), tokenizer_->pos(start), cx_));
-    return result;
-}
-
-template<typename Tok> JS::Result<ParseNode*>
-BinASTParser<Tok>::parseInterfaceBindingWithInitializer(const size_t start, const BinKind kind, const BinFields& fields)
-{
-    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()
-{
-    BinKind kind;
-    BinFields fields(cx_);
-    AutoTaggedTuple guard(*tokenizer_);
-
-    MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    if (kind != BinKind::Block) {
-        return raiseInvalidKind("Block", kind);
-    }
-    const auto start = tokenizer_->offset();
-    BINJS_MOZ_TRY_DECL(result, parseInterfaceBlock(start, kind, fields));
-    MOZ_TRY(guard.done());
-
-    return result;
-}
-
-template<typename Tok> JS::Result<ParseNode*>
-BinASTParser<Tok>::parseInterfaceBlock(const size_t start, const BinKind kind, const BinFields& fields)
-{
-    MOZ_ASSERT(kind == BinKind::Block);
-    BINJS_TRY(CheckRecursionLimit(cx_));
-
-#if defined(DEBUG)
-    const BinField expected_fields[2] = { BinField::Scope, BinField::Statements };
-    MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
-#endif // defined(DEBUG)
-    ParseContext::Statement stmt(parseContext_, StatementKind::Block);
-    ParseContext::Scope currentScope(cx_, parseContext_, usedNames_);
-    BINJS_TRY(currentScope.init(parseContext_));
-
-    MOZ_TRY(parseAssertedBlockScope());
-
-    BINJS_MOZ_TRY_DECL(statements, parseListOfStatement());
-
-    MOZ_TRY(checkClosedVars(currentScope));
-    BINJS_TRY_DECL(bindings, NewLexicalScopeData(cx_, currentScope, alloc_, parseContext_));
-    BINJS_TRY_DECL(result, factory_.newLexicalScope(*bindings, statements));
-    return result;
-}
-
-template<typename Tok> JS::Result<ParseNode*>
-BinASTParser<Tok>::parseInterfaceBreakStatement(const size_t start, const BinKind kind, const BinFields& fields)
-{
-    MOZ_ASSERT(kind == BinKind::BreakStatement);
-    BINJS_TRY(CheckRecursionLimit(cx_));
-
-#if defined(DEBUG)
-    const BinField expected_fields[1] = { BinField::Label };
-    MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
-#endif // defined(DEBUG)
-    RootedAtom label(cx_);
-    MOZ_TRY_VAR(label, tokenizer_->readMaybeAtom());
-
-    if (label) {
-        if (!IsIdentifier(label)) {
-            return raiseError("Invalid identifier");
-        }
-
-        auto validity = parseContext_->checkBreakStatement(label->asPropertyName());
-
-        if (validity.isErr()) {
-            switch (validity.unwrapErr()) {
-            case ParseContext::BreakStatementError::ToughBreak:
-                return raiseError(kind, "Not in a loop");
-            case ParseContext::BreakStatementError::LabelNotFound:
-                return raiseError(kind, "Label not found");
-            }
-        }
-    }
-    BINJS_TRY_DECL(result, factory_.newBreakStatement(label ? label->asPropertyName() : nullptr, tokenizer_->pos(start)));
-    return result;
-}
-
-template<typename Tok> JS::Result<ParseNode*>
-BinASTParser<Tok>::parseInterfaceCallExpression(const size_t start, const BinKind kind, const BinFields& fields)
-{
-    MOZ_ASSERT(kind == BinKind::CallExpression);
-    BINJS_TRY(CheckRecursionLimit(cx_));
-
-#if defined(DEBUG)
-    const BinField expected_fields[2] = { BinField::Callee, BinField::Arguments };
-    MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
-#endif // defined(DEBUG)
-
-    BINJS_MOZ_TRY_DECL(callee, parseExpressionOrSuper());
-
-    BINJS_MOZ_TRY_DECL(arguments, parseArguments());
-
-    auto op = JSOP_CALL;
-
-    // Try to optimize funcall and funapply at the bytecode level
-    if (PropertyName* prop = factory_.maybeDottedProperty(callee)) {
-        if (prop == cx_->names().apply) {
-            op = JSOP_FUNAPPLY;
-            if (parseContext_->isFunctionBox())
-                parseContext_->functionBox()->usesApply = true;
-        } else if (prop == cx_->names().call) {
-            op = JSOP_FUNCALL;
-        }
-    }
-
-    // Check for direct calls to `eval`.
-    if (factory_.isEvalName(callee, cx_)) {
-        if (!parseContext_->varScope().lookupDeclaredNameForAdd(cx_->names().eval)
-         && !parseContext_->innermostScope()->lookupDeclaredNameForAdd(cx_->names().eval))
-        {
-            // This is a direct call to `eval`.
-            if (!parseContext_->sc()->hasDirectEval()) {
-                return raiseMissingDirectEvalInAssertedScope();
-            }
-
-            op = parseContext_->sc()->strict() ? JSOP_STRICTEVAL : JSOP_EVAL;
-        }
-    }
-
-    BINJS_TRY_DECL(result, factory_.newCall(callee, arguments));
-    result->setOp(op);
-    return result;
-}
-
-
-/*
- interface CatchClause : Node {
-    AssertedBoundNamesScope bindingScope;
-    Binding binding;
-    Block body;
- }
-*/
-template<typename Tok> JS::Result<LexicalScopeNode*>
-BinASTParser<Tok>::parseCatchClause()
-{
-    BinKind kind;
-    BinFields fields(cx_);
-    AutoTaggedTuple guard(*tokenizer_);
-
-    MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    if (kind != BinKind::CatchClause) {
-        return raiseInvalidKind("CatchClause", kind);
-    }
-    const auto start = tokenizer_->offset();
-    BINJS_MOZ_TRY_DECL(result, parseInterfaceCatchClause(start, kind, fields));
-    MOZ_TRY(guard.done());
-
-    return result;
-}
-
-template<typename Tok> JS::Result<LexicalScopeNode*>
-BinASTParser<Tok>::parseInterfaceCatchClause(const size_t start, const BinKind kind, const BinFields& fields)
-{
-    MOZ_ASSERT(kind == BinKind::CatchClause);
-    BINJS_TRY(CheckRecursionLimit(cx_));
-
-#if defined(DEBUG)
-    const BinField expected_fields[3] = { BinField::BindingScope, BinField::Binding, BinField::Body };
-    MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
-#endif // defined(DEBUG)
-    ParseContext::Statement stmt(parseContext_, StatementKind::Catch);
-    ParseContext::Scope currentScope(cx_, parseContext_, usedNames_);
-    BINJS_TRY(currentScope.init(parseContext_));
-
-    MOZ_TRY(parseAssertedBoundNamesScope());
-
-    BINJS_MOZ_TRY_DECL(binding, parseBinding());
-
-    BINJS_MOZ_TRY_DECL(body, parseBlock());
-
-    MOZ_TRY(checkClosedVars(currentScope));
-    BINJS_TRY_DECL(bindings, NewLexicalScopeData(cx_, currentScope, alloc_, parseContext_));
-    BINJS_TRY_DECL(result, factory_.newLexicalScope(*bindings, body));
-    BINJS_TRY(factory_.setupCatchScope(result, binding, body));
-    return result;
-}
-
-template<typename Tok> JS::Result<ParseNode*>
-BinASTParser<Tok>::parseInterfaceClassDeclaration(const size_t start, const BinKind kind, const BinFields& fields)
-{
-    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 BinKind kind, const BinFields& fields)
-{
-    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 BinKind kind, const BinFields& fields)
-{
-    MOZ_ASSERT(kind == BinKind::CompoundAssignmentExpression);
-    BINJS_TRY(CheckRecursionLimit(cx_));
-
-#if defined(DEBUG)
-    const BinField expected_fields[3] = { BinField::Operator, BinField::Binding, BinField::Expression };
-    MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
-#endif // defined(DEBUG)
-
-    BINJS_MOZ_TRY_DECL(operator_, parseCompoundAssignmentOperator());
-
-    BINJS_MOZ_TRY_DECL(binding, parseSimpleAssignmentTarget());
-
-    BINJS_MOZ_TRY_DECL(expression, parseExpression());
-
-    ParseNodeKind pnk;
-    switch (operator_){
-      case CompoundAssignmentOperator::PlusAssign:
-        pnk = ParseNodeKind::AddAssign;
-        break;
-      case CompoundAssignmentOperator::MinusAssign:
-        pnk = ParseNodeKind::SubAssign;
-        break;
-      case CompoundAssignmentOperator::MulAssign:
-        pnk = ParseNodeKind::MulAssign;
-        break;
-      case CompoundAssignmentOperator::DivAssign:
-        pnk = ParseNodeKind::DivAssign;
-        break;
-      case CompoundAssignmentOperator::ModAssign:
-        pnk = ParseNodeKind::ModAssign;
-        break;
-      case CompoundAssignmentOperator::PowAssign:
-        pnk = ParseNodeKind::PowAssign;
-        break;
-      case CompoundAssignmentOperator::LshAssign:
-        pnk = ParseNodeKind::LshAssign;
-        break;
-      case CompoundAssignmentOperator::RshAssign:
-        pnk = ParseNodeKind::RshAssign;
-        break;
-      case CompoundAssignmentOperator::UrshAssign:
-        pnk = ParseNodeKind::UrshAssign;
-        break;
-      case CompoundAssignmentOperator::BitOrAssign:
-        pnk = ParseNodeKind::BitOrAssign;
-        break;
-      case CompoundAssignmentOperator::BitXorAssign:
-        pnk = ParseNodeKind::BitXorAssign;
-        break;
-      case CompoundAssignmentOperator::BitAndAssign:
-        pnk = ParseNodeKind::BitAndAssign;
-        break;
-    }
-    BINJS_TRY_DECL(result, factory_.newAssignment(pnk, binding, expression));
-    return result;
-}
-
-template<typename Tok> JS::Result<ParseNode*>
-BinASTParser<Tok>::parseInterfaceComputedMemberAssignmentTarget(const size_t start, const BinKind kind, const BinFields& fields)
-{
-    MOZ_ASSERT(kind == BinKind::ComputedMemberAssignmentTarget);
-    BINJS_TRY(CheckRecursionLimit(cx_));
-
-#if defined(DEBUG)
-    const BinField expected_fields[2] = { BinField::Object, BinField::Expression };
-    MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
-#endif // defined(DEBUG)
-
-    BINJS_MOZ_TRY_DECL(object, parseExpressionOrSuper());
-
-    BINJS_MOZ_TRY_DECL(expression, parseExpression());
-
-    BINJS_TRY_DECL(result, factory_.newPropertyByValue(object, expression, tokenizer_->offset()));
-    return result;
-}
-
-template<typename Tok> JS::Result<ParseNode*>
-BinASTParser<Tok>::parseInterfaceComputedMemberExpression(const size_t start, const BinKind kind, const BinFields& fields)
-{
-    MOZ_ASSERT(kind == BinKind::ComputedMemberExpression);
-    BINJS_TRY(CheckRecursionLimit(cx_));
-
-#if defined(DEBUG)
-    const BinField expected_fields[2] = { BinField::Object, BinField::Expression };
-    MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
-#endif // defined(DEBUG)
-
-    BINJS_MOZ_TRY_DECL(object, parseExpressionOrSuper());
-
-    BINJS_MOZ_TRY_DECL(expression, parseExpression());
-
-    BINJS_TRY_DECL(result, factory_.newPropertyByValue(object, expression, tokenizer_->offset()));
-    return result;
-}
-
-template<typename Tok> JS::Result<ParseNode*>
-BinASTParser<Tok>::parseInterfaceComputedPropertyName(const size_t start, const BinKind kind, const BinFields& fields)
-{
-    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 BinKind kind, const BinFields& fields)
-{
-    MOZ_ASSERT(kind == BinKind::ConditionalExpression);
-    BINJS_TRY(CheckRecursionLimit(cx_));
-
-#if defined(DEBUG)
-    const BinField expected_fields[3] = { BinField::Test, BinField::Consequent, BinField::Alternate };
-    MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
-#endif // defined(DEBUG)
-
-    BINJS_MOZ_TRY_DECL(test, parseExpression());
-
-    BINJS_MOZ_TRY_DECL(consequent, parseExpression());
-
-    BINJS_MOZ_TRY_DECL(alternate, parseExpression());
-
-    BINJS_TRY_DECL(result, factory_.newConditional(test, consequent, alternate));
-    return result;
-}
-
-template<typename Tok> JS::Result<ParseNode*>
-BinASTParser<Tok>::parseInterfaceContinueStatement(const size_t start, const BinKind kind, const BinFields& fields)
-{
-    MOZ_ASSERT(kind == BinKind::ContinueStatement);
-    BINJS_TRY(CheckRecursionLimit(cx_));
-
-#if defined(DEBUG)
-    const BinField expected_fields[1] = { BinField::Label };
-    MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
-#endif // defined(DEBUG)
-    RootedAtom label(cx_);
-    MOZ_TRY_VAR(label, tokenizer_->readMaybeAtom());
-
-    if (label) {
-        if (!IsIdentifier(label)) {
-            return raiseError("ContinueStatement - Label MUST be an identifier");
-        }
-
-        auto validity = parseContext_->checkContinueStatement(label ? label->asPropertyName() : nullptr);
-        if (validity.isErr()) {
-            switch (validity.unwrapErr()) {
-              case ParseContext::ContinueStatementError::NotInALoop:
-                return raiseError(kind, "Not in a loop");
-              case ParseContext::ContinueStatementError::LabelNotFound:
-                return raiseError(kind, "Label not found");
-            }
-        }
-    }
-
-    BINJS_TRY_DECL(result, factory_.newContinueStatement(label ? label->asPropertyName() : nullptr, tokenizer_->pos(start)));
-    return result;
-}
-
-template<typename Tok> JS::Result<ParseNode*>
-BinASTParser<Tok>::parseInterfaceDataProperty(const size_t start, const BinKind kind, const BinFields& fields)
-{
-    MOZ_ASSERT(kind == BinKind::DataProperty);
-    BINJS_TRY(CheckRecursionLimit(cx_));
-
-#if defined(DEBUG)
-    const BinField expected_fields[2] = { BinField::Name, BinField::Expression };
-    MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
-#endif // defined(DEBUG)
-
-    BINJS_MOZ_TRY_DECL(name, parsePropertyName());
-
-    BINJS_MOZ_TRY_DECL(expression, parseExpression());
-
-    if (!factory_.isUsableAsObjectPropertyName(name)) {
-        return raiseError("DataProperty key kind");
-    }
-
-    ParseNode* result;
-    if (name->template is<NameNode>() && name->template as<NameNode>().atom() == cx_->names().proto) {
-        BINJS_TRY_VAR(result, factory_.newUnary(ParseNodeKind::MutateProto, start, expression));
-    } else {
-        BINJS_TRY_VAR(result, factory_.newObjectMethodOrPropertyDefinition(name, expression, AccessorType::None));
-    }
-    return result;
-}
-
-template<typename Tok> JS::Result<ParseNode*>
-BinASTParser<Tok>::parseInterfaceDebuggerStatement(const size_t start, const BinKind kind, const BinFields& fields)
-{
-    return raiseError("FIXME: Not implemented yet in this preview release (DebuggerStatement)");
-}
-
-
-/*
- interface Directive : Node {
-    string rawValue;
- }
-*/
-template<typename Tok> JS::Result<ParseNode*>
-BinASTParser<Tok>::parseDirective()
-{
-    BinKind kind;
-    BinFields fields(cx_);
-    AutoTaggedTuple guard(*tokenizer_);
-
-    MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    if (kind != BinKind::Directive) {
-        return raiseInvalidKind("Directive", kind);
-    }
-    const auto start = tokenizer_->offset();
-    BINJS_MOZ_TRY_DECL(result, parseInterfaceDirective(start, kind, fields));
-    MOZ_TRY(guard.done());
-
-    return result;
-}
-
-template<typename Tok> JS::Result<ParseNode*>
-BinASTParser<Tok>::parseInterfaceDirective(const size_t start, const BinKind kind, const BinFields& fields)
-{
-    MOZ_ASSERT(kind == BinKind::Directive);
-    BINJS_TRY(CheckRecursionLimit(cx_));
-
-#if defined(DEBUG)
-    const BinField expected_fields[1] = { BinField::RawValue };
-    MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
-#endif // defined(DEBUG)
-
-    RootedAtom rawValue(cx_);
-    MOZ_TRY_VAR(rawValue, tokenizer_->readAtom());
-
-    TokenPos pos = tokenizer_->pos(start);
-    BINJS_TRY_DECL(result, factory_.newStringLiteral(rawValue, pos));
-    return result;
-}
-
-template<typename Tok> JS::Result<ParseNode*>
-BinASTParser<Tok>::parseInterfaceDoWhileStatement(const size_t start, const BinKind kind, const BinFields& fields)
-{
-    MOZ_ASSERT(kind == BinKind::DoWhileStatement);
-    BINJS_TRY(CheckRecursionLimit(cx_));
-
-#if defined(DEBUG)
-    const BinField expected_fields[2] = { BinField::Test, BinField::Body };
-    MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
-#endif // defined(DEBUG)
-    ParseContext::Statement stmt(parseContext_, StatementKind::DoLoop);
-
-    BINJS_MOZ_TRY_DECL(test, parseExpression());
-
-    BINJS_MOZ_TRY_DECL(body, parseStatement());
-
-    BINJS_TRY_DECL(result, factory_.newDoWhileStatement(body, test, tokenizer_->pos(start)));
-    return result;
-}
-
-template<typename Tok> JS::Result<ParseNode*>
-BinASTParser<Tok>::parseInterfaceEagerArrowExpressionWithExpression(const size_t start, const BinKind kind, const BinFields& fields)
-{
-    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 BinKind kind, const BinFields& fields)
-{
-    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 BinKind kind, const BinFields& fields)
-{
-    MOZ_ASSERT(kind == BinKind::EagerFunctionDeclaration);
-    BINJS_TRY(CheckRecursionLimit(cx_));
-
-#if defined(DEBUG)
-    const BinField expected_fields[6] = { BinField::IsAsync, BinField::IsGenerator, BinField::Name, BinField::Length, BinField::Directives, BinField::Contents };
-    MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
-#endif // defined(DEBUG)
-    const auto syntax = FunctionSyntaxKind::Statement;
-
-    BINJS_MOZ_TRY_DECL(isAsync, tokenizer_->readBool());
-    if (isAsync) {
-        return raiseError("Async function is not supported in this preview release");
-    }
-    BINJS_MOZ_TRY_DECL(isGenerator, tokenizer_->readBool());
-    if (isGenerator) {
-        return raiseError("Generator is not supported in this preview release");
-    }
-    BINJS_MOZ_TRY_DECL(name, parseBindingIdentifier());
-
-    BINJS_MOZ_TRY_DECL(length, tokenizer_->readUnsignedLong());
-
-    BINJS_MOZ_TRY_DECL(directives, parseListOfDirective());
-
-    BINJS_MOZ_TRY_DECL(funbox, buildFunctionBox(
-        isGenerator ? GeneratorKind::Generator
-                    : GeneratorKind::NotGenerator,
-        isAsync ? FunctionAsyncKind::AsyncFunction
-                : FunctionAsyncKind::SyncFunction,
-        syntax,
-        (syntax != FunctionSyntaxKind::Setter &&
-         syntax != FunctionSyntaxKind::Getter) ? name : nullptr));
-
-    forceStrictIfNecessary(funbox, directives);
-
-    // Push a new ParseContext. It will be used to parse `scope`, the arguments, the function.
-    BinParseContext funpc(cx_, this, funbox, /* newDirectives = */ nullptr);
-    BINJS_TRY(funpc.init());
-    parseContext_->functionScope().useAsVarScope(parseContext_);
-    MOZ_ASSERT(parseContext_->isFunctionBox());
-
-    ParseContext::Scope lexicalScope(cx_, parseContext_, usedNames_);
-    BINJS_TRY(lexicalScope.init(parseContext_));
-    ListNode* params;
-    ListNode* body;
-    MOZ_TRY(parseFunctionOrMethodContents(
-        length, &params, &body));
-    MOZ_TRY(prependDirectivesToBody(body, directives));
-    BINJS_TRY_DECL(lexicalScopeData, NewLexicalScopeData(cx_, lexicalScope, alloc_, parseContext_));
-    BINJS_TRY_DECL(bodyScope, factory_.newLexicalScope(*lexicalScopeData, body));
-    BINJS_MOZ_TRY_DECL(result, buildFunction(start, kind, name, params, bodyScope, funbox));
-    return result;
-}
-
-template<typename Tok> JS::Result<ParseNode*>
-BinASTParser<Tok>::parseInterfaceEagerFunctionExpression(const size_t start, const BinKind kind, const BinFields& fields)
-{
-    MOZ_ASSERT(kind == BinKind::EagerFunctionExpression);
-    BINJS_TRY(CheckRecursionLimit(cx_));
-
-#if defined(DEBUG)
-    const BinField expected_fields[6] = { BinField::IsAsync, BinField::IsGenerator, BinField::Name, BinField::Length, BinField::Directives, BinField::Contents };
-    MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
-#endif // defined(DEBUG)
-    const auto syntax = FunctionSyntaxKind::Expression;
-
-    BINJS_MOZ_TRY_DECL(isAsync, tokenizer_->readBool());
-    if (isAsync) {
-        return raiseError("Async function is not supported in this preview release");
-    }
-    BINJS_MOZ_TRY_DECL(isGenerator, tokenizer_->readBool());
-    if (isGenerator) {
-        return raiseError("Generator is not supported in this preview release");
-    }
-    BINJS_MOZ_TRY_DECL(name, parseOptionalBindingIdentifier());
-
-    BINJS_MOZ_TRY_DECL(length, tokenizer_->readUnsignedLong());
-
-    BINJS_MOZ_TRY_DECL(directives, parseListOfDirective());
-
-    BINJS_MOZ_TRY_DECL(funbox, buildFunctionBox(
-        isGenerator ? GeneratorKind::Generator
-                    : GeneratorKind::NotGenerator,
-        isAsync ? FunctionAsyncKind::AsyncFunction
-                : FunctionAsyncKind::SyncFunction,
-        syntax,
-        (syntax != FunctionSyntaxKind::Setter &&
-         syntax != FunctionSyntaxKind::Getter) ? name : nullptr));
-
-    forceStrictIfNecessary(funbox, directives);
-
-    // Push a new ParseContext. It will be used to parse `scope`, the arguments, the function.
-    BinParseContext funpc(cx_, this, funbox, /* newDirectives = */ nullptr);
-    BINJS_TRY(funpc.init());
-    parseContext_->functionScope().useAsVarScope(parseContext_);
-    MOZ_ASSERT(parseContext_->isFunctionBox());
-
-    ParseContext::Scope lexicalScope(cx_, parseContext_, usedNames_);
-    BINJS_TRY(lexicalScope.init(parseContext_));
-    ListNode* params;
-    ListNode* body;
-    MOZ_TRY(parseFunctionExpressionContents(
-        length, &params, &body));
-    MOZ_TRY(prependDirectivesToBody(body, directives));
-    BINJS_TRY_DECL(lexicalScopeData, NewLexicalScopeData(cx_, lexicalScope, alloc_, parseContext_));
-    BINJS_TRY_DECL(bodyScope, factory_.newLexicalScope(*lexicalScopeData, body));
-    BINJS_MOZ_TRY_DECL(result, buildFunction(start, kind, name, params, bodyScope, funbox));
-    return result;
-}
-
-template<typename Tok> JS::Result<ParseNode*>
-BinASTParser<Tok>::parseInterfaceEagerGetter(const size_t start, const BinKind kind, const BinFields& fields)
-{
-    MOZ_ASSERT(kind == BinKind::EagerGetter);
-    BINJS_TRY(CheckRecursionLimit(cx_));
-
-#if defined(DEBUG)
-    const BinField expected_fields[3] = { BinField::Name, BinField::Directives, BinField::Contents };
-    MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
-#endif // defined(DEBUG)
-    const auto syntax = FunctionSyntaxKind::Setter;
-    const bool isGenerator = false;
-    const bool isAsync = false;
-    const auto accessorType = AccessorType::Getter;
-    const uint32_t length = 0;
-
-    BINJS_MOZ_TRY_DECL(name, parsePropertyName());
-
-    BINJS_MOZ_TRY_DECL(directives, parseListOfDirective());
-
-    BINJS_MOZ_TRY_DECL(funbox, buildFunctionBox(
-        isGenerator ? GeneratorKind::Generator
-                    : GeneratorKind::NotGenerator,
-        isAsync ? FunctionAsyncKind::AsyncFunction
-                : FunctionAsyncKind::SyncFunction,
-        syntax,
-        (syntax != FunctionSyntaxKind::Setter &&
-         syntax != FunctionSyntaxKind::Getter) ? name : nullptr));
-
-    forceStrictIfNecessary(funbox, directives);
-
-    // Push a new ParseContext. It will be used to parse `scope`, the arguments, the function.
-    BinParseContext funpc(cx_, this, funbox, /* newDirectives = */ nullptr);
-    BINJS_TRY(funpc.init());
-    parseContext_->functionScope().useAsVarScope(parseContext_);
-    MOZ_ASSERT(parseContext_->isFunctionBox());
-
-    ParseContext::Scope lexicalScope(cx_, parseContext_, usedNames_);
-    BINJS_TRY(lexicalScope.init(parseContext_));
-    ListNode* params;
-    ListNode* body;
-    MOZ_TRY(parseGetterContents(
-        length, &params, &body));
-    MOZ_TRY(prependDirectivesToBody(body, directives));
-    BINJS_MOZ_TRY_DECL(method, buildFunction(start, kind, name, params, body, funbox));
-    BINJS_TRY_DECL(result, factory_.newObjectMethodOrPropertyDefinition(name, method, accessorType));
-    return result;
-}
-
-template<typename Tok> JS::Result<ParseNode*>
-BinASTParser<Tok>::parseInterfaceEagerMethod(const size_t start, const BinKind kind, const BinFields& fields)
-{
-    MOZ_ASSERT(kind == BinKind::EagerMethod);
-    BINJS_TRY(CheckRecursionLimit(cx_));
-
-#if defined(DEBUG)
-    const BinField expected_fields[6] = { BinField::IsAsync, BinField::IsGenerator, BinField::Name, BinField::Length, BinField::Directives, BinField::Contents };
-    MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
-#endif // defined(DEBUG)
-    const auto syntax = FunctionSyntaxKind::Method;
-    const auto accessorType = AccessorType::None;
-
-    BINJS_MOZ_TRY_DECL(isAsync, tokenizer_->readBool());
-    if (isAsync) {
-        return raiseError("Async function is not supported in this preview release");
-    }
-    BINJS_MOZ_TRY_DECL(isGenerator, tokenizer_->readBool());
-    if (isGenerator) {
-        return raiseError("Generator is not supported in this preview release");
-    }
-    BINJS_MOZ_TRY_DECL(name, parsePropertyName());
-
-    BINJS_MOZ_TRY_DECL(length, tokenizer_->readUnsignedLong());
-
-    BINJS_MOZ_TRY_DECL(directives, parseListOfDirective());
-
-    BINJS_MOZ_TRY_DECL(funbox, buildFunctionBox(
-        isGenerator ? GeneratorKind::Generator
-                    : GeneratorKind::NotGenerator,
-        isAsync ? FunctionAsyncKind::AsyncFunction
-                : FunctionAsyncKind::SyncFunction,
-        syntax,
-        (syntax != FunctionSyntaxKind::Setter &&
-         syntax != FunctionSyntaxKind::Getter) ? name : nullptr));
-
-    forceStrictIfNecessary(funbox, directives);
-
-    // Push a new ParseContext. It will be used to parse `scope`, the arguments, the function.
-    BinParseContext funpc(cx_, this, funbox, /* newDirectives = */ nullptr);
-    BINJS_TRY(funpc.init());
-    parseContext_->functionScope().useAsVarScope(parseContext_);
-    MOZ_ASSERT(parseContext_->isFunctionBox());
-
-    ParseContext::Scope lexicalScope(cx_, parseContext_, usedNames_);
-    BINJS_TRY(lexicalScope.init(parseContext_));
-    ListNode* params;
-    ListNode* body;
-    MOZ_TRY(parseFunctionOrMethodContents(
-        length, &params, &body));
-    MOZ_TRY(prependDirectivesToBody(body, directives));
-    BINJS_MOZ_TRY_DECL(method, buildFunction(start, kind, name, params, body, funbox));
-    BINJS_TRY_DECL(result, factory_.newObjectMethodOrPropertyDefinition(name, method, accessorType));
-    return result;
-}
-
-template<typename Tok> JS::Result<ParseNode*>
-BinASTParser<Tok>::parseInterfaceEagerSetter(const size_t start, const BinKind kind, const BinFields& fields)
-{
-    MOZ_ASSERT(kind == BinKind::EagerSetter);
-    BINJS_TRY(CheckRecursionLimit(cx_));
-
-#if defined(DEBUG)
-    const BinField expected_fields[4] = { BinField::Name, BinField::Length, BinField::Directives, BinField::Contents };
-    MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
-#endif // defined(DEBUG)
-    const auto syntax = FunctionSyntaxKind::Setter;
-    const bool isGenerator = false;
-    const bool isAsync = false;
-    const auto accessorType = AccessorType::Setter;
-
-    BINJS_MOZ_TRY_DECL(name, parsePropertyName());
-
-    BINJS_MOZ_TRY_DECL(length, tokenizer_->readUnsignedLong());
-
-    BINJS_MOZ_TRY_DECL(directives, parseListOfDirective());
-
-    BINJS_MOZ_TRY_DECL(funbox, buildFunctionBox(
-        isGenerator ? GeneratorKind::Generator
-                    : GeneratorKind::NotGenerator,
-        isAsync ? FunctionAsyncKind::AsyncFunction
-                : FunctionAsyncKind::SyncFunction,
-        syntax,
-        (syntax != FunctionSyntaxKind::Setter &&
-         syntax != FunctionSyntaxKind::Getter) ? name : nullptr));
-
-    forceStrictIfNecessary(funbox, directives);
-
-    // Push a new ParseContext. It will be used to parse `scope`, the arguments, the function.
-    BinParseContext funpc(cx_, this, funbox, /* newDirectives = */ nullptr);
-    BINJS_TRY(funpc.init());
-    parseContext_->functionScope().useAsVarScope(parseContext_);
-    MOZ_ASSERT(parseContext_->isFunctionBox());
-
-    ParseContext::Scope lexicalScope(cx_, parseContext_, usedNames_);
-    BINJS_TRY(lexicalScope.init(parseContext_));
-    ListNode* params;
-    ListNode* body;
-    MOZ_TRY(parseSetterContents(
-        length, &params, &body));
-    MOZ_TRY(prependDirectivesToBody(body, directives));
-    BINJS_MOZ_TRY_DECL(method, buildFunction(start, kind, name, params, body, funbox));
-    BINJS_TRY_DECL(result, factory_.newObjectMethodOrPropertyDefinition(name, method, accessorType));
-    return result;
-}
-
-template<typename Tok> JS::Result<ParseNode*>
-BinASTParser<Tok>::parseInterfaceEmptyStatement(const size_t start, const BinKind kind, const BinFields& fields)
-{
-    MOZ_ASSERT(kind == BinKind::EmptyStatement);
-    BINJS_TRY(CheckRecursionLimit(cx_));
-MOZ_TRY(tokenizer_->checkFields0(kind, fields));
-
-    BINJS_TRY_DECL(result, factory_.newEmptyStatement(tokenizer_->pos(start)));
-    return result;
-}
-
-template<typename Tok> JS::Result<ParseNode*>
-BinASTParser<Tok>::parseInterfaceExpressionStatement(const size_t start, const BinKind kind, const BinFields& fields)
-{
-    MOZ_ASSERT(kind == BinKind::ExpressionStatement);
-    BINJS_TRY(CheckRecursionLimit(cx_));
-
-#if defined(DEBUG)
-    const BinField expected_fields[1] = { BinField::Expression };
-    MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
-#endif // defined(DEBUG)
-
-    BINJS_MOZ_TRY_DECL(expression, parseExpression());
-
-    BINJS_TRY_DECL(result, factory_.newExprStatement(expression, tokenizer_->offset()));
-    return result;
-}
-
-template<typename Tok> JS::Result<ParseNode*>
-BinASTParser<Tok>::parseInterfaceForInOfBinding(const size_t start, const BinKind kind, const BinFields& fields)
-{
-    MOZ_ASSERT(kind == BinKind::ForInOfBinding);
-    BINJS_TRY(CheckRecursionLimit(cx_));
-
-#if defined(DEBUG)
-    const BinField expected_fields[2] = { BinField::Kind, BinField::Binding };
-    MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
-#endif // defined(DEBUG)
-    AutoVariableDeclarationKind kindGuard(this);
-
-    BINJS_MOZ_TRY_DECL(kind_, parseVariableDeclarationKind());
-
-    BINJS_MOZ_TRY_DECL(binding, parseBinding());
-
-    // Restored by `kindGuard`.
-    variableDeclarationKind_ = kind_;
-    MOZ_TRY(checkBinding(binding->template as<NameNode>().atom()->asPropertyName()));
-    ParseNodeKind pnk;
-    switch (kind_) {
-      case VariableDeclarationKind::Var:
-        pnk = ParseNodeKind::Var;
-        break;
-      case VariableDeclarationKind::Let:
-        return raiseError("Let is not supported in this preview release");
-      case VariableDeclarationKind::Const:
-        return raiseError("Const is not supported in this preview release");
-    }
-    BINJS_TRY_DECL(result, factory_.newDeclarationList(pnk, tokenizer_->pos(start)));
-    factory_.addList(result, binding);
-    return result;
-}
-
-template<typename Tok> JS::Result<ParseNode*>
-BinASTParser<Tok>::parseInterfaceForInStatement(const size_t start, const BinKind kind, const BinFields& fields)
-{
-    MOZ_ASSERT(kind == BinKind::ForInStatement);
-    BINJS_TRY(CheckRecursionLimit(cx_));
-
-#if defined(DEBUG)
-    const BinField expected_fields[3] = { BinField::Left, BinField::Right, BinField::Body };
-    MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
-#endif // defined(DEBUG)
-    ParseContext::Statement stmt(parseContext_, StatementKind::ForInLoop);
-
-    // Implicit scope around the `for`, used to store `for (let x in  ...)`
-    // or `for (const x in ...)`-style declarations. Detail on the
-    // declaration is stored as part of `scope`.
-    ParseContext::Scope scope(cx_, parseContext_, usedNames_);
-    BINJS_TRY(scope.init(parseContext_));
-
-    BINJS_MOZ_TRY_DECL(left, parseForInOfBindingOrAssignmentTarget());
-
-    BINJS_MOZ_TRY_DECL(right, parseExpression());
-
-    BINJS_MOZ_TRY_DECL(body, parseStatement());
-
-    BINJS_TRY_DECL(forHead, factory_.newForInOrOfHead(ParseNodeKind::ForIn, left, right, tokenizer_->pos(start)));
-    ParseNode* result;
-    BINJS_TRY_VAR(result, factory_.newForStatement(start, forHead, body, /*flags*/ 0));
-
-    if (!scope.isEmpty()) {
-        BINJS_TRY_DECL(bindings, NewLexicalScopeData(cx_, scope, alloc_, parseContext_));
-        BINJS_TRY_VAR(result, factory_.newLexicalScope(*bindings, result));
-    }
-    return result;
-}
-
-template<typename Tok> JS::Result<ParseNode*>
-BinASTParser<Tok>::parseInterfaceForOfStatement(const size_t start, const BinKind kind, const BinFields& fields)
-{
-    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 BinKind kind, const BinFields& fields)
-{
-    MOZ_ASSERT(kind == BinKind::ForStatement);
-    BINJS_TRY(CheckRecursionLimit(cx_));
-
-#if defined(DEBUG)
-    const BinField expected_fields[4] = { BinField::Init, BinField::Test, BinField::Update, BinField::Body };
-    MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
-#endif // defined(DEBUG)
-    ParseContext::Statement stmt(parseContext_, StatementKind::ForLoop);
-
-    // Implicit scope around the `for`, used to store `for (let x; ...; ...)`
-    // or `for (const x; ...; ...)`-style declarations. Detail on the
-    // declaration is stored as part of `BINJS_Scope`.
-    ParseContext::Scope scope(cx_, parseContext_, usedNames_);
-    BINJS_TRY(scope.init(parseContext_));
-
-    BINJS_MOZ_TRY_DECL(init, parseOptionalVariableDeclarationOrExpression());
-
-    BINJS_MOZ_TRY_DECL(test, parseOptionalExpression());
-
-    BINJS_MOZ_TRY_DECL(update, parseOptionalExpression());
-
-    BINJS_MOZ_TRY_DECL(body, parseStatement());
-
-    BINJS_TRY_DECL(forHead, factory_.newForHead(init, test, update, tokenizer_->pos(start)));
-    ParseNode* result;
-    BINJS_TRY_VAR(result, factory_.newForStatement(start, forHead, body, /* iflags = */ 0));
-
-    if (!scope.isEmpty()) {
-        BINJS_TRY_DECL(bindings, NewLexicalScopeData(cx_, scope, alloc_, parseContext_));
-        BINJS_TRY_VAR(result, factory_.newLexicalScope(*bindings, result));
-    }
-    return result;
-}
-
-
-/*
- interface FormalParameters : Node {
-    FrozenArray<Parameter> items;
-    Binding? rest;
- }
-*/
-template<typename Tok> JS::Result<ListNode*>
-BinASTParser<Tok>::parseFormalParameters()
-{
-    BinKind kind;
-    BinFields fields(cx_);
-    AutoTaggedTuple guard(*tokenizer_);
-
-    MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    if (kind != BinKind::FormalParameters) {
-        return raiseInvalidKind("FormalParameters", kind);
-    }
-    const auto start = tokenizer_->offset();
-    BINJS_MOZ_TRY_DECL(result, parseInterfaceFormalParameters(start, kind, fields));
-    MOZ_TRY(guard.done());
-
-    return result;
-}
-
-template<typename Tok> JS::Result<ListNode*>
-BinASTParser<Tok>::parseInterfaceFormalParameters(const size_t start, const BinKind kind, const BinFields& fields)
-{
-    MOZ_ASSERT(kind == BinKind::FormalParameters);
-    BINJS_TRY(CheckRecursionLimit(cx_));
-
-#if defined(DEBUG)
-    const BinField expected_fields[2] = { BinField::Items, BinField::Rest };
-    MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
-#endif // defined(DEBUG)
-
-    BINJS_MOZ_TRY_DECL(items, parseListOfParameter());
-
-    BINJS_MOZ_TRY_DECL(rest, parseOptionalBinding());
-
-    auto result = items;
-    if (rest) {
-        return raiseError("Rest parameter is not supported in this preview release");
-    }
-    return result;
-}
-
-
-/*
- interface FunctionExpressionContents : Node {
-    bool isFunctionNameCaptured;
-    bool isThisCaptured;
-    AssertedParameterScope parameterScope;
-    FormalParameters params;
-    AssertedVarScope bodyScope;
-    FunctionBody body;
- }
-*/
-template<typename Tok> JS::Result<Ok>
-BinASTParser<Tok>::parseFunctionExpressionContents(
-        uint32_t funLength,
-        ListNode** paramsOut,
-        ListNode** bodyOut)
-{
-    BinKind kind;
-    BinFields fields(cx_);
-    AutoTaggedTuple guard(*tokenizer_);
-
-    MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    if (kind != BinKind::FunctionExpressionContents) {
-        return raiseInvalidKind("FunctionExpressionContents", kind);
-    }
-    const auto start = tokenizer_->offset();
-    BINJS_MOZ_TRY_DECL(result, parseInterfaceFunctionExpressionContents(start, kind, fields,
-        funLength, paramsOut, bodyOut));
-    MOZ_TRY(guard.done());
-
-    return result;
-}
-
-template<typename Tok> JS::Result<Ok>
-BinASTParser<Tok>::parseInterfaceFunctionExpressionContents(const size_t start, const BinKind kind, const BinFields& fields,
-        uint32_t funLength,
-        ListNode** paramsOut,
-        ListNode** bodyOut)
-{
-    MOZ_ASSERT(kind == BinKind::FunctionExpressionContents);
-    BINJS_TRY(CheckRecursionLimit(cx_));
-
-#if defined(DEBUG)
-    const BinField expected_fields[6] = { BinField::IsFunctionNameCaptured, BinField::IsThisCaptured, BinField::ParameterScope, BinField::Params, BinField::BodyScope, BinField::Body };
-    MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
-#endif // defined(DEBUG)
-
-    BINJS_MOZ_TRY_DECL(isFunctionNameCaptured, tokenizer_->readBool());
-    // Per spec, isFunctionNameCaptured can be true for anonymous
-    // function.  Check isFunctionNameCaptured only for named
-    // function.
-    if (parseContext_->functionBox()->function()->isNamedLambda() &&
-        isFunctionNameCaptured)
-    {
-        captureFunctionName();
-    }
-    BINJS_MOZ_TRY_DECL(isThisCaptured, tokenizer_->readBool());
-    // TODO: Use this in BinASTParser::buildFunction.
-    (void) isThisCaptured;
-    Rooted<GCVector<JSAtom*>> positionalParams(cx_, GCVector<JSAtom*>(cx_));
-    MOZ_TRY(parseAssertedParameterScope(
-        &positionalParams));
-
-    BINJS_MOZ_TRY_DECL(params, parseFormalParameters());
-    MOZ_TRY(checkFunctionLength(funLength));
-    MOZ_TRY(checkPositionalParameterIndices(positionalParams, params));
-    MOZ_TRY(parseAssertedVarScope());
-
-    BINJS_MOZ_TRY_DECL(body, parseFunctionBody());
-
-    *paramsOut = params;
-    *bodyOut = body;
-    auto result = Ok();
-    return result;
-}
-
-
-/*
- interface FunctionOrMethodContents : Node {
-    bool isThisCaptured;
-    AssertedParameterScope parameterScope;
-    FormalParameters params;
-    AssertedVarScope bodyScope;
-    FunctionBody body;
- }
-*/
-template<typename Tok> JS::Result<Ok>
-BinASTParser<Tok>::parseFunctionOrMethodContents(
-        uint32_t funLength,
-        ListNode** paramsOut,
-        ListNode** bodyOut)
-{
-    BinKind kind;
-    BinFields fields(cx_);
-    AutoTaggedTuple guard(*tokenizer_);
-
-    MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    if (kind != BinKind::FunctionOrMethodContents) {
-        return raiseInvalidKind("FunctionOrMethodContents", kind);
-    }
-    const auto start = tokenizer_->offset();
-    BINJS_MOZ_TRY_DECL(result, parseInterfaceFunctionOrMethodContents(start, kind, fields,
-        funLength, paramsOut, bodyOut));
-    MOZ_TRY(guard.done());
-
-    return result;
-}
-
-template<typename Tok> JS::Result<Ok>
-BinASTParser<Tok>::parseInterfaceFunctionOrMethodContents(const size_t start, const BinKind kind, const BinFields& fields,
-        uint32_t funLength,
-        ListNode** paramsOut,
-        ListNode** bodyOut)
-{
-    MOZ_ASSERT(kind == BinKind::FunctionOrMethodContents);
-    BINJS_TRY(CheckRecursionLimit(cx_));
-
-#if defined(DEBUG)
-    const BinField expected_fields[5] = { BinField::IsThisCaptured, BinField::ParameterScope, BinField::Params, BinField::BodyScope, BinField::Body };
-    MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
-#endif // defined(DEBUG)
-
-    BINJS_MOZ_TRY_DECL(isThisCaptured, tokenizer_->readBool());
-    // TODO: Use this in BinASTParser::buildFunction.
-    (void) isThisCaptured;
-    Rooted<GCVector<JSAtom*>> positionalParams(cx_, GCVector<JSAtom*>(cx_));
-    MOZ_TRY(parseAssertedParameterScope(
-        &positionalParams));
-
-    BINJS_MOZ_TRY_DECL(params, parseFormalParameters());
-    MOZ_TRY(checkFunctionLength(funLength));
-    MOZ_TRY(checkPositionalParameterIndices(positionalParams, params));
-    MOZ_TRY(parseAssertedVarScope());
-
-    BINJS_MOZ_TRY_DECL(body, parseFunctionBody());
-
-    *paramsOut = params;
-    *bodyOut = body;
-    auto result = Ok();
-    return result;
-}
-
-
-/*
- interface GetterContents : Node {
-    bool isThisCaptured;
-    AssertedVarScope bodyScope;
-    FunctionBody body;
- }
-*/
-template<typename Tok> JS::Result<Ok>
-BinASTParser<Tok>::parseGetterContents(
-        uint32_t funLength,
-        ListNode** paramsOut,
-        ListNode** bodyOut)
-{
-    BinKind kind;
-    BinFields fields(cx_);
-    AutoTaggedTuple guard(*tokenizer_);
-
-    MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    if (kind != BinKind::GetterContents) {
-        return raiseInvalidKind("GetterContents", kind);
-    }
-    const auto start = tokenizer_->offset();
-    BINJS_MOZ_TRY_DECL(result, parseInterfaceGetterContents(start, kind, fields,
-        funLength, paramsOut, bodyOut));
-    MOZ_TRY(guard.done());
-
-    return result;
-}
-
-template<typename Tok> JS::Result<Ok>
-BinASTParser<Tok>::parseInterfaceGetterContents(const size_t start, const BinKind kind, const BinFields& fields,
-        uint32_t funLength,
-        ListNode** paramsOut,
-        ListNode** bodyOut)
-{
-    MOZ_ASSERT(kind == BinKind::GetterContents);
-    BINJS_TRY(CheckRecursionLimit(cx_));
-
-#if defined(DEBUG)
-    const BinField expected_fields[3] = { BinField::IsThisCaptured, BinField::BodyScope, BinField::Body };
-    MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
-#endif // defined(DEBUG)
-
-    BINJS_MOZ_TRY_DECL(isThisCaptured, tokenizer_->readBool());
-    // TODO: Use this in BinASTParser::buildFunction.
-    (void) isThisCaptured;
-    MOZ_TRY(parseAssertedVarScope());
-
-    BINJS_TRY_DECL(params, new_<ListNode>(ParseNodeKind::ParamsBody, tokenizer_->pos(start)));
-    BINJS_MOZ_TRY_DECL(body, parseFunctionBody());
-
-    *paramsOut = params;
-    *bodyOut = body;
-    auto result = Ok();
-    return result;
-}
-
-
-/*
- interface IdentifierExpression : Node {
-    [IdentifierName] string name;
- }
-*/
-template<typename Tok> JS::Result<ParseNode*>
-BinASTParser<Tok>::parseIdentifierExpression()
-{
-    BinKind kind;
-    BinFields fields(cx_);
-    AutoTaggedTuple guard(*tokenizer_);
-
-    MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
-    if (kind != BinKind::IdentifierExpression) {
-        return raiseInvalidKind("IdentifierExpression", kind);
-    }
-    const auto start = tokenizer_->offset();
-    BINJS_MOZ_TRY_DECL(result, parseInterfaceIdentifierExpression(start, kind, fields));
-    MOZ_TRY(guard.done());
-
-    return result;
-}
-
-template<typename Tok> JS::Result<ParseNode*>
-BinASTParser<Tok>::parseInterfaceIdentifierExpression(const size_t start, const BinKind kind, const BinFields& fields)
-{
-    MOZ_ASSERT(kind == BinKind::IdentifierExpression);
-    BINJS_TRY(CheckRecursionLimit(cx_));
-
-#if defined(DEBUG)
-    const BinField expected_fields[1] = { BinField::Name };
-    MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
-#endif // defined(DEBUG)
-
-    RootedAtom name(cx_);
-    MOZ_TRY_VAR(name, tokenizer_->readIdentifierName());
-
-    if (!IsIdentifier(name)) {
-        return raiseError("Invalid identifier");
-    }
-    BINJS_TRY(usedNames_.noteUse(cx_, name, parseContext_->scriptId(), parseContext_->innermostScope()->id()));
-    BINJS_TRY_DECL(result, factory_.newName(name->asPropertyName(), tokenizer_->pos(start), cx_));
-    return result;
-}
-
-template<typename Tok> JS::Result<ParseNode*>
-BinASTParser<Tok>::parseInterfaceIfStatement(const size_t start, const BinKind kind, const BinFields& fields)
-{
-    MOZ_ASSERT(kind == BinKind::IfStatement);
-    BINJS_TRY(CheckRecursionLimit(cx_));
-
-#if defined(DEBUG)
-    const BinField expected_fields[3] = { BinField::Test, BinField::Consequent, BinField::Alternate };
-    MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
-#endif // defined(DEBUG)
-
-    BINJS_MOZ_TRY_DECL(test, parseExpression());
-
-    BINJS_MOZ_TRY_DECL(consequent, parseStatement());
-
-    BINJS_MOZ_TRY_DECL(alternate, parseOptionalStatement());
-
-    BINJS_TRY_DECL(result, factory_.newIfStatement(start, test, consequent, alternate));
-    return result;
-}
-
-template<typename Tok> JS::Result<ParseNode*>
-BinASTParser<Tok>::parseInterfaceLabelledStatement(const size_t start, const BinKind kind, const BinFields& fields)
-{
-    MOZ_ASSERT(kind == BinKind::LabelledStatement);
-    BINJS_TRY(CheckRecursionLimit(cx_));
-
-#if defined(DEBUG)
-    const BinField expected_fields[2] = { BinField::Label, BinField::Body };
-    MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
-#endif // defined(DEBUG)
-
-    RootedAtom label(cx_);
-    MOZ_TRY_VAR(label, tokenizer_->readAtom());
-    if (!IsIdentifier(label)) {
-        return raiseError("Invalid identifier");
-    }
-    ParseContext::LabelStatement stmt(parseContext_, label);
-    BINJS_MOZ_TRY_DECL(body, parseStatement());
-
-    BINJS_TRY_DECL(result, factory_.newLabeledStatement(label->asPropertyName(), body, start));
-    return result;
-}
-
-template<typename Tok> JS::Result<ParseNode*>
-BinASTParser<Tok>::parseInterfaceLazyArrowExpressionWithExpression(const size_t start, const BinKind kind, const BinFields& fields)
-{
-    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 BinKind kind, const BinFields& fields)
-{
-    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 BinKind kind, const BinFields& fields)
-{
-    MOZ_ASSERT(kind == BinKind::LazyFunctionDeclaration);
-    BINJS_TRY(CheckRecursionLimit(cx_));
-
-#if defined(DEBUG)
-    const BinField expected_fields[7] = { BinField::IsAsync, BinField::IsGenerator, BinField::Name, BinField::Length, BinField::Directives, BinField::ContentsSkip, BinField::Contents };
-    MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
-#endif // defined(DEBUG)
-    const auto syntax = FunctionSyntaxKind::Statement;
-
-    BINJS_MOZ_TRY_DECL(isAsync, tokenizer_->readBool());
-    if (isAsync) {
-        return raiseError("Async function is not supported in this preview release");
-    }
-    BINJS_MOZ_TRY_DECL(isGenerator, tokenizer_->readBool());
-    if (isGenerator) {
-        return raiseError("Generator is not supported in this preview release");
-    }
-    BINJS_MOZ_TRY_DECL(name, parseBindingIdentifier());
-
-    BINJS_MOZ_TRY_DECL(length, tokenizer_->readUnsignedLong());
-
-    BINJS_MOZ_TRY_DECL(directives, parseListOfDirective());
-
-    BINJS_MOZ_TRY_DECL(contentsSkip, tokenizer_->readSkippableSubTree());
-    // Don't parse the contents until we delazify.
-
-    BINJS_MOZ_TRY_DECL(funbox, buildFunctionBox(
-        isGenerator ? GeneratorKind::Generator
-                    : GeneratorKind::NotGenerator,
-        isAsync ? FunctionAsyncKind::AsyncFunction
-                : FunctionAsyncKind::SyncFunction,
-        syntax, name));
-
-    forceStrictIfNecessary(funbox, directives);
-
-    RootedFunction fun(cx_, funbox->function());
-
-    // TODO: This will become incorrect in the face of ES6 features.
-    fun->setArgCount(length);
-
-    auto skipStart = contentsSkip.startOffset();
-    BINJS_TRY_DECL(lazy, LazyScript::Create(cx_, fun, sourceObject_, parseContext_->closedOverBindingsForLazy(), parseContext_->innerFunctionsForLazy,
-                                            skipStart, skipStart + contentsSkip.length(),
-                                            skipStart, 0, skipStart, ParseGoal::Script));
-
-    if (funbox->strict()) {
-        lazy->setStrict();
-    }
-    lazy->setIsBinAST();
-    funbox->function()->initLazyScript(lazy);
-
-    BINJS_MOZ_TRY_DECL(result, makeEmptyFunctionNode(skipStart, kind, funbox));
-    return result;
-}
-
-template<typename Tok> JS::Result<ParseNode*>
-BinASTParser<Tok>::parseInterfaceLazyFunctionExpression(const size_t start, const BinKind kind, const BinFields& fields)
-{
-    MOZ_ASSERT(kind == BinKind::LazyFunctionExpression);
-    BINJS_TRY(CheckRecursionLimit(cx_));
-
-#if defined(DEBUG)
-    const BinField expected_fields[7] = { BinField::IsAsync, BinField::IsGenerator, BinField::Name, BinField::Length, BinField::Directives, BinField::ContentsSkip, BinField::Contents };
-    MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
-#endif // defined(DEBUG)
-    const auto syntax = FunctionSyntaxKind::Expression;
-
-    BINJS_MOZ_TRY_DECL(isAsync, tokenizer_->readBool());
-    if (isAsync) {
-        return raiseError("Async function is not supported in this preview release");
-    }
-    BINJS_MOZ_TRY_DECL(isGenerator, tokenizer_->readBool());
-    if (isGenerator) {
-        return raiseError("Generator is not supported in this preview release");
-    }
-    BINJS_MOZ_TRY_DECL(name, parseOptionalBindingIdentifier());
-
-    BINJS_MOZ_TRY_DECL(length, tokenizer_->readUnsignedLong());
-
-    BINJS_MOZ_TRY_DECL(directives, parseListOfDirective());
-
-    BINJS_MOZ_TRY_DECL(contentsSkip, tokenizer_->readSkippableSubTree());
-    // Don't parse the contents until we delazify.
-
-    BINJS_MOZ_TRY_DECL(funbox, buildFunctionBox(
-        isGenerator ? GeneratorKind::Generator
-                    : GeneratorKind::NotGenerator,
-        isAsync ? FunctionAsyncKind::AsyncFunction
-                : FunctionAsyncKind::SyncFunction,
-        syntax, name));
-
-    forceStrictIfNecessary(funbox, directives);
-
-    RootedFunction fun(cx_, funbox->function());
-
-    // TODO: This will become incorrect in the face of ES6 features.
-    fun->setArgCount(length);
-
-    auto skipStart = contentsSkip.startOffset();
-    BINJS_TRY_DECL(lazy, LazyScript::Create(cx_, fun, sourceObject_, parseContext_->closedOverBindingsForLazy(), parseContext_->innerFunctionsForLazy,
-                                            skipStart, skipStart + contentsSkip.length(),
-                                            skipStart, 0, skipStart, ParseGoal::Script));
-
-    if (funbox->strict()) {
-        lazy->setStrict();
-    }
-    lazy->setIsBinAST();
-    funbox->function()->initLazyScript(lazy);
-
-    BINJS_MOZ_TRY_DECL(result, makeEmptyFunctionNode(skipStart, kind, funbox));
-    return result;
-}
-
-template<typename Tok> JS::Result<ParseNode*>
-BinASTParser<Tok>::parseInterfaceLazyGetter(const size_t start, const BinKind kind, const BinFields& fields)
-{
-    return raiseError("FIXME: Not implemented yet in this preview release (LazyGetter)");
-}
-
-template<typename Tok> JS::Result<ParseNode*>
-BinASTParser<Tok>::parseInterfaceLazyMethod(const size_t start, const BinKind kind, const BinFields& fields)
-{
-    return raiseError("FIXME: Not implemented yet in this preview release (LazyMethod)");
-}
-
-template<typename Tok> JS::Result<ParseNode*>
-BinASTParser<Tok>::parseInterfaceLazySetter(const size_t start, const BinKind kind, const BinFields& fields)
-{
-    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 BinKind kind, const BinFields& fields)
-{
-    MOZ_ASSERT(kind == BinKind::LiteralBooleanExpression);
-    BINJS_TRY(CheckRecursionLimit(cx_));
-
-#if defined(DEBUG)
-    const BinField expected_fields[1] = { BinField::Value };
-    MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
-#endif // defined(DEBUG)
-
-    BINJS_MOZ_TRY_DECL(value, tokenizer_->readBool());
-
-    BINJS_TRY_DECL(result, factory_.newBooleanLiteral(value, tokenizer_->pos(start)));
-    return result;
-}
-
-template<typename Tok> JS::Result<ParseNode*>
-BinASTParser<Tok>::parseInterfaceLiteralInfinityExpression(const size_t start, const BinKind kind, const BinFields& fields)
-{
-    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 BinKind kind, const BinFields& fields)
-{
-    MOZ_ASSERT(kind == BinKind::LiteralNullExpression);
-    BINJS_TRY(CheckRecursionLimit(cx_));
-MOZ_TRY(tokenizer_->checkFields0(kind, fields));
-
-    BINJS_TRY_DECL(result, factory_.newNullLiteral(tokenizer_->pos(start)));
-    return result;
-}
-
-template<typename Tok> JS::Result<ParseNode*>
-BinASTParser<Tok>::parseInterfaceLiteralNumericExpression(const size_t start, const BinKind kind, const BinFields& fields)
-{
-    MOZ_ASSERT(kind == BinKind::LiteralNumericExpression);
-    BINJS_TRY(CheckRecursionLimit(cx_));
-