tor-browser

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

ParseNode.h (90021B)


      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_ParseNode_h
      8 #define frontend_ParseNode_h
      9 
     10 #include "mozilla/Assertions.h"
     11 
     12 #include <iterator>
     13 #include <stddef.h>
     14 #include <stdint.h>
     15 
     16 #include "jstypes.h"  // js::Bit
     17 
     18 #include "frontend/FunctionSyntaxKind.h"  // FunctionSyntaxKind
     19 #include "frontend/NameAnalysisTypes.h"   // PrivateNameKind
     20 #include "frontend/ParserAtom.h"          // TaggedParserAtomIndex
     21 #include "frontend/Stencil.h"             // BigIntStencil
     22 #include "frontend/Token.h"
     23 #include "js/TypeDecls.h"
     24 #include "vm/Opcodes.h"
     25 #include "vm/Scope.h"
     26 #include "vm/ScopeKind.h"
     27 
     28 // [SMDOC] ParseNode tree lifetime information
     29 //
     30 // - All the `ParseNode` instances MUST BE explicitly allocated in the context's
     31 //   `LifoAlloc`. This is typically implemented by the `FullParseHandler` or it
     32 //   can be reimplemented with a custom `new_`.
     33 //
     34 // - The tree is bulk-deallocated when the parser is deallocated. Consequently,
     35 //   references to a subtree MUST NOT exist once the parser has been
     36 //   deallocated.
     37 //
     38 // - This bulk-deallocation DOES NOT run destructors.
     39 //
     40 // - Instances of `LexicalScope::ParserData` and `ClassBodyScope::ParserData`
     41 //   MUST BE allocated as instances of `ParseNode`, in the same `LifoAlloc`.
     42 //   They are bulk-deallocated alongside the rest of the tree.
     43 
     44 struct JSContext;
     45 
     46 namespace js {
     47 
     48 class JS_PUBLIC_API GenericPrinter;
     49 class LifoAlloc;
     50 class RegExpObject;
     51 
     52 namespace frontend {
     53 
     54 class ParserAtomsTable;
     55 class ParserBase;
     56 class ParseContext;
     57 struct ExtensibleCompilationStencil;
     58 class ParserSharedBase;
     59 class FullParseHandler;
     60 
     61 class FunctionBox;
     62 
     63 #define FOR_EACH_PARSE_NODE_KIND(F)                                       \
     64  F(EmptyStmt, NullaryNode)                                               \
     65  F(ExpressionStmt, UnaryNode)                                            \
     66  F(CommaExpr, ListNode)                                                  \
     67  F(ConditionalExpr, ConditionalExpression)                               \
     68  F(PropertyDefinition, PropertyDefinition)                               \
     69  F(Shorthand, BinaryNode)                                                \
     70  F(PosExpr, UnaryNode)                                                   \
     71  F(NegExpr, UnaryNode)                                                   \
     72  F(PreIncrementExpr, UnaryNode)                                          \
     73  F(PostIncrementExpr, UnaryNode)                                         \
     74  F(PreDecrementExpr, UnaryNode)                                          \
     75  F(PostDecrementExpr, UnaryNode)                                         \
     76  F(PropertyNameExpr, NameNode)                                           \
     77  F(DotExpr, PropertyAccess)                                              \
     78  F(ArgumentsLength, ArgumentsLength)                                     \
     79  F(ElemExpr, PropertyByValue)                                            \
     80  F(PrivateMemberExpr, PrivateMemberAccess)                               \
     81  F(OptionalDotExpr, OptionalPropertyAccess)                              \
     82  F(OptionalChain, UnaryNode)                                             \
     83  F(OptionalElemExpr, OptionalPropertyByValue)                            \
     84  F(OptionalPrivateMemberExpr, OptionalPrivateMemberAccess)               \
     85  F(OptionalCallExpr, CallNode)                                           \
     86  F(ArrayExpr, ListNode)                                                  \
     87  F(Elision, NullaryNode)                                                 \
     88  F(StatementList, ListNode)                                              \
     89  F(LabelStmt, LabeledStatement)                                          \
     90  F(ObjectExpr, ListNode)                                                 \
     91  F(CallExpr, CallNode)                                                   \
     92  F(Arguments, ListNode)                                                  \
     93  F(Name, NameNode)                                                       \
     94  F(ObjectPropertyName, NameNode)                                         \
     95  F(PrivateName, NameNode)                                                \
     96  F(ComputedName, UnaryNode)                                              \
     97  F(NumberExpr, NumericLiteral)                                           \
     98  F(BigIntExpr, BigIntLiteral)                                            \
     99  F(StringExpr, NameNode)                                                 \
    100  F(TemplateStringListExpr, ListNode)                                     \
    101  F(TemplateStringExpr, NameNode)                                         \
    102  F(TaggedTemplateExpr, CallNode)                                         \
    103  F(CallSiteObj, CallSiteNode)                                            \
    104  F(RegExpExpr, RegExpLiteral)                                            \
    105  F(TrueExpr, BooleanLiteral)                                             \
    106  F(FalseExpr, BooleanLiteral)                                            \
    107  F(NullExpr, NullLiteral)                                                \
    108  F(RawUndefinedExpr, RawUndefinedLiteral)                                \
    109  F(ThisExpr, UnaryNode)                                                  \
    110  F(Function, FunctionNode)                                               \
    111  F(Module, ModuleNode)                                                   \
    112  F(IfStmt, TernaryNode)                                                  \
    113  F(SwitchStmt, SwitchStatement)                                          \
    114  F(Case, CaseClause)                                                     \
    115  F(WhileStmt, BinaryNode)                                                \
    116  F(DoWhileStmt, BinaryNode)                                              \
    117  F(ForStmt, ForNode)                                                     \
    118  F(BreakStmt, BreakStatement)                                            \
    119  F(ContinueStmt, ContinueStatement)                                      \
    120  F(VarStmt, DeclarationListNode)                                         \
    121  F(ConstDecl, DeclarationListNode)                                       \
    122  IF_EXPLICIT_RESOURCE_MANAGEMENT(F(UsingDecl, DeclarationListNode))      \
    123  IF_EXPLICIT_RESOURCE_MANAGEMENT(F(AwaitUsingDecl, DeclarationListNode)) \
    124  F(WithStmt, BinaryNode)                                                 \
    125  F(ReturnStmt, UnaryNode)                                                \
    126  F(NewExpr, CallNode)                                                    \
    127  IF_DECORATORS(F(DecoratorList, ListNode))                               \
    128  /* Delete operations.  These must be sequential. */                     \
    129  F(DeleteNameExpr, UnaryNode)                                            \
    130  F(DeletePropExpr, UnaryNode)                                            \
    131  F(DeleteElemExpr, UnaryNode)                                            \
    132  F(DeleteOptionalChainExpr, UnaryNode)                                   \
    133  F(DeleteExpr, UnaryNode)                                                \
    134  F(TryStmt, TernaryNode)                                                 \
    135  F(Catch, BinaryNode)                                                    \
    136  F(ThrowStmt, UnaryNode)                                                 \
    137  F(DebuggerStmt, DebuggerStatement)                                      \
    138  F(Generator, NullaryNode)                                               \
    139  F(InitialYield, UnaryNode)                                              \
    140  F(YieldExpr, UnaryNode)                                                 \
    141  F(YieldStarExpr, UnaryNode)                                             \
    142  F(LexicalScope, LexicalScopeNode)                                       \
    143  F(LetDecl, DeclarationListNode)                                         \
    144  F(ImportDecl, BinaryNode)                                               \
    145  F(ImportSpecList, ListNode)                                             \
    146  F(ImportSpec, BinaryNode)                                               \
    147  F(ImportNamespaceSpec, UnaryNode)                                       \
    148  F(ImportAttributeList, ListNode)                                        \
    149  F(ImportAttribute, BinaryNode)                                          \
    150  F(ImportModuleRequest, BinaryNode)                                      \
    151  F(ExportStmt, UnaryNode)                                                \
    152  F(ExportFromStmt, BinaryNode)                                           \
    153  F(ExportDefaultStmt, BinaryNode)                                        \
    154  F(ExportSpecList, ListNode)                                             \
    155  F(ExportSpec, BinaryNode)                                               \
    156  F(ExportNamespaceSpec, UnaryNode)                                       \
    157  F(ExportBatchSpecStmt, NullaryNode)                                     \
    158  F(ForIn, TernaryNode)                                                   \
    159  F(ForOf, TernaryNode)                                                   \
    160  F(ForHead, TernaryNode)                                                 \
    161  F(ParamsBody, ParamsBodyNode)                                           \
    162  F(Spread, UnaryNode)                                                    \
    163  F(MutateProto, UnaryNode)                                               \
    164  F(ClassDecl, ClassNode)                                                 \
    165  F(DefaultConstructor, ClassMethod)                                      \
    166  F(ClassBodyScope, ClassBodyScopeNode)                                   \
    167  F(ClassMethod, ClassMethod)                                             \
    168  F(StaticClassBlock, StaticClassBlock)                                   \
    169  F(ClassField, ClassField)                                               \
    170  F(ClassMemberList, ListNode)                                            \
    171  F(ClassNames, ClassNames)                                               \
    172  F(NewTargetExpr, NewTargetNode)                                         \
    173  F(PosHolder, NullaryNode)                                               \
    174  F(SuperBase, UnaryNode)                                                 \
    175  F(SuperCallExpr, CallNode)                                              \
    176  F(SetThis, BinaryNode)                                                  \
    177  F(ImportMetaExpr, BinaryNode)                                           \
    178  F(CallImportExpr, BinaryNode)                                           \
    179  F(CallImportSpec, BinaryNode)                                           \
    180  F(InitExpr, BinaryNode)                                                 \
    181                                                                          \
    182  /* Unary operators. */                                                  \
    183  F(TypeOfNameExpr, UnaryNode)                                            \
    184  F(TypeOfExpr, UnaryNode)                                                \
    185  F(VoidExpr, UnaryNode)                                                  \
    186  F(NotExpr, UnaryNode)                                                   \
    187  F(BitNotExpr, UnaryNode)                                                \
    188  F(AwaitExpr, UnaryNode)                                                 \
    189                                                                          \
    190  /*                                                                      \
    191   * Binary operators.                                                    \
    192   * This list must be kept in the same order in several places:          \
    193   *   - The binary operators in ParseNode.h                              \
    194   *   - the binary operators in TokenKind.h                              \
    195   *   - the precedence list in Parser.cpp                                \
    196   *   - the JSOp code list in BytecodeEmitter.cpp                        \
    197   */                                                                     \
    198  F(CoalesceExpr, ListNode)                                               \
    199  F(OrExpr, ListNode)                                                     \
    200  F(AndExpr, ListNode)                                                    \
    201  F(BitOrExpr, ListNode)                                                  \
    202  F(BitXorExpr, ListNode)                                                 \
    203  F(BitAndExpr, ListNode)                                                 \
    204  F(StrictEqExpr, ListNode)                                               \
    205  F(EqExpr, ListNode)                                                     \
    206  F(StrictNeExpr, ListNode)                                               \
    207  F(NeExpr, ListNode)                                                     \
    208  F(LtExpr, ListNode)                                                     \
    209  F(LeExpr, ListNode)                                                     \
    210  F(GtExpr, ListNode)                                                     \
    211  F(GeExpr, ListNode)                                                     \
    212  F(InstanceOfExpr, ListNode)                                             \
    213  F(InExpr, ListNode)                                                     \
    214  F(PrivateInExpr, ListNode)                                              \
    215  F(LshExpr, ListNode)                                                    \
    216  F(RshExpr, ListNode)                                                    \
    217  F(UrshExpr, ListNode)                                                   \
    218  F(AddExpr, ListNode)                                                    \
    219  F(SubExpr, ListNode)                                                    \
    220  F(MulExpr, ListNode)                                                    \
    221  F(DivExpr, ListNode)                                                    \
    222  F(ModExpr, ListNode)                                                    \
    223  F(PowExpr, ListNode)                                                    \
    224                                                                          \
    225  /* Assignment operators (= += -= etc.). */                              \
    226  /* AssignmentNode::test assumes all these are consecutive. */           \
    227  F(AssignExpr, AssignmentNode)                                           \
    228  F(AddAssignExpr, AssignmentNode)                                        \
    229  F(SubAssignExpr, AssignmentNode)                                        \
    230  F(CoalesceAssignExpr, AssignmentNode)                                   \
    231  F(OrAssignExpr, AssignmentNode)                                         \
    232  F(AndAssignExpr, AssignmentNode)                                        \
    233  F(BitOrAssignExpr, AssignmentNode)                                      \
    234  F(BitXorAssignExpr, AssignmentNode)                                     \
    235  F(BitAndAssignExpr, AssignmentNode)                                     \
    236  F(LshAssignExpr, AssignmentNode)                                        \
    237  F(RshAssignExpr, AssignmentNode)                                        \
    238  F(UrshAssignExpr, AssignmentNode)                                       \
    239  F(MulAssignExpr, AssignmentNode)                                        \
    240  F(DivAssignExpr, AssignmentNode)                                        \
    241  F(ModAssignExpr, AssignmentNode)                                        \
    242  F(PowAssignExpr, AssignmentNode)
    243 
    244 /*
    245 * Parsing builds a tree of nodes that directs code generation.  This tree is
    246 * not a concrete syntax tree in all respects (for example, || and && are left
    247 * associative, but (A && B && C) translates into the right-associated tree
    248 * <A && <B && C>> so that code generation can emit a left-associative branch
    249 * around <B && C> when A is false).  Nodes are labeled by kind.
    250 *
    251 * The long comment after this enum block describes the kinds in detail.
    252 */
    253 enum class ParseNodeKind : uint16_t {
    254  // These constants start at 1001, the better to catch
    255  LastUnused = 1000,
    256 #define EMIT_ENUM(name, _type) name,
    257  FOR_EACH_PARSE_NODE_KIND(EMIT_ENUM)
    258 #undef EMIT_ENUM
    259      Limit,
    260  Start = LastUnused + 1,
    261  BinOpFirst = ParseNodeKind::CoalesceExpr,
    262  BinOpLast = ParseNodeKind::PowExpr,
    263  AssignmentStart = ParseNodeKind::AssignExpr,
    264  AssignmentLast = ParseNodeKind::PowAssignExpr,
    265 };
    266 
    267 inline bool IsDeleteKind(ParseNodeKind kind) {
    268  return ParseNodeKind::DeleteNameExpr <= kind &&
    269         kind <= ParseNodeKind::DeleteExpr;
    270 }
    271 
    272 inline bool IsTypeofKind(ParseNodeKind kind) {
    273  return ParseNodeKind::TypeOfNameExpr <= kind &&
    274         kind <= ParseNodeKind::TypeOfExpr;
    275 }
    276 
    277 /*
    278 * <Definitions>
    279 * Function (FunctionNode)
    280 *   funbox: ptr to js::FunctionBox
    281 *   body: ParamsBody or null for lazily-parsed function
    282 *   syntaxKind: the syntax of the function
    283 * ParamsBody (ListNode)
    284 *   head: list of formal parameters with
    285 *           * Name node with non-empty name for SingleNameBinding without
    286 *             Initializer
    287 *           * AssignExpr node for SingleNameBinding with Initializer
    288 *           * Name node with empty name for destructuring
    289 *               expr: Array or Object for BindingPattern without
    290 *                     Initializer, Assign for BindingPattern with
    291 *                     Initializer
    292 *         followed by:
    293 *           * LexicalScopeNode
    294 *   count: number of formal parameters + 1
    295 * Spread (UnaryNode)
    296 *   kid: expression being spread
    297 * ClassDecl (ClassNode)
    298 *   kid1: ClassNames for class name. can be null for anonymous class.
    299 *   kid2: expression after `extends`. null if no expression
    300 *   kid3: either of
    301 *           * ClassMemberList, if anonymous class
    302 *           * LexicalScopeNode which contains ClassMemberList as scopeBody,
    303 *             if named class
    304 * ClassNames (ClassNames)
    305 *   left: Name node for outer binding, or null if the class is an expression
    306 *         that doesn't create an outer binding
    307 *   right: Name node for inner binding
    308 * ClassMemberList (ListNode)
    309 *   head: list of N ClassMethod, ClassField or StaticClassBlock nodes
    310 *   count: N >= 0
    311 * DefaultConstructor (ClassMethod)
    312 *   name: propertyName
    313 *   method: methodDefinition
    314 * ClassMethod (ClassMethod)
    315 *   name: propertyName
    316 *   method: methodDefinition
    317 *   initializerIfPrivate: initializer to stamp private method onto instance
    318 * Module (ModuleNode)
    319 *   body: statement list of the module
    320 *
    321 * <Statements>
    322 * StatementList (ListNode)
    323 *   head: list of N statements
    324 *   count: N >= 0
    325 * IfStmt (TernaryNode)
    326 *   kid1: cond
    327 *   kid2: then
    328 *   kid3: else or null
    329 * SwitchStmt (SwitchStatement)
    330 *   left: discriminant
    331 *   right: LexicalScope node that contains the list of Case nodes, with at
    332 *          most one default node.
    333 *   hasDefault: true if there's a default case
    334 * Case (CaseClause)
    335 *   left: case-expression if CaseClause, or null if DefaultClause
    336 *   right: StatementList node for this case's statements
    337 * WhileStmt (BinaryNode)
    338 *   left: cond
    339 *   right: body
    340 * DoWhileStmt (BinaryNode)
    341 *   left: body
    342 *   right: cond
    343 * ForStmt (ForNode)
    344 *   left: one of
    345 *           * ForIn: for (x in y) ...
    346 *           * ForOf: for (x of x) ...
    347 *           * ForHead: for (;;) ...
    348 *   right: body
    349 * ForIn (TernaryNode)
    350 *   kid1: declaration or expression to left of 'in'
    351 *   kid2: null
    352 *   kid3: object expr to right of 'in'
    353 * ForOf (TernaryNode)
    354 *   kid1: declaration or expression to left of 'of'
    355 *   kid2: null
    356 *   kid3: expr to right of 'of'
    357 * ForHead (TernaryNode)
    358 *   kid1:  init expr before first ';' or nullptr
    359 *   kid2:  cond expr before second ';' or nullptr
    360 *   kid3:  update expr after second ';' or nullptr
    361 * ThrowStmt (UnaryNode)
    362 *   kid: thrown exception
    363 * TryStmt (TernaryNode)
    364 *   kid1: try block
    365 *   kid2: null or LexicalScope for catch-block with scopeBody pointing to a
    366 *         Catch node
    367 *   kid3: null or finally block
    368 * Catch (BinaryNode)
    369 *   left: Name, Array, or Object catch var node
    370 *         (Array or Object if destructuring),
    371 *         or null if optional catch binding
    372 *   right: catch block statements
    373 * BreakStmt (BreakStatement)
    374 *   label: label or null
    375 * ContinueStmt (ContinueStatement)
    376 *   label: label or null
    377 * WithStmt (BinaryNode)
    378 *   left: head expr
    379 *   right: body
    380 * VarStmt, LetDecl, ConstDecl (DeclarationListNode)
    381 *   head: list of N Name or AssignExpr nodes
    382 *         each name node has either
    383 *           atom: variable name
    384 *           expr: initializer or null
    385 *         or
    386 *           atom: variable name
    387 *         each assignment node has
    388 *           left: pattern
    389 *           right: initializer
    390 *   count: N > 0
    391 * ReturnStmt (UnaryNode)
    392 *   kid: returned expression, or null if none
    393 * ExpressionStmt (UnaryNode)
    394 *   kid: expr
    395 * EmptyStmt (NullaryNode)
    396 *   (no fields)
    397 * LabelStmt (LabeledStatement)
    398 *   atom: label
    399 *   expr: labeled statement
    400 * ImportDecl (BinaryNode)
    401 *   left: ImportSpecList import specifiers
    402 *   right: String module specifier
    403 * ImportSpecList (ListNode)
    404 *   head: list of N ImportSpec nodes
    405 *   count: N >= 0 (N = 0 for `import {} from ...`)
    406 * ImportSpec (BinaryNode)
    407 *   left: import name
    408 *   right: local binding name
    409 * ImportNamespaceSpec (UnaryNode)
    410 *   kid: local binding name
    411 * ExportStmt (UnaryNode)
    412 *   kid: declaration expression
    413 * ExportFromStmt (BinaryNode)
    414 *   left: ExportSpecList export specifiers
    415 *   right: String module specifier
    416 * ExportSpecList (ListNode)
    417 *   head: list of N ExportSpec nodes
    418 *   count: N >= 0 (N = 0 for `export {}`)
    419 * ExportSpec (BinaryNode)
    420 *   left: local binding name
    421 *   right: export name
    422 * ExportNamespaceSpec (UnaryNode)
    423 *   kid: export name
    424 * ExportDefaultStmt (BinaryNode)
    425 *   left: export default declaration or expression
    426 *   right: Name node for assignment
    427 *
    428 * <Expressions>
    429 * The `Expr` suffix is used for nodes that can appear anywhere an expression
    430 * could appear.  It is not used on a few weird kinds like Arguments and
    431 * CallSiteObj that are always the child node of an expression node, but which
    432 * can't stand alone.
    433 *
    434 * All left-associated binary trees of the same type are optimized into lists
    435 * to avoid recursion when processing expression chains.
    436 *
    437 * CommaExpr (ListNode)
    438 *   head: list of N comma-separated exprs
    439 *   count: N >= 2
    440 * AssignExpr (BinaryNode)
    441 *   left: target of assignment
    442 *   right: value to assign
    443 * AddAssignExpr, SubAssignExpr, CoalesceAssignExpr, OrAssignExpr,
    444 * AndAssignExpr, BitOrAssignExpr, BitXorAssignExpr, BitAndAssignExpr,
    445 * LshAssignExpr, RshAssignExpr, UrshAssignExpr, MulAssignExpr, DivAssignExpr,
    446 * ModAssignExpr, PowAssignExpr (AssignmentNode)
    447 *   left: target of assignment
    448 *   right: value to assign
    449 * ConditionalExpr (ConditionalExpression)
    450 *   (cond ? thenExpr : elseExpr)
    451 *   kid1: cond
    452 *   kid2: thenExpr
    453 *   kid3: elseExpr
    454 * CoalesceExpr, OrExpr, AndExpr, BitOrExpr, BitXorExpr,
    455 * BitAndExpr, StrictEqExpr, EqExpr, StrictNeExpr, NeExpr, LtExpr, LeExpr,
    456 * GtExpr, GeExpr, InstanceOfExpr, InExpr, LshExpr, RshExpr, UrshExpr, AddExpr,
    457 * SubExpr, MulExpr, DivExpr, ModExpr, PowExpr (ListNode)
    458 *   head: list of N subexpressions
    459 *         All of these operators are left-associative except Pow which is
    460 *         right-associative, but still forms a list (see comments in
    461 *         ParseNode::appendOrCreateList).
    462 *   count: N >= 2
    463 * PosExpr, NegExpr, VoidExpr, NotExpr, BitNotExpr, TypeOfNameExpr,
    464 * TypeOfExpr (UnaryNode)
    465 *   kid: unary expr
    466 * PreIncrementExpr, PostIncrementExpr, PreDecrementExpr,
    467 * PostDecrementExpr (UnaryNode)
    468 *   kid: member expr
    469 * NewExpr (BinaryNode)
    470 *   left: ctor expression on the left of the '('
    471 *   right: Arguments
    472 * DecoratorList (ListNode)
    473 *   head: list of N nodes, each item is one of:
    474 *           * NameNode (DecoratorMemberExpression)
    475 *           * CallNode (DecoratorCallExpression)
    476 *           * Node (DecoratorParenthesizedExpression)
    477 *   count: N > 0
    478 * DeleteNameExpr, DeletePropExpr, DeleteElemExpr, DeleteExpr (UnaryNode)
    479 *   kid: expression that's evaluated, then the overall delete evaluates to
    480 *        true; can't be a kind for a more-specific ParseNodeKind::Delete*
    481 *        unless constant folding (or a similar parse tree manipulation) has
    482 *        occurred
    483 *          * DeleteNameExpr: Name expr
    484 *          * DeletePropExpr: Dot expr
    485 *          * DeleteElemExpr: Elem expr
    486 *          * DeleteOptionalChainExpr: Member expr
    487 *          * DeleteExpr: Member expr
    488 * DeleteOptionalChainExpr (UnaryNode)
    489 *   kid: expression that's evaluated, then the overall delete evaluates to
    490 *        true; If constant folding occurs, Elem expr may become Dot expr.
    491 *        OptionalElemExpr does not get folded into OptionalDot.
    492 * OptionalChain (UnaryNode)
    493 *   kid: expression that is evaluated as a chain. An Optional chain contains
    494 *        one or more optional nodes. It's first node (kid) is always an
    495 *        optional node, for example: an OptionalElemExpr, OptionalDotExpr, or
    496 *        OptionalCall.  An OptionalChain will shortcircuit and return
    497 *        Undefined without evaluating the rest of the expression if any of the
    498 *        optional nodes it contains are nullish. An optionalChain also can
    499 *        contain nodes such as DotExpr, ElemExpr, NameExpr CallExpr, etc.
    500 *        These are evaluated normally.
    501 *          * OptionalDotExpr: Dot expr with jump
    502 *          * OptionalElemExpr: Elem expr with jump
    503 *          * OptionalCallExpr: Call expr with jump
    504 *          * DotExpr: Dot expr without jump
    505 *          * ElemExpr: Elem expr without jump
    506 *          * CallExpr: Call expr without jump
    507 * PropertyNameExpr (NameNode)
    508 *   atom: property name being accessed
    509 *   privateNameKind: kind of the name if private
    510 * DotExpr (PropertyAccess)
    511 *   left: Member expr to left of '.'
    512 *   right: PropertyName to right of '.'
    513 * OptionalDotExpr (OptionalPropertyAccess)
    514 *   left: Member expr to left of '.', short circuits back to OptionalChain
    515 *        if nullish.
    516 *   right: PropertyName to right of '.'
    517 * ElemExpr (PropertyByValue)
    518 *   left: Member expr to left of '['
    519 *   right: expr between '[' and ']'
    520 * OptionalElemExpr (OptionalPropertyByValue)
    521 *   left: Member expr to left of '[', short circuits back to OptionalChain
    522 *         if nullish.
    523 *   right: expr between '[' and ']'
    524 * CallExpr (BinaryNode)
    525 *   left: callee expression on the left of the '('
    526 *   right: Arguments
    527 * OptionalCallExpr (BinaryNode)
    528 *   left: callee expression on the left of the '(', short circuits back to
    529 *         OptionalChain if nullish.
    530 *   right: Arguments
    531 * Arguments (ListNode)
    532 *   head: list of arg1, arg2, ... argN
    533 *   count: N >= 0
    534 * ArrayExpr (ListNode)
    535 *   head: list of N array element expressions
    536 *         holes ([,,]) are represented by Elision nodes,
    537 *         spread elements ([...X]) are represented by Spread nodes
    538 *   count: N >= 0
    539 * ObjectExpr (ListNode)
    540 *   head: list of N nodes, each item is one of:
    541 *           * MutateProto
    542 *           * PropertyDefinition
    543 *           * Shorthand
    544 *           * Spread
    545 *   count: N >= 0
    546 * PropertyDefinition (PropertyDefinition)
    547 *   key-value pair in object initializer or destructuring lhs
    548 *   left: property id
    549 *   right: value
    550 * Shorthand (BinaryNode)
    551 *   Same fields as PropertyDefinition. This is used for object literal
    552 *   properties using shorthand ({x}).
    553 * ComputedName (UnaryNode)
    554 *   ES6 ComputedPropertyName.
    555 *   kid: the AssignmentExpression inside the square brackets
    556 * Name (NameNode)
    557 *   atom: name, or object atom
    558 * StringExpr (NameNode)
    559 *   atom: string
    560 * TemplateStringListExpr (ListNode)
    561 *   head: list of alternating expr and template strings
    562 *           TemplateString [, expression, TemplateString]+
    563 *         there's at least one expression.  If the template literal contains
    564 *         no ${}-delimited expression, it's parsed as a single TemplateString
    565 * TemplateStringExpr (NameNode)
    566 *   atom: template string atom
    567 * TaggedTemplateExpr (BinaryNode)
    568 *   left: tag expression
    569 *   right: Arguments, with the first being the call site object, then
    570 *          arg1, arg2, ... argN
    571 * CallSiteObj (CallSiteNode)
    572 *   head:  an Array of raw TemplateString, then corresponding cooked
    573 *          TemplateString nodes
    574 *            Array [, cooked TemplateString]+
    575 *          where the Array is
    576 *            [raw TemplateString]+
    577 * RegExpExpr (RegExpLiteral)
    578 *   regexp: RegExp model object
    579 * NumberExpr (NumericLiteral)
    580 *   value: double value of numeric literal
    581 * BigIntExpr (BigIntLiteral)
    582 *   stencil: script compilation struct that has |bigIntData| vector
    583 *   index: index into the script compilation's |bigIntData| vector
    584 * TrueExpr, FalseExpr (BooleanLiteral)
    585 * NullExpr (NullLiteral)
    586 * RawUndefinedExpr (RawUndefinedLiteral)
    587 *
    588 * ThisExpr (UnaryNode)
    589 *   kid: '.this' Name if function `this`, else nullptr
    590 * SuperBase (UnaryNode)
    591 *   kid: '.this' Name
    592 * SuperCallExpr (BinaryNode)
    593 *   left: SuperBase
    594 *   right: Arguments
    595 * SetThis (BinaryNode)
    596 *   left: '.this' Name
    597 *   right: SuperCall
    598 *
    599 * LexicalScope (LexicalScopeNode)
    600 *   scopeBindings: scope bindings
    601 *   scopeBody: scope body
    602 * Generator (NullaryNode)
    603 * InitialYield (UnaryNode)
    604 *   kid: generator object
    605 * YieldExpr, YieldStarExpr, AwaitExpr (UnaryNode)
    606 *   kid: expr or null
    607 */
    608 
    609 #define FOR_EACH_PARSENODE_SUBCLASS(MACRO) \
    610  MACRO(BinaryNode)                        \
    611  MACRO(AssignmentNode)                    \
    612  MACRO(CaseClause)                        \
    613  MACRO(ClassMethod)                       \
    614  MACRO(ClassField)                        \
    615  MACRO(StaticClassBlock)                  \
    616  MACRO(PropertyDefinition)                \
    617  MACRO(ClassNames)                        \
    618  MACRO(ForNode)                           \
    619  MACRO(PropertyAccess)                    \
    620  MACRO(ArgumentsLength)                   \
    621  MACRO(OptionalPropertyAccess)            \
    622  MACRO(PropertyByValue)                   \
    623  MACRO(OptionalPropertyByValue)           \
    624  MACRO(PrivateMemberAccess)               \
    625  MACRO(OptionalPrivateMemberAccess)       \
    626  MACRO(NewTargetNode)                     \
    627  MACRO(SwitchStatement)                   \
    628  MACRO(DeclarationListNode)               \
    629                                           \
    630  MACRO(ParamsBodyNode)                    \
    631  MACRO(FunctionNode)                      \
    632  MACRO(ModuleNode)                        \
    633                                           \
    634  MACRO(LexicalScopeNode)                  \
    635  MACRO(ClassBodyScopeNode)                \
    636                                           \
    637  MACRO(ListNode)                          \
    638  MACRO(CallSiteNode)                      \
    639  MACRO(CallNode)                          \
    640                                           \
    641  MACRO(LoopControlStatement)              \
    642  MACRO(BreakStatement)                    \
    643  MACRO(ContinueStatement)                 \
    644                                           \
    645  MACRO(NameNode)                          \
    646  MACRO(LabeledStatement)                  \
    647                                           \
    648  MACRO(NullaryNode)                       \
    649  MACRO(BooleanLiteral)                    \
    650  MACRO(DebuggerStatement)                 \
    651  MACRO(NullLiteral)                       \
    652  MACRO(RawUndefinedLiteral)               \
    653                                           \
    654  MACRO(NumericLiteral)                    \
    655  MACRO(BigIntLiteral)                     \
    656                                           \
    657  MACRO(RegExpLiteral)                     \
    658                                           \
    659  MACRO(TernaryNode)                       \
    660  MACRO(ClassNode)                         \
    661  MACRO(ConditionalExpression)             \
    662  MACRO(TryNode)                           \
    663                                           \
    664  MACRO(UnaryNode)                         \
    665  MACRO(ThisLiteral)
    666 
    667 #define DECLARE_CLASS(typeName) class typeName;
    668 FOR_EACH_PARSENODE_SUBCLASS(DECLARE_CLASS)
    669 #undef DECLARE_CLASS
    670 
    671 enum class AccessorType { None, Getter, Setter };
    672 
    673 static inline bool IsConstructorKind(FunctionSyntaxKind kind) {
    674  return kind == FunctionSyntaxKind::ClassConstructor ||
    675         kind == FunctionSyntaxKind::DerivedClassConstructor;
    676 }
    677 
    678 static inline bool IsMethodDefinitionKind(FunctionSyntaxKind kind) {
    679  return IsConstructorKind(kind) || kind == FunctionSyntaxKind::Method ||
    680         kind == FunctionSyntaxKind::FieldInitializer ||
    681         kind == FunctionSyntaxKind::Getter ||
    682         kind == FunctionSyntaxKind::Setter;
    683 }
    684 
    685 // To help diagnose sporadic crashes in the frontend, a few assertions are
    686 // enabled in early beta builds. (Most are not; those still use MOZ_ASSERT.)
    687 // See bug 1547561.
    688 #if defined(EARLY_BETA_OR_EARLIER)
    689 #  define JS_PARSE_NODE_ASSERT MOZ_RELEASE_ASSERT
    690 #else
    691 #  define JS_PARSE_NODE_ASSERT MOZ_ASSERT
    692 #endif
    693 
    694 class ParseNode;
    695 struct ParseNodeError {};
    696 using ParseNodeResult = mozilla::Result<ParseNode*, ParseNodeError>;
    697 
    698 class ParseNode {
    699  const ParseNodeKind pn_type;
    700 
    701  bool pn_parens : 1;       /* this expr was enclosed in parens */
    702  bool pn_rhs_anon_fun : 1; /* this expr is anonymous function or class that
    703                             * is a direct RHS of ParseNodeKind::Assign or
    704                             * ParseNodeKind::PropertyDefinition of property,
    705                             * that needs SetFunctionName. */
    706 
    707 protected:
    708  // Used by ComputedName to indicate if the ComputedName is a
    709  // a synthetic construct. This allows us to avoid needing to
    710  // compute ToString on uncommon property values such as BigInt.
    711  // Instead we parse as though they were computed names.
    712  //
    713  // We need this bit to distinguish a synthetic computed name like
    714  // this however to undo this transformation in Reflect.parse and
    715  // name guessing.
    716  bool pn_synthetic_computed : 1;
    717 
    718  ParseNode(const ParseNode& other) = delete;
    719  void operator=(const ParseNode& other) = delete;
    720 
    721 public:
    722  explicit ParseNode(ParseNodeKind kind)
    723      : pn_type(kind),
    724        pn_parens(false),
    725        pn_rhs_anon_fun(false),
    726        pn_synthetic_computed(false),
    727        pn_pos(0, 0),
    728        pn_next(nullptr) {
    729    JS_PARSE_NODE_ASSERT(ParseNodeKind::Start <= kind);
    730    JS_PARSE_NODE_ASSERT(kind < ParseNodeKind::Limit);
    731  }
    732 
    733  ParseNode(ParseNodeKind kind, const TokenPos& pos)
    734      : pn_type(kind),
    735        pn_parens(false),
    736        pn_rhs_anon_fun(false),
    737        pn_synthetic_computed(false),
    738        pn_pos(pos),
    739        pn_next(nullptr) {
    740    JS_PARSE_NODE_ASSERT(ParseNodeKind::Start <= kind);
    741    JS_PARSE_NODE_ASSERT(kind < ParseNodeKind::Limit);
    742  }
    743 
    744  ParseNodeKind getKind() const {
    745    JS_PARSE_NODE_ASSERT(ParseNodeKind::Start <= pn_type);
    746    JS_PARSE_NODE_ASSERT(pn_type < ParseNodeKind::Limit);
    747    return pn_type;
    748  }
    749  bool isKind(ParseNodeKind kind) const { return getKind() == kind; }
    750 
    751 protected:
    752  size_t getKindAsIndex() const {
    753    return size_t(getKind()) - size_t(ParseNodeKind::Start);
    754  }
    755 
    756  // Used to implement test() on a few ParseNodes efficiently.
    757  // (This enum doesn't fully reflect the ParseNode class hierarchy,
    758  // so don't use it for anything else.)
    759  enum class TypeCode : uint8_t {
    760    Nullary,
    761    Unary,
    762    Binary,
    763    Ternary,
    764    List,
    765    Name,
    766    Other
    767  };
    768 
    769  // typeCodeTable[getKindAsIndex()] is the type code of a ParseNode of kind
    770  // pnk.
    771  static const TypeCode typeCodeTable[];
    772 
    773 private:
    774 #ifdef DEBUG
    775  static const size_t sizeTable[];
    776 #endif
    777 
    778 public:
    779  TypeCode typeCode() const { return typeCodeTable[getKindAsIndex()]; }
    780 
    781  bool isBinaryOperation() const {
    782    ParseNodeKind kind = getKind();
    783    return ParseNodeKind::BinOpFirst <= kind &&
    784           kind <= ParseNodeKind::BinOpLast;
    785  }
    786  inline bool isName(TaggedParserAtomIndex name) const;
    787 
    788  /* Boolean attributes. */
    789  bool isInParens() const { return pn_parens; }
    790  bool isLikelyIIFE() const { return isInParens(); }
    791  void setInParens(bool enabled) { pn_parens = enabled; }
    792 
    793  bool isDirectRHSAnonFunction() const { return pn_rhs_anon_fun; }
    794  void setDirectRHSAnonFunction(bool enabled) { pn_rhs_anon_fun = enabled; }
    795 
    796  TokenPos pn_pos;    /* two 16-bit pairs here, for 64 bits */
    797  ParseNode* pn_next; /* intrinsic link in parent ListNode */
    798 
    799 public:
    800  /*
    801   * If |left| is a list of the given kind/left-associative op, append
    802   * |right| to it and return |left|.  Otherwise return a [left, right] list.
    803   */
    804  static ParseNodeResult appendOrCreateList(ParseNodeKind kind, ParseNode* left,
    805                                            ParseNode* right,
    806                                            FullParseHandler* handler,
    807                                            ParseContext* pc);
    808 
    809  /* True if pn is a parsenode representing a literal constant. */
    810  bool isLiteral() const {
    811    return isKind(ParseNodeKind::NumberExpr) ||
    812           isKind(ParseNodeKind::BigIntExpr) ||
    813           isKind(ParseNodeKind::StringExpr) ||
    814           isKind(ParseNodeKind::TrueExpr) ||
    815           isKind(ParseNodeKind::FalseExpr) ||
    816           isKind(ParseNodeKind::NullExpr) ||
    817           isKind(ParseNodeKind::RawUndefinedExpr);
    818  }
    819 
    820  inline bool isConstant();
    821 
    822  inline bool isUndefinedLiteral();
    823 
    824  template <class NodeType>
    825  inline bool is() const {
    826    return NodeType::test(*this);
    827  }
    828 
    829  /* Casting operations. */
    830  template <class NodeType>
    831  inline NodeType& as() {
    832    MOZ_ASSERT(NodeType::test(*this));
    833    return *static_cast<NodeType*>(this);
    834  }
    835 
    836  template <class NodeType>
    837  inline const NodeType& as() const {
    838    MOZ_ASSERT(NodeType::test(*this));
    839    return *static_cast<const NodeType*>(this);
    840  }
    841 
    842 #ifdef DEBUG
    843  // Debugger-friendly stderr printer.
    844  void dump();
    845  void dump(const ParserAtomsTable* parserAtoms);
    846  void dump(const ParserAtomsTable* parserAtoms, GenericPrinter& out);
    847  void dump(const ParserAtomsTable* parserAtoms, GenericPrinter& out,
    848            int indent);
    849 
    850  // The size of this node, in bytes.
    851  size_t size() const { return sizeTable[getKindAsIndex()]; }
    852 #endif
    853 };
    854 
    855 // Remove a ParseNode, **pnp, from a parse tree, putting another ParseNode,
    856 // *pn, in its place.
    857 //
    858 // pnp points to a ParseNode pointer. This must be the only pointer that points
    859 // to the parse node being replaced. The replacement, *pn, is unchanged except
    860 // for its pn_next pointer; updating that is necessary if *pn's new parent is a
    861 // list node.
    862 inline void ReplaceNode(ParseNode** pnp, ParseNode* pn) {
    863  pn->pn_next = (*pnp)->pn_next;
    864  *pnp = pn;
    865 }
    866 
    867 class NullaryNode : public ParseNode {
    868 public:
    869  NullaryNode(ParseNodeKind kind, const TokenPos& pos) : ParseNode(kind, pos) {
    870    MOZ_ASSERT(is<NullaryNode>());
    871  }
    872 
    873  static bool test(const ParseNode& node) {
    874    return node.typeCode() == TypeCode::Nullary;
    875  }
    876 
    877  static constexpr TypeCode classTypeCode() { return TypeCode::Nullary; }
    878 
    879  template <typename Visitor>
    880  bool accept(Visitor& visitor) {
    881    return true;
    882  }
    883 
    884 #ifdef DEBUG
    885  void dumpImpl(const ParserAtomsTable* parserAtoms, GenericPrinter& out,
    886                int indent);
    887 #endif
    888 };
    889 
    890 class NameNode : public ParseNode {
    891  TaggedParserAtomIndex atom_; /* lexical name or label atom */
    892  PrivateNameKind privateNameKind_ = PrivateNameKind::None;
    893 
    894 public:
    895  NameNode(ParseNodeKind kind, TaggedParserAtomIndex atom, const TokenPos& pos)
    896      : ParseNode(kind, pos), atom_(atom) {
    897    MOZ_ASSERT(atom);
    898    MOZ_ASSERT(is<NameNode>());
    899  }
    900 
    901  static bool test(const ParseNode& node) {
    902    return node.typeCode() == TypeCode::Name;
    903  }
    904 
    905  static constexpr TypeCode classTypeCode() { return TypeCode::Name; }
    906 
    907  template <typename Visitor>
    908  bool accept(Visitor& visitor) {
    909    return true;
    910  }
    911 
    912 #ifdef DEBUG
    913  void dumpImpl(const ParserAtomsTable* parserAtoms, GenericPrinter& out,
    914                int indent);
    915 #endif
    916 
    917  TaggedParserAtomIndex atom() const { return atom_; }
    918 
    919  TaggedParserAtomIndex name() const {
    920    MOZ_ASSERT(isKind(ParseNodeKind::Name) ||
    921               isKind(ParseNodeKind::PrivateName));
    922    return atom_;
    923  }
    924 
    925  void setAtom(TaggedParserAtomIndex atom) { atom_ = atom; }
    926 
    927  void setPrivateNameKind(PrivateNameKind privateNameKind) {
    928    privateNameKind_ = privateNameKind;
    929  }
    930 
    931  PrivateNameKind privateNameKind() { return privateNameKind_; }
    932 };
    933 
    934 inline bool ParseNode::isName(TaggedParserAtomIndex name) const {
    935  return getKind() == ParseNodeKind::Name && as<NameNode>().name() == name;
    936 }
    937 
    938 class UnaryNode : public ParseNode {
    939  ParseNode* kid_;
    940 
    941 public:
    942  UnaryNode(ParseNodeKind kind, const TokenPos& pos, ParseNode* kid)
    943      : ParseNode(kind, pos), kid_(kid) {
    944    MOZ_ASSERT(is<UnaryNode>());
    945  }
    946 
    947  static bool test(const ParseNode& node) {
    948    return node.typeCode() == TypeCode::Unary;
    949  }
    950 
    951  static constexpr TypeCode classTypeCode() { return TypeCode::Unary; }
    952 
    953  template <typename Visitor>
    954  bool accept(Visitor& visitor) {
    955    if (kid_) {
    956      if (!visitor.visit(kid_)) {
    957        return false;
    958      }
    959    }
    960    return true;
    961  }
    962 
    963 #ifdef DEBUG
    964  void dumpImpl(const ParserAtomsTable* parserAtoms, GenericPrinter& out,
    965                int indent);
    966 #endif
    967 
    968  ParseNode* kid() const { return kid_; }
    969 
    970  /*
    971   * Non-null if this is a statement node which could be a member of a
    972   * Directive Prologue: an expression statement consisting of a single
    973   * string literal.
    974   *
    975   * This considers only the node and its children, not its context. After
    976   * parsing, check the node's prologue flag to see if it is indeed part of
    977   * a directive prologue.
    978   *
    979   * Note that a Directive Prologue can contain statements that cannot
    980   * themselves be directives (string literals that include escape sequences
    981   * or escaped newlines, say). This member function returns true for such
    982   * nodes; we use it to determine the extent of the prologue.
    983   */
    984  TaggedParserAtomIndex isStringExprStatement() const {
    985    if (isKind(ParseNodeKind::ExpressionStmt)) {
    986      if (kid()->isKind(ParseNodeKind::StringExpr) && !kid()->isInParens()) {
    987        return kid()->as<NameNode>().atom();
    988      }
    989    }
    990    return TaggedParserAtomIndex::null();
    991  }
    992 
    993  // Methods used by FoldConstants.cpp.
    994  ParseNode** unsafeKidReference() { return &kid_; }
    995 
    996  void setSyntheticComputedName() { pn_synthetic_computed = true; }
    997  bool isSyntheticComputedName() {
    998    MOZ_ASSERT(isKind(ParseNodeKind::ComputedName));
    999    return pn_synthetic_computed;
   1000  }
   1001 };
   1002 
   1003 class BinaryNode : public ParseNode {
   1004  ParseNode* left_;
   1005  ParseNode* right_;
   1006 
   1007 public:
   1008  BinaryNode(ParseNodeKind kind, const TokenPos& pos, ParseNode* left,
   1009             ParseNode* right)
   1010      : ParseNode(kind, pos), left_(left), right_(right) {
   1011    MOZ_ASSERT(is<BinaryNode>());
   1012  }
   1013 
   1014  BinaryNode(ParseNodeKind kind, ParseNode* left, ParseNode* right)
   1015      : ParseNode(kind, TokenPos::box(left->pn_pos, right->pn_pos)),
   1016        left_(left),
   1017        right_(right) {
   1018    MOZ_ASSERT(is<BinaryNode>());
   1019  }
   1020 
   1021  static bool test(const ParseNode& node) {
   1022    return node.typeCode() == TypeCode::Binary;
   1023  }
   1024 
   1025  static constexpr TypeCode classTypeCode() { return TypeCode::Binary; }
   1026 
   1027  template <typename Visitor>
   1028  bool accept(Visitor& visitor) {
   1029    if (left_) {
   1030      if (!visitor.visit(left_)) {
   1031        return false;
   1032      }
   1033    }
   1034    if (right_) {
   1035      if (!visitor.visit(right_)) {
   1036        return false;
   1037      }
   1038    }
   1039    return true;
   1040  }
   1041 
   1042 #ifdef DEBUG
   1043  void dumpImpl(const ParserAtomsTable* parserAtoms, GenericPrinter& out,
   1044                int indent);
   1045 #endif
   1046 
   1047  ParseNode* left() const { return left_; }
   1048 
   1049  ParseNode* right() const { return right_; }
   1050 
   1051  // Methods used by FoldConstants.cpp.
   1052  // callers are responsible for keeping the list consistent.
   1053  ParseNode** unsafeLeftReference() { return &left_; }
   1054 
   1055  ParseNode** unsafeRightReference() { return &right_; }
   1056 };
   1057 
   1058 class AssignmentNode : public BinaryNode {
   1059 public:
   1060  AssignmentNode(ParseNodeKind kind, ParseNode* left, ParseNode* right)
   1061      : BinaryNode(kind, TokenPos(left->pn_pos.begin, right->pn_pos.end), left,
   1062                   right) {
   1063    MOZ_ASSERT(is<AssignmentNode>());
   1064  }
   1065 
   1066  static bool test(const ParseNode& node) {
   1067    ParseNodeKind kind = node.getKind();
   1068    bool match = ParseNodeKind::AssignmentStart <= kind &&
   1069                 kind <= ParseNodeKind::AssignmentLast;
   1070    MOZ_ASSERT_IF(match, node.is<BinaryNode>());
   1071    return match;
   1072  }
   1073 };
   1074 
   1075 class ForNode : public BinaryNode {
   1076  unsigned iflags_; /* JSITER_* flags */
   1077 
   1078 public:
   1079  ForNode(const TokenPos& pos, ParseNode* forHead, ParseNode* body,
   1080          unsigned iflags)
   1081      : BinaryNode(ParseNodeKind::ForStmt, pos, forHead, body),
   1082        iflags_(iflags) {
   1083    MOZ_ASSERT(forHead->isKind(ParseNodeKind::ForIn) ||
   1084               forHead->isKind(ParseNodeKind::ForOf) ||
   1085               forHead->isKind(ParseNodeKind::ForHead));
   1086  }
   1087 
   1088  static bool test(const ParseNode& node) {
   1089    bool match = node.isKind(ParseNodeKind::ForStmt);
   1090    MOZ_ASSERT_IF(match, node.is<BinaryNode>());
   1091    return match;
   1092  }
   1093 
   1094  TernaryNode* head() const { return &left()->as<TernaryNode>(); }
   1095 
   1096  ParseNode* body() const { return right(); }
   1097 
   1098  unsigned iflags() const { return iflags_; }
   1099 };
   1100 
   1101 class TernaryNode : public ParseNode {
   1102  ParseNode* kid1_; /* condition, discriminant, etc. */
   1103  ParseNode* kid2_; /* then-part, case list, etc. */
   1104  ParseNode* kid3_; /* else-part, default case, etc. */
   1105 
   1106 public:
   1107  TernaryNode(ParseNodeKind kind, ParseNode* kid1, ParseNode* kid2,
   1108              ParseNode* kid3)
   1109      : TernaryNode(kind, kid1, kid2, kid3,
   1110                    TokenPos((kid1   ? kid1
   1111                              : kid2 ? kid2
   1112                                     : kid3)
   1113                                 ->pn_pos.begin,
   1114                             (kid3   ? kid3
   1115                              : kid2 ? kid2
   1116                                     : kid1)
   1117                                 ->pn_pos.end)) {}
   1118 
   1119  TernaryNode(ParseNodeKind kind, ParseNode* kid1, ParseNode* kid2,
   1120              ParseNode* kid3, const TokenPos& pos)
   1121      : ParseNode(kind, pos), kid1_(kid1), kid2_(kid2), kid3_(kid3) {
   1122    MOZ_ASSERT(is<TernaryNode>());
   1123  }
   1124 
   1125  static bool test(const ParseNode& node) {
   1126    return node.typeCode() == TypeCode::Ternary;
   1127  }
   1128 
   1129  static constexpr TypeCode classTypeCode() { return TypeCode::Ternary; }
   1130 
   1131  template <typename Visitor>
   1132  bool accept(Visitor& visitor) {
   1133    if (kid1_) {
   1134      if (!visitor.visit(kid1_)) {
   1135        return false;
   1136      }
   1137    }
   1138    if (kid2_) {
   1139      if (!visitor.visit(kid2_)) {
   1140        return false;
   1141      }
   1142    }
   1143    if (kid3_) {
   1144      if (!visitor.visit(kid3_)) {
   1145        return false;
   1146      }
   1147    }
   1148    return true;
   1149  }
   1150 
   1151 #ifdef DEBUG
   1152  void dumpImpl(const ParserAtomsTable* parserAtoms, GenericPrinter& out,
   1153                int indent);
   1154 #endif
   1155 
   1156  ParseNode* kid1() const { return kid1_; }
   1157 
   1158  ParseNode* kid2() const { return kid2_; }
   1159 
   1160  ParseNode* kid3() const { return kid3_; }
   1161 
   1162  // Methods used by FoldConstants.cpp.
   1163  ParseNode** unsafeKid1Reference() { return &kid1_; }
   1164 
   1165  ParseNode** unsafeKid2Reference() { return &kid2_; }
   1166 
   1167  ParseNode** unsafeKid3Reference() { return &kid3_; }
   1168 };
   1169 
   1170 class ListNode : public ParseNode {
   1171  ParseNode* head_;  /* first node in list */
   1172  ParseNode** tail_; /* ptr to last node's pn_next in list */
   1173  uint32_t count_;   /* number of nodes in list */
   1174  uint32_t xflags;
   1175 
   1176 private:
   1177  // xflags bits.
   1178 
   1179  // Statement list has top-level function statements.
   1180  static constexpr uint32_t hasTopLevelFunctionDeclarationsBit = Bit(0);
   1181 
   1182  // Array/Object/Class initializer has non-constants.
   1183  //   * array has holes
   1184  //   * array has spread node
   1185  //   * array has element which is known not to be constant
   1186  //   * array has no element
   1187  //   * object/class has __proto__
   1188  //   * object/class has property which is known not to be constant
   1189  //   * object/class shorthand property
   1190  //   * object/class spread property
   1191  //   * object/class has method
   1192  //   * object/class has computed property
   1193  static constexpr uint32_t hasNonConstInitializerBit = Bit(1);
   1194 
   1195  // Flag set by the emitter after emitting top-level function statements.
   1196  static constexpr uint32_t emittedTopLevelFunctionDeclarationsBit = Bit(2);
   1197 
   1198 public:
   1199  ListNode(ParseNodeKind kind, const TokenPos& pos)
   1200      : ParseNode(kind, pos),
   1201        head_(nullptr),
   1202        tail_(&head_),
   1203        count_(0),
   1204        xflags(0) {
   1205    MOZ_ASSERT(is<ListNode>());
   1206  }
   1207 
   1208  ListNode(ParseNodeKind kind, ParseNode* kid)
   1209      : ParseNode(kind, kid->pn_pos),
   1210        head_(kid),
   1211        tail_(&kid->pn_next),
   1212        count_(1),
   1213        xflags(0) {
   1214    if (kid->pn_pos.begin < pn_pos.begin) {
   1215      pn_pos.begin = kid->pn_pos.begin;
   1216    }
   1217    pn_pos.end = kid->pn_pos.end;
   1218 
   1219    MOZ_ASSERT(is<ListNode>());
   1220  }
   1221 
   1222  static bool test(const ParseNode& node) {
   1223    return node.typeCode() == TypeCode::List;
   1224  }
   1225 
   1226  static constexpr TypeCode classTypeCode() { return TypeCode::List; }
   1227 
   1228  template <typename Visitor>
   1229  bool accept(Visitor& visitor) {
   1230    ParseNode** listp = &head_;
   1231    for (; *listp; listp = &(*listp)->pn_next) {
   1232      // Don't use reference because we want to check if it changed, so we can
   1233      // use ReplaceNode
   1234      ParseNode* pn = *listp;
   1235      if (!visitor.visit(pn)) {
   1236        return false;
   1237      }
   1238      if (pn != *listp) {
   1239        ReplaceNode(listp, pn);
   1240      }
   1241    }
   1242    unsafeReplaceTail(listp);
   1243    return true;
   1244  }
   1245 
   1246 #ifdef DEBUG
   1247  void dumpImpl(const ParserAtomsTable* parserAtoms, GenericPrinter& out,
   1248                int indent);
   1249 #endif
   1250 
   1251  ParseNode* head() const { return head_; }
   1252 
   1253  ParseNode** tail() const { return tail_; }
   1254 
   1255  uint32_t count() const { return count_; }
   1256 
   1257  bool empty() const { return count() == 0; }
   1258 
   1259  void checkConsistency() const
   1260 #ifndef DEBUG
   1261  {}
   1262 #endif
   1263  ;
   1264 
   1265  [[nodiscard]] bool hasTopLevelFunctionDeclarations() const {
   1266    MOZ_ASSERT(isKind(ParseNodeKind::StatementList));
   1267    return xflags & hasTopLevelFunctionDeclarationsBit;
   1268  }
   1269 
   1270  [[nodiscard]] bool emittedTopLevelFunctionDeclarations() const {
   1271    MOZ_ASSERT(isKind(ParseNodeKind::StatementList));
   1272    MOZ_ASSERT(hasTopLevelFunctionDeclarations());
   1273    return xflags & emittedTopLevelFunctionDeclarationsBit;
   1274  }
   1275 
   1276  [[nodiscard]] bool hasNonConstInitializer() const {
   1277    MOZ_ASSERT(isKind(ParseNodeKind::ArrayExpr) ||
   1278               isKind(ParseNodeKind::ObjectExpr));
   1279    return xflags & hasNonConstInitializerBit;
   1280  }
   1281 
   1282  void setHasTopLevelFunctionDeclarations() {
   1283    MOZ_ASSERT(isKind(ParseNodeKind::StatementList));
   1284    xflags |= hasTopLevelFunctionDeclarationsBit;
   1285  }
   1286 
   1287  void setEmittedTopLevelFunctionDeclarations() {
   1288    MOZ_ASSERT(isKind(ParseNodeKind::StatementList));
   1289    MOZ_ASSERT(hasTopLevelFunctionDeclarations());
   1290    xflags |= emittedTopLevelFunctionDeclarationsBit;
   1291  }
   1292 
   1293  void setHasNonConstInitializer() {
   1294    MOZ_ASSERT(isKind(ParseNodeKind::ArrayExpr) ||
   1295               isKind(ParseNodeKind::ObjectExpr));
   1296    xflags |= hasNonConstInitializerBit;
   1297  }
   1298 
   1299  void unsetHasNonConstInitializer() {
   1300    MOZ_ASSERT(isKind(ParseNodeKind::ArrayExpr) ||
   1301               isKind(ParseNodeKind::ObjectExpr));
   1302    xflags &= ~hasNonConstInitializerBit;
   1303  }
   1304 
   1305  /*
   1306   * Compute a pointer to the last element in a singly-linked list. NB: list
   1307   * must be non-empty -- this is asserted!
   1308   */
   1309  ParseNode* last() const {
   1310    MOZ_ASSERT(!empty());
   1311    //
   1312    // ParseNode                      ParseNode
   1313    // +-----+---------+-----+        +-----+---------+-----+
   1314    // | ... | pn_next | ... | +-...->| ... | pn_next | ... |
   1315    // +-----+---------+-----+ |      +-----+---------+-----+
   1316    // ^       |               |      ^     ^
   1317    // |       +---------------+      |     |
   1318    // |                              |     tail()
   1319    // |                              |
   1320    // head()                         last()
   1321    //
   1322    return (ParseNode*)(uintptr_t(tail()) - offsetof(ParseNode, pn_next));
   1323  }
   1324 
   1325  void replaceLast(ParseNode* node) {
   1326    MOZ_ASSERT(!empty());
   1327    pn_pos.end = node->pn_pos.end;
   1328 
   1329    ParseNode* item = head();
   1330    ParseNode* lastNode = last();
   1331    MOZ_ASSERT(item);
   1332    if (item == lastNode) {
   1333      head_ = node;
   1334    } else {
   1335      while (item->pn_next != lastNode) {
   1336        MOZ_ASSERT(item->pn_next);
   1337        item = item->pn_next;
   1338      }
   1339      item->pn_next = node;
   1340    }
   1341    tail_ = &node->pn_next;
   1342  }
   1343 
   1344  void append(ParseNode* item) {
   1345    MOZ_ASSERT(item->pn_pos.begin >= pn_pos.begin);
   1346    pn_pos.end = item->pn_pos.end;
   1347    *tail_ = item;
   1348    tail_ = &item->pn_next;
   1349    count_++;
   1350  }
   1351 
   1352  void prepend(ParseNode* item) {
   1353    item->pn_next = head_;
   1354    head_ = item;
   1355    if (tail_ == &head_) {
   1356      tail_ = &item->pn_next;
   1357    }
   1358    count_++;
   1359  }
   1360 
   1361  // Methods used by FoldConstants.cpp.
   1362  // Caller is responsible for keeping the list consistent.
   1363  ParseNode** unsafeHeadReference() { return &head_; }
   1364 
   1365  void unsafeReplaceTail(ParseNode** newTail) {
   1366    tail_ = newTail;
   1367    checkConsistency();
   1368  }
   1369 
   1370  void unsafeDecrementCount() {
   1371    MOZ_ASSERT(count() > 1);
   1372    count_--;
   1373  }
   1374 
   1375 private:
   1376  // Classes to iterate over ListNode contents:
   1377  //
   1378  // Usage:
   1379  //   ListNode* list;
   1380  //   for (ParseNode* item : list->contents()) {
   1381  //     // item is ParseNode* typed.
   1382  //   }
   1383  class iterator {
   1384   private:
   1385    ParseNode* node_;
   1386 
   1387    friend class ListNode;
   1388    explicit iterator(ParseNode* node) : node_(node) {}
   1389 
   1390   public:
   1391    // Implement std::iterator_traits.
   1392    using iterator_category = std::input_iterator_tag;
   1393    using value_type = ParseNode*;
   1394    using difference_type = ptrdiff_t;
   1395    using pointer = ParseNode**;
   1396    using reference = ParseNode*&;
   1397 
   1398    bool operator==(const iterator& other) const {
   1399      return node_ == other.node_;
   1400    }
   1401 
   1402    bool operator!=(const iterator& other) const { return !(*this == other); }
   1403 
   1404    iterator& operator++() {
   1405      node_ = node_->pn_next;
   1406      return *this;
   1407    }
   1408 
   1409    ParseNode* operator*() { return node_; }
   1410 
   1411    const ParseNode* operator*() const { return node_; }
   1412  };
   1413 
   1414  class range {
   1415   private:
   1416    ParseNode* begin_;
   1417    ParseNode* end_;
   1418 
   1419    friend class ListNode;
   1420    range(ParseNode* begin, ParseNode* end) : begin_(begin), end_(end) {}
   1421 
   1422   public:
   1423    iterator begin() { return iterator(begin_); }
   1424 
   1425    iterator end() { return iterator(end_); }
   1426 
   1427    const iterator begin() const { return iterator(begin_); }
   1428 
   1429    const iterator end() const { return iterator(end_); }
   1430 
   1431    const iterator cbegin() const { return begin(); }
   1432 
   1433    const iterator cend() const { return end(); }
   1434  };
   1435 
   1436 #ifdef DEBUG
   1437  [[nodiscard]] bool contains(ParseNode* target) const {
   1438    MOZ_ASSERT(target);
   1439    for (ParseNode* node : contents()) {
   1440      if (target == node) {
   1441        return true;
   1442      }
   1443    }
   1444    return false;
   1445  }
   1446 #endif
   1447 
   1448 public:
   1449  range contents() { return range(head(), nullptr); }
   1450 
   1451  const range contents() const { return range(head(), nullptr); }
   1452 
   1453  range contentsFrom(ParseNode* begin) {
   1454    MOZ_ASSERT_IF(begin, contains(begin));
   1455    return range(begin, nullptr);
   1456  }
   1457 
   1458  const range contentsFrom(ParseNode* begin) const {
   1459    MOZ_ASSERT_IF(begin, contains(begin));
   1460    return range(begin, nullptr);
   1461  }
   1462 
   1463  range contentsTo(ParseNode* end) {
   1464    MOZ_ASSERT_IF(end, contains(end));
   1465    return range(head(), end);
   1466  }
   1467 
   1468  const range contentsTo(ParseNode* end) const {
   1469    MOZ_ASSERT_IF(end, contains(end));
   1470    return range(head(), end);
   1471  }
   1472 };
   1473 
   1474 class DeclarationListNode : public ListNode {
   1475 public:
   1476  DeclarationListNode(ParseNodeKind kind, const TokenPos& pos)
   1477      : ListNode(kind, pos) {
   1478    MOZ_ASSERT(is<DeclarationListNode>());
   1479  }
   1480 
   1481  static bool test(const ParseNode& node) {
   1482    bool match = node.isKind(ParseNodeKind::VarStmt) ||
   1483                 node.isKind(ParseNodeKind::LetDecl) ||
   1484 #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT
   1485                 node.isKind(ParseNodeKind::UsingDecl) ||
   1486                 node.isKind(ParseNodeKind::AwaitUsingDecl) ||
   1487 #endif
   1488                 node.isKind(ParseNodeKind::ConstDecl);
   1489    MOZ_ASSERT_IF(match, node.is<ListNode>());
   1490    return match;
   1491  }
   1492 
   1493  auto* singleBinding() const {
   1494    MOZ_ASSERT(count() == 1);
   1495    return head();
   1496  }
   1497 };
   1498 
   1499 class ParamsBodyNode : public ListNode {
   1500 public:
   1501  explicit ParamsBodyNode(const TokenPos& pos)
   1502      : ListNode(ParseNodeKind::ParamsBody, pos) {
   1503    MOZ_ASSERT(is<ParamsBodyNode>());
   1504  }
   1505 
   1506  static bool test(const ParseNode& node) {
   1507    bool match = node.isKind(ParseNodeKind::ParamsBody);
   1508    MOZ_ASSERT_IF(match, node.is<ListNode>());
   1509    return match;
   1510  }
   1511 
   1512  auto parameters() const {
   1513    MOZ_ASSERT(last()->is<LexicalScopeNode>());
   1514    return contentsTo(last());
   1515  }
   1516 
   1517  auto* body() const {
   1518    MOZ_ASSERT(last()->is<LexicalScopeNode>());
   1519    return &last()->as<LexicalScopeNode>();
   1520  }
   1521 };
   1522 
   1523 class FunctionNode : public ParseNode {
   1524  FunctionBox* funbox_;
   1525  ParseNode* body_;
   1526  FunctionSyntaxKind syntaxKind_;
   1527 
   1528 public:
   1529  FunctionNode(FunctionSyntaxKind syntaxKind, const TokenPos& pos)
   1530      : ParseNode(ParseNodeKind::Function, pos),
   1531        funbox_(nullptr),
   1532        body_(nullptr),
   1533        syntaxKind_(syntaxKind) {
   1534    MOZ_ASSERT(!body_);
   1535    MOZ_ASSERT(!funbox_);
   1536    MOZ_ASSERT(is<FunctionNode>());
   1537  }
   1538 
   1539  static bool test(const ParseNode& node) {
   1540    return node.isKind(ParseNodeKind::Function);
   1541  }
   1542 
   1543  static constexpr TypeCode classTypeCode() { return TypeCode::Other; }
   1544 
   1545  template <typename Visitor>
   1546  bool accept(Visitor& visitor) {
   1547    // Note: body is null for lazily-parsed functions.
   1548    if (body_) {
   1549      if (!visitor.visit(body_)) {
   1550        return false;
   1551      }
   1552      MOZ_ASSERT(body_->is<ParamsBodyNode>());
   1553    }
   1554    return true;
   1555  }
   1556 
   1557 #ifdef DEBUG
   1558  void dumpImpl(const ParserAtomsTable* parserAtoms, GenericPrinter& out,
   1559                int indent);
   1560 #endif
   1561 
   1562  FunctionBox* funbox() const { return funbox_; }
   1563 
   1564  ParamsBodyNode* body() const {
   1565    return body_ ? &body_->as<ParamsBodyNode>() : nullptr;
   1566  }
   1567 
   1568  void setFunbox(FunctionBox* funbox) { funbox_ = funbox; }
   1569 
   1570  void setBody(ParamsBodyNode* body) { body_ = body; }
   1571 
   1572  FunctionSyntaxKind syntaxKind() const { return syntaxKind_; }
   1573 
   1574  bool functionIsHoisted() const {
   1575    return syntaxKind() == FunctionSyntaxKind::Statement;
   1576  }
   1577 };
   1578 
   1579 class ModuleNode : public ParseNode {
   1580  ParseNode* body_;
   1581 
   1582 public:
   1583  explicit ModuleNode(const TokenPos& pos)
   1584      : ParseNode(ParseNodeKind::Module, pos), body_(nullptr) {
   1585    MOZ_ASSERT(!body_);
   1586    MOZ_ASSERT(is<ModuleNode>());
   1587  }
   1588 
   1589  static bool test(const ParseNode& node) {
   1590    return node.isKind(ParseNodeKind::Module);
   1591  }
   1592 
   1593  static constexpr TypeCode classTypeCode() { return TypeCode::Other; }
   1594 
   1595  template <typename Visitor>
   1596  bool accept(Visitor& visitor) {
   1597    return visitor.visit(body_);
   1598  }
   1599 
   1600 #ifdef DEBUG
   1601  void dumpImpl(const ParserAtomsTable* parserAtoms, GenericPrinter& out,
   1602                int indent);
   1603 #endif
   1604 
   1605  ListNode* body() const { return &body_->as<ListNode>(); }
   1606 
   1607  void setBody(ListNode* body) { body_ = body; }
   1608 };
   1609 
   1610 class NumericLiteral : public ParseNode {
   1611  double value_;              /* aligned numeric literal value */
   1612  DecimalPoint decimalPoint_; /* Whether the number has a decimal point */
   1613 
   1614 public:
   1615  NumericLiteral(double value, DecimalPoint decimalPoint, const TokenPos& pos)
   1616      : ParseNode(ParseNodeKind::NumberExpr, pos),
   1617        value_(value),
   1618        decimalPoint_(decimalPoint) {}
   1619 
   1620  static bool test(const ParseNode& node) {
   1621    return node.isKind(ParseNodeKind::NumberExpr);
   1622  }
   1623 
   1624  static constexpr TypeCode classTypeCode() { return TypeCode::Other; }
   1625 
   1626  template <typename Visitor>
   1627  bool accept(Visitor& visitor) {
   1628    return true;
   1629  }
   1630 
   1631 #ifdef DEBUG
   1632  void dumpImpl(const ParserAtomsTable* parserAtoms, GenericPrinter& out,
   1633                int indent);
   1634 #endif
   1635 
   1636  double value() const { return value_; }
   1637 
   1638  DecimalPoint decimalPoint() const { return decimalPoint_; }
   1639 
   1640  // Return the decimal string representation of this numeric literal.
   1641  TaggedParserAtomIndex toAtom(FrontendContext* fc,
   1642                               ParserAtomsTable& parserAtoms) const;
   1643 };
   1644 
   1645 class BigIntLiteral : public ParseNode {
   1646  BigIntIndex index_;
   1647 
   1648 public:
   1649  BigIntLiteral(BigIntIndex index, const TokenPos& pos)
   1650      : ParseNode(ParseNodeKind::BigIntExpr, pos), index_(index) {}
   1651 
   1652  static bool test(const ParseNode& node) {
   1653    return node.isKind(ParseNodeKind::BigIntExpr);
   1654  }
   1655 
   1656  static constexpr TypeCode classTypeCode() { return TypeCode::Other; }
   1657 
   1658  template <typename Visitor>
   1659  bool accept(Visitor& visitor) {
   1660    return true;
   1661  }
   1662 
   1663 #ifdef DEBUG
   1664  void dumpImpl(const ParserAtomsTable* parserAtoms, GenericPrinter& out,
   1665                int indent);
   1666 #endif
   1667 
   1668  BigIntIndex index() { return index_; }
   1669 };
   1670 
   1671 template <ParseNodeKind NodeKind, typename ScopeType>
   1672 class BaseScopeNode : public ParseNode {
   1673  using ParserData = typename ScopeType::ParserData;
   1674  ParserData* bindings;
   1675  ParseNode* body;
   1676  ScopeKind kind_;
   1677 
   1678 public:
   1679  BaseScopeNode(ParserData* bindings, ParseNode* body,
   1680                ScopeKind kind = ScopeKind::Lexical)
   1681      : ParseNode(NodeKind, body->pn_pos),
   1682        bindings(bindings),
   1683        body(body),
   1684        kind_(kind) {}
   1685 
   1686  static bool test(const ParseNode& node) { return node.isKind(NodeKind); }
   1687 
   1688  static constexpr TypeCode classTypeCode() { return TypeCode::Other; }
   1689 
   1690  template <typename Visitor>
   1691  bool accept(Visitor& visitor) {
   1692    return visitor.visit(body);
   1693  }
   1694 
   1695 #ifdef DEBUG
   1696  void dumpImpl(const ParserAtomsTable* parserAtoms, GenericPrinter& out,
   1697                int indent);
   1698 #endif
   1699 
   1700  ParserData* scopeBindings() const {
   1701    MOZ_ASSERT(!isEmptyScope());
   1702    return bindings;
   1703  }
   1704 
   1705  ParseNode* scopeBody() const { return body; }
   1706 
   1707  void setScopeBody(ParseNode* body) { this->body = body; }
   1708 
   1709  bool isEmptyScope() const { return !bindings; }
   1710 
   1711  ScopeKind kind() const { return kind_; }
   1712 };
   1713 
   1714 class LexicalScopeNode
   1715    : public BaseScopeNode<ParseNodeKind::LexicalScope, LexicalScope> {
   1716 public:
   1717  LexicalScopeNode(LexicalScope::ParserData* bindings, ParseNode* body,
   1718                   ScopeKind kind = ScopeKind::Lexical)
   1719      : BaseScopeNode(bindings, body, kind) {}
   1720 };
   1721 
   1722 class ClassBodyScopeNode
   1723    : public BaseScopeNode<ParseNodeKind::ClassBodyScope, ClassBodyScope> {
   1724 public:
   1725  ClassBodyScopeNode(ClassBodyScope::ParserData* bindings, ListNode* memberList)
   1726      : BaseScopeNode(bindings, memberList, ScopeKind::ClassBody) {
   1727    MOZ_ASSERT(memberList->isKind(ParseNodeKind::ClassMemberList));
   1728  }
   1729 
   1730  ListNode* memberList() const {
   1731    ListNode* list = &scopeBody()->as<ListNode>();
   1732    MOZ_ASSERT(list->isKind(ParseNodeKind::ClassMemberList));
   1733    return list;
   1734  }
   1735 };
   1736 
   1737 class LabeledStatement : public NameNode {
   1738  ParseNode* statement_;
   1739 
   1740 public:
   1741  LabeledStatement(TaggedParserAtomIndex label, ParseNode* stmt, uint32_t begin)
   1742      : NameNode(ParseNodeKind::LabelStmt, label,
   1743                 TokenPos(begin, stmt->pn_pos.end)),
   1744        statement_(stmt) {}
   1745 
   1746  TaggedParserAtomIndex label() const { return atom(); }
   1747 
   1748  ParseNode* statement() const { return statement_; }
   1749 
   1750  static bool test(const ParseNode& node) {
   1751    return node.isKind(ParseNodeKind::LabelStmt);
   1752  }
   1753 
   1754  template <typename Visitor>
   1755  bool accept(Visitor& visitor) {
   1756    if (statement_) {
   1757      if (!visitor.visit(statement_)) {
   1758        return false;
   1759      }
   1760    }
   1761    return true;
   1762  }
   1763 
   1764 #ifdef DEBUG
   1765  void dumpImpl(const ParserAtomsTable* parserAtoms, GenericPrinter& out,
   1766                int indent);
   1767 #endif
   1768 };
   1769 
   1770 // Inside a switch statement, a CaseClause is a case-label and the subsequent
   1771 // statements. The same node type is used for DefaultClauses. The only
   1772 // difference is that their caseExpression() is null.
   1773 class CaseClause : public BinaryNode {
   1774 public:
   1775  CaseClause(ParseNode* expr, ParseNode* stmts, uint32_t begin)
   1776      : BinaryNode(ParseNodeKind::Case, TokenPos(begin, stmts->pn_pos.end),
   1777                   expr, stmts) {}
   1778 
   1779  ParseNode* caseExpression() const { return left(); }
   1780 
   1781  bool isDefault() const { return !caseExpression(); }
   1782 
   1783  ListNode* statementList() const { return &right()->as<ListNode>(); }
   1784 
   1785  static bool test(const ParseNode& node) {
   1786    bool match = node.isKind(ParseNodeKind::Case);
   1787    MOZ_ASSERT_IF(match, node.is<BinaryNode>());
   1788    return match;
   1789  }
   1790 };
   1791 
   1792 class LoopControlStatement : public ParseNode {
   1793  TaggedParserAtomIndex label_; /* target of break/continue statement */
   1794 
   1795 protected:
   1796  LoopControlStatement(ParseNodeKind kind, TaggedParserAtomIndex label,
   1797                       const TokenPos& pos)
   1798      : ParseNode(kind, pos), label_(label) {
   1799    MOZ_ASSERT(kind == ParseNodeKind::BreakStmt ||
   1800               kind == ParseNodeKind::ContinueStmt);
   1801    MOZ_ASSERT(is<LoopControlStatement>());
   1802  }
   1803 
   1804 public:
   1805  /* Label associated with this break/continue statement, if any. */
   1806  TaggedParserAtomIndex label() const { return label_; }
   1807 
   1808 #ifdef DEBUG
   1809  void dumpImpl(const ParserAtomsTable* parserAtoms, GenericPrinter& out,
   1810                int indent);
   1811 #endif
   1812 
   1813  static bool test(const ParseNode& node) {
   1814    return node.isKind(ParseNodeKind::BreakStmt) ||
   1815           node.isKind(ParseNodeKind::ContinueStmt);
   1816  }
   1817 
   1818  static constexpr TypeCode classTypeCode() { return TypeCode::Other; }
   1819 
   1820  template <typename Visitor>
   1821  bool accept(Visitor& visitor) {
   1822    return true;
   1823  }
   1824 };
   1825 
   1826 class BreakStatement : public LoopControlStatement {
   1827 public:
   1828  BreakStatement(TaggedParserAtomIndex label, const TokenPos& pos)
   1829      : LoopControlStatement(ParseNodeKind::BreakStmt, label, pos) {}
   1830 
   1831  static bool test(const ParseNode& node) {
   1832    bool match = node.isKind(ParseNodeKind::BreakStmt);
   1833    MOZ_ASSERT_IF(match, node.is<LoopControlStatement>());
   1834    return match;
   1835  }
   1836 };
   1837 
   1838 class ContinueStatement : public LoopControlStatement {
   1839 public:
   1840  ContinueStatement(TaggedParserAtomIndex label, const TokenPos& pos)
   1841      : LoopControlStatement(ParseNodeKind::ContinueStmt, label, pos) {}
   1842 
   1843  static bool test(const ParseNode& node) {
   1844    bool match = node.isKind(ParseNodeKind::ContinueStmt);
   1845    MOZ_ASSERT_IF(match, node.is<LoopControlStatement>());
   1846    return match;
   1847  }
   1848 };
   1849 
   1850 class DebuggerStatement : public NullaryNode {
   1851 public:
   1852  explicit DebuggerStatement(const TokenPos& pos)
   1853      : NullaryNode(ParseNodeKind::DebuggerStmt, pos) {}
   1854 
   1855  static bool test(const ParseNode& node) {
   1856    bool match = node.isKind(ParseNodeKind::DebuggerStmt);
   1857    MOZ_ASSERT_IF(match, node.is<NullaryNode>());
   1858    return match;
   1859  }
   1860 };
   1861 
   1862 class ConditionalExpression : public TernaryNode {
   1863 public:
   1864  ConditionalExpression(ParseNode* condition, ParseNode* thenExpr,
   1865                        ParseNode* elseExpr)
   1866      : TernaryNode(ParseNodeKind::ConditionalExpr, condition, thenExpr,
   1867                    elseExpr,
   1868                    TokenPos(condition->pn_pos.begin, elseExpr->pn_pos.end)) {
   1869    MOZ_ASSERT(condition);
   1870    MOZ_ASSERT(thenExpr);
   1871    MOZ_ASSERT(elseExpr);
   1872  }
   1873 
   1874  ParseNode& condition() const { return *kid1(); }
   1875 
   1876  ParseNode& thenExpression() const { return *kid2(); }
   1877 
   1878  ParseNode& elseExpression() const { return *kid3(); }
   1879 
   1880  static bool test(const ParseNode& node) {
   1881    bool match = node.isKind(ParseNodeKind::ConditionalExpr);
   1882    MOZ_ASSERT_IF(match, node.is<TernaryNode>());
   1883    return match;
   1884  }
   1885 };
   1886 
   1887 class TryNode : public TernaryNode {
   1888 public:
   1889  TryNode(uint32_t begin, ParseNode* body, LexicalScopeNode* catchScope,
   1890          ParseNode* finallyBlock)
   1891      : TernaryNode(
   1892            ParseNodeKind::TryStmt, body, catchScope, finallyBlock,
   1893            TokenPos(begin,
   1894                     (finallyBlock ? finallyBlock : catchScope)->pn_pos.end)) {
   1895    MOZ_ASSERT(body);
   1896    MOZ_ASSERT(catchScope || finallyBlock);
   1897  }
   1898 
   1899  static bool test(const ParseNode& node) {
   1900    bool match = node.isKind(ParseNodeKind::TryStmt);
   1901    MOZ_ASSERT_IF(match, node.is<TernaryNode>());
   1902    return match;
   1903  }
   1904 
   1905  ParseNode* body() const { return kid1(); }
   1906 
   1907  LexicalScopeNode* catchScope() const {
   1908    return kid2() ? &kid2()->as<LexicalScopeNode>() : nullptr;
   1909  }
   1910 
   1911  ParseNode* finallyBlock() const { return kid3(); }
   1912 };
   1913 
   1914 class ThisLiteral : public UnaryNode {
   1915 public:
   1916  ThisLiteral(const TokenPos& pos, ParseNode* thisName)
   1917      : UnaryNode(ParseNodeKind::ThisExpr, pos, thisName) {}
   1918 
   1919  static bool test(const ParseNode& node) {
   1920    bool match = node.isKind(ParseNodeKind::ThisExpr);
   1921    MOZ_ASSERT_IF(match, node.is<UnaryNode>());
   1922    return match;
   1923  }
   1924 };
   1925 
   1926 class NullLiteral : public NullaryNode {
   1927 public:
   1928  explicit NullLiteral(const TokenPos& pos)
   1929      : NullaryNode(ParseNodeKind::NullExpr, pos) {}
   1930 
   1931  static bool test(const ParseNode& node) {
   1932    bool match = node.isKind(ParseNodeKind::NullExpr);
   1933    MOZ_ASSERT_IF(match, node.is<NullaryNode>());
   1934    return match;
   1935  }
   1936 };
   1937 
   1938 // This is only used internally, currently just for tagged templates and the
   1939 // initial value of fields without initializers. It represents the value
   1940 // 'undefined' (aka `void 0`), like NullLiteral represents the value 'null'.
   1941 class RawUndefinedLiteral : public NullaryNode {
   1942 public:
   1943  explicit RawUndefinedLiteral(const TokenPos& pos)
   1944      : NullaryNode(ParseNodeKind::RawUndefinedExpr, pos) {}
   1945 
   1946  static bool test(const ParseNode& node) {
   1947    bool match = node.isKind(ParseNodeKind::RawUndefinedExpr);
   1948    MOZ_ASSERT_IF(match, node.is<NullaryNode>());
   1949    return match;
   1950  }
   1951 };
   1952 
   1953 class BooleanLiteral : public NullaryNode {
   1954 public:
   1955  BooleanLiteral(bool b, const TokenPos& pos)
   1956      : NullaryNode(b ? ParseNodeKind::TrueExpr : ParseNodeKind::FalseExpr,
   1957                    pos) {}
   1958 
   1959  static bool test(const ParseNode& node) {
   1960    bool match = node.isKind(ParseNodeKind::TrueExpr) ||
   1961                 node.isKind(ParseNodeKind::FalseExpr);
   1962    MOZ_ASSERT_IF(match, node.is<NullaryNode>());
   1963    return match;
   1964  }
   1965 };
   1966 
   1967 class RegExpLiteral : public ParseNode {
   1968  RegExpIndex index_;
   1969 
   1970 public:
   1971  RegExpLiteral(RegExpIndex dataIndex, const TokenPos& pos)
   1972      : ParseNode(ParseNodeKind::RegExpExpr, pos), index_(dataIndex) {}
   1973 
   1974  // Create a RegExp object of this RegExp literal.
   1975  RegExpObject* create(JSContext* cx, FrontendContext* fc,
   1976                       ParserAtomsTable& parserAtoms,
   1977                       CompilationAtomCache& atomCache,
   1978                       ExtensibleCompilationStencil& stencil) const;
   1979 
   1980 #ifdef DEBUG
   1981  void dumpImpl(const ParserAtomsTable* parserAtoms, GenericPrinter& out,
   1982                int indent);
   1983 #endif
   1984 
   1985  static bool test(const ParseNode& node) {
   1986    return node.isKind(ParseNodeKind::RegExpExpr);
   1987  }
   1988 
   1989  static constexpr TypeCode classTypeCode() { return TypeCode::Other; }
   1990 
   1991  template <typename Visitor>
   1992  bool accept(Visitor& visitor) {
   1993    return true;
   1994  }
   1995 
   1996  RegExpIndex index() { return index_; }
   1997 };
   1998 
   1999 class PropertyAccessBase : public BinaryNode {
   2000 public:
   2001  /*
   2002   * PropertyAccess nodes can have any expression/'super' as left-hand
   2003   * side, but the name must be a ParseNodeKind::PropertyName node.
   2004   */
   2005  PropertyAccessBase(ParseNodeKind kind, ParseNode* lhs, NameNode* name,
   2006                     uint32_t begin, uint32_t end)
   2007      : BinaryNode(kind, TokenPos(begin, end), lhs, name) {
   2008    MOZ_ASSERT(lhs);
   2009    MOZ_ASSERT(name);
   2010  }
   2011 
   2012  ParseNode& expression() const { return *left(); }
   2013 
   2014  static bool test(const ParseNode& node) {
   2015    bool match = node.isKind(ParseNodeKind::DotExpr) ||
   2016                 node.isKind(ParseNodeKind::OptionalDotExpr) ||
   2017                 node.isKind(ParseNodeKind::ArgumentsLength);
   2018    MOZ_ASSERT_IF(match, node.is<BinaryNode>());
   2019    MOZ_ASSERT_IF(match, node.as<BinaryNode>().right()->isKind(
   2020                             ParseNodeKind::PropertyNameExpr));
   2021    return match;
   2022  }
   2023 
   2024  NameNode& key() const { return right()->as<NameNode>(); }
   2025 
   2026  // Method used by BytecodeEmitter::emitPropLHS for optimization.
   2027  // Those methods allow expression to temporarily be nullptr for
   2028  // optimization purpose.
   2029  ParseNode* maybeExpression() const { return left(); }
   2030 
   2031  void setExpression(ParseNode* pn) { *unsafeLeftReference() = pn; }
   2032 
   2033  TaggedParserAtomIndex name() const { return right()->as<NameNode>().atom(); }
   2034 };
   2035 
   2036 class PropertyAccess : public PropertyAccessBase {
   2037 public:
   2038  PropertyAccess(ParseNode* lhs, NameNode* name, uint32_t begin, uint32_t end)
   2039      : PropertyAccessBase(ParseNodeKind::DotExpr, lhs, name, begin, end) {
   2040    MOZ_ASSERT(lhs);
   2041    MOZ_ASSERT(name);
   2042  }
   2043 
   2044  static bool test(const ParseNode& node) {
   2045    bool match = node.isKind(ParseNodeKind::DotExpr) ||
   2046                 node.isKind(ParseNodeKind::ArgumentsLength);
   2047    MOZ_ASSERT_IF(match, node.is<PropertyAccessBase>());
   2048    return match;
   2049  }
   2050 
   2051  bool isSuper() const {
   2052    // ParseNodeKind::SuperBase cannot result from any expression syntax.
   2053    return expression().isKind(ParseNodeKind::SuperBase);
   2054  }
   2055 
   2056 protected:
   2057  using PropertyAccessBase::PropertyAccessBase;
   2058 };
   2059 
   2060 class ArgumentsLength : public PropertyAccess {
   2061 public:
   2062  ArgumentsLength(ParseNode* lhs, NameNode* name, uint32_t begin, uint32_t end)
   2063      : PropertyAccess(ParseNodeKind::ArgumentsLength, lhs, name, begin, end) {
   2064    MOZ_ASSERT(lhs);
   2065    MOZ_ASSERT(name);
   2066  }
   2067 
   2068  static bool test(const ParseNode& node) {
   2069    bool match = node.isKind(ParseNodeKind::ArgumentsLength);
   2070    MOZ_ASSERT_IF(match, node.is<PropertyAccessBase>());
   2071    return match;
   2072  }
   2073 
   2074  bool isSuper() const { return false; }
   2075 };
   2076 
   2077 class OptionalPropertyAccess : public PropertyAccessBase {
   2078 public:
   2079  OptionalPropertyAccess(ParseNode* lhs, NameNode* name, uint32_t begin,
   2080                         uint32_t end)
   2081      : PropertyAccessBase(ParseNodeKind::OptionalDotExpr, lhs, name, begin,
   2082                           end) {
   2083    MOZ_ASSERT(lhs);
   2084    MOZ_ASSERT(name);
   2085  }
   2086 
   2087  static bool test(const ParseNode& node) {
   2088    bool match = node.isKind(ParseNodeKind::OptionalDotExpr);
   2089    MOZ_ASSERT_IF(match, node.is<PropertyAccessBase>());
   2090    return match;
   2091  }
   2092 };
   2093 
   2094 class PropertyByValueBase : public BinaryNode {
   2095 public:
   2096  PropertyByValueBase(ParseNodeKind kind, ParseNode* lhs, ParseNode* propExpr,
   2097                      uint32_t begin, uint32_t end)
   2098      : BinaryNode(kind, TokenPos(begin, end), lhs, propExpr) {}
   2099 
   2100  static bool test(const ParseNode& node) {
   2101    bool match = node.isKind(ParseNodeKind::ElemExpr) ||
   2102                 node.isKind(ParseNodeKind::OptionalElemExpr);
   2103    MOZ_ASSERT_IF(match, node.is<BinaryNode>());
   2104    return match;
   2105  }
   2106 
   2107  ParseNode& expression() const { return *left(); }
   2108 
   2109  ParseNode& key() const { return *right(); }
   2110 };
   2111 
   2112 class PropertyByValue : public PropertyByValueBase {
   2113 public:
   2114  PropertyByValue(ParseNode* lhs, ParseNode* propExpr, uint32_t begin,
   2115                  uint32_t end)
   2116      : PropertyByValueBase(ParseNodeKind::ElemExpr, lhs, propExpr, begin,
   2117                            end) {}
   2118 
   2119  static bool test(const ParseNode& node) {
   2120    bool match = node.isKind(ParseNodeKind::ElemExpr);
   2121    MOZ_ASSERT_IF(match, node.is<PropertyByValueBase>());
   2122    return match;
   2123  }
   2124 
   2125  bool isSuper() const { return left()->isKind(ParseNodeKind::SuperBase); }
   2126 };
   2127 
   2128 class OptionalPropertyByValue : public PropertyByValueBase {
   2129 public:
   2130  OptionalPropertyByValue(ParseNode* lhs, ParseNode* propExpr, uint32_t begin,
   2131                          uint32_t end)
   2132      : PropertyByValueBase(ParseNodeKind::OptionalElemExpr, lhs, propExpr,
   2133                            begin, end) {}
   2134 
   2135  static bool test(const ParseNode& node) {
   2136    bool match = node.isKind(ParseNodeKind::OptionalElemExpr);
   2137    MOZ_ASSERT_IF(match, node.is<PropertyByValueBase>());
   2138    return match;
   2139  }
   2140 };
   2141 
   2142 class PrivateMemberAccessBase : public BinaryNode {
   2143 public:
   2144  PrivateMemberAccessBase(ParseNodeKind kind, ParseNode* lhs, NameNode* name,
   2145                          uint32_t begin, uint32_t end)
   2146      : BinaryNode(kind, TokenPos(begin, end), lhs, name) {
   2147    MOZ_ASSERT(name->isKind(ParseNodeKind::PrivateName));
   2148  }
   2149 
   2150  ParseNode& expression() const { return *left(); }
   2151 
   2152  NameNode& privateName() const {
   2153    NameNode& name = right()->as<NameNode>();
   2154    MOZ_ASSERT(name.isKind(ParseNodeKind::PrivateName));
   2155    return name;
   2156  }
   2157 
   2158  static bool test(const ParseNode& node) {
   2159    bool match = node.isKind(ParseNodeKind::PrivateMemberExpr) ||
   2160                 node.isKind(ParseNodeKind::OptionalPrivateMemberExpr);
   2161    MOZ_ASSERT_IF(match, node.is<BinaryNode>());
   2162    MOZ_ASSERT_IF(match, node.as<BinaryNode>().right()->isKind(
   2163                             ParseNodeKind::PrivateName));
   2164    return match;
   2165  }
   2166 };
   2167 
   2168 class PrivateMemberAccess : public PrivateMemberAccessBase {
   2169 public:
   2170  PrivateMemberAccess(ParseNode* lhs, NameNode* name, uint32_t begin,
   2171                      uint32_t end)
   2172      : PrivateMemberAccessBase(ParseNodeKind::PrivateMemberExpr, lhs, name,
   2173                                begin, end) {}
   2174 
   2175  static bool test(const ParseNode& node) {
   2176    return node.isKind(ParseNodeKind::PrivateMemberExpr);
   2177  }
   2178 };
   2179 
   2180 class OptionalPrivateMemberAccess : public PrivateMemberAccessBase {
   2181 public:
   2182  OptionalPrivateMemberAccess(ParseNode* lhs, NameNode* name, uint32_t begin,
   2183                              uint32_t end)
   2184      : PrivateMemberAccessBase(ParseNodeKind::OptionalPrivateMemberExpr, lhs,
   2185                                name, begin, end) {}
   2186 
   2187  static bool test(const ParseNode& node) {
   2188    return node.isKind(ParseNodeKind::OptionalPrivateMemberExpr);
   2189  }
   2190 };
   2191 
   2192 class NewTargetNode : public TernaryNode {
   2193 public:
   2194  NewTargetNode(NullaryNode* newHolder, NullaryNode* targetHolder,
   2195                NameNode* newTargetName)
   2196      : TernaryNode(ParseNodeKind::NewTargetExpr, newHolder, targetHolder,
   2197                    newTargetName) {}
   2198 
   2199  static bool test(const ParseNode& node) {
   2200    bool match = node.isKind(ParseNodeKind::NewTargetExpr);
   2201    MOZ_ASSERT_IF(match, node.is<TernaryNode>());
   2202    return match;
   2203  }
   2204 
   2205  auto* newHolder() const { return &kid1()->as<NullaryNode>(); }
   2206  auto* targetHolder() const { return &kid2()->as<NullaryNode>(); }
   2207  auto* newTargetName() const { return &kid3()->as<NameNode>(); }
   2208 };
   2209 
   2210 /*
   2211 * A CallSiteNode represents the implicit call site object argument in a
   2212 * TaggedTemplate.
   2213 */
   2214 class CallSiteNode : public ListNode {
   2215 public:
   2216  explicit CallSiteNode(uint32_t begin)
   2217      : ListNode(ParseNodeKind::CallSiteObj, TokenPos(begin, begin + 1)) {}
   2218 
   2219  static bool test(const ParseNode& node) {
   2220    bool match = node.isKind(ParseNodeKind::CallSiteObj);
   2221    MOZ_ASSERT_IF(match, node.is<ListNode>());
   2222    return match;
   2223  }
   2224 
   2225  ListNode* rawNodes() const {
   2226    MOZ_ASSERT(head());
   2227    return &head()->as<ListNode>();
   2228  }
   2229 };
   2230 
   2231 class CallNode : public BinaryNode {
   2232  const JSOp callOp_;
   2233 
   2234 public:
   2235  CallNode(ParseNodeKind kind, JSOp callOp, ParseNode* left, ListNode* right)
   2236      : CallNode(kind, callOp, TokenPos(left->pn_pos.begin, right->pn_pos.end),
   2237                 left, right) {}
   2238 
   2239  CallNode(ParseNodeKind kind, JSOp callOp, TokenPos pos, ParseNode* left,
   2240           ListNode* right)
   2241      : BinaryNode(kind, pos, left, right), callOp_(callOp) {
   2242    MOZ_ASSERT(is<CallNode>());
   2243  }
   2244 
   2245  static bool test(const ParseNode& node) {
   2246    bool match = node.isKind(ParseNodeKind::CallExpr) ||
   2247                 node.isKind(ParseNodeKind::SuperCallExpr) ||
   2248                 node.isKind(ParseNodeKind::OptionalCallExpr) ||
   2249                 node.isKind(ParseNodeKind::TaggedTemplateExpr) ||
   2250                 node.isKind(ParseNodeKind::NewExpr);
   2251    MOZ_ASSERT_IF(match, node.is<BinaryNode>());
   2252    return match;
   2253  }
   2254 
   2255  JSOp callOp() const { return callOp_; }
   2256  auto* callee() const { return left(); }
   2257  auto* args() const { return &right()->as<ListNode>(); }
   2258 };
   2259 
   2260 class ClassMethod : public BinaryNode {
   2261  using Base = BinaryNode;
   2262 
   2263  bool isStatic_;
   2264  AccessorType accessorType_;
   2265  FunctionNode* initializerIfPrivate_;
   2266 
   2267 #ifdef ENABLE_DECORATORS
   2268  ListNode* decorators_;
   2269 #endif
   2270 
   2271 public:
   2272  /*
   2273   * Method definitions often keep a name and function body that overlap,
   2274   * so explicitly define the beginning and end here.
   2275   */
   2276  ClassMethod(ParseNodeKind kind, ParseNode* name, ParseNode* body,
   2277              AccessorType accessorType, bool isStatic,
   2278              FunctionNode* initializerIfPrivate
   2279 #ifdef ENABLE_DECORATORS
   2280              ,
   2281              ListNode* decorators
   2282 #endif
   2283              )
   2284      : BinaryNode(kind, TokenPos(name->pn_pos.begin, body->pn_pos.end), name,
   2285                   body),
   2286        isStatic_(isStatic),
   2287        accessorType_(accessorType),
   2288        initializerIfPrivate_(initializerIfPrivate)
   2289 #ifdef ENABLE_DECORATORS
   2290        ,
   2291        decorators_(decorators)
   2292 #endif
   2293  {
   2294    MOZ_ASSERT(kind == ParseNodeKind::DefaultConstructor ||
   2295               kind == ParseNodeKind::ClassMethod);
   2296  }
   2297 
   2298  static bool test(const ParseNode& node) {
   2299    bool match = node.isKind(ParseNodeKind::DefaultConstructor) ||
   2300                 node.isKind(ParseNodeKind::ClassMethod);
   2301    MOZ_ASSERT_IF(match, node.is<BinaryNode>());
   2302    return match;
   2303  }
   2304 
   2305  ParseNode& name() const { return *left(); }
   2306 
   2307  FunctionNode& method() const { return right()->as<FunctionNode>(); }
   2308 
   2309  bool isStatic() const { return isStatic_; }
   2310 
   2311  AccessorType accessorType() const { return accessorType_; }
   2312 
   2313  FunctionNode* initializerIfPrivate() const { return initializerIfPrivate_; }
   2314 
   2315 #ifdef ENABLE_DECORATORS
   2316  ListNode* decorators() const { return decorators_; }
   2317 
   2318 #  ifdef DEBUG
   2319  void dumpImpl(const ParserAtomsTable* parserAtoms, GenericPrinter& out,
   2320                int indent);
   2321 #  endif
   2322 #endif
   2323 };
   2324 
   2325 class ClassField : public BinaryNode {
   2326  using Base = BinaryNode;
   2327 
   2328  bool isStatic_;
   2329 #ifdef ENABLE_DECORATORS
   2330  // The accessorGetterNode_ and accessorSetterNode_ are used to store the
   2331  // getter and setter synthesized by the `accessor` keyword when they are
   2332  // decorated. Otherwise, they are null.
   2333  //
   2334  // In most cases, the accessors are not added to the class members, and the
   2335  // code generation occurs immediately prior to the decorator running. For
   2336  // non-static private methods, the accessors are added to the class members
   2337  // which causes them to be stored in lexical variables. The references here
   2338  // are used to store the names of the accessors to look up the values of these
   2339  // variables during bytecode generation.
   2340  ClassMethod* accessorGetterNode_;
   2341  ClassMethod* accessorSetterNode_;
   2342  ListNode* decorators_;
   2343 #endif
   2344 
   2345 public:
   2346  ClassField(ParseNode* name, ParseNode* initializer, bool isStatic
   2347 #ifdef ENABLE_DECORATORS
   2348             ,
   2349             ListNode* decorators, ClassMethod* accessorGetterNode,
   2350             ClassMethod* accessorSetterNode
   2351 #endif
   2352             )
   2353      : BinaryNode(ParseNodeKind::ClassField, initializer->pn_pos, name,
   2354                   initializer),
   2355        isStatic_(isStatic)
   2356 #ifdef ENABLE_DECORATORS
   2357        ,
   2358        accessorGetterNode_(accessorGetterNode),
   2359        accessorSetterNode_(accessorSetterNode),
   2360        decorators_(decorators)
   2361 #endif
   2362  {
   2363 #ifdef ENABLE_DECORATORS
   2364    MOZ_ASSERT((accessorGetterNode_ == nullptr) ==
   2365               (accessorSetterNode_ == nullptr));
   2366 #endif
   2367  }
   2368 
   2369  static bool test(const ParseNode& node) {
   2370    bool match = node.isKind(ParseNodeKind::ClassField);
   2371    MOZ_ASSERT_IF(match, node.is<BinaryNode>());
   2372    return match;
   2373  }
   2374 
   2375  ParseNode& name() const { return *left(); }
   2376 
   2377  FunctionNode* initializer() const { return &right()->as<FunctionNode>(); }
   2378 
   2379  bool isStatic() const { return isStatic_; }
   2380 
   2381 #ifdef ENABLE_DECORATORS
   2382  ListNode* decorators() const { return decorators_; }
   2383  bool hasAccessor() const {
   2384    return accessorGetterNode_ != nullptr && accessorSetterNode_ != nullptr;
   2385  }
   2386  ClassMethod* accessorGetterNode() { return accessorGetterNode_; }
   2387  ClassMethod* accessorSetterNode() { return accessorSetterNode_; }
   2388 
   2389 #  ifdef DEBUG
   2390  void dumpImpl(const ParserAtomsTable* parserAtoms, GenericPrinter& out,
   2391                int indent);
   2392 #  endif
   2393 #endif
   2394 };
   2395 
   2396 // Hold onto the function generated for a class static block like
   2397 //
   2398 // class A {
   2399 //  static { /* this static block */ }
   2400 // }
   2401 //
   2402 class StaticClassBlock : public UnaryNode {
   2403 public:
   2404  explicit StaticClassBlock(FunctionNode* function)
   2405      : UnaryNode(ParseNodeKind::StaticClassBlock, function->pn_pos, function) {
   2406  }
   2407 
   2408  static bool test(const ParseNode& node) {
   2409    bool match = node.isKind(ParseNodeKind::StaticClassBlock);
   2410    MOZ_ASSERT_IF(match, node.is<UnaryNode>());
   2411    return match;
   2412  }
   2413  FunctionNode* function() const { return &kid()->as<FunctionNode>(); }
   2414 };
   2415 
   2416 class PropertyDefinition : public BinaryNode {
   2417  AccessorType accessorType_;
   2418 
   2419 public:
   2420  PropertyDefinition(ParseNode* name, ParseNode* value,
   2421                     AccessorType accessorType)
   2422      : BinaryNode(ParseNodeKind::PropertyDefinition,
   2423                   TokenPos(name->pn_pos.begin, value->pn_pos.end), name,
   2424                   value),
   2425        accessorType_(accessorType) {}
   2426 
   2427  static bool test(const ParseNode& node) {
   2428    bool match = node.isKind(ParseNodeKind::PropertyDefinition);
   2429    MOZ_ASSERT_IF(match, node.is<BinaryNode>());
   2430    return match;
   2431  }
   2432 
   2433  AccessorType accessorType() { return accessorType_; }
   2434 };
   2435 
   2436 class SwitchStatement : public BinaryNode {
   2437  bool hasDefault_; /* only for ParseNodeKind::Switch */
   2438 
   2439 public:
   2440  SwitchStatement(uint32_t begin, ParseNode* discriminant,
   2441                  LexicalScopeNode* lexicalForCaseList, bool hasDefault)
   2442      : BinaryNode(ParseNodeKind::SwitchStmt,
   2443                   TokenPos(begin, lexicalForCaseList->pn_pos.end),
   2444                   discriminant, lexicalForCaseList),
   2445        hasDefault_(hasDefault) {
   2446 #ifdef DEBUG
   2447    ListNode* cases = &lexicalForCaseList->scopeBody()->as<ListNode>();
   2448    MOZ_ASSERT(cases->isKind(ParseNodeKind::StatementList));
   2449    bool found = false;
   2450    for (ParseNode* item : cases->contents()) {
   2451      CaseClause* caseNode = &item->as<CaseClause>();
   2452      if (caseNode->isDefault()) {
   2453        found = true;
   2454        break;
   2455      }
   2456    }
   2457    MOZ_ASSERT(found == hasDefault);
   2458 #endif
   2459  }
   2460 
   2461  static bool test(const ParseNode& node) {
   2462    bool match = node.isKind(ParseNodeKind::SwitchStmt);
   2463    MOZ_ASSERT_IF(match, node.is<BinaryNode>());
   2464    return match;
   2465  }
   2466 
   2467  ParseNode& discriminant() const { return *left(); }
   2468 
   2469  LexicalScopeNode& lexicalForCaseList() const {
   2470    return right()->as<LexicalScopeNode>();
   2471  }
   2472 
   2473  bool hasDefault() const { return hasDefault_; }
   2474 };
   2475 
   2476 class ClassNames : public BinaryNode {
   2477 public:
   2478  ClassNames(ParseNode* outerBinding, ParseNode* innerBinding,
   2479             const TokenPos& pos)
   2480      : BinaryNode(ParseNodeKind::ClassNames, pos, outerBinding, innerBinding) {
   2481    MOZ_ASSERT_IF(outerBinding, outerBinding->isKind(ParseNodeKind::Name));
   2482    MOZ_ASSERT(innerBinding->isKind(ParseNodeKind::Name));
   2483    MOZ_ASSERT_IF(outerBinding, innerBinding->as<NameNode>().atom() ==
   2484                                    outerBinding->as<NameNode>().atom());
   2485  }
   2486 
   2487  static bool test(const ParseNode& node) {
   2488    bool match = node.isKind(ParseNodeKind::ClassNames);
   2489    MOZ_ASSERT_IF(match, node.is<BinaryNode>());
   2490    return match;
   2491  }
   2492 
   2493  /*
   2494   * Classes require two definitions: The first "outer" binding binds the
   2495   * class into the scope in which it was declared. the outer binding is a
   2496   * mutable lexial binding. The second "inner" binding binds the class by
   2497   * name inside a block in which the methods are evaulated. It is immutable,
   2498   * giving the methods access to the static members of the class even if
   2499   * the outer binding has been overwritten.
   2500   */
   2501  NameNode* outerBinding() const {
   2502    if (ParseNode* binding = left()) {
   2503      return &binding->as<NameNode>();
   2504    }
   2505    return nullptr;
   2506  }
   2507 
   2508  NameNode* innerBinding() const { return &right()->as<NameNode>(); }
   2509 };
   2510 
   2511 class ClassNode : public TernaryNode {
   2512  using Base = TernaryNode;
   2513 
   2514 private:
   2515  LexicalScopeNode* innerScope() const {
   2516    return &kid3()->as<LexicalScopeNode>();
   2517  }
   2518 
   2519  ClassBodyScopeNode* bodyScope() const {
   2520    return &innerScope()->scopeBody()->as<ClassBodyScopeNode>();
   2521  }
   2522 
   2523 #ifdef ENABLE_DECORATORS
   2524  ListNode* decorators_;
   2525  FunctionNode* addInitializerFunction_;
   2526 #endif
   2527 
   2528 public:
   2529  ClassNode(ParseNode* names, ParseNode* heritage,
   2530            LexicalScopeNode* memberBlock,
   2531 #ifdef ENABLE_DECORATORS
   2532            ListNode* decorators, FunctionNode* addInitializerFunction,
   2533 #endif
   2534            const TokenPos& pos)
   2535      : TernaryNode(ParseNodeKind::ClassDecl, names, heritage, memberBlock, pos)
   2536 #ifdef ENABLE_DECORATORS
   2537        ,
   2538        decorators_(decorators),
   2539        addInitializerFunction_(addInitializerFunction)
   2540 #endif
   2541  {
   2542    MOZ_ASSERT(innerScope()->scopeBody()->is<ClassBodyScopeNode>());
   2543    MOZ_ASSERT_IF(names, names->is<ClassNames>());
   2544  }
   2545 
   2546  static bool test(const ParseNode& node) {
   2547    bool match = node.isKind(ParseNodeKind::ClassDecl);
   2548    MOZ_ASSERT_IF(match, node.is<TernaryNode>());
   2549    return match;
   2550  }
   2551 
   2552  ClassNames* names() const {
   2553    return kid1() ? &kid1()->as<ClassNames>() : nullptr;
   2554  }
   2555 
   2556  ParseNode* heritage() const { return kid2(); }
   2557 
   2558  ListNode* memberList() const { return bodyScope()->memberList(); }
   2559 
   2560  LexicalScopeNode* scopeBindings() const {
   2561    LexicalScopeNode* scope = innerScope();
   2562    return scope->isEmptyScope() ? nullptr : scope;
   2563  }
   2564 
   2565  ClassBodyScopeNode* bodyScopeBindings() const {
   2566    ClassBodyScopeNode* scope = bodyScope();
   2567    return scope->isEmptyScope() ? nullptr : scope;
   2568  }
   2569 #ifdef ENABLE_DECORATORS
   2570  ListNode* decorators() const { return decorators_; }
   2571 
   2572  FunctionNode* addInitializerFunction() const {
   2573    return addInitializerFunction_;
   2574  }
   2575 #  ifdef DEBUG
   2576  void dumpImpl(const ParserAtomsTable* parserAtoms, GenericPrinter& out,
   2577                int indent);
   2578 #  endif
   2579 #endif
   2580 };
   2581 
   2582 #ifdef DEBUG
   2583 void DumpParseTree(ParserBase* parser, ParseNode* pn, GenericPrinter& out,
   2584                   int indent = 0);
   2585 #endif
   2586 
   2587 class ParseNodeAllocator {
   2588 public:
   2589  explicit ParseNodeAllocator(FrontendContext* fc, LifoAlloc& alloc)
   2590      : fc(fc), alloc(alloc) {}
   2591 
   2592  void* allocNode(size_t size);
   2593 
   2594 private:
   2595  FrontendContext* fc;
   2596  LifoAlloc& alloc;
   2597 };
   2598 
   2599 inline bool ParseNode::isConstant() {
   2600  switch (pn_type) {
   2601    case ParseNodeKind::NumberExpr:
   2602    case ParseNodeKind::StringExpr:
   2603    case ParseNodeKind::TemplateStringExpr:
   2604    case ParseNodeKind::NullExpr:
   2605    case ParseNodeKind::RawUndefinedExpr:
   2606    case ParseNodeKind::FalseExpr:
   2607    case ParseNodeKind::TrueExpr:
   2608      return true;
   2609    case ParseNodeKind::ArrayExpr:
   2610    case ParseNodeKind::ObjectExpr:
   2611      return !as<ListNode>().hasNonConstInitializer();
   2612    default:
   2613      return false;
   2614  }
   2615 }
   2616 
   2617 inline bool ParseNode::isUndefinedLiteral() {
   2618  switch (pn_type) {
   2619    case ParseNodeKind::Name: {
   2620      return as<NameNode>().name() ==
   2621             TaggedParserAtomIndex::WellKnown::undefined();
   2622    }
   2623    default: {
   2624      return false;
   2625    }
   2626  }
   2627 }
   2628 
   2629 bool IsAnonymousFunctionDefinition(ParseNode* pn);
   2630 
   2631 } /* namespace frontend */
   2632 } /* namespace js */
   2633 
   2634 #endif /* frontend_ParseNode_h */