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