SyntaxParseHandler.h (29062B)
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_SyntaxParseHandler_h 8 #define frontend_SyntaxParseHandler_h 9 10 #include "mozilla/Assertions.h" 11 #include "mozilla/Maybe.h" // mozilla::Maybe 12 #include "mozilla/Result.h" // mozilla::Result, mozilla::UnusedZero 13 14 #include <string.h> 15 16 #include "jstypes.h" 17 18 #include "frontend/CompilationStencil.h" // CompilationState 19 #include "frontend/FunctionSyntaxKind.h" // FunctionSyntaxKind 20 #include "frontend/NameAnalysisTypes.h" // PrivateNameKind 21 #include "frontend/ParseNode.h" 22 #include "frontend/ParserAtom.h" // TaggedParserAtomIndex 23 #include "frontend/TokenStream.h" 24 25 namespace js { 26 namespace frontend { 27 enum SyntaxParseHandlerNode { 28 NodeFailure = 0, 29 NodeGeneric, 30 NodeGetProp, 31 NodeStringExprStatement, 32 NodeReturn, 33 NodeBreak, 34 NodeThrow, 35 NodeEmptyStatement, 36 37 NodeVarDeclaration, 38 NodeLexicalDeclaration, 39 40 // A non-arrow function expression with block body, from bog-standard 41 // ECMAScript. 42 NodeFunctionExpression, 43 44 NodeFunctionArrow, 45 NodeFunctionStatement, 46 47 // This is needed for proper assignment-target handling. ES6 formally 48 // requires function calls *not* pass IsValidSimpleAssignmentTarget, 49 // but at last check there were still sites with |f() = 5| and similar 50 // in code not actually executed (or at least not executed enough to be 51 // noticed). 52 NodeFunctionCall, 53 54 NodeOptionalFunctionCall, 55 56 // Node representing normal names which don't require any special 57 // casing. 58 NodeName, 59 60 // Nodes representing the names "arguments", "length" and "eval". 61 NodeArgumentsName, 62 NodeLengthName, 63 NodeEvalName, 64 65 // Node representing the "async" name, which may actually be a 66 // contextual keyword. 67 NodePotentialAsyncKeyword, 68 69 // Node representing private names. 70 NodePrivateName, 71 72 NodeDottedProperty, 73 NodeOptionalDottedProperty, 74 NodeElement, 75 NodeOptionalElement, 76 // A distinct node for [PrivateName], to make detecting delete this.#x 77 // detectable in syntax parse 78 NodePrivateMemberAccess, 79 NodeOptionalPrivateMemberAccess, 80 81 // Node representing the compound Arguments.length expression; 82 // Used only for property access, not assignment. 83 NodeArgumentsLength, 84 85 // Destructuring target patterns can't be parenthesized: |([a]) = [3];| 86 // must be a syntax error. (We can't use NodeGeneric instead of these 87 // because that would trigger invalid-left-hand-side ReferenceError 88 // semantics when SyntaxError semantics are desired.) 89 NodeParenthesizedArray, 90 NodeParenthesizedObject, 91 92 // In rare cases a parenthesized |node| doesn't have the same semantics 93 // as |node|. Each such node has a special Node value, and we use a 94 // different Node value to represent the parenthesized form. See also 95 // is{Unp,P}arenthesized*(Node), parenthesize(Node), and the various 96 // functions that deal in NodeUnparenthesized* below. 97 98 // Valuable for recognizing potential destructuring patterns. 99 NodeUnparenthesizedArray, 100 NodeUnparenthesizedObject, 101 102 // The directive prologue at the start of a FunctionBody or ScriptBody 103 // is the longest sequence (possibly empty) of string literal 104 // expression statements at the start of a function. Thus we need this 105 // to treat |"use strict";| as a possible Use Strict Directive and 106 // |("use strict");| as a useless statement. 107 NodeUnparenthesizedString, 108 109 // For destructuring patterns an assignment element with 110 // an initializer expression is not allowed be parenthesized. 111 // i.e. |{x = 1} = obj| 112 NodeUnparenthesizedAssignment, 113 114 // This node is necessary to determine if the base operand in an 115 // exponentiation operation is an unparenthesized unary expression. 116 // We want to reject |-2 ** 3|, but still need to allow |(-2) ** 3|. 117 NodeUnparenthesizedUnary, 118 119 // This node is necessary to determine if the LHS of a property access is 120 // super related. 121 NodeSuperBase 122 }; 123 124 } // namespace frontend 125 } // namespace js 126 127 template <> 128 struct mozilla::detail::UnusedZero<js::frontend::SyntaxParseHandlerNode> { 129 static const bool value = true; 130 }; 131 132 namespace js { 133 namespace frontend { 134 135 // Parse handler used when processing the syntax in a block of code, to generate 136 // the minimal information which is required to detect syntax errors and allow 137 // bytecode to be emitted for outer functions. 138 // 139 // When parsing, we start at the top level with a full parse, and when possible 140 // only check the syntax for inner functions, so that they can be lazily parsed 141 // into bytecode when/if they first run. Checking the syntax of a function is 142 // several times faster than doing a full parse/emit, and lazy parsing improves 143 // both performance and memory usage significantly when pages contain large 144 // amounts of code that never executes (which happens often). 145 class SyntaxParseHandler { 146 // Remember the last encountered name or string literal during syntax parses. 147 TaggedParserAtomIndex lastAtom; 148 TokenPos lastStringPos; 149 150 public: 151 struct NodeError {}; 152 153 using Node = SyntaxParseHandlerNode; 154 155 using NodeResult = mozilla::Result<Node, NodeError>; 156 using NodeErrorResult = mozilla::GenericErrorResult<NodeError>; 157 158 #define DECLARE_TYPE(typeName) \ 159 using typeName##Type = Node; \ 160 using typeName##Result = mozilla::Result<Node, NodeError>; 161 FOR_EACH_PARSENODE_SUBCLASS(DECLARE_TYPE) 162 #undef DECLARE_TYPE 163 164 using NullNode = Node; 165 166 bool isNonArrowFunctionExpression(Node node) const { 167 return node == NodeFunctionExpression; 168 } 169 170 bool isPropertyOrPrivateMemberAccess(Node node) { 171 return node == NodeDottedProperty || node == NodeElement || 172 node == NodePrivateMemberAccess || node == NodeArgumentsLength; 173 } 174 175 bool isOptionalPropertyOrPrivateMemberAccess(Node node) { 176 return node == NodeOptionalDottedProperty || node == NodeOptionalElement || 177 node == NodeOptionalPrivateMemberAccess; 178 } 179 180 bool isFunctionCall(Node node) { 181 // Note: super() is a special form, *not* a function call. 182 return node == NodeFunctionCall; 183 } 184 185 static bool isUnparenthesizedDestructuringPattern(Node node) { 186 return node == NodeUnparenthesizedArray || 187 node == NodeUnparenthesizedObject; 188 } 189 190 static bool isParenthesizedDestructuringPattern(Node node) { 191 // Technically this isn't a destructuring target at all -- the grammar 192 // doesn't treat it as such. But we need to know when this happens to 193 // consider it a SyntaxError rather than an invalid-left-hand-side 194 // ReferenceError. 195 return node == NodeParenthesizedArray || node == NodeParenthesizedObject; 196 } 197 198 public: 199 SyntaxParseHandler(FrontendContext* fc, CompilationState& compilationState) { 200 MOZ_ASSERT(!compilationState.input.isDelazifying()); 201 } 202 203 static NullNode null() { return NodeFailure; } 204 static constexpr NodeErrorResult errorResult() { 205 return NodeErrorResult(NodeError()); 206 } 207 208 #define DECLARE_AS(typeName) \ 209 static typeName##Type as##typeName(Node node) { return node; } 210 FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS) 211 #undef DECLARE_AS 212 213 NameNodeResult newName(TaggedParserAtomIndex name, const TokenPos& pos) { 214 lastAtom = name; 215 if (name == TaggedParserAtomIndex::WellKnown::arguments()) { 216 return NodeArgumentsName; 217 } 218 if (pos.begin + strlen("async") == pos.end && 219 name == TaggedParserAtomIndex::WellKnown::async()) { 220 return NodePotentialAsyncKeyword; 221 } 222 if (name == TaggedParserAtomIndex::WellKnown::eval()) { 223 return NodeEvalName; 224 } 225 return NodeName; 226 } 227 228 UnaryNodeResult newComputedName(Node expr, uint32_t start, uint32_t end) { 229 return NodeGeneric; 230 } 231 232 UnaryNodeResult newSyntheticComputedName(Node expr, uint32_t start, 233 uint32_t end) { 234 return NodeGeneric; 235 } 236 237 NameNodeResult newObjectLiteralPropertyName(TaggedParserAtomIndex atom, 238 const TokenPos& pos) { 239 return NodeName; 240 } 241 242 NameNodeResult newPrivateName(TaggedParserAtomIndex atom, 243 const TokenPos& pos) { 244 return NodePrivateName; 245 } 246 247 NumericLiteralResult newNumber(double value, DecimalPoint decimalPoint, 248 const TokenPos& pos) { 249 return NodeGeneric; 250 } 251 252 BigIntLiteralResult newBigInt() { return NodeGeneric; } 253 254 BooleanLiteralResult newBooleanLiteral(bool cond, const TokenPos& pos) { 255 return NodeGeneric; 256 } 257 258 NameNodeResult newStringLiteral(TaggedParserAtomIndex atom, 259 const TokenPos& pos) { 260 lastAtom = atom; 261 lastStringPos = pos; 262 return NodeUnparenthesizedString; 263 } 264 265 NameNodeResult newTemplateStringLiteral(TaggedParserAtomIndex atom, 266 const TokenPos& pos) { 267 return NodeGeneric; 268 } 269 270 CallSiteNodeResult newCallSiteObject(uint32_t begin) { return NodeGeneric; } 271 272 void addToCallSiteObject(CallSiteNodeType callSiteObj, Node rawNode, 273 Node cookedNode) {} 274 275 ThisLiteralResult newThisLiteral(const TokenPos& pos, Node thisName) { 276 return NodeGeneric; 277 } 278 NullLiteralResult newNullLiteral(const TokenPos& pos) { return NodeGeneric; } 279 RawUndefinedLiteralResult newRawUndefinedLiteral(const TokenPos& pos) { 280 return NodeGeneric; 281 } 282 283 RegExpLiteralResult newRegExp(Node reobj, const TokenPos& pos) { 284 return NodeGeneric; 285 } 286 287 ConditionalExpressionResult newConditional(Node cond, Node thenExpr, 288 Node elseExpr) { 289 return NodeGeneric; 290 } 291 292 UnaryNodeResult newDelete(uint32_t begin, Node expr) { 293 return NodeUnparenthesizedUnary; 294 } 295 296 UnaryNodeResult newTypeof(uint32_t begin, Node kid) { 297 return NodeUnparenthesizedUnary; 298 } 299 300 UnaryNodeResult newUnary(ParseNodeKind kind, uint32_t begin, Node kid) { 301 return NodeUnparenthesizedUnary; 302 } 303 304 UnaryNodeResult newUpdate(ParseNodeKind kind, uint32_t begin, Node kid) { 305 return NodeGeneric; 306 } 307 308 UnaryNodeResult newSpread(uint32_t begin, Node kid) { return NodeGeneric; } 309 310 NodeResult appendOrCreateList(ParseNodeKind kind, Node left, Node right, 311 ParseContext* pc) { 312 return NodeGeneric; 313 } 314 315 // Expressions 316 317 ListNodeResult newArrayLiteral(uint32_t begin) { 318 return NodeUnparenthesizedArray; 319 } 320 [[nodiscard]] bool addElision(ListNodeType literal, const TokenPos& pos) { 321 return true; 322 } 323 [[nodiscard]] bool addSpreadElement(ListNodeType literal, uint32_t begin, 324 Node inner) { 325 return true; 326 } 327 void addArrayElement(ListNodeType literal, Node element) {} 328 329 ListNodeResult newArguments(const TokenPos& pos) { return NodeGeneric; } 330 CallNodeResult newCall(Node callee, ListNodeType args, JSOp callOp) { 331 return NodeFunctionCall; 332 } 333 334 CallNodeResult newOptionalCall(Node callee, ListNodeType args, JSOp callOp) { 335 return NodeOptionalFunctionCall; 336 } 337 338 CallNodeResult newSuperCall(Node callee, ListNodeType args, bool isSpread) { 339 return NodeGeneric; 340 } 341 CallNodeResult newTaggedTemplate(Node tag, ListNodeType args, JSOp callOp) { 342 return NodeGeneric; 343 } 344 345 ListNodeResult newObjectLiteral(uint32_t begin) { 346 return NodeUnparenthesizedObject; 347 } 348 349 ListNodeResult newClassMemberList(uint32_t begin) { return NodeGeneric; } 350 ClassNamesResult newClassNames(Node outer, Node inner, const TokenPos& pos) { 351 return NodeGeneric; 352 } 353 ClassNodeResult newClass(Node name, Node heritage, Node methodBlock, 354 #ifdef ENABLE_DECORATORS 355 ListNodeType decorators, 356 FunctionNodeType addInitializerFunction, 357 #endif 358 const TokenPos& pos) { 359 return NodeGeneric; 360 } 361 362 LexicalScopeNodeResult newLexicalScope(Node body) { 363 return NodeLexicalDeclaration; 364 } 365 366 ClassBodyScopeNodeResult newClassBodyScope(Node body) { 367 return NodeLexicalDeclaration; 368 } 369 370 NewTargetNodeResult newNewTarget(NullaryNodeType newHolder, 371 NullaryNodeType targetHolder, 372 NameNodeType newTargetName) { 373 return NodeGeneric; 374 } 375 NullaryNodeResult newPosHolder(const TokenPos& pos) { return NodeGeneric; } 376 UnaryNodeResult newSuperBase(Node thisName, const TokenPos& pos) { 377 return NodeSuperBase; 378 } 379 380 [[nodiscard]] bool addPrototypeMutation(ListNodeType literal, uint32_t begin, 381 Node expr) { 382 return true; 383 } 384 BinaryNodeResult newPropertyDefinition(Node key, Node val) { 385 return NodeGeneric; 386 } 387 void addPropertyDefinition(ListNodeType literal, BinaryNodeType propdef) {} 388 [[nodiscard]] bool addPropertyDefinition(ListNodeType literal, Node key, 389 Node expr) { 390 return true; 391 } 392 [[nodiscard]] bool addShorthand(ListNodeType literal, NameNodeType name, 393 NameNodeType expr) { 394 return true; 395 } 396 [[nodiscard]] bool addSpreadProperty(ListNodeType literal, uint32_t begin, 397 Node inner) { 398 return true; 399 } 400 [[nodiscard]] bool addObjectMethodDefinition(ListNodeType literal, Node key, 401 FunctionNodeType funNode, 402 AccessorType atype) { 403 return true; 404 } 405 [[nodiscard]] NodeResult newDefaultClassConstructor( 406 Node key, FunctionNodeType funNode) { 407 return NodeGeneric; 408 } 409 [[nodiscard]] NodeResult newClassMethodDefinition( 410 Node key, FunctionNodeType funNode, AccessorType atype, bool isStatic, 411 mozilla::Maybe<FunctionNodeType> initializerIfPrivate 412 #ifdef ENABLE_DECORATORS 413 , 414 ListNodeType decorators 415 #endif 416 ) { 417 return NodeGeneric; 418 } 419 [[nodiscard]] NodeResult newClassFieldDefinition( 420 Node name, FunctionNodeType initializer, bool isStatic 421 #ifdef ENABLE_DECORATORS 422 , 423 ListNodeType decorators, ClassMethodType accessorGetterNode, 424 ClassMethodType accessorSetterNode 425 #endif 426 ) { 427 return NodeGeneric; 428 } 429 430 [[nodiscard]] NodeResult newStaticClassBlock(FunctionNodeType block) { 431 return NodeGeneric; 432 } 433 434 [[nodiscard]] bool addClassMemberDefinition(ListNodeType memberList, 435 Node member) { 436 return true; 437 } 438 UnaryNodeResult newYieldExpression(uint32_t begin, Node value) { 439 return NodeGeneric; 440 } 441 UnaryNodeResult newYieldStarExpression(uint32_t begin, Node value) { 442 return NodeGeneric; 443 } 444 UnaryNodeResult newAwaitExpression(uint32_t begin, Node value) { 445 return NodeUnparenthesizedUnary; 446 } 447 UnaryNodeResult newOptionalChain(uint32_t begin, Node value) { 448 return NodeGeneric; 449 } 450 451 // Statements 452 453 ListNodeResult newStatementList(const TokenPos& pos) { return NodeGeneric; } 454 void addStatementToList(ListNodeType list, Node stmt) {} 455 void setListEndPosition(ListNodeType list, const TokenPos& pos) {} 456 void addCaseStatementToList(ListNodeType list, CaseClauseType caseClause) {} 457 [[nodiscard]] bool prependInitialYield(ListNodeType stmtList, Node genName) { 458 return true; 459 } 460 NullaryNodeResult newEmptyStatement(const TokenPos& pos) { 461 return NodeEmptyStatement; 462 } 463 464 BinaryNodeResult newImportAttribute(Node keyNode, Node valueNode) { 465 return NodeGeneric; 466 } 467 BinaryNodeResult newModuleRequest(Node moduleSpec, Node importAttributeList, 468 const TokenPos& pos) { 469 return NodeGeneric; 470 } 471 BinaryNodeResult newImportDeclaration(Node importSpecSet, Node moduleRequest, 472 const TokenPos& pos) { 473 return NodeGeneric; 474 } 475 BinaryNodeResult newImportSpec(Node importNameNode, Node bindingName) { 476 return NodeGeneric; 477 } 478 UnaryNodeResult newImportNamespaceSpec(uint32_t begin, Node bindingName) { 479 return NodeGeneric; 480 } 481 UnaryNodeResult newExportDeclaration(Node kid, const TokenPos& pos) { 482 return NodeGeneric; 483 } 484 BinaryNodeResult newExportFromDeclaration(uint32_t begin, Node exportSpecSet, 485 Node moduleRequest) { 486 return NodeGeneric; 487 } 488 BinaryNodeResult newExportDefaultDeclaration(Node kid, Node maybeBinding, 489 const TokenPos& pos) { 490 return NodeGeneric; 491 } 492 BinaryNodeResult newExportSpec(Node bindingName, Node exportName) { 493 return NodeGeneric; 494 } 495 UnaryNodeResult newExportNamespaceSpec(uint32_t begin, Node exportName) { 496 return NodeGeneric; 497 } 498 NullaryNodeResult newExportBatchSpec(const TokenPos& pos) { 499 return NodeGeneric; 500 } 501 BinaryNodeResult newImportMeta(NullaryNodeType importHolder, 502 NullaryNodeType metaHolder) { 503 return NodeGeneric; 504 } 505 BinaryNodeResult newCallImport(NullaryNodeType importHolder, Node singleArg) { 506 return NodeGeneric; 507 } 508 BinaryNodeResult newCallImportSpec(Node specifierArg, Node optionalArg) { 509 return NodeGeneric; 510 } 511 512 BinaryNodeResult newSetThis(Node thisName, Node value) { return value; } 513 514 UnaryNodeResult newExprStatement(Node expr, uint32_t end) { 515 return expr == NodeUnparenthesizedString ? NodeStringExprStatement 516 : NodeGeneric; 517 } 518 519 TernaryNodeResult newIfStatement(uint32_t begin, Node cond, Node thenBranch, 520 Node elseBranch) { 521 return NodeGeneric; 522 } 523 BinaryNodeResult newDoWhileStatement(Node body, Node cond, 524 const TokenPos& pos) { 525 return NodeGeneric; 526 } 527 BinaryNodeResult newWhileStatement(uint32_t begin, Node cond, Node body) { 528 return NodeGeneric; 529 } 530 SwitchStatementResult newSwitchStatement( 531 uint32_t begin, Node discriminant, 532 LexicalScopeNodeType lexicalForCaseList, bool hasDefault) { 533 return NodeGeneric; 534 } 535 CaseClauseResult newCaseOrDefault(uint32_t begin, Node expr, Node body) { 536 return NodeGeneric; 537 } 538 ContinueStatementResult newContinueStatement(TaggedParserAtomIndex label, 539 const TokenPos& pos) { 540 return NodeGeneric; 541 } 542 BreakStatementResult newBreakStatement(TaggedParserAtomIndex label, 543 const TokenPos& pos) { 544 return NodeBreak; 545 } 546 UnaryNodeResult newReturnStatement(Node expr, const TokenPos& pos) { 547 return NodeReturn; 548 } 549 UnaryNodeResult newExpressionBody(Node expr) { return NodeReturn; } 550 BinaryNodeResult newWithStatement(uint32_t begin, Node expr, Node body) { 551 return NodeGeneric; 552 } 553 554 LabeledStatementResult newLabeledStatement(TaggedParserAtomIndex label, 555 Node stmt, uint32_t begin) { 556 return NodeGeneric; 557 } 558 559 UnaryNodeResult newThrowStatement(Node expr, const TokenPos& pos) { 560 return NodeThrow; 561 } 562 TernaryNodeResult newTryStatement(uint32_t begin, Node body, 563 LexicalScopeNodeType catchScope, 564 Node finallyBlock) { 565 return NodeGeneric; 566 } 567 DebuggerStatementResult newDebuggerStatement(const TokenPos& pos) { 568 return NodeGeneric; 569 } 570 571 NameNodeResult newPropertyName(TaggedParserAtomIndex name, 572 const TokenPos& pos) { 573 lastAtom = name; 574 if (name == TaggedParserAtomIndex::WellKnown::length()) { 575 return NodeLengthName; 576 } 577 return NodeGeneric; 578 } 579 580 PropertyAccessResult newPropertyAccess(Node expr, NameNodeType key) { 581 return NodeDottedProperty; 582 } 583 584 PropertyAccessResult newArgumentsLength(Node expr, NameNodeType key) { 585 return NodeArgumentsLength; 586 } 587 588 PropertyAccessResult newOptionalPropertyAccess(Node expr, NameNodeType key) { 589 return NodeOptionalDottedProperty; 590 } 591 592 PropertyByValueResult newPropertyByValue(Node lhs, Node index, uint32_t end) { 593 MOZ_ASSERT(!isPrivateName(index)); 594 return NodeElement; 595 } 596 597 PropertyByValueResult newOptionalPropertyByValue(Node lhs, Node index, 598 uint32_t end) { 599 return NodeOptionalElement; 600 } 601 602 PrivateMemberAccessResult newPrivateMemberAccess(Node lhs, Node privateName, 603 uint32_t end) { 604 return NodePrivateMemberAccess; 605 } 606 607 PrivateMemberAccessResult newOptionalPrivateMemberAccess(Node lhs, 608 Node privateName, 609 uint32_t end) { 610 return NodeOptionalPrivateMemberAccess; 611 } 612 613 [[nodiscard]] bool setupCatchScope(LexicalScopeNodeType lexicalScope, 614 Node catchName, Node catchBody) { 615 return true; 616 } 617 618 [[nodiscard]] bool setLastFunctionFormalParameterDefault( 619 FunctionNodeType funNode, Node defaultValue) { 620 return true; 621 } 622 623 void checkAndSetIsDirectRHSAnonFunction(Node pn) {} 624 625 ParamsBodyNodeResult newParamsBody(const TokenPos& pos) { 626 return NodeGeneric; 627 } 628 629 FunctionNodeResult newFunction(FunctionSyntaxKind syntaxKind, 630 const TokenPos& pos) { 631 switch (syntaxKind) { 632 case FunctionSyntaxKind::Statement: 633 return NodeFunctionStatement; 634 case FunctionSyntaxKind::Arrow: 635 return NodeFunctionArrow; 636 default: 637 // All non-arrow function expressions are initially presumed to have 638 // block body. This will be overridden later *if* the function 639 // expression permissibly has an AssignmentExpression body. 640 return NodeFunctionExpression; 641 } 642 } 643 644 void setFunctionFormalParametersAndBody(FunctionNodeType funNode, 645 ParamsBodyNodeType paramsBody) {} 646 void setFunctionBody(FunctionNodeType funNode, LexicalScopeNodeType body) {} 647 void setFunctionBox(FunctionNodeType funNode, FunctionBox* funbox) {} 648 void addFunctionFormalParameter(FunctionNodeType funNode, Node argpn) {} 649 650 ForNodeResult newForStatement(uint32_t begin, TernaryNodeType forHead, 651 Node body, unsigned iflags) { 652 return NodeGeneric; 653 } 654 655 TernaryNodeResult newForHead(Node init, Node test, Node update, 656 const TokenPos& pos) { 657 return NodeGeneric; 658 } 659 660 TernaryNodeResult newForInOrOfHead(ParseNodeKind kind, Node target, 661 Node iteratedExpr, const TokenPos& pos) { 662 return NodeGeneric; 663 } 664 665 AssignmentNodeResult finishInitializerAssignment(NameNodeType nameNode, 666 Node init) { 667 return NodeUnparenthesizedAssignment; 668 } 669 670 void setBeginPosition(Node pn, Node oth) {} 671 void setBeginPosition(Node pn, uint32_t begin) {} 672 673 void setEndPosition(Node pn, Node oth) {} 674 void setEndPosition(Node pn, uint32_t end) {} 675 676 uint32_t getFunctionNameOffset(Node func, TokenStreamAnyChars& ts) { 677 // XXX This offset isn't relevant to the offending function name. But 678 // we may not *have* that function name around, because of how lazy 679 // parsing works -- the actual name could be outside 680 // |tokenStream.userbuf|'s observed region. So the current offset 681 // is the best we can do. 682 return ts.currentToken().pos.begin; 683 } 684 685 ListNodeResult newList(ParseNodeKind kind, const TokenPos& pos) { 686 MOZ_ASSERT(kind != ParseNodeKind::VarStmt); 687 MOZ_ASSERT(kind != ParseNodeKind::LetDecl); 688 MOZ_ASSERT(kind != ParseNodeKind::ConstDecl); 689 MOZ_ASSERT(kind != ParseNodeKind::ParamsBody); 690 #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT 691 MOZ_ASSERT(kind != ParseNodeKind::UsingDecl); 692 MOZ_ASSERT(kind != ParseNodeKind::AwaitUsingDecl); 693 #endif 694 return NodeGeneric; 695 } 696 697 ListNodeResult newList(ParseNodeKind kind, Node kid) { 698 return newList(kind, TokenPos()); 699 } 700 701 DeclarationListNodeResult newDeclarationList(ParseNodeKind kind, 702 const TokenPos& pos) { 703 if (kind == ParseNodeKind::VarStmt) { 704 return NodeVarDeclaration; 705 } 706 MOZ_ASSERT(kind == ParseNodeKind::LetDecl || 707 kind == ParseNodeKind::ConstDecl 708 #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT 709 || kind == ParseNodeKind::UsingDecl || 710 kind == ParseNodeKind::AwaitUsingDecl 711 #endif 712 ); 713 return NodeLexicalDeclaration; 714 } 715 716 ListNodeResult newCommaExpressionList(Node kid) { return NodeGeneric; } 717 718 void addList(ListNodeType list, Node kid) { 719 MOZ_ASSERT(list == NodeGeneric || list == NodeUnparenthesizedArray || 720 list == NodeUnparenthesizedObject || 721 list == NodeVarDeclaration || list == NodeLexicalDeclaration || 722 list == NodeFunctionCall); 723 } 724 725 CallNodeResult newNewExpression(uint32_t begin, Node ctor, ListNodeType args, 726 bool isSpread) { 727 return NodeGeneric; 728 } 729 730 AssignmentNodeResult newAssignment(ParseNodeKind kind, Node lhs, Node rhs) { 731 return kind == ParseNodeKind::AssignExpr ? NodeUnparenthesizedAssignment 732 : NodeGeneric; 733 } 734 735 AssignmentNodeResult newInitExpr(Node lhs, Node rhs) { return NodeGeneric; } 736 737 bool isUnparenthesizedAssignment(Node node) { 738 return node == NodeUnparenthesizedAssignment; 739 } 740 741 bool isUnparenthesizedUnaryExpression(Node node) { 742 return node == NodeUnparenthesizedUnary; 743 } 744 745 bool isReturnStatement(Node node) { return node == NodeReturn; } 746 747 bool isStatementPermittedAfterReturnStatement(Node pn) { 748 return pn == NodeFunctionStatement || isNonArrowFunctionExpression(pn) || 749 pn == NodeVarDeclaration || pn == NodeBreak || pn == NodeThrow || 750 pn == NodeEmptyStatement; 751 } 752 753 bool isSuperBase(Node pn) { return pn == NodeSuperBase; } 754 755 void setListHasNonConstInitializer(ListNodeType literal) {} 756 757 // NOTE: This is infallible. 758 [[nodiscard]] Node parenthesize(Node node) { 759 // A number of nodes have different behavior upon parenthesization, but 760 // only in some circumstances. Convert these nodes to special 761 // parenthesized forms. 762 if (node == NodeUnparenthesizedArray) { 763 return NodeParenthesizedArray; 764 } 765 if (node == NodeUnparenthesizedObject) { 766 return NodeParenthesizedObject; 767 } 768 769 // Other nodes need not be recognizable after parenthesization; convert 770 // them to a generic node. 771 if (node == NodeUnparenthesizedString || 772 node == NodeUnparenthesizedAssignment || 773 node == NodeUnparenthesizedUnary) { 774 return NodeGeneric; 775 } 776 777 // Convert parenthesized |async| to a normal name node. 778 if (node == NodePotentialAsyncKeyword) { 779 return NodeName; 780 } 781 782 // In all other cases, the parenthesized form of |node| is equivalent 783 // to the unparenthesized form: return |node| unchanged. 784 return node; 785 } 786 787 // NOTE: This is infallible. 788 template <typename NodeType> 789 [[nodiscard]] NodeType setLikelyIIFE(NodeType node) { 790 return node; // Remain in syntax-parse mode. 791 } 792 793 bool isName(Node node) { 794 return node == NodeName || node == NodeArgumentsName || 795 node == NodeLengthName || node == NodeEvalName || 796 node == NodePotentialAsyncKeyword; 797 } 798 799 bool isArgumentsName(Node node) { return node == NodeArgumentsName; } 800 bool isLengthName(Node node) { return node == NodeLengthName; } 801 bool isEvalName(Node node) { return node == NodeEvalName; } 802 bool isAsyncKeyword(Node node) { return node == NodePotentialAsyncKeyword; } 803 804 bool isArgumentsLength(Node node) { return node == NodeArgumentsLength; } 805 806 bool isPrivateName(Node node) { return node == NodePrivateName; } 807 bool isPrivateMemberAccess(Node node) { 808 return node == NodePrivateMemberAccess; 809 } 810 811 TaggedParserAtomIndex maybeDottedProperty(Node node) { 812 // Note: |super.apply(...)| is a special form that calls an "apply" 813 // method retrieved from one value, but using a *different* value as 814 // |this|. It's not really eligible for the funapply/funcall 815 // optimizations as they're currently implemented (assuming a single 816 // value is used for both retrieval and |this|). 817 if (node != NodeDottedProperty && node != NodeOptionalDottedProperty && 818 node != NodeArgumentsLength) { 819 return TaggedParserAtomIndex::null(); 820 } 821 return lastAtom; 822 } 823 824 TaggedParserAtomIndex isStringExprStatement(Node pn, TokenPos* pos) { 825 if (pn == NodeStringExprStatement) { 826 *pos = lastStringPos; 827 return lastAtom; 828 } 829 return TaggedParserAtomIndex::null(); 830 } 831 832 bool reuseLazyInnerFunctions() { return false; } 833 bool reuseClosedOverBindings() { return false; } 834 TaggedParserAtomIndex nextLazyClosedOverBinding() { 835 MOZ_CRASH( 836 "SyntaxParseHandler::canSkipLazyClosedOverBindings must return false"); 837 } 838 839 void setPrivateNameKind(Node node, PrivateNameKind kind) {} 840 }; 841 842 } // namespace frontend 843 } // namespace js 844 845 #endif /* frontend_SyntaxParseHandler_h */