tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

FullParseHandler.h (44614B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
      2 * vim: set ts=8 sts=2 et sw=2 tw=80:
      3 * This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #ifndef frontend_FullParseHandler_h
      8 #define frontend_FullParseHandler_h
      9 
     10 #include "mozilla/Maybe.h"   // mozilla::Maybe
     11 #include "mozilla/Result.h"  // mozilla::Result, mozilla::UnusedZero
     12 #include "mozilla/Try.h"     // MOZ_TRY*
     13 
     14 #include <cstddef>  // std::nullptr_t
     15 #include <string.h>
     16 
     17 #include "jstypes.h"
     18 
     19 #include "frontend/CompilationStencil.h"  // CompilationState
     20 #include "frontend/FunctionSyntaxKind.h"  // FunctionSyntaxKind
     21 #include "frontend/NameAnalysisTypes.h"   // PrivateNameKind
     22 #include "frontend/ParseNode.h"
     23 #include "frontend/Parser-macros.h"  // MOZ_TRY_VAR_OR_RETURN
     24 #include "frontend/ParserAtom.h"     // TaggedParserAtomIndex
     25 #include "frontend/SharedContext.h"
     26 #include "frontend/Stencil.h"
     27 
     28 template <>
     29 struct mozilla::detail::UnusedZero<js::frontend::ParseNode*> {
     30  static const bool value = true;
     31 };
     32 
     33 #define DEFINE_UNUSED_ZERO(typeName)                            \
     34  template <>                                                   \
     35  struct mozilla::detail::UnusedZero<js::frontend::typeName*> { \
     36    static const bool value = true;                             \
     37  };
     38 FOR_EACH_PARSENODE_SUBCLASS(DEFINE_UNUSED_ZERO)
     39 #undef DEFINE_UNUSED_ZERO
     40 
     41 namespace js {
     42 namespace frontend {
     43 
     44 class TokenStreamAnyChars;
     45 
     46 // Parse handler used when generating a full parse tree for all code which the
     47 // parser encounters.
     48 class FullParseHandler {
     49  ParseNodeAllocator allocator;
     50 
     51  ParseNode* allocParseNode(size_t size) {
     52    return static_cast<ParseNode*>(allocator.allocNode(size));
     53  }
     54 
     55  // If this is a full parse to construct the bytecode for a function that
     56  // was previously lazily parsed, we still don't want to full parse the
     57  // inner functions. These members are used for this functionality:
     58  //
     59  // - reuseGCThings if ture it means that the following fields are valid.
     60  // - gcThingsData holds an incomplete stencil-like copy of inner functions as
     61  //   well as atoms.
     62  // - scriptData and scriptExtra_ hold information necessary to locate inner
     63  //   functions to skip over each.
     64  // - lazyInnerFunctionIndex is used as we skip over inner functions
     65  //   (see skipLazyInnerFunction),
     66  // - lazyClosedOverBindingIndex is used to synchronize binding computation
     67  //   with the scope traversal.
     68  //   (see propagateFreeNamesAndMarkClosedOverBindings),
     69  const CompilationSyntaxParseCache& previousParseCache_;
     70 
     71  size_t lazyInnerFunctionIndex;
     72  size_t lazyClosedOverBindingIndex;
     73 
     74  bool reuseGCThings;
     75 
     76  /* new_ methods for creating parse nodes. These report OOM on context. */
     77  JS_DECLARE_NEW_METHODS(new_, allocParseNode, inline)
     78 
     79 public:
     80  using NodeError = ParseNodeError;
     81 
     82  using Node = ParseNode*;
     83  using NodeResult = ParseNodeResult;
     84  using NodeErrorResult = mozilla::GenericErrorResult<NodeError>;
     85 
     86 #define DECLARE_TYPE(typeName)      \
     87  using typeName##Type = typeName*; \
     88  using typeName##Result = mozilla::Result<typeName*, NodeError>;
     89  FOR_EACH_PARSENODE_SUBCLASS(DECLARE_TYPE)
     90 #undef DECLARE_TYPE
     91 
     92  template <class T, typename... Args>
     93  inline mozilla::Result<T*, NodeError> newResult(Args&&... args) {
     94    auto* node = new_<T>(std::forward<Args>(args)...);
     95    if (!node) {
     96      return mozilla::Result<T*, NodeError>(NodeError());
     97    }
     98    return node;
     99  }
    100 
    101  using NullNode = std::nullptr_t;
    102 
    103  bool isPropertyOrPrivateMemberAccess(Node node) {
    104    return node->isKind(ParseNodeKind::DotExpr) ||
    105           node->isKind(ParseNodeKind::ElemExpr) ||
    106           node->isKind(ParseNodeKind::PrivateMemberExpr) ||
    107           node->isKind(ParseNodeKind::ArgumentsLength);
    108  }
    109 
    110  bool isOptionalPropertyOrPrivateMemberAccess(Node node) {
    111    return node->isKind(ParseNodeKind::OptionalDotExpr) ||
    112           node->isKind(ParseNodeKind::OptionalElemExpr) ||
    113           node->isKind(ParseNodeKind::PrivateMemberExpr);
    114  }
    115 
    116  bool isFunctionCall(Node node) {
    117    // Note: super() is a special form, *not* a function call.
    118    return node->isKind(ParseNodeKind::CallExpr);
    119  }
    120 
    121  static bool isUnparenthesizedDestructuringPattern(Node node) {
    122    return !node->isInParens() && (node->isKind(ParseNodeKind::ObjectExpr) ||
    123                                   node->isKind(ParseNodeKind::ArrayExpr));
    124  }
    125 
    126  static bool isParenthesizedDestructuringPattern(Node node) {
    127    // Technically this isn't a destructuring pattern at all -- the grammar
    128    // doesn't treat it as such.  But we need to know when this happens to
    129    // consider it a SyntaxError rather than an invalid-left-hand-side
    130    // ReferenceError.
    131    return node->isInParens() && (node->isKind(ParseNodeKind::ObjectExpr) ||
    132                                  node->isKind(ParseNodeKind::ArrayExpr));
    133  }
    134 
    135  FullParseHandler(FrontendContext* fc, CompilationState& compilationState)
    136      : allocator(fc, compilationState.parserAllocScope.alloc()),
    137        previousParseCache_(compilationState.previousParseCache),
    138        lazyInnerFunctionIndex(0),
    139        lazyClosedOverBindingIndex(0),
    140        reuseGCThings(compilationState.input.isDelazifying()) {}
    141 
    142  static NullNode null() { return NullNode(); }
    143  static constexpr NodeErrorResult errorResult() {
    144    return NodeErrorResult(NodeError());
    145  }
    146 
    147 #define DECLARE_AS(typeName)                      \
    148  static typeName##Type as##typeName(Node node) { \
    149    return &node->as<typeName>();                 \
    150  }
    151  FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS)
    152 #undef DECLARE_AS
    153 
    154  NameNodeResult newName(TaggedParserAtomIndex name, const TokenPos& pos) {
    155    return newResult<NameNode>(ParseNodeKind::Name, name, pos);
    156  }
    157 
    158  UnaryNodeResult newComputedName(Node expr, uint32_t begin, uint32_t end) {
    159    TokenPos pos(begin, end);
    160    return newResult<UnaryNode>(ParseNodeKind::ComputedName, pos, expr);
    161  }
    162 
    163  UnaryNodeResult newSyntheticComputedName(Node expr, uint32_t begin,
    164                                           uint32_t end) {
    165    TokenPos pos(begin, end);
    166    UnaryNode* node =
    167        MOZ_TRY(newResult<UnaryNode>(ParseNodeKind::ComputedName, pos, expr));
    168    node->setSyntheticComputedName();
    169    return node;
    170  }
    171 
    172  NameNodeResult newObjectLiteralPropertyName(TaggedParserAtomIndex atom,
    173                                              const TokenPos& pos) {
    174    return newResult<NameNode>(ParseNodeKind::ObjectPropertyName, atom, pos);
    175  }
    176 
    177  NameNodeResult newPrivateName(TaggedParserAtomIndex atom,
    178                                const TokenPos& pos) {
    179    return newResult<NameNode>(ParseNodeKind::PrivateName, atom, pos);
    180  }
    181 
    182  NumericLiteralResult newNumber(double value, DecimalPoint decimalPoint,
    183                                 const TokenPos& pos) {
    184    return newResult<NumericLiteral>(value, decimalPoint, pos);
    185  }
    186 
    187  BigIntLiteralResult newBigInt(BigIntIndex index, const TokenPos& pos) {
    188    return newResult<BigIntLiteral>(index, pos);
    189  }
    190 
    191  BooleanLiteralResult newBooleanLiteral(bool cond, const TokenPos& pos) {
    192    return newResult<BooleanLiteral>(cond, pos);
    193  }
    194 
    195  NameNodeResult newStringLiteral(TaggedParserAtomIndex atom,
    196                                  const TokenPos& pos) {
    197    return newResult<NameNode>(ParseNodeKind::StringExpr, atom, pos);
    198  }
    199 
    200  NameNodeResult newTemplateStringLiteral(TaggedParserAtomIndex atom,
    201                                          const TokenPos& pos) {
    202    return newResult<NameNode>(ParseNodeKind::TemplateStringExpr, atom, pos);
    203  }
    204 
    205  CallSiteNodeResult newCallSiteObject(uint32_t begin) {
    206    CallSiteNode* callSiteObj = MOZ_TRY(newResult<CallSiteNode>(begin));
    207 
    208    ListNode* rawNodes = MOZ_TRY(newArrayLiteral(callSiteObj->pn_pos.begin));
    209 
    210    addArrayElement(callSiteObj, rawNodes);
    211 
    212    return callSiteObj;
    213  }
    214 
    215  void addToCallSiteObject(CallSiteNodeType callSiteObj, Node rawNode,
    216                           Node cookedNode) {
    217    MOZ_ASSERT(callSiteObj->isKind(ParseNodeKind::CallSiteObj));
    218    MOZ_ASSERT(rawNode->isKind(ParseNodeKind::TemplateStringExpr));
    219    MOZ_ASSERT(cookedNode->isKind(ParseNodeKind::TemplateStringExpr) ||
    220               cookedNode->isKind(ParseNodeKind::RawUndefinedExpr));
    221 
    222    addArrayElement(callSiteObj, cookedNode);
    223    addArrayElement(callSiteObj->rawNodes(), rawNode);
    224 
    225    /*
    226     * We don't know when the last noSubstTemplate will come in, and we
    227     * don't want to deal with this outside this method
    228     */
    229    setEndPosition(callSiteObj, callSiteObj->rawNodes());
    230  }
    231 
    232  ThisLiteralResult newThisLiteral(const TokenPos& pos, Node thisName) {
    233    return newResult<ThisLiteral>(pos, thisName);
    234  }
    235 
    236  NullLiteralResult newNullLiteral(const TokenPos& pos) {
    237    return newResult<NullLiteral>(pos);
    238  }
    239 
    240  RawUndefinedLiteralResult newRawUndefinedLiteral(const TokenPos& pos) {
    241    return newResult<RawUndefinedLiteral>(pos);
    242  }
    243 
    244  RegExpLiteralResult newRegExp(RegExpIndex index, const TokenPos& pos) {
    245    return newResult<RegExpLiteral>(index, pos);
    246  }
    247 
    248  ConditionalExpressionResult newConditional(Node cond, Node thenExpr,
    249                                             Node elseExpr) {
    250    return newResult<ConditionalExpression>(cond, thenExpr, elseExpr);
    251  }
    252 
    253  UnaryNodeResult newDelete(uint32_t begin, Node expr) {
    254    if (expr->isKind(ParseNodeKind::Name)) {
    255      return newUnary(ParseNodeKind::DeleteNameExpr, begin, expr);
    256    }
    257 
    258    if (expr->isKind(ParseNodeKind::DotExpr)) {
    259      return newUnary(ParseNodeKind::DeletePropExpr, begin, expr);
    260    }
    261 
    262    if (expr->isKind(ParseNodeKind::ElemExpr)) {
    263      return newUnary(ParseNodeKind::DeleteElemExpr, begin, expr);
    264    }
    265 
    266    if (expr->isKind(ParseNodeKind::OptionalChain)) {
    267      Node kid = expr->as<UnaryNode>().kid();
    268      // Handle property deletion explicitly. OptionalCall is handled
    269      // via DeleteExpr.
    270      if (kid->isKind(ParseNodeKind::DotExpr) ||
    271          kid->isKind(ParseNodeKind::OptionalDotExpr) ||
    272          kid->isKind(ParseNodeKind::ElemExpr) ||
    273          kid->isKind(ParseNodeKind::OptionalElemExpr)) {
    274        return newUnary(ParseNodeKind::DeleteOptionalChainExpr, begin, kid);
    275      }
    276    }
    277 
    278    return newUnary(ParseNodeKind::DeleteExpr, begin, expr);
    279  }
    280 
    281  UnaryNodeResult newTypeof(uint32_t begin, Node kid) {
    282    ParseNodeKind pnk = kid->isKind(ParseNodeKind::Name)
    283                            ? ParseNodeKind::TypeOfNameExpr
    284                            : ParseNodeKind::TypeOfExpr;
    285    return newUnary(pnk, begin, kid);
    286  }
    287 
    288  UnaryNodeResult newUnary(ParseNodeKind kind, uint32_t begin, Node kid) {
    289    TokenPos pos(begin, kid->pn_pos.end);
    290    return newResult<UnaryNode>(kind, pos, kid);
    291  }
    292 
    293  UnaryNodeResult newUpdate(ParseNodeKind kind, uint32_t begin, Node kid) {
    294    TokenPos pos(begin, kid->pn_pos.end);
    295    return newResult<UnaryNode>(kind, pos, kid);
    296  }
    297 
    298  UnaryNodeResult newSpread(uint32_t begin, Node kid) {
    299    TokenPos pos(begin, kid->pn_pos.end);
    300    return newResult<UnaryNode>(ParseNodeKind::Spread, pos, kid);
    301  }
    302 
    303 private:
    304  BinaryNodeResult newBinary(ParseNodeKind kind, Node left, Node right) {
    305    TokenPos pos(left->pn_pos.begin, right->pn_pos.end);
    306    return newResult<BinaryNode>(kind, pos, left, right);
    307  }
    308 
    309 public:
    310  NodeResult appendOrCreateList(ParseNodeKind kind, Node left, Node right,
    311                                ParseContext* pc) {
    312    return ParseNode::appendOrCreateList(kind, left, right, this, pc);
    313  }
    314 
    315  // Expressions
    316 
    317  ListNodeResult newArrayLiteral(uint32_t begin) {
    318    return newResult<ListNode>(ParseNodeKind::ArrayExpr,
    319                               TokenPos(begin, begin + 1));
    320  }
    321 
    322  [[nodiscard]] bool addElision(ListNodeType literal, const TokenPos& pos) {
    323    MOZ_ASSERT(literal->isKind(ParseNodeKind::ArrayExpr));
    324 
    325    NullaryNode* elision;
    326    MOZ_TRY_VAR_OR_RETURN(
    327        elision, newResult<NullaryNode>(ParseNodeKind::Elision, pos), false);
    328    addList(/* list = */ literal, /* kid = */ elision);
    329    literal->setHasNonConstInitializer();
    330    return true;
    331  }
    332 
    333  [[nodiscard]] bool addSpreadElement(ListNodeType literal, uint32_t begin,
    334                                      Node inner) {
    335    MOZ_ASSERT(literal->isKind(ParseNodeKind::ArrayExpr));
    336 
    337    UnaryNodeType spread;
    338    MOZ_TRY_VAR_OR_RETURN(spread, newSpread(begin, inner), false);
    339    addList(/* list = */ literal, /* kid = */ spread);
    340    literal->setHasNonConstInitializer();
    341    return true;
    342  }
    343 
    344  void addArrayElement(ListNodeType literal, Node element) {
    345    MOZ_ASSERT(literal->isKind(ParseNodeKind::ArrayExpr) ||
    346               literal->isKind(ParseNodeKind::CallSiteObj));
    347    if (!element->isConstant()) {
    348      literal->setHasNonConstInitializer();
    349    }
    350    addList(/* list = */ literal, /* kid = */ element);
    351  }
    352 
    353  CallNodeResult newCall(Node callee, ListNodeType args, JSOp callOp) {
    354    return newResult<CallNode>(ParseNodeKind::CallExpr, callOp, callee, args);
    355  }
    356 
    357  CallNodeResult newOptionalCall(Node callee, ListNodeType args, JSOp callOp) {
    358    return newResult<CallNode>(ParseNodeKind::OptionalCallExpr, callOp, callee,
    359                               args);
    360  }
    361 
    362  ListNodeResult newArguments(const TokenPos& pos) {
    363    return newResult<ListNode>(ParseNodeKind::Arguments, pos);
    364  }
    365 
    366  CallNodeResult newSuperCall(Node callee, ListNodeType args, bool isSpread) {
    367    return newResult<CallNode>(
    368        ParseNodeKind::SuperCallExpr,
    369        isSpread ? JSOp::SpreadSuperCall : JSOp::SuperCall, callee, args);
    370  }
    371 
    372  CallNodeResult newTaggedTemplate(Node tag, ListNodeType args, JSOp callOp) {
    373    return newResult<CallNode>(ParseNodeKind::TaggedTemplateExpr, callOp, tag,
    374                               args);
    375  }
    376 
    377  ListNodeResult newObjectLiteral(uint32_t begin) {
    378    return newResult<ListNode>(ParseNodeKind::ObjectExpr,
    379                               TokenPos(begin, begin + 1));
    380  }
    381 
    382  ClassNodeResult newClass(Node name, Node heritage,
    383                           LexicalScopeNodeType memberBlock,
    384 #ifdef ENABLE_DECORATORS
    385                           ListNodeType decorators,
    386                           FunctionNodeType addInitializerFunction,
    387 #endif
    388                           const TokenPos& pos) {
    389    return newResult<ClassNode>(name, heritage, memberBlock,
    390 #ifdef ENABLE_DECORATORS
    391                                decorators, addInitializerFunction,
    392 #endif
    393                                pos);
    394  }
    395  ListNodeResult newClassMemberList(uint32_t begin) {
    396    return newResult<ListNode>(ParseNodeKind::ClassMemberList,
    397                               TokenPos(begin, begin + 1));
    398  }
    399  ClassNamesResult newClassNames(Node outer, Node inner, const TokenPos& pos) {
    400    return newResult<ClassNames>(outer, inner, pos);
    401  }
    402  NewTargetNodeResult newNewTarget(NullaryNodeType newHolder,
    403                                   NullaryNodeType targetHolder,
    404                                   NameNodeType newTargetName) {
    405    return newResult<NewTargetNode>(newHolder, targetHolder, newTargetName);
    406  }
    407  NullaryNodeResult newPosHolder(const TokenPos& pos) {
    408    return newResult<NullaryNode>(ParseNodeKind::PosHolder, pos);
    409  }
    410  UnaryNodeResult newSuperBase(Node thisName, const TokenPos& pos) {
    411    return newResult<UnaryNode>(ParseNodeKind::SuperBase, pos, thisName);
    412  }
    413  [[nodiscard]] bool addPrototypeMutation(ListNodeType literal, uint32_t begin,
    414                                          Node expr) {
    415    MOZ_ASSERT(literal->isKind(ParseNodeKind::ObjectExpr));
    416 
    417    // Object literals with mutated [[Prototype]] are non-constant so that
    418    // singleton objects will have Object.prototype as their [[Prototype]].
    419    literal->setHasNonConstInitializer();
    420 
    421    UnaryNode* mutation;
    422    MOZ_TRY_VAR_OR_RETURN(
    423        mutation, newUnary(ParseNodeKind::MutateProto, begin, expr), false);
    424    addList(/* list = */ literal, /* kid = */ mutation);
    425    return true;
    426  }
    427 
    428  BinaryNodeResult newPropertyDefinition(Node key, Node val) {
    429    MOZ_ASSERT(isUsableAsObjectPropertyName(key));
    430    checkAndSetIsDirectRHSAnonFunction(val);
    431    return newResult<PropertyDefinition>(key, val, AccessorType::None);
    432  }
    433 
    434  void addPropertyDefinition(ListNodeType literal, BinaryNodeType propdef) {
    435    MOZ_ASSERT(literal->isKind(ParseNodeKind::ObjectExpr));
    436    MOZ_ASSERT(propdef->isKind(ParseNodeKind::PropertyDefinition));
    437 
    438    if (!propdef->right()->isConstant()) {
    439      literal->setHasNonConstInitializer();
    440    }
    441 
    442    addList(/* list = */ literal, /* kid = */ propdef);
    443  }
    444 
    445  [[nodiscard]] bool addPropertyDefinition(ListNodeType literal, Node key,
    446                                           Node val) {
    447    BinaryNode* propdef;
    448    MOZ_TRY_VAR_OR_RETURN(propdef, newPropertyDefinition(key, val), false);
    449    addPropertyDefinition(literal, propdef);
    450    return true;
    451  }
    452 
    453  [[nodiscard]] bool addShorthand(ListNodeType literal, NameNodeType name,
    454                                  NameNodeType expr) {
    455    MOZ_ASSERT(literal->isKind(ParseNodeKind::ObjectExpr));
    456    MOZ_ASSERT(name->isKind(ParseNodeKind::ObjectPropertyName));
    457    MOZ_ASSERT(expr->isKind(ParseNodeKind::Name));
    458    MOZ_ASSERT(name->atom() == expr->atom());
    459 
    460    literal->setHasNonConstInitializer();
    461    BinaryNode* propdef;
    462    MOZ_TRY_VAR_OR_RETURN(
    463        propdef, newBinary(ParseNodeKind::Shorthand, name, expr), false);
    464    addList(/* list = */ literal, /* kid = */ propdef);
    465    return true;
    466  }
    467 
    468  [[nodiscard]] bool addSpreadProperty(ListNodeType literal, uint32_t begin,
    469                                       Node inner) {
    470    MOZ_ASSERT(literal->isKind(ParseNodeKind::ObjectExpr));
    471 
    472    literal->setHasNonConstInitializer();
    473    ParseNode* spread;
    474    MOZ_TRY_VAR_OR_RETURN(spread, newSpread(begin, inner), false);
    475    addList(/* list = */ literal, /* kid = */ spread);
    476    return true;
    477  }
    478 
    479  [[nodiscard]] bool addObjectMethodDefinition(ListNodeType literal, Node key,
    480                                               FunctionNodeType funNode,
    481                                               AccessorType atype) {
    482    literal->setHasNonConstInitializer();
    483 
    484    checkAndSetIsDirectRHSAnonFunction(funNode);
    485 
    486    ParseNode* propdef;
    487    MOZ_TRY_VAR_OR_RETURN(
    488        propdef, newObjectMethodOrPropertyDefinition(key, funNode, atype),
    489        false);
    490    addList(/* list = */ literal, /* kid = */ propdef);
    491    return true;
    492  }
    493 
    494  [[nodiscard]] ClassMethodResult newDefaultClassConstructor(
    495      Node key, FunctionNodeType funNode) {
    496    MOZ_ASSERT(isUsableAsObjectPropertyName(key));
    497 
    498    checkAndSetIsDirectRHSAnonFunction(funNode);
    499 
    500    return newResult<ClassMethod>(
    501        ParseNodeKind::DefaultConstructor, key, funNode, AccessorType::None,
    502        /* isStatic = */ false, /* initializeIfPrivate = */ nullptr
    503 #ifdef ENABLE_DECORATORS
    504        ,
    505        /* decorators = */ nullptr
    506 #endif
    507    );
    508  }
    509 
    510  [[nodiscard]] ClassMethodResult newClassMethodDefinition(
    511      Node key, FunctionNodeType funNode, AccessorType atype, bool isStatic,
    512      mozilla::Maybe<FunctionNodeType> initializerIfPrivate
    513 #ifdef ENABLE_DECORATORS
    514      ,
    515      ListNodeType decorators
    516 #endif
    517  ) {
    518    MOZ_ASSERT(isUsableAsObjectPropertyName(key));
    519 
    520    checkAndSetIsDirectRHSAnonFunction(funNode);
    521 
    522    if (initializerIfPrivate.isSome()) {
    523      return newResult<ClassMethod>(ParseNodeKind::ClassMethod, key, funNode,
    524                                    atype, isStatic,
    525                                    initializerIfPrivate.value()
    526 #ifdef ENABLE_DECORATORS
    527                                        ,
    528                                    decorators
    529 #endif
    530      );
    531    }
    532    return newResult<ClassMethod>(ParseNodeKind::ClassMethod, key, funNode,
    533                                  atype, isStatic,
    534                                  /* initializeIfPrivate = */ nullptr
    535 #ifdef ENABLE_DECORATORS
    536                                  ,
    537                                  decorators
    538 #endif
    539    );
    540  }
    541 
    542  [[nodiscard]] ClassFieldResult newClassFieldDefinition(
    543      Node name, FunctionNodeType initializer, bool isStatic
    544 #ifdef ENABLE_DECORATORS
    545      ,
    546      ListNodeType decorators, ClassMethodType accessorGetterNode,
    547      ClassMethodType accessorSetterNode
    548 #endif
    549  ) {
    550    MOZ_ASSERT(isUsableAsObjectPropertyName(name));
    551 
    552    return newResult<ClassField>(name, initializer, isStatic
    553 #if ENABLE_DECORATORS
    554                                 ,
    555                                 decorators, accessorGetterNode,
    556                                 accessorSetterNode
    557 #endif
    558    );
    559  }
    560 
    561  [[nodiscard]] StaticClassBlockResult newStaticClassBlock(
    562      FunctionNodeType block) {
    563    return newResult<StaticClassBlock>(block);
    564  }
    565 
    566  [[nodiscard]] bool addClassMemberDefinition(ListNodeType memberList,
    567                                              Node member) {
    568    MOZ_ASSERT(memberList->isKind(ParseNodeKind::ClassMemberList));
    569    // Constructors can be surrounded by LexicalScopes.
    570    MOZ_ASSERT(member->isKind(ParseNodeKind::DefaultConstructor) ||
    571               member->isKind(ParseNodeKind::ClassMethod) ||
    572               member->isKind(ParseNodeKind::ClassField) ||
    573               member->isKind(ParseNodeKind::StaticClassBlock) ||
    574               (member->isKind(ParseNodeKind::LexicalScope) &&
    575                member->as<LexicalScopeNode>().scopeBody()->is<ClassMethod>()));
    576 
    577    addList(/* list = */ memberList, /* kid = */ member);
    578    return true;
    579  }
    580 
    581  UnaryNodeResult newInitialYieldExpression(uint32_t begin, Node gen) {
    582    TokenPos pos(begin, begin + 1);
    583    return newResult<UnaryNode>(ParseNodeKind::InitialYield, pos, gen);
    584  }
    585 
    586  UnaryNodeResult newYieldExpression(uint32_t begin, Node value) {
    587    TokenPos pos(begin, value ? value->pn_pos.end : begin + 1);
    588    return newResult<UnaryNode>(ParseNodeKind::YieldExpr, pos, value);
    589  }
    590 
    591  UnaryNodeResult newYieldStarExpression(uint32_t begin, Node value) {
    592    TokenPos pos(begin, value->pn_pos.end);
    593    return newResult<UnaryNode>(ParseNodeKind::YieldStarExpr, pos, value);
    594  }
    595 
    596  UnaryNodeResult newAwaitExpression(uint32_t begin, Node value) {
    597    TokenPos pos(begin, value ? value->pn_pos.end : begin + 1);
    598    return newResult<UnaryNode>(ParseNodeKind::AwaitExpr, pos, value);
    599  }
    600 
    601  UnaryNodeResult newOptionalChain(uint32_t begin, Node value) {
    602    TokenPos pos(begin, value->pn_pos.end);
    603    return newResult<UnaryNode>(ParseNodeKind::OptionalChain, pos, value);
    604  }
    605 
    606  // Statements
    607 
    608  ListNodeResult newStatementList(const TokenPos& pos) {
    609    return newResult<ListNode>(ParseNodeKind::StatementList, pos);
    610  }
    611 
    612  [[nodiscard]] bool isFunctionStmt(Node stmt) {
    613    while (stmt->isKind(ParseNodeKind::LabelStmt)) {
    614      stmt = stmt->as<LabeledStatement>().statement();
    615    }
    616    return stmt->is<FunctionNode>();
    617  }
    618 
    619  void addStatementToList(ListNodeType list, Node stmt) {
    620    MOZ_ASSERT(list->isKind(ParseNodeKind::StatementList));
    621 
    622    addList(/* list = */ list, /* kid = */ stmt);
    623 
    624    if (isFunctionStmt(stmt)) {
    625      // Notify the emitter that the block contains body-level function
    626      // definitions that should be processed before the rest of nodes.
    627      list->setHasTopLevelFunctionDeclarations();
    628    }
    629  }
    630 
    631  void setListEndPosition(ListNodeType list, const TokenPos& pos) {
    632    MOZ_ASSERT(list->isKind(ParseNodeKind::StatementList));
    633    list->pn_pos.end = pos.end;
    634  }
    635 
    636  void addCaseStatementToList(ListNodeType list, CaseClauseType caseClause) {
    637    MOZ_ASSERT(list->isKind(ParseNodeKind::StatementList));
    638 
    639    addList(/* list = */ list, /* kid = */ caseClause);
    640 
    641    if (caseClause->statementList()->hasTopLevelFunctionDeclarations()) {
    642      list->setHasTopLevelFunctionDeclarations();
    643    }
    644  }
    645 
    646  [[nodiscard]] bool prependInitialYield(ListNodeType stmtList, Node genName) {
    647    MOZ_ASSERT(stmtList->isKind(ParseNodeKind::StatementList));
    648 
    649    TokenPos yieldPos(stmtList->pn_pos.begin, stmtList->pn_pos.begin + 1);
    650    NullaryNode* makeGen;
    651    MOZ_TRY_VAR_OR_RETURN(
    652        makeGen, newResult<NullaryNode>(ParseNodeKind::Generator, yieldPos),
    653        false);
    654 
    655    ParseNode* genInit;
    656    MOZ_TRY_VAR_OR_RETURN(
    657        genInit,
    658        newAssignment(ParseNodeKind::AssignExpr, /* lhs = */ genName,
    659                      /* rhs = */ makeGen),
    660        false);
    661 
    662    UnaryNode* initialYield;
    663    MOZ_TRY_VAR_OR_RETURN(initialYield,
    664                          newInitialYieldExpression(yieldPos.begin, genInit),
    665                          false);
    666 
    667    stmtList->prepend(initialYield);
    668    return true;
    669  }
    670 
    671  BinaryNodeResult newSetThis(Node thisName, Node value) {
    672    return newBinary(ParseNodeKind::SetThis, thisName, value);
    673  }
    674 
    675  NullaryNodeResult newEmptyStatement(const TokenPos& pos) {
    676    return newResult<NullaryNode>(ParseNodeKind::EmptyStmt, pos);
    677  }
    678 
    679  BinaryNodeResult newImportAttribute(Node keyNode, Node valueNode) {
    680    return newBinary(ParseNodeKind::ImportAttribute, keyNode, valueNode);
    681  }
    682 
    683  BinaryNodeResult newModuleRequest(Node moduleSpec, Node importAttributeList,
    684                                    const TokenPos& pos) {
    685    return newResult<BinaryNode>(ParseNodeKind::ImportModuleRequest, pos,
    686                                 moduleSpec, importAttributeList);
    687  }
    688 
    689  BinaryNodeResult newImportDeclaration(Node importSpecSet, Node moduleRequest,
    690                                        const TokenPos& pos) {
    691    return newResult<BinaryNode>(ParseNodeKind::ImportDecl, pos, importSpecSet,
    692                                 moduleRequest);
    693  }
    694 
    695  BinaryNodeResult newImportSpec(Node importNameNode, Node bindingName) {
    696    return newBinary(ParseNodeKind::ImportSpec, importNameNode, bindingName);
    697  }
    698 
    699  UnaryNodeResult newImportNamespaceSpec(uint32_t begin, Node bindingName) {
    700    return newUnary(ParseNodeKind::ImportNamespaceSpec, begin, bindingName);
    701  }
    702 
    703  UnaryNodeResult newExportDeclaration(Node kid, const TokenPos& pos) {
    704    return newResult<UnaryNode>(ParseNodeKind::ExportStmt, pos, kid);
    705  }
    706 
    707  BinaryNodeResult newExportFromDeclaration(uint32_t begin, Node exportSpecSet,
    708                                            Node moduleRequest) {
    709    BinaryNode* decl = MOZ_TRY(newResult<BinaryNode>(
    710        ParseNodeKind::ExportFromStmt, exportSpecSet, moduleRequest));
    711    decl->pn_pos.begin = begin;
    712    return decl;
    713  }
    714 
    715  BinaryNodeResult newExportDefaultDeclaration(Node kid, Node maybeBinding,
    716                                               const TokenPos& pos) {
    717    if (maybeBinding) {
    718      MOZ_ASSERT(maybeBinding->isKind(ParseNodeKind::Name));
    719      MOZ_ASSERT(!maybeBinding->isInParens());
    720 
    721      checkAndSetIsDirectRHSAnonFunction(kid);
    722    }
    723 
    724    return newResult<BinaryNode>(ParseNodeKind::ExportDefaultStmt, pos, kid,
    725                                 maybeBinding);
    726  }
    727 
    728  BinaryNodeResult newExportSpec(Node bindingName, Node exportName) {
    729    return newBinary(ParseNodeKind::ExportSpec, bindingName, exportName);
    730  }
    731 
    732  UnaryNodeResult newExportNamespaceSpec(uint32_t begin, Node exportName) {
    733    return newUnary(ParseNodeKind::ExportNamespaceSpec, begin, exportName);
    734  }
    735 
    736  NullaryNodeResult newExportBatchSpec(const TokenPos& pos) {
    737    return newResult<NullaryNode>(ParseNodeKind::ExportBatchSpecStmt, pos);
    738  }
    739 
    740  BinaryNodeResult newImportMeta(NullaryNodeType importHolder,
    741                                 NullaryNodeType metaHolder) {
    742    return newResult<BinaryNode>(ParseNodeKind::ImportMetaExpr, importHolder,
    743                                 metaHolder);
    744  }
    745 
    746  BinaryNodeResult newCallImport(NullaryNodeType importHolder, Node singleArg) {
    747    return newResult<BinaryNode>(ParseNodeKind::CallImportExpr, importHolder,
    748                                 singleArg);
    749  }
    750 
    751  BinaryNodeResult newCallImportSpec(Node specifierArg, Node optionalArg) {
    752    return newResult<BinaryNode>(ParseNodeKind::CallImportSpec, specifierArg,
    753                                 optionalArg);
    754  }
    755 
    756  UnaryNodeResult newExprStatement(Node expr, uint32_t end) {
    757    MOZ_ASSERT(expr->pn_pos.end <= end);
    758    return newResult<UnaryNode>(ParseNodeKind::ExpressionStmt,
    759                                TokenPos(expr->pn_pos.begin, end), expr);
    760  }
    761 
    762  TernaryNodeResult newIfStatement(uint32_t begin, Node cond, Node thenBranch,
    763                                   Node elseBranch) {
    764    TernaryNode* node = MOZ_TRY(newResult<TernaryNode>(
    765        ParseNodeKind::IfStmt, cond, thenBranch, elseBranch));
    766    node->pn_pos.begin = begin;
    767    return node;
    768  }
    769 
    770  BinaryNodeResult newDoWhileStatement(Node body, Node cond,
    771                                       const TokenPos& pos) {
    772    return newResult<BinaryNode>(ParseNodeKind::DoWhileStmt, pos, body, cond);
    773  }
    774 
    775  BinaryNodeResult newWhileStatement(uint32_t begin, Node cond, Node body) {
    776    TokenPos pos(begin, body->pn_pos.end);
    777    return newResult<BinaryNode>(ParseNodeKind::WhileStmt, pos, cond, body);
    778  }
    779 
    780  ForNodeResult newForStatement(uint32_t begin, TernaryNodeType forHead,
    781                                Node body, unsigned iflags) {
    782    return newResult<ForNode>(TokenPos(begin, body->pn_pos.end), forHead, body,
    783                              iflags);
    784  }
    785 
    786  TernaryNodeResult newForHead(Node init, Node test, Node update,
    787                               const TokenPos& pos) {
    788    return newResult<TernaryNode>(ParseNodeKind::ForHead, init, test, update,
    789                                  pos);
    790  }
    791 
    792  TernaryNodeResult newForInOrOfHead(ParseNodeKind kind, Node target,
    793                                     Node iteratedExpr, const TokenPos& pos) {
    794    MOZ_ASSERT(kind == ParseNodeKind::ForIn || kind == ParseNodeKind::ForOf);
    795    return newResult<TernaryNode>(kind, target, nullptr, iteratedExpr, pos);
    796  }
    797 
    798  SwitchStatementResult newSwitchStatement(
    799      uint32_t begin, Node discriminant,
    800      LexicalScopeNodeType lexicalForCaseList, bool hasDefault) {
    801    return newResult<SwitchStatement>(begin, discriminant, lexicalForCaseList,
    802                                      hasDefault);
    803  }
    804 
    805  CaseClauseResult newCaseOrDefault(uint32_t begin, Node expr, Node body) {
    806    return newResult<CaseClause>(expr, body, begin);
    807  }
    808 
    809  ContinueStatementResult newContinueStatement(TaggedParserAtomIndex label,
    810                                               const TokenPos& pos) {
    811    return newResult<ContinueStatement>(label, pos);
    812  }
    813 
    814  BreakStatementResult newBreakStatement(TaggedParserAtomIndex label,
    815                                         const TokenPos& pos) {
    816    return newResult<BreakStatement>(label, pos);
    817  }
    818 
    819  UnaryNodeResult newReturnStatement(Node expr, const TokenPos& pos) {
    820    MOZ_ASSERT_IF(expr, pos.encloses(expr->pn_pos));
    821    return newResult<UnaryNode>(ParseNodeKind::ReturnStmt, pos, expr);
    822  }
    823 
    824  UnaryNodeResult newExpressionBody(Node expr) {
    825    return newResult<UnaryNode>(ParseNodeKind::ReturnStmt, expr->pn_pos, expr);
    826  }
    827 
    828  BinaryNodeResult newWithStatement(uint32_t begin, Node expr, Node body) {
    829    return newResult<BinaryNode>(ParseNodeKind::WithStmt,
    830                                 TokenPos(begin, body->pn_pos.end), expr, body);
    831  }
    832 
    833  LabeledStatementResult newLabeledStatement(TaggedParserAtomIndex label,
    834                                             Node stmt, uint32_t begin) {
    835    return newResult<LabeledStatement>(label, stmt, begin);
    836  }
    837 
    838  UnaryNodeResult newThrowStatement(Node expr, const TokenPos& pos) {
    839    MOZ_ASSERT(pos.encloses(expr->pn_pos));
    840    return newResult<UnaryNode>(ParseNodeKind::ThrowStmt, pos, expr);
    841  }
    842 
    843  TernaryNodeResult newTryStatement(uint32_t begin, Node body,
    844                                    LexicalScopeNodeType catchScope,
    845                                    Node finallyBlock) {
    846    return newResult<TryNode>(begin, body, catchScope, finallyBlock);
    847  }
    848 
    849  DebuggerStatementResult newDebuggerStatement(const TokenPos& pos) {
    850    return newResult<DebuggerStatement>(pos);
    851  }
    852 
    853  NameNodeResult newPropertyName(TaggedParserAtomIndex name,
    854                                 const TokenPos& pos) {
    855    return newResult<NameNode>(ParseNodeKind::PropertyNameExpr, name, pos);
    856  }
    857 
    858  PropertyAccessResult newPropertyAccess(Node expr, NameNodeType key) {
    859    return newResult<PropertyAccess>(expr, key, expr->pn_pos.begin,
    860                                     key->pn_pos.end);
    861  }
    862 
    863  ArgumentsLengthResult newArgumentsLength(Node expr, NameNodeType key) {
    864    return newResult<ArgumentsLength>(expr, key, expr->pn_pos.begin,
    865                                      key->pn_pos.end);
    866  }
    867 
    868  PropertyByValueResult newPropertyByValue(Node lhs, Node index, uint32_t end) {
    869    return newResult<PropertyByValue>(lhs, index, lhs->pn_pos.begin, end);
    870  }
    871 
    872  OptionalPropertyAccessResult newOptionalPropertyAccess(Node expr,
    873                                                         NameNodeType key) {
    874    return newResult<OptionalPropertyAccess>(expr, key, expr->pn_pos.begin,
    875                                             key->pn_pos.end);
    876  }
    877 
    878  OptionalPropertyByValueResult newOptionalPropertyByValue(Node lhs, Node index,
    879                                                           uint32_t end) {
    880    return newResult<OptionalPropertyByValue>(lhs, index, lhs->pn_pos.begin,
    881                                              end);
    882  }
    883 
    884  PrivateMemberAccessResult newPrivateMemberAccess(Node lhs,
    885                                                   NameNodeType privateName,
    886                                                   uint32_t end) {
    887    return newResult<PrivateMemberAccess>(lhs, privateName, lhs->pn_pos.begin,
    888                                          end);
    889  }
    890 
    891  OptionalPrivateMemberAccessResult newOptionalPrivateMemberAccess(
    892      Node lhs, NameNodeType privateName, uint32_t end) {
    893    return newResult<OptionalPrivateMemberAccess>(lhs, privateName,
    894                                                  lhs->pn_pos.begin, end);
    895  }
    896 
    897  bool setupCatchScope(LexicalScopeNodeType lexicalScope, Node catchName,
    898                       Node catchBody) {
    899    BinaryNode* catchClause;
    900    if (catchName) {
    901      MOZ_TRY_VAR_OR_RETURN(
    902          catchClause,
    903          newResult<BinaryNode>(ParseNodeKind::Catch, catchName, catchBody),
    904          false);
    905    } else {
    906      MOZ_TRY_VAR_OR_RETURN(
    907          catchClause,
    908          newResult<BinaryNode>(ParseNodeKind::Catch, catchBody->pn_pos,
    909                                catchName, catchBody),
    910          false);
    911    }
    912    lexicalScope->setScopeBody(catchClause);
    913    return true;
    914  }
    915 
    916  [[nodiscard]] inline bool setLastFunctionFormalParameterDefault(
    917      FunctionNodeType funNode, Node defaultValue);
    918 
    919  void checkAndSetIsDirectRHSAnonFunction(Node pn) {
    920    if (IsAnonymousFunctionDefinition(pn)) {
    921      pn->setDirectRHSAnonFunction(true);
    922    }
    923  }
    924 
    925  ParamsBodyNodeResult newParamsBody(const TokenPos& pos) {
    926    return newResult<ParamsBodyNode>(pos);
    927  }
    928 
    929  FunctionNodeResult newFunction(FunctionSyntaxKind syntaxKind,
    930                                 const TokenPos& pos) {
    931    return newResult<FunctionNode>(syntaxKind, pos);
    932  }
    933 
    934  BinaryNodeResult newObjectMethodOrPropertyDefinition(Node key, Node value,
    935                                                       AccessorType atype) {
    936    MOZ_ASSERT(isUsableAsObjectPropertyName(key));
    937 
    938    return newResult<PropertyDefinition>(key, value, atype);
    939  }
    940 
    941  void setFunctionFormalParametersAndBody(FunctionNodeType funNode,
    942                                          ParamsBodyNodeType paramsBody) {
    943    funNode->setBody(paramsBody);
    944  }
    945  void setFunctionBox(FunctionNodeType funNode, FunctionBox* funbox) {
    946    funNode->setFunbox(funbox);
    947    funbox->functionNode = funNode;
    948  }
    949  void addFunctionFormalParameter(FunctionNodeType funNode, Node argpn) {
    950    addList(/* list = */ funNode->body(), /* kid = */ argpn);
    951  }
    952  void setFunctionBody(FunctionNodeType funNode, LexicalScopeNodeType body) {
    953    addList(/* list = */ funNode->body(), /* kid = */ body);
    954  }
    955 
    956  ModuleNodeResult newModule(const TokenPos& pos) {
    957    return newResult<ModuleNode>(pos);
    958  }
    959 
    960  LexicalScopeNodeResult newLexicalScope(LexicalScope::ParserData* bindings,
    961                                         Node body,
    962                                         ScopeKind kind = ScopeKind::Lexical) {
    963    return newResult<LexicalScopeNode>(bindings, body, kind);
    964  }
    965 
    966  ClassBodyScopeNodeResult newClassBodyScope(
    967      ClassBodyScope::ParserData* bindings, ListNodeType body) {
    968    return newResult<ClassBodyScopeNode>(bindings, body);
    969  }
    970 
    971  CallNodeResult newNewExpression(uint32_t begin, Node ctor, ListNodeType args,
    972                                  bool isSpread) {
    973    return newResult<CallNode>(ParseNodeKind::NewExpr,
    974                               isSpread ? JSOp::SpreadNew : JSOp::New,
    975                               TokenPos(begin, args->pn_pos.end), ctor, args);
    976  }
    977 
    978  AssignmentNodeResult newAssignment(ParseNodeKind kind, Node lhs, Node rhs) {
    979    if ((kind == ParseNodeKind::AssignExpr ||
    980         kind == ParseNodeKind::CoalesceAssignExpr ||
    981         kind == ParseNodeKind::OrAssignExpr ||
    982         kind == ParseNodeKind::AndAssignExpr) &&
    983        lhs->isKind(ParseNodeKind::Name) && !lhs->isInParens()) {
    984      checkAndSetIsDirectRHSAnonFunction(rhs);
    985    }
    986 
    987    return newResult<AssignmentNode>(kind, lhs, rhs);
    988  }
    989 
    990  BinaryNodeResult newInitExpr(Node lhs, Node rhs) {
    991    TokenPos pos(lhs->pn_pos.begin, rhs->pn_pos.end);
    992    return newResult<BinaryNode>(ParseNodeKind::InitExpr, pos, lhs, rhs);
    993  }
    994 
    995  bool isUnparenthesizedAssignment(Node node) {
    996    if ((node->isKind(ParseNodeKind::AssignExpr)) && !node->isInParens()) {
    997      return true;
    998    }
    999 
   1000    return false;
   1001  }
   1002 
   1003  bool isUnparenthesizedUnaryExpression(Node node) {
   1004    if (!node->isInParens()) {
   1005      ParseNodeKind kind = node->getKind();
   1006      return kind == ParseNodeKind::VoidExpr ||
   1007             kind == ParseNodeKind::NotExpr ||
   1008             kind == ParseNodeKind::BitNotExpr ||
   1009             kind == ParseNodeKind::PosExpr || kind == ParseNodeKind::NegExpr ||
   1010             kind == ParseNodeKind::AwaitExpr || IsTypeofKind(kind) ||
   1011             IsDeleteKind(kind);
   1012    }
   1013    return false;
   1014  }
   1015 
   1016  bool isReturnStatement(Node node) {
   1017    return node->isKind(ParseNodeKind::ReturnStmt);
   1018  }
   1019 
   1020  bool isStatementPermittedAfterReturnStatement(Node node) {
   1021    ParseNodeKind kind = node->getKind();
   1022    return kind == ParseNodeKind::Function || kind == ParseNodeKind::VarStmt ||
   1023           kind == ParseNodeKind::BreakStmt ||
   1024           kind == ParseNodeKind::ThrowStmt || kind == ParseNodeKind::EmptyStmt;
   1025  }
   1026 
   1027  bool isSuperBase(Node node) { return node->isKind(ParseNodeKind::SuperBase); }
   1028 
   1029  bool isUsableAsObjectPropertyName(Node node) {
   1030    return node->isKind(ParseNodeKind::NumberExpr) ||
   1031           node->isKind(ParseNodeKind::BigIntExpr) ||
   1032           node->isKind(ParseNodeKind::ObjectPropertyName) ||
   1033           node->isKind(ParseNodeKind::StringExpr) ||
   1034           node->isKind(ParseNodeKind::ComputedName) ||
   1035           node->isKind(ParseNodeKind::PrivateName);
   1036  }
   1037 
   1038  AssignmentNodeResult finishInitializerAssignment(NameNodeType nameNode,
   1039                                                   Node init) {
   1040    MOZ_ASSERT(nameNode->isKind(ParseNodeKind::Name));
   1041    MOZ_ASSERT(!nameNode->isInParens());
   1042 
   1043    checkAndSetIsDirectRHSAnonFunction(init);
   1044 
   1045    return newAssignment(ParseNodeKind::AssignExpr, nameNode, init);
   1046  }
   1047 
   1048  void setBeginPosition(Node pn, Node oth) {
   1049    setBeginPosition(pn, oth->pn_pos.begin);
   1050  }
   1051  void setBeginPosition(Node pn, uint32_t begin) {
   1052    pn->pn_pos.begin = begin;
   1053    MOZ_ASSERT(pn->pn_pos.begin <= pn->pn_pos.end);
   1054  }
   1055 
   1056  void setEndPosition(Node pn, Node oth) {
   1057    setEndPosition(pn, oth->pn_pos.end);
   1058  }
   1059  void setEndPosition(Node pn, uint32_t end) {
   1060    pn->pn_pos.end = end;
   1061    MOZ_ASSERT(pn->pn_pos.begin <= pn->pn_pos.end);
   1062  }
   1063 
   1064  uint32_t getFunctionNameOffset(Node func, TokenStreamAnyChars& ts) {
   1065    return func->pn_pos.begin;
   1066  }
   1067 
   1068  ListNodeResult newList(ParseNodeKind kind, const TokenPos& pos) {
   1069    auto list = newResult<ListNode>(kind, pos);
   1070    MOZ_ASSERT_IF(list.isOk(), !list.unwrap()->is<DeclarationListNode>());
   1071    MOZ_ASSERT_IF(list.isOk(), !list.unwrap()->is<ParamsBodyNode>());
   1072    return list;
   1073  }
   1074 
   1075  ListNodeResult newList(ParseNodeKind kind, Node kid) {
   1076    auto list = newResult<ListNode>(kind, kid);
   1077    MOZ_ASSERT_IF(list.isOk(), !list.unwrap()->is<DeclarationListNode>());
   1078    MOZ_ASSERT_IF(list.isOk(), !list.unwrap()->is<ParamsBodyNode>());
   1079    return list;
   1080  }
   1081 
   1082  DeclarationListNodeResult newDeclarationList(ParseNodeKind kind,
   1083                                               const TokenPos& pos) {
   1084    return newResult<DeclarationListNode>(kind, pos);
   1085  }
   1086 
   1087  ListNodeResult newCommaExpressionList(Node kid) {
   1088    return newResult<ListNode>(ParseNodeKind::CommaExpr, kid);
   1089  }
   1090 
   1091  void addList(ListNodeType list, Node kid) { list->append(kid); }
   1092 
   1093  void setListHasNonConstInitializer(ListNodeType literal) {
   1094    literal->setHasNonConstInitializer();
   1095  }
   1096 
   1097  // NOTE: This is infallible.
   1098  template <typename NodeType>
   1099  [[nodiscard]] NodeType parenthesize(NodeType node) {
   1100    node->setInParens(true);
   1101    return node;
   1102  }
   1103 
   1104  // NOTE: This is infallible.
   1105  template <typename NodeType>
   1106  [[nodiscard]] NodeType setLikelyIIFE(NodeType node) {
   1107    return parenthesize(node);
   1108  }
   1109 
   1110  bool isName(Node node) { return node->isKind(ParseNodeKind::Name); }
   1111 
   1112  bool isArgumentsName(Node node) {
   1113    return node->isKind(ParseNodeKind::Name) &&
   1114           node->as<NameNode>().atom() ==
   1115               TaggedParserAtomIndex::WellKnown::arguments();
   1116  }
   1117 
   1118  bool isLengthName(Node node) {
   1119    return node->isKind(ParseNodeKind::PropertyNameExpr) &&
   1120           node->as<NameNode>().atom() ==
   1121               TaggedParserAtomIndex::WellKnown::length();
   1122  }
   1123 
   1124  bool isEvalName(Node node) {
   1125    return node->isKind(ParseNodeKind::Name) &&
   1126           node->as<NameNode>().atom() ==
   1127               TaggedParserAtomIndex::WellKnown::eval();
   1128  }
   1129 
   1130  bool isAsyncKeyword(Node node) {
   1131    return node->isKind(ParseNodeKind::Name) &&
   1132           node->pn_pos.begin + strlen("async") == node->pn_pos.end &&
   1133           node->as<NameNode>().atom() ==
   1134               TaggedParserAtomIndex::WellKnown::async();
   1135  }
   1136 
   1137  bool isArgumentsLength(Node node) {
   1138    return node->isKind(ParseNodeKind::ArgumentsLength);
   1139  }
   1140 
   1141  bool isPrivateName(Node node) {
   1142    return node->isKind(ParseNodeKind::PrivateName);
   1143  }
   1144 
   1145  bool isPrivateMemberAccess(Node node) {
   1146    if (node->isKind(ParseNodeKind::OptionalChain)) {
   1147      return isPrivateMemberAccess(node->as<UnaryNode>().kid());
   1148    }
   1149    return node->is<PrivateMemberAccessBase>();
   1150  }
   1151 
   1152  TaggedParserAtomIndex maybeDottedProperty(Node pn) {
   1153    return pn->is<PropertyAccessBase>() ? pn->as<PropertyAccessBase>().name()
   1154                                        : TaggedParserAtomIndex::null();
   1155  }
   1156  TaggedParserAtomIndex isStringExprStatement(Node pn, TokenPos* pos) {
   1157    if (pn->is<UnaryNode>()) {
   1158      UnaryNode* unary = &pn->as<UnaryNode>();
   1159      if (auto atom = unary->isStringExprStatement()) {
   1160        *pos = unary->kid()->pn_pos;
   1161        return atom;
   1162      }
   1163    }
   1164    return TaggedParserAtomIndex::null();
   1165  }
   1166 
   1167  bool reuseLazyInnerFunctions() { return reuseGCThings; }
   1168  bool reuseClosedOverBindings() { return reuseGCThings; }
   1169  bool reuseRegexpSyntaxParse() { return reuseGCThings; }
   1170  void nextLazyInnerFunction() { lazyInnerFunctionIndex++; }
   1171  TaggedParserAtomIndex nextLazyClosedOverBinding() {
   1172    // Trailing nullptrs were elided in PerHandlerParser::finishFunction().
   1173    auto closedOverBindings = previousParseCache_.closedOverBindings();
   1174    if (lazyClosedOverBindingIndex >= closedOverBindings.Length()) {
   1175      return TaggedParserAtomIndex::null();
   1176    }
   1177 
   1178    return closedOverBindings[lazyClosedOverBindingIndex++];
   1179  }
   1180  const ScriptStencil& cachedScriptData() const {
   1181    // lazyInnerFunctionIndex is incremented with nextLazyInnferFunction before
   1182    // reading the content, thus we need -1 to access the element that we just
   1183    // skipped.
   1184    return previousParseCache_.scriptData(lazyInnerFunctionIndex - 1);
   1185  }
   1186  const ScriptStencilExtra& cachedScriptExtra() const {
   1187    // lazyInnerFunctionIndex is incremented with nextLazyInnferFunction before
   1188    // reading the content, thus we need -1 to access the element that we just
   1189    // skipped.
   1190    return previousParseCache_.scriptExtra(lazyInnerFunctionIndex - 1);
   1191  }
   1192 
   1193  void setPrivateNameKind(Node node, PrivateNameKind kind) {
   1194    MOZ_ASSERT(node->is<NameNode>());
   1195    node->as<NameNode>().setPrivateNameKind(kind);
   1196  }
   1197 };
   1198 
   1199 inline bool FullParseHandler::setLastFunctionFormalParameterDefault(
   1200    FunctionNodeType funNode, Node defaultValue) {
   1201  ParamsBodyNode* body = funNode->body();
   1202  ParseNode* arg = body->last();
   1203  ParseNode* pn;
   1204  MOZ_TRY_VAR_OR_RETURN(
   1205      pn, newAssignment(ParseNodeKind::AssignExpr, arg, defaultValue), false);
   1206 
   1207  body->replaceLast(pn);
   1208  return true;
   1209 }
   1210 
   1211 }  // namespace frontend
   1212 }  // namespace js
   1213 
   1214 #endif /* frontend_FullParseHandler_h */