new file mode 100644
--- /dev/null
+++ b/js/src/frontend/BinSource-auto.cpp
@@ -0,0 +1,6987 @@
+// 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, you will need to run binjs_generate_spidermonkey,
+// as follows:
+// - cd $(topsrcdir)/js/src/frontend/binsource
+// - cargo run -- $(topsrcdir)/js/src/frontend/BinSource.webidl $(topsrcdir)/js/src/frontend/BinSource.yaml
+// --out-class $(topsrcdir)/js/src/frontend/{class}
+// --out-impl $(topsrcdir)/js/src/frontend/{impl_}
+// --out-token $(topsrcdir)/js/src/frontend/{token}
+
+#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.h"
+#include "frontend/BinTokenReaderTester.h"
+#include "frontend/FullParseHandler.h"
+#include "frontend/Parser.h"
+#include "frontend/SharedContext.h"
+
+#include "vm/RegExpObject.h"
+
+#include "frontend/ParseContext-inl.h"
+#include "frontend/ParseNode-inl.h"
+
+namespace js {
+namespace frontend {
+
+using AutoList = BinTokenReaderTester::AutoList;
+using AutoTaggedTuple = BinTokenReaderTester::AutoTaggedTuple;
+using AutoTuple = BinTokenReaderTester::AutoTuple;
+using BinFields = BinTokenReaderTester::BinFields;
+using Chars = BinTokenReaderTester::Chars;
+using NameBag = GCHashSet<JSString*>;
+using Names = GCVector<JSString*, 8>;
+using UsedNamePtr = UsedNameTracker::UsedNameMap::Ptr;
+
+// Evaluate an expression EXPR, checking that the result is not falsy.
+//
+// Throw `cx->alreadyReportedError()` if it returns 0/nullptr.
+#define TRY(EXPR) \
+ do { \
+ if (!EXPR) \
+ return cx_->alreadyReportedError(); \
+ } while(false)
+
+
+// Evaluate an expression EXPR, checking that the result is not falsy.
+// In case of success, assign the result to VAR.
+//
+// Throw `cx->alreadyReportedError()` if it returns 0/nullptr.
+#define TRY_VAR(VAR, EXPR) \
+ do { \
+ VAR = EXPR; \
+ if (!VAR) \
+ return cx_->alreadyReportedError(); \
+ } while (false)
+
+// Evaluate an expression EXPR, checking that the result is not falsy.
+// In case of success, assign the result to a new variable VAR.
+//
+// Throw `cx->alreadyReportedError()` if it returns 0/nullptr.
+#define TRY_DECL(VAR, EXPR) \
+ auto VAR = EXPR; \
+ if (!VAR) \
+ return cx_->alreadyReportedError();
+
+// Evaluate an expression EXPR, checking that the result is a success.
+// In case of success, unwrap and assign the result to a new variable VAR.
+//
+// In case of error, propagate the error.
+#define MOZ_TRY_DECL(VAR, EXPR) \
+ auto _##VAR = EXPR; \
+ if (_##VAR.isErr()) \
+ return ::mozilla::Err(_##VAR.unwrapErr()); \
+ auto VAR = _##VAR.unwrap();
+
+// Ensure that we are visiting the right fields.
+template<size_t N>
+JS::Result<Ok, JS::Error&>
+BinASTParser::checkFields(const BinKind kind, const BinFields& actual, const BinField (&expected)[N])
+{
+ if (actual.length() != N)
+ return raiseInvalidNumberOfFields(kind, N, actual.length());
+
+ for (size_t i = 0; i < N; ++i) {
+ if (actual[i] != expected[i])
+ return raiseInvalidField(describeBinKind(kind), actual[i]);
+ }
+
+ return Ok();
+}
+
+// Special case for N=0, as empty arrays are not permitted in C++
+JS::Result<Ok, JS::Error&>
+BinASTParser::checkFields0(const BinKind kind, const BinFields& actual)
+{
+ if (actual.length() != 0)
+ return raiseInvalidNumberOfFields(kind, 0, actual.length());
+
+ return Ok();
+}
+
+// Compare a bunch of `uint8_t` values (as returned by the tokenizer_) with
+// a string literal (and ONLY a string literal).
+template<size_t N>
+bool operator==(const Chars& left, const char (&right)[N]) {
+ return BinTokenReaderTester::equals(left, right);
+}
+
+// Helper class: Restore field `variableDeclarationKind` upon leaving a scope.
+class MOZ_RAII AutoVariableDeclarationKind {
+ public:
+ explicit AutoVariableDeclarationKind(BinASTParser* parser
+ MOZ_GUARD_OBJECT_NOTIFIER_PARAM) :
+ parser_(parser),
+ kind(parser->variableDeclarationKind)
+ {
+ MOZ_GUARD_OBJECT_NOTIFIER_INIT;
+ }
+ ~AutoVariableDeclarationKind() {
+ parser_->variableDeclarationKind = kind;
+ }
+ private:
+ BinASTParser* parser_;
+ BinASTParser::VariableDeclarationKind kind;
+ MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
+};
+
+
+// ----- Sums of interfaces (autogenerated, by lexicographical order)
+// Sums of sums are flattened.
+/*
+AssignmentTarget ::= ArrayAssignmentTarget
+ AssignmentTargetIdentifier
+ ComputedMemberAssignmentTarget
+ ObjectAssignmentTarget
+ StaticMemberAssignmentTarget
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseAssignmentTarget()
+{
+ BinKind kind;
+ BinFields fields((cx_));
+ AutoTaggedTuple guard(*tokenizer_);
+ const auto start = tokenizer_->offset();
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+
+ MOZ_TRY_DECL(result, parseSumAssignmentTarget(start, kind, fields));
+
+ TRY(guard.done());
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::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;
+}
+
+/*
+AssignmentTargetOrAssignmentTargetWithInitializer ::= ArrayAssignmentTarget
+ AssignmentTargetIdentifier
+ AssignmentTargetWithInitializer
+ ComputedMemberAssignmentTarget
+ ObjectAssignmentTarget
+ StaticMemberAssignmentTarget
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseAssignmentTargetOrAssignmentTargetWithInitializer()
+{
+ BinKind kind;
+ BinFields fields((cx_));
+ AutoTaggedTuple guard(*tokenizer_);
+ const auto start = tokenizer_->offset();
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+
+ MOZ_TRY_DECL(result, parseSumAssignmentTargetOrAssignmentTargetWithInitializer(start, kind, fields));
+
+ TRY(guard.done());
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseSumAssignmentTargetOrAssignmentTargetWithInitializer(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::AssignmentTargetWithInitializer:
+ MOZ_TRY_VAR(result, parseInterfaceAssignmentTargetWithInitializer(start, kind, fields));
+ break;
+ case BinKind::ComputedMemberAssignmentTarget:
+ MOZ_TRY_VAR(result, parseInterfaceComputedMemberAssignmentTarget(start, kind, fields));
+ break;
+ case BinKind::ObjectAssignmentTarget:
+ MOZ_TRY_VAR(result, parseInterfaceObjectAssignmentTarget(start, kind, fields));
+ break;
+ case BinKind::StaticMemberAssignmentTarget:
+ MOZ_TRY_VAR(result, parseInterfaceStaticMemberAssignmentTarget(start, kind, fields));
+ break;
+ default:
+ return raiseInvalidKind("AssignmentTargetOrAssignmentTargetWithInitializer", kind);
+ }
+ return result;
+}
+
+/*
+AssignmentTargetPattern ::= ArrayAssignmentTarget
+ ObjectAssignmentTarget
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseAssignmentTargetPattern()
+{
+ BinKind kind;
+ BinFields fields((cx_));
+ AutoTaggedTuple guard(*tokenizer_);
+ const auto start = tokenizer_->offset();
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+
+ MOZ_TRY_DECL(result, parseSumAssignmentTargetPattern(start, kind, fields));
+
+ TRY(guard.done());
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseSumAssignmentTargetPattern(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::ObjectAssignmentTarget:
+ MOZ_TRY_VAR(result, parseInterfaceObjectAssignmentTarget(start, kind, fields));
+ break;
+ default:
+ return raiseInvalidKind("AssignmentTargetPattern", kind);
+ }
+ return result;
+}
+
+/*
+AssignmentTargetProperty ::= AssignmentTargetPropertyIdentifier
+ AssignmentTargetPropertyProperty
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseAssignmentTargetProperty()
+{
+ BinKind kind;
+ BinFields fields((cx_));
+ AutoTaggedTuple guard(*tokenizer_);
+ const auto start = tokenizer_->offset();
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+
+ MOZ_TRY_DECL(result, parseSumAssignmentTargetProperty(start, kind, fields));
+
+ TRY(guard.done());
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseSumAssignmentTargetProperty(const size_t start, const BinKind kind, const BinFields& fields)
+{
+ ParseNode* result;
+ switch(kind) {
+ case BinKind::AssignmentTargetPropertyIdentifier:
+ MOZ_TRY_VAR(result, parseInterfaceAssignmentTargetPropertyIdentifier(start, kind, fields));
+ break;
+ case BinKind::AssignmentTargetPropertyProperty:
+ MOZ_TRY_VAR(result, parseInterfaceAssignmentTargetPropertyProperty(start, kind, fields));
+ break;
+ default:
+ return raiseInvalidKind("AssignmentTargetProperty", kind);
+ }
+ return result;
+}
+
+/*
+Binding ::= ArrayBinding
+ BindingIdentifier
+ ObjectBinding
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseBinding()
+{
+ BinKind kind;
+ BinFields fields((cx_));
+ AutoTaggedTuple guard(*tokenizer_);
+ const auto start = tokenizer_->offset();
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+
+ MOZ_TRY_DECL(result, parseSumBinding(start, kind, fields));
+
+ TRY(guard.done());
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::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;
+}
+
+/*
+BindingOrBindingWithInitializer ::= ArrayBinding
+ BindingIdentifier
+ BindingWithInitializer
+ ObjectBinding
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseBindingOrBindingWithInitializer()
+{
+ BinKind kind;
+ BinFields fields((cx_));
+ AutoTaggedTuple guard(*tokenizer_);
+ const auto start = tokenizer_->offset();
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+
+ MOZ_TRY_DECL(result, parseSumBindingOrBindingWithInitializer(start, kind, fields));
+
+ TRY(guard.done());
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseSumBindingOrBindingWithInitializer(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::BindingWithInitializer:
+ MOZ_TRY_VAR(result, parseInterfaceBindingWithInitializer(start, kind, fields));
+ break;
+ case BinKind::ObjectBinding:
+ MOZ_TRY_VAR(result, parseInterfaceObjectBinding(start, kind, fields));
+ break;
+ default:
+ return raiseInvalidKind("BindingOrBindingWithInitializer", kind);
+ }
+ return result;
+}
+
+/*
+BindingPattern ::= ArrayBinding
+ ObjectBinding
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseBindingPattern()
+{
+ BinKind kind;
+ BinFields fields((cx_));
+ AutoTaggedTuple guard(*tokenizer_);
+ const auto start = tokenizer_->offset();
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+
+ MOZ_TRY_DECL(result, parseSumBindingPattern(start, kind, fields));
+
+ TRY(guard.done());
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseSumBindingPattern(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::ObjectBinding:
+ MOZ_TRY_VAR(result, parseInterfaceObjectBinding(start, kind, fields));
+ break;
+ default:
+ return raiseInvalidKind("BindingPattern", kind);
+ }
+ return result;
+}
+
+/*
+BindingProperty ::= BindingPropertyIdentifier
+ BindingPropertyProperty
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseBindingProperty()
+{
+ BinKind kind;
+ BinFields fields((cx_));
+ AutoTaggedTuple guard(*tokenizer_);
+ const auto start = tokenizer_->offset();
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+
+ MOZ_TRY_DECL(result, parseSumBindingProperty(start, kind, fields));
+
+ TRY(guard.done());
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseSumBindingProperty(const size_t start, const BinKind kind, const BinFields& fields)
+{
+ ParseNode* result;
+ switch(kind) {
+ case BinKind::BindingPropertyIdentifier:
+ MOZ_TRY_VAR(result, parseInterfaceBindingPropertyIdentifier(start, kind, fields));
+ break;
+ case BinKind::BindingPropertyProperty:
+ MOZ_TRY_VAR(result, parseInterfaceBindingPropertyProperty(start, kind, fields));
+ break;
+ default:
+ return raiseInvalidKind("BindingProperty", kind);
+ }
+ return result;
+}
+
+/*
+ExportDeclaration ::= Export
+ ExportAllFrom
+ ExportDefault
+ ExportFrom
+ ExportLocals
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseExportDeclaration()
+{
+ BinKind kind;
+ BinFields fields((cx_));
+ AutoTaggedTuple guard(*tokenizer_);
+ const auto start = tokenizer_->offset();
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+
+ MOZ_TRY_DECL(result, parseSumExportDeclaration(start, kind, fields));
+
+ TRY(guard.done());
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseSumExportDeclaration(const size_t start, const BinKind kind, const BinFields& fields)
+{
+ ParseNode* result;
+ switch(kind) {
+ case BinKind::Export:
+ MOZ_TRY_VAR(result, parseInterfaceExport(start, kind, fields));
+ break;
+ case BinKind::ExportAllFrom:
+ MOZ_TRY_VAR(result, parseInterfaceExportAllFrom(start, kind, fields));
+ break;
+ case BinKind::ExportDefault:
+ MOZ_TRY_VAR(result, parseInterfaceExportDefault(start, kind, fields));
+ break;
+ case BinKind::ExportFrom:
+ MOZ_TRY_VAR(result, parseInterfaceExportFrom(start, kind, fields));
+ break;
+ case BinKind::ExportLocals:
+ MOZ_TRY_VAR(result, parseInterfaceExportLocals(start, kind, fields));
+ break;
+ default:
+ return raiseInvalidKind("ExportDeclaration", kind);
+ }
+ return result;
+}
+
+/*
+Expression ::= ArrayExpression
+ ArrowExpression
+ AssignmentExpression
+ AwaitExpression
+ BinaryExpression
+ CallExpression
+ ClassExpression
+ CompoundAssignmentExpression
+ ComputedMemberExpression
+ ConditionalExpression
+ FunctionExpression
+ IdentifierExpression
+ LiteralBooleanExpression
+ LiteralInfinityExpression
+ LiteralNullExpression
+ LiteralNumericExpression
+ LiteralRegExpExpression
+ LiteralStringExpression
+ NewExpression
+ NewTargetExpression
+ ObjectExpression
+ StaticMemberExpression
+ TemplateExpression
+ ThisExpression
+ UnaryExpression
+ UpdateExpression
+ YieldExpression
+ YieldStarExpression
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseExpression()
+{
+ BinKind kind;
+ BinFields fields((cx_));
+ AutoTaggedTuple guard(*tokenizer_);
+ const auto start = tokenizer_->offset();
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+
+ MOZ_TRY_DECL(result, parseSumExpression(start, kind, fields));
+
+ TRY(guard.done());
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::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::ArrowExpression:
+ MOZ_TRY_VAR(result, parseInterfaceArrowExpression(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::FunctionExpression:
+ MOZ_TRY_VAR(result, parseInterfaceFunctionExpression(start, kind, fields));
+ break;
+ case BinKind::IdentifierExpression:
+ MOZ_TRY_VAR(result, parseInterfaceIdentifierExpression(start, kind, fields));
+ break;
+ case BinKind::LiteralBooleanExpression:
+ MOZ_TRY_VAR(result, parseInterfaceLiteralBooleanExpression(start, kind, fields));
+ break;
+ case BinKind::LiteralInfinityExpression:
+ MOZ_TRY_VAR(result, parseInterfaceLiteralInfinityExpression(start, kind, fields));
+ break;
+ case BinKind::LiteralNullExpression:
+ MOZ_TRY_VAR(result, parseInterfaceLiteralNullExpression(start, kind, fields));
+ break;
+ case BinKind::LiteralNumericExpression:
+ MOZ_TRY_VAR(result, parseInterfaceLiteralNumericExpression(start, kind, fields));
+ break;
+ case BinKind::LiteralRegExpExpression:
+ MOZ_TRY_VAR(result, parseInterfaceLiteralRegExpExpression(start, kind, fields));
+ break;
+ case BinKind::LiteralStringExpression:
+ MOZ_TRY_VAR(result, parseInterfaceLiteralStringExpression(start, kind, fields));
+ break;
+ case BinKind::NewExpression:
+ MOZ_TRY_VAR(result, parseInterfaceNewExpression(start, kind, fields));
+ break;
+ case BinKind::NewTargetExpression:
+ MOZ_TRY_VAR(result, parseInterfaceNewTargetExpression(start, kind, fields));
+ break;
+ case BinKind::ObjectExpression:
+ MOZ_TRY_VAR(result, parseInterfaceObjectExpression(start, kind, fields));
+ break;
+ case BinKind::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
+ ArrowExpression
+ AssignmentExpression
+ AwaitExpression
+ BinaryExpression
+ CallExpression
+ ClassExpression
+ CompoundAssignmentExpression
+ ComputedMemberExpression
+ ConditionalExpression
+ FunctionExpression
+ IdentifierExpression
+ LiteralBooleanExpression
+ LiteralInfinityExpression
+ LiteralNullExpression
+ LiteralNumericExpression
+ LiteralRegExpExpression
+ LiteralStringExpression
+ NewExpression
+ NewTargetExpression
+ ObjectExpression
+ StaticMemberExpression
+ Super
+ TemplateExpression
+ ThisExpression
+ UnaryExpression
+ UpdateExpression
+ YieldExpression
+ YieldStarExpression
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseExpressionOrSuper()
+{
+ BinKind kind;
+ BinFields fields((cx_));
+ AutoTaggedTuple guard(*tokenizer_);
+ const auto start = tokenizer_->offset();
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+
+ MOZ_TRY_DECL(result, parseSumExpressionOrSuper(start, kind, fields));
+
+ TRY(guard.done());
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::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::ArrowExpression:
+ MOZ_TRY_VAR(result, parseInterfaceArrowExpression(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::FunctionExpression:
+ MOZ_TRY_VAR(result, parseInterfaceFunctionExpression(start, kind, fields));
+ break;
+ case BinKind::IdentifierExpression:
+ MOZ_TRY_VAR(result, parseInterfaceIdentifierExpression(start, kind, fields));
+ break;
+ case BinKind::LiteralBooleanExpression:
+ MOZ_TRY_VAR(result, parseInterfaceLiteralBooleanExpression(start, kind, fields));
+ break;
+ case BinKind::LiteralInfinityExpression:
+ MOZ_TRY_VAR(result, parseInterfaceLiteralInfinityExpression(start, kind, fields));
+ break;
+ case BinKind::LiteralNullExpression:
+ MOZ_TRY_VAR(result, parseInterfaceLiteralNullExpression(start, kind, fields));
+ break;
+ case BinKind::LiteralNumericExpression:
+ MOZ_TRY_VAR(result, parseInterfaceLiteralNumericExpression(start, kind, fields));
+ break;
+ case BinKind::LiteralRegExpExpression:
+ MOZ_TRY_VAR(result, parseInterfaceLiteralRegExpExpression(start, kind, fields));
+ break;
+ case BinKind::LiteralStringExpression:
+ MOZ_TRY_VAR(result, parseInterfaceLiteralStringExpression(start, kind, fields));
+ break;
+ case BinKind::NewExpression:
+ MOZ_TRY_VAR(result, parseInterfaceNewExpression(start, kind, fields));
+ break;
+ case BinKind::NewTargetExpression:
+ MOZ_TRY_VAR(result, parseInterfaceNewTargetExpression(start, kind, fields));
+ break;
+ case BinKind::ObjectExpression:
+ MOZ_TRY_VAR(result, parseInterfaceObjectExpression(start, kind, fields));
+ break;
+ case BinKind::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;
+}
+
+/*
+ExpressionOrTemplateElement ::= ArrayExpression
+ ArrowExpression
+ AssignmentExpression
+ AwaitExpression
+ BinaryExpression
+ CallExpression
+ ClassExpression
+ CompoundAssignmentExpression
+ ComputedMemberExpression
+ ConditionalExpression
+ FunctionExpression
+ IdentifierExpression
+ LiteralBooleanExpression
+ LiteralInfinityExpression
+ LiteralNullExpression
+ LiteralNumericExpression
+ LiteralRegExpExpression
+ LiteralStringExpression
+ NewExpression
+ NewTargetExpression
+ ObjectExpression
+ StaticMemberExpression
+ TemplateElement
+ TemplateExpression
+ ThisExpression
+ UnaryExpression
+ UpdateExpression
+ YieldExpression
+ YieldStarExpression
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseExpressionOrTemplateElement()
+{
+ BinKind kind;
+ BinFields fields((cx_));
+ AutoTaggedTuple guard(*tokenizer_);
+ const auto start = tokenizer_->offset();
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+
+ MOZ_TRY_DECL(result, parseSumExpressionOrTemplateElement(start, kind, fields));
+
+ TRY(guard.done());
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseSumExpressionOrTemplateElement(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::ArrowExpression:
+ MOZ_TRY_VAR(result, parseInterfaceArrowExpression(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::FunctionExpression:
+ MOZ_TRY_VAR(result, parseInterfaceFunctionExpression(start, kind, fields));
+ break;
+ case BinKind::IdentifierExpression:
+ MOZ_TRY_VAR(result, parseInterfaceIdentifierExpression(start, kind, fields));
+ break;
+ case BinKind::LiteralBooleanExpression:
+ MOZ_TRY_VAR(result, parseInterfaceLiteralBooleanExpression(start, kind, fields));
+ break;
+ case BinKind::LiteralInfinityExpression:
+ MOZ_TRY_VAR(result, parseInterfaceLiteralInfinityExpression(start, kind, fields));
+ break;
+ case BinKind::LiteralNullExpression:
+ MOZ_TRY_VAR(result, parseInterfaceLiteralNullExpression(start, kind, fields));
+ break;
+ case BinKind::LiteralNumericExpression:
+ MOZ_TRY_VAR(result, parseInterfaceLiteralNumericExpression(start, kind, fields));
+ break;
+ case BinKind::LiteralRegExpExpression:
+ MOZ_TRY_VAR(result, parseInterfaceLiteralRegExpExpression(start, kind, fields));
+ break;
+ case BinKind::LiteralStringExpression:
+ MOZ_TRY_VAR(result, parseInterfaceLiteralStringExpression(start, kind, fields));
+ break;
+ case BinKind::NewExpression:
+ MOZ_TRY_VAR(result, parseInterfaceNewExpression(start, kind, fields));
+ break;
+ case BinKind::NewTargetExpression:
+ MOZ_TRY_VAR(result, parseInterfaceNewTargetExpression(start, kind, fields));
+ break;
+ case BinKind::ObjectExpression:
+ MOZ_TRY_VAR(result, parseInterfaceObjectExpression(start, kind, fields));
+ break;
+ case BinKind::StaticMemberExpression:
+ MOZ_TRY_VAR(result, parseInterfaceStaticMemberExpression(start, kind, fields));
+ break;
+ case BinKind::TemplateElement:
+ MOZ_TRY_VAR(result, parseInterfaceTemplateElement(start, kind, fields));
+ break;
+ case BinKind::TemplateExpression:
+ MOZ_TRY_VAR(result, parseInterfaceTemplateExpression(start, kind, fields));
+ break;
+ case BinKind::ThisExpression:
+ MOZ_TRY_VAR(result, parseInterfaceThisExpression(start, kind, fields));
+ break;
+ case BinKind::UnaryExpression:
+ MOZ_TRY_VAR(result, parseInterfaceUnaryExpression(start, kind, fields));
+ break;
+ case BinKind::UpdateExpression:
+ MOZ_TRY_VAR(result, parseInterfaceUpdateExpression(start, kind, fields));
+ break;
+ case BinKind::YieldExpression:
+ MOZ_TRY_VAR(result, parseInterfaceYieldExpression(start, kind, fields));
+ break;
+ case BinKind::YieldStarExpression:
+ MOZ_TRY_VAR(result, parseInterfaceYieldStarExpression(start, kind, fields));
+ break;
+ default:
+ return raiseInvalidKind("ExpressionOrTemplateElement", kind);
+ }
+ return result;
+}
+
+/*
+ForInOfBindingOrAssignmentTarget ::= ArrayAssignmentTarget
+ AssignmentTargetIdentifier
+ ComputedMemberAssignmentTarget
+ ForInOfBinding
+ ObjectAssignmentTarget
+ StaticMemberAssignmentTarget
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseForInOfBindingOrAssignmentTarget()
+{
+ BinKind kind;
+ BinFields fields((cx_));
+ AutoTaggedTuple guard(*tokenizer_);
+ const auto start = tokenizer_->offset();
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+
+ MOZ_TRY_DECL(result, parseSumForInOfBindingOrAssignmentTarget(start, kind, fields));
+
+ TRY(guard.done());
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::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;
+}
+
+/*
+FunctionBodyOrExpression ::= ArrayExpression
+ ArrowExpression
+ AssignmentExpression
+ AwaitExpression
+ BinaryExpression
+ CallExpression
+ ClassExpression
+ CompoundAssignmentExpression
+ ComputedMemberExpression
+ ConditionalExpression
+ FunctionBody
+ FunctionExpression
+ IdentifierExpression
+ LiteralBooleanExpression
+ LiteralInfinityExpression
+ LiteralNullExpression
+ LiteralNumericExpression
+ LiteralRegExpExpression
+ LiteralStringExpression
+ NewExpression
+ NewTargetExpression
+ ObjectExpression
+ StaticMemberExpression
+ TemplateExpression
+ ThisExpression
+ UnaryExpression
+ UpdateExpression
+ YieldExpression
+ YieldStarExpression
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseFunctionBodyOrExpression()
+{
+ BinKind kind;
+ BinFields fields((cx_));
+ AutoTaggedTuple guard(*tokenizer_);
+ const auto start = tokenizer_->offset();
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+
+ MOZ_TRY_DECL(result, parseSumFunctionBodyOrExpression(start, kind, fields));
+
+ TRY(guard.done());
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseSumFunctionBodyOrExpression(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::ArrowExpression:
+ MOZ_TRY_VAR(result, parseInterfaceArrowExpression(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::FunctionBody:
+ MOZ_TRY_VAR(result, parseInterfaceFunctionBody(start, kind, fields));
+ break;
+ case BinKind::FunctionExpression:
+ MOZ_TRY_VAR(result, parseInterfaceFunctionExpression(start, kind, fields));
+ break;
+ case BinKind::IdentifierExpression:
+ MOZ_TRY_VAR(result, parseInterfaceIdentifierExpression(start, kind, fields));
+ break;
+ case BinKind::LiteralBooleanExpression:
+ MOZ_TRY_VAR(result, parseInterfaceLiteralBooleanExpression(start, kind, fields));
+ break;
+ case BinKind::LiteralInfinityExpression:
+ MOZ_TRY_VAR(result, parseInterfaceLiteralInfinityExpression(start, kind, fields));
+ break;
+ case BinKind::LiteralNullExpression:
+ MOZ_TRY_VAR(result, parseInterfaceLiteralNullExpression(start, kind, fields));
+ break;
+ case BinKind::LiteralNumericExpression:
+ MOZ_TRY_VAR(result, parseInterfaceLiteralNumericExpression(start, kind, fields));
+ break;
+ case BinKind::LiteralRegExpExpression:
+ MOZ_TRY_VAR(result, parseInterfaceLiteralRegExpExpression(start, kind, fields));
+ break;
+ case BinKind::LiteralStringExpression:
+ MOZ_TRY_VAR(result, parseInterfaceLiteralStringExpression(start, kind, fields));
+ break;
+ case BinKind::NewExpression:
+ MOZ_TRY_VAR(result, parseInterfaceNewExpression(start, kind, fields));
+ break;
+ case BinKind::NewTargetExpression:
+ MOZ_TRY_VAR(result, parseInterfaceNewTargetExpression(start, kind, fields));
+ break;
+ case BinKind::ObjectExpression:
+ MOZ_TRY_VAR(result, parseInterfaceObjectExpression(start, kind, fields));
+ break;
+ case BinKind::StaticMemberExpression:
+ MOZ_TRY_VAR(result, parseInterfaceStaticMemberExpression(start, kind, fields));
+ break;
+ case BinKind::TemplateExpression:
+ MOZ_TRY_VAR(result, parseInterfaceTemplateExpression(start, kind, fields));
+ break;
+ case BinKind::ThisExpression:
+ MOZ_TRY_VAR(result, parseInterfaceThisExpression(start, kind, fields));
+ break;
+ case BinKind::UnaryExpression:
+ MOZ_TRY_VAR(result, parseInterfaceUnaryExpression(start, kind, fields));
+ break;
+ case BinKind::UpdateExpression:
+ MOZ_TRY_VAR(result, parseInterfaceUpdateExpression(start, kind, fields));
+ break;
+ case BinKind::YieldExpression:
+ MOZ_TRY_VAR(result, parseInterfaceYieldExpression(start, kind, fields));
+ break;
+ case BinKind::YieldStarExpression:
+ MOZ_TRY_VAR(result, parseInterfaceYieldStarExpression(start, kind, fields));
+ break;
+ default:
+ return raiseInvalidKind("FunctionBodyOrExpression", kind);
+ }
+ return result;
+}
+
+/*
+FunctionDeclarationOrClassDeclarationOrExpression ::= ArrayExpression
+ ArrowExpression
+ AssignmentExpression
+ AwaitExpression
+ BinaryExpression
+ CallExpression
+ ClassDeclaration
+ ClassExpression
+ CompoundAssignmentExpression
+ ComputedMemberExpression
+ ConditionalExpression
+ FunctionDeclaration
+ FunctionExpression
+ IdentifierExpression
+ LiteralBooleanExpression
+ LiteralInfinityExpression
+ LiteralNullExpression
+ LiteralNumericExpression
+ LiteralRegExpExpression
+ LiteralStringExpression
+ NewExpression
+ NewTargetExpression
+ ObjectExpression
+ StaticMemberExpression
+ TemplateExpression
+ ThisExpression
+ UnaryExpression
+ UpdateExpression
+ YieldExpression
+ YieldStarExpression
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseFunctionDeclarationOrClassDeclarationOrExpression()
+{
+ BinKind kind;
+ BinFields fields((cx_));
+ AutoTaggedTuple guard(*tokenizer_);
+ const auto start = tokenizer_->offset();
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+
+ MOZ_TRY_DECL(result, parseSumFunctionDeclarationOrClassDeclarationOrExpression(start, kind, fields));
+
+ TRY(guard.done());
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseSumFunctionDeclarationOrClassDeclarationOrExpression(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::ArrowExpression:
+ MOZ_TRY_VAR(result, parseInterfaceArrowExpression(start, kind, fields));
+ break;
+ case BinKind::AssignmentExpression:
+ MOZ_TRY_VAR(result, parseInterfaceAssignmentExpression(start, kind, fields));
+ break;
+ case BinKind::AwaitExpression:
+ MOZ_TRY_VAR(result, parseInterfaceAwaitExpression(start, kind, fields));
+ break;
+ case BinKind::BinaryExpression:
+ MOZ_TRY_VAR(result, parseInterfaceBinaryExpression(start, kind, fields));
+ break;
+ case BinKind::CallExpression:
+ MOZ_TRY_VAR(result, parseInterfaceCallExpression(start, kind, fields));
+ break;
+ case BinKind::ClassDeclaration:
+ MOZ_TRY_VAR(result, parseInterfaceClassDeclaration(start, kind, fields));
+ break;
+ case BinKind::ClassExpression:
+ MOZ_TRY_VAR(result, parseInterfaceClassExpression(start, kind, fields));
+ break;
+ case BinKind::CompoundAssignmentExpression:
+ MOZ_TRY_VAR(result, parseInterfaceCompoundAssignmentExpression(start, kind, fields));
+ break;
+ case BinKind::ComputedMemberExpression:
+ MOZ_TRY_VAR(result, parseInterfaceComputedMemberExpression(start, kind, fields));
+ break;
+ case BinKind::ConditionalExpression:
+ MOZ_TRY_VAR(result, parseInterfaceConditionalExpression(start, kind, fields));
+ break;
+ case BinKind::FunctionDeclaration:
+ MOZ_TRY_VAR(result, parseInterfaceFunctionDeclaration(start, kind, fields));
+ break;
+ case BinKind::FunctionExpression:
+ MOZ_TRY_VAR(result, parseInterfaceFunctionExpression(start, kind, fields));
+ break;
+ case BinKind::IdentifierExpression:
+ MOZ_TRY_VAR(result, parseInterfaceIdentifierExpression(start, kind, fields));
+ break;
+ case BinKind::LiteralBooleanExpression:
+ MOZ_TRY_VAR(result, parseInterfaceLiteralBooleanExpression(start, kind, fields));
+ break;
+ case BinKind::LiteralInfinityExpression:
+ MOZ_TRY_VAR(result, parseInterfaceLiteralInfinityExpression(start, kind, fields));
+ break;
+ case BinKind::LiteralNullExpression:
+ MOZ_TRY_VAR(result, parseInterfaceLiteralNullExpression(start, kind, fields));
+ break;
+ case BinKind::LiteralNumericExpression:
+ MOZ_TRY_VAR(result, parseInterfaceLiteralNumericExpression(start, kind, fields));
+ break;
+ case BinKind::LiteralRegExpExpression:
+ MOZ_TRY_VAR(result, parseInterfaceLiteralRegExpExpression(start, kind, fields));
+ break;
+ case BinKind::LiteralStringExpression:
+ MOZ_TRY_VAR(result, parseInterfaceLiteralStringExpression(start, kind, fields));
+ break;
+ case BinKind::NewExpression:
+ MOZ_TRY_VAR(result, parseInterfaceNewExpression(start, kind, fields));
+ break;
+ case BinKind::NewTargetExpression:
+ MOZ_TRY_VAR(result, parseInterfaceNewTargetExpression(start, kind, fields));
+ break;
+ case BinKind::ObjectExpression:
+ MOZ_TRY_VAR(result, parseInterfaceObjectExpression(start, kind, fields));
+ break;
+ case BinKind::StaticMemberExpression:
+ MOZ_TRY_VAR(result, parseInterfaceStaticMemberExpression(start, kind, fields));
+ break;
+ case BinKind::TemplateExpression:
+ MOZ_TRY_VAR(result, parseInterfaceTemplateExpression(start, kind, fields));
+ break;
+ case BinKind::ThisExpression:
+ MOZ_TRY_VAR(result, parseInterfaceThisExpression(start, kind, fields));
+ break;
+ case BinKind::UnaryExpression:
+ MOZ_TRY_VAR(result, parseInterfaceUnaryExpression(start, kind, fields));
+ break;
+ case BinKind::UpdateExpression:
+ MOZ_TRY_VAR(result, parseInterfaceUpdateExpression(start, kind, fields));
+ break;
+ case BinKind::YieldExpression:
+ MOZ_TRY_VAR(result, parseInterfaceYieldExpression(start, kind, fields));
+ break;
+ case BinKind::YieldStarExpression:
+ MOZ_TRY_VAR(result, parseInterfaceYieldStarExpression(start, kind, fields));
+ break;
+ default:
+ return raiseInvalidKind("FunctionDeclarationOrClassDeclarationOrExpression", kind);
+ }
+ return result;
+}
+
+/*
+FunctionDeclarationOrClassDeclarationOrVariableDeclaration ::= ClassDeclaration
+ FunctionDeclaration
+ VariableDeclaration
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseFunctionDeclarationOrClassDeclarationOrVariableDeclaration()
+{
+ BinKind kind;
+ BinFields fields((cx_));
+ AutoTaggedTuple guard(*tokenizer_);
+ const auto start = tokenizer_->offset();
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+
+ MOZ_TRY_DECL(result, parseSumFunctionDeclarationOrClassDeclarationOrVariableDeclaration(start, kind, fields));
+
+ TRY(guard.done());
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseSumFunctionDeclarationOrClassDeclarationOrVariableDeclaration(const size_t start, const BinKind kind, const BinFields& fields)
+{
+ ParseNode* result;
+ switch(kind) {
+ case BinKind::ClassDeclaration:
+ MOZ_TRY_VAR(result, parseInterfaceClassDeclaration(start, kind, fields));
+ break;
+ case BinKind::FunctionDeclaration:
+ MOZ_TRY_VAR(result, parseInterfaceFunctionDeclaration(start, kind, fields));
+ break;
+ case BinKind::VariableDeclaration:
+ MOZ_TRY_VAR(result, parseInterfaceVariableDeclaration(start, kind, fields));
+ break;
+ default:
+ return raiseInvalidKind("FunctionDeclarationOrClassDeclarationOrVariableDeclaration", kind);
+ }
+ return result;
+}
+
+/*
+ImportDeclaration ::= Import
+ ImportNamespace
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseImportDeclaration()
+{
+ BinKind kind;
+ BinFields fields((cx_));
+ AutoTaggedTuple guard(*tokenizer_);
+ const auto start = tokenizer_->offset();
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+
+ MOZ_TRY_DECL(result, parseSumImportDeclaration(start, kind, fields));
+
+ TRY(guard.done());
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseSumImportDeclaration(const size_t start, const BinKind kind, const BinFields& fields)
+{
+ ParseNode* result;
+ switch(kind) {
+ case BinKind::Import:
+ MOZ_TRY_VAR(result, parseInterfaceImport(start, kind, fields));
+ break;
+ case BinKind::ImportNamespace:
+ MOZ_TRY_VAR(result, parseInterfaceImportNamespace(start, kind, fields));
+ break;
+ default:
+ return raiseInvalidKind("ImportDeclaration", kind);
+ }
+ return result;
+}
+
+/*
+ImportDeclarationOrExportDeclarationOrStatement ::= Block
+ BreakStatement
+ ClassDeclaration
+ ContinueStatement
+ DebuggerStatement
+ DoWhileStatement
+ EmptyStatement
+ Export
+ ExportAllFrom
+ ExportDefault
+ ExportFrom
+ ExportLocals
+ ExpressionStatement
+ ForInStatement
+ ForOfStatement
+ ForStatement
+ FunctionDeclaration
+ IfStatement
+ Import
+ ImportNamespace
+ LabelledStatement
+ ReturnStatement
+ SwitchStatement
+ SwitchStatementWithDefault
+ ThrowStatement
+ TryCatchStatement
+ TryFinallyStatement
+ VariableDeclaration
+ WhileStatement
+ WithStatement
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseImportDeclarationOrExportDeclarationOrStatement()
+{
+ BinKind kind;
+ BinFields fields((cx_));
+ AutoTaggedTuple guard(*tokenizer_);
+ const auto start = tokenizer_->offset();
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+
+ MOZ_TRY_DECL(result, parseSumImportDeclarationOrExportDeclarationOrStatement(start, kind, fields));
+
+ TRY(guard.done());
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseSumImportDeclarationOrExportDeclarationOrStatement(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::EmptyStatement:
+ MOZ_TRY_VAR(result, parseInterfaceEmptyStatement(start, kind, fields));
+ break;
+ case BinKind::Export:
+ MOZ_TRY_VAR(result, parseInterfaceExport(start, kind, fields));
+ break;
+ case BinKind::ExportAllFrom:
+ MOZ_TRY_VAR(result, parseInterfaceExportAllFrom(start, kind, fields));
+ break;
+ case BinKind::ExportDefault:
+ MOZ_TRY_VAR(result, parseInterfaceExportDefault(start, kind, fields));
+ break;
+ case BinKind::ExportFrom:
+ MOZ_TRY_VAR(result, parseInterfaceExportFrom(start, kind, fields));
+ break;
+ case BinKind::ExportLocals:
+ MOZ_TRY_VAR(result, parseInterfaceExportLocals(start, kind, fields));
+ break;
+ case BinKind::ExpressionStatement:
+ MOZ_TRY_VAR(result, parseInterfaceExpressionStatement(start, kind, fields));
+ break;
+ case BinKind::ForInStatement:
+ MOZ_TRY_VAR(result, parseInterfaceForInStatement(start, kind, fields));
+ break;
+ case BinKind::ForOfStatement:
+ MOZ_TRY_VAR(result, parseInterfaceForOfStatement(start, kind, fields));
+ break;
+ case BinKind::ForStatement:
+ MOZ_TRY_VAR(result, parseInterfaceForStatement(start, kind, fields));
+ break;
+ case BinKind::FunctionDeclaration:
+ MOZ_TRY_VAR(result, parseInterfaceFunctionDeclaration(start, kind, fields));
+ break;
+ case BinKind::IfStatement:
+ MOZ_TRY_VAR(result, parseInterfaceIfStatement(start, kind, fields));
+ break;
+ case BinKind::Import:
+ MOZ_TRY_VAR(result, parseInterfaceImport(start, kind, fields));
+ break;
+ case BinKind::ImportNamespace:
+ MOZ_TRY_VAR(result, parseInterfaceImportNamespace(start, kind, fields));
+ break;
+ case BinKind::LabelledStatement:
+ MOZ_TRY_VAR(result, parseInterfaceLabelledStatement(start, kind, fields));
+ break;
+ case BinKind::ReturnStatement:
+ MOZ_TRY_VAR(result, parseInterfaceReturnStatement(start, kind, fields));
+ break;
+ case BinKind::SwitchStatement:
+ MOZ_TRY_VAR(result, parseInterfaceSwitchStatement(start, kind, fields));
+ break;
+ case BinKind::SwitchStatementWithDefault:
+ MOZ_TRY_VAR(result, parseInterfaceSwitchStatementWithDefault(start, kind, fields));
+ break;
+ case BinKind::ThrowStatement:
+ MOZ_TRY_VAR(result, parseInterfaceThrowStatement(start, kind, fields));
+ break;
+ case BinKind::TryCatchStatement:
+ MOZ_TRY_VAR(result, parseInterfaceTryCatchStatement(start, kind, fields));
+ break;
+ case BinKind::TryFinallyStatement:
+ MOZ_TRY_VAR(result, parseInterfaceTryFinallyStatement(start, kind, fields));
+ break;
+ case BinKind::VariableDeclaration:
+ MOZ_TRY_VAR(result, parseInterfaceVariableDeclaration(start, kind, fields));
+ break;
+ case BinKind::WhileStatement:
+ MOZ_TRY_VAR(result, parseInterfaceWhileStatement(start, kind, fields));
+ break;
+ case BinKind::WithStatement:
+ MOZ_TRY_VAR(result, parseInterfaceWithStatement(start, kind, fields));
+ break;
+ default:
+ return raiseInvalidKind("ImportDeclarationOrExportDeclarationOrStatement", kind);
+ }
+ return result;
+}
+
+/*
+IterationStatement ::= DoWhileStatement
+ ForInStatement
+ ForOfStatement
+ ForStatement
+ WhileStatement
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseIterationStatement()
+{
+ BinKind kind;
+ BinFields fields((cx_));
+ AutoTaggedTuple guard(*tokenizer_);
+ const auto start = tokenizer_->offset();
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+
+ MOZ_TRY_DECL(result, parseSumIterationStatement(start, kind, fields));
+
+ TRY(guard.done());
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseSumIterationStatement(const size_t start, const BinKind kind, const BinFields& fields)
+{
+ ParseNode* result;
+ switch(kind) {
+ case BinKind::DoWhileStatement:
+ MOZ_TRY_VAR(result, parseInterfaceDoWhileStatement(start, kind, fields));
+ break;
+ case BinKind::ForInStatement:
+ MOZ_TRY_VAR(result, parseInterfaceForInStatement(start, kind, fields));
+ break;
+ case BinKind::ForOfStatement:
+ MOZ_TRY_VAR(result, parseInterfaceForOfStatement(start, kind, fields));
+ break;
+ case BinKind::ForStatement:
+ MOZ_TRY_VAR(result, parseInterfaceForStatement(start, kind, fields));
+ break;
+ case BinKind::WhileStatement:
+ MOZ_TRY_VAR(result, parseInterfaceWhileStatement(start, kind, fields));
+ break;
+ default:
+ return raiseInvalidKind("IterationStatement", kind);
+ }
+ return result;
+}
+
+/*
+Literal ::= LiteralBooleanExpression
+ LiteralInfinityExpression
+ LiteralNullExpression
+ LiteralNumericExpression
+ LiteralStringExpression
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseLiteral()
+{
+ BinKind kind;
+ BinFields fields((cx_));
+ AutoTaggedTuple guard(*tokenizer_);
+ const auto start = tokenizer_->offset();
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+
+ MOZ_TRY_DECL(result, parseSumLiteral(start, kind, fields));
+
+ TRY(guard.done());
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseSumLiteral(const size_t start, const BinKind kind, const BinFields& fields)
+{
+ ParseNode* result;
+ switch(kind) {
+ case BinKind::LiteralBooleanExpression:
+ MOZ_TRY_VAR(result, parseInterfaceLiteralBooleanExpression(start, kind, fields));
+ break;
+ case BinKind::LiteralInfinityExpression:
+ MOZ_TRY_VAR(result, parseInterfaceLiteralInfinityExpression(start, kind, fields));
+ break;
+ case BinKind::LiteralNullExpression:
+ MOZ_TRY_VAR(result, parseInterfaceLiteralNullExpression(start, kind, fields));
+ break;
+ case BinKind::LiteralNumericExpression:
+ MOZ_TRY_VAR(result, parseInterfaceLiteralNumericExpression(start, kind, fields));
+ break;
+ case BinKind::LiteralStringExpression:
+ MOZ_TRY_VAR(result, parseInterfaceLiteralStringExpression(start, kind, fields));
+ break;
+ default:
+ return raiseInvalidKind("Literal", kind);
+ }
+ return result;
+}
+
+/*
+MethodDefinition ::= Getter
+ Method
+ Setter
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseMethodDefinition()
+{
+ BinKind kind;
+ BinFields fields((cx_));
+ AutoTaggedTuple guard(*tokenizer_);
+ const auto start = tokenizer_->offset();
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+
+ MOZ_TRY_DECL(result, parseSumMethodDefinition(start, kind, fields));
+
+ TRY(guard.done());
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseSumMethodDefinition(const size_t start, const BinKind kind, const BinFields& fields)
+{
+ ParseNode* result;
+ switch(kind) {
+ case BinKind::Getter:
+ MOZ_TRY_VAR(result, parseInterfaceGetter(start, kind, fields));
+ break;
+ case BinKind::Method:
+ MOZ_TRY_VAR(result, parseInterfaceMethod(start, kind, fields));
+ break;
+ case BinKind::Setter:
+ MOZ_TRY_VAR(result, parseInterfaceSetter(start, kind, fields));
+ break;
+ default:
+ return raiseInvalidKind("MethodDefinition", kind);
+ }
+ return result;
+}
+
+/*
+ObjectProperty ::= DataProperty
+ Getter
+ Method
+ Setter
+ ShorthandProperty
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseObjectProperty()
+{
+ BinKind kind;
+ BinFields fields((cx_));
+ AutoTaggedTuple guard(*tokenizer_);
+ const auto start = tokenizer_->offset();
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+
+ MOZ_TRY_DECL(result, parseSumObjectProperty(start, kind, fields));
+
+ TRY(guard.done());
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::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::Getter:
+ MOZ_TRY_VAR(result, parseInterfaceGetter(start, kind, fields));
+ break;
+ case BinKind::Method:
+ MOZ_TRY_VAR(result, parseInterfaceMethod(start, kind, fields));
+ break;
+ case BinKind::Setter:
+ MOZ_TRY_VAR(result, parseInterfaceSetter(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
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseParameter()
+{
+ BinKind kind;
+ BinFields fields((cx_));
+ AutoTaggedTuple guard(*tokenizer_);
+ const auto start = tokenizer_->offset();
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+
+ MOZ_TRY_DECL(result, parseSumParameter(start, kind, fields));
+
+ TRY(guard.done());
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::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));
+ 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
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseProgram()
+{
+ BinKind kind;
+ BinFields fields((cx_));
+ AutoTaggedTuple guard(*tokenizer_);
+ const auto start = tokenizer_->offset();
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+
+ MOZ_TRY_DECL(result, parseSumProgram(start, kind, fields));
+
+ TRY(guard.done());
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::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
+*/
+JS::Result<ParseNode*>
+BinASTParser::parsePropertyName()
+{
+ BinKind kind;
+ BinFields fields((cx_));
+ AutoTaggedTuple guard(*tokenizer_);
+ const auto start = tokenizer_->offset();
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+
+ MOZ_TRY_DECL(result, parseSumPropertyName(start, kind, fields));
+
+ TRY(guard.done());
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::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
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseSimpleAssignmentTarget()
+{
+ BinKind kind;
+ BinFields fields((cx_));
+ AutoTaggedTuple guard(*tokenizer_);
+ const auto start = tokenizer_->offset();
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+
+ MOZ_TRY_DECL(result, parseSumSimpleAssignmentTarget(start, kind, fields));
+
+ TRY(guard.done());
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::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
+ ArrowExpression
+ AssignmentExpression
+ AwaitExpression
+ BinaryExpression
+ CallExpression
+ ClassExpression
+ CompoundAssignmentExpression
+ ComputedMemberExpression
+ ConditionalExpression
+ FunctionExpression
+ IdentifierExpression
+ LiteralBooleanExpression
+ LiteralInfinityExpression
+ LiteralNullExpression
+ LiteralNumericExpression
+ LiteralRegExpExpression
+ LiteralStringExpression
+ NewExpression
+ NewTargetExpression
+ ObjectExpression
+ SpreadElement
+ StaticMemberExpression
+ TemplateExpression
+ ThisExpression
+ UnaryExpression
+ UpdateExpression
+ YieldExpression
+ YieldStarExpression
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseSpreadElementOrExpression()
+{
+ BinKind kind;
+ BinFields fields((cx_));
+ AutoTaggedTuple guard(*tokenizer_);
+ const auto start = tokenizer_->offset();
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+
+ MOZ_TRY_DECL(result, parseSumSpreadElementOrExpression(start, kind, fields));
+
+ TRY(guard.done());
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::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::ArrowExpression:
+ MOZ_TRY_VAR(result, parseInterfaceArrowExpression(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::FunctionExpression:
+ MOZ_TRY_VAR(result, parseInterfaceFunctionExpression(start, kind, fields));
+ break;
+ case BinKind::IdentifierExpression:
+ MOZ_TRY_VAR(result, parseInterfaceIdentifierExpression(start, kind, fields));
+ break;
+ case BinKind::LiteralBooleanExpression:
+ MOZ_TRY_VAR(result, parseInterfaceLiteralBooleanExpression(start, kind, fields));
+ break;
+ case BinKind::LiteralInfinityExpression:
+ MOZ_TRY_VAR(result, parseInterfaceLiteralInfinityExpression(start, kind, fields));
+ break;
+ case BinKind::LiteralNullExpression:
+ MOZ_TRY_VAR(result, parseInterfaceLiteralNullExpression(start, kind, fields));
+ break;
+ case BinKind::LiteralNumericExpression:
+ MOZ_TRY_VAR(result, parseInterfaceLiteralNumericExpression(start, kind, fields));
+ break;
+ case BinKind::LiteralRegExpExpression:
+ MOZ_TRY_VAR(result, parseInterfaceLiteralRegExpExpression(start, kind, fields));
+ break;
+ case BinKind::LiteralStringExpression:
+ MOZ_TRY_VAR(result, parseInterfaceLiteralStringExpression(start, kind, fields));
+ break;
+ case BinKind::NewExpression:
+ MOZ_TRY_VAR(result, parseInterfaceNewExpression(start, kind, fields));
+ break;
+ case BinKind::NewTargetExpression:
+ MOZ_TRY_VAR(result, parseInterfaceNewTargetExpression(start, kind, fields));
+ break;
+ case BinKind::ObjectExpression:
+ MOZ_TRY_VAR(result, parseInterfaceObjectExpression(start, kind, fields));
+ break;
+ case BinKind::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
+ EmptyStatement
+ ExpressionStatement
+ ForInStatement
+ ForOfStatement
+ ForStatement
+ FunctionDeclaration
+ IfStatement
+ LabelledStatement
+ ReturnStatement
+ SwitchStatement
+ SwitchStatementWithDefault
+ ThrowStatement
+ TryCatchStatement
+ TryFinallyStatement
+ VariableDeclaration
+ WhileStatement
+ WithStatement
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseStatement()
+{
+ BinKind kind;
+ BinFields fields((cx_));
+ AutoTaggedTuple guard(*tokenizer_);
+ const auto start = tokenizer_->offset();
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+
+ MOZ_TRY_DECL(result, parseSumStatement(start, kind, fields));
+
+ TRY(guard.done());
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::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::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::FunctionDeclaration:
+ MOZ_TRY_VAR(result, parseInterfaceFunctionDeclaration(start, kind, fields));
+ break;
+ case BinKind::IfStatement:
+ MOZ_TRY_VAR(result, parseInterfaceIfStatement(start, kind, fields));
+ break;
+ case BinKind::LabelledStatement:
+ MOZ_TRY_VAR(result, parseInterfaceLabelledStatement(start, kind, fields));
+ break;
+ case BinKind::ReturnStatement:
+ MOZ_TRY_VAR(result, parseInterfaceReturnStatement(start, kind, fields));
+ break;
+ case BinKind::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;
+}
+
+/*
+VariableDeclarationOrExpression ::= ArrayExpression
+ ArrowExpression
+ AssignmentExpression
+ AwaitExpression
+ BinaryExpression
+ CallExpression
+ ClassExpression
+ CompoundAssignmentExpression
+ ComputedMemberExpression
+ ConditionalExpression
+ FunctionExpression
+ IdentifierExpression
+ LiteralBooleanExpression
+ LiteralInfinityExpression
+ LiteralNullExpression
+ LiteralNumericExpression
+ LiteralRegExpExpression
+ LiteralStringExpression
+ NewExpression
+ NewTargetExpression
+ ObjectExpression
+ StaticMemberExpression
+ TemplateExpression
+ ThisExpression
+ UnaryExpression
+ UpdateExpression
+ VariableDeclaration
+ YieldExpression
+ YieldStarExpression
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseVariableDeclarationOrExpression()
+{
+ BinKind kind;
+ BinFields fields((cx_));
+ AutoTaggedTuple guard(*tokenizer_);
+ const auto start = tokenizer_->offset();
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+
+ MOZ_TRY_DECL(result, parseSumVariableDeclarationOrExpression(start, kind, fields));
+
+ TRY(guard.done());
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::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::ArrowExpression:
+ MOZ_TRY_VAR(result, parseInterfaceArrowExpression(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::FunctionExpression:
+ MOZ_TRY_VAR(result, parseInterfaceFunctionExpression(start, kind, fields));
+ break;
+ case BinKind::IdentifierExpression:
+ MOZ_TRY_VAR(result, parseInterfaceIdentifierExpression(start, kind, fields));
+ break;
+ case BinKind::LiteralBooleanExpression:
+ MOZ_TRY_VAR(result, parseInterfaceLiteralBooleanExpression(start, kind, fields));
+ break;
+ case BinKind::LiteralInfinityExpression:
+ MOZ_TRY_VAR(result, parseInterfaceLiteralInfinityExpression(start, kind, fields));
+ break;
+ case BinKind::LiteralNullExpression:
+ MOZ_TRY_VAR(result, parseInterfaceLiteralNullExpression(start, kind, fields));
+ break;
+ case BinKind::LiteralNumericExpression:
+ MOZ_TRY_VAR(result, parseInterfaceLiteralNumericExpression(start, kind, fields));
+ break;
+ case BinKind::LiteralRegExpExpression:
+ MOZ_TRY_VAR(result, parseInterfaceLiteralRegExpExpression(start, kind, fields));
+ break;
+ case BinKind::LiteralStringExpression:
+ MOZ_TRY_VAR(result, parseInterfaceLiteralStringExpression(start, kind, fields));
+ break;
+ case BinKind::NewExpression:
+ MOZ_TRY_VAR(result, parseInterfaceNewExpression(start, kind, fields));
+ break;
+ case BinKind::NewTargetExpression:
+ MOZ_TRY_VAR(result, parseInterfaceNewTargetExpression(start, kind, fields));
+ break;
+ case BinKind::ObjectExpression:
+ MOZ_TRY_VAR(result, parseInterfaceObjectExpression(start, kind, fields));
+ break;
+ case BinKind::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.
+
+/*
+ interface ArrayAssignmentTarget : Node {
+ FrozenArray<(AssignmentTarget or AssignmentTargetWithInitializer)> elements;
+ AssignmentTarget? rest;
+ }
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseArrayAssignmentTarget()
+{
+ BinKind kind;
+ BinFields fields(cx_);
+ AutoTaggedTuple guard(*tokenizer_);
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+ const auto start = tokenizer_->offset();
+
+ MOZ_TRY_DECL(result, parseInterfaceArrayAssignmentTarget(start, kind, fields));
+ TRY(guard.done());
+
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseInterfaceArrayAssignmentTarget(const size_t start, const BinKind kind, const BinFields& fields)
+{
+ return raiseError("FIXME: Not implemented yet (ArrayAssignmentTarget)");
+}
+
+
+/*
+ interface ArrayBinding : Node {
+ FrozenArray<(Binding or BindingWithInitializer)?> elements;
+ Binding? rest;
+ }
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseArrayBinding()
+{
+ BinKind kind;
+ BinFields fields(cx_);
+ AutoTaggedTuple guard(*tokenizer_);
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+ const auto start = tokenizer_->offset();
+
+ MOZ_TRY_DECL(result, parseInterfaceArrayBinding(start, kind, fields));
+ TRY(guard.done());
+
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseInterfaceArrayBinding(const size_t start, const BinKind kind, const BinFields& fields)
+{
+ return raiseError("FIXME: Not implemented yet (ArrayBinding)");
+}
+
+
+/*
+ interface ArrayExpression : Node {
+ FrozenArray<(SpreadElement or Expression)?> elements;
+ }
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseArrayExpression()
+{
+ BinKind kind;
+ BinFields fields(cx_);
+ AutoTaggedTuple guard(*tokenizer_);
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+ const auto start = tokenizer_->offset();
+
+ MOZ_TRY_DECL(result, parseInterfaceArrayExpression(start, kind, fields));
+ TRY(guard.done());
+
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseInterfaceArrayExpression(const size_t start, const BinKind kind, const BinFields& fields)
+{
+ MOZ_ASSERT(kind == BinKind::ArrayExpression);
+ MOZ_TRY(checkFields(kind, fields, { BinField::Elements }));
+
+
+ MOZ_TRY_DECL(elements, parseListOfOptionalSpreadElementOrExpression());
+
+ auto result = elements;return result;
+}
+
+
+/*
+ interface ArrowExpression : Node {
+ bool isAsync;
+ AssertedParameterScope? parameterScope;
+ AssertedVarScope? bodyScope;
+ FormalParameters params;
+ (FunctionBody or Expression) body;
+ }
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseArrowExpression()
+{
+ BinKind kind;
+ BinFields fields(cx_);
+ AutoTaggedTuple guard(*tokenizer_);
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+ const auto start = tokenizer_->offset();
+
+ MOZ_TRY_DECL(result, parseInterfaceArrowExpression(start, kind, fields));
+ TRY(guard.done());
+
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseInterfaceArrowExpression(const size_t start, const BinKind kind, const BinFields& fields)
+{
+ return raiseError("FIXME: Not implemented yet (ArrowExpression)");
+}
+
+
+/*
+ interface AssertedBlockScope : Node {
+ FrozenArray<IdentifierName> lexicallyDeclaredNames;
+ FrozenArray<IdentifierName> capturedNames;
+ bool hasDirectEval;
+ }
+*/
+JS::Result<Ok>
+BinASTParser::parseAssertedBlockScope()
+{
+ BinKind kind;
+ BinFields fields(cx_);
+ AutoTaggedTuple guard(*tokenizer_);
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+ const auto start = tokenizer_->offset();
+
+ MOZ_TRY_DECL(result, parseInterfaceAssertedBlockScope(start, kind, fields));
+ TRY(guard.done());
+
+ return result;
+}
+
+JS::Result<Ok>
+BinASTParser::parseInterfaceAssertedBlockScope(const size_t start, const BinKind kind, const BinFields& fields)
+{
+ MOZ_ASSERT(kind == BinKind::AssertedBlockScope);
+ MOZ_TRY(checkFields(kind, fields, { BinField::LexicallyDeclaredNames, BinField::CapturedNames, BinField::HasDirectEval }));
+ MOZ_TRY(parseAndUpdateScopeNames(*parseContext_->innermostScope(), DeclarationKind::Let));
+ MOZ_TRY(parseAndUpdateCapturedNames());
+
+
+
+ MOZ_TRY_DECL(hasDirectEval, 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 AssertedParameterScope : Node {
+ FrozenArray<IdentifierName> parameterNames;
+ FrozenArray<IdentifierName> capturedNames;
+ bool hasDirectEval;
+ }
+*/
+JS::Result<Ok>
+BinASTParser::parseAssertedParameterScope()
+{
+ BinKind kind;
+ BinFields fields(cx_);
+ AutoTaggedTuple guard(*tokenizer_);
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+ const auto start = tokenizer_->offset();
+
+ MOZ_TRY_DECL(result, parseInterfaceAssertedParameterScope(start, kind, fields));
+ TRY(guard.done());
+
+ return result;
+}
+
+JS::Result<Ok>
+BinASTParser::parseInterfaceAssertedParameterScope(const size_t start, const BinKind kind, const BinFields& fields)
+{
+ MOZ_ASSERT(kind == BinKind::AssertedParameterScope);
+ MOZ_TRY(checkFields(kind, fields, { BinField::ParameterNames, BinField::CapturedNames, BinField::HasDirectEval }));
+ MOZ_TRY(parseAndUpdateScopeNames(parseContext_->functionScope(), DeclarationKind:: PositionalFormalParameter));
+ MOZ_TRY(parseAndUpdateCapturedNames());
+
+
+
+ MOZ_TRY_DECL(hasDirectEval, 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<IdentifierName> lexicallyDeclaredNames;
+ FrozenArray<IdentifierName> varDeclaredNames;
+ FrozenArray<IdentifierName> capturedNames;
+ bool hasDirectEval;
+ }
+*/
+JS::Result<Ok>
+BinASTParser::parseAssertedVarScope()
+{
+ BinKind kind;
+ BinFields fields(cx_);
+ AutoTaggedTuple guard(*tokenizer_);
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+ const auto start = tokenizer_->offset();
+
+ MOZ_TRY_DECL(result, parseInterfaceAssertedVarScope(start, kind, fields));
+ TRY(guard.done());
+
+ return result;
+}
+
+JS::Result<Ok>
+BinASTParser::parseInterfaceAssertedVarScope(const size_t start, const BinKind kind, const BinFields& fields)
+{
+ MOZ_ASSERT(kind == BinKind::AssertedVarScope);
+ MOZ_TRY(checkFields(kind, fields, { BinField::LexicallyDeclaredNames, BinField::VarDeclaredNames, BinField::CapturedNames, BinField::HasDirectEval }));
+ MOZ_TRY(parseAndUpdateScopeNames(*parseContext_->innermostScope(), DeclarationKind::Let));
+ MOZ_TRY(parseAndUpdateScopeNames(parseContext_->varScope(), DeclarationKind::Var));
+ MOZ_TRY(parseAndUpdateCapturedNames());
+
+
+
+ MOZ_TRY_DECL(hasDirectEval, 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 AssignmentExpression : Node {
+ AssignmentTarget binding;
+ Expression expression;
+ }
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseAssignmentExpression()
+{
+ BinKind kind;
+ BinFields fields(cx_);
+ AutoTaggedTuple guard(*tokenizer_);
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+ const auto start = tokenizer_->offset();
+
+ MOZ_TRY_DECL(result, parseInterfaceAssignmentExpression(start, kind, fields));
+ TRY(guard.done());
+
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseInterfaceAssignmentExpression(const size_t start, const BinKind kind, const BinFields& fields)
+{
+ MOZ_ASSERT(kind == BinKind::AssignmentExpression);
+ MOZ_TRY(checkFields(kind, fields, { BinField::Binding, BinField::Expression }));
+
+
+ MOZ_TRY_DECL(binding, parseAssignmentTarget());
+
+
+ MOZ_TRY_DECL(expression, parseExpression());
+
+ TRY_DECL(result, factory_.newAssignment(ParseNodeKind::Assign, binding, expression));return result;
+}
+
+
+/*
+ interface AssignmentTargetIdentifier : Node {
+ Identifier name;
+ }
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseAssignmentTargetIdentifier()
+{
+ BinKind kind;
+ BinFields fields(cx_);
+ AutoTaggedTuple guard(*tokenizer_);
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+ const auto start = tokenizer_->offset();
+
+ MOZ_TRY_DECL(result, parseInterfaceAssignmentTargetIdentifier(start, kind, fields));
+ TRY(guard.done());
+
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseInterfaceAssignmentTargetIdentifier(const size_t start, const BinKind kind, const BinFields& fields)
+{
+ MOZ_ASSERT(kind == BinKind::AssignmentTargetIdentifier);
+ MOZ_TRY(checkFields(kind, fields, { BinField::Name }));
+
+ RootedAtom name((cx_));
+ MOZ_TRY(readString(&name));
+
+ if (!IsIdentifier(name))
+ return raiseError("Invalid identifier");
+ TRY_DECL(result, factory_.newName(name->asPropertyName(), tokenizer_->pos(start), cx_));return result;
+}
+
+
+/*
+ interface AssignmentTargetPropertyIdentifier : Node {
+ AssignmentTargetIdentifier binding;
+ Expression? init;
+ }
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseAssignmentTargetPropertyIdentifier()
+{
+ BinKind kind;
+ BinFields fields(cx_);
+ AutoTaggedTuple guard(*tokenizer_);
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+ const auto start = tokenizer_->offset();
+
+ MOZ_TRY_DECL(result, parseInterfaceAssignmentTargetPropertyIdentifier(start, kind, fields));
+ TRY(guard.done());
+
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseInterfaceAssignmentTargetPropertyIdentifier(const size_t start, const BinKind kind, const BinFields& fields)
+{
+ return raiseError("FIXME: Not implemented yet (AssignmentTargetPropertyIdentifier)");
+}
+
+
+/*
+ interface AssignmentTargetPropertyProperty : Node {
+ PropertyName name;
+ (AssignmentTarget or AssignmentTargetWithInitializer) binding;
+ }
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseAssignmentTargetPropertyProperty()
+{
+ BinKind kind;
+ BinFields fields(cx_);
+ AutoTaggedTuple guard(*tokenizer_);
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+ const auto start = tokenizer_->offset();
+
+ MOZ_TRY_DECL(result, parseInterfaceAssignmentTargetPropertyProperty(start, kind, fields));
+ TRY(guard.done());
+
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseInterfaceAssignmentTargetPropertyProperty(const size_t start, const BinKind kind, const BinFields& fields)
+{
+ return raiseError("FIXME: Not implemented yet (AssignmentTargetPropertyProperty)");
+}
+
+
+/*
+ interface AssignmentTargetWithInitializer : Node {
+ AssignmentTarget binding;
+ Expression init;
+ }
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseAssignmentTargetWithInitializer()
+{
+ BinKind kind;
+ BinFields fields(cx_);
+ AutoTaggedTuple guard(*tokenizer_);
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+ const auto start = tokenizer_->offset();
+
+ MOZ_TRY_DECL(result, parseInterfaceAssignmentTargetWithInitializer(start, kind, fields));
+ TRY(guard.done());
+
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseInterfaceAssignmentTargetWithInitializer(const size_t start, const BinKind kind, const BinFields& fields)
+{
+ return raiseError("FIXME: Not implemented yet (AssignmentTargetWithInitializer)");
+}
+
+
+/*
+ interface AwaitExpression : Node {
+ Expression expression;
+ }
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseAwaitExpression()
+{
+ BinKind kind;
+ BinFields fields(cx_);
+ AutoTaggedTuple guard(*tokenizer_);
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+ const auto start = tokenizer_->offset();
+
+ MOZ_TRY_DECL(result, parseInterfaceAwaitExpression(start, kind, fields));
+ TRY(guard.done());
+
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseInterfaceAwaitExpression(const size_t start, const BinKind kind, const BinFields& fields)
+{
+ return raiseError("FIXME: Not implemented yet (AwaitExpression)");
+}
+
+
+/*
+ interface BinaryExpression : Node {
+ BinaryOperator operator;
+ Expression left;
+ Expression right;
+ }
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseBinaryExpression()
+{
+ BinKind kind;
+ BinFields fields(cx_);
+ AutoTaggedTuple guard(*tokenizer_);
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+ const auto start = tokenizer_->offset();
+
+ MOZ_TRY_DECL(result, parseInterfaceBinaryExpression(start, kind, fields));
+ TRY(guard.done());
+
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseInterfaceBinaryExpression(const size_t start, const BinKind kind, const BinFields& fields)
+{
+ MOZ_ASSERT(kind == BinKind::BinaryExpression);
+ MOZ_TRY(checkFields(kind, fields, { BinField::Operator, BinField::Left, BinField::Right }));
+
+
+ MOZ_TRY_DECL(operator_, parseBinaryOperator());
+
+
+ MOZ_TRY_DECL(left, parseExpression());
+
+
+ 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->appendWithoutOrderAssumption(right);
+ result = left;
+ } else {
+ TRY_DECL(list, factory_.newList(pnk, tokenizer_->pos(start)));
+
+ list->appendWithoutOrderAssumption(left);
+ list->appendWithoutOrderAssumption(right);
+ result = list;
+ }return result;
+}
+
+
+/*
+ interface BindingIdentifier : Node {
+ Identifier name;
+ }
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseBindingIdentifier()
+{
+ BinKind kind;
+ BinFields fields(cx_);
+ AutoTaggedTuple guard(*tokenizer_);
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+ const auto start = tokenizer_->offset();
+
+ MOZ_TRY_DECL(result, parseInterfaceBindingIdentifier(start, kind, fields));
+ TRY(guard.done());
+
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseInterfaceBindingIdentifier(const size_t start, const BinKind kind, const BinFields& fields)
+{
+ MOZ_ASSERT(kind == BinKind::BindingIdentifier);
+ MOZ_TRY(checkFields(kind, fields, { BinField::Name }));
+
+ RootedAtom name((cx_));
+ MOZ_TRY(readString(&name));
+
+ if (!IsIdentifier(name))
+ return raiseError("Invalid identifier");
+ TRY_DECL(result, factory_.newName(name->asPropertyName(), tokenizer_->pos(start), cx_));return result;
+}
+
+
+/*
+ interface BindingPropertyIdentifier : Node {
+ BindingIdentifier binding;
+ Expression? init;
+ }
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseBindingPropertyIdentifier()
+{
+ BinKind kind;
+ BinFields fields(cx_);
+ AutoTaggedTuple guard(*tokenizer_);
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+ const auto start = tokenizer_->offset();
+
+ MOZ_TRY_DECL(result, parseInterfaceBindingPropertyIdentifier(start, kind, fields));
+ TRY(guard.done());
+
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseInterfaceBindingPropertyIdentifier(const size_t start, const BinKind kind, const BinFields& fields)
+{
+ return raiseError("FIXME: Not implemented yet (BindingPropertyIdentifier)");
+}
+
+
+/*
+ interface BindingPropertyProperty : Node {
+ PropertyName name;
+ (Binding or BindingWithInitializer) binding;
+ }
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseBindingPropertyProperty()
+{
+ BinKind kind;
+ BinFields fields(cx_);
+ AutoTaggedTuple guard(*tokenizer_);
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+ const auto start = tokenizer_->offset();
+
+ MOZ_TRY_DECL(result, parseInterfaceBindingPropertyProperty(start, kind, fields));
+ TRY(guard.done());
+
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseInterfaceBindingPropertyProperty(const size_t start, const BinKind kind, const BinFields& fields)
+{
+ return raiseError("FIXME: Not implemented yet (BindingPropertyProperty)");
+}
+
+
+/*
+ interface BindingWithInitializer : Node {
+ Binding binding;
+ Expression init;
+ }
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseBindingWithInitializer()
+{
+ BinKind kind;
+ BinFields fields(cx_);
+ AutoTaggedTuple guard(*tokenizer_);
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+ const auto start = tokenizer_->offset();
+
+ MOZ_TRY_DECL(result, parseInterfaceBindingWithInitializer(start, kind, fields));
+ TRY(guard.done());
+
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseInterfaceBindingWithInitializer(const size_t start, const BinKind kind, const BinFields& fields)
+{
+ return raiseError("FIXME: Not implemented yet (BindingWithInitializer)");
+}
+
+
+/*
+ interface Block : Node {
+ AssertedBlockScope? scope;
+ FrozenArray<Statement> statements;
+ }
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseBlock()
+{
+ BinKind kind;
+ BinFields fields(cx_);
+ AutoTaggedTuple guard(*tokenizer_);
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+ const auto start = tokenizer_->offset();
+
+ MOZ_TRY_DECL(result, parseInterfaceBlock(start, kind, fields));
+ TRY(guard.done());
+
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseInterfaceBlock(const size_t start, const BinKind kind, const BinFields& fields)
+{
+ MOZ_ASSERT(kind == BinKind::Block);
+ MOZ_TRY(checkFields(kind, fields, { BinField::Scope, BinField::Statements }));
+ fprintf(stderr, "Block: PUSH parse context\n");
+ ParseContext::Statement stmt(parseContext_, StatementKind::Block);
+ ParseContext::Scope currentScope(cx_, parseContext_, usedNames_);
+ TRY(currentScope.init(parseContext_));
+
+ MOZ_TRY(parseOptionalAssertedBlockScope());
+
+
+ MOZ_TRY_DECL(statements, parseListOfStatement());
+
+ TRY_DECL(bindings, NewLexicalScopeData(cx_, currentScope, alloc_, parseContext_));
+ TRY_DECL(result, factory_.newLexicalScope(*bindings, statements));
+ fprintf(stderr, "Block: POP parse context\n");return result;
+}
+
+
+/*
+ interface BreakStatement : Node {
+ Label? label;
+ }
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseBreakStatement()
+{
+ BinKind kind;
+ BinFields fields(cx_);
+ AutoTaggedTuple guard(*tokenizer_);
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+ const auto start = tokenizer_->offset();
+
+ MOZ_TRY_DECL(result, parseInterfaceBreakStatement(start, kind, fields));
+ TRY(guard.done());
+
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseInterfaceBreakStatement(const size_t start, const BinKind kind, const BinFields& fields)
+{
+ MOZ_ASSERT(kind == BinKind::BreakStatement);
+ MOZ_TRY(checkFields(kind, fields, { BinField::Label }));
+ RootedAtom label(cx_);
+ MOZ_TRY(readMaybeString(&label));
+
+ if (label && !IsIdentifier(label))
+ return raiseError("Invalid identifier");
+
+ if (label) {
+ 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");
+ }
+ }
+ }
+ TRY_DECL(result, factory_.newBreakStatement(label ? label->asPropertyName() : nullptr, tokenizer_->pos(start)));return result;
+}
+
+
+/*
+ interface CallExpression : Node {
+ (Expression or Super) callee;
+ Arguments arguments;
+ }
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseCallExpression()
+{
+ BinKind kind;
+ BinFields fields(cx_);
+ AutoTaggedTuple guard(*tokenizer_);
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+ const auto start = tokenizer_->offset();
+
+ MOZ_TRY_DECL(result, parseInterfaceCallExpression(start, kind, fields));
+ TRY(guard.done());
+
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseInterfaceCallExpression(const size_t start, const BinKind kind, const BinFields& fields)
+{
+ MOZ_ASSERT(kind == BinKind::CallExpression);
+ MOZ_TRY(checkFields(kind, fields, { BinField::Callee, BinField::Arguments }));
+
+
+ MOZ_TRY_DECL(callee, parseExpressionOrSuper());
+
+
+ MOZ_TRY_DECL(arguments, parseArguments());
+
+ auto op = JSOP_CALL;
+ // Check for direct calls to `eval`.
+ if (factory_.isEvalName(callee, cx_)) {
+ if (!parseContext_->varScope().lookupDeclaredNameForAdd(callee->name())
+ && !parseContext_->innermostScope()->lookupDeclaredNameForAdd(callee->name())) {
+ // This is a direct call to `eval`.
+ if (!parseContext_->sc()->hasDirectEval())
+ return raiseMissingDirectEvalInAssertedScope();
+
+ op = parseContext_->sc()->strict() ? JSOP_STRICTEVAL : JSOP_EVAL;
+ }
+ }
+ auto result = arguments;
+ result->setKind(ParseNodeKind::Call);
+ result->prepend(callee);
+ result->setOp(op);return result;
+}
+
+
+/*
+ interface CatchClause : Node {
+ Binding binding;
+ Block body;
+ }
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseCatchClause()
+{
+ BinKind kind;
+ BinFields fields(cx_);
+ AutoTaggedTuple guard(*tokenizer_);
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+ const auto start = tokenizer_->offset();
+
+ MOZ_TRY_DECL(result, parseInterfaceCatchClause(start, kind, fields));
+ TRY(guard.done());
+
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseInterfaceCatchClause(const size_t start, const BinKind kind, const BinFields& fields)
+{
+ MOZ_ASSERT(kind == BinKind::CatchClause);
+ MOZ_TRY(checkFields(kind, fields, { BinField::Binding, BinField::Body }));
+ ParseContext::Statement stmt(parseContext_, StatementKind::Catch);
+ ParseContext::Scope currentScope(cx_, parseContext_, usedNames_);
+ TRY(currentScope.init(parseContext_));
+
+ MOZ_TRY_DECL(binding, parseBinding());
+
+
+ MOZ_TRY_DECL(body, parseBlock());
+
+ // Export implicit variables to the scope.
+ // FIXME: Handle cases other than Name.
+ MOZ_ASSERT(binding->isKind(ParseNodeKind::Name));
+ auto ptr = currentScope.lookupDeclaredNameForAdd(binding->name());
+ TRY(currentScope.addDeclaredName(parseContext_, ptr, binding->name(), DeclarationKind::Let, start));
+
+ TRY_DECL(bindings, NewLexicalScopeData(cx_, currentScope, alloc_, parseContext_));
+ TRY_DECL(result, factory_.newLexicalScope(*bindings, body));
+ TRY(factory_.setupCatchScope(result, binding, body));return result;
+}
+
+
+/*
+ interface ClassDeclaration : Node {
+ BindingIdentifier name;
+ Expression? super;
+ FrozenArray<ClassElement> elements;
+ }
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseClassDeclaration()
+{
+ BinKind kind;
+ BinFields fields(cx_);
+ AutoTaggedTuple guard(*tokenizer_);
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+ const auto start = tokenizer_->offset();
+
+ MOZ_TRY_DECL(result, parseInterfaceClassDeclaration(start, kind, fields));
+ TRY(guard.done());
+
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseInterfaceClassDeclaration(const size_t start, const BinKind kind, const BinFields& fields)
+{
+ return raiseError("FIXME: Not implemented yet (ClassDeclaration)");
+}
+
+
+/*
+ interface ClassElement : Node {
+ bool isStatic;
+ MethodDefinition method;
+ }
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseClassElement()
+{
+ BinKind kind;
+ BinFields fields(cx_);
+ AutoTaggedTuple guard(*tokenizer_);
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+ const auto start = tokenizer_->offset();
+
+ MOZ_TRY_DECL(result, parseInterfaceClassElement(start, kind, fields));
+ TRY(guard.done());
+
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseInterfaceClassElement(const size_t start, const BinKind kind, const BinFields& fields)
+{
+ return raiseError("FIXME: Not implemented yet (ClassElement)");
+}
+
+
+/*
+ interface ClassExpression : Node {
+ BindingIdentifier? name;
+ Expression? super;
+ FrozenArray<ClassElement> elements;
+ }
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseClassExpression()
+{
+ BinKind kind;
+ BinFields fields(cx_);
+ AutoTaggedTuple guard(*tokenizer_);
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+ const auto start = tokenizer_->offset();
+
+ MOZ_TRY_DECL(result, parseInterfaceClassExpression(start, kind, fields));
+ TRY(guard.done());
+
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseInterfaceClassExpression(const size_t start, const BinKind kind, const BinFields& fields)
+{
+ return raiseError("FIXME: Not implemented yet (ClassExpression)");
+}
+
+
+/*
+ interface CompoundAssignmentExpression : Node {
+ CompoundAssignmentOperator operator;
+ SimpleAssignmentTarget binding;
+ Expression expression;
+ }
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseCompoundAssignmentExpression()
+{
+ BinKind kind;
+ BinFields fields(cx_);
+ AutoTaggedTuple guard(*tokenizer_);
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+ const auto start = tokenizer_->offset();
+
+ MOZ_TRY_DECL(result, parseInterfaceCompoundAssignmentExpression(start, kind, fields));
+ TRY(guard.done());
+
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseInterfaceCompoundAssignmentExpression(const size_t start, const BinKind kind, const BinFields& fields)
+{
+ MOZ_ASSERT(kind == BinKind::CompoundAssignmentExpression);
+ MOZ_TRY(checkFields(kind, fields, { BinField::Operator, BinField::Binding, BinField::Expression }));
+
+
+ MOZ_TRY_DECL(operator_, parseCompoundAssignmentOperator());
+
+
+ MOZ_TRY_DECL(binding, parseSimpleAssignmentTarget());
+
+
+ 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;
+ }
+ TRY_DECL(result, factory_.newAssignment(pnk, binding, expression));return result;
+}
+
+
+/*
+ interface ComputedMemberAssignmentTarget : Node {
+ (Expression or Super) object;
+ Expression expression;
+ }
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseComputedMemberAssignmentTarget()
+{
+ BinKind kind;
+ BinFields fields(cx_);
+ AutoTaggedTuple guard(*tokenizer_);
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+ const auto start = tokenizer_->offset();
+
+ MOZ_TRY_DECL(result, parseInterfaceComputedMemberAssignmentTarget(start, kind, fields));
+ TRY(guard.done());
+
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseInterfaceComputedMemberAssignmentTarget(const size_t start, const BinKind kind, const BinFields& fields)
+{
+ MOZ_ASSERT(kind == BinKind::ComputedMemberAssignmentTarget);
+ MOZ_TRY(checkFields(kind, fields, { BinField::Object, BinField::Expression }));
+
+
+ MOZ_TRY_DECL(object, parseExpressionOrSuper());
+
+
+ MOZ_TRY_DECL(expression, parseExpression());
+
+ TRY_DECL(result, factory_.newPropertyByValue(object, expression, start));return result;
+}
+
+
+/*
+ interface ComputedMemberExpression : Node {
+ (Expression or Super) object;
+ Expression expression;
+ }
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseComputedMemberExpression()
+{
+ BinKind kind;
+ BinFields fields(cx_);
+ AutoTaggedTuple guard(*tokenizer_);
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+ const auto start = tokenizer_->offset();
+
+ MOZ_TRY_DECL(result, parseInterfaceComputedMemberExpression(start, kind, fields));
+ TRY(guard.done());
+
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseInterfaceComputedMemberExpression(const size_t start, const BinKind kind, const BinFields& fields)
+{
+ MOZ_ASSERT(kind == BinKind::ComputedMemberExpression);
+ MOZ_TRY(checkFields(kind, fields, { BinField::Object, BinField::Expression }));
+
+
+ MOZ_TRY_DECL(object, parseExpressionOrSuper());
+
+
+ MOZ_TRY_DECL(expression, parseExpression());
+
+ TRY_DECL(result, factory_.newPropertyByValue(object, expression, start));return result;
+}
+
+
+/*
+ interface ComputedPropertyName : Node {
+ Expression expression;
+ }
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseComputedPropertyName()
+{
+ BinKind kind;
+ BinFields fields(cx_);
+ AutoTaggedTuple guard(*tokenizer_);
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+ const auto start = tokenizer_->offset();
+
+ MOZ_TRY_DECL(result, parseInterfaceComputedPropertyName(start, kind, fields));
+ TRY(guard.done());
+
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseInterfaceComputedPropertyName(const size_t start, const BinKind kind, const BinFields& fields)
+{
+ return raiseError("FIXME: Not implemented yet (ComputedPropertyName)");
+}
+
+
+/*
+ interface ConditionalExpression : Node {
+ Expression test;
+ Expression consequent;
+ Expression alternate;
+ }
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseConditionalExpression()
+{
+ BinKind kind;
+ BinFields fields(cx_);
+ AutoTaggedTuple guard(*tokenizer_);
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+ const auto start = tokenizer_->offset();
+
+ MOZ_TRY_DECL(result, parseInterfaceConditionalExpression(start, kind, fields));
+ TRY(guard.done());
+
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseInterfaceConditionalExpression(const size_t start, const BinKind kind, const BinFields& fields)
+{
+ MOZ_ASSERT(kind == BinKind::ConditionalExpression);
+ MOZ_TRY(checkFields(kind, fields, { BinField::Test, BinField::Consequent, BinField::Alternate }));
+
+
+ MOZ_TRY_DECL(test, parseExpression());
+
+
+ MOZ_TRY_DECL(consequent, parseExpression());
+
+
+ MOZ_TRY_DECL(alternate, parseExpression());
+
+ TRY_DECL(result, factory_.newConditional(test, consequent, alternate));return result;
+}
+
+
+/*
+ interface ContinueStatement : Node {
+ Label? label;
+ }
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseContinueStatement()
+{
+ BinKind kind;
+ BinFields fields(cx_);
+ AutoTaggedTuple guard(*tokenizer_);
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+ const auto start = tokenizer_->offset();
+
+ MOZ_TRY_DECL(result, parseInterfaceContinueStatement(start, kind, fields));
+ TRY(guard.done());
+
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseInterfaceContinueStatement(const size_t start, const BinKind kind, const BinFields& fields)
+{
+ MOZ_ASSERT(kind == BinKind::ContinueStatement);
+ MOZ_TRY(checkFields(kind, fields, { BinField::Label }));
+ RootedAtom label(cx_);
+ MOZ_TRY(readMaybeString(&label));
+
+ if (label && !IsIdentifier(label))
+ return raiseError("ContinueStatement - Label MUST be an identifier");
+
+ if (label) {
+ 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");
+ }
+ }
+ }
+
+ TRY_DECL(result, factory_.newContinueStatement(label ? label->asPropertyName() : nullptr, tokenizer_->pos(start)));return result;
+}
+
+
+/*
+ interface DataProperty : Node {
+ PropertyName name;
+ Expression expression;
+ }
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseDataProperty()
+{
+ BinKind kind;
+ BinFields fields(cx_);
+ AutoTaggedTuple guard(*tokenizer_);
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+ const auto start = tokenizer_->offset();
+
+ MOZ_TRY_DECL(result, parseInterfaceDataProperty(start, kind, fields));
+ TRY(guard.done());
+
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseInterfaceDataProperty(const size_t start, const BinKind kind, const BinFields& fields)
+{
+ MOZ_ASSERT(kind == BinKind::DataProperty);
+ MOZ_TRY(checkFields(kind, fields, { BinField::Name, BinField::Expression }));
+
+
+ MOZ_TRY_DECL(name, parsePropertyName());
+
+
+ MOZ_TRY_DECL(expression, parseExpression());
+
+ if (!factory_.isUsableAsObjectPropertyName(name))
+ return raiseError("DataProperty key kind");
+
+ TRY_DECL(result, factory_.newObjectMethodOrPropertyDefinition(name, expression, AccessorType::None));return result;
+}
+
+
+/*
+ interface DebuggerStatement : Node {
+ }
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseDebuggerStatement()
+{
+ BinKind kind;
+ BinFields fields(cx_);
+ AutoTaggedTuple guard(*tokenizer_);
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+ const auto start = tokenizer_->offset();
+
+ MOZ_TRY_DECL(result, parseInterfaceDebuggerStatement(start, kind, fields));
+ TRY(guard.done());
+
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseInterfaceDebuggerStatement(const size_t start, const BinKind kind, const BinFields& fields)
+{
+ return raiseError("FIXME: Not implemented yet (DebuggerStatement)");
+}
+
+
+/*
+ interface Directive : Node {
+ string rawValue;
+ }
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseDirective()
+{
+ BinKind kind;
+ BinFields fields(cx_);
+ AutoTaggedTuple guard(*tokenizer_);
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+ const auto start = tokenizer_->offset();
+
+ MOZ_TRY_DECL(result, parseInterfaceDirective(start, kind, fields));
+ TRY(guard.done());
+
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseInterfaceDirective(const size_t start, const BinKind kind, const BinFields& fields)
+{
+ MOZ_ASSERT(kind == BinKind::Directive);
+ MOZ_TRY(checkFields(kind, fields, { BinField::RawValue }));
+
+ RootedAtom rawValue((cx_));
+ MOZ_TRY(readString(&rawValue));
+
+ TokenPos pos = tokenizer_->pos(start);
+ TRY_DECL(result, factory_.newStringLiteral(rawValue, pos));return result;
+}
+
+
+/*
+ interface DoWhileStatement : Node {
+ Expression test;
+ Statement body;
+ }
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseDoWhileStatement()
+{
+ BinKind kind;
+ BinFields fields(cx_);
+ AutoTaggedTuple guard(*tokenizer_);
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+ const auto start = tokenizer_->offset();
+
+ MOZ_TRY_DECL(result, parseInterfaceDoWhileStatement(start, kind, fields));
+ TRY(guard.done());
+
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseInterfaceDoWhileStatement(const size_t start, const BinKind kind, const BinFields& fields)
+{
+ MOZ_ASSERT(kind == BinKind::DoWhileStatement);
+ MOZ_TRY(checkFields(kind, fields, { BinField::Test, BinField::Body }));
+ ParseContext::Statement stmt(parseContext_, StatementKind::DoLoop);
+
+ MOZ_TRY_DECL(test, parseExpression());
+
+
+ MOZ_TRY_DECL(body, parseStatement());
+
+ TRY_DECL(result, factory_.newDoWhileStatement(body, test, tokenizer_->pos(start)));return result;
+}
+
+
+/*
+ interface EmptyStatement : Node {
+ }
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseEmptyStatement()
+{
+ BinKind kind;
+ BinFields fields(cx_);
+ AutoTaggedTuple guard(*tokenizer_);
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+ const auto start = tokenizer_->offset();
+
+ MOZ_TRY_DECL(result, parseInterfaceEmptyStatement(start, kind, fields));
+ TRY(guard.done());
+
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseInterfaceEmptyStatement(const size_t start, const BinKind kind, const BinFields& fields)
+{
+ MOZ_ASSERT(kind == BinKind::EmptyStatement);
+ MOZ_TRY(checkFields0(kind, fields));
+
+ TRY_DECL(result, factory_.newEmptyStatement(tokenizer_->pos(start)));return result;
+}
+
+
+/*
+ interface Export : Node {
+ (FunctionDeclaration or ClassDeclaration or VariableDeclaration) declaration;
+ }
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseExport()
+{
+ BinKind kind;
+ BinFields fields(cx_);
+ AutoTaggedTuple guard(*tokenizer_);
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+ const auto start = tokenizer_->offset();
+
+ MOZ_TRY_DECL(result, parseInterfaceExport(start, kind, fields));
+ TRY(guard.done());
+
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseInterfaceExport(const size_t start, const BinKind kind, const BinFields& fields)
+{
+ return raiseError("FIXME: Not implemented yet (Export)");
+}
+
+
+/*
+ interface ExportAllFrom : Node {
+ string moduleSpecifier;
+ }
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseExportAllFrom()
+{
+ BinKind kind;
+ BinFields fields(cx_);
+ AutoTaggedTuple guard(*tokenizer_);
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+ const auto start = tokenizer_->offset();
+
+ MOZ_TRY_DECL(result, parseInterfaceExportAllFrom(start, kind, fields));
+ TRY(guard.done());
+
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseInterfaceExportAllFrom(const size_t start, const BinKind kind, const BinFields& fields)
+{
+ return raiseError("FIXME: Not implemented yet (ExportAllFrom)");
+}
+
+
+/*
+ interface ExportDefault : Node {
+ (FunctionDeclaration or ClassDeclaration or Expression) body;
+ }
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseExportDefault()
+{
+ BinKind kind;
+ BinFields fields(cx_);
+ AutoTaggedTuple guard(*tokenizer_);
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+ const auto start = tokenizer_->offset();
+
+ MOZ_TRY_DECL(result, parseInterfaceExportDefault(start, kind, fields));
+ TRY(guard.done());
+
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseInterfaceExportDefault(const size_t start, const BinKind kind, const BinFields& fields)
+{
+ return raiseError("FIXME: Not implemented yet (ExportDefault)");
+}
+
+
+/*
+ interface ExportFrom : Node {
+ FrozenArray<ExportFromSpecifier> namedExports;
+ string moduleSpecifier;
+ }
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseExportFrom()
+{
+ BinKind kind;
+ BinFields fields(cx_);
+ AutoTaggedTuple guard(*tokenizer_);
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+ const auto start = tokenizer_->offset();
+
+ MOZ_TRY_DECL(result, parseInterfaceExportFrom(start, kind, fields));
+ TRY(guard.done());
+
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseInterfaceExportFrom(const size_t start, const BinKind kind, const BinFields& fields)
+{
+ return raiseError("FIXME: Not implemented yet (ExportFrom)");
+}
+
+
+/*
+ interface ExportFromSpecifier : Node {
+ IdentifierName name;
+ IdentifierName? exportedName;
+ }
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseExportFromSpecifier()
+{
+ BinKind kind;
+ BinFields fields(cx_);
+ AutoTaggedTuple guard(*tokenizer_);
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+ const auto start = tokenizer_->offset();
+
+ MOZ_TRY_DECL(result, parseInterfaceExportFromSpecifier(start, kind, fields));
+ TRY(guard.done());
+
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseInterfaceExportFromSpecifier(const size_t start, const BinKind kind, const BinFields& fields)
+{
+ return raiseError("FIXME: Not implemented yet (ExportFromSpecifier)");
+}
+
+
+/*
+ interface ExportLocalSpecifier : Node {
+ IdentifierExpression name;
+ IdentifierName? exportedName;
+ }
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseExportLocalSpecifier()
+{
+ BinKind kind;
+ BinFields fields(cx_);
+ AutoTaggedTuple guard(*tokenizer_);
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+ const auto start = tokenizer_->offset();
+
+ MOZ_TRY_DECL(result, parseInterfaceExportLocalSpecifier(start, kind, fields));
+ TRY(guard.done());
+
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseInterfaceExportLocalSpecifier(const size_t start, const BinKind kind, const BinFields& fields)
+{
+ return raiseError("FIXME: Not implemented yet (ExportLocalSpecifier)");
+}
+
+
+/*
+ interface ExportLocals : Node {
+ FrozenArray<ExportLocalSpecifier> namedExports;
+ }
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseExportLocals()
+{
+ BinKind kind;
+ BinFields fields(cx_);
+ AutoTaggedTuple guard(*tokenizer_);
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+ const auto start = tokenizer_->offset();
+
+ MOZ_TRY_DECL(result, parseInterfaceExportLocals(start, kind, fields));
+ TRY(guard.done());
+
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseInterfaceExportLocals(const size_t start, const BinKind kind, const BinFields& fields)
+{
+ return raiseError("FIXME: Not implemented yet (ExportLocals)");
+}
+
+
+/*
+ interface ExpressionStatement : Node {
+ Expression expression;
+ }
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseExpressionStatement()
+{
+ BinKind kind;
+ BinFields fields(cx_);
+ AutoTaggedTuple guard(*tokenizer_);
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+ const auto start = tokenizer_->offset();
+
+ MOZ_TRY_DECL(result, parseInterfaceExpressionStatement(start, kind, fields));
+ TRY(guard.done());
+
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseInterfaceExpressionStatement(const size_t start, const BinKind kind, const BinFields& fields)
+{
+ MOZ_ASSERT(kind == BinKind::ExpressionStatement);
+ MOZ_TRY(checkFields(kind, fields, { BinField::Expression }));
+
+
+ MOZ_TRY_DECL(expression, parseExpression());
+
+ TRY_DECL(result, factory_.newExprStatement(expression, tokenizer_->offset()));return result;
+}
+
+
+/*
+ interface ForInOfBinding : Node {
+ VariableDeclarationKind kind;
+ Binding binding;
+ }
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseForInOfBinding()
+{
+ BinKind kind;
+ BinFields fields(cx_);
+ AutoTaggedTuple guard(*tokenizer_);
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+ const auto start = tokenizer_->offset();
+
+ MOZ_TRY_DECL(result, parseInterfaceForInOfBinding(start, kind, fields));
+ TRY(guard.done());
+
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseInterfaceForInOfBinding(const size_t start, const BinKind kind, const BinFields& fields)
+{
+ MOZ_ASSERT(kind == BinKind::ForInOfBinding);
+ MOZ_TRY(checkFields(kind, fields, { BinField::Kind, BinField::Binding }));
+ AutoVariableDeclarationKind kindGuard(this);
+
+ MOZ_TRY_DECL(kind_, parseVariableDeclarationKind());
+
+
+ MOZ_TRY_DECL(binding, parseBinding());
+
+ // Restored by `kindGuard`.
+ variableDeclarationKind = kind_;
+ MOZ_TRY(checkBinding(binding->pn_atom->asPropertyName()));
+ auto pnk =
+ kind_ == VariableDeclarationKind::Let
+ ? ParseNodeKind::Let
+ : ParseNodeKind::Var;
+ TRY_DECL(result, factory_.newDeclarationList(pnk, tokenizer_->pos(start)));
+ factory_.addList(result, binding);return result;
+}
+
+
+/*
+ interface ForInStatement : Node {
+ (ForInOfBinding or AssignmentTarget) left;
+ Expression right;
+ Statement body;
+ }
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseForInStatement()
+{
+ BinKind kind;
+ BinFields fields(cx_);
+ AutoTaggedTuple guard(*tokenizer_);
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+ const auto start = tokenizer_->offset();
+
+ MOZ_TRY_DECL(result, parseInterfaceForInStatement(start, kind, fields));
+ TRY(guard.done());
+
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseInterfaceForInStatement(const size_t start, const BinKind kind, const BinFields& fields)
+{
+ MOZ_ASSERT(kind == BinKind::ForInStatement);
+ MOZ_TRY(checkFields(kind, fields, { BinField::Left, BinField::Right, BinField::Body }));
+ 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_);
+ TRY(scope.init(parseContext_));
+
+ MOZ_TRY_DECL(left, parseForInOfBindingOrAssignmentTarget());
+
+
+ MOZ_TRY_DECL(right, parseExpression());
+
+
+ MOZ_TRY_DECL(body, parseStatement());
+
+ TRY_DECL(forHead, factory_.newForInOrOfHead(ParseNodeKind::ForIn, left, right, tokenizer_->pos(start)));
+ TRY_DECL(result, factory_.newForStatement(start, forHead, body, /*flags*/ 0));
+
+ if (!scope.isEmpty()) {
+ TRY_DECL(bindings, NewLexicalScopeData(cx_, scope, alloc_, parseContext_));
+ TRY_VAR(result, factory_.newLexicalScope(*bindings, result));
+ }return result;
+}
+
+
+/*
+ interface ForOfStatement : Node {
+ (ForInOfBinding or AssignmentTarget) left;
+ Expression right;
+ Statement body;
+ }
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseForOfStatement()
+{
+ BinKind kind;
+ BinFields fields(cx_);
+ AutoTaggedTuple guard(*tokenizer_);
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+ const auto start = tokenizer_->offset();
+
+ MOZ_TRY_DECL(result, parseInterfaceForOfStatement(start, kind, fields));
+ TRY(guard.done());
+
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseInterfaceForOfStatement(const size_t start, const BinKind kind, const BinFields& fields)
+{
+ return raiseError("FIXME: Not implemented yet (ForOfStatement)");
+}
+
+
+/*
+ interface ForStatement : Node {
+ (VariableDeclaration or Expression)? init;
+ Expression? test;
+ Expression? update;
+ Statement body;
+ }
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseForStatement()
+{
+ BinKind kind;
+ BinFields fields(cx_);
+ AutoTaggedTuple guard(*tokenizer_);
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+ const auto start = tokenizer_->offset();
+
+ MOZ_TRY_DECL(result, parseInterfaceForStatement(start, kind, fields));
+ TRY(guard.done());
+
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseInterfaceForStatement(const size_t start, const BinKind kind, const BinFields& fields)
+{
+ MOZ_ASSERT(kind == BinKind::ForStatement);
+ MOZ_TRY(checkFields(kind, fields, { BinField::Init, BinField::Test, BinField::Update, BinField::Body }));
+ 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_);
+ TRY(scope.init(parseContext_));
+
+ MOZ_TRY_DECL(init, parseOptionalVariableDeclarationOrExpression());
+
+
+ MOZ_TRY_DECL(test, parseOptionalExpression());
+
+
+ MOZ_TRY_DECL(update, parseOptionalExpression());
+
+
+ MOZ_TRY_DECL(body, parseStatement());
+
+ TRY_DECL(forHead, factory_.newForHead(init, test, update, tokenizer_->pos(start)));
+ TRY_DECL(result, factory_.newForStatement(start, forHead, body, /* iflags = */ 0));
+
+ if (!scope.isEmpty()) {
+ TRY_DECL(bindings, NewLexicalScopeData(cx_, scope, alloc_, parseContext_));
+ TRY_VAR(result, factory_.newLexicalScope(*bindings, result));
+ }return result;
+}
+
+
+/*
+ interface FormalParameters : Node {
+ FrozenArray<Parameter> items;
+ Binding? rest;
+ }
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseFormalParameters()
+{
+ BinKind kind;
+ BinFields fields(cx_);
+ AutoTaggedTuple guard(*tokenizer_);
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+ const auto start = tokenizer_->offset();
+
+ MOZ_TRY_DECL(result, parseInterfaceFormalParameters(start, kind, fields));
+ TRY(guard.done());
+
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseInterfaceFormalParameters(const size_t start, const BinKind kind, const BinFields& fields)
+{
+ MOZ_ASSERT(kind == BinKind::FormalParameters);
+ MOZ_TRY(checkFields(kind, fields, { BinField::Items, BinField::Rest }));
+
+
+ MOZ_TRY_DECL(items, parseListOfParameter());
+
+
+ MOZ_TRY_DECL(rest, parseOptionalBinding());
+
+ auto result = items;
+ if (rest) {
+ TRY_DECL(spread, factory_.newSpread(start, rest));
+ factory_.addList(result, spread);
+ }return result;
+}
+
+
+/*
+ interface FunctionBody : Node {
+ FrozenArray<Directive> directives;
+ FrozenArray<Statement> statements;
+ }
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseFunctionBody()
+{
+ BinKind kind;
+ BinFields fields(cx_);
+ AutoTaggedTuple guard(*tokenizer_);
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+ const auto start = tokenizer_->offset();
+
+ MOZ_TRY_DECL(result, parseInterfaceFunctionBody(start, kind, fields));
+ TRY(guard.done());
+
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseInterfaceFunctionBody(const size_t start, const BinKind kind, const BinFields& fields)
+{
+ MOZ_ASSERT(kind == BinKind::FunctionBody);
+ MOZ_TRY(checkFields(kind, fields, { BinField::Directives, BinField::Statements }));
+
+
+ MOZ_TRY_DECL(directives, parseListOfDirective());
+
+
+ MOZ_TRY_DECL(statements, parseListOfStatement());
+
+ MOZ_TRY_DECL(result, appendDirectivesToBody(/* body = */ statements, /* directives = */ directives));return result;
+}
+
+
+/*
+ interface FunctionDeclaration : Node {
+ bool isAsync;
+ bool isGenerator;
+ AssertedParameterScope? parameterScope;
+ AssertedVarScope? bodyScope;
+ BindingIdentifier name;
+ FormalParameters params;
+ FunctionBody body;
+ }
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseFunctionDeclaration()
+{
+ BinKind kind;
+ BinFields fields(cx_);
+ AutoTaggedTuple guard(*tokenizer_);
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+ const auto start = tokenizer_->offset();
+
+ MOZ_TRY_DECL(result, parseInterfaceFunctionDeclaration(start, kind, fields));
+ TRY(guard.done());
+
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseInterfaceFunctionDeclaration(const size_t start, const BinKind kind, const BinFields& fields)
+{
+ MOZ_ASSERT(kind == BinKind::FunctionDeclaration);
+ MOZ_TRY(checkFields(kind, fields, { BinField::IsAsync, BinField::IsGenerator, BinField::ParameterScope, BinField::BodyScope, BinField::Name, BinField::Params, BinField::Body }));
+
+
+ MOZ_TRY_DECL(isAsync, readBool());
+
+
+ MOZ_TRY_DECL(isGenerator, readBool());
+
+ MOZ_TRY_DECL(funbox, buildFunctionBox(
+ isGenerator ? GeneratorKind::Generator
+ : GeneratorKind::NotGenerator,
+ isAsync ? FunctionAsyncKind::AsyncFunction
+ : FunctionAsyncKind::SyncFunction));
+
+ // Push a new ParseContext. It will be used to parse `scope`, the arguments, the function.
+ BinParseContext funpc(cx_, this, funbox, /* newDirectives = */ nullptr);
+ TRY(funpc.init());
+ parseContext_->functionScope().useAsVarScope(parseContext_);
+ MOZ_ASSERT(parseContext_->isFunctionBox());
+
+ ParseContext::Scope lexicalScope(cx_, parseContext_, usedNames_);
+ TRY(lexicalScope.init(parseContext_));
+
+ MOZ_TRY(parseOptionalAssertedParameterScope());
+
+
+
+ MOZ_TRY(parseOptionalAssertedVarScope());
+
+
+ MOZ_TRY_DECL(name, parseBindingIdentifier());
+
+
+ MOZ_TRY_DECL(params, parseFormalParameters());
+
+
+ MOZ_TRY_DECL(body, parseFunctionBody());
+
+ TRY_DECL(lexicalScopeData, NewLexicalScopeData(cx_, lexicalScope, alloc_, parseContext_));
+ TRY_VAR(body, factory_.newLexicalScope(*lexicalScopeData, body));
+ MOZ_TRY_DECL(result, buildFunction(start, kind, name, params, body, funbox));return result;
+}
+
+
+/*
+ interface FunctionExpression : Node {
+ bool isAsync;
+ bool isGenerator;
+ AssertedParameterScope? parameterScope;
+ AssertedVarScope? bodyScope;
+ BindingIdentifier? name;
+ FormalParameters params;
+ FunctionBody body;
+ }
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseFunctionExpression()
+{
+ BinKind kind;
+ BinFields fields(cx_);
+ AutoTaggedTuple guard(*tokenizer_);
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+ const auto start = tokenizer_->offset();
+
+ MOZ_TRY_DECL(result, parseInterfaceFunctionExpression(start, kind, fields));
+ TRY(guard.done());
+
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseInterfaceFunctionExpression(const size_t start, const BinKind kind, const BinFields& fields)
+{
+ MOZ_ASSERT(kind == BinKind::FunctionExpression);
+ MOZ_TRY(checkFields(kind, fields, { BinField::IsAsync, BinField::IsGenerator, BinField::ParameterScope, BinField::BodyScope, BinField::Name, BinField::Params, BinField::Body }));
+
+
+ MOZ_TRY_DECL(isAsync, readBool());
+
+
+ MOZ_TRY_DECL(isGenerator, readBool());
+
+ MOZ_TRY_DECL(funbox, buildFunctionBox(
+ isGenerator ? GeneratorKind::Generator
+ : GeneratorKind::NotGenerator,
+ isAsync ? FunctionAsyncKind::AsyncFunction
+ : FunctionAsyncKind::SyncFunction));
+
+ // Push a new ParseContext. It will be used to parse `scope`, the arguments, the function.
+ BinParseContext funpc(cx_, this, funbox, /* newDirectives = */ nullptr);
+ TRY(funpc.init());
+ parseContext_->functionScope().useAsVarScope(parseContext_);
+ MOZ_ASSERT(parseContext_->isFunctionBox());
+
+ ParseContext::Scope lexicalScope(cx_, parseContext_, usedNames_);
+ TRY(lexicalScope.init(parseContext_));
+
+ MOZ_TRY(parseOptionalAssertedParameterScope());
+
+
+
+ MOZ_TRY(parseOptionalAssertedVarScope());
+
+
+ MOZ_TRY_DECL(name, parseOptionalBindingIdentifier());
+
+
+ MOZ_TRY_DECL(params, parseFormalParameters());
+
+
+ MOZ_TRY_DECL(body, parseFunctionBody());
+
+ TRY_DECL(lexicalScopeData, NewLexicalScopeData(cx_, lexicalScope, alloc_, parseContext_));
+ TRY_VAR(body, factory_.newLexicalScope(*lexicalScopeData, body));
+ MOZ_TRY_DECL(result, buildFunction(start, kind, name, params, body, funbox));return result;
+}
+
+
+/*
+ interface Getter : Node {
+ AssertedVarScope? bodyScope;
+ PropertyName name;
+ FunctionBody body;
+ }
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseGetter()
+{
+ BinKind kind;
+ BinFields fields(cx_);
+ AutoTaggedTuple guard(*tokenizer_);
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+ const auto start = tokenizer_->offset();
+
+ MOZ_TRY_DECL(result, parseInterfaceGetter(start, kind, fields));
+ TRY(guard.done());
+
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseInterfaceGetter(const size_t start, const BinKind kind, const BinFields& fields)
+{
+ return raiseError("FIXME: Not implemented yet (Getter)");
+}
+
+
+/*
+ interface IdentifierExpression : Node {
+ Identifier name;
+ }
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseIdentifierExpression()
+{
+ BinKind kind;
+ BinFields fields(cx_);
+ AutoTaggedTuple guard(*tokenizer_);
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+ const auto start = tokenizer_->offset();
+
+ MOZ_TRY_DECL(result, parseInterfaceIdentifierExpression(start, kind, fields));
+ TRY(guard.done());
+
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseInterfaceIdentifierExpression(const size_t start, const BinKind kind, const BinFields& fields)
+{
+ MOZ_ASSERT(kind == BinKind::IdentifierExpression);
+ MOZ_TRY(checkFields(kind, fields, { BinField::Name }));
+
+ RootedAtom name((cx_));
+ MOZ_TRY(readString(&name));
+
+ if (!IsIdentifier(name))
+ return raiseError("Invalid identifier");
+ TRY_DECL(result, factory_.newName(name->asPropertyName(), tokenizer_->pos(start), cx_));return result;
+}
+
+
+/*
+ interface IfStatement : Node {
+ Expression test;
+ Statement consequent;
+ Statement? alternate;
+ }
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseIfStatement()
+{
+ BinKind kind;
+ BinFields fields(cx_);
+ AutoTaggedTuple guard(*tokenizer_);
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+ const auto start = tokenizer_->offset();
+
+ MOZ_TRY_DECL(result, parseInterfaceIfStatement(start, kind, fields));
+ TRY(guard.done());
+
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseInterfaceIfStatement(const size_t start, const BinKind kind, const BinFields& fields)
+{
+ MOZ_ASSERT(kind == BinKind::IfStatement);
+ MOZ_TRY(checkFields(kind, fields, { BinField::Test, BinField::Consequent, BinField::Alternate }));
+
+
+ MOZ_TRY_DECL(test, parseExpression());
+
+
+ MOZ_TRY_DECL(consequent, parseStatement());
+
+
+ MOZ_TRY_DECL(alternate, parseOptionalStatement());
+
+ TRY_DECL(result, factory_.newIfStatement(start, test, consequent, alternate));return result;
+}
+
+
+/*
+ interface Import : Node {
+ string moduleSpecifier;
+ BindingIdentifier? defaultBinding;
+ FrozenArray<ImportSpecifier> namedImports;
+ }
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseImport()
+{
+ BinKind kind;
+ BinFields fields(cx_);
+ AutoTaggedTuple guard(*tokenizer_);
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+ const auto start = tokenizer_->offset();
+
+ MOZ_TRY_DECL(result, parseInterfaceImport(start, kind, fields));
+ TRY(guard.done());
+
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseInterfaceImport(const size_t start, const BinKind kind, const BinFields& fields)
+{
+ return raiseError("FIXME: Not implemented yet (Import)");
+}
+
+
+/*
+ interface ImportNamespace : Node {
+ string moduleSpecifier;
+ BindingIdentifier? defaultBinding;
+ BindingIdentifier namespaceBinding;
+ }
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseImportNamespace()
+{
+ BinKind kind;
+ BinFields fields(cx_);
+ AutoTaggedTuple guard(*tokenizer_);
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+ const auto start = tokenizer_->offset();
+
+ MOZ_TRY_DECL(result, parseInterfaceImportNamespace(start, kind, fields));
+ TRY(guard.done());
+
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseInterfaceImportNamespace(const size_t start, const BinKind kind, const BinFields& fields)
+{
+ return raiseError("FIXME: Not implemented yet (ImportNamespace)");
+}
+
+
+/*
+ interface ImportSpecifier : Node {
+ IdentifierName? name;
+ BindingIdentifier binding;
+ }
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseImportSpecifier()
+{
+ BinKind kind;
+ BinFields fields(cx_);
+ AutoTaggedTuple guard(*tokenizer_);
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+ const auto start = tokenizer_->offset();
+
+ MOZ_TRY_DECL(result, parseInterfaceImportSpecifier(start, kind, fields));
+ TRY(guard.done());
+
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseInterfaceImportSpecifier(const size_t start, const BinKind kind, const BinFields& fields)
+{
+ return raiseError("FIXME: Not implemented yet (ImportSpecifier)");
+}
+
+
+/*
+ interface LabelledStatement : Node {
+ Label label;
+ Statement body;
+ }
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseLabelledStatement()
+{
+ BinKind kind;
+ BinFields fields(cx_);
+ AutoTaggedTuple guard(*tokenizer_);
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+ const auto start = tokenizer_->offset();
+
+ MOZ_TRY_DECL(result, parseInterfaceLabelledStatement(start, kind, fields));
+ TRY(guard.done());
+
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseInterfaceLabelledStatement(const size_t start, const BinKind kind, const BinFields& fields)
+{
+ MOZ_ASSERT(kind == BinKind::LabelledStatement);
+ MOZ_TRY(checkFields(kind, fields, { BinField::Label, BinField::Body }));
+
+
+ RootedAtom label((cx_));
+ MOZ_TRY(readString(&label));
+ if (!IsIdentifier(label))
+ return raiseError("Invalid identifier");
+ ParseContext::LabelStatement stmt(parseContext_, label);
+
+
+ MOZ_TRY_DECL(body, parseStatement());
+
+ TRY_DECL(result, factory_.newLabeledStatement(label->asPropertyName(), body, start));return result;
+}
+
+
+/*
+ interface LiteralBooleanExpression : Node {
+ bool value;
+ }
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseLiteralBooleanExpression()
+{
+ BinKind kind;
+ BinFields fields(cx_);
+ AutoTaggedTuple guard(*tokenizer_);
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+ const auto start = tokenizer_->offset();
+
+ MOZ_TRY_DECL(result, parseInterfaceLiteralBooleanExpression(start, kind, fields));
+ TRY(guard.done());
+
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseInterfaceLiteralBooleanExpression(const size_t start, const BinKind kind, const BinFields& fields)
+{
+ MOZ_ASSERT(kind == BinKind::LiteralBooleanExpression);
+ MOZ_TRY(checkFields(kind, fields, { BinField::Value }));
+
+
+ MOZ_TRY_DECL(value, readBool());
+
+ TRY_DECL(result, factory_.newBooleanLiteral(value, tokenizer_->pos(start)));return result;
+}
+
+
+/*
+ interface LiteralInfinityExpression : Node {
+ }
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseLiteralInfinityExpression()
+{
+ BinKind kind;
+ BinFields fields(cx_);
+ AutoTaggedTuple guard(*tokenizer_);
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+ const auto start = tokenizer_->offset();
+
+ MOZ_TRY_DECL(result, parseInterfaceLiteralInfinityExpression(start, kind, fields));
+ TRY(guard.done());
+
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseInterfaceLiteralInfinityExpression(const size_t start, const BinKind kind, const BinFields& fields)
+{
+ return raiseError("FIXME: Not implemented yet (LiteralInfinityExpression)");
+}
+
+
+/*
+ interface LiteralNullExpression : Node {
+ }
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseLiteralNullExpression()
+{
+ BinKind kind;
+ BinFields fields(cx_);
+ AutoTaggedTuple guard(*tokenizer_);
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+ const auto start = tokenizer_->offset();
+
+ MOZ_TRY_DECL(result, parseInterfaceLiteralNullExpression(start, kind, fields));
+ TRY(guard.done());
+
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseInterfaceLiteralNullExpression(const size_t start, const BinKind kind, const BinFields& fields)
+{
+ MOZ_ASSERT(kind == BinKind::LiteralNullExpression);
+ MOZ_TRY(checkFields0(kind, fields));
+
+ TRY_DECL(result, factory_.newNullLiteral(tokenizer_->pos(start)));return result;
+}
+
+
+/*
+ interface LiteralNumericExpression : Node {
+ number value;
+ }
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseLiteralNumericExpression()
+{
+ BinKind kind;
+ BinFields fields(cx_);
+ AutoTaggedTuple guard(*tokenizer_);
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+ const auto start = tokenizer_->offset();
+
+ MOZ_TRY_DECL(result, parseInterfaceLiteralNumericExpression(start, kind, fields));
+ TRY(guard.done());
+
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseInterfaceLiteralNumericExpression(const size_t start, const BinKind kind, const BinFields& fields)
+{
+ MOZ_ASSERT(kind == BinKind::LiteralNumericExpression);
+ MOZ_TRY(checkFields(kind, fields, { BinField::Value }));
+
+
+ MOZ_TRY_DECL(value, readNumber());
+
+ TRY_DECL(result, factory_.newNumber(value, DecimalPoint::HasDecimal, tokenizer_->pos(start)));return result;
+}
+
+
+/*
+ interface LiteralPropertyName : Node {
+ string value;
+ }
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseLiteralPropertyName()
+{
+ BinKind kind;
+ BinFields fields(cx_);
+ AutoTaggedTuple guard(*tokenizer_);
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+ const auto start = tokenizer_->offset();
+
+ MOZ_TRY_DECL(result, parseInterfaceLiteralPropertyName(start, kind, fields));
+ TRY(guard.done());
+
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseInterfaceLiteralPropertyName(const size_t start, const BinKind kind, const BinFields& fields)
+{
+ MOZ_ASSERT(kind == BinKind::LiteralPropertyName);
+ MOZ_TRY(checkFields(kind, fields, { BinField::Value }));
+
+ RootedAtom value((cx_));
+ MOZ_TRY(readString(&value));
+
+ ParseNode* result;
+ uint32_t index;
+ if (value->isIndex(&index))
+ TRY_VAR(result, factory_.newNumber(index, NoDecimal, TokenPos(start, tokenizer_->offset())));
+ else
+ TRY_VAR(result, factory_.newObjectLiteralPropertyName(value, tokenizer_->pos(start)));return result;
+}
+
+
+/*
+ interface LiteralRegExpExpression : Node {
+ string pattern;
+ string flags;
+ }
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseLiteralRegExpExpression()
+{
+ BinKind kind;
+ BinFields fields(cx_);
+ AutoTaggedTuple guard(*tokenizer_);
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+ const auto start = tokenizer_->offset();
+
+ MOZ_TRY_DECL(result, parseInterfaceLiteralRegExpExpression(start, kind, fields));
+ TRY(guard.done());
+
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseInterfaceLiteralRegExpExpression(const size_t start, const BinKind kind, const BinFields& fields)
+{
+ MOZ_ASSERT(kind == BinKind::LiteralRegExpExpression);
+ MOZ_TRY(checkFields(kind, fields, { BinField::Pattern, BinField::Flags }));
+
+ RootedAtom pattern((cx_));
+ MOZ_TRY(readString(&pattern));
+ Chars flags(cx_); MOZ_TRY(readString(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 raiseInvalidEnum("RegExpLiteral", flags);
+ }
+
+
+ Rooted<RegExpObject*> reobj(cx_);
+ TRY_VAR(reobj, RegExpObject::create(cx_,
+ pattern,
+ reflags,
+ alloc_,
+ TenuredObject));
+
+ TRY_DECL(result, factory_.newRegExp(reobj, tokenizer_->pos(start), *this));return result;
+}
+
+
+/*
+ interface LiteralStringExpression : Node {
+ string value;
+ }
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseLiteralStringExpression()
+{
+ BinKind kind;
+ BinFields fields(cx_);
+ AutoTaggedTuple guard(*tokenizer_);
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+ const auto start = tokenizer_->offset();
+
+ MOZ_TRY_DECL(result, parseInterfaceLiteralStringExpression(start, kind, fields));
+ TRY(guard.done());
+
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseInterfaceLiteralStringExpression(const size_t start, const BinKind kind, const BinFields& fields)
+{
+ MOZ_ASSERT(kind == BinKind::LiteralStringExpression);
+ MOZ_TRY(checkFields(kind, fields, { BinField::Value }));
+
+ RootedAtom value((cx_));
+ MOZ_TRY(readString(&value));
+
+ TRY_DECL(result, factory_.newStringLiteral(value, tokenizer_->pos(start)));return result;
+}
+
+
+/*
+ interface Method : Node {
+ bool isAsync;
+ bool isGenerator;
+ AssertedParameterScope? parameterScope;
+ AssertedVarScope? bodyScope;
+ PropertyName name;
+ FormalParameters params;
+ FunctionBody body;
+ }
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseMethod()
+{
+ BinKind kind;
+ BinFields fields(cx_);
+ AutoTaggedTuple guard(*tokenizer_);
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+ const auto start = tokenizer_->offset();
+
+ MOZ_TRY_DECL(result, parseInterfaceMethod(start, kind, fields));
+ TRY(guard.done());
+
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseInterfaceMethod(const size_t start, const BinKind kind, const BinFields& fields)
+{
+ MOZ_ASSERT(kind == BinKind::Method);
+ MOZ_TRY(checkFields(kind, fields, { BinField::IsAsync, BinField::IsGenerator, BinField::ParameterScope, BinField::BodyScope, BinField::Name, BinField::Params, BinField::Body }));
+
+
+ MOZ_TRY_DECL(isAsync, readBool());
+
+
+ MOZ_TRY_DECL(isGenerator, readBool());
+
+ MOZ_TRY_DECL(funbox, buildFunctionBox(
+ isGenerator ? GeneratorKind::Generator
+ : GeneratorKind::NotGenerator,
+ isAsync ? FunctionAsyncKind::AsyncFunction
+ : FunctionAsyncKind::SyncFunction));
+
+ // Push a new ParseContext. It will be used to parse `scope`, the arguments, the function.
+ BinParseContext funpc(cx_, this, funbox, /* newDirectives = */ nullptr);
+ TRY(funpc.init());
+ parseContext_->functionScope().useAsVarScope(parseContext_);
+ MOZ_ASSERT(parseContext_->isFunctionBox());
+
+ ParseContext::Scope lexicalScope(cx_, parseContext_, usedNames_);
+ TRY(lexicalScope.init(parseContext_));
+
+ MOZ_TRY(parseOptionalAssertedParameterScope());
+
+
+
+ MOZ_TRY(parseOptionalAssertedVarScope());
+
+
+ MOZ_TRY_DECL(name, parsePropertyName());
+
+
+ MOZ_TRY_DECL(params, parseFormalParameters());
+
+
+ MOZ_TRY_DECL(body, parseFunctionBody());
+
+ MOZ_TRY_DECL(method, buildFunction(start, kind, name, params, body, funbox));
+ TRY_DECL(result, factory_.newObjectMethodOrPropertyDefinition(name, method, AccessorType::None));return result;
+}
+
+
+/*
+ interface Module : Node {
+ AssertedVarScope? scope;
+ FrozenArray<Directive> directives;
+ FrozenArray<(ImportDeclaration or ExportDeclaration or Statement)> items;
+ }
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseModule()
+{
+ BinKind kind;
+ BinFields fields(cx_);
+ AutoTaggedTuple guard(*tokenizer_);
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+ const auto start = tokenizer_->offset();
+
+ MOZ_TRY_DECL(result, parseInterfaceModule(start, kind, fields));
+ TRY(guard.done());
+
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseInterfaceModule(const size_t start, const BinKind kind, const BinFields& fields)
+{
+ return raiseError("FIXME: Not implemented yet (Module)");
+}
+
+
+/*
+ interface NewExpression : Node {
+ Expression callee;
+ Arguments arguments;
+ }
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseNewExpression()
+{
+ BinKind kind;
+ BinFields fields(cx_);
+ AutoTaggedTuple guard(*tokenizer_);
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+ const auto start = tokenizer_->offset();
+
+ MOZ_TRY_DECL(result, parseInterfaceNewExpression(start, kind, fields));
+ TRY(guard.done());
+
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseInterfaceNewExpression(const size_t start, const BinKind kind, const BinFields& fields)
+{
+ MOZ_ASSERT(kind == BinKind::NewExpression);
+ MOZ_TRY(checkFields(kind, fields, { BinField::Callee, BinField::Arguments }));
+
+
+ MOZ_TRY_DECL(callee, parseExpression());
+
+
+ MOZ_TRY_DECL(arguments, parseArguments());
+
+ auto result = arguments;
+ result->setKind(ParseNodeKind::New);
+ result->prepend(callee);return result;
+}
+
+
+/*
+ interface NewTargetExpression : Node {
+ }
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseNewTargetExpression()
+{
+ BinKind kind;
+ BinFields fields(cx_);
+ AutoTaggedTuple guard(*tokenizer_);
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+ const auto start = tokenizer_->offset();
+
+ MOZ_TRY_DECL(result, parseInterfaceNewTargetExpression(start, kind, fields));
+ TRY(guard.done());
+
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseInterfaceNewTargetExpression(const size_t start, const BinKind kind, const BinFields& fields)
+{
+ return raiseError("FIXME: Not implemented yet (NewTargetExpression)");
+}
+
+
+/*
+ interface ObjectAssignmentTarget : Node {
+ FrozenArray<AssignmentTargetProperty> properties;
+ }
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseObjectAssignmentTarget()
+{
+ BinKind kind;
+ BinFields fields(cx_);
+ AutoTaggedTuple guard(*tokenizer_);
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+ const auto start = tokenizer_->offset();
+
+ MOZ_TRY_DECL(result, parseInterfaceObjectAssignmentTarget(start, kind, fields));
+ TRY(guard.done());
+
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseInterfaceObjectAssignmentTarget(const size_t start, const BinKind kind, const BinFields& fields)
+{
+ return raiseError("FIXME: Not implemented yet (ObjectAssignmentTarget)");
+}
+
+
+/*
+ interface ObjectBinding : Node {
+ FrozenArray<BindingProperty> properties;
+ }
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseObjectBinding()
+{
+ BinKind kind;
+ BinFields fields(cx_);
+ AutoTaggedTuple guard(*tokenizer_);
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+ const auto start = tokenizer_->offset();
+
+ MOZ_TRY_DECL(result, parseInterfaceObjectBinding(start, kind, fields));
+ TRY(guard.done());
+
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseInterfaceObjectBinding(const size_t start, const BinKind kind, const BinFields& fields)
+{
+ return raiseError("FIXME: Not implemented yet (ObjectBinding)");
+}
+
+
+/*
+ interface ObjectExpression : Node {
+ FrozenArray<ObjectProperty> properties;
+ }
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseObjectExpression()
+{
+ BinKind kind;
+ BinFields fields(cx_);
+ AutoTaggedTuple guard(*tokenizer_);
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+ const auto start = tokenizer_->offset();
+
+ MOZ_TRY_DECL(result, parseInterfaceObjectExpression(start, kind, fields));
+ TRY(guard.done());
+
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseInterfaceObjectExpression(const size_t start, const BinKind kind, const BinFields& fields)
+{
+ MOZ_ASSERT(kind == BinKind::ObjectExpression);
+ MOZ_TRY(checkFields(kind, fields, { BinField::Properties }));
+
+
+ MOZ_TRY_DECL(properties, parseListOfObjectProperty());
+
+ auto result = properties;return result;
+}
+
+
+/*
+ interface ReturnStatement : Node {
+ Expression? expression;
+ }
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseReturnStatement()
+{
+ BinKind kind;
+ BinFields fields(cx_);
+ AutoTaggedTuple guard(*tokenizer_);
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+ const auto start = tokenizer_->offset();
+
+ MOZ_TRY_DECL(result, parseInterfaceReturnStatement(start, kind, fields));
+ TRY(guard.done());
+
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseInterfaceReturnStatement(const size_t start, const BinKind kind, const BinFields& fields)
+{
+ MOZ_ASSERT(kind == BinKind::ReturnStatement);
+ MOZ_TRY(checkFields(kind, fields, { BinField::Expression }));
+ if (!parseContext_->isFunctionBox()) {
+ // Return statements are permitted only inside functions.
+ return raiseInvalidKind("Toplevel Statement", kind);
+ }
+
+ parseContext_->functionBox()->usesReturn = true;
+
+ MOZ_TRY_DECL(expression, parseOptionalExpression());
+
+ TRY_DECL(result, factory_.newReturnStatement(expression, tokenizer_->pos(start)));return result;
+}
+
+
+/*
+ interface Script : Node {
+ AssertedVarScope? scope;
+ FrozenArray<Directive> directives;
+ FrozenArray<Statement> statements;
+ }
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseScript()
+{
+ BinKind kind;
+ BinFields fields(cx_);
+ AutoTaggedTuple guard(*tokenizer_);
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+ const auto start = tokenizer_->offset();
+
+ MOZ_TRY_DECL(result, parseInterfaceScript(start, kind, fields));
+ TRY(guard.done());
+
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseInterfaceScript(const size_t start, const BinKind kind, const BinFields& fields)
+{
+ MOZ_ASSERT(kind == BinKind::Script);
+ MOZ_TRY(checkFields(kind, fields, { BinField::Scope, BinField::Directives, BinField::Statements }));
+
+
+ MOZ_TRY(parseOptionalAssertedVarScope());
+
+
+ MOZ_TRY_DECL(directives, parseListOfDirective());
+
+
+ MOZ_TRY_DECL(statements, parseListOfStatement());
+
+ MOZ_TRY_DECL(result, appendDirectivesToBody(/* body = */ statements, /* directives = */ directives));return result;
+}
+
+
+/*
+ interface Setter : Node {
+ AssertedParameterScope? parameterScope;
+ AssertedVarScope? bodyScope;
+ PropertyName name;
+ Parameter param;
+ FunctionBody body;
+ }
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseSetter()
+{
+ BinKind kind;
+ BinFields fields(cx_);
+ AutoTaggedTuple guard(*tokenizer_);
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+ const auto start = tokenizer_->offset();
+
+ MOZ_TRY_DECL(result, parseInterfaceSetter(start, kind, fields));
+ TRY(guard.done());
+
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseInterfaceSetter(const size_t start, const BinKind kind, const BinFields& fields)
+{
+ MOZ_ASSERT(kind == BinKind::Setter);
+ MOZ_TRY(checkFields(kind, fields, { BinField::ParameterScope, BinField::BodyScope, BinField::Name, BinField::Param, BinField::Body }));
+ const auto isAsync = false;
+ const auto isGenerator = false;
+ MOZ_TRY_DECL(funbox, buildFunctionBox(
+ isGenerator ? GeneratorKind::Generator
+ : GeneratorKind::NotGenerator,
+ isAsync ? FunctionAsyncKind::AsyncFunction
+ : FunctionAsyncKind::SyncFunction));
+
+ // Push a new ParseContext. It will be used to parse `scope`, the arguments, the function.
+ BinParseContext funpc(cx_, this, funbox, /* newDirectives = */ nullptr);
+ TRY(funpc.init());
+ parseContext_->functionScope().useAsVarScope(parseContext_);
+ MOZ_ASSERT(parseContext_->isFunctionBox());
+
+ ParseContext::Scope lexicalScope(cx_, parseContext_, usedNames_);
+ TRY(lexicalScope.init(parseContext_));
+
+ MOZ_TRY(parseOptionalAssertedParameterScope());
+
+
+
+ MOZ_TRY(parseOptionalAssertedVarScope());
+
+
+ MOZ_TRY_DECL(name, parsePropertyName());
+
+
+ MOZ_TRY_DECL(param, parseParameter());
+
+
+ MOZ_TRY_DECL(body, parseFunctionBody());
+
+ TRY_DECL(params, factory_.newList(ParseNodeKind::ParamsBody, param));
+ MOZ_TRY_DECL(method, buildFunction(start, kind, name, params, body, funbox));
+ TRY_DECL(result, factory_.newObjectMethodOrPropertyDefinition(name, method, AccessorType::Setter));return result;
+}
+
+
+/*
+ interface ShorthandProperty : Node {
+ IdentifierExpression name;
+ }
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseShorthandProperty()
+{
+ BinKind kind;
+ BinFields fields(cx_);
+ AutoTaggedTuple guard(*tokenizer_);
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+ const auto start = tokenizer_->offset();
+
+ MOZ_TRY_DECL(result, parseInterfaceShorthandProperty(start, kind, fields));
+ TRY(guard.done());
+
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseInterfaceShorthandProperty(const size_t start, const BinKind kind, const BinFields& fields)
+{
+ MOZ_ASSERT(kind == BinKind::ShorthandProperty);
+ MOZ_TRY(checkFields(kind, fields, { BinField::Name }));
+
+
+ MOZ_TRY_DECL(name, parseIdentifierExpression());
+
+ if (!factory_.isUsableAsObjectPropertyName(name))
+ TRY_VAR(name, factory_.newObjectLiteralPropertyName(name->name(), tokenizer_->pos(start)));
+
+ TRY_DECL(result, factory_.newObjectMethodOrPropertyDefinition(name, name, AccessorType::None));return result;
+}
+
+
+/*
+ interface SpreadElement : Node {
+ Expression expression;
+ }
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseSpreadElement()
+{
+ BinKind kind;
+ BinFields fields(cx_);
+ AutoTaggedTuple guard(*tokenizer_);
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+ const auto start = tokenizer_->offset();
+
+ MOZ_TRY_DECL(result, parseInterfaceSpreadElement(start, kind, fields));
+ TRY(guard.done());
+
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseInterfaceSpreadElement(const size_t start, const BinKind kind, const BinFields& fields)
+{
+ return raiseError("FIXME: Not implemented yet (SpreadElement)");
+}
+
+
+/*
+ interface StaticMemberAssignmentTarget : Node {
+ (Expression or Super) object;
+ IdentifierName property;
+ }
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseStaticMemberAssignmentTarget()
+{
+ BinKind kind;
+ BinFields fields(cx_);
+ AutoTaggedTuple guard(*tokenizer_);
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+ const auto start = tokenizer_->offset();
+
+ MOZ_TRY_DECL(result, parseInterfaceStaticMemberAssignmentTarget(start, kind, fields));
+ TRY(guard.done());
+
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseInterfaceStaticMemberAssignmentTarget(const size_t start, const BinKind kind, const BinFields& fields)
+{
+ MOZ_ASSERT(kind == BinKind::StaticMemberAssignmentTarget);
+ MOZ_TRY(checkFields(kind, fields, { BinField::Object, BinField::Property }));
+
+
+ MOZ_TRY_DECL(object, parseExpressionOrSuper());
+
+ RootedAtom property((cx_));
+ MOZ_TRY(readString(&property));
+
+ TRY_DECL(result, factory_.newPropertyAccess(object, property->asPropertyName(), start));return result;
+}
+
+
+/*
+ interface StaticMemberExpression : Node {
+ (Expression or Super) object;
+ IdentifierName property;
+ }
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseStaticMemberExpression()
+{
+ BinKind kind;
+ BinFields fields(cx_);
+ AutoTaggedTuple guard(*tokenizer_);
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+ const auto start = tokenizer_->offset();
+
+ MOZ_TRY_DECL(result, parseInterfaceStaticMemberExpression(start, kind, fields));
+ TRY(guard.done());
+
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseInterfaceStaticMemberExpression(const size_t start, const BinKind kind, const BinFields& fields)
+{
+ MOZ_ASSERT(kind == BinKind::StaticMemberExpression);
+ MOZ_TRY(checkFields(kind, fields, { BinField::Object, BinField::Property }));
+
+
+ MOZ_TRY_DECL(object, parseExpressionOrSuper());
+
+ RootedAtom property((cx_));
+ MOZ_TRY(readString(&property));
+
+ TRY_DECL(result, factory_.newPropertyAccess(object, property->asPropertyName(), start));return result;
+}
+
+
+/*
+ interface Super : Node {
+ }
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseSuper()
+{
+ BinKind kind;
+ BinFields fields(cx_);
+ AutoTaggedTuple guard(*tokenizer_);
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+ const auto start = tokenizer_->offset();
+
+ MOZ_TRY_DECL(result, parseInterfaceSuper(start, kind, fields));
+ TRY(guard.done());
+
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseInterfaceSuper(const size_t start, const BinKind kind, const BinFields& fields)
+{
+ return raiseError("FIXME: Not implemented yet (Super)");
+}
+
+
+/*
+ interface SwitchCase : Node {
+ Expression test;
+ FrozenArray<Statement> consequent;
+ }
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseSwitchCase()
+{
+ BinKind kind;
+ BinFields fields(cx_);
+ AutoTaggedTuple guard(*tokenizer_);
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+ const auto start = tokenizer_->offset();
+
+ MOZ_TRY_DECL(result, parseInterfaceSwitchCase(start, kind, fields));
+ TRY(guard.done());
+
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseInterfaceSwitchCase(const size_t start, const BinKind kind, const BinFields& fields)
+{
+ MOZ_ASSERT(kind == BinKind::SwitchCase);
+ MOZ_TRY(checkFields(kind, fields, { BinField::Test, BinField::Consequent }));
+
+
+ MOZ_TRY_DECL(test, parseExpression());
+
+
+ MOZ_TRY_DECL(consequent, parseListOfStatement());
+
+ TRY_DECL(result, factory_.newCaseOrDefault(start, test, consequent));return result;
+}
+
+
+/*
+ interface SwitchDefault : Node {
+ FrozenArray<Statement> consequent;
+ }
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseSwitchDefault()
+{
+ BinKind kind;
+ BinFields fields(cx_);
+ AutoTaggedTuple guard(*tokenizer_);
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+ const auto start = tokenizer_->offset();
+
+ MOZ_TRY_DECL(result, parseInterfaceSwitchDefault(start, kind, fields));
+ TRY(guard.done());
+
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseInterfaceSwitchDefault(const size_t start, const BinKind kind, const BinFields& fields)
+{
+ MOZ_ASSERT(kind == BinKind::SwitchDefault);
+ MOZ_TRY(checkFields(kind, fields, { BinField::Consequent }));
+
+
+ MOZ_TRY_DECL(consequent, parseListOfStatement());
+
+ TRY_DECL(result, factory_.newCaseOrDefault(start, nullptr, consequent));return result;
+}
+
+
+/*
+ interface SwitchStatement : Node {
+ Expression discriminant;
+ FrozenArray<SwitchCase> cases;
+ }
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseSwitchStatement()
+{
+ BinKind kind;
+ BinFields fields(cx_);
+ AutoTaggedTuple guard(*tokenizer_);
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+ const auto start = tokenizer_->offset();
+
+ MOZ_TRY_DECL(result, parseInterfaceSwitchStatement(start, kind, fields));
+ TRY(guard.done());
+
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseInterfaceSwitchStatement(const size_t start, const BinKind kind, const BinFields& fields)
+{
+ MOZ_ASSERT(kind == BinKind::SwitchStatement);
+ MOZ_TRY(checkFields(kind, fields, { BinField::Discriminant, BinField::Cases }));
+
+
+ MOZ_TRY_DECL(discriminant, parseExpression());
+
+
+ MOZ_TRY_DECL(cases, parseListOfSwitchCase());
+
+ TRY_DECL(scope, factory_.newLexicalScope(nullptr, cases));
+ TRY_DECL(result, factory_.newSwitchStatement(start, discriminant, scope));return result;
+}
+
+
+/*
+ interface SwitchStatementWithDefault : Node {
+ Expression discriminant;
+ FrozenArray<SwitchCase> preDefaultCases;
+ SwitchDefault defaultCase;
+ FrozenArray<SwitchCase> postDefaultCases;
+ }
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseSwitchStatementWithDefault()
+{
+ BinKind kind;
+ BinFields fields(cx_);
+ AutoTaggedTuple guard(*tokenizer_);
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+ const auto start = tokenizer_->offset();
+
+ MOZ_TRY_DECL(result, parseInterfaceSwitchStatementWithDefault(start, kind, fields));
+ TRY(guard.done());
+
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseInterfaceSwitchStatementWithDefault(const size_t start, const BinKind kind, const BinFields& fields)
+{
+ MOZ_ASSERT(kind == BinKind::SwitchStatementWithDefault);
+ MOZ_TRY(checkFields(kind, fields, { BinField::Discriminant, BinField::PreDefaultCases, BinField::DefaultCase, BinField::PostDefaultCases }));
+
+
+ MOZ_TRY_DECL(discriminant, parseExpression());
+
+
+ MOZ_TRY_DECL(preDefaultCases, parseListOfSwitchCase());
+
+
+ MOZ_TRY_DECL(defaultCase, parseSwitchDefault());
+
+
+ MOZ_TRY_DECL(postDefaultCases, parseListOfSwitchCase());
+
+ // Concatenate `preDefaultCase`, `defaultCase`, `postDefaultCase`
+ auto cases = preDefaultCases;
+ factory_.addList(cases, defaultCase);
+ ParseNode* iter = postDefaultCases->pn_head;
+ while (iter) {
+ ParseNode* next = iter->pn_next;
+ factory_.addList(cases, iter);
+ iter = next;
+ }
+ TRY_DECL(scope, factory_.newLexicalScope(nullptr, cases));
+ TRY_DECL(result, factory_.newSwitchStatement(start, discriminant, scope));return result;
+}
+
+
+/*
+ interface TemplateElement : Node {
+ string rawValue;
+ }
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseTemplateElement()
+{
+ BinKind kind;
+ BinFields fields(cx_);
+ AutoTaggedTuple guard(*tokenizer_);
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+ const auto start = tokenizer_->offset();
+
+ MOZ_TRY_DECL(result, parseInterfaceTemplateElement(start, kind, fields));
+ TRY(guard.done());
+
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseInterfaceTemplateElement(const size_t start, const BinKind kind, const BinFields& fields)
+{
+ return raiseError("FIXME: Not implemented yet (TemplateElement)");
+}
+
+
+/*
+ interface TemplateExpression : Node {
+ Expression? tag;
+ FrozenArray<(Expression or TemplateElement)> elements;
+ }
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseTemplateExpression()
+{
+ BinKind kind;
+ BinFields fields(cx_);
+ AutoTaggedTuple guard(*tokenizer_);
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+ const auto start = tokenizer_->offset();
+
+ MOZ_TRY_DECL(result, parseInterfaceTemplateExpression(start, kind, fields));
+ TRY(guard.done());
+
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseInterfaceTemplateExpression(const size_t start, const BinKind kind, const BinFields& fields)
+{
+ return raiseError("FIXME: Not implemented yet (TemplateExpression)");
+}
+
+
+/*
+ interface ThisExpression : Node {
+ }
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseThisExpression()
+{
+ BinKind kind;
+ BinFields fields(cx_);
+ AutoTaggedTuple guard(*tokenizer_);
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+ const auto start = tokenizer_->offset();
+
+ MOZ_TRY_DECL(result, parseInterfaceThisExpression(start, kind, fields));
+ TRY(guard.done());
+
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseInterfaceThisExpression(const size_t start, const BinKind kind, const BinFields& fields)
+{
+ MOZ_ASSERT(kind == BinKind::ThisExpression);
+ MOZ_TRY(checkFields0(kind, fields));
+
+ if (parseContext_->isFunctionBox())
+ parseContext_->functionBox()->usesThis = true;
+
+ TokenPos pos = tokenizer_->pos(start);
+ ParseNode* thisName(nullptr);
+ if (parseContext_->sc()->thisBinding() == ThisBinding::Function)
+ TRY_VAR(thisName, factory_.newName(cx_->names().dotThis, pos, cx_));
+
+ TRY_DECL(result, factory_.newThisLiteral(pos, thisName));return result;
+}
+
+
+/*
+ interface ThrowStatement : Node {
+ Expression expression;
+ }
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseThrowStatement()
+{
+ BinKind kind;
+ BinFields fields(cx_);
+ AutoTaggedTuple guard(*tokenizer_);
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+ const auto start = tokenizer_->offset();
+
+ MOZ_TRY_DECL(result, parseInterfaceThrowStatement(start, kind, fields));
+ TRY(guard.done());
+
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseInterfaceThrowStatement(const size_t start, const BinKind kind, const BinFields& fields)
+{
+ MOZ_ASSERT(kind == BinKind::ThrowStatement);
+ MOZ_TRY(checkFields(kind, fields, { BinField::Expression }));
+
+
+ MOZ_TRY_DECL(expression, parseExpression());
+
+ TRY_DECL(result, factory_.newThrowStatement(expression, tokenizer_->pos(start)));return result;
+}
+
+
+/*
+ interface TryCatchStatement : Node {
+ Block body;
+ CatchClause catchClause;
+ }
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseTryCatchStatement()
+{
+ BinKind kind;
+ BinFields fields(cx_);
+ AutoTaggedTuple guard(*tokenizer_);
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+ const auto start = tokenizer_->offset();
+
+ MOZ_TRY_DECL(result, parseInterfaceTryCatchStatement(start, kind, fields));
+ TRY(guard.done());
+
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseInterfaceTryCatchStatement(const size_t start, const BinKind kind, const BinFields& fields)
+{
+ MOZ_ASSERT(kind == BinKind::TryCatchStatement);
+ MOZ_TRY(checkFields(kind, fields, { BinField::Body, BinField::CatchClause }));
+
+ ParseNode* body;
+ {
+ ParseContext::Statement stmt(parseContext_, StatementKind::Try);
+ ParseContext::Scope scope(cx_, parseContext_, usedNames_);
+ TRY(scope.init(parseContext_));
+ MOZ_TRY_VAR(body, parseBlock());
+
+ }
+
+
+ MOZ_TRY_DECL(catchClause, parseCatchClause());
+
+ TRY_DECL(result, factory_.newTryStatement(start, body, catchClause, /* finally = */ nullptr));return result;
+}
+
+
+/*
+ interface TryFinallyStatement : Node {
+ Block body;
+ CatchClause? catchClause;
+ Block finalizer;
+ }
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseTryFinallyStatement()
+{
+ BinKind kind;
+ BinFields fields(cx_);
+ AutoTaggedTuple guard(*tokenizer_);
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+ const auto start = tokenizer_->offset();
+
+ MOZ_TRY_DECL(result, parseInterfaceTryFinallyStatement(start, kind, fields));
+ TRY(guard.done());
+
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseInterfaceTryFinallyStatement(const size_t start, const BinKind kind, const BinFields& fields)
+{
+ MOZ_ASSERT(kind == BinKind::TryFinallyStatement);
+ MOZ_TRY(checkFields(kind, fields, { BinField::Body, BinField::CatchClause, BinField::Finalizer }));
+
+ ParseNode* body;
+ {
+ ParseContext::Statement stmt(parseContext_, StatementKind::Try);
+ ParseContext::Scope scope(cx_, parseContext_, usedNames_);
+ TRY(scope.init(parseContext_));
+ MOZ_TRY_VAR(body, parseBlock());
+
+ }
+
+
+ MOZ_TRY_DECL(catchClause, parseOptionalCatchClause());
+
+ ParseNode* finalizer;
+ {
+ ParseContext::Statement stmt(parseContext_, StatementKind::Finally);
+ ParseContext::Scope scope(cx_, parseContext_, usedNames_);
+ TRY(scope.init(parseContext_));
+ MOZ_TRY_VAR(finalizer, parseBlock());
+
+ }
+
+ TRY_DECL(result, factory_.newTryStatement(start, body, catchClause, finalizer));return result;
+}
+
+
+/*
+ interface UnaryExpression : Node {
+ UnaryOperator operator;
+ Expression operand;
+ }
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseUnaryExpression()
+{
+ BinKind kind;
+ BinFields fields(cx_);
+ AutoTaggedTuple guard(*tokenizer_);
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+ const auto start = tokenizer_->offset();
+
+ MOZ_TRY_DECL(result, parseInterfaceUnaryExpression(start, kind, fields));
+ TRY(guard.done());
+
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseInterfaceUnaryExpression(const size_t start, const BinKind kind, const BinFields& fields)
+{
+ MOZ_ASSERT(kind == BinKind::UnaryExpression);
+ MOZ_TRY(checkFields(kind, fields, { BinField::Operator, BinField::Operand }));
+
+
+ MOZ_TRY_DECL(operator_, parseUnaryOperator());
+
+
+ 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;
+ }
+ }
+ TRY_DECL(result, factory_.newUnary(pnk, start, operand));return result;
+}
+
+
+/*
+ interface UpdateExpression : Node {
+ bool isPrefix;
+ UpdateOperator operator;
+ SimpleAssignmentTarget operand;
+ }
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseUpdateExpression()
+{
+ BinKind kind;
+ BinFields fields(cx_);
+ AutoTaggedTuple guard(*tokenizer_);
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+ const auto start = tokenizer_->offset();
+
+ MOZ_TRY_DECL(result, parseInterfaceUpdateExpression(start, kind, fields));
+ TRY(guard.done());
+
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseInterfaceUpdateExpression(const size_t start, const BinKind kind, const BinFields& fields)
+{
+ MOZ_ASSERT(kind == BinKind::UpdateExpression);
+ MOZ_TRY(checkFields(kind, fields, { BinField::IsPrefix, BinField::Operator, BinField::Operand }));
+
+
+ MOZ_TRY_DECL(isPrefix, readBool());
+
+
+ MOZ_TRY_DECL(operator_, parseUpdateOperator());
+
+
+ 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;
+ }
+ TRY_DECL(result, factory_.newUnary(pnk, start, operand));return result;
+}
+
+
+/*
+ interface VariableDeclaration : Node {
+ VariableDeclarationKind kind;
+ FrozenArray<VariableDeclarator> declarators;
+ }
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseVariableDeclaration()
+{
+ BinKind kind;
+ BinFields fields(cx_);
+ AutoTaggedTuple guard(*tokenizer_);
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+ const auto start = tokenizer_->offset();
+
+ MOZ_TRY_DECL(result, parseInterfaceVariableDeclaration(start, kind, fields));
+ TRY(guard.done());
+
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseInterfaceVariableDeclaration(const size_t start, const BinKind kind, const BinFields& fields)
+{
+ MOZ_ASSERT(kind == BinKind::VariableDeclaration);
+ MOZ_TRY(checkFields(kind, fields, { BinField::Kind, BinField::Declarators }));
+ AutoVariableDeclarationKind kindGuard(this);
+
+
+ MOZ_TRY_DECL(kind_, parseVariableDeclarationKind());
+ // Restored by `kindGuard`.
+ variableDeclarationKind = kind_;
+
+
+ MOZ_TRY_DECL(declarators, parseListOfVariableDeclarator());
+
+ // By specification, the list may not be empty.
+ if (declarators->pn_count == 0)
+ return raiseEmpty("VariableDeclaration");
+
+ ParseNodeKind pnk;
+ switch (kind_) {
+ case VariableDeclarationKind::Var:
+ pnk = ParseNodeKind::Var;
+ break;
+ case VariableDeclarationKind::Let:
+ pnk = ParseNodeKind::Let;
+ break;
+ case VariableDeclarationKind::Const:
+ pnk = ParseNodeKind::Const;
+ break;
+ }
+ declarators->setKind(pnk);
+ auto result = declarators;return result;
+}
+
+
+/*
+ interface VariableDeclarator : Node {
+ Binding binding;
+ Expression? init;
+ }
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseVariableDeclarator()
+{
+ BinKind kind;
+ BinFields fields(cx_);
+ AutoTaggedTuple guard(*tokenizer_);
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+ const auto start = tokenizer_->offset();
+
+ MOZ_TRY_DECL(result, parseInterfaceVariableDeclarator(start, kind, fields));
+ TRY(guard.done());
+
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseInterfaceVariableDeclarator(const size_t start, const BinKind kind, const BinFields& fields)
+{
+ MOZ_ASSERT(kind == BinKind::VariableDeclarator);
+ MOZ_TRY(checkFields(kind, fields, { BinField::Binding, BinField::Init }));
+
+
+ MOZ_TRY_DECL(binding, parseBinding());
+
+
+ MOZ_TRY_DECL(init, parseOptionalExpression());
+
+ ParseNode* result;
+ if (binding->isKind(ParseNodeKind::Name)) {
+ // `var foo [= bar]``
+ MOZ_TRY(checkBinding(binding->pn_atom->asPropertyName()));
+
+ TRY_VAR(result, factory_.newName(binding->pn_atom->asPropertyName(), tokenizer_->pos(start), cx_));
+ if (init)
+ result->pn_expr = 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");
+ TRY_VAR(result, factory_.newAssignment(ParseNodeKind::Assign, binding, init));
+ }return result;
+}
+
+
+/*
+ interface WhileStatement : Node {
+ Expression test;
+ Statement body;
+ }
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseWhileStatement()
+{
+ BinKind kind;
+ BinFields fields(cx_);
+ AutoTaggedTuple guard(*tokenizer_);
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+ const auto start = tokenizer_->offset();
+
+ MOZ_TRY_DECL(result, parseInterfaceWhileStatement(start, kind, fields));
+ TRY(guard.done());
+
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseInterfaceWhileStatement(const size_t start, const BinKind kind, const BinFields& fields)
+{
+ MOZ_ASSERT(kind == BinKind::WhileStatement);
+ MOZ_TRY(checkFields(kind, fields, { BinField::Test, BinField::Body }));
+ ParseContext::Statement stmt(parseContext_, StatementKind::WhileLoop);
+
+ MOZ_TRY_DECL(test, parseExpression());
+
+
+ MOZ_TRY_DECL(body, parseStatement());
+
+ TRY_DECL(result, factory_.newWhileStatement(start, test, body));return result;
+}
+
+
+/*
+ interface WithStatement : Node {
+ Expression object;
+ Statement body;
+ }
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseWithStatement()
+{
+ BinKind kind;
+ BinFields fields(cx_);
+ AutoTaggedTuple guard(*tokenizer_);
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+ const auto start = tokenizer_->offset();
+
+ MOZ_TRY_DECL(result, parseInterfaceWithStatement(start, kind, fields));
+ TRY(guard.done());
+
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseInterfaceWithStatement(const size_t start, const BinKind kind, const BinFields& fields)
+{
+ MOZ_ASSERT(kind == BinKind::WithStatement);
+ MOZ_TRY(checkFields(kind, fields, { BinField::Object, BinField::Body }));
+
+
+ MOZ_TRY_DECL(object, parseExpression());
+
+
+ MOZ_TRY_DECL(body, parseStatement());
+
+ TRY_DECL(result, factory_.newWithStatement(start, object, body));return result;
+}
+
+
+/*
+ interface YieldExpression : Node {
+ Expression? expression;
+ }
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseYieldExpression()
+{
+ BinKind kind;
+ BinFields fields(cx_);
+ AutoTaggedTuple guard(*tokenizer_);
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+ const auto start = tokenizer_->offset();
+
+ MOZ_TRY_DECL(result, parseInterfaceYieldExpression(start, kind, fields));
+ TRY(guard.done());
+
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseInterfaceYieldExpression(const size_t start, const BinKind kind, const BinFields& fields)
+{
+ return raiseError("FIXME: Not implemented yet (YieldExpression)");
+}
+
+
+/*
+ interface YieldStarExpression : Node {
+ Expression expression;
+ }
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseYieldStarExpression()
+{
+ BinKind kind;
+ BinFields fields(cx_);
+ AutoTaggedTuple guard(*tokenizer_);
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+ const auto start = tokenizer_->offset();
+
+ MOZ_TRY_DECL(result, parseInterfaceYieldStarExpression(start, kind, fields));
+ TRY(guard.done());
+
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseInterfaceYieldStarExpression(const size_t start, const BinKind kind, const BinFields& fields)
+{
+ return raiseError("FIXME: Not implemented yet (YieldStarExpression)");
+}
+
+
+/*
+ interface _Null : Node {
+ }
+*/
+JS::Result<ParseNode*>
+BinASTParser::parseNull()
+{
+ BinKind kind;
+ BinFields fields(cx_);
+ AutoTaggedTuple guard(*tokenizer_);
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+ const auto start = tokenizer_->offset();
+
+ MOZ_TRY_DECL(result, parseInterfaceNull(start, kind, fields));
+ TRY(guard.done());
+
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseInterfaceNull(const size_t start, const BinKind kind, const BinFields& fields)
+{
+ return raiseError("FIXME: Not implemented yet (Null)");
+}
+
+
+
+// ----- String enums (autogenerated, by lexicographical order)
+/*
+enum BinaryOperator {
+ ",",
+ "||",
+ "&&",
+ "|",
+ "^",
+ "&",
+ "==",
+ "!=",
+ "===",
+ "!==",
+ "<",
+ "<=",
+ ">",
+ ">=",
+ "in",
+ "instanceof",
+ "<<",
+ ">>",
+ ">>>",
+ "+",
+ "-",
+ "*",
+ "/",
+ "%",
+ "**"
+};
+*/
+JS::Result<BinASTParser::BinaryOperator>
+BinASTParser::parseBinaryOperator()
+{
+ // Unoptimized implementation.
+ Chars chars((cx_));
+ MOZ_TRY(readString(chars));
+
+ if (chars == ",")
+ return BinaryOperator::Comma;
+ if (chars == "||")
+ return BinaryOperator::LogicalOr;
+ if (chars == "&&")
+ return BinaryOperator::LogicalAnd;
+ if (chars == "|")
+ return BinaryOperator::BitOr;
+ if (chars == "^")
+ return BinaryOperator::BitXor;
+ if (chars == "&")
+ return BinaryOperator::BitAnd;
+ if (chars == "==")
+ return BinaryOperator::Eq;
+ if (chars == "!=")
+ return BinaryOperator::Neq;
+ if (chars == "===")
+ return BinaryOperator::StrictEq;
+ if (chars == "!==")
+ return BinaryOperator::StrictNeq;
+ if (chars == "<")
+ return BinaryOperator::LessThan;
+ if (chars == "<=")
+ return BinaryOperator::LeqThan;
+ if (chars == ">")
+ return BinaryOperator::GreaterThan;
+ if (chars == ">=")
+ return BinaryOperator::GeqThan;
+ if (chars == "in")
+ return BinaryOperator::In;
+ if (chars == "instanceof")
+ return BinaryOperator::Instanceof;
+ if (chars == "<<")
+ return BinaryOperator::Lsh;
+ if (chars == ">>")
+ return BinaryOperator::Rsh;
+ if (chars == ">>>")
+ return BinaryOperator::Ursh;
+ if (chars == "+")
+ return BinaryOperator::Plus;
+ if (chars == "-")
+ return BinaryOperator::Minus;
+ if (chars == "*")
+ return BinaryOperator::Mul;
+ if (chars == "/")
+ return BinaryOperator::Div;
+ if (chars == "%")
+ return BinaryOperator::Mod;
+ if (chars == "**")
+ return BinaryOperator::Pow;
+
+ return raiseInvalidEnum("BinaryOperator", chars);
+}
+
+/*
+enum CompoundAssignmentOperator {
+ "+=",
+ "-=",
+ "*=",
+ "/=",
+ "%=",
+ "**=",
+ "<<=",
+ ">>=",
+ ">>>=",
+ "|=",
+ "^=",
+ "&="
+};
+*/
+JS::Result<BinASTParser::CompoundAssignmentOperator>
+BinASTParser::parseCompoundAssignmentOperator()
+{
+ // Unoptimized implementation.
+ Chars chars((cx_));
+ MOZ_TRY(readString(chars));
+
+ if (chars == "+=")
+ return CompoundAssignmentOperator::PlusAssign;
+ if (chars == "-=")
+ return CompoundAssignmentOperator::MinusAssign;
+ if (chars == "*=")
+ return CompoundAssignmentOperator::MulAssign;
+ if (chars == "/=")
+ return CompoundAssignmentOperator::DivAssign;
+ if (chars == "%=")
+ return CompoundAssignmentOperator::ModAssign;
+ if (chars == "**=")
+ return CompoundAssignmentOperator::PowAssign;
+ if (chars == "<<=")
+ return CompoundAssignmentOperator::LshAssign;
+ if (chars == ">>=")
+ return CompoundAssignmentOperator::RshAssign;
+ if (chars == ">>>=")
+ return CompoundAssignmentOperator::UrshAssign;
+ if (chars == "|=")
+ return CompoundAssignmentOperator::BitOrAssign;
+ if (chars == "^=")
+ return CompoundAssignmentOperator::BitXorAssign;
+ if (chars == "&=")
+ return CompoundAssignmentOperator::BitAndAssign;
+
+ return raiseInvalidEnum("CompoundAssignmentOperator", chars);
+}
+
+/*
+enum UnaryOperator {
+ "+",
+ "-",
+ "!",
+ "~",
+ "typeof",
+ "void",
+ "delete"
+};
+*/
+JS::Result<BinASTParser::UnaryOperator>
+BinASTParser::parseUnaryOperator()
+{
+ // Unoptimized implementation.
+ Chars chars((cx_));
+ MOZ_TRY(readString(chars));
+
+ if (chars == "+")
+ return UnaryOperator::Plus;
+ if (chars == "-")
+ return UnaryOperator::Minus;
+ if (chars == "!")
+ return UnaryOperator::Not;
+ if (chars == "~")
+ return UnaryOperator::BitNot;
+ if (chars == "typeof")
+ return UnaryOperator::Typeof;
+ if (chars == "void")
+ return UnaryOperator::Void;
+ if (chars == "delete")
+ return UnaryOperator::Delete;
+
+ return raiseInvalidEnum("UnaryOperator", chars);
+}
+
+/*
+enum UpdateOperator {
+ "++",
+ "--"
+};
+*/
+JS::Result<BinASTParser::UpdateOperator>
+BinASTParser::parseUpdateOperator()
+{
+ // Unoptimized implementation.
+ Chars chars((cx_));
+ MOZ_TRY(readString(chars));
+
+ if (chars == "++")
+ return UpdateOperator::Incr;
+ if (chars == "--")
+ return UpdateOperator::Decr;
+
+ return raiseInvalidEnum("UpdateOperator", chars);
+}
+
+/*
+enum VariableDeclarationKind {
+ "var",
+ "let",
+ "const"
+};
+*/
+JS::Result<BinASTParser::VariableDeclarationKind>
+BinASTParser::parseVariableDeclarationKind()
+{
+ // Unoptimized implementation.
+ Chars chars((cx_));
+ MOZ_TRY(readString(chars));
+
+ if (chars == "var")
+ return VariableDeclarationKind::Var;
+ if (chars == "let")
+ return VariableDeclarationKind::Let;
+ if (chars == "const")
+ return VariableDeclarationKind::Const;
+
+ return raiseInvalidEnum("VariableDeclarationKind", chars);
+}
+
+
+
+// ----- Lists (autogenerated, by lexicographical order)
+
+JS::Result<ParseNode*>
+BinASTParser::parseArguments()
+{
+ uint32_t length;
+ AutoList guard(*tokenizer_);
+
+ const auto start = tokenizer_->offset();
+ TRY(tokenizer_->enterList(length, guard));
+ TRY_DECL(result, factory_.newList(ParseNodeKind::ParamsBody, tokenizer_->pos(start)));
+
+ for (uint32_t i = 0; i < length; ++i) {
+ MOZ_TRY_DECL(item, parseSpreadElementOrExpression());
+ factory_.addList(/* list = */ result, /* child = */ item);
+ }
+
+ TRY(guard.done());
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseListOfAssignmentTargetOrAssignmentTargetWithInitializer()
+{
+ return raiseError("FIXME: Not implemented yet (ListOfAssignmentTargetOrAssignmentTargetWithInitializer)");
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseListOfAssignmentTargetProperty()
+{
+ return raiseError("FIXME: Not implemented yet (ListOfAssignmentTargetProperty)");
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseListOfBindingProperty()
+{
+ return raiseError("FIXME: Not implemented yet (ListOfBindingProperty)");
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseListOfClassElement()
+{
+ return raiseError("FIXME: Not implemented yet (ListOfClassElement)");
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseListOfDirective()
+{
+ uint32_t length;
+ AutoList guard(*tokenizer_);
+
+ const auto start = tokenizer_->offset();
+ TRY(tokenizer_->enterList(length, guard));
+ TRY_DECL(result, factory_.newStatementList(tokenizer_->pos(start)));
+
+ for (uint32_t i = 0; i < length; ++i) {
+ MOZ_TRY_DECL(item, parseDirective());
+ factory_.addStatementToList(result, item);
+ }
+
+ TRY(guard.done());
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseListOfExportFromSpecifier()
+{
+ return raiseError("FIXME: Not implemented yet (ListOfExportFromSpecifier)");
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseListOfExportLocalSpecifier()
+{
+ return raiseError("FIXME: Not implemented yet (ListOfExportLocalSpecifier)");
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseListOfExpressionOrTemplateElement()
+{
+ return raiseError("FIXME: Not implemented yet (ListOfExpressionOrTemplateElement)");
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseListOfIdentifierName()
+{
+ return raiseError("FIXME: Not implemented yet (ListOfIdentifierName)");
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseListOfImportDeclarationOrExportDeclarationOrStatement()
+{
+ return raiseError("FIXME: Not implemented yet (ListOfImportDeclarationOrExportDeclarationOrStatement)");
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseListOfImportSpecifier()
+{
+ return raiseError("FIXME: Not implemented yet (ListOfImportSpecifier)");
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseListOfObjectProperty()
+{
+ uint32_t length;
+ AutoList guard(*tokenizer_);
+
+ const auto start = tokenizer_->offset();
+ TRY(tokenizer_->enterList(length, guard));
+ TRY_DECL(result, factory_.newObjectLiteral(start));
+
+ for (uint32_t i = 0; i < length; ++i) {
+ MOZ_TRY_DECL(item, parseObjectProperty());
+ result->appendWithoutOrderAssumption(item);
+ }
+
+ TRY(guard.done());
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseListOfOptionalBindingOrBindingWithInitializer()
+{
+ return raiseError("FIXME: Not implemented yet (ListOfOptionalBindingOrBindingWithInitializer)");
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseListOfOptionalSpreadElementOrExpression()
+{
+ uint32_t length;
+ AutoList guard(*tokenizer_);
+
+ const auto start = tokenizer_->offset();
+ TRY(tokenizer_->enterList(length, guard));
+ TRY_DECL(result, factory_.newArrayLiteral(start));
+
+ for (uint32_t i = 0; i < length; ++i) {
+ MOZ_TRY_DECL(item, parseOptionalSpreadElementOrExpression());
+ if (item)
+ factory_.addArrayElement(result, item); // Infallible.
+ else
+ TRY(factory_.addElision(result, tokenizer_->pos(start)));
+ }
+
+ TRY(guard.done());
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseListOfParameter()
+{
+ uint32_t length;
+ AutoList guard(*tokenizer_);
+
+ const auto start = tokenizer_->offset();
+ TRY(tokenizer_->enterList(length, guard));
+ ParseNode* result = new_<ListNode>(ParseNodeKind::ParamsBody, tokenizer_->pos(start));
+
+ for (uint32_t i = 0; i < length; ++i) {
+ MOZ_TRY_DECL(item, parseParameter());
+ factory_.addList(/* list = */ result, /* item = */ item);
+ }
+
+ TRY(guard.done());
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseListOfStatement()
+{
+ uint32_t length;
+ AutoList guard(*tokenizer_);
+
+ const auto start = tokenizer_->offset();
+ TRY(tokenizer_->enterList(length, guard));
+ TRY_DECL(result, factory_.newStatementList(tokenizer_->pos(start)));
+
+ for (uint32_t i = 0; i < length; ++i) {
+ MOZ_TRY_DECL(item, parseStatement());
+ factory_.addStatementToList(result, item);
+ }
+
+ TRY(guard.done());
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseListOfSwitchCase()
+{
+ uint32_t length;
+ AutoList guard(*tokenizer_);
+
+ const auto start = tokenizer_->offset();
+ TRY(tokenizer_->enterList(length, guard));
+ TRY_DECL(result, factory_.newStatementList(tokenizer_->pos(start)));
+
+ for (uint32_t i = 0; i < length; ++i) {
+ MOZ_TRY_DECL(item, parseSwitchCase());
+ factory_.addCaseStatementToList(result, item);
+ }
+
+ TRY(guard.done());
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseListOfVariableDeclarator()
+{
+ uint32_t length;
+ AutoList guard(*tokenizer_);
+
+ const auto start = tokenizer_->offset();
+ TRY(tokenizer_->enterList(length, guard));
+ TRY_DECL(result, factory_.newDeclarationList(ParseNodeKind::Const /*Placeholder*/,
+ tokenizer_->pos(start)));
+
+ for (uint32_t i = 0; i < length; ++i) {
+ MOZ_TRY_DECL(item, parseVariableDeclarator());
+ result->appendWithoutOrderAssumption(item);
+ }
+
+ TRY(guard.done());
+ return result;
+}
+
+
+ // ----- Default values (by lexicographical order)
+JS::Result<Ok>
+BinASTParser::parseOptionalAssertedBlockScope()
+{
+ BinKind kind;
+ BinFields fields((cx_));
+ AutoTaggedTuple guard(*tokenizer_);
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+ Ok result;
+ if (kind == BinKind::_Null) {
+ result = Ok();
+ } else {
+ const auto start = tokenizer_->offset();
+ MOZ_TRY_VAR(result, parseInterfaceAssertedBlockScope(start, kind, fields));
+ }
+ TRY(guard.done());
+
+ return result;
+}
+
+JS::Result<Ok>
+BinASTParser::parseOptionalAssertedParameterScope()
+{
+ BinKind kind;
+ BinFields fields((cx_));
+ AutoTaggedTuple guard(*tokenizer_);
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+ Ok result;
+ if (kind == BinKind::_Null) {
+ result = Ok();
+ } else {
+ const auto start = tokenizer_->offset();
+ MOZ_TRY_VAR(result, parseInterfaceAssertedParameterScope(start, kind, fields));
+ }
+ TRY(guard.done());
+
+ return result;
+}
+
+JS::Result<Ok>
+BinASTParser::parseOptionalAssertedVarScope()
+{
+ BinKind kind;
+ BinFields fields((cx_));
+ AutoTaggedTuple guard(*tokenizer_);
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+ Ok result;
+ if (kind == BinKind::_Null) {
+ result = Ok();
+ } else {
+ const auto start = tokenizer_->offset();
+ MOZ_TRY_VAR(result, parseInterfaceAssertedVarScope(start, kind, fields));
+ }
+ TRY(guard.done());
+
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseOptionalAssignmentTarget()
+{
+ BinKind kind;
+ BinFields fields((cx_));
+ AutoTaggedTuple guard(*tokenizer_);
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+ ParseNode* result;
+ if (kind == BinKind::_Null) {
+ result = nullptr;
+ } else {
+ const auto start = tokenizer_->offset();
+ MOZ_TRY_VAR(result, parseSumAssignmentTarget(start, kind, fields));
+ }
+ TRY(guard.done());
+
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseOptionalBinding()
+{
+ BinKind kind;
+ BinFields fields((cx_));
+ AutoTaggedTuple guard(*tokenizer_);
+
+ 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));
+ }
+ TRY(guard.done());
+
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseOptionalBindingIdentifier()
+{
+ BinKind kind;
+ BinFields fields((cx_));
+ AutoTaggedTuple guard(*tokenizer_);
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+ ParseNode* result;
+ if (kind == BinKind::_Null) {
+ result = nullptr;
+ } else {
+ const auto start = tokenizer_->offset();
+ MOZ_TRY_VAR(result, parseInterfaceBindingIdentifier(start, kind, fields));
+ }
+ TRY(guard.done());
+
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseOptionalBindingOrBindingWithInitializer()
+{
+ BinKind kind;
+ BinFields fields((cx_));
+ AutoTaggedTuple guard(*tokenizer_);
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+ ParseNode* result;
+ if (kind == BinKind::_Null) {
+ result = nullptr;
+ } else {
+ const auto start = tokenizer_->offset();
+ MOZ_TRY_VAR(result, parseSumBindingOrBindingWithInitializer(start, kind, fields));
+ }
+ TRY(guard.done());
+
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseOptionalCatchClause()
+{
+ BinKind kind;
+ BinFields fields((cx_));
+ AutoTaggedTuple guard(*tokenizer_);
+
+ TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
+ ParseNode* result;
+ if (kind == BinKind::_Null) {
+ result = nullptr;
+ } else {
+ const auto start = tokenizer_->offset();
+ MOZ_TRY_VAR(result, parseInterfaceCatchClause(start, kind, fields));
+ }
+ TRY(guard.done());
+
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseOptionalExpression()
+{
+ BinKind kind;
+ BinFields fields((cx_));
+ AutoTaggedTuple guard(*tokenizer_);
+
+ 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));
+ }
+ TRY(guard.done());
+
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseOptionalIdentifierName()
+{
+ RootedAtom string((cx_));
+ MOZ_TRY(readMaybeString(&string));
+
+
+
+ return raiseError("FIXME: Not implemented yet (OptionalIdentifierName)");
+
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseOptionalLabel()
+{
+ RootedAtom string((cx_));
+ MOZ_TRY(readMaybeString(&string));
+
+
+
+ return raiseError("FIXME: Not implemented yet (OptionalLabel)");
+
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseOptionalSpreadElementOrExpression()
+{
+ BinKind kind;
+ BinFields fields((cx_));
+ AutoTaggedTuple guard(*tokenizer_);
+
+ 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));
+ }
+ TRY(guard.done());
+
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseOptionalStatement()
+{
+ BinKind kind;
+ BinFields fields((cx_));
+ AutoTaggedTuple guard(*tokenizer_);
+
+ 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));
+ }
+ TRY(guard.done());
+
+ return result;
+}
+
+JS::Result<ParseNode*>
+BinASTParser::parseOptionalVariableDeclarationOrExpression()
+{
+ BinKind kind;
+ BinFields fields((cx_));
+ AutoTaggedTuple guard(*tokenizer_);
+
+ 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));
+ }
+ TRY(guard.done());
+
+ return result;
+}
+
+
+
+#undef TRY
+#undef TRY_VAR
+#undef TRY_DECL
+#undef MOZ_TRY_DECL
+} // namespace frontend
+} // namespace js
--- a/js/src/frontend/BinSource.cpp
+++ b/js/src/frontend/BinSource.cpp
@@ -115,45 +115,17 @@ using AutoList = BinTokenReaderTester::A
using AutoTaggedTuple = BinTokenReaderTester::AutoTaggedTuple;
using AutoTuple = BinTokenReaderTester::AutoTuple;
using BinFields = BinTokenReaderTester::BinFields;
using Chars = BinTokenReaderTester::Chars;
using NameBag = GCHashSet<JSString*>;
using Names = GCVector<JSString*, 8>;
using UsedNamePtr = UsedNameTracker::UsedNameMap::Ptr;
-namespace {
- // Compare a bunch of `uint8_t` values (as returned by the tokenizer_) with
- // a string literal (and ONLY a string literal).
- template<size_t N>
- bool operator==(const Chars& left, const char (&right)[N]) {
- return BinTokenReaderTester::equals(left, right);
- }
-
- bool isMethod(BinKind kind) {
- switch (kind) {
- case BinKind::ObjectMethod:
- case BinKind::ObjectGetter:
- case BinKind::ObjectSetter:
- return true;
- default:
- return false;
- }
- }
-
-#if defined(DEBUG)
- bool isMethodOrFunction(BinKind kind) {
- if (isMethod(kind))
- return true;
- if (kind == BinKind::FunctionExpression || kind == BinKind::FunctionDeclaration)
- return true;
- return false;
- }
-#endif // defined(DEBUG)
-}
+// ------------- Toplevel constructions
JS::Result<ParseNode*>
BinASTParser::parse(const Vector<uint8_t>& data)
{
return parse(data.begin(), data.length());
}
JS::Result<ParseNode*>
@@ -187,181 +159,152 @@ BinASTParser::parseAux(const uint8_t* st
Maybe<GlobalScope::Data*> bindings = NewGlobalScopeData(cx_, varScope, alloc_, parseContext_);
if (!bindings)
return cx_->alreadyReportedError();
globalsc.bindings = *bindings;
return result; // Magic conversion to Ok.
}
-Result<ParseNode*>
-BinASTParser::parseProgram()
+JS::Result<FunctionBox*>
+BinASTParser::buildFunctionBox(GeneratorKind generatorKind, FunctionAsyncKind functionAsyncKind)
{
- BinKind kind;
- BinFields fields(cx_);
- AutoTaggedTuple guard(*tokenizer_);
+ // Allocate the function before walking down the tree.
+ RootedFunction fun(cx_);
+ TRY_VAR(fun, NewFunctionWithProto(cx_,
+ /* native = */ nullptr,
+ /* nargs placeholder = */ 0,
+ JSFunction::INTERPRETED_NORMAL,
+ /* enclosingEnv = */ nullptr,
+ /* name (placeholder) = */ nullptr,
+ /* proto = */ nullptr,
+ gc::AllocKind::FUNCTION,
+ TenuredObject
+ ));
+ TRY_DECL(funbox, alloc_.new_<FunctionBox>(cx_,
+ traceListHead_,
+ fun,
+ /* toStringStart = */ 0,
+ Directives(parseContext_),
+ /* extraWarning = */ false,
+ generatorKind,
+ functionAsyncKind));
- TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
- if (kind != BinKind::Program)
- return this->raiseInvalidKind("Program", kind);
-
- ParseNode* result;
- MOZ_TRY_VAR(result, parseBlockStatementAux(kind, fields));
-
- TRY(guard.done());
- return result;
+ traceListHead_ = funbox;
+ FunctionSyntaxKind syntax = PrimaryExpression; // FIXME - What if we're assigning?
+ // FIXME: The only thing we need to know is whether this is a
+ // ClassConstructor/DerivedClassConstructor
+ funbox->initWithEnclosingParseContext(parseContext_, syntax);
+ return funbox;
}
JS::Result<ParseNode*>
-BinASTParser::parseBlockStatement()
+BinASTParser::buildFunction(const size_t start, const BinKind kind, ParseNode* name,
+ ParseNode* params, ParseNode* body, FunctionBox* funbox)
{
- BinKind kind;
- BinFields fields(cx_);
- AutoTaggedTuple guard(*tokenizer_);
+ TokenPos pos = tokenizer_->pos(start);
+
+ RootedAtom atom((cx_));
+ if (name)
+ atom = name->name();
+
+
+ funbox->function()->setArgCount(uint16_t(params->pn_count));
+ funbox->function()->initAtom(atom);
+
+ // ParseNode represents the body as concatenated after the params.
+ params->appendWithoutOrderAssumption(body);
- TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
- ParseNode* result(nullptr);
- switch (kind) {
- default:
- return raiseInvalidKind("BlockStatement", kind);
- case BinKind::BlockStatement:
- MOZ_TRY_VAR(result, parseBlockStatementAux(kind, fields));
- break;
+ TRY_DECL(result, kind == BinKind::FunctionDeclaration
+ ? factory_.newFunctionStatement(pos)
+ : factory_.newFunctionExpression(pos));
+
+ factory_.setFunctionBox(result, 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);
+ TRY(funScope.addDeclaredName(parseContext_, p, dotThis, DeclarationKind::Var,
+ DeclaredNameInfo::npos));
+ funbox->setHasThisBinding();
}
+ TRY_DECL(bindings,
+ NewFunctionScopeData(cx_, parseContext_->functionScope(),
+ /* hasParameterExprs = */ false, alloc_, parseContext_));
+
+ funbox->functionScopeBindings().set(*bindings);
+
+ return result;
+}
+
+JS::Result<Ok>
+BinASTParser::parseAndUpdateCapturedNames()
+{
+ // For the moment, we do not attempt to validate the list of captured names.
+ AutoList guard(*tokenizer_);
+ uint32_t length = 0;
+
+ TRY(tokenizer_->enterList(length, guard));
+ RootedAtom name(cx_);
+ for (uint32_t i = 0; i < length; ++i) {
+ name = nullptr;
+
+ MOZ_TRY(readString(&name));
+ }
TRY(guard.done());
- return result;
+ return Ok();
}
JS::Result<Ok>
BinASTParser::parseAndUpdateScopeNames(ParseContext::Scope& scope, DeclarationKind kind)
{
AutoList guard(*tokenizer_);
uint32_t length = 0;
TRY(tokenizer_->enterList(length, guard));
RootedAtom name(cx_);
for (uint32_t i = 0; i < length; ++i) {
name = nullptr;
MOZ_TRY(readString(&name));
auto ptr = scope.lookupDeclaredNameForAdd(name);
- if (ptr) {
- if (kind == DeclarationKind::Let || kind == DeclarationKind::Const)
- return raiseError("Variable redeclaration");
-
-#if defined(DEBUG)
- // FIXME: Fix binjs-ref.
- fprintf(stderr, "Weird: `var` redeclaration. Check encoder: ");
- name->dump();
- fprintf(stderr, "\n");
-#endif // defined(DEBUG)
- continue;
- }
+ if (ptr)
+ return raiseError("Variable redeclaration");
TRY(scope.addDeclaredName(parseContext_, ptr, name.get(), kind, tokenizer_->offset()));
}
TRY(guard.done());
return Ok();
}
JS::Result<Ok>
-BinASTParser::parseAndUpdateCurrentScope()
+BinASTParser::checkBinding(JSAtom* name)
{
- return parseAndUpdateScope(parseContext_->varScope(), *parseContext_->innermostScope());
-}
-
-JS::Result<Ok>
-BinASTParser::parseAndUpdateScope(ParseContext::Scope& varScope, ParseContext::Scope& letScope)
-{
- BinKind kind;
- BinFields fields(cx_);
- AutoTaggedTuple guard(*tokenizer_);
+ // Check that the variable appears in the corresponding scope.
+ ParseContext::Scope& scope =
+ variableDeclarationKind == VariableDeclarationKind::Var
+ ? parseContext_->varScope()
+ : *parseContext_->innermostScope();
- TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
- switch (kind) {
- default:
- return raiseInvalidKind("Scope", kind);
- case BinKind::BINJS_Scope:
- for (auto field : fields) {
- switch (field) {
- case BinField::BINJS_HasDirectEval:
- MOZ_TRY(readBool()); // Currently ignored.
- break;
- case BinField::BINJS_LetDeclaredNames:
- MOZ_TRY(parseAndUpdateScopeNames(letScope, DeclarationKind::Let));
- break;
- case BinField::BINJS_ConstDeclaredNames:
- MOZ_TRY(parseAndUpdateScopeNames(letScope, DeclarationKind::Const));
- break;
- case BinField::BINJS_VarDeclaredNames:
- MOZ_TRY(parseAndUpdateScopeNames(varScope, DeclarationKind::Var));
- break;
- case BinField::BINJS_CapturedNames: {
- Rooted<Maybe<Names>> names(cx_); //FIXME: Currently ignored.
- MOZ_TRY(parseStringList(&names));
- break;
- }
- default:
- return raiseInvalidField("Scope", field);
- }
- }
- break;
- }
+ auto ptr = scope.lookupDeclaredName(name->asPropertyName());
+ if (!ptr)
+ return raiseMissingVariableInAssertedScope(name);
- TRY(guard.done());
return Ok();
}
JS::Result<ParseNode*>
-BinASTParser::parseBlockStatementAux(const BinKind kind, const BinFields& fields)
-{
- ParseContext::Statement stmt(parseContext_, StatementKind::Block);
- ParseContext::Scope scope(cx_, parseContext_, usedNames_);
- TRY(scope.init(parseContext_));
-
- ParseNode* body(nullptr);
- ParseNode* directives(nullptr); // FIXME: Largely ignored
-
- for (auto field : fields) {
- switch (field) {
- case BinField::BINJS_Scope:
- MOZ_TRY(parseAndUpdateCurrentScope());
- break;
- case BinField::Body:
- MOZ_TRY_VAR(body, parseStatementList());
- break;
- case BinField::Directives:
- if (kind != BinKind::Program)
- return raiseInvalidField("BlockStatement", field);
- MOZ_TRY_VAR(directives, parseDirectiveList());
- break;
- default:
- return raiseInvalidField("BlockStatement", field);
- }
- }
-
- // In case of absent optional fields, inject default values.
- if (!body)
- TRY_VAR(body, factory_.newStatementList(tokenizer_->pos()));
-
- MOZ_TRY_VAR(body, appendDirectivesToBody(body, directives));
-
- ParseNode* result;
- if (kind == BinKind::Program) {
- result = body;
- } else {
- TRY_DECL(bindings, NewLexicalScopeData(cx_, scope, alloc_, parseContext_));
- TRY_VAR(result, factory_.newLexicalScope(*bindings, body));
- }
-
- return result;
-}
-
-JS::Result<ParseNode*>
BinASTParser::appendDirectivesToBody(ParseNode* body, ParseNode* directives)
{
ParseNode* result = body;
if (directives && directives->pn_count >= 1) {
MOZ_ASSERT(directives->isArity(PN_LIST));
// Convert directive list to a list of strings.
TRY_DECL(prefix, factory_.newStatementList(directives->pn_head->pn_pos));
@@ -384,2004 +327,62 @@ BinASTParser::appendDirectivesToBody(Par
result->checkListConsistency();
#endif // defined(DEBUG)
}
return result;
}
JS::Result<Ok>
-BinASTParser::parseStringList(MutableHandle<Maybe<Names>> out)
-{
- MOZ_ASSERT(out.get().isNothing()); // Sanity check: the node must not have been parsed yet.
-
- uint32_t length;
- AutoList guard(*tokenizer_);
-
- Names result(cx_);
-
- TRY(tokenizer_->enterList(length, guard));
- if (!result.reserve(length))
- return raiseOOM();
-
- RootedAtom string(cx_);
- for (uint32_t i = 0; i < length; ++i) {
- string = nullptr;
-
- MOZ_TRY(readString(&string));
- result.infallibleAppend(Move(string)); // Checked in the call to `reserve`.
- }
-
- TRY(guard.done());
- out.set(Move(Some(Move(result))));
- return Ok();
-}
-
-JS::Result<ParseNode*>
-BinASTParser::parseStatementList()
-{
- uint32_t length;
- AutoList guard(*tokenizer_);
-
- TRY_DECL(result, factory_.newStatementList(tokenizer_->pos()));
-
- TRY(tokenizer_->enterList(length, guard));
- for (uint32_t i = 0; i < length; ++i) {
- BinKind kind;
- BinFields fields(cx_);
- AutoTaggedTuple guard(*tokenizer_);
-
- ParseNode* statement(nullptr);
-
- TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
- switch (kind) {
- case BinKind::FunctionDeclaration:
- MOZ_TRY_VAR(statement, parseFunctionAux(kind, fields));
- break;
- default:
- MOZ_TRY_VAR(statement, parseStatementAux(kind, fields));
- break;
- }
-
- TRY(guard.done());
- result->appendWithoutOrderAssumption(statement);
- }
-
- TRY(guard.done());
- return result;
-}
-
-JS::Result<ParseNode*>
-BinASTParser::parseStatement()
-{
- BinKind kind;
- BinFields fields(cx_);
- AutoTaggedTuple guard(*tokenizer_);
-
- TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
- ParseNode* result;
- MOZ_TRY_VAR(result, parseStatementAux(kind, fields));
-
- TRY(guard.done());
- return result;
-}
-
-JS::Result<ParseNode*>
-BinASTParser::parseStatementAux(const BinKind kind, const BinFields& fields)
+BinASTParser::readString(MutableHandleAtom out)
{
- const size_t start = tokenizer_->offset();
-
- ParseNode* result(nullptr);
- switch (kind) {
- case BinKind::EmptyStatement: {
- TRY_VAR(result, factory_.newEmptyStatement(tokenizer_->pos(start)));
- break;
- }
- case BinKind::BlockStatement:
- MOZ_TRY_VAR(result, parseBlockStatementAux(kind, fields));
- break;
- case BinKind::ExpressionStatement:
- MOZ_TRY_VAR(result, parseExpressionStatementAux(kind, fields));
- break;
- case BinKind::DebuggerStatement: {
- TRY_VAR(result, factory_.newDebuggerStatement(tokenizer_->pos(start)));
- break;
- }
- case BinKind::WithStatement: {
- ParseNode* body(nullptr);
- ParseNode* expr(nullptr);
- for (auto field : fields) {
- switch (field) {
- case BinField::Body:
- MOZ_TRY_VAR(body, parseStatement());
- break;
- case BinField::Object:
- MOZ_TRY_VAR(expr, parseExpression());
- break;
- default:
- return raiseInvalidField("WithStatement", field);
- }
- }
-
- if (!body)
- return raiseMissingField("WithStatement", BinField::Body);
- if (!expr)
- return raiseMissingField("WithStatement", BinField::Object);
-
- TRY_VAR(result, factory_.newWithStatement(start, expr, body));
-
- break;
- }
- case BinKind::ReturnStatement: {
- if (!parseContext_->isFunctionBox()) {
- // Return statements are permitted only inside functions.
- return raiseInvalidKind("Toplevel Statement", kind);
- }
- parseContext_->functionBox()->usesReturn = true;
-
- ParseNode* arg(nullptr);
- for (auto field : fields) {
- switch (field) {
- case BinField::Argument:
- MOZ_TRY_VAR(arg, parseExpression());
- break;
- default:
- return raiseInvalidField("ReturnStatement", field);
- }
- }
-
- TRY_VAR(result, factory_.newReturnStatement(arg, tokenizer_->pos(start)));
-
- break;
- }
- case BinKind::LabeledStatement: {
- // We check for the existence of the jump target when parsing `break label;` or `continue label;`.
- ParseContext::Statement stmt(parseContext_, StatementKind::Label);
- ParseNode* label(nullptr);
- ParseNode* body(nullptr);
-
- for (auto field : fields) {
- switch (field) {
- case BinField::Label:
- MOZ_TRY_VAR(label, parseIdentifier());
- break;
- case BinField::Body: {
- if (!label) // By order of fields, `label` MUST always be before `body` in the file.
- return raiseMissingField("LabeledStatement", BinField::Label);
- MOZ_ASSERT(label->name());
- ParseContext::LabelStatement stmt(parseContext_, label->name());
- MOZ_TRY_VAR(body, parseStatement());
- break;
- }
- default:
- return raiseInvalidField("LabeledStatement", field);
- }
- }
-
- if (!label)
- return raiseMissingField("LabeledStatement", BinField::Label);
- if (!body)
- return raiseMissingField("LabeledStatement", BinField::Body);
-
- TRY_VAR(result, factory_.newLabeledStatement(label->name(), body, start));
-
- break;
- }
-
- case BinKind::BreakStatement:
- case BinKind::ContinueStatement:
- MOZ_TRY_VAR(result, parseBreakOrContinueStatementAux(kind, fields));
- break;
-
- case BinKind::IfStatement: {
- ParseContext::Statement stmt(parseContext_, StatementKind::If);
-
- ParseNode* test(nullptr);
- ParseNode* consequent(nullptr);
- ParseNode* alternate(nullptr); // Optional
-
- for (auto field : fields) {
- switch (field) {
- case BinField::Test:
- MOZ_TRY_VAR(test, parseExpression());
- break;
- case BinField::Consequent:
- MOZ_TRY_VAR(consequent, parseStatement());
- break;
- case BinField::Alternate:
- MOZ_TRY_VAR(alternate, parseStatement());
- break;
- default:
- return raiseInvalidField("IfStatement", field);
- }
- }
-
- if (!test)
- return raiseMissingField("IfStatement", BinField::Test);
- if (!consequent)
- return raiseMissingField("IfStatement", BinField::Consequent);
-
- TRY_VAR(result, factory_.newIfStatement(start, test, consequent, alternate));
-
- break;
- }
- case BinKind::SwitchStatement: {
- ParseContext::Statement stmt(parseContext_, StatementKind::Switch);
- ParseNode* discriminant(nullptr);
- ParseNode* cases(nullptr);
-
- for (auto field : fields) {
- switch (field) {
- case BinField::Discriminant: {
- MOZ_TRY_VAR(discriminant, parseExpression());
- break;
- }
- case BinField::Cases: {
- MOZ_TRY_VAR(cases, parseSwitchCaseList());
- break;
- }
- default:
- return raiseInvalidField("SwitchStatement", field);
- }
- }
-
- if (!discriminant)
- return raiseMissingField("SwitchStatement", BinField::Discriminant);
- if (!cases) {
- TRY_VAR(cases, factory_.newStatementList(tokenizer_->pos()));
-
- TRY_VAR(cases, factory_.newLexicalScope(nullptr, cases));
- }
-
- TRY_VAR(result, factory_.newSwitchStatement(start, discriminant, cases));
-
- break;
- }
-
- case BinKind::ThrowStatement: {
- ParseNode* arg(nullptr);
- for (auto field : fields) {
- if (field != BinField::Argument)
- return raiseInvalidField("ThrowStatement", field);
-
- MOZ_TRY_VAR(arg, parseExpression());
- }
-
- if (!arg)
- return raiseMissingField("ThrowStatement", BinField::Argument);
-
- TRY_VAR(result, factory_.newThrowStatement(arg, tokenizer_->pos(start)));
-
- break;
- }
-
- case BinKind::TryStatement: {
- ParseNode* block(nullptr);
- ParseNode* handler(nullptr);
- ParseNode* finalizer(nullptr);
-
- for (auto field : fields) {
- switch (field) {
- case BinField::Block: {
- ParseContext::Statement stmt(parseContext_, StatementKind::Try);
- ParseContext::Scope scope(cx_, parseContext_, usedNames_);
- TRY(scope.init(parseContext_));
- MOZ_TRY_VAR(block, parseBlockStatement());
- break;
- }
- case BinField::Handler:
- MOZ_TRY_VAR(handler, parseCatchClause());
- break;
-
- case BinField::Finalizer: {
- ParseContext::Statement stmt(parseContext_, StatementKind::Finally);
- ParseContext::Scope scope(cx_, parseContext_, usedNames_);
- TRY(scope.init(parseContext_));
- MOZ_TRY_VAR(finalizer, parseBlockStatement());
- break;
- }
-
- default:
- return raiseInvalidField("TryStatement", field);
- }
- }
-
- if (!block)
- return raiseMissingField("TryStatement", BinField::Handler);
- if (!handler && !finalizer)
- return raiseMissingField("TryStatement (without catch)", BinField::Finalizer);
-
- TRY_VAR(result, factory_.newTryStatement(start, block, handler, finalizer));
- break;
- }
-
- case BinKind::WhileStatement:
- case BinKind::DoWhileStatement: {
- ParseContext::Statement stmt(parseContext_, kind == BinKind::WhileStatement ? StatementKind::WhileLoop : StatementKind::DoLoop);
- ParseNode* test(nullptr);
- ParseNode* body(nullptr);
-
- for (auto field : fields) {
- switch (field) {
- case BinField::Test:
- MOZ_TRY_VAR(test, parseExpression());
- break;
- case BinField::Body:
- MOZ_TRY_VAR(body, parseStatement());
- break;
- default:
- return raiseInvalidField("WhileStatement | DoWhileStatement", field);
- }
- }
-
- if (!test)
- return raiseMissingField("WhileStatement | DoWhileStatement", BinField::Test);
- if (!body)
- return raiseMissingField("WhileStatement | DoWhileStatement", BinField::Body);
-
- if (kind == BinKind::WhileStatement)
- TRY_VAR(result, factory_.newWhileStatement(start, test, body));
- else
- TRY_VAR(result, factory_.newDoWhileStatement(body, test, tokenizer_->pos(start)));
-
- break;
- }
- case BinKind::ForStatement: {
- 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_);
- TRY(scope.init(parseContext_));
- ParseNode* init(nullptr); // Optional
- ParseNode* test(nullptr); // Optional
- ParseNode* update(nullptr); // Optional
- ParseNode* body(nullptr); // Required
-
- for (auto field : fields) {
- switch (field) {
- case BinField::Init:
- MOZ_TRY_VAR(init, parseForInit());
- break;
- case BinField::Test:
- MOZ_TRY_VAR(test, parseExpression());
- break;
- case BinField::Update:
- MOZ_TRY_VAR(update, parseExpression());
- break;
- case BinField::BINJS_Scope: // The scope always appears before the body.
- MOZ_TRY(parseAndUpdateCurrentScope());
- break;
- case BinField::Body:
- MOZ_TRY_VAR(body, parseStatement());
- break;
- default:
- return raiseInvalidField("ForStatement", field);
- }
- }
-
- if (!body)
- return raiseMissingField("ForStatement", BinField::Body);
-
- TRY_DECL(forHead, factory_.newForHead(init, test, update, tokenizer_->pos(start)));
- TRY_VAR(result, factory_.newForStatement(start, forHead, body, /* iflags = */ 0));
-
- if (!scope.isEmpty()) {
- TRY_DECL(bindings, NewLexicalScopeData(cx_, scope, alloc_, parseContext_));
- TRY_VAR(result, factory_.newLexicalScope(*bindings, result));
- }
-
- break;
- }
- case BinKind::ForInStatement: {
- 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 `BINJS_Scope`.
- ParseContext::Scope scope(cx_, parseContext_, usedNames_);
- TRY(scope.init(parseContext_));
- ParseNode* left(nullptr);
- ParseNode* right(nullptr);
- ParseNode* body(nullptr);
-
- for (auto field : fields) {
- switch (field) {
- case BinField::Left:
- MOZ_TRY_VAR(left, parseForInInit());
- break;
- case BinField::Right:
- MOZ_TRY_VAR(right, parseExpression());
- break;
- case BinField::Body:
- MOZ_TRY_VAR(body, parseStatement());
- break;
- case BinField::BINJS_Scope:
- MOZ_TRY(parseAndUpdateCurrentScope());
- break;
- default:
- return raiseInvalidField("ForInStatement", field);
- }
- }
-
- if (!left)
- return raiseMissingField("ForInStatement", BinField::Left);
- if (!right)
- return raiseMissingField("ForInStatement", BinField::Right);
- if (!body)
- return raiseMissingField("ForInStatement", BinField::Body);
-
- TRY_DECL(forHead, factory_.newForInOrOfHead(ParseNodeKind::ForIn, left, right,
- tokenizer_->pos(start)));
- TRY_VAR(result, factory_.newForStatement(start, forHead, body, /*flags*/ 0));
-
- if (!scope.isEmpty()) {
- TRY_DECL(bindings, NewLexicalScopeData(cx_, scope, alloc_, parseContext_));
- TRY_VAR(result, factory_.newLexicalScope(*bindings, result));
- }
- break;
- }
-
- case BinKind::VariableDeclaration:
- MOZ_TRY_VAR(result, parseVariableDeclarationAux(kind, fields));
- break;
-
- default:
- return raiseInvalidKind("Statement", kind);
- }
-
- return result;
-}
-
-JS::Result<ParseNode*>
-BinASTParser::parseBreakOrContinueStatementAux(const BinKind kind, const BinFields& fields)
-{
- const auto start = tokenizer_->offset();
- ParseNode* label(nullptr);
-
- for (auto field : fields) {
- switch (field) {
- case BinField::Label:
- MOZ_TRY_VAR(label, parsePattern());
-
- if (label && !label->isKind(ParseNodeKind::Name))
- return raiseError("ContinueStatement | BreakStatement - Label MUST be an identifier"); // FIXME: This should be changed in the grammar.
-
- break;
- default:
- return raiseInvalidField("ContinueStatement", field);
- }
- }
+ MOZ_ASSERT(!out);
- TokenPos pos = tokenizer_->pos(start);
- ParseNode* result;
- if (kind == BinKind::ContinueStatement) {
-#if 0 // FIXME: We probably need to fix the AST before making this check.
- auto validity = parseContext_->checkContinueStatement(label ? label->name() : 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");
- }
- }
-#endif // 0
- // Ok, this is a valid continue statement.
- TRY_VAR(result, factory_.newContinueStatement(label ? label->name() : nullptr, pos));
- } else {
-#if 0 // FIXME: We probably need to fix the AST before making this check.
- auto validity = parseContext_->checkBreakStatement(label ? label->name() : nullptr);
- 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");
- }
- }
-#endif // 0
- // Ok, this is a valid break statement.
- TRY_VAR(result, factory_.newBreakStatement(label ? label->name() : nullptr, pos));
- }
-
- MOZ_ASSERT(result);
-
- return result;
-}
-
-JS::Result<ParseNode*>
-BinASTParser::parseForInit()
-{
- // This can be either a VarDecl or an Expression.
- BinFields fields(cx_);
- AutoTaggedTuple guard(*tokenizer_);
- BinKind kind;
-
- TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
- ParseNode* result(nullptr);
-
- switch (kind) {
- case BinKind::VariableDeclaration:
- MOZ_TRY_VAR(result, parseVariableDeclarationAux(kind, fields));
- break;
- default:
- // Parse as expression
- MOZ_TRY_VAR(result, parseExpressionAux(kind, fields));
- break;
- }
-
- TRY(guard.done());
- return result;
-}
-
-JS::Result<ParseNode*>
-BinASTParser::parseForInInit()
-{
- // This can be either a VarDecl or a Pattern.
- BinFields fields(cx_);
- AutoTaggedTuple guard(*tokenizer_);
- BinKind kind;
-
- TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
- ParseNode* result(nullptr);
-
- switch (kind) {
- case BinKind::VariableDeclaration:
- MOZ_TRY_VAR(result, parseVariableDeclarationAux(kind, fields));
- break;
- default:
- // Parse as expression. Not a joke: http://www.ecma-international.org/ecma-262/5.1/index.html#sec-12.6.4 .
- MOZ_TRY_VAR(result, parseExpressionAux(kind, fields));
- break;
- }
-
- TRY(guard.done());
- return result;
-}
-
-JS::Result<ParseNode*>
-BinASTParser::parseFunctionAux(const BinKind kind, const BinFields& fields)
-{
- MOZ_ASSERT(isMethodOrFunction(kind));
-
- const size_t start = tokenizer_->offset();
-
- ParseNode* id(nullptr);
- ParseNode* params(nullptr);
- ParseNode* body(nullptr);
- ParseNode* directives(nullptr); // Largely ignored for the moment.
- ParseNode* key(nullptr); // Methods only
-
- // Allocate the function before walking down the tree.
- RootedFunction fun(cx_);
- TRY_VAR(fun, NewFunctionWithProto(cx_,
- /*native*/nullptr,
- /*nargs ?*/0,
- /*flags */ JSFunction::INTERPRETED_NORMAL,
- /*enclosing env*/nullptr,
- /*name*/ nullptr, // Will be known later
- /*proto*/ nullptr,
- /*alloc*/gc::AllocKind::FUNCTION,
- TenuredObject
- ));
- TRY_DECL(funbox, alloc_.new_<FunctionBox>(cx_,
- traceListHead_,
- fun,
- /* toStringStart = */0,
- /* directives = */Directives(parseContext_),
- /* extraWarning = */false,
- GeneratorKind::NotGenerator,
- FunctionAsyncKind::SyncFunction
- ));
-
- traceListHead_ = funbox;
-
- FunctionSyntaxKind syntax;
- switch (kind) {
- case BinKind::FunctionDeclaration:
- syntax = Statement;
- break;
- case BinKind::FunctionExpression:
- syntax = PrimaryExpression; // FIXME: Probably doesn't work.
- break;
- case BinKind::ObjectMethod:
- syntax = Method;
- break;
- case BinKind::ObjectGetter:
- syntax = Getter;
- break;
- case BinKind::ObjectSetter:
- syntax = Setter;
- break;
- default:
- MOZ_CRASH("Invalid FunctionSyntaxKind"); // Checked above.
- }
- funbox->initWithEnclosingParseContext(parseContext_, syntax);
-
- // Container scopes.
- ParseContext::Scope& varScope = parseContext_->varScope();
- ParseContext::Scope* letScope = parseContext_->innermostScope();
-
- // Push a new ParseContext.
- BinParseContext funpc(cx_, this, funbox, /* newDirectives = */ nullptr);
- TRY(funpc.init());
- parseContext_->functionScope().useAsVarScope(parseContext_);
- MOZ_ASSERT(parseContext_->isFunctionBox());
-
- for (auto field : fields) {
- switch (field) {
- case BinField::Id:
- MOZ_TRY_VAR(id, parseIdentifier());
- break;
- case BinField::Params:
- MOZ_TRY_VAR(params, parseArgumentList());
- break;
- case BinField::BINJS_Scope:
- // This scope information affects the scopes contained in the function body. MUST appear before the `body`.
- MOZ_TRY(parseAndUpdateScope(varScope, *letScope));
- break;
- case BinField::Directives:
- MOZ_TRY_VAR(directives, parseDirectiveList());
- break;
- case BinField::Body:
- MOZ_TRY_VAR(body, parseBlockStatement());
- break;
- case BinField::Key:
- if (!isMethod(kind))
- return raiseInvalidField("Functions (unless defined as methods)", field);
-
- MOZ_TRY_VAR(key, parseObjectPropertyName());
- break;
- default:
- return raiseInvalidField("Function", field);
- }
- }
-
- // Inject default values for absent fields.
- if (!params)
- TRY_VAR(params, new_<ListNode>(ParseNodeKind::ParamsBody, tokenizer_->pos()));
-
- if (!body)
- TRY_VAR(body, factory_.newStatementList(tokenizer_->pos()));
-
- if (kind == BinKind::FunctionDeclaration && !id) {
- // The name is compulsory only for function declarations.
- return raiseMissingField("FunctionDeclaration", BinField::Id);
- }
-
- // Reject if required values are missing.
- if (isMethod(kind) && !key)
- return raiseMissingField("method", BinField::Key);
-
- if (id)
- fun->initAtom(id->pn_atom);
-
- MOZ_ASSERT(params->isArity(PN_LIST));
-
- if (!(body->isKind(ParseNodeKind::LexicalScope) &&
- body->pn_u.scope.body->isKind(ParseNodeKind::StatementList)))
- {
- // Promote to lexical scope + statement list.
- if (!body->isKind(ParseNodeKind::StatementList)) {
- TRY_DECL(list, factory_.newStatementList(tokenizer_->pos(start)));
-
- list->initList(body);
- body = list;
- }
-
- // Promote to lexical scope.
- TRY_VAR(body, factory_.newLexicalScope(nullptr, body));
- }
- MOZ_ASSERT(body->isKind(ParseNodeKind::LexicalScope));
-
- MOZ_TRY_VAR(body, appendDirectivesToBody(body, directives));
-
- params->appendWithoutOrderAssumption(body);
-
- TokenPos pos = tokenizer_->pos(start);
- TRY_DECL(function, kind == BinKind::FunctionDeclaration
- ? factory_.newFunctionStatement(pos)
- : factory_.newFunctionExpression(pos));
-
- factory_.setFunctionBox(function, funbox);
- factory_.setFunctionFormalParametersAndBody(function, params);
-
- ParseNode* result;
- if (kind == BinKind::ObjectMethod)
- TRY_VAR(result, factory_.newObjectMethodOrPropertyDefinition(key, function, AccessorType::None));
- else if (kind == BinKind::ObjectGetter)
- TRY_VAR(result, factory_.newObjectMethodOrPropertyDefinition(key, function, AccessorType::Getter));
- else if (kind == BinKind::ObjectSetter)
- TRY_VAR(result, factory_.newObjectMethodOrPropertyDefinition(key, function, AccessorType::Setter));
- else
- result = function;
-
- // Now handle bindings.
- HandlePropertyName dotThis = cx_->names().dotThis;
- const bool declareThis = hasUsedName(dotThis) || funbox->bindingsAccessedDynamically() || funbox->isDerivedClassConstructor();
+ Maybe<Chars> string;
+ MOZ_TRY(readMaybeString(string));
+ MOZ_ASSERT(string);
- if (declareThis) {
- ParseContext::Scope& funScope = parseContext_->functionScope();
- ParseContext::Scope::AddDeclaredNamePtr p = funScope.lookupDeclaredNameForAdd(dotThis);
- MOZ_ASSERT(!p);
- TRY(funScope.addDeclaredName(parseContext_, p, dotThis, DeclarationKind::Var,
- DeclaredNameInfo::npos));
- funbox->setHasThisBinding();
- }
-
- TRY_DECL(bindings,
- NewFunctionScopeData(cx_, parseContext_->functionScope(),
- /* hasParameterExprs = */false, alloc_, parseContext_));
-
- funbox->functionScopeBindings().set(*bindings);
- return result;
-}
-
-JS::Result<ParseNode*>
-BinASTParser::parseObjectPropertyName()
-{
- auto start = tokenizer_->offset();
-
- BinFields fields(cx_);
- AutoTaggedTuple guard(*tokenizer_);
- BinKind kind;
-
- TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
- ParseNode* result;
- switch (kind) {
- case BinKind::StringLiteral: {
- ParseNode* string;
- MOZ_TRY_VAR(string, parseStringLiteralAux(kind, fields));
- uint32_t index;
- if (string->pn_atom->isIndex(&index))
- TRY_VAR(result, factory_.newNumber(index, NoDecimal, TokenPos(start, tokenizer_->offset())));
- else
- result = string;
-
- break;
- }
- case BinKind::NumericLiteral:
- MOZ_TRY_VAR(result, parseNumericLiteralAux(kind, fields));
- break;
- case BinKind::Identifier:
- MOZ_TRY_VAR(result, parseIdentifierAux(kind, fields, /* expectObjectPropertyName = */ true));
- break;
- case BinKind::ComputedPropertyName: {
- ParseNode* expr;
- MOZ_TRY_VAR(expr, parseExpressionAux(kind, fields));
- TRY_VAR(result, factory_.newComputedName(expr, start, tokenizer_->offset()));
- break;
- }
- default:
- return raiseInvalidKind("ObjectLiteralPropertyName", kind);
- }
-
- TRY(guard.done());
- return result;
-}
-
-JS::Result<ParseNode*>
-BinASTParser::parseVariableDeclarationAux(const BinKind kind, const BinFields& fields)
-{
- const size_t start = tokenizer_->offset();
-
- ParseNode* result(nullptr);
- switch (kind) {
- default:
- return raiseInvalidKind("VariableDeclaration", kind);
- case BinKind::VariableDeclaration:
- ParseNodeKind pnk = ParseNodeKind::Limit;
-
- for (auto field : fields) {
- switch (field) {
- case BinField::Kind: {
- Maybe<Chars> kindName;
- MOZ_TRY(readString(kindName));
-
- if (*kindName == "let")
- pnk = ParseNodeKind::Let;
- else if (*kindName == "var")
- pnk = ParseNodeKind::Var;
- else if (*kindName == "const")
- pnk = ParseNodeKind::Const;
- else
- return raiseInvalidEnum("VariableDeclaration", *kindName);
-
- break;
- }
- case BinField::Declarations: {
- uint32_t length;
- AutoList guard(*tokenizer_);
-
- TRY(tokenizer_->enterList(length, guard));
- TRY_VAR(result, factory_.newDeclarationList(ParseNodeKind::Const /*Placeholder*/,
- tokenizer_->pos(start)));
-
- for (uint32_t i = 0; i < length; ++i) {
- ParseNode* current;
- MOZ_TRY_VAR(current, parseVariableDeclarator());
- MOZ_ASSERT(current);
-
- result->appendWithoutOrderAssumption(current);
- }
-
- TRY(guard.done());
- break;
- }
- default:
- return raiseInvalidField("VariableDeclaration", field);
- }
- }
-
- if (!result || pnk == ParseNodeKind::Limit)
- return raiseMissingField("VariableDeclaration", BinField::Declarations);
-
- result->setKind(pnk);
- }
-
- return result;
-}
-
+ RootedAtom atom(cx_);
+ TRY_VAR(atom, AtomizeUTF8Chars(cx_, (const char*)string->begin(), string->length()));
-JS::Result<ParseNode*>
-BinASTParser::parseExpressionStatementAux(const BinKind kind, const BinFields& fields)
-{
- MOZ_ASSERT(kind == BinKind::ExpressionStatement);
-
- ParseNode* expr(nullptr);
- for (auto field : fields) {
- switch (field) {
- case BinField::Expression:
- MOZ_TRY_VAR(expr, parseExpression());
-
- break;
- default:
- return raiseInvalidField("ExpressionStatement", field);
- }
- }
-
- if (!expr)
- return raiseMissingField("ExpressionStatement", BinField::Expression);
-
- TRY_DECL(result, factory_.newExprStatement(expr, tokenizer_->offset()));
- return result;
-}
-
-JS::Result<ParseNode*>
-BinASTParser::parseVariableDeclarator()
-{
- const size_t start = tokenizer_->offset();
-
- BinKind kind;
- BinFields fields(cx_);
- AutoTaggedTuple guard(*tokenizer_);
-
- TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
- if (kind != BinKind::VariableDeclarator)
- return raiseInvalidKind("VariableDeclarator", kind);
-
- ParseNode* id(nullptr);
- ParseNode* init(nullptr); // Optional.
- for (auto field : fields) {
- switch (field) {
- case BinField::Id:
- MOZ_TRY_VAR(id, parsePattern());
-
- break;
- case BinField::Init:
- MOZ_TRY_VAR(init, parseExpression());
-
- break;
- default:
- return raiseInvalidField("VariableDeclarator", field);
- }
- }
-
- TRY(guard.done());
- if (!id)
- return raiseMissingField("VariableDeclarator", BinField::Id);
-
- ParseNode* result(nullptr);
-
- // FIXME: Documentation in ParseNode is clearly obsolete.
- if (id->isKind(ParseNodeKind::Name)) {
- // `var foo [= bar]``
- TRY_VAR(result, factory_.newName(id->pn_atom->asPropertyName(), tokenizer_->pos(start), cx_));
-
- if (init)
- result->pn_expr = init;
-
- } else {
- // `var pattern = bar`
- if (!init) {
- // Here, `init` is required.
- return raiseMissingField("VariableDeclarator (with non-trivial pattern)", BinField::Init);
- }
-
- TRY_VAR(result, factory_.newAssignment(ParseNodeKind::Assign, id, init));
- }
-
- return result;
-}
-
-JS::Result<ParseNode*>
-BinASTParser::parseExpressionList(bool acceptElisions)
-{
- const size_t start = tokenizer_->offset();
-
- uint32_t length;
- AutoList guard(*tokenizer_);
-
- TRY(tokenizer_->enterList(length, guard));
- TRY_DECL(result, factory_.newArrayLiteral(start));
-
- for (uint32_t i = 0; i < length; ++i) {
- BinFields fields(cx_);
- AutoTaggedTuple guard(*tokenizer_);
- BinKind kind;
-
- TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
- switch (kind) {
- case BinKind::Elision: {
- if (!acceptElisions)
- return raiseInvalidKind("[Expression]", kind);
-
- MOZ_TRY(parseElisionAux(kind, fields));
- TRY(!factory_.addElision(result, tokenizer_->pos(start)));
- break;
- }
- default: {
- ParseNode* expr(nullptr);
- MOZ_TRY_VAR(expr, parseExpressionAux(kind, fields));
-
- MOZ_ASSERT(expr);
- factory_.addArrayElement(result, expr);
- }
- }
-
- TRY(guard.done());
- }
-
- TRY(guard.done());
- return result;
-}
-
-JS::Result<Ok>
-BinASTParser::parseElisionAux(const BinKind kind, const BinFields& fields)
-{
- MOZ_ASSERT(kind == BinKind::Elision);
- MOZ_TRY(checkEmptyTuple(kind, fields));
-
+ out.set(Move(atom));
return Ok();
}
-JS::Result<ParseNode*>
-BinASTParser::parseSwitchCaseList()
+JS::Result<Ok>
+BinASTParser::readMaybeString(MutableHandleAtom out)
{
- uint32_t length;
- AutoList guard(*tokenizer_);
-
- TRY(tokenizer_->enterList(length, guard));
- TRY_DECL(list, factory_.newStatementList(tokenizer_->pos()));
-
- // Set to `true` once we have encountered a `default:` case.
- // Two `default:` cases is an error.
- bool haveDefault = false;
+ MOZ_ASSERT(!out);
- for (uint32_t i = 0; i < length; ++i) {
- ParseNode* caseNode(nullptr);
- MOZ_TRY_VAR(caseNode, parseSwitchCase());
- MOZ_ASSERT(caseNode);
-
- if (caseNode->pn_left == nullptr) {
- // Ah, seems that we have encountered a default case.
- if (haveDefault) {
- // Oh, wait, two defaults? That's an error.
- return raiseError("This switch() has more than one `default:` case");
- }
- haveDefault = true;
- }
- factory_.addCaseStatementToList(list, caseNode);
+ Maybe<Chars> string;
+ MOZ_TRY(readMaybeString(string));
+ if (!string) {
+ return Ok();
}
- TRY(guard.done());
- TRY_DECL(result, factory_.newLexicalScope(nullptr, list));
-
- return result;
-}
-
-JS::Result<ParseNode*>
-BinASTParser::parseExpression()
-{
- BinFields fields(cx_);
- AutoTaggedTuple guard(*tokenizer_);
- BinKind kind;
-
- TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
- ParseNode* result(nullptr);
- MOZ_TRY_VAR(result, parseExpressionAux(kind, fields));
-
- TRY(guard.done());
- return result;
-}
-
-JS::Result<ParseNode*>
-BinASTParser::parseExpressionAux(const BinKind kind, const BinFields& fields)
-{
- const size_t start = tokenizer_->offset();
-
- ParseNode* result(nullptr);
-
- switch (kind) {
- case BinKind::Identifier: {
- MOZ_TRY_VAR(result, parseIdentifierAux(kind, fields));
- break;
- }
- case BinKind::BooleanLiteral: {
- Maybe<bool> value;
- for (auto field : fields) {
- switch (field) {
- case BinField::Value:
- MOZ_TRY_EMPLACE(value, readBool());
- break;
- default:
- return raiseInvalidField("BooleanLiteral", field);
- }
- }
-
- // In case of absent optional fields, inject default values.
- if (!value)
- value.emplace(false);
-
- TRY_VAR(result, factory_.newBooleanLiteral(*value, tokenizer_->pos(start)));
-
- break;
- }
- case BinKind::NullLiteral: {
- MOZ_TRY(checkEmptyTuple(kind, fields));
- TRY_VAR(result, factory_.newNullLiteral(tokenizer_->pos(start)));
- break;
- }
- case BinKind::NumericLiteral:
- MOZ_TRY_VAR(result, parseNumericLiteralAux(kind, fields));
- break;
-
- case BinKind::RegExpLiteral: {
- RootedAtom pattern(cx_);
- Maybe<Chars> flags;
- for (auto field : fields) {
- switch (field) {
- case BinField::Pattern:
- MOZ_TRY(readString(&pattern));
- break;
- case BinField::Flags:
- MOZ_TRY(readString(flags));
- break;
- default:
- return raiseInvalidField("RegExpLiteral", field);
- }
- }
-
- if (!pattern)
- return raiseMissingField("RegExpLiteral", BinField::Pattern);
- if (!flags)
- return raiseMissingField("RegExpLiteral", BinField::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 raiseInvalidEnum("RegExpLiteral", *flags);
- }
-
-
- Rooted<RegExpObject*> reobj(cx_);
- TRY_VAR(reobj, RegExpObject::create(cx_,
- pattern,
- reflags,
- alloc_,
- TenuredObject));
-
- TRY_VAR(result, factory_.newRegExp(reobj, tokenizer_->pos(start), *this));
-
- break;
- }
- case BinKind::StringLiteral:
- MOZ_TRY_VAR(result, parseStringLiteralAux(kind, fields));
- break;
-
- case BinKind::ThisExpression: {
- MOZ_TRY(checkEmptyTuple(kind, fields));
-
- if (parseContext_->isFunctionBox())
- parseContext_->functionBox()->usesThis = true;
-
- TokenPos pos = tokenizer_->pos(start);
- ParseNode* thisName(nullptr);
- if (parseContext_->sc()->thisBinding() == ThisBinding::Function)
- TRY_VAR(thisName, factory_.newName(cx_->names().dotThis, pos, cx_));
-
- TRY_VAR(result, factory_.newThisLiteral(pos, thisName));
- break;
- }
- case BinKind::ArrayExpression:
- MOZ_TRY_VAR(result, parseArrayExpressionAux(kind, fields));
- break;
-
- case BinKind::ObjectExpression:
- MOZ_TRY_VAR(result, parseObjectExpressionAux(kind, fields));
- break;
-
- case BinKind::FunctionExpression:
- MOZ_TRY_VAR(result, parseFunctionAux(kind, fields));
- result->setOp(JSOP_LAMBDA);
- break;
-
- case BinKind::UnaryExpression:
- case BinKind::UpdateExpression: {
- ParseNode* expr(nullptr);
- Maybe<Chars> operation;
- Maybe<bool> prefix; // FIXME: Ignored for unary_expression?
-
- for (auto field : fields) {
- switch (field) {
- case BinField::Operator:
- MOZ_TRY(readString(operation));
- break;
- case BinField::Prefix:
- MOZ_TRY_EMPLACE(prefix, readBool());
- break;
- case BinField::Argument:
- // arguments are always parsed *after* operator.
- if (operation.isNothing())
- return raiseMissingField("UpdateExpression", BinField::Operator);
- MOZ_TRY_VAR(expr, parseExpression());
- break;
- default:
- return raiseInvalidField("UpdateExpression", field);
- }
- }
-
- if (!expr)
- return raiseMissingField("UpdateExpression", BinField::Argument);
- if (operation.isNothing())
- return raiseMissingField("UpdateExpression", BinField::Operator);
-
- // In case of absent optional fields, inject default values.
- if (prefix.isNothing())
- prefix.emplace(false);
-
- ParseNodeKind pnk = ParseNodeKind::Limit;
- if (kind == BinKind::UnaryExpression) {
- if (*operation == "-") {
- pnk = ParseNodeKind::Neg;
- } else if (*operation == "+") {
- pnk = ParseNodeKind::Pos;
- } else if (*operation == "!") {
- pnk = ParseNodeKind::Not;
- } else if (*operation == "~") {
- pnk = ParseNodeKind::BitNot;
- } else if (*operation == "typeof") {
- if (expr->isKind(ParseNodeKind::Name))
- pnk = ParseNodeKind::TypeOfName;
- else
- pnk = ParseNodeKind::TypeOfExpr;
- } else if (*operation == "void") {
- pnk = ParseNodeKind::Void;
- } else if (*operation == "delete") {
- switch (expr->getKind()) {
- case ParseNodeKind::Name:
- expr->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;
- }
- } else {
- return raiseInvalidEnum("UnaryOperator", *operation);
- }
- } else if (kind == BinKind::UpdateExpression) {
- if (!expr->isKind(ParseNodeKind::Name) && !factory_.isPropertyAccess(expr))
- return raiseError("Invalid increment/decrement operand"); // FIXME: Shouldn't this be part of the syntax?
-
- if (*operation == "++") {
- if (*prefix)
- pnk = ParseNodeKind::PreIncrement;
- else
- pnk = ParseNodeKind::PostIncrement;
- } else if (*operation == "--") {
- if (*prefix)
- pnk = ParseNodeKind::PreDecrement;
- else
- pnk = ParseNodeKind::PostDecrement;
- } else {
- return raiseInvalidEnum("UpdateOperator", *operation);
- }
- }
-
- TRY_VAR(result, factory_.newUnary(pnk, start, expr));
-
- break;
- }
- case BinKind::BinaryExpression:
- case BinKind::LogicalExpression: {
- ParseNode* left(nullptr);
- ParseNode* right(nullptr);
- Maybe<Chars> operation;
- for (auto field : fields) {
- switch (field) {
- case BinField::Left:
- MOZ_TRY_VAR(left, parseExpression());
- break;
- case BinField::Right:
- MOZ_TRY_VAR(right, parseExpression());
- break;
- case BinField::Operator:
- MOZ_TRY(readString(operation));
- break;
- default:
- return raiseInvalidField("LogicalExpression | BinaryExpression", field);
- }
- }
-
- if (!left)
- return raiseMissingField("LogicalExpression | BinaryExpression", BinField::Left);
- if (!right)
- return raiseMissingField("LogicalExpression | BinaryExpression", BinField::Right);
- if (operation.isNothing())
- return raiseMissingField("LogicalExpression | BinaryExpression", BinField::Operator);
-
- // FIXME: Instead of Chars, we should use atoms and comparison
- // between atom ptr.
- ParseNodeKind pnk = ParseNodeKind::Limit;
- if (*operation == "==")
- pnk = ParseNodeKind::Eq;
- else if (*operation == "!=")
- pnk = ParseNodeKind::Ne;
- else if (*operation == "===")
- pnk = ParseNodeKind::StrictEq;
- else if (*operation == "!==")
- pnk = ParseNodeKind::StrictNe;
- else if (*operation == "<")
- pnk = ParseNodeKind::Lt;
- else if (*operation == "<=")
- pnk = ParseNodeKind::Le;
- else if (*operation == ">")
- pnk = ParseNodeKind::Gt;
- else if (*operation == ">=")
- pnk = ParseNodeKind::Ge;
- else if (*operation == "<<")
- pnk = ParseNodeKind::Lsh;
- else if (*operation == ">>")
- pnk = ParseNodeKind::Rsh;
- else if (*operation == ">>>")
- pnk = ParseNodeKind::Ursh;
- else if (*operation == "+")
- pnk = ParseNodeKind::Add;
- else if (*operation == "-")
- pnk = ParseNodeKind::Sub;
- else if (*operation == "*")
- pnk = ParseNodeKind::Star;
- else if (*operation == "/")
- pnk = ParseNodeKind::Div;
- else if (*operation == "%")
- pnk = ParseNodeKind::Mod;
- else if (*operation == "|")
- pnk = ParseNodeKind::BitOr;
- else if (*operation == "^")
- pnk = ParseNodeKind::BitXor;
- else if (*operation == "&")
- pnk = ParseNodeKind::BitAnd;
- else if (*operation == "in")
- pnk = ParseNodeKind::In;
- else if (*operation == "instanceof")
- pnk = ParseNodeKind::InstanceOf;
- else if (*operation == "||")
- pnk = ParseNodeKind::Or;
- else if (*operation == "&&")
- pnk = ParseNodeKind::And;
- else if (*operation == "**")
- pnk = ParseNodeKind::Pow;
- else
- return raiseInvalidEnum("BinaryOperator | LogicalOperator", *operation);
-
- if (left->isKind(pnk) &&
- pnk != ParseNodeKind::Pow /* ParseNodeKind::Pow is not left-associative */)
- {
- // Regroup left-associative operations into lists.
- left->appendWithoutOrderAssumption(right);
- result = left;
- } else {
- TRY_DECL(list, factory_.newList(pnk, tokenizer_->pos(start)));
-
- list->appendWithoutOrderAssumption(left);
- list->appendWithoutOrderAssumption(right);
- result = list;
- }
-
- break;
- }
- case BinKind::AssignmentExpression: {
- ParseNode* left(nullptr);
- ParseNode* right(nullptr);
- Maybe<Chars> operation;
- for (auto field : fields) {
- switch (field) {
- case BinField::Left:
- MOZ_TRY_VAR(left, parseExpression());
- break;
- case BinField::Right:
- MOZ_TRY_VAR(right, parseExpression());
- break;
- case BinField::Operator:
- MOZ_TRY(readString(operation));
- break;
- default:
- return raiseInvalidField("AssignmentExpression", field);
- }
- }
-
- if (!left)
- return raiseMissingField("AssignmentExpression", BinField::Left);
- if (!right)
- return raiseMissingField("AssignmentExpression", BinField::Right);
- if (operation.isNothing())
- return raiseMissingField("AssignmentExpression", BinField::Operator);
-
- // FIXME: Instead of Chars, we should use atoms and comparison
- // between atom ptr.
- // FIXME: We should probably turn associative operations into lists.
- ParseNodeKind pnk = ParseNodeKind::Limit;
- if (*operation == "=")
- pnk = ParseNodeKind::Assign;
- else if (*operation == "+=")
- pnk = ParseNodeKind::AddAssign;
- else if (*operation == "-=")
- pnk = ParseNodeKind::SubAssign;
- else if (*operation == "*=")
- pnk = ParseNodeKind::MulAssign;
- else if (*operation == "/=")
- pnk = ParseNodeKind::DivAssign;
- else if (*operation == "%=")
- pnk = ParseNodeKind::ModAssign;
- else if (*operation == "<<=")
- pnk = ParseNodeKind::LshAssign;
- else if (*operation == ">>=")
- pnk = ParseNodeKind::RshAssign;
- else if (*operation == ">>>=")
- pnk = ParseNodeKind::UrshAssign;
- else if (*operation == "|=")
- pnk = ParseNodeKind::BitOrAssign;
- else if (*operation == "^=")
- pnk = ParseNodeKind::BitXorAssign;
- else if (*operation == "&=")
- pnk = ParseNodeKind::BitAndAssign;
- else
- return raiseInvalidEnum("AssignmentOperator", *operation);
-
- TRY_VAR(result, factory_.newAssignment(pnk, left, right));
-
- break;
- }
- case BinKind::BracketExpression:
- case BinKind::DotExpression:
- MOZ_TRY_VAR(result, parseMemberExpressionAux(kind, fields));
-
- break;
- case BinKind::ConditionalExpression: {
- ParseNode* test(nullptr);
- ParseNode* alternate(nullptr);
- ParseNode* consequent(nullptr);
-
- for (auto field : fields) {
- switch (field) {
- case BinField::Test:
- MOZ_TRY_VAR(test, parseExpression());
- break;
- case BinField::Consequent:
- MOZ_TRY_VAR(consequent, parseExpression());
- break;
- case BinField::Alternate:
- MOZ_TRY_VAR(alternate, parseExpression());
- break;
- default:
- return raiseInvalidField("ConditionalExpression", field);
- }
- }
-
- if (!test)
- return raiseMissingField("ConditionalExpression", BinField::Test);
- if (!consequent)
- return raiseMissingField("ConditionalExpression", BinField::Consequent);
- if (!alternate)
- return raiseMissingField("ConditionalExpression", BinField::Alternate);
-
- TRY_VAR(result, factory_.newConditional(test, consequent, alternate));
-
- break;
- }
- case BinKind::CallExpression:
- case BinKind::NewExpression: {
- ParseNode* callee(nullptr);
-
- for (auto field : fields) {
- switch (field) {
- case BinField::Callee:
- MOZ_TRY_VAR(callee, parseExpression());
- break;
- case BinField::Arguments:
- MOZ_TRY_VAR(result, parseExpressionList(/* acceptElisions = */ false));
- break;
- default:
- return raiseInvalidField("NewExpression", field);
- }
- }
-
- // In case of absent required fields, fail.
- if (!callee)
- return raiseMissingField("NewExpression", BinField::Callee);
-
- // In case of absent optional fields, inject default values.
- if (!result)
- TRY_VAR(result, factory_.newArrayLiteral(start));
-
- ParseNodeKind pnk =
- kind == BinKind::CallExpression
- ? ParseNodeKind::Call
- : ParseNodeKind::New;
- result->setKind(pnk);
- result->prepend(callee);
+ RootedAtom atom(cx_);
+ TRY_VAR(atom, AtomizeUTF8Chars(cx_, (const char*)string->begin(), string->length()));
- break;
- }
- case BinKind::SequenceExpression: {
- for (auto field : fields) {
- switch (field) {
- case BinField::Expressions:
- MOZ_TRY_VAR(result, parseExpressionList(/* acceptElisions = */ false));
- break;
- default:
- return raiseInvalidField("SequenceExpression", field);
- }
- }
-
- if (!result)
- return raiseMissingField("SequenceExpression", BinField::Expression);
-
- result->setKind(ParseNodeKind::Comma);
- break;
- }
- default:
- return raiseInvalidKind("Expression", kind);
- }
-
- return result;
-}
-
-JS::Result<ParseNode*>
-BinASTParser::parseNumericLiteralAux(const BinKind kind, const BinFields& fields)
-{
- auto start = tokenizer_->offset();
-
- Maybe<double> value;
- for (auto field : fields) {
- switch (field) {
- case BinField::Value:
- MOZ_TRY_EMPLACE(value, readNumber());
- break;
- default:
- return raiseInvalidField("NumericLiteral", field);
- }
- }
-
- // In case of absent optional fields, inject default values.
- if (!value)
- value.emplace(0);
-
- TRY_DECL(result, factory_.newNumber(*value, DecimalPoint::HasDecimal, tokenizer_->pos(start)));
- return result;
-}
-
-JS::Result<ParseNode*>
-BinASTParser::parseStringLiteralAux(const BinKind kind, const BinFields& fields)
-{
- auto start = tokenizer_->offset();
-
- RootedAtom value(cx_);
- for (auto field : fields) {
- switch (field) {
- case BinField::Value:
- MOZ_TRY(readString(&value));
- break;
- default:
- return raiseInvalidField("StringLiteral", field);
- }
- }
-
- if (!value)
- return raiseMissingField("StringLiteral", BinField::Value);
-
- TRY_DECL(result, factory_.newStringLiteral(value, tokenizer_->pos(start)));
- return result;
-}
-
-JS::Result<ParseNode*>
-BinASTParser::parseArrayExpressionAux(const BinKind kind, const BinFields& fields)
-{
- MOZ_ASSERT(kind == BinKind::ArrayExpression);
-
- ParseNode* result(nullptr);
- for (auto field : fields) {
- switch (field) {
- case BinField::Elements: {
- MOZ_TRY_VAR(result, parseExpressionList(/* acceptElisions = */ true));
- break;
- }
- default:
- return raiseInvalidField("ArrayExpression", field);
- }
- }
-
- // Inject default values for absent fields.
- if (!result)
- TRY_VAR(result, factory_.newArrayLiteral(tokenizer_->offset()));
-
- MOZ_ASSERT(result->isKind(ParseNodeKind::Array));
- return result;
-}
-
-JS::Result<ParseNode*>
-BinASTParser::parseObjectExpressionAux(const BinKind kind, const BinFields& fields)
-{
- MOZ_ASSERT(kind == BinKind::ObjectExpression);
-
- ParseNode* result(nullptr);
- for (auto field : fields) {
- switch (field) {
- case BinField::Properties: {
- MOZ_TRY_VAR(result, parseObjectMemberList());
- break;
- }
- default:
- return raiseInvalidField("Property | Method", field);
- }
- }
-
- if (!result)
- TRY_VAR(result, factory_.newObjectLiteral(tokenizer_->offset()));
-
- MOZ_ASSERT(result->isArity(PN_LIST));
- MOZ_ASSERT(result->isKind(ParseNodeKind::Object));
-
-#if defined(DEBUG)
- // Sanity check.
- for (ParseNode* iter = result->pn_head; iter != nullptr; iter = iter->pn_next) {
- MOZ_ASSERT(iter->isKind(ParseNodeKind::Colon));
- MOZ_ASSERT(iter->pn_left != nullptr);
- MOZ_ASSERT(iter->pn_right != nullptr);
- }
-#endif // defined(DEBUG)
-
- return result;
-}
-
-JS::Result<ParseNode*>
-BinASTParser::parseMemberExpressionAux(const BinKind kind, const BinFields& fields)
-{
- MOZ_ASSERT(kind == BinKind::DotExpression || kind == BinKind::BracketExpression);
-
- ParseNode* object(nullptr);
- ParseNode* property(nullptr);
-
- for (auto field : fields) {
- switch (field) {
- case BinField::Object:
- MOZ_TRY_VAR(object, parseExpression());
- break;
- case BinField::Property:
- if (kind == BinKind::BracketExpression)
- MOZ_TRY_VAR(property, parseExpression());
- else
- MOZ_TRY_VAR(property, parseIdentifier());
- break;
- default:
- return raiseInvalidField("MemberExpression", field);
- }
- }
-
- // In case of absent required fields, fail.
- if (!object)
- return raiseMissingField("MemberExpression", BinField::Object);
- if (!property)
- return raiseMissingField("MemberExpression", BinField::Property);
-
- ParseNode* result(nullptr);
- if (kind == BinKind::DotExpression) {
- MOZ_ASSERT(property->isKind(ParseNodeKind::Name));
- PropertyName* name = property->pn_atom->asPropertyName();
- TRY_VAR(result, factory_.newPropertyAccess(object, name, tokenizer_->offset()));
- } else {
- TRY_VAR(result, factory_.newPropertyByValue(object, property, tokenizer_->offset()));
- }
-
- return result;
-}
-
-JS::Result<ParseNode*>
-BinASTParser::parseDirectiveList()
-{
- uint32_t length;
- AutoList guard(*tokenizer_);
- TRY(tokenizer_->enterList(length, guard));
-
- TokenPos pos = tokenizer_->pos();
- TRY_DECL(result, factory_.newStatementList(pos));
-
- RootedAtom value(cx_);
- for (uint32_t i = 0; i < length; ++i) {
- value = nullptr;
- MOZ_TRY(readString(&value));
-
- TRY_DECL(directive, factory_.newStringLiteral(value, pos));
- factory_.addStatementToList(result, directive);
- }
-
- TRY(guard.done());
- return result;
-}
-
-JS::Result<ParseNode*>
-BinASTParser::parseSwitchCase()
-{
- const size_t start = tokenizer_->offset();
-
- BinKind kind;
- BinFields fields(cx_);
- AutoTaggedTuple guard(*tokenizer_);
-
- TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
- if (kind != BinKind::SwitchCase)
- return raiseInvalidKind("SwitchCase", kind);
-
- ParseNode* test(nullptr); // Optional.
- ParseNode* statements(nullptr); // Required.
-
- for (auto field : fields) {
- switch (field) {
- case BinField::Test:
- MOZ_TRY_VAR(test, parseExpression());
- break;
- case BinField::Consequent:
- MOZ_TRY_VAR(statements, parseStatementList());
- break;
- default:
- return raiseInvalidField("SwitchCase", field);
- }
- }
-
- TRY(guard.done());
- if (!statements)
- return raiseMissingField("SwitchCase", BinField::Consequent);
-
- MOZ_ASSERT(statements->isKind(ParseNodeKind::StatementList));
-
- TRY_DECL(result, factory_.newCaseOrDefault(start, test, statements));
-
- return result;
-}
-
-JS::Result<ParseNode*>
-BinASTParser::parseCatchClause()
-{
- ParseContext::Statement stmt(parseContext_, StatementKind::Catch);
- ParseContext::Scope scope(cx_, parseContext_, usedNames_);
- TRY(scope.init(parseContext_));
-
- BinKind kind;
- BinFields fields(cx_);
- AutoTaggedTuple guard(*tokenizer_);
-
- TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
- ParseNode* result(nullptr);
-
- switch (kind) {
- default:
- return raiseInvalidKind("CatchClause", kind);
- case BinKind::CatchClause: {
- ParseNode* param(nullptr);
- ParseNode* body(nullptr);
-
- for (auto field : fields) {
- switch (field) {
- case BinField::Param:
- MOZ_TRY_VAR(param, parsePattern());
- break;
- case BinField::Body:
- MOZ_TRY_VAR(body, parseBlockStatement());
- break;
- case BinField::BINJS_Scope:
- MOZ_TRY(parseAndUpdateCurrentScope());
- break;
- default:
- return raiseInvalidField("CatchClause", field);
- }
- }
-
- if (!param)
- return raiseMissingField("CatchClause", BinField::Param);
- if (!body)
- return raiseMissingField("CatchClause", BinField::Body);
-
- TRY_DECL(bindings, NewLexicalScopeData(cx_, scope, alloc_, parseContext_));
- TRY_VAR(result, factory_.newLexicalScope(*bindings, body));
- TRY(factory_.setupCatchScope(result, param, body));
- }
- }
-
- TRY(guard.done());
- return result;
-}
-
-JS::Result<ParseNode*>
-BinASTParser::parseArgumentList()
-{
- uint32_t length;
- AutoList guard(*tokenizer_);
-
- TRY(tokenizer_->enterList(length, guard));
- ParseNode* result = new_<ListNode>(ParseNodeKind::ParamsBody, tokenizer_->pos());
-
- for (uint32_t i = 0; i < length; ++i) {
- ParseNode* pattern;
- MOZ_TRY_VAR(pattern, parsePattern());
-
- result->appendWithoutOrderAssumption(pattern);
- }
-
- TRY(guard.done());
- return result;
-}
-
-JS::Result<ParseNode*>
-BinASTParser::parseIdentifier()
-{
- BinKind kind;
- BinFields fields(cx_);
- AutoTaggedTuple guard(*tokenizer_);
-
- TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
- ParseNode* result;
- MOZ_TRY_VAR(result, parseIdentifierAux(kind, fields));
-
- TRY(guard.done());
- return result;
-}
-
-JS::Result<ParseNode*>
-BinASTParser::parseIdentifierAux(const BinKind, const BinFields& fields, const bool expectObjectPropertyName /* = false */)
-{
- const size_t start = tokenizer_->offset();
-
- RootedAtom id(cx_);
- for (auto field : fields) {
- switch (field) {
- case BinField::Name:
- MOZ_TRY(readString(&id));
- break;
- default:
- return raiseInvalidField("Identifier", field);
- }
- }
-
- if (!id)
- return raiseMissingField("Identifier", BinField::Name);
-
- if (!IsIdentifier(id))
- return raiseError("Invalid identifier");
- if (!expectObjectPropertyName && IsKeyword(id))
- return raiseError("Invalid identifier (keyword)");
-
- // Once `IsIdentifier` has returned true, we may call `asPropertyName()` without fear.
- TokenPos pos = tokenizer_->pos(start);
-
- ParseNode* result;
- if (expectObjectPropertyName)
- TRY_VAR(result, factory_.newObjectLiteralPropertyName(id->asPropertyName(), pos));
- else
- TRY_VAR(result, factory_.newName(id->asPropertyName(), pos, cx_));
-
- return result;
-}
-
-
-JS::Result<ParseNode*>
-BinASTParser::parsePattern()
-{
- BinKind kind;
- BinFields fields(cx_);
- AutoTaggedTuple guard(*tokenizer_);
-
- TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
- ParseNode* result;
- MOZ_TRY_VAR(result, parsePatternAux(kind, fields));
-
- TRY(guard.done());
- return result;
-}
-
-JS::Result<ParseNode*>
-BinASTParser::parsePatternAux(const BinKind kind, const BinFields& fields)
-{
- ParseNode* result;
- switch (kind) {
- case BinKind::Identifier:
- MOZ_TRY_VAR(result, parseIdentifierAux(kind ,fields));
- break;
- default:
- return raiseInvalidKind("Pattern", kind);
- }
-
- return result;
-}
-
-JS::Result<ParseNode*>
-BinASTParser::parseObjectMember()
-{
- BinKind kind;
- BinFields fields(cx_);
- AutoTaggedTuple guard(*tokenizer_);
-
- TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
- ParseNode* result(nullptr);
-
- switch (kind) {
- case BinKind::ObjectProperty: {
- ParseNode* key(nullptr);
- ParseNode* value(nullptr);
- for (auto field : fields) {
- switch (field) {
- case BinField::Key:
- MOZ_TRY_VAR(key, parseObjectPropertyName());
- break;
- case BinField::Value:
- MOZ_TRY_VAR(value, parseExpression());
- break;
- default:
- return raiseInvalidField("ObjectMember", field);
- }
- }
-
- if (!key)
- return raiseMissingField("ObjectMember", BinField::Key);
- if (!value)
- return raiseMissingField("ObjectMember", BinField::Value);
-
- if (!factory_.isUsableAsObjectPropertyName(key))
- return raiseError("ObjectMember key kind");
-
- TRY_VAR(result, factory_.newObjectMethodOrPropertyDefinition(key, value, AccessorType::None));
-
- break;
- }
- case BinKind::ObjectMethod:
- case BinKind::ObjectGetter:
- case BinKind::ObjectSetter:
- MOZ_TRY_VAR(result, parseFunctionAux(kind, fields));
-
- if (!result)
- return raiseEmpty("ObjectMethod");
-
- MOZ_ASSERT(result->isKind(ParseNodeKind::Colon));
- break;
- default:
- return raiseInvalidKind("ObjectMember", kind);
- }
-
- TRY(guard.done());
- MOZ_ASSERT(result);
- return result;
-}
-
-JS::Result<ParseNode*>
-BinASTParser::parseObjectMemberList()
-{
- uint32_t length;
- AutoList guard(*tokenizer_);
-
- auto start = tokenizer_->offset();
- TRY(tokenizer_->enterList(length, guard));
-
- TRY_DECL(result, factory_.newObjectLiteral(start));
-
- for (uint32_t i = 0; i < length; ++i) {
- ParseNode* keyValue;
- MOZ_TRY_VAR(keyValue, parseObjectMember());
- MOZ_ASSERT(keyValue);
-
- result->appendWithoutOrderAssumption(keyValue);
- }
-
- TRY(guard.done());
- return result;
-}
-
-
-JS::Result<Ok>
-BinASTParser::checkEmptyTuple(const BinKind kind, const BinFields& fields)
-{
- if (fields.length() != 0)
- return raiseInvalidField(describeBinKind(kind), fields[0]);
-
+ out.set(Move(atom));
return Ok();
}
JS::Result<Ok>
-BinASTParser::readString(MutableHandleAtom out)
+BinASTParser::readString(Chars& result)
{
- MOZ_ASSERT(!out);
-
- Maybe<Chars> string;
- MOZ_TRY(readString(string));
- MOZ_ASSERT(string);
-
- RootedAtom atom(cx_);
- TRY_VAR(atom, Atomize(cx_, (const char*)string->begin(), string->length()));
-
- out.set(Move(atom));
+ TRY(tokenizer_->readChars(result));
return Ok();
}
-JS::Result<ParseNode*>
-BinASTParser::parsePropertyName()
-{
- RootedAtom atom(cx_);
- MOZ_TRY(readString(&atom));
-
- TokenPos pos = tokenizer_->pos();
-
- ParseNode* result;
-
- // If the atom matches an index (e.g. "3"), we need to normalize the
- // propertyName to ensure that it has the same representation as
- // the numeric index (e.g. 3).
- uint32_t index;
- if (atom->isIndex(&index))
- TRY_VAR(result, factory_.newNumber(index, NoDecimal, pos));
- else
- TRY_VAR(result, factory_.newStringLiteral(atom, pos));
-
- return result;
-}
-
JS::Result<Ok>
-BinASTParser::readString(Maybe<Chars>& out)
+BinASTParser::readMaybeString(Maybe<Chars>& out)
{
MOZ_ASSERT(out.isNothing());
- Chars result(cx_);
- TRY(tokenizer_->readChars(result));
-
- out.emplace(Move(result));
+ TRY(tokenizer_->readMaybeChars(out));
return Ok();
}
JS::Result<double>
BinASTParser::readNumber()
{
double result;
TRY(tokenizer_->readDouble(result));
@@ -2394,16 +395,30 @@ BinASTParser::readBool()
{
bool result;
TRY(tokenizer_->readBool(result));
return result;
}
mozilla::GenericErrorResult<JS::Error&>
+BinASTParser::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");
+}
+
+mozilla::GenericErrorResult<JS::Error&>
+BinASTParser::raiseMissingDirectEvalInAssertedScope()
+{
+ return raiseError("Direct call to `eval` was not declared in AssertedScope");
+}
+
+mozilla::GenericErrorResult<JS::Error&>
BinASTParser::raiseInvalidKind(const char* superKind, const BinKind kind)
{
Sprinter out(cx_);
TRY(out.init());
TRY(out.printf("In %s, invalid kind %s", superKind, describeBinKind(kind)));
return raiseError(out.string());
}
@@ -2412,16 +427,26 @@ BinASTParser::raiseInvalidField(const ch
{
Sprinter out(cx_);
TRY(out.init());
TRY(out.printf("In %s, invalid field '%s'", kind, describeBinField(field)));
return raiseError(out.string());
}
mozilla::GenericErrorResult<JS::Error&>
+BinASTParser::raiseInvalidNumberOfFields(const BinKind kind, const uint32_t expected, const uint32_t got)
+{
+ Sprinter out(cx_);
+ TRY(out.init());
+ TRY(out.printf("In %s, invalid number of fields: expected %u, got %u",
+ describeBinKind(kind), expected, got));
+ return raiseError(out.string());
+}
+
+mozilla::GenericErrorResult<JS::Error&>
BinASTParser::raiseInvalidEnum(const char* kind, const Chars& value)
{
// We don't trust the actual chars of `value` to be properly formatted anything, so let's not use
// them anywhere.
return raiseError("Invalid enum");
}
mozilla::GenericErrorResult<JS::Error&>