FullParseHandler.h (44614B)
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_FullParseHandler_h 8 #define frontend_FullParseHandler_h 9 10 #include "mozilla/Maybe.h" // mozilla::Maybe 11 #include "mozilla/Result.h" // mozilla::Result, mozilla::UnusedZero 12 #include "mozilla/Try.h" // MOZ_TRY* 13 14 #include <cstddef> // std::nullptr_t 15 #include <string.h> 16 17 #include "jstypes.h" 18 19 #include "frontend/CompilationStencil.h" // CompilationState 20 #include "frontend/FunctionSyntaxKind.h" // FunctionSyntaxKind 21 #include "frontend/NameAnalysisTypes.h" // PrivateNameKind 22 #include "frontend/ParseNode.h" 23 #include "frontend/Parser-macros.h" // MOZ_TRY_VAR_OR_RETURN 24 #include "frontend/ParserAtom.h" // TaggedParserAtomIndex 25 #include "frontend/SharedContext.h" 26 #include "frontend/Stencil.h" 27 28 template <> 29 struct mozilla::detail::UnusedZero<js::frontend::ParseNode*> { 30 static const bool value = true; 31 }; 32 33 #define DEFINE_UNUSED_ZERO(typeName) \ 34 template <> \ 35 struct mozilla::detail::UnusedZero<js::frontend::typeName*> { \ 36 static const bool value = true; \ 37 }; 38 FOR_EACH_PARSENODE_SUBCLASS(DEFINE_UNUSED_ZERO) 39 #undef DEFINE_UNUSED_ZERO 40 41 namespace js { 42 namespace frontend { 43 44 class TokenStreamAnyChars; 45 46 // Parse handler used when generating a full parse tree for all code which the 47 // parser encounters. 48 class FullParseHandler { 49 ParseNodeAllocator allocator; 50 51 ParseNode* allocParseNode(size_t size) { 52 return static_cast<ParseNode*>(allocator.allocNode(size)); 53 } 54 55 // If this is a full parse to construct the bytecode for a function that 56 // was previously lazily parsed, we still don't want to full parse the 57 // inner functions. These members are used for this functionality: 58 // 59 // - reuseGCThings if ture it means that the following fields are valid. 60 // - gcThingsData holds an incomplete stencil-like copy of inner functions as 61 // well as atoms. 62 // - scriptData and scriptExtra_ hold information necessary to locate inner 63 // functions to skip over each. 64 // - lazyInnerFunctionIndex is used as we skip over inner functions 65 // (see skipLazyInnerFunction), 66 // - lazyClosedOverBindingIndex is used to synchronize binding computation 67 // with the scope traversal. 68 // (see propagateFreeNamesAndMarkClosedOverBindings), 69 const CompilationSyntaxParseCache& previousParseCache_; 70 71 size_t lazyInnerFunctionIndex; 72 size_t lazyClosedOverBindingIndex; 73 74 bool reuseGCThings; 75 76 /* new_ methods for creating parse nodes. These report OOM on context. */ 77 JS_DECLARE_NEW_METHODS(new_, allocParseNode, inline) 78 79 public: 80 using NodeError = ParseNodeError; 81 82 using Node = ParseNode*; 83 using NodeResult = ParseNodeResult; 84 using NodeErrorResult = mozilla::GenericErrorResult<NodeError>; 85 86 #define DECLARE_TYPE(typeName) \ 87 using typeName##Type = typeName*; \ 88 using typeName##Result = mozilla::Result<typeName*, NodeError>; 89 FOR_EACH_PARSENODE_SUBCLASS(DECLARE_TYPE) 90 #undef DECLARE_TYPE 91 92 template <class T, typename... Args> 93 inline mozilla::Result<T*, NodeError> newResult(Args&&... args) { 94 auto* node = new_<T>(std::forward<Args>(args)...); 95 if (!node) { 96 return mozilla::Result<T*, NodeError>(NodeError()); 97 } 98 return node; 99 } 100 101 using NullNode = std::nullptr_t; 102 103 bool isPropertyOrPrivateMemberAccess(Node node) { 104 return node->isKind(ParseNodeKind::DotExpr) || 105 node->isKind(ParseNodeKind::ElemExpr) || 106 node->isKind(ParseNodeKind::PrivateMemberExpr) || 107 node->isKind(ParseNodeKind::ArgumentsLength); 108 } 109 110 bool isOptionalPropertyOrPrivateMemberAccess(Node node) { 111 return node->isKind(ParseNodeKind::OptionalDotExpr) || 112 node->isKind(ParseNodeKind::OptionalElemExpr) || 113 node->isKind(ParseNodeKind::PrivateMemberExpr); 114 } 115 116 bool isFunctionCall(Node node) { 117 // Note: super() is a special form, *not* a function call. 118 return node->isKind(ParseNodeKind::CallExpr); 119 } 120 121 static bool isUnparenthesizedDestructuringPattern(Node node) { 122 return !node->isInParens() && (node->isKind(ParseNodeKind::ObjectExpr) || 123 node->isKind(ParseNodeKind::ArrayExpr)); 124 } 125 126 static bool isParenthesizedDestructuringPattern(Node node) { 127 // Technically this isn't a destructuring pattern at all -- the grammar 128 // doesn't treat it as such. But we need to know when this happens to 129 // consider it a SyntaxError rather than an invalid-left-hand-side 130 // ReferenceError. 131 return node->isInParens() && (node->isKind(ParseNodeKind::ObjectExpr) || 132 node->isKind(ParseNodeKind::ArrayExpr)); 133 } 134 135 FullParseHandler(FrontendContext* fc, CompilationState& compilationState) 136 : allocator(fc, compilationState.parserAllocScope.alloc()), 137 previousParseCache_(compilationState.previousParseCache), 138 lazyInnerFunctionIndex(0), 139 lazyClosedOverBindingIndex(0), 140 reuseGCThings(compilationState.input.isDelazifying()) {} 141 142 static NullNode null() { return NullNode(); } 143 static constexpr NodeErrorResult errorResult() { 144 return NodeErrorResult(NodeError()); 145 } 146 147 #define DECLARE_AS(typeName) \ 148 static typeName##Type as##typeName(Node node) { \ 149 return &node->as<typeName>(); \ 150 } 151 FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS) 152 #undef DECLARE_AS 153 154 NameNodeResult newName(TaggedParserAtomIndex name, const TokenPos& pos) { 155 return newResult<NameNode>(ParseNodeKind::Name, name, pos); 156 } 157 158 UnaryNodeResult newComputedName(Node expr, uint32_t begin, uint32_t end) { 159 TokenPos pos(begin, end); 160 return newResult<UnaryNode>(ParseNodeKind::ComputedName, pos, expr); 161 } 162 163 UnaryNodeResult newSyntheticComputedName(Node expr, uint32_t begin, 164 uint32_t end) { 165 TokenPos pos(begin, end); 166 UnaryNode* node = 167 MOZ_TRY(newResult<UnaryNode>(ParseNodeKind::ComputedName, pos, expr)); 168 node->setSyntheticComputedName(); 169 return node; 170 } 171 172 NameNodeResult newObjectLiteralPropertyName(TaggedParserAtomIndex atom, 173 const TokenPos& pos) { 174 return newResult<NameNode>(ParseNodeKind::ObjectPropertyName, atom, pos); 175 } 176 177 NameNodeResult newPrivateName(TaggedParserAtomIndex atom, 178 const TokenPos& pos) { 179 return newResult<NameNode>(ParseNodeKind::PrivateName, atom, pos); 180 } 181 182 NumericLiteralResult newNumber(double value, DecimalPoint decimalPoint, 183 const TokenPos& pos) { 184 return newResult<NumericLiteral>(value, decimalPoint, pos); 185 } 186 187 BigIntLiteralResult newBigInt(BigIntIndex index, const TokenPos& pos) { 188 return newResult<BigIntLiteral>(index, pos); 189 } 190 191 BooleanLiteralResult newBooleanLiteral(bool cond, const TokenPos& pos) { 192 return newResult<BooleanLiteral>(cond, pos); 193 } 194 195 NameNodeResult newStringLiteral(TaggedParserAtomIndex atom, 196 const TokenPos& pos) { 197 return newResult<NameNode>(ParseNodeKind::StringExpr, atom, pos); 198 } 199 200 NameNodeResult newTemplateStringLiteral(TaggedParserAtomIndex atom, 201 const TokenPos& pos) { 202 return newResult<NameNode>(ParseNodeKind::TemplateStringExpr, atom, pos); 203 } 204 205 CallSiteNodeResult newCallSiteObject(uint32_t begin) { 206 CallSiteNode* callSiteObj = MOZ_TRY(newResult<CallSiteNode>(begin)); 207 208 ListNode* rawNodes = MOZ_TRY(newArrayLiteral(callSiteObj->pn_pos.begin)); 209 210 addArrayElement(callSiteObj, rawNodes); 211 212 return callSiteObj; 213 } 214 215 void addToCallSiteObject(CallSiteNodeType callSiteObj, Node rawNode, 216 Node cookedNode) { 217 MOZ_ASSERT(callSiteObj->isKind(ParseNodeKind::CallSiteObj)); 218 MOZ_ASSERT(rawNode->isKind(ParseNodeKind::TemplateStringExpr)); 219 MOZ_ASSERT(cookedNode->isKind(ParseNodeKind::TemplateStringExpr) || 220 cookedNode->isKind(ParseNodeKind::RawUndefinedExpr)); 221 222 addArrayElement(callSiteObj, cookedNode); 223 addArrayElement(callSiteObj->rawNodes(), rawNode); 224 225 /* 226 * We don't know when the last noSubstTemplate will come in, and we 227 * don't want to deal with this outside this method 228 */ 229 setEndPosition(callSiteObj, callSiteObj->rawNodes()); 230 } 231 232 ThisLiteralResult newThisLiteral(const TokenPos& pos, Node thisName) { 233 return newResult<ThisLiteral>(pos, thisName); 234 } 235 236 NullLiteralResult newNullLiteral(const TokenPos& pos) { 237 return newResult<NullLiteral>(pos); 238 } 239 240 RawUndefinedLiteralResult newRawUndefinedLiteral(const TokenPos& pos) { 241 return newResult<RawUndefinedLiteral>(pos); 242 } 243 244 RegExpLiteralResult newRegExp(RegExpIndex index, const TokenPos& pos) { 245 return newResult<RegExpLiteral>(index, pos); 246 } 247 248 ConditionalExpressionResult newConditional(Node cond, Node thenExpr, 249 Node elseExpr) { 250 return newResult<ConditionalExpression>(cond, thenExpr, elseExpr); 251 } 252 253 UnaryNodeResult newDelete(uint32_t begin, Node expr) { 254 if (expr->isKind(ParseNodeKind::Name)) { 255 return newUnary(ParseNodeKind::DeleteNameExpr, begin, expr); 256 } 257 258 if (expr->isKind(ParseNodeKind::DotExpr)) { 259 return newUnary(ParseNodeKind::DeletePropExpr, begin, expr); 260 } 261 262 if (expr->isKind(ParseNodeKind::ElemExpr)) { 263 return newUnary(ParseNodeKind::DeleteElemExpr, begin, expr); 264 } 265 266 if (expr->isKind(ParseNodeKind::OptionalChain)) { 267 Node kid = expr->as<UnaryNode>().kid(); 268 // Handle property deletion explicitly. OptionalCall is handled 269 // via DeleteExpr. 270 if (kid->isKind(ParseNodeKind::DotExpr) || 271 kid->isKind(ParseNodeKind::OptionalDotExpr) || 272 kid->isKind(ParseNodeKind::ElemExpr) || 273 kid->isKind(ParseNodeKind::OptionalElemExpr)) { 274 return newUnary(ParseNodeKind::DeleteOptionalChainExpr, begin, kid); 275 } 276 } 277 278 return newUnary(ParseNodeKind::DeleteExpr, begin, expr); 279 } 280 281 UnaryNodeResult newTypeof(uint32_t begin, Node kid) { 282 ParseNodeKind pnk = kid->isKind(ParseNodeKind::Name) 283 ? ParseNodeKind::TypeOfNameExpr 284 : ParseNodeKind::TypeOfExpr; 285 return newUnary(pnk, begin, kid); 286 } 287 288 UnaryNodeResult newUnary(ParseNodeKind kind, uint32_t begin, Node kid) { 289 TokenPos pos(begin, kid->pn_pos.end); 290 return newResult<UnaryNode>(kind, pos, kid); 291 } 292 293 UnaryNodeResult newUpdate(ParseNodeKind kind, uint32_t begin, Node kid) { 294 TokenPos pos(begin, kid->pn_pos.end); 295 return newResult<UnaryNode>(kind, pos, kid); 296 } 297 298 UnaryNodeResult newSpread(uint32_t begin, Node kid) { 299 TokenPos pos(begin, kid->pn_pos.end); 300 return newResult<UnaryNode>(ParseNodeKind::Spread, pos, kid); 301 } 302 303 private: 304 BinaryNodeResult newBinary(ParseNodeKind kind, Node left, Node right) { 305 TokenPos pos(left->pn_pos.begin, right->pn_pos.end); 306 return newResult<BinaryNode>(kind, pos, left, right); 307 } 308 309 public: 310 NodeResult appendOrCreateList(ParseNodeKind kind, Node left, Node right, 311 ParseContext* pc) { 312 return ParseNode::appendOrCreateList(kind, left, right, this, pc); 313 } 314 315 // Expressions 316 317 ListNodeResult newArrayLiteral(uint32_t begin) { 318 return newResult<ListNode>(ParseNodeKind::ArrayExpr, 319 TokenPos(begin, begin + 1)); 320 } 321 322 [[nodiscard]] bool addElision(ListNodeType literal, const TokenPos& pos) { 323 MOZ_ASSERT(literal->isKind(ParseNodeKind::ArrayExpr)); 324 325 NullaryNode* elision; 326 MOZ_TRY_VAR_OR_RETURN( 327 elision, newResult<NullaryNode>(ParseNodeKind::Elision, pos), false); 328 addList(/* list = */ literal, /* kid = */ elision); 329 literal->setHasNonConstInitializer(); 330 return true; 331 } 332 333 [[nodiscard]] bool addSpreadElement(ListNodeType literal, uint32_t begin, 334 Node inner) { 335 MOZ_ASSERT(literal->isKind(ParseNodeKind::ArrayExpr)); 336 337 UnaryNodeType spread; 338 MOZ_TRY_VAR_OR_RETURN(spread, newSpread(begin, inner), false); 339 addList(/* list = */ literal, /* kid = */ spread); 340 literal->setHasNonConstInitializer(); 341 return true; 342 } 343 344 void addArrayElement(ListNodeType literal, Node element) { 345 MOZ_ASSERT(literal->isKind(ParseNodeKind::ArrayExpr) || 346 literal->isKind(ParseNodeKind::CallSiteObj)); 347 if (!element->isConstant()) { 348 literal->setHasNonConstInitializer(); 349 } 350 addList(/* list = */ literal, /* kid = */ element); 351 } 352 353 CallNodeResult newCall(Node callee, ListNodeType args, JSOp callOp) { 354 return newResult<CallNode>(ParseNodeKind::CallExpr, callOp, callee, args); 355 } 356 357 CallNodeResult newOptionalCall(Node callee, ListNodeType args, JSOp callOp) { 358 return newResult<CallNode>(ParseNodeKind::OptionalCallExpr, callOp, callee, 359 args); 360 } 361 362 ListNodeResult newArguments(const TokenPos& pos) { 363 return newResult<ListNode>(ParseNodeKind::Arguments, pos); 364 } 365 366 CallNodeResult newSuperCall(Node callee, ListNodeType args, bool isSpread) { 367 return newResult<CallNode>( 368 ParseNodeKind::SuperCallExpr, 369 isSpread ? JSOp::SpreadSuperCall : JSOp::SuperCall, callee, args); 370 } 371 372 CallNodeResult newTaggedTemplate(Node tag, ListNodeType args, JSOp callOp) { 373 return newResult<CallNode>(ParseNodeKind::TaggedTemplateExpr, callOp, tag, 374 args); 375 } 376 377 ListNodeResult newObjectLiteral(uint32_t begin) { 378 return newResult<ListNode>(ParseNodeKind::ObjectExpr, 379 TokenPos(begin, begin + 1)); 380 } 381 382 ClassNodeResult newClass(Node name, Node heritage, 383 LexicalScopeNodeType memberBlock, 384 #ifdef ENABLE_DECORATORS 385 ListNodeType decorators, 386 FunctionNodeType addInitializerFunction, 387 #endif 388 const TokenPos& pos) { 389 return newResult<ClassNode>(name, heritage, memberBlock, 390 #ifdef ENABLE_DECORATORS 391 decorators, addInitializerFunction, 392 #endif 393 pos); 394 } 395 ListNodeResult newClassMemberList(uint32_t begin) { 396 return newResult<ListNode>(ParseNodeKind::ClassMemberList, 397 TokenPos(begin, begin + 1)); 398 } 399 ClassNamesResult newClassNames(Node outer, Node inner, const TokenPos& pos) { 400 return newResult<ClassNames>(outer, inner, pos); 401 } 402 NewTargetNodeResult newNewTarget(NullaryNodeType newHolder, 403 NullaryNodeType targetHolder, 404 NameNodeType newTargetName) { 405 return newResult<NewTargetNode>(newHolder, targetHolder, newTargetName); 406 } 407 NullaryNodeResult newPosHolder(const TokenPos& pos) { 408 return newResult<NullaryNode>(ParseNodeKind::PosHolder, pos); 409 } 410 UnaryNodeResult newSuperBase(Node thisName, const TokenPos& pos) { 411 return newResult<UnaryNode>(ParseNodeKind::SuperBase, pos, thisName); 412 } 413 [[nodiscard]] bool addPrototypeMutation(ListNodeType literal, uint32_t begin, 414 Node expr) { 415 MOZ_ASSERT(literal->isKind(ParseNodeKind::ObjectExpr)); 416 417 // Object literals with mutated [[Prototype]] are non-constant so that 418 // singleton objects will have Object.prototype as their [[Prototype]]. 419 literal->setHasNonConstInitializer(); 420 421 UnaryNode* mutation; 422 MOZ_TRY_VAR_OR_RETURN( 423 mutation, newUnary(ParseNodeKind::MutateProto, begin, expr), false); 424 addList(/* list = */ literal, /* kid = */ mutation); 425 return true; 426 } 427 428 BinaryNodeResult newPropertyDefinition(Node key, Node val) { 429 MOZ_ASSERT(isUsableAsObjectPropertyName(key)); 430 checkAndSetIsDirectRHSAnonFunction(val); 431 return newResult<PropertyDefinition>(key, val, AccessorType::None); 432 } 433 434 void addPropertyDefinition(ListNodeType literal, BinaryNodeType propdef) { 435 MOZ_ASSERT(literal->isKind(ParseNodeKind::ObjectExpr)); 436 MOZ_ASSERT(propdef->isKind(ParseNodeKind::PropertyDefinition)); 437 438 if (!propdef->right()->isConstant()) { 439 literal->setHasNonConstInitializer(); 440 } 441 442 addList(/* list = */ literal, /* kid = */ propdef); 443 } 444 445 [[nodiscard]] bool addPropertyDefinition(ListNodeType literal, Node key, 446 Node val) { 447 BinaryNode* propdef; 448 MOZ_TRY_VAR_OR_RETURN(propdef, newPropertyDefinition(key, val), false); 449 addPropertyDefinition(literal, propdef); 450 return true; 451 } 452 453 [[nodiscard]] bool addShorthand(ListNodeType literal, NameNodeType name, 454 NameNodeType expr) { 455 MOZ_ASSERT(literal->isKind(ParseNodeKind::ObjectExpr)); 456 MOZ_ASSERT(name->isKind(ParseNodeKind::ObjectPropertyName)); 457 MOZ_ASSERT(expr->isKind(ParseNodeKind::Name)); 458 MOZ_ASSERT(name->atom() == expr->atom()); 459 460 literal->setHasNonConstInitializer(); 461 BinaryNode* propdef; 462 MOZ_TRY_VAR_OR_RETURN( 463 propdef, newBinary(ParseNodeKind::Shorthand, name, expr), false); 464 addList(/* list = */ literal, /* kid = */ propdef); 465 return true; 466 } 467 468 [[nodiscard]] bool addSpreadProperty(ListNodeType literal, uint32_t begin, 469 Node inner) { 470 MOZ_ASSERT(literal->isKind(ParseNodeKind::ObjectExpr)); 471 472 literal->setHasNonConstInitializer(); 473 ParseNode* spread; 474 MOZ_TRY_VAR_OR_RETURN(spread, newSpread(begin, inner), false); 475 addList(/* list = */ literal, /* kid = */ spread); 476 return true; 477 } 478 479 [[nodiscard]] bool addObjectMethodDefinition(ListNodeType literal, Node key, 480 FunctionNodeType funNode, 481 AccessorType atype) { 482 literal->setHasNonConstInitializer(); 483 484 checkAndSetIsDirectRHSAnonFunction(funNode); 485 486 ParseNode* propdef; 487 MOZ_TRY_VAR_OR_RETURN( 488 propdef, newObjectMethodOrPropertyDefinition(key, funNode, atype), 489 false); 490 addList(/* list = */ literal, /* kid = */ propdef); 491 return true; 492 } 493 494 [[nodiscard]] ClassMethodResult newDefaultClassConstructor( 495 Node key, FunctionNodeType funNode) { 496 MOZ_ASSERT(isUsableAsObjectPropertyName(key)); 497 498 checkAndSetIsDirectRHSAnonFunction(funNode); 499 500 return newResult<ClassMethod>( 501 ParseNodeKind::DefaultConstructor, key, funNode, AccessorType::None, 502 /* isStatic = */ false, /* initializeIfPrivate = */ nullptr 503 #ifdef ENABLE_DECORATORS 504 , 505 /* decorators = */ nullptr 506 #endif 507 ); 508 } 509 510 [[nodiscard]] ClassMethodResult newClassMethodDefinition( 511 Node key, FunctionNodeType funNode, AccessorType atype, bool isStatic, 512 mozilla::Maybe<FunctionNodeType> initializerIfPrivate 513 #ifdef ENABLE_DECORATORS 514 , 515 ListNodeType decorators 516 #endif 517 ) { 518 MOZ_ASSERT(isUsableAsObjectPropertyName(key)); 519 520 checkAndSetIsDirectRHSAnonFunction(funNode); 521 522 if (initializerIfPrivate.isSome()) { 523 return newResult<ClassMethod>(ParseNodeKind::ClassMethod, key, funNode, 524 atype, isStatic, 525 initializerIfPrivate.value() 526 #ifdef ENABLE_DECORATORS 527 , 528 decorators 529 #endif 530 ); 531 } 532 return newResult<ClassMethod>(ParseNodeKind::ClassMethod, key, funNode, 533 atype, isStatic, 534 /* initializeIfPrivate = */ nullptr 535 #ifdef ENABLE_DECORATORS 536 , 537 decorators 538 #endif 539 ); 540 } 541 542 [[nodiscard]] ClassFieldResult newClassFieldDefinition( 543 Node name, FunctionNodeType initializer, bool isStatic 544 #ifdef ENABLE_DECORATORS 545 , 546 ListNodeType decorators, ClassMethodType accessorGetterNode, 547 ClassMethodType accessorSetterNode 548 #endif 549 ) { 550 MOZ_ASSERT(isUsableAsObjectPropertyName(name)); 551 552 return newResult<ClassField>(name, initializer, isStatic 553 #if ENABLE_DECORATORS 554 , 555 decorators, accessorGetterNode, 556 accessorSetterNode 557 #endif 558 ); 559 } 560 561 [[nodiscard]] StaticClassBlockResult newStaticClassBlock( 562 FunctionNodeType block) { 563 return newResult<StaticClassBlock>(block); 564 } 565 566 [[nodiscard]] bool addClassMemberDefinition(ListNodeType memberList, 567 Node member) { 568 MOZ_ASSERT(memberList->isKind(ParseNodeKind::ClassMemberList)); 569 // Constructors can be surrounded by LexicalScopes. 570 MOZ_ASSERT(member->isKind(ParseNodeKind::DefaultConstructor) || 571 member->isKind(ParseNodeKind::ClassMethod) || 572 member->isKind(ParseNodeKind::ClassField) || 573 member->isKind(ParseNodeKind::StaticClassBlock) || 574 (member->isKind(ParseNodeKind::LexicalScope) && 575 member->as<LexicalScopeNode>().scopeBody()->is<ClassMethod>())); 576 577 addList(/* list = */ memberList, /* kid = */ member); 578 return true; 579 } 580 581 UnaryNodeResult newInitialYieldExpression(uint32_t begin, Node gen) { 582 TokenPos pos(begin, begin + 1); 583 return newResult<UnaryNode>(ParseNodeKind::InitialYield, pos, gen); 584 } 585 586 UnaryNodeResult newYieldExpression(uint32_t begin, Node value) { 587 TokenPos pos(begin, value ? value->pn_pos.end : begin + 1); 588 return newResult<UnaryNode>(ParseNodeKind::YieldExpr, pos, value); 589 } 590 591 UnaryNodeResult newYieldStarExpression(uint32_t begin, Node value) { 592 TokenPos pos(begin, value->pn_pos.end); 593 return newResult<UnaryNode>(ParseNodeKind::YieldStarExpr, pos, value); 594 } 595 596 UnaryNodeResult newAwaitExpression(uint32_t begin, Node value) { 597 TokenPos pos(begin, value ? value->pn_pos.end : begin + 1); 598 return newResult<UnaryNode>(ParseNodeKind::AwaitExpr, pos, value); 599 } 600 601 UnaryNodeResult newOptionalChain(uint32_t begin, Node value) { 602 TokenPos pos(begin, value->pn_pos.end); 603 return newResult<UnaryNode>(ParseNodeKind::OptionalChain, pos, value); 604 } 605 606 // Statements 607 608 ListNodeResult newStatementList(const TokenPos& pos) { 609 return newResult<ListNode>(ParseNodeKind::StatementList, pos); 610 } 611 612 [[nodiscard]] bool isFunctionStmt(Node stmt) { 613 while (stmt->isKind(ParseNodeKind::LabelStmt)) { 614 stmt = stmt->as<LabeledStatement>().statement(); 615 } 616 return stmt->is<FunctionNode>(); 617 } 618 619 void addStatementToList(ListNodeType list, Node stmt) { 620 MOZ_ASSERT(list->isKind(ParseNodeKind::StatementList)); 621 622 addList(/* list = */ list, /* kid = */ stmt); 623 624 if (isFunctionStmt(stmt)) { 625 // Notify the emitter that the block contains body-level function 626 // definitions that should be processed before the rest of nodes. 627 list->setHasTopLevelFunctionDeclarations(); 628 } 629 } 630 631 void setListEndPosition(ListNodeType list, const TokenPos& pos) { 632 MOZ_ASSERT(list->isKind(ParseNodeKind::StatementList)); 633 list->pn_pos.end = pos.end; 634 } 635 636 void addCaseStatementToList(ListNodeType list, CaseClauseType caseClause) { 637 MOZ_ASSERT(list->isKind(ParseNodeKind::StatementList)); 638 639 addList(/* list = */ list, /* kid = */ caseClause); 640 641 if (caseClause->statementList()->hasTopLevelFunctionDeclarations()) { 642 list->setHasTopLevelFunctionDeclarations(); 643 } 644 } 645 646 [[nodiscard]] bool prependInitialYield(ListNodeType stmtList, Node genName) { 647 MOZ_ASSERT(stmtList->isKind(ParseNodeKind::StatementList)); 648 649 TokenPos yieldPos(stmtList->pn_pos.begin, stmtList->pn_pos.begin + 1); 650 NullaryNode* makeGen; 651 MOZ_TRY_VAR_OR_RETURN( 652 makeGen, newResult<NullaryNode>(ParseNodeKind::Generator, yieldPos), 653 false); 654 655 ParseNode* genInit; 656 MOZ_TRY_VAR_OR_RETURN( 657 genInit, 658 newAssignment(ParseNodeKind::AssignExpr, /* lhs = */ genName, 659 /* rhs = */ makeGen), 660 false); 661 662 UnaryNode* initialYield; 663 MOZ_TRY_VAR_OR_RETURN(initialYield, 664 newInitialYieldExpression(yieldPos.begin, genInit), 665 false); 666 667 stmtList->prepend(initialYield); 668 return true; 669 } 670 671 BinaryNodeResult newSetThis(Node thisName, Node value) { 672 return newBinary(ParseNodeKind::SetThis, thisName, value); 673 } 674 675 NullaryNodeResult newEmptyStatement(const TokenPos& pos) { 676 return newResult<NullaryNode>(ParseNodeKind::EmptyStmt, pos); 677 } 678 679 BinaryNodeResult newImportAttribute(Node keyNode, Node valueNode) { 680 return newBinary(ParseNodeKind::ImportAttribute, keyNode, valueNode); 681 } 682 683 BinaryNodeResult newModuleRequest(Node moduleSpec, Node importAttributeList, 684 const TokenPos& pos) { 685 return newResult<BinaryNode>(ParseNodeKind::ImportModuleRequest, pos, 686 moduleSpec, importAttributeList); 687 } 688 689 BinaryNodeResult newImportDeclaration(Node importSpecSet, Node moduleRequest, 690 const TokenPos& pos) { 691 return newResult<BinaryNode>(ParseNodeKind::ImportDecl, pos, importSpecSet, 692 moduleRequest); 693 } 694 695 BinaryNodeResult newImportSpec(Node importNameNode, Node bindingName) { 696 return newBinary(ParseNodeKind::ImportSpec, importNameNode, bindingName); 697 } 698 699 UnaryNodeResult newImportNamespaceSpec(uint32_t begin, Node bindingName) { 700 return newUnary(ParseNodeKind::ImportNamespaceSpec, begin, bindingName); 701 } 702 703 UnaryNodeResult newExportDeclaration(Node kid, const TokenPos& pos) { 704 return newResult<UnaryNode>(ParseNodeKind::ExportStmt, pos, kid); 705 } 706 707 BinaryNodeResult newExportFromDeclaration(uint32_t begin, Node exportSpecSet, 708 Node moduleRequest) { 709 BinaryNode* decl = MOZ_TRY(newResult<BinaryNode>( 710 ParseNodeKind::ExportFromStmt, exportSpecSet, moduleRequest)); 711 decl->pn_pos.begin = begin; 712 return decl; 713 } 714 715 BinaryNodeResult newExportDefaultDeclaration(Node kid, Node maybeBinding, 716 const TokenPos& pos) { 717 if (maybeBinding) { 718 MOZ_ASSERT(maybeBinding->isKind(ParseNodeKind::Name)); 719 MOZ_ASSERT(!maybeBinding->isInParens()); 720 721 checkAndSetIsDirectRHSAnonFunction(kid); 722 } 723 724 return newResult<BinaryNode>(ParseNodeKind::ExportDefaultStmt, pos, kid, 725 maybeBinding); 726 } 727 728 BinaryNodeResult newExportSpec(Node bindingName, Node exportName) { 729 return newBinary(ParseNodeKind::ExportSpec, bindingName, exportName); 730 } 731 732 UnaryNodeResult newExportNamespaceSpec(uint32_t begin, Node exportName) { 733 return newUnary(ParseNodeKind::ExportNamespaceSpec, begin, exportName); 734 } 735 736 NullaryNodeResult newExportBatchSpec(const TokenPos& pos) { 737 return newResult<NullaryNode>(ParseNodeKind::ExportBatchSpecStmt, pos); 738 } 739 740 BinaryNodeResult newImportMeta(NullaryNodeType importHolder, 741 NullaryNodeType metaHolder) { 742 return newResult<BinaryNode>(ParseNodeKind::ImportMetaExpr, importHolder, 743 metaHolder); 744 } 745 746 BinaryNodeResult newCallImport(NullaryNodeType importHolder, Node singleArg) { 747 return newResult<BinaryNode>(ParseNodeKind::CallImportExpr, importHolder, 748 singleArg); 749 } 750 751 BinaryNodeResult newCallImportSpec(Node specifierArg, Node optionalArg) { 752 return newResult<BinaryNode>(ParseNodeKind::CallImportSpec, specifierArg, 753 optionalArg); 754 } 755 756 UnaryNodeResult newExprStatement(Node expr, uint32_t end) { 757 MOZ_ASSERT(expr->pn_pos.end <= end); 758 return newResult<UnaryNode>(ParseNodeKind::ExpressionStmt, 759 TokenPos(expr->pn_pos.begin, end), expr); 760 } 761 762 TernaryNodeResult newIfStatement(uint32_t begin, Node cond, Node thenBranch, 763 Node elseBranch) { 764 TernaryNode* node = MOZ_TRY(newResult<TernaryNode>( 765 ParseNodeKind::IfStmt, cond, thenBranch, elseBranch)); 766 node->pn_pos.begin = begin; 767 return node; 768 } 769 770 BinaryNodeResult newDoWhileStatement(Node body, Node cond, 771 const TokenPos& pos) { 772 return newResult<BinaryNode>(ParseNodeKind::DoWhileStmt, pos, body, cond); 773 } 774 775 BinaryNodeResult newWhileStatement(uint32_t begin, Node cond, Node body) { 776 TokenPos pos(begin, body->pn_pos.end); 777 return newResult<BinaryNode>(ParseNodeKind::WhileStmt, pos, cond, body); 778 } 779 780 ForNodeResult newForStatement(uint32_t begin, TernaryNodeType forHead, 781 Node body, unsigned iflags) { 782 return newResult<ForNode>(TokenPos(begin, body->pn_pos.end), forHead, body, 783 iflags); 784 } 785 786 TernaryNodeResult newForHead(Node init, Node test, Node update, 787 const TokenPos& pos) { 788 return newResult<TernaryNode>(ParseNodeKind::ForHead, init, test, update, 789 pos); 790 } 791 792 TernaryNodeResult newForInOrOfHead(ParseNodeKind kind, Node target, 793 Node iteratedExpr, const TokenPos& pos) { 794 MOZ_ASSERT(kind == ParseNodeKind::ForIn || kind == ParseNodeKind::ForOf); 795 return newResult<TernaryNode>(kind, target, nullptr, iteratedExpr, pos); 796 } 797 798 SwitchStatementResult newSwitchStatement( 799 uint32_t begin, Node discriminant, 800 LexicalScopeNodeType lexicalForCaseList, bool hasDefault) { 801 return newResult<SwitchStatement>(begin, discriminant, lexicalForCaseList, 802 hasDefault); 803 } 804 805 CaseClauseResult newCaseOrDefault(uint32_t begin, Node expr, Node body) { 806 return newResult<CaseClause>(expr, body, begin); 807 } 808 809 ContinueStatementResult newContinueStatement(TaggedParserAtomIndex label, 810 const TokenPos& pos) { 811 return newResult<ContinueStatement>(label, pos); 812 } 813 814 BreakStatementResult newBreakStatement(TaggedParserAtomIndex label, 815 const TokenPos& pos) { 816 return newResult<BreakStatement>(label, pos); 817 } 818 819 UnaryNodeResult newReturnStatement(Node expr, const TokenPos& pos) { 820 MOZ_ASSERT_IF(expr, pos.encloses(expr->pn_pos)); 821 return newResult<UnaryNode>(ParseNodeKind::ReturnStmt, pos, expr); 822 } 823 824 UnaryNodeResult newExpressionBody(Node expr) { 825 return newResult<UnaryNode>(ParseNodeKind::ReturnStmt, expr->pn_pos, expr); 826 } 827 828 BinaryNodeResult newWithStatement(uint32_t begin, Node expr, Node body) { 829 return newResult<BinaryNode>(ParseNodeKind::WithStmt, 830 TokenPos(begin, body->pn_pos.end), expr, body); 831 } 832 833 LabeledStatementResult newLabeledStatement(TaggedParserAtomIndex label, 834 Node stmt, uint32_t begin) { 835 return newResult<LabeledStatement>(label, stmt, begin); 836 } 837 838 UnaryNodeResult newThrowStatement(Node expr, const TokenPos& pos) { 839 MOZ_ASSERT(pos.encloses(expr->pn_pos)); 840 return newResult<UnaryNode>(ParseNodeKind::ThrowStmt, pos, expr); 841 } 842 843 TernaryNodeResult newTryStatement(uint32_t begin, Node body, 844 LexicalScopeNodeType catchScope, 845 Node finallyBlock) { 846 return newResult<TryNode>(begin, body, catchScope, finallyBlock); 847 } 848 849 DebuggerStatementResult newDebuggerStatement(const TokenPos& pos) { 850 return newResult<DebuggerStatement>(pos); 851 } 852 853 NameNodeResult newPropertyName(TaggedParserAtomIndex name, 854 const TokenPos& pos) { 855 return newResult<NameNode>(ParseNodeKind::PropertyNameExpr, name, pos); 856 } 857 858 PropertyAccessResult newPropertyAccess(Node expr, NameNodeType key) { 859 return newResult<PropertyAccess>(expr, key, expr->pn_pos.begin, 860 key->pn_pos.end); 861 } 862 863 ArgumentsLengthResult newArgumentsLength(Node expr, NameNodeType key) { 864 return newResult<ArgumentsLength>(expr, key, expr->pn_pos.begin, 865 key->pn_pos.end); 866 } 867 868 PropertyByValueResult newPropertyByValue(Node lhs, Node index, uint32_t end) { 869 return newResult<PropertyByValue>(lhs, index, lhs->pn_pos.begin, end); 870 } 871 872 OptionalPropertyAccessResult newOptionalPropertyAccess(Node expr, 873 NameNodeType key) { 874 return newResult<OptionalPropertyAccess>(expr, key, expr->pn_pos.begin, 875 key->pn_pos.end); 876 } 877 878 OptionalPropertyByValueResult newOptionalPropertyByValue(Node lhs, Node index, 879 uint32_t end) { 880 return newResult<OptionalPropertyByValue>(lhs, index, lhs->pn_pos.begin, 881 end); 882 } 883 884 PrivateMemberAccessResult newPrivateMemberAccess(Node lhs, 885 NameNodeType privateName, 886 uint32_t end) { 887 return newResult<PrivateMemberAccess>(lhs, privateName, lhs->pn_pos.begin, 888 end); 889 } 890 891 OptionalPrivateMemberAccessResult newOptionalPrivateMemberAccess( 892 Node lhs, NameNodeType privateName, uint32_t end) { 893 return newResult<OptionalPrivateMemberAccess>(lhs, privateName, 894 lhs->pn_pos.begin, end); 895 } 896 897 bool setupCatchScope(LexicalScopeNodeType lexicalScope, Node catchName, 898 Node catchBody) { 899 BinaryNode* catchClause; 900 if (catchName) { 901 MOZ_TRY_VAR_OR_RETURN( 902 catchClause, 903 newResult<BinaryNode>(ParseNodeKind::Catch, catchName, catchBody), 904 false); 905 } else { 906 MOZ_TRY_VAR_OR_RETURN( 907 catchClause, 908 newResult<BinaryNode>(ParseNodeKind::Catch, catchBody->pn_pos, 909 catchName, catchBody), 910 false); 911 } 912 lexicalScope->setScopeBody(catchClause); 913 return true; 914 } 915 916 [[nodiscard]] inline bool setLastFunctionFormalParameterDefault( 917 FunctionNodeType funNode, Node defaultValue); 918 919 void checkAndSetIsDirectRHSAnonFunction(Node pn) { 920 if (IsAnonymousFunctionDefinition(pn)) { 921 pn->setDirectRHSAnonFunction(true); 922 } 923 } 924 925 ParamsBodyNodeResult newParamsBody(const TokenPos& pos) { 926 return newResult<ParamsBodyNode>(pos); 927 } 928 929 FunctionNodeResult newFunction(FunctionSyntaxKind syntaxKind, 930 const TokenPos& pos) { 931 return newResult<FunctionNode>(syntaxKind, pos); 932 } 933 934 BinaryNodeResult newObjectMethodOrPropertyDefinition(Node key, Node value, 935 AccessorType atype) { 936 MOZ_ASSERT(isUsableAsObjectPropertyName(key)); 937 938 return newResult<PropertyDefinition>(key, value, atype); 939 } 940 941 void setFunctionFormalParametersAndBody(FunctionNodeType funNode, 942 ParamsBodyNodeType paramsBody) { 943 funNode->setBody(paramsBody); 944 } 945 void setFunctionBox(FunctionNodeType funNode, FunctionBox* funbox) { 946 funNode->setFunbox(funbox); 947 funbox->functionNode = funNode; 948 } 949 void addFunctionFormalParameter(FunctionNodeType funNode, Node argpn) { 950 addList(/* list = */ funNode->body(), /* kid = */ argpn); 951 } 952 void setFunctionBody(FunctionNodeType funNode, LexicalScopeNodeType body) { 953 addList(/* list = */ funNode->body(), /* kid = */ body); 954 } 955 956 ModuleNodeResult newModule(const TokenPos& pos) { 957 return newResult<ModuleNode>(pos); 958 } 959 960 LexicalScopeNodeResult newLexicalScope(LexicalScope::ParserData* bindings, 961 Node body, 962 ScopeKind kind = ScopeKind::Lexical) { 963 return newResult<LexicalScopeNode>(bindings, body, kind); 964 } 965 966 ClassBodyScopeNodeResult newClassBodyScope( 967 ClassBodyScope::ParserData* bindings, ListNodeType body) { 968 return newResult<ClassBodyScopeNode>(bindings, body); 969 } 970 971 CallNodeResult newNewExpression(uint32_t begin, Node ctor, ListNodeType args, 972 bool isSpread) { 973 return newResult<CallNode>(ParseNodeKind::NewExpr, 974 isSpread ? JSOp::SpreadNew : JSOp::New, 975 TokenPos(begin, args->pn_pos.end), ctor, args); 976 } 977 978 AssignmentNodeResult newAssignment(ParseNodeKind kind, Node lhs, Node rhs) { 979 if ((kind == ParseNodeKind::AssignExpr || 980 kind == ParseNodeKind::CoalesceAssignExpr || 981 kind == ParseNodeKind::OrAssignExpr || 982 kind == ParseNodeKind::AndAssignExpr) && 983 lhs->isKind(ParseNodeKind::Name) && !lhs->isInParens()) { 984 checkAndSetIsDirectRHSAnonFunction(rhs); 985 } 986 987 return newResult<AssignmentNode>(kind, lhs, rhs); 988 } 989 990 BinaryNodeResult newInitExpr(Node lhs, Node rhs) { 991 TokenPos pos(lhs->pn_pos.begin, rhs->pn_pos.end); 992 return newResult<BinaryNode>(ParseNodeKind::InitExpr, pos, lhs, rhs); 993 } 994 995 bool isUnparenthesizedAssignment(Node node) { 996 if ((node->isKind(ParseNodeKind::AssignExpr)) && !node->isInParens()) { 997 return true; 998 } 999 1000 return false; 1001 } 1002 1003 bool isUnparenthesizedUnaryExpression(Node node) { 1004 if (!node->isInParens()) { 1005 ParseNodeKind kind = node->getKind(); 1006 return kind == ParseNodeKind::VoidExpr || 1007 kind == ParseNodeKind::NotExpr || 1008 kind == ParseNodeKind::BitNotExpr || 1009 kind == ParseNodeKind::PosExpr || kind == ParseNodeKind::NegExpr || 1010 kind == ParseNodeKind::AwaitExpr || IsTypeofKind(kind) || 1011 IsDeleteKind(kind); 1012 } 1013 return false; 1014 } 1015 1016 bool isReturnStatement(Node node) { 1017 return node->isKind(ParseNodeKind::ReturnStmt); 1018 } 1019 1020 bool isStatementPermittedAfterReturnStatement(Node node) { 1021 ParseNodeKind kind = node->getKind(); 1022 return kind == ParseNodeKind::Function || kind == ParseNodeKind::VarStmt || 1023 kind == ParseNodeKind::BreakStmt || 1024 kind == ParseNodeKind::ThrowStmt || kind == ParseNodeKind::EmptyStmt; 1025 } 1026 1027 bool isSuperBase(Node node) { return node->isKind(ParseNodeKind::SuperBase); } 1028 1029 bool isUsableAsObjectPropertyName(Node node) { 1030 return node->isKind(ParseNodeKind::NumberExpr) || 1031 node->isKind(ParseNodeKind::BigIntExpr) || 1032 node->isKind(ParseNodeKind::ObjectPropertyName) || 1033 node->isKind(ParseNodeKind::StringExpr) || 1034 node->isKind(ParseNodeKind::ComputedName) || 1035 node->isKind(ParseNodeKind::PrivateName); 1036 } 1037 1038 AssignmentNodeResult finishInitializerAssignment(NameNodeType nameNode, 1039 Node init) { 1040 MOZ_ASSERT(nameNode->isKind(ParseNodeKind::Name)); 1041 MOZ_ASSERT(!nameNode->isInParens()); 1042 1043 checkAndSetIsDirectRHSAnonFunction(init); 1044 1045 return newAssignment(ParseNodeKind::AssignExpr, nameNode, init); 1046 } 1047 1048 void setBeginPosition(Node pn, Node oth) { 1049 setBeginPosition(pn, oth->pn_pos.begin); 1050 } 1051 void setBeginPosition(Node pn, uint32_t begin) { 1052 pn->pn_pos.begin = begin; 1053 MOZ_ASSERT(pn->pn_pos.begin <= pn->pn_pos.end); 1054 } 1055 1056 void setEndPosition(Node pn, Node oth) { 1057 setEndPosition(pn, oth->pn_pos.end); 1058 } 1059 void setEndPosition(Node pn, uint32_t end) { 1060 pn->pn_pos.end = end; 1061 MOZ_ASSERT(pn->pn_pos.begin <= pn->pn_pos.end); 1062 } 1063 1064 uint32_t getFunctionNameOffset(Node func, TokenStreamAnyChars& ts) { 1065 return func->pn_pos.begin; 1066 } 1067 1068 ListNodeResult newList(ParseNodeKind kind, const TokenPos& pos) { 1069 auto list = newResult<ListNode>(kind, pos); 1070 MOZ_ASSERT_IF(list.isOk(), !list.unwrap()->is<DeclarationListNode>()); 1071 MOZ_ASSERT_IF(list.isOk(), !list.unwrap()->is<ParamsBodyNode>()); 1072 return list; 1073 } 1074 1075 ListNodeResult newList(ParseNodeKind kind, Node kid) { 1076 auto list = newResult<ListNode>(kind, kid); 1077 MOZ_ASSERT_IF(list.isOk(), !list.unwrap()->is<DeclarationListNode>()); 1078 MOZ_ASSERT_IF(list.isOk(), !list.unwrap()->is<ParamsBodyNode>()); 1079 return list; 1080 } 1081 1082 DeclarationListNodeResult newDeclarationList(ParseNodeKind kind, 1083 const TokenPos& pos) { 1084 return newResult<DeclarationListNode>(kind, pos); 1085 } 1086 1087 ListNodeResult newCommaExpressionList(Node kid) { 1088 return newResult<ListNode>(ParseNodeKind::CommaExpr, kid); 1089 } 1090 1091 void addList(ListNodeType list, Node kid) { list->append(kid); } 1092 1093 void setListHasNonConstInitializer(ListNodeType literal) { 1094 literal->setHasNonConstInitializer(); 1095 } 1096 1097 // NOTE: This is infallible. 1098 template <typename NodeType> 1099 [[nodiscard]] NodeType parenthesize(NodeType node) { 1100 node->setInParens(true); 1101 return node; 1102 } 1103 1104 // NOTE: This is infallible. 1105 template <typename NodeType> 1106 [[nodiscard]] NodeType setLikelyIIFE(NodeType node) { 1107 return parenthesize(node); 1108 } 1109 1110 bool isName(Node node) { return node->isKind(ParseNodeKind::Name); } 1111 1112 bool isArgumentsName(Node node) { 1113 return node->isKind(ParseNodeKind::Name) && 1114 node->as<NameNode>().atom() == 1115 TaggedParserAtomIndex::WellKnown::arguments(); 1116 } 1117 1118 bool isLengthName(Node node) { 1119 return node->isKind(ParseNodeKind::PropertyNameExpr) && 1120 node->as<NameNode>().atom() == 1121 TaggedParserAtomIndex::WellKnown::length(); 1122 } 1123 1124 bool isEvalName(Node node) { 1125 return node->isKind(ParseNodeKind::Name) && 1126 node->as<NameNode>().atom() == 1127 TaggedParserAtomIndex::WellKnown::eval(); 1128 } 1129 1130 bool isAsyncKeyword(Node node) { 1131 return node->isKind(ParseNodeKind::Name) && 1132 node->pn_pos.begin + strlen("async") == node->pn_pos.end && 1133 node->as<NameNode>().atom() == 1134 TaggedParserAtomIndex::WellKnown::async(); 1135 } 1136 1137 bool isArgumentsLength(Node node) { 1138 return node->isKind(ParseNodeKind::ArgumentsLength); 1139 } 1140 1141 bool isPrivateName(Node node) { 1142 return node->isKind(ParseNodeKind::PrivateName); 1143 } 1144 1145 bool isPrivateMemberAccess(Node node) { 1146 if (node->isKind(ParseNodeKind::OptionalChain)) { 1147 return isPrivateMemberAccess(node->as<UnaryNode>().kid()); 1148 } 1149 return node->is<PrivateMemberAccessBase>(); 1150 } 1151 1152 TaggedParserAtomIndex maybeDottedProperty(Node pn) { 1153 return pn->is<PropertyAccessBase>() ? pn->as<PropertyAccessBase>().name() 1154 : TaggedParserAtomIndex::null(); 1155 } 1156 TaggedParserAtomIndex isStringExprStatement(Node pn, TokenPos* pos) { 1157 if (pn->is<UnaryNode>()) { 1158 UnaryNode* unary = &pn->as<UnaryNode>(); 1159 if (auto atom = unary->isStringExprStatement()) { 1160 *pos = unary->kid()->pn_pos; 1161 return atom; 1162 } 1163 } 1164 return TaggedParserAtomIndex::null(); 1165 } 1166 1167 bool reuseLazyInnerFunctions() { return reuseGCThings; } 1168 bool reuseClosedOverBindings() { return reuseGCThings; } 1169 bool reuseRegexpSyntaxParse() { return reuseGCThings; } 1170 void nextLazyInnerFunction() { lazyInnerFunctionIndex++; } 1171 TaggedParserAtomIndex nextLazyClosedOverBinding() { 1172 // Trailing nullptrs were elided in PerHandlerParser::finishFunction(). 1173 auto closedOverBindings = previousParseCache_.closedOverBindings(); 1174 if (lazyClosedOverBindingIndex >= closedOverBindings.Length()) { 1175 return TaggedParserAtomIndex::null(); 1176 } 1177 1178 return closedOverBindings[lazyClosedOverBindingIndex++]; 1179 } 1180 const ScriptStencil& cachedScriptData() const { 1181 // lazyInnerFunctionIndex is incremented with nextLazyInnferFunction before 1182 // reading the content, thus we need -1 to access the element that we just 1183 // skipped. 1184 return previousParseCache_.scriptData(lazyInnerFunctionIndex - 1); 1185 } 1186 const ScriptStencilExtra& cachedScriptExtra() const { 1187 // lazyInnerFunctionIndex is incremented with nextLazyInnferFunction before 1188 // reading the content, thus we need -1 to access the element that we just 1189 // skipped. 1190 return previousParseCache_.scriptExtra(lazyInnerFunctionIndex - 1); 1191 } 1192 1193 void setPrivateNameKind(Node node, PrivateNameKind kind) { 1194 MOZ_ASSERT(node->is<NameNode>()); 1195 node->as<NameNode>().setPrivateNameKind(kind); 1196 } 1197 }; 1198 1199 inline bool FullParseHandler::setLastFunctionFormalParameterDefault( 1200 FunctionNodeType funNode, Node defaultValue) { 1201 ParamsBodyNode* body = funNode->body(); 1202 ParseNode* arg = body->last(); 1203 ParseNode* pn; 1204 MOZ_TRY_VAR_OR_RETURN( 1205 pn, newAssignment(ParseNodeKind::AssignExpr, arg, defaultValue), false); 1206 1207 body->replaceLast(pn); 1208 return true; 1209 } 1210 1211 } // namespace frontend 1212 } // namespace js 1213 1214 #endif /* frontend_FullParseHandler_h */