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