ParseContext.h (25542B)
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_ParseContext_h 8 #define frontend_ParseContext_h 9 10 #include "ds/Nestable.h" 11 #include "frontend/ErrorReporter.h" 12 #include "frontend/NameAnalysisTypes.h" // DeclaredNameInfo, FunctionBoxVector 13 #include "frontend/NameCollections.h" 14 #include "frontend/ParserAtom.h" // TaggedParserAtomIndex 15 #include "frontend/ScriptIndex.h" // ScriptIndex 16 #include "frontend/SharedContext.h" 17 #include "js/friend/ErrorMessages.h" // JSMSG_* 18 #include "vm/GeneratorAndAsyncKind.h" // js::GeneratorKind, js::FunctionAsyncKind 19 20 namespace js { 21 22 namespace frontend { 23 24 class ParserBase; 25 class UsedNameTracker; 26 27 struct CompilationState; 28 29 const char* DeclarationKindString(DeclarationKind kind); 30 31 // Returns true if the declaration is `var` or equivalent. 32 bool DeclarationKindIsVar(DeclarationKind kind); 33 34 bool DeclarationKindIsParameter(DeclarationKind kind); 35 36 /* 37 * The struct ParseContext stores information about the current parsing context, 38 * which is part of the parser state (see the field Parser::pc). The current 39 * parsing context is either the global context, or the function currently being 40 * parsed. When the parser encounters a function definition, it creates a new 41 * ParseContext, makes it the new current context. 42 */ 43 class MOZ_STACK_CLASS ParseContext : public Nestable<ParseContext> { 44 public: 45 // The intra-function statement stack. 46 // 47 // Used for early error checking that depend on the nesting structure of 48 // statements, such as continue/break targets, labels, and unbraced 49 // lexical declarations. 50 class MOZ_STACK_CLASS Statement : public Nestable<Statement> { 51 StatementKind kind_; 52 53 public: 54 using Nestable<Statement>::enclosing; 55 using Nestable<Statement>::findNearest; 56 57 Statement(ParseContext* pc, StatementKind kind) 58 : Nestable<Statement>(&pc->innermostStatement_), kind_(kind) {} 59 60 template <typename T> 61 inline bool is() const; 62 template <typename T> 63 inline T& as(); 64 65 StatementKind kind() const { return kind_; } 66 67 void refineForKind(StatementKind newForKind) { 68 MOZ_ASSERT(kind_ == StatementKind::ForLoop); 69 MOZ_ASSERT(newForKind == StatementKind::ForInLoop || 70 newForKind == StatementKind::ForOfLoop); 71 kind_ = newForKind; 72 } 73 }; 74 75 class LabelStatement : public Statement { 76 TaggedParserAtomIndex label_; 77 78 public: 79 LabelStatement(ParseContext* pc, TaggedParserAtomIndex label) 80 : Statement(pc, StatementKind::Label), label_(label) {} 81 82 TaggedParserAtomIndex label() const { return label_; } 83 }; 84 85 struct ClassStatement : public Statement { 86 FunctionBox* constructorBox; 87 88 explicit ClassStatement(ParseContext* pc) 89 : Statement(pc, StatementKind::Class), constructorBox(nullptr) {} 90 }; 91 92 // The intra-function scope stack. 93 // 94 // Tracks declared and used names within a scope. 95 class MOZ_STACK_CLASS Scope : public Nestable<Scope> { 96 // Names declared in this scope. Corresponds to the union of 97 // VarDeclaredNames and LexicallyDeclaredNames in the ES spec. 98 // 99 // A 'var' declared name is a member of the declared name set of every 100 // scope in its scope contour. 101 // 102 // A lexically declared name is a member only of the declared name set of 103 // the scope in which it is declared. 104 PooledMapPtr<DeclaredNameMap> declared_; 105 106 // FunctionBoxes in this scope that need to be considered for Annex 107 // B.3.3 semantics. This is checked on Scope exit, as by then we have 108 // all the declared names and would know if Annex B.3.3 is applicable. 109 PooledVectorPtr<FunctionBoxVector> possibleAnnexBFunctionBoxes_; 110 111 // Monotonically increasing id. 112 uint32_t id_; 113 114 // Flag for determining if we can apply an optimization to store bindings in 115 // stack slots, which is applied in generator or async functions, or in 116 // async modules. 117 // 118 // This limit is a performance heuristic. Stack slots reduce allocations, 119 // and `Local` opcodes are a bit faster than `AliasedVar` ones; but at each 120 // `yield` or `await` the stack slots must be memcpy'd into a 121 // GeneratorObject. At some point the memcpy is too much. The limit is 122 // plenty for typical human-authored code. 123 enum class GeneratorOrAsyncScopeFlag : uint32_t { 124 // Scope is small enough that bindings can be stored in stack slots. 125 Optimizable = 0, 126 127 // Scope is too big and all bindings should be closed over. 128 TooManyBindings = UINT32_MAX, 129 }; 130 131 // Scope size info, relevant for scopes in generators, async functions, and 132 // async modules only. 133 static constexpr uint32_t InnerScopeSlotCountInitialValue = 0; 134 union { 135 // The estimated number of slots needed for nested scopes inside this one. 136 // Calculated while parsing the scope and inner scopes. 137 // Valid only if isOptimizableFlagCalculated_ is false. 138 uint32_t innerScopeSlotCount_ = InnerScopeSlotCountInitialValue; 139 140 // Set when leaving the scope. 141 // Valid only if isOptimizableFlagCalculated_ is true. 142 GeneratorOrAsyncScopeFlag optimizableFlag_; 143 } generatorOrAsyncScopeInfo_; 144 145 #ifdef DEBUG 146 bool isGeneratorOrAsyncScopeInfoUsed_ = false; 147 bool isOptimizableFlagCalculated_ = false; 148 #endif 149 150 uint32_t innerScopeSlotCount() { 151 MOZ_ASSERT(!isOptimizableFlagCalculated_); 152 #ifdef DEBUG 153 isGeneratorOrAsyncScopeInfoUsed_ = true; 154 #endif 155 return generatorOrAsyncScopeInfo_.innerScopeSlotCount_; 156 } 157 void setInnerScopeSlotCount(uint32_t slotCount) { 158 MOZ_ASSERT(!isOptimizableFlagCalculated_); 159 generatorOrAsyncScopeInfo_.innerScopeSlotCount_ = slotCount; 160 #ifdef DEBUG 161 isGeneratorOrAsyncScopeInfoUsed_ = true; 162 #endif 163 } 164 void propagateInnerScopeSlotCount(uint32_t slotCount) { 165 if (slotCount > innerScopeSlotCount()) { 166 setInnerScopeSlotCount(slotCount); 167 } 168 } 169 170 void setGeneratorOrAsyncScopeIsOptimizable() { 171 MOZ_ASSERT(!isOptimizableFlagCalculated_); 172 #ifdef DEBUG 173 isGeneratorOrAsyncScopeInfoUsed_ = true; 174 isOptimizableFlagCalculated_ = true; 175 #endif 176 generatorOrAsyncScopeInfo_.optimizableFlag_ = 177 GeneratorOrAsyncScopeFlag::Optimizable; 178 } 179 180 void setGeneratorOrAsyncScopeHasTooManyBindings() { 181 MOZ_ASSERT(!isOptimizableFlagCalculated_); 182 #ifdef DEBUG 183 isGeneratorOrAsyncScopeInfoUsed_ = true; 184 isOptimizableFlagCalculated_ = true; 185 #endif 186 generatorOrAsyncScopeInfo_.optimizableFlag_ = 187 GeneratorOrAsyncScopeFlag::TooManyBindings; 188 } 189 190 bool maybeReportOOM(ParseContext* pc, bool result) { 191 if (!result) { 192 ReportOutOfMemory(pc->sc()->fc_); 193 } 194 return result; 195 } 196 197 public: 198 using DeclaredNamePtr = DeclaredNameMap::Ptr; 199 using AddDeclaredNamePtr = DeclaredNameMap::AddPtr; 200 201 using Nestable<Scope>::enclosing; 202 203 explicit inline Scope(ParserBase* parser); 204 explicit inline Scope(FrontendContext* fc, ParseContext* pc, 205 UsedNameTracker& usedNames); 206 207 void dump(ParseContext* pc, ParserBase* parser); 208 209 uint32_t id() const { return id_; } 210 211 [[nodiscard]] bool init(ParseContext* pc) { 212 if (id_ == UINT32_MAX) { 213 pc->errorReporter_.errorNoOffset(JSMSG_NEED_DIET, "script"); 214 return false; 215 } 216 217 return declared_.acquire(pc->sc()->fc_); 218 } 219 220 bool isEmpty() const { return declared_->all().empty(); } 221 222 uint32_t declaredCount() const { 223 size_t count = declared_->count(); 224 MOZ_ASSERT(count <= UINT32_MAX); 225 return uint32_t(count); 226 } 227 228 DeclaredNamePtr lookupDeclaredName(TaggedParserAtomIndex name) { 229 return declared_->lookup(name); 230 } 231 232 AddDeclaredNamePtr lookupDeclaredNameForAdd(TaggedParserAtomIndex name) { 233 return declared_->lookupForAdd(name); 234 } 235 236 [[nodiscard]] bool addDeclaredName(ParseContext* pc, AddDeclaredNamePtr& p, 237 TaggedParserAtomIndex name, 238 DeclarationKind kind, uint32_t pos, 239 ClosedOver closedOver = ClosedOver::No) { 240 return maybeReportOOM( 241 pc, declared_->add(p, name, DeclaredNameInfo(kind, pos, closedOver))); 242 } 243 244 // Add a FunctionBox as a possible candidate for Annex B.3.3 semantics. 245 [[nodiscard]] bool addPossibleAnnexBFunctionBox(ParseContext* pc, 246 FunctionBox* funbox); 247 248 // Check if the candidate function boxes for Annex B.3.3 should in 249 // fact get Annex B semantics. Checked on Scope exit. 250 [[nodiscard]] bool propagateAndMarkAnnexBFunctionBoxes(ParseContext* pc, 251 ParserBase* parser); 252 253 // Add and remove catch parameter names. Used to implement the odd 254 // semantics of catch bodies. 255 bool addCatchParameters(ParseContext* pc, Scope& catchParamScope); 256 void removeCatchParameters(ParseContext* pc, Scope& catchParamScope); 257 258 void useAsVarScope(ParseContext* pc) { 259 MOZ_ASSERT(!pc->varScope_); 260 pc->varScope_ = this; 261 } 262 263 // Maximum number of fixed stack slots in a generator or async function 264 // script. If a script would have more, we instead store some variables in 265 // heap EnvironmentObjects. 266 // 267 // This limit is a performance heuristic. Stack slots reduce allocations, 268 // and `Local` opcodes are a bit faster than `AliasedVar` ones; but at each 269 // `yield` or `await` the stack slots must be memcpy'd into a 270 // GeneratorObject. At some point the memcpy is too much. The limit is 271 // plenty for typical human-authored code. 272 // 273 // NOTE: This just limits the number of fixed slots, not the entire stack 274 // slots. `yield` and `await` can happen with more slots if there 275 // are many stack values, and the number of values copied to the 276 // generator's stack storage array can be more than the limit. 277 static constexpr uint32_t FixedSlotLimit = 256; 278 279 // This is called as we leave a function, var, or lexical scope in a 280 // generator or async function. `ownSlotCount` is the number of `bindings_` 281 // that are not closed over. 282 void setOwnStackSlotCount(uint32_t ownSlotCount) { 283 uint32_t slotCount = ownSlotCount + innerScopeSlotCount(); 284 if (slotCount > FixedSlotLimit) { 285 slotCount = innerScopeSlotCount(); 286 setGeneratorOrAsyncScopeHasTooManyBindings(); 287 } else { 288 setGeneratorOrAsyncScopeIsOptimizable(); 289 } 290 291 // Propagate total size to enclosing scope. 292 if (Scope* parent = enclosing()) { 293 parent->propagateInnerScopeSlotCount(slotCount); 294 } 295 } 296 297 bool tooBigToOptimize() const { 298 // NOTE: This is called also for scopes in non-generator/non-async. 299 // generatorOrAsyncScopeInfo_ is used only from generator or async, 300 // and if it's not used, it holds the initial value, which is the 301 // same value as GeneratorOrAsyncScopeFlag::Optimizable. 302 static_assert(InnerScopeSlotCountInitialValue == 303 uint32_t(GeneratorOrAsyncScopeFlag::Optimizable)); 304 MOZ_ASSERT(!isGeneratorOrAsyncScopeInfoUsed_ || 305 isOptimizableFlagCalculated_); 306 return generatorOrAsyncScopeInfo_.optimizableFlag_ != 307 GeneratorOrAsyncScopeFlag::Optimizable; 308 } 309 310 // An iterator for the set of names a scope binds: the set of all 311 // declared names for 'var' scopes, and the set of lexically declared 312 // names, plus synthetic names, for non-'var' scopes. 313 class BindingIter { 314 friend class Scope; 315 316 DeclaredNameMap::Range declaredRange_; 317 mozilla::DebugOnly<uint32_t> count_; 318 bool isVarScope_; 319 320 BindingIter(Scope& scope, bool isVarScope) 321 : declaredRange_(scope.declared_->all()), 322 count_(0), 323 isVarScope_(isVarScope) { 324 settle(); 325 } 326 327 bool isLexicallyDeclared() { 328 return BindingKindIsLexical(kind()) || 329 kind() == BindingKind::Synthetic || 330 kind() == BindingKind::PrivateMethod; 331 } 332 333 void settle() { 334 // Both var and lexically declared names are binding in a var 335 // scope. 336 if (isVarScope_) { 337 return; 338 } 339 340 // Otherwise, only lexically declared names are binding. Pop the range 341 // until we find such a name. 342 while (!declaredRange_.empty()) { 343 if (isLexicallyDeclared()) { 344 break; 345 } 346 declaredRange_.popFront(); 347 } 348 } 349 350 public: 351 bool done() const { return declaredRange_.empty(); } 352 353 explicit operator bool() const { return !done(); } 354 355 TaggedParserAtomIndex name() { 356 MOZ_ASSERT(!done()); 357 return declaredRange_.front().key(); 358 } 359 360 DeclarationKind declarationKind() { 361 MOZ_ASSERT(!done()); 362 return declaredRange_.front().value()->kind(); 363 } 364 365 BindingKind kind() { 366 return DeclarationKindToBindingKind(declarationKind()); 367 } 368 369 bool closedOver() { 370 MOZ_ASSERT(!done()); 371 return declaredRange_.front().value()->closedOver(); 372 } 373 374 void setClosedOver() { 375 MOZ_ASSERT(!done()); 376 return declaredRange_.front().value()->setClosedOver(); 377 } 378 379 void operator++(int) { 380 MOZ_ASSERT(!done()); 381 MOZ_ASSERT(count_ != UINT32_MAX); 382 declaredRange_.popFront(); 383 settle(); 384 } 385 }; 386 387 inline BindingIter bindings(ParseContext* pc); 388 }; 389 390 class VarScope : public Scope { 391 public: 392 explicit inline VarScope(ParserBase* parser); 393 explicit inline VarScope(FrontendContext* fc, ParseContext* pc, 394 UsedNameTracker& usedNames); 395 }; 396 397 private: 398 // Context shared between parsing and bytecode generation. 399 SharedContext* sc_; 400 401 // A mechanism used for error reporting. 402 ErrorReporter& errorReporter_; 403 404 // The innermost statement, i.e., top of the statement stack. 405 Statement* innermostStatement_; 406 407 // The innermost scope, i.e., top of the scope stack. 408 // 409 // The outermost scope in the stack is usually varScope_. In the case of 410 // functions, the outermost scope is functionScope_, which may be 411 // varScope_. See comment above functionScope_. 412 Scope* innermostScope_; 413 414 // If isFunctionBox() and the function is a named lambda, the DeclEnv 415 // scope for named lambdas. 416 mozilla::Maybe<Scope> namedLambdaScope_; 417 418 // If isFunctionBox(), the scope for the function. If there are no 419 // parameter expressions, this is scope for the entire function. If there 420 // are parameter expressions, this holds the special function names 421 // ('.this', 'arguments') and the formal parameters. 422 mozilla::Maybe<Scope> functionScope_; 423 424 // The body-level scope. This always exists, but not necessarily at the 425 // beginning of parsing the script in the case of functions with parameter 426 // expressions. 427 Scope* varScope_; 428 429 // Simple formal parameter names, in order of appearance. Only used when 430 // isFunctionBox(). 431 PooledVectorPtr<AtomVector> positionalFormalParameterNames_; 432 433 // Closed over binding names, in order of appearance. Null-delimited 434 // between scopes. Only used when syntax parsing. 435 PooledVectorPtr<AtomVector> closedOverBindingsForLazy_; 436 437 public: 438 // All inner functions in this context. Only used when syntax parsing. 439 // The Functions (or FunctionCreateionDatas) are traced as part of the 440 // CompilationStencil function vector. 441 Vector<ScriptIndex, 4> innerFunctionIndexesForLazy; 442 443 // In a function context, points to a Directive struct that can be updated 444 // to reflect new directives encountered in the Directive Prologue that 445 // require reparsing the function. In global/module/generator-tail contexts, 446 // we don't need to reparse when encountering a DirectivePrologue so this 447 // pointer may be nullptr. 448 Directives* newDirectives; 449 450 // lastYieldOffset stores the offset of the last yield that was parsed. 451 // NoYieldOffset is its initial value. 452 static const uint32_t NoYieldOffset = UINT32_MAX; 453 uint32_t lastYieldOffset; 454 455 // lastAwaitOffset stores the offset of the last await that was parsed. 456 // NoAwaitOffset is its initial value. 457 static const uint32_t NoAwaitOffset = UINT32_MAX; 458 uint32_t lastAwaitOffset; 459 460 private: 461 // Monotonically increasing id. 462 uint32_t scriptId_; 463 464 // Set when encountering a super.property inside a method. We need to mark 465 // the nearest super scope as needing a home object. 466 bool superScopeNeedsHomeObject_; 467 468 public: 469 ParseContext(FrontendContext* fc, ParseContext*& parent, SharedContext* sc, 470 ErrorReporter& errorReporter, CompilationState& compilationState, 471 Directives* newDirectives, bool isFull); 472 473 [[nodiscard]] bool init(); 474 475 SharedContext* sc() { return sc_; } 476 477 // `true` if we are in the body of a function definition. 478 bool isFunctionBox() const { return sc_->isFunctionBox(); } 479 480 FunctionBox* functionBox() { return sc_->asFunctionBox(); } 481 482 Statement* innermostStatement() { return innermostStatement_; } 483 484 Scope* innermostScope() { 485 // There is always at least one scope: the 'var' scope. 486 MOZ_ASSERT(innermostScope_); 487 return innermostScope_; 488 } 489 490 Scope& namedLambdaScope() { 491 MOZ_ASSERT(functionBox()->isNamedLambda()); 492 return *namedLambdaScope_; 493 } 494 495 Scope& functionScope() { 496 MOZ_ASSERT(isFunctionBox()); 497 return *functionScope_; 498 } 499 500 Scope& varScope() { 501 MOZ_ASSERT(varScope_); 502 return *varScope_; 503 } 504 505 bool isFunctionExtraBodyVarScopeInnermost() { 506 return isFunctionBox() && functionBox()->hasParameterExprs && 507 innermostScope() == varScope_; 508 } 509 510 template <typename Predicate /* (Statement*) -> bool */> 511 Statement* findInnermostStatement(Predicate predicate) { 512 return Statement::findNearest(innermostStatement_, predicate); 513 } 514 515 template <typename T, typename Predicate /* (Statement*) -> bool */> 516 T* findInnermostStatement(Predicate predicate) { 517 return Statement::findNearest<T>(innermostStatement_, predicate); 518 } 519 520 template <typename T> 521 T* findInnermostStatement() { 522 return Statement::findNearest<T>(innermostStatement_); 523 } 524 525 AtomVector& positionalFormalParameterNames() { 526 return *positionalFormalParameterNames_; 527 } 528 529 AtomVector& closedOverBindingsForLazy() { 530 return *closedOverBindingsForLazy_; 531 } 532 533 enum class BreakStatementError : uint8_t { 534 // Unlabeled break must be inside loop or switch. 535 ToughBreak, 536 LabelNotFound, 537 }; 538 539 // Return Err(true) if we have encountered at least one loop, 540 // Err(false) otherwise. 541 [[nodiscard]] inline JS::Result<Ok, BreakStatementError> checkBreakStatement( 542 TaggedParserAtomIndex label); 543 544 enum class ContinueStatementError : uint8_t { 545 NotInALoop, 546 LabelNotFound, 547 }; 548 [[nodiscard]] inline JS::Result<Ok, ContinueStatementError> 549 checkContinueStatement(TaggedParserAtomIndex label); 550 551 // True if we are at the topmost level of a entire script or function body. 552 // For example, while parsing this code we would encounter f1 and f2 at 553 // body level, but we would not encounter f3 or f4 at body level: 554 // 555 // function f1() { function f2() { } } 556 // if (cond) { function f3() { if (cond) { function f4() { } } } } 557 // 558 bool atBodyLevel() { return !innermostStatement_; } 559 560 bool atGlobalLevel() { return atBodyLevel() && sc_->isGlobalContext(); } 561 562 // True if we are at the topmost level of a module only. 563 bool atModuleLevel() { return atBodyLevel() && sc_->isModuleContext(); } 564 565 // True if we are at the topmost level of an entire script or module. For 566 // example, in the comment on |atBodyLevel()| above, we would encounter |f1| 567 // and the outermost |if (cond)| at top level, and everything else would not 568 // be at top level. 569 bool atTopLevel() { return atBodyLevel() && sc_->isTopLevelContext(); } 570 571 bool atModuleTopLevel() { 572 // True if we are at the topmost level of an entire module. 573 // 574 // For example, this is used to determine if an await statement should 575 // mark a module as an async module during parsing. 576 // 577 // Example module: 578 // import x from "y"; 579 // 580 // await x.foo(); // mark as Top level await. 581 // 582 // if (cond) { 583 // await x.bar(); // mark as Top level await. 584 // } 585 // 586 // async function z() { 587 // await x.baz(); // do not mark as Top level await. 588 // } 589 return sc_->isModuleContext() && sc_->isTopLevelContext(); 590 } 591 592 // True if this is the outermost ParserContext for current compile. For 593 // delazification, this lets us identify if the lazy PrivateScriptData is for 594 // current parser context. 595 bool isOutermostOfCurrentCompile() const { 596 MOZ_ASSERT(!!enclosing() == !!scriptId()); 597 return (scriptId() == 0); 598 } 599 600 #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT 601 bool isUsingSyntaxAllowed() { 602 if (innermostStatement() && 603 innermostStatement()->kind() == StatementKind::Switch) { 604 return false; 605 } 606 607 return innermostStatement_ || sc_->isFunction() || sc_->isModule(); 608 } 609 #endif 610 611 void setSuperScopeNeedsHomeObject() { 612 MOZ_ASSERT(sc_->allowSuperProperty()); 613 superScopeNeedsHomeObject_ = true; 614 } 615 616 bool superScopeNeedsHomeObject() const { return superScopeNeedsHomeObject_; } 617 618 bool useAsmOrInsideUseAsm() const { 619 return sc_->isFunctionBox() && sc_->asFunctionBox()->useAsmOrInsideUseAsm(); 620 } 621 622 // A generator is marked as a generator before its body is parsed. 623 GeneratorKind generatorKind() const { 624 return sc_->isFunctionBox() ? sc_->asFunctionBox()->generatorKind() 625 : GeneratorKind::NotGenerator; 626 } 627 628 bool isGenerator() const { 629 return generatorKind() == GeneratorKind::Generator; 630 } 631 632 bool isAsync() const { 633 return sc_->isSuspendableContext() && 634 sc_->asSuspendableContext()->isAsync(); 635 } 636 637 bool isGeneratorOrAsync() const { return isGenerator() || isAsync(); } 638 639 bool needsDotGeneratorName() const { return isGeneratorOrAsync(); } 640 641 FunctionAsyncKind asyncKind() const { 642 return isAsync() ? FunctionAsyncKind::AsyncFunction 643 : FunctionAsyncKind::SyncFunction; 644 } 645 646 bool isArrowFunction() const { 647 return sc_->isFunctionBox() && sc_->asFunctionBox()->isArrow(); 648 } 649 650 bool isMethod() const { 651 return sc_->isFunctionBox() && sc_->asFunctionBox()->isMethod(); 652 } 653 654 bool isGetterOrSetter() const { 655 return sc_->isFunctionBox() && (sc_->asFunctionBox()->isGetter() || 656 sc_->asFunctionBox()->isSetter()); 657 } 658 659 bool allowReturn() const { 660 return sc_->isFunctionBox() && sc_->asFunctionBox()->allowReturn(); 661 } 662 663 uint32_t scriptId() const { return scriptId_; } 664 665 bool computeAnnexBAppliesToLexicalFunctionInInnermostScope( 666 FunctionBox* funbox, ParserBase* parser, bool* annexBApplies); 667 668 bool tryDeclareVar(TaggedParserAtomIndex name, ParserBase* parser, 669 DeclarationKind kind, uint32_t beginPos, 670 mozilla::Maybe<DeclarationKind>* redeclaredKind, 671 uint32_t* prevPos); 672 673 bool hasUsedName(const UsedNameTracker& usedNames, 674 TaggedParserAtomIndex name); 675 bool hasClosedOverName(const UsedNameTracker& usedNames, 676 TaggedParserAtomIndex name); 677 bool hasUsedFunctionSpecialName(const UsedNameTracker& usedNames, 678 TaggedParserAtomIndex name); 679 bool hasClosedOverFunctionSpecialName(const UsedNameTracker& usedNames, 680 TaggedParserAtomIndex name); 681 682 bool declareFunctionThis(const UsedNameTracker& usedNames, 683 bool canSkipLazyClosedOverBindings); 684 bool declareFunctionArgumentsObject(const UsedNameTracker& usedNames, 685 bool canSkipLazyClosedOverBindings); 686 bool declareNewTarget(const UsedNameTracker& usedNames, 687 bool canSkipLazyClosedOverBindings); 688 bool declareDotGeneratorName(); 689 bool declareTopLevelDotGeneratorName(); 690 691 // Used to determine if we have non-length uses of the arguments binding. 692 // This works by incrementing this counter each time we encounter the 693 // arguments name, and decrementing each time it is combined into 694 // arguments.length; as a result, if this is non-zero at the end of parsing, 695 // we have identified a non-length use of the arguments binding. 696 size_t numberOfArgumentsNames = 0; 697 698 private: 699 [[nodiscard]] bool isVarRedeclaredInInnermostScope( 700 TaggedParserAtomIndex name, ParserBase* parser, DeclarationKind kind, 701 mozilla::Maybe<DeclarationKind>* out); 702 703 [[nodiscard]] bool isVarRedeclaredInEval( 704 TaggedParserAtomIndex name, ParserBase* parser, DeclarationKind kind, 705 mozilla::Maybe<DeclarationKind>* out); 706 707 enum DryRunOption { NotDryRun, DryRunInnermostScopeOnly }; 708 template <DryRunOption dryRunOption> 709 bool tryDeclareVarHelper(TaggedParserAtomIndex name, ParserBase* parser, 710 DeclarationKind kind, uint32_t beginPos, 711 mozilla::Maybe<DeclarationKind>* redeclaredKind, 712 uint32_t* prevPos); 713 }; 714 715 } // namespace frontend 716 717 } // namespace js 718 719 #endif // frontend_ParseContext_h