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/. */
7 #ifndef frontend_ParseNode_h
8 #define frontend_ParseNode_h
10 #include "mozilla/Assertions.h"
16 #include "jstypes.h" // js::Bit
18 #include "frontend/FunctionSyntaxKind.h" // FunctionSyntaxKind
19 #include "frontend/NameAnalysisTypes.h" // PrivateNameKind
20 #include "frontend/ParserAtom.h" // TaggedParserAtomIndex
21 #include "frontend/Stencil.h" // BigIntStencil
22 #include "frontend/Token.h"
23 #include "js/TypeDecls.h"
24 #include "vm/Opcodes.h"
26 #include "vm/ScopeKind.h"
28 // [SMDOC] ParseNode tree lifetime information
30 // - All the `ParseNode` instances MUST BE explicitly allocated in the context's
31 // `LifoAlloc`. This is typically implemented by the `FullParseHandler` or it
32 // can be reimplemented with a custom `new_`.
34 // - The tree is bulk-deallocated when the parser is deallocated. Consequently,
35 // references to a subtree MUST NOT exist once the parser has been
38 // - This bulk-deallocation DOES NOT run destructors.
40 // - Instances of `LexicalScope::ParserData` and `ClassBodyScope::ParserData`
41 // MUST BE allocated as instances of `ParseNode`, in the same `LifoAlloc`.
42 // They are bulk-deallocated alongside the rest of the tree.
48 class JS_PUBLIC_API GenericPrinter
;
54 class ParserAtomsTable
;
57 struct ExtensibleCompilationStencil
;
58 class ParserSharedBase
;
59 class FullParseHandler
;
63 #define FOR_EACH_PARSE_NODE_KIND(F) \
64 F(EmptyStmt, NullaryNode) \
65 F(ExpressionStmt, UnaryNode) \
66 F(CommaExpr, ListNode) \
67 F(ConditionalExpr, ConditionalExpression) \
68 F(PropertyDefinition, PropertyDefinition) \
69 F(Shorthand, BinaryNode) \
70 F(PosExpr, UnaryNode) \
71 F(NegExpr, UnaryNode) \
72 F(PreIncrementExpr, UnaryNode) \
73 F(PostIncrementExpr, UnaryNode) \
74 F(PreDecrementExpr, UnaryNode) \
75 F(PostDecrementExpr, UnaryNode) \
76 F(PropertyNameExpr, NameNode) \
77 F(DotExpr, PropertyAccess) \
78 F(ElemExpr, PropertyByValue) \
79 F(PrivateMemberExpr, PrivateMemberAccess) \
80 F(OptionalDotExpr, OptionalPropertyAccess) \
81 F(OptionalChain, UnaryNode) \
82 F(OptionalElemExpr, OptionalPropertyByValue) \
83 F(OptionalPrivateMemberExpr, OptionalPrivateMemberAccess) \
84 F(OptionalCallExpr, CallNode) \
85 F(ArrayExpr, ListNode) \
86 F(Elision, NullaryNode) \
87 F(StatementList, ListNode) \
88 F(LabelStmt, LabeledStatement) \
89 F(ObjectExpr, ListNode) \
90 F(CallExpr, CallNode) \
91 F(Arguments, ListNode) \
93 F(ObjectPropertyName, NameNode) \
94 F(PrivateName, NameNode) \
95 F(ComputedName, UnaryNode) \
96 F(NumberExpr, NumericLiteral) \
97 F(BigIntExpr, BigIntLiteral) \
98 F(StringExpr, NameNode) \
99 F(TemplateStringListExpr, ListNode) \
100 F(TemplateStringExpr, NameNode) \
101 F(TaggedTemplateExpr, CallNode) \
102 F(CallSiteObj, CallSiteNode) \
103 F(RegExpExpr, RegExpLiteral) \
104 F(TrueExpr, BooleanLiteral) \
105 F(FalseExpr, BooleanLiteral) \
106 F(NullExpr, NullLiteral) \
107 F(RawUndefinedExpr, RawUndefinedLiteral) \
108 F(ThisExpr, UnaryNode) \
109 IF_RECORD_TUPLE(F(RecordExpr, ListNode)) \
110 IF_RECORD_TUPLE(F(TupleExpr, ListNode)) \
111 F(Function, FunctionNode) \
112 F(Module, ModuleNode) \
113 F(IfStmt, TernaryNode) \
114 F(SwitchStmt, SwitchStatement) \
115 F(Case, CaseClause) \
116 F(WhileStmt, BinaryNode) \
117 F(DoWhileStmt, BinaryNode) \
118 F(ForStmt, ForNode) \
119 F(BreakStmt, BreakStatement) \
120 F(ContinueStmt, ContinueStatement) \
121 F(VarStmt, DeclarationListNode) \
122 F(ConstDecl, DeclarationListNode) \
123 F(WithStmt, BinaryNode) \
124 F(ReturnStmt, UnaryNode) \
125 F(NewExpr, CallNode) \
126 IF_DECORATORS(F(DecoratorList, ListNode)) \
127 /* Delete operations. These must be sequential. */ \
128 F(DeleteNameExpr, UnaryNode) \
129 F(DeletePropExpr, UnaryNode) \
130 F(DeleteElemExpr, UnaryNode) \
131 F(DeleteOptionalChainExpr, UnaryNode) \
132 F(DeleteExpr, UnaryNode) \
133 F(TryStmt, TernaryNode) \
134 F(Catch, BinaryNode) \
135 F(ThrowStmt, UnaryNode) \
136 F(DebuggerStmt, DebuggerStatement) \
137 F(Generator, NullaryNode) \
138 F(InitialYield, UnaryNode) \
139 F(YieldExpr, UnaryNode) \
140 F(YieldStarExpr, UnaryNode) \
141 F(LexicalScope, LexicalScopeNode) \
142 F(LetDecl, DeclarationListNode) \
143 F(ImportDecl, BinaryNode) \
144 F(ImportSpecList, ListNode) \
145 F(ImportSpec, BinaryNode) \
146 F(ImportNamespaceSpec, UnaryNode) \
147 F(ImportAssertionList, ListNode) \
148 F(ImportAssertion, BinaryNode) \
149 F(ImportModuleRequest, BinaryNode) \
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, ParamsBodyNode) \
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, NewTargetNode) \
172 F(PosHolder, NullaryNode) \
173 F(SuperBase, UnaryNode) \
174 F(SuperCallExpr, CallNode) \
175 F(SetThis, BinaryNode) \
176 F(ImportMetaExpr, BinaryNode) \
177 F(CallImportExpr, BinaryNode) \
178 F(CallImportSpec, BinaryNode) \
179 F(InitExpr, BinaryNode) \
181 /* Unary operators. */ \
182 F(TypeOfNameExpr, UnaryNode) \
183 F(TypeOfExpr, UnaryNode) \
184 F(VoidExpr, UnaryNode) \
185 F(NotExpr, UnaryNode) \
186 F(BitNotExpr, UnaryNode) \
187 F(AwaitExpr, UnaryNode) \
190 * Binary operators. \
191 * This list must be kept in the same order in several places: \
192 * - The binary operators in ParseNode.h \
193 * - the binary operators in TokenKind.h \
194 * - the precedence list in Parser.cpp \
195 * - the JSOp code list in BytecodeEmitter.cpp \
197 F(CoalesceExpr, ListNode) \
198 F(OrExpr, ListNode) \
199 F(AndExpr, ListNode) \
200 F(BitOrExpr, ListNode) \
201 F(BitXorExpr, ListNode) \
202 F(BitAndExpr, ListNode) \
203 F(StrictEqExpr, ListNode) \
204 F(EqExpr, ListNode) \
205 F(StrictNeExpr, ListNode) \
206 F(NeExpr, ListNode) \
207 F(LtExpr, ListNode) \
208 F(LeExpr, ListNode) \
209 F(GtExpr, ListNode) \
210 F(GeExpr, ListNode) \
211 F(InstanceOfExpr, ListNode) \
212 F(InExpr, ListNode) \
213 F(PrivateInExpr, ListNode) \
214 F(LshExpr, ListNode) \
215 F(RshExpr, ListNode) \
216 F(UrshExpr, ListNode) \
217 F(AddExpr, ListNode) \
218 F(SubExpr, ListNode) \
219 F(MulExpr, ListNode) \
220 F(DivExpr, ListNode) \
221 F(ModExpr, ListNode) \
222 F(PowExpr, ListNode) \
224 /* Assignment operators (= += -= etc.). */ \
225 /* AssignmentNode::test assumes all these are consecutive. */ \
226 F(AssignExpr, AssignmentNode) \
227 F(AddAssignExpr, AssignmentNode) \
228 F(SubAssignExpr, AssignmentNode) \
229 F(CoalesceAssignExpr, AssignmentNode) \
230 F(OrAssignExpr, AssignmentNode) \
231 F(AndAssignExpr, AssignmentNode) \
232 F(BitOrAssignExpr, AssignmentNode) \
233 F(BitXorAssignExpr, AssignmentNode) \
234 F(BitAndAssignExpr, AssignmentNode) \
235 F(LshAssignExpr, AssignmentNode) \
236 F(RshAssignExpr, AssignmentNode) \
237 F(UrshAssignExpr, AssignmentNode) \
238 F(MulAssignExpr, AssignmentNode) \
239 F(DivAssignExpr, AssignmentNode) \
240 F(ModAssignExpr, AssignmentNode) \
241 F(PowAssignExpr, AssignmentNode)
244 * Parsing builds a tree of nodes that directs code generation. This tree is
245 * not a concrete syntax tree in all respects (for example, || and && are left
246 * associative, but (A && B && C) translates into the right-associated tree
247 * <A && <B && C>> so that code generation can emit a left-associative branch
248 * around <B && C> when A is false). Nodes are labeled by kind.
250 * The long comment after this enum block describes the kinds in detail.
252 enum class ParseNodeKind
: uint16_t {
253 // These constants start at 1001, the better to catch
255 #define EMIT_ENUM(name, _type) name,
256 FOR_EACH_PARSE_NODE_KIND(EMIT_ENUM
)
259 Start
= LastUnused
+ 1,
260 BinOpFirst
= ParseNodeKind::CoalesceExpr
,
261 BinOpLast
= ParseNodeKind::PowExpr
,
262 AssignmentStart
= ParseNodeKind::AssignExpr
,
263 AssignmentLast
= ParseNodeKind::PowAssignExpr
,
266 inline bool IsDeleteKind(ParseNodeKind kind
) {
267 return ParseNodeKind::DeleteNameExpr
<= kind
&&
268 kind
<= ParseNodeKind::DeleteExpr
;
271 inline bool IsTypeofKind(ParseNodeKind kind
) {
272 return ParseNodeKind::TypeOfNameExpr
<= kind
&&
273 kind
<= ParseNodeKind::TypeOfExpr
;
278 * Function (FunctionNode)
279 * funbox: ptr to js::FunctionBox
280 * body: ParamsBody or null for lazily-parsed function
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
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
293 * count: number of formal parameters + 1
295 * kid: expression being spread
296 * ClassDecl (ClassNode)
297 * kid1: ClassNames for class name. can be null for anonymous class.
298 * kid2: expression after `extends`. null if no expression
300 * * ClassMemberList, if anonymous class
301 * * LexicalScopeNode which contains ClassMemberList as scopeBody,
303 * ClassNames (ClassNames)
304 * left: Name node for outer binding, or null if the class is an expression
305 * that doesn't create an outer binding
306 * right: Name node for inner binding
307 * ClassMemberList (ListNode)
308 * head: list of N ClassMethod, ClassField or StaticClassBlock nodes
310 * DefaultConstructor (ClassMethod)
312 * method: methodDefinition
313 * ClassMethod (ClassMethod)
315 * method: methodDefinition
316 * initializerIfPrivate: initializer to stamp private method onto instance
317 * Module (ModuleNode)
318 * body: statement list of the module
321 * StatementList (ListNode)
322 * head: list of N statements
324 * IfStmt (TernaryNode)
328 * SwitchStmt (SwitchStatement)
330 * right: LexicalScope node that contains the list of Case nodes, with at
331 * most one default node.
332 * hasDefault: true if there's a default case
334 * left: case-expression if CaseClause, or null if DefaultClause
335 * right: StatementList node for this case's statements
336 * WhileStmt (BinaryNode)
339 * DoWhileStmt (BinaryNode)
344 * * ForIn: for (x in y) ...
345 * * ForOf: for (x of x) ...
346 * * ForHead: for (;;) ...
348 * ForIn (TernaryNode)
349 * kid1: declaration or expression to left of 'in'
351 * kid3: object expr to right of 'in'
352 * ForOf (TernaryNode)
353 * kid1: declaration or expression to left of 'of'
355 * kid3: expr to right of 'of'
356 * ForHead (TernaryNode)
357 * kid1: init expr before first ';' or nullptr
358 * kid2: cond expr before second ';' or nullptr
359 * kid3: update expr after second ';' or nullptr
360 * ThrowStmt (UnaryNode)
361 * kid: thrown exception
362 * TryStmt (TernaryNode)
364 * kid2: null or LexicalScope for catch-block with scopeBody pointing to a
366 * kid3: null or finally block
368 * left: Name, Array, or Object catch var node
369 * (Array or Object if destructuring),
370 * or null if optional catch binding
371 * right: catch block statements
372 * BreakStmt (BreakStatement)
373 * label: label or null
374 * ContinueStmt (ContinueStatement)
375 * label: label or null
376 * WithStmt (BinaryNode)
379 * VarStmt, LetDecl, ConstDecl (DeclarationListNode)
380 * head: list of N Name or AssignExpr nodes
381 * each name node has either
382 * atom: variable name
383 * expr: initializer or null
385 * atom: variable name
386 * each assignment node has
390 * ReturnStmt (UnaryNode)
391 * kid: returned expression, or null if none
392 * ExpressionStmt (UnaryNode)
394 * EmptyStmt (NullaryNode)
396 * LabelStmt (LabeledStatement)
398 * expr: labeled statement
399 * ImportDecl (BinaryNode)
400 * left: ImportSpecList import specifiers
401 * right: String module specifier
402 * ImportSpecList (ListNode)
403 * head: list of N ImportSpec nodes
404 * count: N >= 0 (N = 0 for `import {} from ...`)
405 * ImportSpec (BinaryNode)
407 * right: local binding name
408 * ImportNamespaceSpec (UnaryNode)
409 * kid: local binding name
410 * ExportStmt (UnaryNode)
411 * kid: declaration expression
412 * ExportFromStmt (BinaryNode)
413 * left: ExportSpecList export specifiers
414 * right: String module specifier
415 * ExportSpecList (ListNode)
416 * head: list of N ExportSpec nodes
417 * count: N >= 0 (N = 0 for `export {}`)
418 * ExportSpec (BinaryNode)
419 * left: local binding name
421 * ExportNamespaceSpec (UnaryNode)
423 * ExportDefaultStmt (BinaryNode)
424 * left: export default declaration or expression
425 * right: Name node for assignment
428 * The `Expr` suffix is used for nodes that can appear anywhere an expression
429 * could appear. It is not used on a few weird kinds like Arguments and
430 * CallSiteObj that are always the child node of an expression node, but which
433 * All left-associated binary trees of the same type are optimized into lists
434 * to avoid recursion when processing expression chains.
436 * CommaExpr (ListNode)
437 * head: list of N comma-separated exprs
439 * AssignExpr (BinaryNode)
440 * left: target of assignment
441 * right: value to assign
442 * AddAssignExpr, SubAssignExpr, CoalesceAssignExpr, OrAssignExpr,
443 * AndAssignExpr, BitOrAssignExpr, BitXorAssignExpr, BitAndAssignExpr,
444 * LshAssignExpr, RshAssignExpr, UrshAssignExpr, MulAssignExpr, DivAssignExpr,
445 * ModAssignExpr, PowAssignExpr (AssignmentNode)
446 * left: target of assignment
447 * right: value to assign
448 * ConditionalExpr (ConditionalExpression)
449 * (cond ? thenExpr : elseExpr)
453 * CoalesceExpr, OrExpr, AndExpr, BitOrExpr, BitXorExpr,
454 * BitAndExpr, StrictEqExpr, EqExpr, StrictNeExpr, NeExpr, LtExpr, LeExpr,
455 * GtExpr, GeExpr, InstanceOfExpr, InExpr, LshExpr, RshExpr, UrshExpr, AddExpr,
456 * SubExpr, MulExpr, DivExpr, ModExpr, PowExpr (ListNode)
457 * head: list of N subexpressions
458 * All of these operators are left-associative except Pow which is
459 * right-associative, but still forms a list (see comments in
460 * ParseNode::appendOrCreateList).
462 * PosExpr, NegExpr, VoidExpr, NotExpr, BitNotExpr, TypeOfNameExpr,
463 * TypeOfExpr (UnaryNode)
465 * PreIncrementExpr, PostIncrementExpr, PreDecrementExpr,
466 * PostDecrementExpr (UnaryNode)
468 * NewExpr (BinaryNode)
469 * left: ctor expression on the left of the '('
471 * DecoratorList (ListNode)
472 * head: list of N nodes, each item is one of:
473 * * NameNode (DecoratorMemberExpression)
474 * * CallNode (DecoratorCallExpression)
475 * * Node (DecoratorParenthesizedExpression)
477 * DeleteNameExpr, DeletePropExpr, DeleteElemExpr, DeleteExpr (UnaryNode)
478 * kid: expression that's evaluated, then the overall delete evaluates to
479 * true; can't be a kind for a more-specific ParseNodeKind::Delete*
480 * unless constant folding (or a similar parse tree manipulation) has
482 * * DeleteNameExpr: Name expr
483 * * DeletePropExpr: Dot expr
484 * * DeleteElemExpr: Elem expr
485 * * DeleteOptionalChainExpr: Member expr
486 * * DeleteExpr: Member expr
487 * DeleteOptionalChainExpr (UnaryNode)
488 * kid: expression that's evaluated, then the overall delete evaluates to
489 * true; If constant folding occurs, Elem expr may become Dot expr.
490 * OptionalElemExpr does not get folded into OptionalDot.
491 * OptionalChain (UnaryNode)
492 * kid: expression that is evaluated as a chain. An Optional chain contains
493 * one or more optional nodes. It's first node (kid) is always an
494 * optional node, for example: an OptionalElemExpr, OptionalDotExpr, or
495 * OptionalCall. An OptionalChain will shortcircuit and return
496 * Undefined without evaluating the rest of the expression if any of the
497 * optional nodes it contains are nullish. An optionalChain also can
498 * contain nodes such as DotExpr, ElemExpr, NameExpr CallExpr, etc.
499 * These are evaluated normally.
500 * * OptionalDotExpr: Dot expr with jump
501 * * OptionalElemExpr: Elem expr with jump
502 * * OptionalCallExpr: Call expr with jump
503 * * DotExpr: Dot expr without jump
504 * * ElemExpr: Elem expr without jump
505 * * CallExpr: Call expr without jump
506 * PropertyNameExpr (NameNode)
507 * atom: property name being accessed
508 * privateNameKind: kind of the name if private
509 * DotExpr (PropertyAccess)
510 * left: Member expr to left of '.'
511 * right: PropertyName to right of '.'
512 * OptionalDotExpr (OptionalPropertyAccess)
513 * left: Member expr to left of '.', short circuits back to OptionalChain
515 * right: PropertyName to right of '.'
516 * ElemExpr (PropertyByValue)
517 * left: Member expr to left of '['
518 * right: expr between '[' and ']'
519 * OptionalElemExpr (OptionalPropertyByValue)
520 * left: Member expr to left of '[', short circuits back to OptionalChain
522 * right: expr between '[' and ']'
523 * CallExpr (BinaryNode)
524 * left: callee expression on the left of the '('
526 * OptionalCallExpr (BinaryNode)
527 * left: callee expression on the left of the '(', short circuits back to
528 * OptionalChain if nullish.
530 * Arguments (ListNode)
531 * head: list of arg1, arg2, ... argN
533 * ArrayExpr (ListNode)
534 * head: list of N array element expressions
535 * holes ([,,]) are represented by Elision nodes,
536 * spread elements ([...X]) are represented by Spread nodes
538 * ObjectExpr (ListNode)
539 * head: list of N nodes, each item is one of:
541 * * PropertyDefinition
545 * PropertyDefinition (PropertyDefinition)
546 * key-value pair in object initializer or destructuring lhs
549 * Shorthand (BinaryNode)
550 * Same fields as PropertyDefinition. This is used for object literal
551 * properties using shorthand ({x}).
552 * ComputedName (UnaryNode)
553 * ES6 ComputedPropertyName.
554 * kid: the AssignmentExpression inside the square brackets
556 * atom: name, or object atom
557 * StringExpr (NameNode)
559 * TemplateStringListExpr (ListNode)
560 * head: list of alternating expr and template strings
561 * TemplateString [, expression, TemplateString]+
562 * there's at least one expression. If the template literal contains
563 * no ${}-delimited expression, it's parsed as a single TemplateString
564 * TemplateStringExpr (NameNode)
565 * atom: template string atom
566 * TaggedTemplateExpr (BinaryNode)
567 * left: tag expression
568 * right: Arguments, with the first being the call site object, then
569 * arg1, arg2, ... argN
570 * CallSiteObj (CallSiteNode)
571 * head: an Array of raw TemplateString, then corresponding cooked
572 * TemplateString nodes
573 * Array [, cooked TemplateString]+
575 * [raw TemplateString]+
576 * RegExpExpr (RegExpLiteral)
577 * regexp: RegExp model object
578 * NumberExpr (NumericLiteral)
579 * value: double value of numeric literal
580 * BigIntExpr (BigIntLiteral)
581 * stencil: script compilation struct that has |bigIntData| vector
582 * index: index into the script compilation's |bigIntData| vector
583 * TrueExpr, FalseExpr (BooleanLiteral)
584 * NullExpr (NullLiteral)
585 * RawUndefinedExpr (RawUndefinedLiteral)
587 * ThisExpr (UnaryNode)
588 * kid: '.this' Name if function `this`, else nullptr
589 * SuperBase (UnaryNode)
591 * SuperCallExpr (BinaryNode)
594 * SetThis (BinaryNode)
598 * LexicalScope (LexicalScopeNode)
599 * scopeBindings: scope bindings
600 * scopeBody: scope body
601 * Generator (NullaryNode)
602 * InitialYield (UnaryNode)
603 * kid: generator object
604 * YieldExpr, YieldStarExpr, AwaitExpr (UnaryNode)
608 #define FOR_EACH_PARSENODE_SUBCLASS(MACRO) \
610 MACRO(AssignmentNode) \
614 MACRO(StaticClassBlock) \
615 MACRO(PropertyDefinition) \
618 MACRO(PropertyAccess) \
619 MACRO(OptionalPropertyAccess) \
620 MACRO(PropertyByValue) \
621 MACRO(OptionalPropertyByValue) \
622 MACRO(PrivateMemberAccess) \
623 MACRO(OptionalPrivateMemberAccess) \
624 MACRO(NewTargetNode) \
625 MACRO(SwitchStatement) \
626 MACRO(DeclarationListNode) \
628 MACRO(ParamsBodyNode) \
629 MACRO(FunctionNode) \
632 MACRO(LexicalScopeNode) \
633 MACRO(ClassBodyScopeNode) \
636 MACRO(CallSiteNode) \
639 MACRO(LoopControlStatement) \
640 MACRO(BreakStatement) \
641 MACRO(ContinueStatement) \
644 MACRO(LabeledStatement) \
647 MACRO(BooleanLiteral) \
648 MACRO(DebuggerStatement) \
650 MACRO(RawUndefinedLiteral) \
652 MACRO(NumericLiteral) \
653 MACRO(BigIntLiteral) \
655 MACRO(RegExpLiteral) \
659 MACRO(ConditionalExpression) \
665 #define DECLARE_CLASS(typeName) class typeName;
666 FOR_EACH_PARSENODE_SUBCLASS(DECLARE_CLASS
)
669 enum class AccessorType
{ None
, Getter
, Setter
};
671 static inline bool IsConstructorKind(FunctionSyntaxKind kind
) {
672 return kind
== FunctionSyntaxKind::ClassConstructor
||
673 kind
== FunctionSyntaxKind::DerivedClassConstructor
;
676 static inline bool IsMethodDefinitionKind(FunctionSyntaxKind kind
) {
677 return IsConstructorKind(kind
) || kind
== FunctionSyntaxKind::Method
||
678 kind
== FunctionSyntaxKind::FieldInitializer
||
679 kind
== FunctionSyntaxKind::Getter
||
680 kind
== FunctionSyntaxKind::Setter
;
683 // To help diagnose sporadic crashes in the frontend, a few assertions are
684 // enabled in early beta builds. (Most are not; those still use MOZ_ASSERT.)
686 #if defined(EARLY_BETA_OR_EARLIER)
687 # define JS_PARSE_NODE_ASSERT MOZ_RELEASE_ASSERT
689 # define JS_PARSE_NODE_ASSERT MOZ_ASSERT
693 struct ParseNodeError
{};
694 using ParseNodeResult
= mozilla::Result
<ParseNode
*, ParseNodeError
>;
697 const ParseNodeKind pn_type
;
699 bool pn_parens
: 1; /* this expr was enclosed in parens */
700 bool pn_rhs_anon_fun
: 1; /* this expr is anonymous function or class that
701 * is a direct RHS of ParseNodeKind::Assign or
702 * ParseNodeKind::PropertyDefinition of property,
703 * that needs SetFunctionName. */
706 // Used by ComputedName to indicate if the ComputedName is a
707 // a synthetic construct. This allows us to avoid needing to
708 // compute ToString on uncommon property values such as BigInt.
709 // Instead we parse as though they were computed names.
711 // We need this bit to distinguish a synthetic computed name like
712 // this however to undo this transformation in Reflect.parse and
714 bool pn_synthetic_computed
: 1;
716 ParseNode(const ParseNode
& other
) = delete;
717 void operator=(const ParseNode
& other
) = delete;
720 explicit ParseNode(ParseNodeKind kind
)
723 pn_rhs_anon_fun(false),
724 pn_synthetic_computed(false),
727 JS_PARSE_NODE_ASSERT(ParseNodeKind::Start
<= kind
);
728 JS_PARSE_NODE_ASSERT(kind
< ParseNodeKind::Limit
);
731 ParseNode(ParseNodeKind kind
, const TokenPos
& pos
)
734 pn_rhs_anon_fun(false),
735 pn_synthetic_computed(false),
738 JS_PARSE_NODE_ASSERT(ParseNodeKind::Start
<= kind
);
739 JS_PARSE_NODE_ASSERT(kind
< ParseNodeKind::Limit
);
742 ParseNodeKind
getKind() const {
743 JS_PARSE_NODE_ASSERT(ParseNodeKind::Start
<= pn_type
);
744 JS_PARSE_NODE_ASSERT(pn_type
< ParseNodeKind::Limit
);
747 bool isKind(ParseNodeKind kind
) const { return getKind() == kind
; }
750 size_t getKindAsIndex() const {
751 return size_t(getKind()) - size_t(ParseNodeKind::Start
);
754 // Used to implement test() on a few ParseNodes efficiently.
755 // (This enum doesn't fully reflect the ParseNode class hierarchy,
756 // so don't use it for anything else.)
757 enum class TypeCode
: uint8_t {
767 // typeCodeTable[getKindAsIndex()] is the type code of a ParseNode of kind
769 static const TypeCode typeCodeTable
[];
773 static const size_t sizeTable
[];
777 TypeCode
typeCode() const { return typeCodeTable
[getKindAsIndex()]; }
779 bool isBinaryOperation() const {
780 ParseNodeKind kind
= getKind();
781 return ParseNodeKind::BinOpFirst
<= kind
&&
782 kind
<= ParseNodeKind::BinOpLast
;
784 inline bool isName(TaggedParserAtomIndex name
) const;
786 /* Boolean attributes. */
787 bool isInParens() const { return pn_parens
; }
788 bool isLikelyIIFE() const { return isInParens(); }
789 void setInParens(bool enabled
) { pn_parens
= enabled
; }
791 bool isDirectRHSAnonFunction() const { return pn_rhs_anon_fun
; }
792 void setDirectRHSAnonFunction(bool enabled
) { pn_rhs_anon_fun
= enabled
; }
794 TokenPos pn_pos
; /* two 16-bit pairs here, for 64 bits */
795 ParseNode
* pn_next
; /* intrinsic link in parent ListNode */
799 * If |left| is a list of the given kind/left-associative op, append
800 * |right| to it and return |left|. Otherwise return a [left, right] list.
802 static ParseNodeResult
appendOrCreateList(ParseNodeKind kind
, ParseNode
* left
,
804 FullParseHandler
* handler
,
807 /* True if pn is a parsenode representing a literal constant. */
808 bool isLiteral() const {
809 return isKind(ParseNodeKind::NumberExpr
) ||
810 isKind(ParseNodeKind::BigIntExpr
) ||
811 isKind(ParseNodeKind::StringExpr
) ||
812 isKind(ParseNodeKind::TrueExpr
) ||
813 isKind(ParseNodeKind::FalseExpr
) ||
814 isKind(ParseNodeKind::NullExpr
) ||
815 isKind(ParseNodeKind::RawUndefinedExpr
);
818 inline bool isConstant();
820 template <class NodeType
>
821 inline bool is() const {
822 return NodeType::test(*this);
825 /* Casting operations. */
826 template <class NodeType
>
827 inline NodeType
& as() {
828 MOZ_ASSERT(NodeType::test(*this));
829 return *static_cast<NodeType
*>(this);
832 template <class NodeType
>
833 inline const NodeType
& as() const {
834 MOZ_ASSERT(NodeType::test(*this));
835 return *static_cast<const NodeType
*>(this);
839 // Debugger-friendly stderr printer.
841 void dump(const ParserAtomsTable
* parserAtoms
);
842 void dump(const ParserAtomsTable
* parserAtoms
, GenericPrinter
& out
);
843 void dump(const ParserAtomsTable
* parserAtoms
, GenericPrinter
& out
,
846 // The size of this node, in bytes.
847 size_t size() const { return sizeTable
[getKindAsIndex()]; }
851 // Remove a ParseNode, **pnp, from a parse tree, putting another ParseNode,
852 // *pn, in its place.
854 // pnp points to a ParseNode pointer. This must be the only pointer that points
855 // to the parse node being replaced. The replacement, *pn, is unchanged except
856 // for its pn_next pointer; updating that is necessary if *pn's new parent is a
858 inline void ReplaceNode(ParseNode
** pnp
, ParseNode
* pn
) {
859 pn
->pn_next
= (*pnp
)->pn_next
;
863 class NullaryNode
: public ParseNode
{
865 NullaryNode(ParseNodeKind kind
, const TokenPos
& pos
) : ParseNode(kind
, pos
) {
866 MOZ_ASSERT(is
<NullaryNode
>());
869 static bool test(const ParseNode
& node
) {
870 return node
.typeCode() == TypeCode::Nullary
;
873 static constexpr TypeCode
classTypeCode() { return TypeCode::Nullary
; }
875 template <typename Visitor
>
876 bool accept(Visitor
& visitor
) {
881 void dumpImpl(const ParserAtomsTable
* parserAtoms
, GenericPrinter
& out
,
886 class NameNode
: public ParseNode
{
887 TaggedParserAtomIndex atom_
; /* lexical name or label atom */
888 PrivateNameKind privateNameKind_
= PrivateNameKind::None
;
891 NameNode(ParseNodeKind kind
, TaggedParserAtomIndex atom
, const TokenPos
& pos
)
892 : ParseNode(kind
, pos
), atom_(atom
) {
894 MOZ_ASSERT(is
<NameNode
>());
897 static bool test(const ParseNode
& node
) {
898 return node
.typeCode() == TypeCode::Name
;
901 static constexpr TypeCode
classTypeCode() { return TypeCode::Name
; }
903 template <typename Visitor
>
904 bool accept(Visitor
& visitor
) {
909 void dumpImpl(const ParserAtomsTable
* parserAtoms
, GenericPrinter
& out
,
913 TaggedParserAtomIndex
atom() const { return atom_
; }
915 TaggedParserAtomIndex
name() const {
916 MOZ_ASSERT(isKind(ParseNodeKind::Name
) ||
917 isKind(ParseNodeKind::PrivateName
));
921 void setAtom(TaggedParserAtomIndex atom
) { atom_
= atom
; }
923 void setPrivateNameKind(PrivateNameKind privateNameKind
) {
924 privateNameKind_
= privateNameKind
;
927 PrivateNameKind
privateNameKind() { return privateNameKind_
; }
930 inline bool ParseNode::isName(TaggedParserAtomIndex name
) const {
931 return getKind() == ParseNodeKind::Name
&& as
<NameNode
>().name() == name
;
934 class UnaryNode
: public ParseNode
{
938 UnaryNode(ParseNodeKind kind
, const TokenPos
& pos
, ParseNode
* kid
)
939 : ParseNode(kind
, pos
), kid_(kid
) {
940 MOZ_ASSERT(is
<UnaryNode
>());
943 static bool test(const ParseNode
& node
) {
944 return node
.typeCode() == TypeCode::Unary
;
947 static constexpr TypeCode
classTypeCode() { return TypeCode::Unary
; }
949 template <typename Visitor
>
950 bool accept(Visitor
& visitor
) {
952 if (!visitor
.visit(kid_
)) {
960 void dumpImpl(const ParserAtomsTable
* parserAtoms
, GenericPrinter
& out
,
964 ParseNode
* kid() const { return kid_
; }
967 * Non-null if this is a statement node which could be a member of a
968 * Directive Prologue: an expression statement consisting of a single
971 * This considers only the node and its children, not its context. After
972 * parsing, check the node's prologue flag to see if it is indeed part of
973 * a directive prologue.
975 * Note that a Directive Prologue can contain statements that cannot
976 * themselves be directives (string literals that include escape sequences
977 * or escaped newlines, say). This member function returns true for such
978 * nodes; we use it to determine the extent of the prologue.
980 TaggedParserAtomIndex
isStringExprStatement() const {
981 if (isKind(ParseNodeKind::ExpressionStmt
)) {
982 if (kid()->isKind(ParseNodeKind::StringExpr
) && !kid()->isInParens()) {
983 return kid()->as
<NameNode
>().atom();
986 return TaggedParserAtomIndex::null();
989 // Methods used by FoldConstants.cpp.
990 ParseNode
** unsafeKidReference() { return &kid_
; }
992 void setSyntheticComputedName() { pn_synthetic_computed
= true; }
993 bool isSyntheticComputedName() {
994 MOZ_ASSERT(isKind(ParseNodeKind::ComputedName
));
995 return pn_synthetic_computed
;
999 class BinaryNode
: public ParseNode
{
1004 BinaryNode(ParseNodeKind kind
, const TokenPos
& pos
, ParseNode
* left
,
1006 : ParseNode(kind
, pos
), left_(left
), right_(right
) {
1007 MOZ_ASSERT(is
<BinaryNode
>());
1010 BinaryNode(ParseNodeKind kind
, ParseNode
* left
, ParseNode
* right
)
1011 : ParseNode(kind
, TokenPos::box(left
->pn_pos
, right
->pn_pos
)),
1014 MOZ_ASSERT(is
<BinaryNode
>());
1017 static bool test(const ParseNode
& node
) {
1018 return node
.typeCode() == TypeCode::Binary
;
1021 static constexpr TypeCode
classTypeCode() { return TypeCode::Binary
; }
1023 template <typename Visitor
>
1024 bool accept(Visitor
& visitor
) {
1026 if (!visitor
.visit(left_
)) {
1031 if (!visitor
.visit(right_
)) {
1039 void dumpImpl(const ParserAtomsTable
* parserAtoms
, GenericPrinter
& out
,
1043 ParseNode
* left() const { return left_
; }
1045 ParseNode
* right() const { return right_
; }
1047 // Methods used by FoldConstants.cpp.
1048 // callers are responsible for keeping the list consistent.
1049 ParseNode
** unsafeLeftReference() { return &left_
; }
1051 ParseNode
** unsafeRightReference() { return &right_
; }
1054 class AssignmentNode
: public BinaryNode
{
1056 AssignmentNode(ParseNodeKind kind
, ParseNode
* left
, ParseNode
* right
)
1057 : BinaryNode(kind
, TokenPos(left
->pn_pos
.begin
, right
->pn_pos
.end
), left
,
1059 MOZ_ASSERT(is
<AssignmentNode
>());
1062 static bool test(const ParseNode
& node
) {
1063 ParseNodeKind kind
= node
.getKind();
1064 bool match
= ParseNodeKind::AssignmentStart
<= kind
&&
1065 kind
<= ParseNodeKind::AssignmentLast
;
1066 MOZ_ASSERT_IF(match
, node
.is
<BinaryNode
>());
1071 class ForNode
: public BinaryNode
{
1072 unsigned iflags_
; /* JSITER_* flags */
1075 ForNode(const TokenPos
& pos
, ParseNode
* forHead
, ParseNode
* body
,
1077 : BinaryNode(ParseNodeKind::ForStmt
, pos
, forHead
, body
),
1079 MOZ_ASSERT(forHead
->isKind(ParseNodeKind::ForIn
) ||
1080 forHead
->isKind(ParseNodeKind::ForOf
) ||
1081 forHead
->isKind(ParseNodeKind::ForHead
));
1084 static bool test(const ParseNode
& node
) {
1085 bool match
= node
.isKind(ParseNodeKind::ForStmt
);
1086 MOZ_ASSERT_IF(match
, node
.is
<BinaryNode
>());
1090 TernaryNode
* head() const { return &left()->as
<TernaryNode
>(); }
1092 ParseNode
* body() const { return right(); }
1094 unsigned iflags() const { return iflags_
; }
1097 class TernaryNode
: public ParseNode
{
1098 ParseNode
* kid1_
; /* condition, discriminant, etc. */
1099 ParseNode
* kid2_
; /* then-part, case list, etc. */
1100 ParseNode
* kid3_
; /* else-part, default case, etc. */
1103 TernaryNode(ParseNodeKind kind
, ParseNode
* kid1
, ParseNode
* kid2
,
1105 : TernaryNode(kind
, kid1
, kid2
, kid3
,
1106 TokenPos((kid1
? kid1
1115 TernaryNode(ParseNodeKind kind
, ParseNode
* kid1
, ParseNode
* kid2
,
1116 ParseNode
* kid3
, const TokenPos
& pos
)
1117 : ParseNode(kind
, pos
), kid1_(kid1
), kid2_(kid2
), kid3_(kid3
) {
1118 MOZ_ASSERT(is
<TernaryNode
>());
1121 static bool test(const ParseNode
& node
) {
1122 return node
.typeCode() == TypeCode::Ternary
;
1125 static constexpr TypeCode
classTypeCode() { return TypeCode::Ternary
; }
1127 template <typename Visitor
>
1128 bool accept(Visitor
& visitor
) {
1130 if (!visitor
.visit(kid1_
)) {
1135 if (!visitor
.visit(kid2_
)) {
1140 if (!visitor
.visit(kid3_
)) {
1148 void dumpImpl(const ParserAtomsTable
* parserAtoms
, GenericPrinter
& out
,
1152 ParseNode
* kid1() const { return kid1_
; }
1154 ParseNode
* kid2() const { return kid2_
; }
1156 ParseNode
* kid3() const { return kid3_
; }
1158 // Methods used by FoldConstants.cpp.
1159 ParseNode
** unsafeKid1Reference() { return &kid1_
; }
1161 ParseNode
** unsafeKid2Reference() { return &kid2_
; }
1163 ParseNode
** unsafeKid3Reference() { return &kid3_
; }
1166 class ListNode
: public ParseNode
{
1167 ParseNode
* head_
; /* first node in list */
1168 ParseNode
** tail_
; /* ptr to last node's pn_next in list */
1169 uint32_t count_
; /* number of nodes in list */
1175 // Statement list has top-level function statements.
1176 static constexpr uint32_t hasTopLevelFunctionDeclarationsBit
= Bit(0);
1178 // Array/Object/Class initializer has non-constants.
1179 // * array has holes
1180 // * array has spread node
1181 // * array has element which is known not to be constant
1182 // * array has no element
1183 // * object/class has __proto__
1184 // * object/class has property which is known not to be constant
1185 // * object/class shorthand property
1186 // * object/class spread property
1187 // * object/class has method
1188 // * object/class has computed property
1189 static constexpr uint32_t hasNonConstInitializerBit
= Bit(1);
1191 // Flag set by the emitter after emitting top-level function statements.
1192 static constexpr uint32_t emittedTopLevelFunctionDeclarationsBit
= Bit(2);
1195 ListNode(ParseNodeKind kind
, const TokenPos
& pos
)
1196 : ParseNode(kind
, pos
),
1201 MOZ_ASSERT(is
<ListNode
>());
1204 ListNode(ParseNodeKind kind
, ParseNode
* kid
)
1205 : ParseNode(kind
, kid
->pn_pos
),
1207 tail_(&kid
->pn_next
),
1210 if (kid
->pn_pos
.begin
< pn_pos
.begin
) {
1211 pn_pos
.begin
= kid
->pn_pos
.begin
;
1213 pn_pos
.end
= kid
->pn_pos
.end
;
1215 MOZ_ASSERT(is
<ListNode
>());
1218 static bool test(const ParseNode
& node
) {
1219 return node
.typeCode() == TypeCode::List
;
1222 static constexpr TypeCode
classTypeCode() { return TypeCode::List
; }
1224 template <typename Visitor
>
1225 bool accept(Visitor
& visitor
) {
1226 ParseNode
** listp
= &head_
;
1227 for (; *listp
; listp
= &(*listp
)->pn_next
) {
1228 // Don't use reference because we want to check if it changed, so we can
1230 ParseNode
* pn
= *listp
;
1231 if (!visitor
.visit(pn
)) {
1235 ReplaceNode(listp
, pn
);
1238 unsafeReplaceTail(listp
);
1243 void dumpImpl(const ParserAtomsTable
* parserAtoms
, GenericPrinter
& out
,
1247 ParseNode
* head() const { return head_
; }
1249 ParseNode
** tail() const { return tail_
; }
1251 uint32_t count() const { return count_
; }
1253 bool empty() const { return count() == 0; }
1255 void checkConsistency() const
1261 [[nodiscard
]] bool hasTopLevelFunctionDeclarations() const {
1262 MOZ_ASSERT(isKind(ParseNodeKind::StatementList
));
1263 return xflags
& hasTopLevelFunctionDeclarationsBit
;
1266 [[nodiscard
]] bool emittedTopLevelFunctionDeclarations() const {
1267 MOZ_ASSERT(isKind(ParseNodeKind::StatementList
));
1268 MOZ_ASSERT(hasTopLevelFunctionDeclarations());
1269 return xflags
& emittedTopLevelFunctionDeclarationsBit
;
1272 [[nodiscard
]] bool hasNonConstInitializer() const {
1273 MOZ_ASSERT(isKind(ParseNodeKind::ArrayExpr
) ||
1274 isKind(ParseNodeKind::ObjectExpr
));
1275 return xflags
& hasNonConstInitializerBit
;
1278 void setHasTopLevelFunctionDeclarations() {
1279 MOZ_ASSERT(isKind(ParseNodeKind::StatementList
));
1280 xflags
|= hasTopLevelFunctionDeclarationsBit
;
1283 void setEmittedTopLevelFunctionDeclarations() {
1284 MOZ_ASSERT(isKind(ParseNodeKind::StatementList
));
1285 MOZ_ASSERT(hasTopLevelFunctionDeclarations());
1286 xflags
|= emittedTopLevelFunctionDeclarationsBit
;
1289 void setHasNonConstInitializer() {
1290 MOZ_ASSERT(isKind(ParseNodeKind::ArrayExpr
) ||
1291 isKind(ParseNodeKind::ObjectExpr
) ||
1292 IF_RECORD_TUPLE(isKind(ParseNodeKind::TupleExpr
), false) ||
1293 IF_RECORD_TUPLE(isKind(ParseNodeKind::RecordExpr
), false));
1294 xflags
|= hasNonConstInitializerBit
;
1297 void unsetHasNonConstInitializer() {
1298 MOZ_ASSERT(isKind(ParseNodeKind::ArrayExpr
) ||
1299 isKind(ParseNodeKind::ObjectExpr
) ||
1300 IF_RECORD_TUPLE(isKind(ParseNodeKind::TupleExpr
), false) ||
1301 IF_RECORD_TUPLE(isKind(ParseNodeKind::RecordExpr
), false));
1302 xflags
&= ~hasNonConstInitializerBit
;
1306 * Compute a pointer to the last element in a singly-linked list. NB: list
1307 * must be non-empty -- this is asserted!
1309 ParseNode
* last() const {
1310 MOZ_ASSERT(!empty());
1312 // ParseNode ParseNode
1313 // +-----+---------+-----+ +-----+---------+-----+
1314 // | ... | pn_next | ... | +-...->| ... | pn_next | ... |
1315 // +-----+---------+-----+ | +-----+---------+-----+
1317 // | +---------------+ | |
1322 return (ParseNode
*)(uintptr_t(tail()) - offsetof(ParseNode
, pn_next
));
1325 void replaceLast(ParseNode
* node
) {
1326 MOZ_ASSERT(!empty());
1327 pn_pos
.end
= node
->pn_pos
.end
;
1329 ParseNode
* item
= head();
1330 ParseNode
* lastNode
= last();
1332 if (item
== lastNode
) {
1335 while (item
->pn_next
!= lastNode
) {
1336 MOZ_ASSERT(item
->pn_next
);
1337 item
= item
->pn_next
;
1339 item
->pn_next
= node
;
1341 tail_
= &node
->pn_next
;
1344 void append(ParseNode
* item
) {
1345 MOZ_ASSERT(item
->pn_pos
.begin
>= pn_pos
.begin
);
1346 pn_pos
.end
= item
->pn_pos
.end
;
1348 tail_
= &item
->pn_next
;
1352 void prepend(ParseNode
* item
) {
1353 item
->pn_next
= head_
;
1355 if (tail_
== &head_
) {
1356 tail_
= &item
->pn_next
;
1361 // Methods used by FoldConstants.cpp.
1362 // Caller is responsible for keeping the list consistent.
1363 ParseNode
** unsafeHeadReference() { return &head_
; }
1365 void unsafeReplaceTail(ParseNode
** newTail
) {
1370 void unsafeDecrementCount() {
1371 MOZ_ASSERT(count() > 1);
1376 // Classes to iterate over ListNode contents:
1380 // for (ParseNode* item : list->contents()) {
1381 // // item is ParseNode* typed.
1387 friend class ListNode
;
1388 explicit iterator(ParseNode
* node
) : node_(node
) {}
1391 // Implement std::iterator_traits.
1392 using iterator_category
= std::input_iterator_tag
;
1393 using value_type
= ParseNode
*;
1394 using difference_type
= ptrdiff_t;
1395 using pointer
= ParseNode
**;
1396 using reference
= ParseNode
*&;
1398 bool operator==(const iterator
& other
) const {
1399 return node_
== other
.node_
;
1402 bool operator!=(const iterator
& other
) const { return !(*this == other
); }
1404 iterator
& operator++() {
1405 node_
= node_
->pn_next
;
1409 ParseNode
* operator*() { return node_
; }
1411 const ParseNode
* operator*() const { return node_
; }
1419 friend class ListNode
;
1420 range(ParseNode
* begin
, ParseNode
* end
) : begin_(begin
), end_(end
) {}
1423 iterator
begin() { return iterator(begin_
); }
1425 iterator
end() { return iterator(end_
); }
1427 const iterator
begin() const { return iterator(begin_
); }
1429 const iterator
end() const { return iterator(end_
); }
1431 const iterator
cbegin() const { return begin(); }
1433 const iterator
cend() const { return end(); }
1437 [[nodiscard
]] bool contains(ParseNode
* target
) const {
1439 for (ParseNode
* node
: contents()) {
1440 if (target
== node
) {
1449 range
contents() { return range(head(), nullptr); }
1451 const range
contents() const { return range(head(), nullptr); }
1453 range
contentsFrom(ParseNode
* begin
) {
1454 MOZ_ASSERT_IF(begin
, contains(begin
));
1455 return range(begin
, nullptr);
1458 const range
contentsFrom(ParseNode
* begin
) const {
1459 MOZ_ASSERT_IF(begin
, contains(begin
));
1460 return range(begin
, nullptr);
1463 range
contentsTo(ParseNode
* end
) {
1464 MOZ_ASSERT_IF(end
, contains(end
));
1465 return range(head(), end
);
1468 const range
contentsTo(ParseNode
* end
) const {
1469 MOZ_ASSERT_IF(end
, contains(end
));
1470 return range(head(), end
);
1474 class DeclarationListNode
: public ListNode
{
1476 DeclarationListNode(ParseNodeKind kind
, const TokenPos
& pos
)
1477 : ListNode(kind
, pos
) {
1478 MOZ_ASSERT(is
<DeclarationListNode
>());
1481 static bool test(const ParseNode
& node
) {
1482 bool match
= node
.isKind(ParseNodeKind::VarStmt
) ||
1483 node
.isKind(ParseNodeKind::LetDecl
) ||
1484 node
.isKind(ParseNodeKind::ConstDecl
);
1485 MOZ_ASSERT_IF(match
, node
.is
<ListNode
>());
1489 auto* singleBinding() const {
1490 MOZ_ASSERT(count() == 1);
1495 class ParamsBodyNode
: public ListNode
{
1497 explicit ParamsBodyNode(const TokenPos
& pos
)
1498 : ListNode(ParseNodeKind::ParamsBody
, pos
) {
1499 MOZ_ASSERT(is
<ParamsBodyNode
>());
1502 static bool test(const ParseNode
& node
) {
1503 bool match
= node
.isKind(ParseNodeKind::ParamsBody
);
1504 MOZ_ASSERT_IF(match
, node
.is
<ListNode
>());
1508 auto parameters() const {
1509 MOZ_ASSERT(last()->is
<LexicalScopeNode
>());
1510 return contentsTo(last());
1513 auto* body() const {
1514 MOZ_ASSERT(last()->is
<LexicalScopeNode
>());
1515 return &last()->as
<LexicalScopeNode
>();
1519 class FunctionNode
: public ParseNode
{
1520 FunctionBox
* funbox_
;
1522 FunctionSyntaxKind syntaxKind_
;
1525 FunctionNode(FunctionSyntaxKind syntaxKind
, const TokenPos
& pos
)
1526 : ParseNode(ParseNodeKind::Function
, pos
),
1529 syntaxKind_(syntaxKind
) {
1531 MOZ_ASSERT(!funbox_
);
1532 MOZ_ASSERT(is
<FunctionNode
>());
1535 static bool test(const ParseNode
& node
) {
1536 return node
.isKind(ParseNodeKind::Function
);
1539 static constexpr TypeCode
classTypeCode() { return TypeCode::Other
; }
1541 template <typename Visitor
>
1542 bool accept(Visitor
& visitor
) {
1543 // Note: body is null for lazily-parsed functions.
1545 if (!visitor
.visit(body_
)) {
1548 MOZ_ASSERT(body_
->is
<ParamsBodyNode
>());
1554 void dumpImpl(const ParserAtomsTable
* parserAtoms
, GenericPrinter
& out
,
1558 FunctionBox
* funbox() const { return funbox_
; }
1560 ParamsBodyNode
* body() const {
1561 return body_
? &body_
->as
<ParamsBodyNode
>() : nullptr;
1564 void setFunbox(FunctionBox
* funbox
) { funbox_
= funbox
; }
1566 void setBody(ParamsBodyNode
* body
) { body_
= body
; }
1568 FunctionSyntaxKind
syntaxKind() const { return syntaxKind_
; }
1570 bool functionIsHoisted() const {
1571 return syntaxKind() == FunctionSyntaxKind::Statement
;
1575 class ModuleNode
: public ParseNode
{
1579 explicit ModuleNode(const TokenPos
& pos
)
1580 : ParseNode(ParseNodeKind::Module
, pos
), body_(nullptr) {
1582 MOZ_ASSERT(is
<ModuleNode
>());
1585 static bool test(const ParseNode
& node
) {
1586 return node
.isKind(ParseNodeKind::Module
);
1589 static constexpr TypeCode
classTypeCode() { return TypeCode::Other
; }
1591 template <typename Visitor
>
1592 bool accept(Visitor
& visitor
) {
1593 return visitor
.visit(body_
);
1597 void dumpImpl(const ParserAtomsTable
* parserAtoms
, GenericPrinter
& out
,
1601 ListNode
* body() const { return &body_
->as
<ListNode
>(); }
1603 void setBody(ListNode
* body
) { body_
= body
; }
1606 class NumericLiteral
: public ParseNode
{
1607 double value_
; /* aligned numeric literal value */
1608 DecimalPoint decimalPoint_
; /* Whether the number has a decimal point */
1611 NumericLiteral(double value
, DecimalPoint decimalPoint
, const TokenPos
& pos
)
1612 : ParseNode(ParseNodeKind::NumberExpr
, pos
),
1614 decimalPoint_(decimalPoint
) {}
1616 static bool test(const ParseNode
& node
) {
1617 return node
.isKind(ParseNodeKind::NumberExpr
);
1620 static constexpr TypeCode
classTypeCode() { return TypeCode::Other
; }
1622 template <typename Visitor
>
1623 bool accept(Visitor
& visitor
) {
1628 void dumpImpl(const ParserAtomsTable
* parserAtoms
, GenericPrinter
& out
,
1632 double value() const { return value_
; }
1634 DecimalPoint
decimalPoint() const { return decimalPoint_
; }
1636 // Return the decimal string representation of this numeric literal.
1637 TaggedParserAtomIndex
toAtom(FrontendContext
* fc
,
1638 ParserAtomsTable
& parserAtoms
) const;
1641 class BigIntLiteral
: public ParseNode
{
1646 BigIntLiteral(BigIntIndex index
, bool isZero
, const TokenPos
& pos
)
1647 : ParseNode(ParseNodeKind::BigIntExpr
, pos
),
1651 static bool test(const ParseNode
& node
) {
1652 return node
.isKind(ParseNodeKind::BigIntExpr
);
1655 static constexpr TypeCode
classTypeCode() { return TypeCode::Other
; }
1657 template <typename Visitor
>
1658 bool accept(Visitor
& visitor
) {
1663 void dumpImpl(const ParserAtomsTable
* parserAtoms
, GenericPrinter
& out
,
1667 BigIntIndex
index() { return index_
; }
1669 bool isZero() const { return isZero_
; }
1672 template <ParseNodeKind NodeKind
, typename ScopeType
>
1673 class BaseScopeNode
: public ParseNode
{
1674 using ParserData
= typename
ScopeType::ParserData
;
1675 ParserData
* bindings
;
1680 BaseScopeNode(ParserData
* bindings
, ParseNode
* body
,
1681 ScopeKind kind
= ScopeKind::Lexical
)
1682 : ParseNode(NodeKind
, body
->pn_pos
),
1687 static bool test(const ParseNode
& node
) { return node
.isKind(NodeKind
); }
1689 static constexpr TypeCode
classTypeCode() { return TypeCode::Other
; }
1691 template <typename Visitor
>
1692 bool accept(Visitor
& visitor
) {
1693 return visitor
.visit(body
);
1697 void dumpImpl(const ParserAtomsTable
* parserAtoms
, GenericPrinter
& out
,
1701 ParserData
* scopeBindings() const {
1702 MOZ_ASSERT(!isEmptyScope());
1706 ParseNode
* scopeBody() const { return body
; }
1708 void setScopeBody(ParseNode
* body
) { this->body
= body
; }
1710 bool isEmptyScope() const { return !bindings
; }
1712 ScopeKind
kind() const { return kind_
; }
1715 class LexicalScopeNode
1716 : public BaseScopeNode
<ParseNodeKind::LexicalScope
, LexicalScope
> {
1718 LexicalScopeNode(LexicalScope::ParserData
* bindings
, ParseNode
* body
,
1719 ScopeKind kind
= ScopeKind::Lexical
)
1720 : BaseScopeNode(bindings
, body
, kind
) {}
1723 class ClassBodyScopeNode
1724 : public BaseScopeNode
<ParseNodeKind::ClassBodyScope
, ClassBodyScope
> {
1726 ClassBodyScopeNode(ClassBodyScope::ParserData
* bindings
, ListNode
* memberList
)
1727 : BaseScopeNode(bindings
, memberList
, ScopeKind::ClassBody
) {
1728 MOZ_ASSERT(memberList
->isKind(ParseNodeKind::ClassMemberList
));
1731 ListNode
* memberList() const {
1732 ListNode
* list
= &scopeBody()->as
<ListNode
>();
1733 MOZ_ASSERT(list
->isKind(ParseNodeKind::ClassMemberList
));
1738 class LabeledStatement
: public NameNode
{
1739 ParseNode
* statement_
;
1742 LabeledStatement(TaggedParserAtomIndex label
, ParseNode
* stmt
, uint32_t begin
)
1743 : NameNode(ParseNodeKind::LabelStmt
, label
,
1744 TokenPos(begin
, stmt
->pn_pos
.end
)),
1747 TaggedParserAtomIndex
label() const { return atom(); }
1749 ParseNode
* statement() const { return statement_
; }
1751 static bool test(const ParseNode
& node
) {
1752 return node
.isKind(ParseNodeKind::LabelStmt
);
1755 template <typename Visitor
>
1756 bool accept(Visitor
& visitor
) {
1758 if (!visitor
.visit(statement_
)) {
1766 void dumpImpl(const ParserAtomsTable
* parserAtoms
, GenericPrinter
& out
,
1771 // Inside a switch statement, a CaseClause is a case-label and the subsequent
1772 // statements. The same node type is used for DefaultClauses. The only
1773 // difference is that their caseExpression() is null.
1774 class CaseClause
: public BinaryNode
{
1776 CaseClause(ParseNode
* expr
, ParseNode
* stmts
, uint32_t begin
)
1777 : BinaryNode(ParseNodeKind::Case
, TokenPos(begin
, stmts
->pn_pos
.end
),
1780 ParseNode
* caseExpression() const { return left(); }
1782 bool isDefault() const { return !caseExpression(); }
1784 ListNode
* statementList() const { return &right()->as
<ListNode
>(); }
1786 static bool test(const ParseNode
& node
) {
1787 bool match
= node
.isKind(ParseNodeKind::Case
);
1788 MOZ_ASSERT_IF(match
, node
.is
<BinaryNode
>());
1793 class LoopControlStatement
: public ParseNode
{
1794 TaggedParserAtomIndex label_
; /* target of break/continue statement */
1797 LoopControlStatement(ParseNodeKind kind
, TaggedParserAtomIndex label
,
1798 const TokenPos
& pos
)
1799 : ParseNode(kind
, pos
), label_(label
) {
1800 MOZ_ASSERT(kind
== ParseNodeKind::BreakStmt
||
1801 kind
== ParseNodeKind::ContinueStmt
);
1802 MOZ_ASSERT(is
<LoopControlStatement
>());
1806 /* Label associated with this break/continue statement, if any. */
1807 TaggedParserAtomIndex
label() const { return label_
; }
1810 void dumpImpl(const ParserAtomsTable
* parserAtoms
, GenericPrinter
& out
,
1814 static bool test(const ParseNode
& node
) {
1815 return node
.isKind(ParseNodeKind::BreakStmt
) ||
1816 node
.isKind(ParseNodeKind::ContinueStmt
);
1819 static constexpr TypeCode
classTypeCode() { return TypeCode::Other
; }
1821 template <typename Visitor
>
1822 bool accept(Visitor
& visitor
) {
1827 class BreakStatement
: public LoopControlStatement
{
1829 BreakStatement(TaggedParserAtomIndex label
, const TokenPos
& pos
)
1830 : LoopControlStatement(ParseNodeKind::BreakStmt
, label
, pos
) {}
1832 static bool test(const ParseNode
& node
) {
1833 bool match
= node
.isKind(ParseNodeKind::BreakStmt
);
1834 MOZ_ASSERT_IF(match
, node
.is
<LoopControlStatement
>());
1839 class ContinueStatement
: public LoopControlStatement
{
1841 ContinueStatement(TaggedParserAtomIndex label
, const TokenPos
& pos
)
1842 : LoopControlStatement(ParseNodeKind::ContinueStmt
, label
, pos
) {}
1844 static bool test(const ParseNode
& node
) {
1845 bool match
= node
.isKind(ParseNodeKind::ContinueStmt
);
1846 MOZ_ASSERT_IF(match
, node
.is
<LoopControlStatement
>());
1851 class DebuggerStatement
: public NullaryNode
{
1853 explicit DebuggerStatement(const TokenPos
& pos
)
1854 : NullaryNode(ParseNodeKind::DebuggerStmt
, pos
) {}
1856 static bool test(const ParseNode
& node
) {
1857 bool match
= node
.isKind(ParseNodeKind::DebuggerStmt
);
1858 MOZ_ASSERT_IF(match
, node
.is
<NullaryNode
>());
1863 class ConditionalExpression
: public TernaryNode
{
1865 ConditionalExpression(ParseNode
* condition
, ParseNode
* thenExpr
,
1866 ParseNode
* elseExpr
)
1867 : TernaryNode(ParseNodeKind::ConditionalExpr
, condition
, thenExpr
,
1869 TokenPos(condition
->pn_pos
.begin
, elseExpr
->pn_pos
.end
)) {
1870 MOZ_ASSERT(condition
);
1871 MOZ_ASSERT(thenExpr
);
1872 MOZ_ASSERT(elseExpr
);
1875 ParseNode
& condition() const { return *kid1(); }
1877 ParseNode
& thenExpression() const { return *kid2(); }
1879 ParseNode
& elseExpression() const { return *kid3(); }
1881 static bool test(const ParseNode
& node
) {
1882 bool match
= node
.isKind(ParseNodeKind::ConditionalExpr
);
1883 MOZ_ASSERT_IF(match
, node
.is
<TernaryNode
>());
1888 class TryNode
: public TernaryNode
{
1890 TryNode(uint32_t begin
, ParseNode
* body
, LexicalScopeNode
* catchScope
,
1891 ParseNode
* finallyBlock
)
1893 ParseNodeKind::TryStmt
, body
, catchScope
, finallyBlock
,
1895 (finallyBlock
? finallyBlock
: catchScope
)->pn_pos
.end
)) {
1897 MOZ_ASSERT(catchScope
|| finallyBlock
);
1900 static bool test(const ParseNode
& node
) {
1901 bool match
= node
.isKind(ParseNodeKind::TryStmt
);
1902 MOZ_ASSERT_IF(match
, node
.is
<TernaryNode
>());
1906 ParseNode
* body() const { return kid1(); }
1908 LexicalScopeNode
* catchScope() const {
1909 return kid2() ? &kid2()->as
<LexicalScopeNode
>() : nullptr;
1912 ParseNode
* finallyBlock() const { return kid3(); }
1915 class ThisLiteral
: public UnaryNode
{
1917 ThisLiteral(const TokenPos
& pos
, ParseNode
* thisName
)
1918 : UnaryNode(ParseNodeKind::ThisExpr
, pos
, thisName
) {}
1920 static bool test(const ParseNode
& node
) {
1921 bool match
= node
.isKind(ParseNodeKind::ThisExpr
);
1922 MOZ_ASSERT_IF(match
, node
.is
<UnaryNode
>());
1927 class NullLiteral
: public NullaryNode
{
1929 explicit NullLiteral(const TokenPos
& pos
)
1930 : NullaryNode(ParseNodeKind::NullExpr
, pos
) {}
1932 static bool test(const ParseNode
& node
) {
1933 bool match
= node
.isKind(ParseNodeKind::NullExpr
);
1934 MOZ_ASSERT_IF(match
, node
.is
<NullaryNode
>());
1939 // This is only used internally, currently just for tagged templates and the
1940 // initial value of fields without initializers. It represents the value
1941 // 'undefined' (aka `void 0`), like NullLiteral represents the value 'null'.
1942 class RawUndefinedLiteral
: public NullaryNode
{
1944 explicit RawUndefinedLiteral(const TokenPos
& pos
)
1945 : NullaryNode(ParseNodeKind::RawUndefinedExpr
, pos
) {}
1947 static bool test(const ParseNode
& node
) {
1948 bool match
= node
.isKind(ParseNodeKind::RawUndefinedExpr
);
1949 MOZ_ASSERT_IF(match
, node
.is
<NullaryNode
>());
1954 class BooleanLiteral
: public NullaryNode
{
1956 BooleanLiteral(bool b
, const TokenPos
& pos
)
1957 : NullaryNode(b
? ParseNodeKind::TrueExpr
: ParseNodeKind::FalseExpr
,
1960 static bool test(const ParseNode
& node
) {
1961 bool match
= node
.isKind(ParseNodeKind::TrueExpr
) ||
1962 node
.isKind(ParseNodeKind::FalseExpr
);
1963 MOZ_ASSERT_IF(match
, node
.is
<NullaryNode
>());
1968 class RegExpLiteral
: public ParseNode
{
1972 RegExpLiteral(RegExpIndex dataIndex
, const TokenPos
& pos
)
1973 : ParseNode(ParseNodeKind::RegExpExpr
, pos
), index_(dataIndex
) {}
1975 // Create a RegExp object of this RegExp literal.
1976 RegExpObject
* create(JSContext
* cx
, FrontendContext
* fc
,
1977 ParserAtomsTable
& parserAtoms
,
1978 CompilationAtomCache
& atomCache
,
1979 ExtensibleCompilationStencil
& stencil
) const;
1982 void dumpImpl(const ParserAtomsTable
* parserAtoms
, GenericPrinter
& out
,
1986 static bool test(const ParseNode
& node
) {
1987 return node
.isKind(ParseNodeKind::RegExpExpr
);
1990 static constexpr TypeCode
classTypeCode() { return TypeCode::Other
; }
1992 template <typename Visitor
>
1993 bool accept(Visitor
& visitor
) {
1997 RegExpIndex
index() { return index_
; }
2000 class PropertyAccessBase
: public BinaryNode
{
2003 * PropertyAccess nodes can have any expression/'super' as left-hand
2004 * side, but the name must be a ParseNodeKind::PropertyName node.
2006 PropertyAccessBase(ParseNodeKind kind
, ParseNode
* lhs
, NameNode
* name
,
2007 uint32_t begin
, uint32_t end
)
2008 : BinaryNode(kind
, TokenPos(begin
, end
), lhs
, name
) {
2013 ParseNode
& expression() const { return *left(); }
2015 static bool test(const ParseNode
& node
) {
2016 bool match
= node
.isKind(ParseNodeKind::DotExpr
) ||
2017 node
.isKind(ParseNodeKind::OptionalDotExpr
);
2018 MOZ_ASSERT_IF(match
, node
.is
<BinaryNode
>());
2019 MOZ_ASSERT_IF(match
, node
.as
<BinaryNode
>().right()->isKind(
2020 ParseNodeKind::PropertyNameExpr
));
2024 NameNode
& key() const { return right()->as
<NameNode
>(); }
2026 // Method used by BytecodeEmitter::emitPropLHS for optimization.
2027 // Those methods allow expression to temporarily be nullptr for
2028 // optimization purpose.
2029 ParseNode
* maybeExpression() const { return left(); }
2031 void setExpression(ParseNode
* pn
) { *unsafeLeftReference() = pn
; }
2033 TaggedParserAtomIndex
name() const { return right()->as
<NameNode
>().atom(); }
2036 class PropertyAccess
: public PropertyAccessBase
{
2038 PropertyAccess(ParseNode
* lhs
, NameNode
* name
, uint32_t begin
, uint32_t end
)
2039 : PropertyAccessBase(ParseNodeKind::DotExpr
, lhs
, name
, begin
, end
) {
2044 static bool test(const ParseNode
& node
) {
2045 bool match
= node
.isKind(ParseNodeKind::DotExpr
);
2046 MOZ_ASSERT_IF(match
, node
.is
<PropertyAccessBase
>());
2050 bool isSuper() const {
2051 // ParseNodeKind::SuperBase cannot result from any expression syntax.
2052 return expression().isKind(ParseNodeKind::SuperBase
);
2056 class OptionalPropertyAccess
: public PropertyAccessBase
{
2058 OptionalPropertyAccess(ParseNode
* lhs
, NameNode
* name
, uint32_t begin
,
2060 : PropertyAccessBase(ParseNodeKind::OptionalDotExpr
, lhs
, name
, begin
,
2066 static bool test(const ParseNode
& node
) {
2067 bool match
= node
.isKind(ParseNodeKind::OptionalDotExpr
);
2068 MOZ_ASSERT_IF(match
, node
.is
<PropertyAccessBase
>());
2073 class PropertyByValueBase
: public BinaryNode
{
2075 PropertyByValueBase(ParseNodeKind kind
, ParseNode
* lhs
, ParseNode
* propExpr
,
2076 uint32_t begin
, uint32_t end
)
2077 : BinaryNode(kind
, TokenPos(begin
, end
), lhs
, propExpr
) {}
2079 static bool test(const ParseNode
& node
) {
2080 bool match
= node
.isKind(ParseNodeKind::ElemExpr
) ||
2081 node
.isKind(ParseNodeKind::OptionalElemExpr
);
2082 MOZ_ASSERT_IF(match
, node
.is
<BinaryNode
>());
2086 ParseNode
& expression() const { return *left(); }
2088 ParseNode
& key() const { return *right(); }
2091 class PropertyByValue
: public PropertyByValueBase
{
2093 PropertyByValue(ParseNode
* lhs
, ParseNode
* propExpr
, uint32_t begin
,
2095 : PropertyByValueBase(ParseNodeKind::ElemExpr
, lhs
, propExpr
, begin
,
2098 static bool test(const ParseNode
& node
) {
2099 bool match
= node
.isKind(ParseNodeKind::ElemExpr
);
2100 MOZ_ASSERT_IF(match
, node
.is
<PropertyByValueBase
>());
2104 bool isSuper() const { return left()->isKind(ParseNodeKind::SuperBase
); }
2107 class OptionalPropertyByValue
: public PropertyByValueBase
{
2109 OptionalPropertyByValue(ParseNode
* lhs
, ParseNode
* propExpr
, uint32_t begin
,
2111 : PropertyByValueBase(ParseNodeKind::OptionalElemExpr
, lhs
, propExpr
,
2114 static bool test(const ParseNode
& node
) {
2115 bool match
= node
.isKind(ParseNodeKind::OptionalElemExpr
);
2116 MOZ_ASSERT_IF(match
, node
.is
<PropertyByValueBase
>());
2121 class PrivateMemberAccessBase
: public BinaryNode
{
2123 PrivateMemberAccessBase(ParseNodeKind kind
, ParseNode
* lhs
, NameNode
* name
,
2124 uint32_t begin
, uint32_t end
)
2125 : BinaryNode(kind
, TokenPos(begin
, end
), lhs
, name
) {
2126 MOZ_ASSERT(name
->isKind(ParseNodeKind::PrivateName
));
2129 ParseNode
& expression() const { return *left(); }
2131 NameNode
& privateName() const {
2132 NameNode
& name
= right()->as
<NameNode
>();
2133 MOZ_ASSERT(name
.isKind(ParseNodeKind::PrivateName
));
2137 static bool test(const ParseNode
& node
) {
2138 bool match
= node
.isKind(ParseNodeKind::PrivateMemberExpr
) ||
2139 node
.isKind(ParseNodeKind::OptionalPrivateMemberExpr
);
2140 MOZ_ASSERT_IF(match
, node
.is
<BinaryNode
>());
2141 MOZ_ASSERT_IF(match
, node
.as
<BinaryNode
>().right()->isKind(
2142 ParseNodeKind::PrivateName
));
2147 class PrivateMemberAccess
: public PrivateMemberAccessBase
{
2149 PrivateMemberAccess(ParseNode
* lhs
, NameNode
* name
, uint32_t begin
,
2151 : PrivateMemberAccessBase(ParseNodeKind::PrivateMemberExpr
, lhs
, name
,
2154 static bool test(const ParseNode
& node
) {
2155 return node
.isKind(ParseNodeKind::PrivateMemberExpr
);
2159 class OptionalPrivateMemberAccess
: public PrivateMemberAccessBase
{
2161 OptionalPrivateMemberAccess(ParseNode
* lhs
, NameNode
* name
, uint32_t begin
,
2163 : PrivateMemberAccessBase(ParseNodeKind::OptionalPrivateMemberExpr
, lhs
,
2164 name
, begin
, end
) {}
2166 static bool test(const ParseNode
& node
) {
2167 return node
.isKind(ParseNodeKind::OptionalPrivateMemberExpr
);
2171 class NewTargetNode
: public TernaryNode
{
2173 NewTargetNode(NullaryNode
* newHolder
, NullaryNode
* targetHolder
,
2174 NameNode
* newTargetName
)
2175 : TernaryNode(ParseNodeKind::NewTargetExpr
, newHolder
, targetHolder
,
2178 static bool test(const ParseNode
& node
) {
2179 bool match
= node
.isKind(ParseNodeKind::NewTargetExpr
);
2180 MOZ_ASSERT_IF(match
, node
.is
<TernaryNode
>());
2184 auto* newHolder() const { return &kid1()->as
<NullaryNode
>(); }
2185 auto* targetHolder() const { return &kid2()->as
<NullaryNode
>(); }
2186 auto* newTargetName() const { return &kid3()->as
<NameNode
>(); }
2190 * A CallSiteNode represents the implicit call site object argument in a
2193 class CallSiteNode
: public ListNode
{
2195 explicit CallSiteNode(uint32_t begin
)
2196 : ListNode(ParseNodeKind::CallSiteObj
, TokenPos(begin
, begin
+ 1)) {}
2198 static bool test(const ParseNode
& node
) {
2199 bool match
= node
.isKind(ParseNodeKind::CallSiteObj
);
2200 MOZ_ASSERT_IF(match
, node
.is
<ListNode
>());
2204 ListNode
* rawNodes() const {
2206 return &head()->as
<ListNode
>();
2210 class CallNode
: public BinaryNode
{
2214 CallNode(ParseNodeKind kind
, JSOp callOp
, ParseNode
* left
, ListNode
* right
)
2215 : CallNode(kind
, callOp
, TokenPos(left
->pn_pos
.begin
, right
->pn_pos
.end
),
2218 CallNode(ParseNodeKind kind
, JSOp callOp
, TokenPos pos
, ParseNode
* left
,
2220 : BinaryNode(kind
, pos
, left
, right
), callOp_(callOp
) {
2221 MOZ_ASSERT(is
<CallNode
>());
2224 static bool test(const ParseNode
& node
) {
2225 bool match
= node
.isKind(ParseNodeKind::CallExpr
) ||
2226 node
.isKind(ParseNodeKind::SuperCallExpr
) ||
2227 node
.isKind(ParseNodeKind::OptionalCallExpr
) ||
2228 node
.isKind(ParseNodeKind::TaggedTemplateExpr
) ||
2229 node
.isKind(ParseNodeKind::NewExpr
);
2230 MOZ_ASSERT_IF(match
, node
.is
<BinaryNode
>());
2234 JSOp
callOp() const { return callOp_
; }
2235 auto* callee() const { return left(); }
2236 auto* args() const { return &right()->as
<ListNode
>(); }
2239 class ClassMethod
: public BinaryNode
{
2240 using Base
= BinaryNode
;
2243 AccessorType accessorType_
;
2244 FunctionNode
* initializerIfPrivate_
;
2246 #ifdef ENABLE_DECORATORS
2247 ListNode
* decorators_
;
2252 * Method definitions often keep a name and function body that overlap,
2253 * so explicitly define the beginning and end here.
2255 ClassMethod(ParseNodeKind kind
, ParseNode
* name
, ParseNode
* body
,
2256 AccessorType accessorType
, bool isStatic
,
2257 FunctionNode
* initializerIfPrivate
2258 #ifdef ENABLE_DECORATORS
2260 ListNode
* decorators
2263 : BinaryNode(kind
, TokenPos(name
->pn_pos
.begin
, body
->pn_pos
.end
), name
,
2265 isStatic_(isStatic
),
2266 accessorType_(accessorType
),
2267 initializerIfPrivate_(initializerIfPrivate
)
2268 #ifdef ENABLE_DECORATORS
2270 decorators_(decorators
)
2273 MOZ_ASSERT(kind
== ParseNodeKind::DefaultConstructor
||
2274 kind
== ParseNodeKind::ClassMethod
);
2277 static bool test(const ParseNode
& node
) {
2278 bool match
= node
.isKind(ParseNodeKind::DefaultConstructor
) ||
2279 node
.isKind(ParseNodeKind::ClassMethod
);
2280 MOZ_ASSERT_IF(match
, node
.is
<BinaryNode
>());
2284 ParseNode
& name() const { return *left(); }
2286 FunctionNode
& method() const { return right()->as
<FunctionNode
>(); }
2288 bool isStatic() const { return isStatic_
; }
2290 AccessorType
accessorType() const { return accessorType_
; }
2292 FunctionNode
* initializerIfPrivate() const { return initializerIfPrivate_
; }
2294 #ifdef ENABLE_DECORATORS
2295 ListNode
* decorators() const { return decorators_
; }
2298 void dumpImpl(const ParserAtomsTable
* parserAtoms
, GenericPrinter
& out
,
2304 class ClassField
: public BinaryNode
{
2305 using Base
= BinaryNode
;
2308 #ifdef ENABLE_DECORATORS
2309 // The accessorGetterNode_ and accessorSetterNode_ are used to store the
2310 // getter and setter synthesized by the `accessor` keyword when they are
2311 // decorated. Otherwise, they are null.
2313 // In most cases, the accessors are not added to the class members, and the
2314 // code generation occurs immediately prior to the decorator running. For
2315 // non-static private methods, the accessors are added to the class members
2316 // which causes them to be stored in lexical variables. The references here
2317 // are used to store the names of the accessors to look up the values of these
2318 // variables during bytecode generation.
2319 ClassMethod
* accessorGetterNode_
;
2320 ClassMethod
* accessorSetterNode_
;
2321 ListNode
* decorators_
;
2325 ClassField(ParseNode
* name
, ParseNode
* initializer
, bool isStatic
2326 #ifdef ENABLE_DECORATORS
2328 ListNode
* decorators
, ClassMethod
* accessorGetterNode
,
2329 ClassMethod
* accessorSetterNode
2332 : BinaryNode(ParseNodeKind::ClassField
, initializer
->pn_pos
, name
,
2335 #ifdef ENABLE_DECORATORS
2337 accessorGetterNode_(accessorGetterNode
),
2338 accessorSetterNode_(accessorSetterNode
),
2339 decorators_(decorators
)
2342 #ifdef ENABLE_DECORATORS
2343 MOZ_ASSERT((accessorGetterNode_
== nullptr) ==
2344 (accessorSetterNode_
== nullptr));
2348 static bool test(const ParseNode
& node
) {
2349 bool match
= node
.isKind(ParseNodeKind::ClassField
);
2350 MOZ_ASSERT_IF(match
, node
.is
<BinaryNode
>());
2354 ParseNode
& name() const { return *left(); }
2356 FunctionNode
* initializer() const { return &right()->as
<FunctionNode
>(); }
2358 bool isStatic() const { return isStatic_
; }
2360 #ifdef ENABLE_DECORATORS
2361 ListNode
* decorators() const { return decorators_
; }
2362 bool hasAccessor() const {
2363 return accessorGetterNode_
!= nullptr && accessorSetterNode_
!= nullptr;
2365 ClassMethod
* accessorGetterNode() { return accessorGetterNode_
; }
2366 ClassMethod
* accessorSetterNode() { return accessorSetterNode_
; }
2369 void dumpImpl(const ParserAtomsTable
* parserAtoms
, GenericPrinter
& out
,
2375 // Hold onto the function generated for a class static block like
2378 // static { /* this static block */ }
2381 class StaticClassBlock
: public UnaryNode
{
2383 explicit StaticClassBlock(FunctionNode
* function
)
2384 : UnaryNode(ParseNodeKind::StaticClassBlock
, function
->pn_pos
, function
) {
2387 static bool test(const ParseNode
& node
) {
2388 bool match
= node
.isKind(ParseNodeKind::StaticClassBlock
);
2389 MOZ_ASSERT_IF(match
, node
.is
<UnaryNode
>());
2392 FunctionNode
* function() const { return &kid()->as
<FunctionNode
>(); }
2395 class PropertyDefinition
: public BinaryNode
{
2396 AccessorType accessorType_
;
2399 PropertyDefinition(ParseNode
* name
, ParseNode
* value
,
2400 AccessorType accessorType
)
2401 : BinaryNode(ParseNodeKind::PropertyDefinition
,
2402 TokenPos(name
->pn_pos
.begin
, value
->pn_pos
.end
), name
,
2404 accessorType_(accessorType
) {}
2406 static bool test(const ParseNode
& node
) {
2407 bool match
= node
.isKind(ParseNodeKind::PropertyDefinition
);
2408 MOZ_ASSERT_IF(match
, node
.is
<BinaryNode
>());
2412 AccessorType
accessorType() { return accessorType_
; }
2415 class SwitchStatement
: public BinaryNode
{
2416 bool hasDefault_
; /* only for ParseNodeKind::Switch */
2419 SwitchStatement(uint32_t begin
, ParseNode
* discriminant
,
2420 LexicalScopeNode
* lexicalForCaseList
, bool hasDefault
)
2421 : BinaryNode(ParseNodeKind::SwitchStmt
,
2422 TokenPos(begin
, lexicalForCaseList
->pn_pos
.end
),
2423 discriminant
, lexicalForCaseList
),
2424 hasDefault_(hasDefault
) {
2426 ListNode
* cases
= &lexicalForCaseList
->scopeBody()->as
<ListNode
>();
2427 MOZ_ASSERT(cases
->isKind(ParseNodeKind::StatementList
));
2429 for (ParseNode
* item
: cases
->contents()) {
2430 CaseClause
* caseNode
= &item
->as
<CaseClause
>();
2431 if (caseNode
->isDefault()) {
2436 MOZ_ASSERT(found
== hasDefault
);
2440 static bool test(const ParseNode
& node
) {
2441 bool match
= node
.isKind(ParseNodeKind::SwitchStmt
);
2442 MOZ_ASSERT_IF(match
, node
.is
<BinaryNode
>());
2446 ParseNode
& discriminant() const { return *left(); }
2448 LexicalScopeNode
& lexicalForCaseList() const {
2449 return right()->as
<LexicalScopeNode
>();
2452 bool hasDefault() const { return hasDefault_
; }
2455 class ClassNames
: public BinaryNode
{
2457 ClassNames(ParseNode
* outerBinding
, ParseNode
* innerBinding
,
2458 const TokenPos
& pos
)
2459 : BinaryNode(ParseNodeKind::ClassNames
, pos
, outerBinding
, innerBinding
) {
2460 MOZ_ASSERT_IF(outerBinding
, outerBinding
->isKind(ParseNodeKind::Name
));
2461 MOZ_ASSERT(innerBinding
->isKind(ParseNodeKind::Name
));
2462 MOZ_ASSERT_IF(outerBinding
, innerBinding
->as
<NameNode
>().atom() ==
2463 outerBinding
->as
<NameNode
>().atom());
2466 static bool test(const ParseNode
& node
) {
2467 bool match
= node
.isKind(ParseNodeKind::ClassNames
);
2468 MOZ_ASSERT_IF(match
, node
.is
<BinaryNode
>());
2473 * Classes require two definitions: The first "outer" binding binds the
2474 * class into the scope in which it was declared. the outer binding is a
2475 * mutable lexial binding. The second "inner" binding binds the class by
2476 * name inside a block in which the methods are evaulated. It is immutable,
2477 * giving the methods access to the static members of the class even if
2478 * the outer binding has been overwritten.
2480 NameNode
* outerBinding() const {
2481 if (ParseNode
* binding
= left()) {
2482 return &binding
->as
<NameNode
>();
2487 NameNode
* innerBinding() const { return &right()->as
<NameNode
>(); }
2490 class ClassNode
: public TernaryNode
{
2491 using Base
= TernaryNode
;
2494 LexicalScopeNode
* innerScope() const {
2495 return &kid3()->as
<LexicalScopeNode
>();
2498 ClassBodyScopeNode
* bodyScope() const {
2499 return &innerScope()->scopeBody()->as
<ClassBodyScopeNode
>();
2502 #ifdef ENABLE_DECORATORS
2503 ListNode
* decorators_
;
2507 ClassNode(ParseNode
* names
, ParseNode
* heritage
,
2508 LexicalScopeNode
* memberBlock
,
2509 #ifdef ENABLE_DECORATORS
2510 ListNode
* decorators
,
2512 const TokenPos
& pos
)
2513 : TernaryNode(ParseNodeKind::ClassDecl
, names
, heritage
, memberBlock
, pos
)
2514 #ifdef ENABLE_DECORATORS
2516 decorators_(decorators
)
2519 MOZ_ASSERT(innerScope()->scopeBody()->is
<ClassBodyScopeNode
>());
2520 MOZ_ASSERT_IF(names
, names
->is
<ClassNames
>());
2523 static bool test(const ParseNode
& node
) {
2524 bool match
= node
.isKind(ParseNodeKind::ClassDecl
);
2525 MOZ_ASSERT_IF(match
, node
.is
<TernaryNode
>());
2529 ClassNames
* names() const {
2530 return kid1() ? &kid1()->as
<ClassNames
>() : nullptr;
2533 ParseNode
* heritage() const { return kid2(); }
2535 ListNode
* memberList() const { return bodyScope()->memberList(); }
2537 LexicalScopeNode
* scopeBindings() const {
2538 LexicalScopeNode
* scope
= innerScope();
2539 return scope
->isEmptyScope() ? nullptr : scope
;
2542 ClassBodyScopeNode
* bodyScopeBindings() const {
2543 ClassBodyScopeNode
* scope
= bodyScope();
2544 return scope
->isEmptyScope() ? nullptr : scope
;
2546 #ifdef ENABLE_DECORATORS
2547 ListNode
* decorators() const { return decorators_
; }
2550 void dumpImpl(const ParserAtomsTable
* parserAtoms
, GenericPrinter
& out
,
2557 void DumpParseTree(ParserBase
* parser
, ParseNode
* pn
, GenericPrinter
& out
,
2561 class ParseNodeAllocator
{
2563 explicit ParseNodeAllocator(FrontendContext
* fc
, LifoAlloc
& alloc
)
2564 : fc(fc
), alloc(alloc
) {}
2566 void* allocNode(size_t size
);
2569 FrontendContext
* fc
;
2573 inline bool ParseNode::isConstant() {
2575 case ParseNodeKind::NumberExpr
:
2576 case ParseNodeKind::StringExpr
:
2577 case ParseNodeKind::TemplateStringExpr
:
2578 case ParseNodeKind::NullExpr
:
2579 case ParseNodeKind::RawUndefinedExpr
:
2580 case ParseNodeKind::FalseExpr
:
2581 case ParseNodeKind::TrueExpr
:
2583 case ParseNodeKind::ArrayExpr
:
2584 case ParseNodeKind::ObjectExpr
:
2585 return !as
<ListNode
>().hasNonConstInitializer();
2591 bool IsAnonymousFunctionDefinition(ParseNode
* pn
);
2593 } /* namespace frontend */
2594 } /* namespace js */
2596 #endif /* frontend_ParseNode_h */