tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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