tor-browser

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

SharedContext.h (26404B)


      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_SharedContext_h
      8 #define frontend_SharedContext_h
      9 
     10 #include "mozilla/Assertions.h"
     11 #include "mozilla/Attributes.h"
     12 #include "mozilla/Maybe.h"
     13 
     14 #include <stddef.h>
     15 #include <stdint.h>
     16 
     17 #include "jstypes.h"
     18 
     19 #include "frontend/FunctionSyntaxKind.h"  // FunctionSyntaxKind
     20 #include "frontend/ParserAtom.h"          // TaggedParserAtomIndex
     21 #include "frontend/ScopeIndex.h"          // ScopeIndex
     22 #include "frontend/ScriptIndex.h"         // ScriptIndex
     23 #include "js/ColumnNumber.h"              // JS::LimitedColumnNumberOneOrigin
     24 #include "vm/FunctionFlags.h"             // js::FunctionFlags
     25 #include "vm/GeneratorAndAsyncKind.h"  // js::GeneratorKind, js::FunctionAsyncKind
     26 #include "vm/Scope.h"
     27 #include "vm/ScopeKind.h"
     28 #include "vm/SharedStencil.h"
     29 #include "vm/StencilEnums.h"
     30 
     31 namespace JS {
     32 class JS_PUBLIC_API ReadOnlyCompileOptions;
     33 struct WasmModule;
     34 }  // namespace JS
     35 
     36 namespace js {
     37 
     38 class FrontendContext;
     39 
     40 namespace frontend {
     41 
     42 struct CompilationState;
     43 class FunctionBox;
     44 class FunctionNode;
     45 class ParseContext;
     46 class ScriptStencil;
     47 class ScriptStencilExtra;
     48 struct ScopeContext;
     49 
     50 enum class StatementKind : uint8_t {
     51  Label,
     52  Block,
     53  If,
     54  Switch,
     55  With,
     56  Catch,
     57  Try,
     58  Finally,
     59  ForLoopLexicalHead,
     60  ForLoop,
     61  ForInLoop,
     62  ForOfLoop,
     63  DoLoop,
     64  WhileLoop,
     65  Class,
     66 
     67  // Used only by BytecodeEmitter.
     68  Spread,
     69  YieldStar,
     70 };
     71 
     72 static inline bool StatementKindIsLoop(StatementKind kind) {
     73  return kind == StatementKind::ForLoop || kind == StatementKind::ForInLoop ||
     74         kind == StatementKind::ForOfLoop || kind == StatementKind::DoLoop ||
     75         kind == StatementKind::WhileLoop || kind == StatementKind::Spread ||
     76         kind == StatementKind::YieldStar;
     77 }
     78 
     79 static inline bool StatementKindIsUnlabeledBreakTarget(StatementKind kind) {
     80  return StatementKindIsLoop(kind) || kind == StatementKind::Switch;
     81 }
     82 
     83 // List of directives that may be encountered in a Directive Prologue
     84 // (ES5 15.1).
     85 class Directives {
     86  bool strict_;
     87  bool asmJS_;
     88 
     89 public:
     90  explicit Directives(bool strict) : strict_(strict), asmJS_(false) {}
     91  explicit Directives(ParseContext* parent);
     92 
     93  void setStrict() { strict_ = true; }
     94  bool strict() const { return strict_; }
     95 
     96  void setAsmJS() { asmJS_ = true; }
     97  bool asmJS() const { return asmJS_; }
     98 
     99  Directives& operator=(Directives rhs) {
    100    strict_ = rhs.strict_;
    101    asmJS_ = rhs.asmJS_;
    102    return *this;
    103  }
    104  bool operator==(const Directives& rhs) const {
    105    return strict_ == rhs.strict_ && asmJS_ == rhs.asmJS_;
    106  }
    107  bool operator!=(const Directives& rhs) const { return !(*this == rhs); }
    108 };
    109 
    110 // The kind of this-binding for the current scope. Note that arrow functions
    111 // have a lexical this-binding so their ThisBinding is the same as the
    112 // ThisBinding of their enclosing scope and can be any value. Derived
    113 // constructors require TDZ checks when accessing the binding.
    114 enum class ThisBinding : uint8_t {
    115  Global,
    116  Module,
    117  Function,
    118  DerivedConstructor
    119 };
    120 
    121 // If Yes, the script inherits it's "this" environment and binding from the
    122 // enclosing script. This is true for arrow-functions and eval scripts.
    123 enum class InheritThis { No, Yes };
    124 
    125 class GlobalSharedContext;
    126 class EvalSharedContext;
    127 class ModuleSharedContext;
    128 class SuspendableContext;
    129 
    130 #define IMMUTABLE_FLAG_GETTER_SETTER(lowerName, name) \
    131  GENERIC_FLAG_GETTER_SETTER(ImmutableFlags, lowerName, name)
    132 
    133 #define IMMUTABLE_FLAG_GETTER(lowerName, name) \
    134  GENERIC_FLAG_GETTER(ImmutableFlags, lowerName, name)
    135 
    136 /*
    137 * The struct SharedContext is part of the current parser context (see
    138 * ParseContext). It stores information that is reused between the parser and
    139 * the bytecode emitter.
    140 */
    141 class SharedContext {
    142 public:
    143  FrontendContext* const fc_;
    144 
    145 protected:
    146  // See: BaseScript::immutableFlags_
    147  ImmutableScriptFlags immutableFlags_ = {};
    148 
    149  // The location of this script in the source. Note that the value here differs
    150  // from the final BaseScript for the case of standalone functions.
    151  // This field is copied to ScriptStencil, and shouldn't be modified after the
    152  // copy.
    153  SourceExtent extent_ = {};
    154 
    155 protected:
    156  // See: ThisBinding
    157  ThisBinding thisBinding_ = ThisBinding::Global;
    158 
    159  // These flags do not have corresponding script flags and may be inherited
    160  // from the scope chain in the case of eval and arrows.
    161  bool allowNewTarget_ : 1;
    162  bool allowSuperProperty_ : 1;
    163  bool allowSuperCall_ : 1;
    164  bool allowArguments_ : 1;
    165  bool inWith_ : 1;
    166  bool inClass_ : 1;
    167 
    168  // See `strict()` below.
    169  bool localStrict : 1;
    170 
    171  // True if "use strict"; appears in the body instead of being inherited.
    172  bool hasExplicitUseStrict_ : 1;
    173 
    174  // Tracks if script-related fields are already copied to ScriptStencilExtra.
    175  //
    176  // If this field is true, those fileds shouldn't be modified.
    177  //
    178  // For FunctionBox, some fields are allowed to be modified, but the
    179  // modification should be synced with ScriptStencilExtra by
    180  // FunctionBox::copyUpdated* methods.
    181  bool isScriptExtraFieldCopiedToStencil : 1;
    182 
    183  // Indicates this shared context is eligible to use JSOp::ArgumentsLength
    184  // when emitting the ArgumentsLength parse node.
    185  bool eligibleForArgumentsLength : 1;
    186 
    187  // End of fields.
    188 
    189  enum class Kind : uint8_t { FunctionBox, Global, Eval, Module };
    190 
    191  // Alias enum into SharedContext
    192  using ImmutableFlags = ImmutableScriptFlagsEnum;
    193 
    194  [[nodiscard]] bool hasFlag(ImmutableFlags flag) const {
    195    return immutableFlags_.hasFlag(flag);
    196  }
    197  void setFlag(ImmutableFlags flag, bool b = true) {
    198    MOZ_ASSERT(!isScriptExtraFieldCopiedToStencil);
    199    immutableFlags_.setFlag(flag, b);
    200  }
    201  void clearFlag(ImmutableFlags flag) {
    202    MOZ_ASSERT(!isScriptExtraFieldCopiedToStencil);
    203    immutableFlags_.clearFlag(flag);
    204  }
    205 
    206 public:
    207  SharedContext(FrontendContext* fc, Kind kind,
    208                const JS::ReadOnlyCompileOptions& options,
    209                Directives directives, SourceExtent extent);
    210 
    211  IMMUTABLE_FLAG_GETTER_SETTER(isForEval, IsForEval)
    212  IMMUTABLE_FLAG_GETTER_SETTER(isModule, IsModule)
    213  IMMUTABLE_FLAG_GETTER_SETTER(isFunction, IsFunction)
    214  IMMUTABLE_FLAG_GETTER_SETTER(selfHosted, SelfHosted)
    215  IMMUTABLE_FLAG_GETTER_SETTER(forceStrict, ForceStrict)
    216  IMMUTABLE_FLAG_GETTER_SETTER(hasNonSyntacticScope, HasNonSyntacticScope)
    217  IMMUTABLE_FLAG_GETTER_SETTER(noScriptRval, NoScriptRval)
    218  IMMUTABLE_FLAG_GETTER(treatAsRunOnce, TreatAsRunOnce)
    219  // Strict: custom logic below
    220  IMMUTABLE_FLAG_GETTER_SETTER(hasModuleGoal, HasModuleGoal)
    221  IMMUTABLE_FLAG_GETTER_SETTER(hasInnerFunctions, HasInnerFunctions)
    222  IMMUTABLE_FLAG_GETTER_SETTER(hasDirectEval, HasDirectEval)
    223  IMMUTABLE_FLAG_GETTER_SETTER(bindingsAccessedDynamically,
    224                               BindingsAccessedDynamically)
    225  IMMUTABLE_FLAG_GETTER_SETTER(hasCallSiteObj, HasCallSiteObj)
    226 
    227  const SourceExtent& extent() const { return extent_; }
    228 
    229  bool isFunctionBox() const { return isFunction(); }
    230  inline FunctionBox* asFunctionBox();
    231  bool isModuleContext() const { return isModule(); }
    232  inline ModuleSharedContext* asModuleContext();
    233  bool isSuspendableContext() const { return isFunction() || isModule(); }
    234  inline SuspendableContext* asSuspendableContext();
    235  bool isGlobalContext() const {
    236    return !(isFunction() || isModule() || isForEval());
    237  }
    238  inline GlobalSharedContext* asGlobalContext();
    239  bool isEvalContext() const { return isForEval(); }
    240  inline EvalSharedContext* asEvalContext();
    241 
    242  bool isTopLevelContext() const { return !isFunction(); }
    243 
    244  ThisBinding thisBinding() const { return thisBinding_; }
    245  bool hasFunctionThisBinding() const {
    246    return thisBinding() == ThisBinding::Function ||
    247           thisBinding() == ThisBinding::DerivedConstructor;
    248  }
    249  bool needsThisTDZChecks() const {
    250    return thisBinding() == ThisBinding::DerivedConstructor;
    251  }
    252 
    253  bool isSelfHosted() const { return selfHosted(); }
    254  bool allowNewTarget() const { return allowNewTarget_; }
    255  bool allowSuperProperty() const { return allowSuperProperty_; }
    256  bool allowSuperCall() const { return allowSuperCall_; }
    257  bool allowArguments() const { return allowArguments_; }
    258  bool inWith() const { return inWith_; }
    259  bool inClass() const { return inClass_; }
    260 
    261  bool hasExplicitUseStrict() const { return hasExplicitUseStrict_; }
    262  void setExplicitUseStrict() { hasExplicitUseStrict_ = true; }
    263 
    264  ImmutableScriptFlags immutableFlags() const { return immutableFlags_; }
    265 
    266  bool allBindingsClosedOver() const { return bindingsAccessedDynamically(); }
    267 
    268  // The ImmutableFlag tracks if the entire script is strict, while the
    269  // localStrict flag indicates the current region (such as class body) should
    270  // be treated as strict. The localStrict flag will always be reset to false
    271  // before the end of the script.
    272  bool strict() const { return hasFlag(ImmutableFlags::Strict) || localStrict; }
    273  void setStrictScript() { setFlag(ImmutableFlags::Strict); }
    274  bool setLocalStrictMode(bool strict) {
    275    bool retVal = localStrict;
    276    localStrict = strict;
    277    return retVal;
    278  }
    279 
    280  bool isEligibleForArgumentsLength() const {
    281    return eligibleForArgumentsLength && !bindingsAccessedDynamically();
    282  }
    283  void setIneligibleForArgumentsLength() { eligibleForArgumentsLength = false; }
    284 
    285  void copyScriptExtraFields(ScriptStencilExtra& scriptExtra);
    286 };
    287 
    288 class MOZ_STACK_CLASS GlobalSharedContext : public SharedContext {
    289  ScopeKind scopeKind_;
    290 
    291 public:
    292  GlobalScope::ParserData* bindings;
    293 
    294  GlobalSharedContext(FrontendContext* fc, ScopeKind scopeKind,
    295                      const JS::ReadOnlyCompileOptions& options,
    296                      Directives directives, SourceExtent extent);
    297 
    298  ScopeKind scopeKind() const { return scopeKind_; }
    299 };
    300 
    301 inline GlobalSharedContext* SharedContext::asGlobalContext() {
    302  MOZ_ASSERT(isGlobalContext());
    303  return static_cast<GlobalSharedContext*>(this);
    304 }
    305 
    306 class MOZ_STACK_CLASS EvalSharedContext : public SharedContext {
    307 public:
    308  EvalScope::ParserData* bindings;
    309 
    310  EvalSharedContext(FrontendContext* fc, CompilationState& compilationState,
    311                    SourceExtent extent);
    312 };
    313 
    314 inline EvalSharedContext* SharedContext::asEvalContext() {
    315  MOZ_ASSERT(isEvalContext());
    316  return static_cast<EvalSharedContext*>(this);
    317 }
    318 
    319 enum class HasHeritage { No, Yes };
    320 
    321 class SuspendableContext : public SharedContext {
    322 public:
    323  SuspendableContext(FrontendContext* fc, Kind kind,
    324                     const JS::ReadOnlyCompileOptions& options,
    325                     Directives directives, SourceExtent extent,
    326                     bool isGenerator, bool isAsync);
    327 
    328  IMMUTABLE_FLAG_GETTER_SETTER(isAsync, IsAsync)
    329  IMMUTABLE_FLAG_GETTER_SETTER(isGenerator, IsGenerator)
    330 
    331  bool needsFinalYield() const { return isGenerator() || isAsync(); }
    332  bool needsDotGeneratorName() const { return isGenerator() || isAsync(); }
    333  bool needsClearSlotsOnExit() const { return isGenerator() || isAsync(); }
    334  bool needsIteratorResult() const { return isGenerator() && !isAsync(); }
    335  bool needsPromiseResult() const { return isAsync() && !isGenerator(); }
    336 };
    337 
    338 class FunctionBox : public SuspendableContext {
    339  friend struct GCThingList;
    340 
    341  CompilationState& compilationState_;
    342 
    343  // If this FunctionBox refers to a lazy child of the function being
    344  // compiled, this field holds the child's immediately enclosing scope's index.
    345  // Once compilation succeeds, we will store the scope pointed by this in the
    346  // child's BaseScript.  (Debugger may become confused if lazy scripts refer to
    347  // partially initialized enclosing scopes, so we must avoid storing the
    348  // scope in the BaseScript until compilation has completed
    349  // successfully.)
    350  // This is copied to ScriptStencil.
    351  // Any update after the copy should be synced to the ScriptStencil.
    352  mozilla::Maybe<ScopeIndex> enclosingScopeIndex_;
    353 
    354  // Names from the named lambda scope, if a named lambda.
    355  LexicalScope::ParserData* namedLambdaBindings_ = nullptr;
    356 
    357  // Names from the function scope.
    358  FunctionScope::ParserData* functionScopeBindings_ = nullptr;
    359 
    360  // Names from the extra 'var' scope of the function, if the parameter list
    361  // has expressions.
    362  VarScope::ParserData* extraVarScopeBindings_ = nullptr;
    363 
    364  // The explicit or implicit name of the function. The FunctionFlags indicate
    365  // the kind of name.
    366  // This is copied to ScriptStencil.
    367  // Any update after the copy should be synced to the ScriptStencil.
    368  TaggedParserAtomIndex atom_;
    369 
    370  // Index into CompilationStencil::scriptData.
    371  ScriptIndex funcDataIndex_ = ScriptIndex(-1);
    372 
    373  // See: FunctionFlags
    374  // This is copied to ScriptStencil.
    375  // Any update after the copy should be synced to the ScriptStencil.
    376  FunctionFlags flags_ = {};
    377 
    378  // See: ImmutableScriptData::funLength
    379  uint16_t length_ = 0;
    380 
    381  // JSFunction::nargs_
    382  // This field is copied to ScriptStencil, and shouldn't be modified after the
    383  // copy.
    384  uint16_t nargs_ = 0;
    385 
    386  // See: PrivateScriptData::memberInitializers_
    387  // This field is copied to ScriptStencil, and shouldn't be modified after the
    388  // copy.
    389  MemberInitializers memberInitializers_ = MemberInitializers::Invalid();
    390 
    391 public:
    392  // Back pointer used by asm.js for error messages.
    393  FunctionNode* functionNode = nullptr;
    394 
    395  // True if bytecode will be emitted for this function in the current
    396  // compilation.
    397  bool emitBytecode : 1;
    398 
    399  // This is set by the BytecodeEmitter of the enclosing script when a reference
    400  // to this function is generated. This is also used to determine a hoisted
    401  // function already is referenced by the bytecode.
    402  bool wasEmittedByEnclosingScript_ : 1;
    403 
    404  // Need to emit a synthesized Annex B assignment
    405  bool isAnnexB : 1;
    406 
    407  // Track if we saw "use asm".
    408  // If we successfully validated it, `flags_` is seto to `AsmJS` kind.
    409  bool useAsm : 1;
    410 
    411  // Analysis of parameter list
    412  bool hasParameterExprs : 1;
    413  bool hasDestructuringArgs : 1;
    414  bool hasDuplicateParameters : 1;
    415 
    416  // Arrow function with expression body like: `() => 1`.
    417  bool hasExprBody_ : 1;
    418 
    419  // Used to issue an early error in static class blocks.
    420  bool allowReturn_ : 1;
    421 
    422  // Tracks if function-related fields are already copied to ScriptStencil.
    423  // If this field is true, modification to those fields should be synced with
    424  // ScriptStencil by copyUpdated* methods.
    425  bool isFunctionFieldCopiedToStencil : 1;
    426 
    427  // True if this is part of initial compilation.
    428  // False if this is part of delazification.
    429  bool isInitialCompilation : 1;
    430 
    431  // True if this is standalone function
    432  // (new Function() including generator/async, or event handler).
    433  bool isStandalone : 1;
    434 
    435  // End of fields.
    436 
    437  FunctionBox(FrontendContext* fc, SourceExtent extent,
    438              CompilationState& compilationState, Directives directives,
    439              GeneratorKind generatorKind, FunctionAsyncKind asyncKind,
    440              bool isInitialCompilation, TaggedParserAtomIndex atom,
    441              FunctionFlags flags, ScriptIndex index);
    442 
    443  ScriptStencil& functionStencil() const;
    444  ScriptStencilExtra& functionExtraStencil() const;
    445 
    446  LexicalScope::ParserData* namedLambdaBindings() {
    447    return namedLambdaBindings_;
    448  }
    449  void setNamedLambdaBindings(LexicalScope::ParserData* bindings) {
    450    namedLambdaBindings_ = bindings;
    451  }
    452 
    453  FunctionScope::ParserData* functionScopeBindings() {
    454    return functionScopeBindings_;
    455  }
    456  void setFunctionScopeBindings(FunctionScope::ParserData* bindings) {
    457    functionScopeBindings_ = bindings;
    458  }
    459 
    460  VarScope::ParserData* extraVarScopeBindings() {
    461    return extraVarScopeBindings_;
    462  }
    463  void setExtraVarScopeBindings(VarScope::ParserData* bindings) {
    464    extraVarScopeBindings_ = bindings;
    465  }
    466 
    467  void initFromLazyFunction(const ScriptStencilExtra& extra,
    468                            ScopeContext& scopeContext,
    469                            FunctionSyntaxKind kind);
    470  void initFromScriptStencilExtra(const ScriptStencilExtra& extra);
    471  void initStandalone(ScopeContext& scopeContext, FunctionSyntaxKind kind);
    472 
    473 private:
    474  void initStandaloneOrLazy(ScopeContext& scopeContext,
    475                            FunctionSyntaxKind kind);
    476 
    477 public:
    478  void initWithEnclosingParseContext(ParseContext* enclosing,
    479                                     FunctionSyntaxKind kind);
    480 
    481  void setEnclosingScopeForInnerLazyFunction(ScopeIndex scopeIndex);
    482 
    483  bool wasEmittedByEnclosingScript() const {
    484    return wasEmittedByEnclosingScript_;
    485  }
    486  void setWasEmittedByEnclosingScript(bool wasEmitted) {
    487    wasEmittedByEnclosingScript_ = wasEmitted;
    488    if (isFunctionFieldCopiedToStencil) {
    489      copyUpdatedWasEmitted();
    490    }
    491  }
    492 
    493  [[nodiscard]] bool setUseAsm();
    494  [[nodiscard]] bool setAsmJSModule(const JS::WasmModule* module);
    495  bool isAsmJSModule() const { return flags_.isAsmJSNative(); }
    496 
    497  bool hasEnclosingScopeIndex() const { return enclosingScopeIndex_.isSome(); }
    498  ScopeIndex getEnclosingScopeIndex() const { return *enclosingScopeIndex_; }
    499 
    500  IMMUTABLE_FLAG_GETTER_SETTER(isAsync, IsAsync)
    501  IMMUTABLE_FLAG_GETTER_SETTER(isGenerator, IsGenerator)
    502  IMMUTABLE_FLAG_GETTER_SETTER(funHasExtensibleScope, FunHasExtensibleScope)
    503  IMMUTABLE_FLAG_GETTER_SETTER(functionHasThisBinding, FunctionHasThisBinding)
    504  IMMUTABLE_FLAG_GETTER_SETTER(functionHasNewTargetBinding,
    505                               FunctionHasNewTargetBinding)
    506  // NeedsHomeObject: custom logic below.
    507  // IsDerivedClassConstructor: custom logic below.
    508  // IsFieldInitializer: custom logic below.
    509  IMMUTABLE_FLAG_GETTER(useMemberInitializers, UseMemberInitializers)
    510  IMMUTABLE_FLAG_GETTER_SETTER(hasRest, HasRest)
    511  IMMUTABLE_FLAG_GETTER_SETTER(needsFunctionEnvironmentObjects,
    512                               NeedsFunctionEnvironmentObjects)
    513  IMMUTABLE_FLAG_GETTER_SETTER(functionHasExtraBodyVarScope,
    514                               FunctionHasExtraBodyVarScope)
    515  IMMUTABLE_FLAG_GETTER_SETTER(shouldDeclareArguments, ShouldDeclareArguments)
    516  IMMUTABLE_FLAG_GETTER_SETTER(needsArgsObj, NeedsArgsObj)
    517  // HasMappedArgsObj: custom logic below.
    518 
    519  bool needsCallObjectRegardlessOfBindings() const {
    520    // Always create a CallObject if:
    521    // - The scope is extensible at runtime due to sloppy eval.
    522    // - The function is a generator or async function. (The debugger reads the
    523    //   generator object directly from the frame.)
    524 
    525    return funHasExtensibleScope() || isGenerator() || isAsync();
    526  }
    527 
    528  bool needsExtraBodyVarEnvironmentRegardlessOfBindings() const {
    529    MOZ_ASSERT(hasParameterExprs);
    530    return funHasExtensibleScope();
    531  }
    532 
    533  GeneratorKind generatorKind() const {
    534    return isGenerator() ? GeneratorKind::Generator
    535                         : GeneratorKind::NotGenerator;
    536  }
    537 
    538  FunctionAsyncKind asyncKind() const {
    539    return isAsync() ? FunctionAsyncKind::AsyncFunction
    540                     : FunctionAsyncKind::SyncFunction;
    541  }
    542 
    543  bool needsFinalYield() const { return isGenerator() || isAsync(); }
    544  bool needsDotGeneratorName() const { return isGenerator() || isAsync(); }
    545  bool needsClearSlotsOnExit() const { return isGenerator() || isAsync(); }
    546  bool needsIteratorResult() const { return isGenerator() && !isAsync(); }
    547  bool needsPromiseResult() const { return isAsync() && !isGenerator(); }
    548 
    549  bool isArrow() const { return flags_.isArrow(); }
    550  bool isLambda() const { return flags_.isLambda(); }
    551 
    552  bool hasExprBody() const { return hasExprBody_; }
    553  void setHasExprBody() {
    554    MOZ_ASSERT(isArrow());
    555    hasExprBody_ = true;
    556  }
    557 
    558  bool allowReturn() const { return allowReturn_; }
    559 
    560  bool isNamedLambda() const { return flags_.isNamedLambda(!!explicitName()); }
    561  bool isGetter() const { return flags_.isGetter(); }
    562  bool isSetter() const { return flags_.isSetter(); }
    563  bool isMethod() const { return flags_.isMethod(); }
    564  bool isClassConstructor() const { return flags_.isClassConstructor(); }
    565 
    566  bool isInterpreted() const { return flags_.hasBaseScript(); }
    567 
    568  FunctionFlags::FunctionKind kind() const { return flags_.kind(); }
    569 
    570  bool hasInferredName() const { return flags_.hasInferredName(); }
    571  bool hasGuessedAtom() const { return flags_.hasGuessedAtom(); }
    572 
    573  TaggedParserAtomIndex displayAtom() const { return atom_; }
    574  TaggedParserAtomIndex explicitName() const {
    575    return (hasInferredName() || hasGuessedAtom())
    576               ? TaggedParserAtomIndex::null()
    577               : atom_;
    578  }
    579 
    580  // NOTE: We propagate to any existing functions for now. This handles both the
    581  // delazification case where functions already exist, and also handles
    582  // code-coverage which is not yet deferred.
    583  void setInferredName(TaggedParserAtomIndex atom) {
    584    atom_ = atom;
    585    flags_.setInferredName();
    586    if (isFunctionFieldCopiedToStencil) {
    587      copyUpdatedAtomAndFlags();
    588    }
    589  }
    590  void setGuessedAtom(TaggedParserAtomIndex atom) {
    591    atom_ = atom;
    592    flags_.setGuessedAtom();
    593    if (isFunctionFieldCopiedToStencil) {
    594      copyUpdatedAtomAndFlags();
    595    }
    596  }
    597 
    598  bool needsHomeObject() const {
    599    return hasFlag(ImmutableFlags::NeedsHomeObject);
    600  }
    601  void setNeedsHomeObject() {
    602    MOZ_ASSERT(flags_.allowSuperProperty());
    603    setFlag(ImmutableFlags::NeedsHomeObject);
    604    flags_.setIsExtended();
    605  }
    606 
    607  bool isDerivedClassConstructor() const {
    608    return hasFlag(ImmutableFlags::IsDerivedClassConstructor);
    609  }
    610  void setDerivedClassConstructor() {
    611    MOZ_ASSERT(flags_.isClassConstructor());
    612    setFlag(ImmutableFlags::IsDerivedClassConstructor);
    613  }
    614 
    615  bool isSyntheticFunction() const {
    616    return hasFlag(ImmutableFlags::IsSyntheticFunction);
    617  }
    618  void setSyntheticFunction() {
    619    // Field initializer, class constructor or getter or setter
    620    // synthesized from accessor keyword.
    621    MOZ_ASSERT(flags_.isMethod() || flags_.isGetter() || flags_.isSetter());
    622    setFlag(ImmutableFlags::IsSyntheticFunction);
    623  }
    624 
    625  bool hasSimpleParameterList() const {
    626    return !hasRest() && !hasParameterExprs && !hasDestructuringArgs;
    627  }
    628 
    629  bool hasMappedArgsObj() const {
    630    return !strict() && hasSimpleParameterList();
    631  }
    632 
    633  // Return whether this or an enclosing function is being parsed and
    634  // validated as asm.js. Note: if asm.js validation fails, this will be false
    635  // while the function is being reparsed. This flag can be used to disable
    636  // certain parsing features that are necessary in general, but unnecessary
    637  // for validated asm.js.
    638  bool useAsmOrInsideUseAsm() const { return useAsm; }
    639 
    640  void setStart(uint32_t offset, uint32_t line,
    641                JS::LimitedColumnNumberOneOrigin column) {
    642    MOZ_ASSERT(!isScriptExtraFieldCopiedToStencil);
    643    extent_.sourceStart = offset;
    644    extent_.lineno = line;
    645    extent_.column = column;
    646  }
    647 
    648  void setEnd(uint32_t end) {
    649    MOZ_ASSERT(!isScriptExtraFieldCopiedToStencil);
    650    // For all functions except class constructors, the buffer and
    651    // toString ending positions are the same. Class constructors override
    652    // the toString ending position with the end of the class definition.
    653    extent_.sourceEnd = end;
    654    extent_.toStringEnd = end;
    655  }
    656 
    657  void setCtorToStringEnd(uint32_t end) {
    658    extent_.toStringEnd = end;
    659    if (isScriptExtraFieldCopiedToStencil) {
    660      copyUpdatedExtent();
    661    }
    662  }
    663 
    664  void setCtorFunctionHasThisBinding() {
    665    immutableFlags_.setFlag(ImmutableFlags::FunctionHasThisBinding, true);
    666    if (isScriptExtraFieldCopiedToStencil) {
    667      copyUpdatedImmutableFlags();
    668    }
    669  }
    670 
    671  void setIsInlinableLargeFunction() {
    672    immutableFlags_.setFlag(ImmutableFlags::IsInlinableLargeFunction, true);
    673    if (isScriptExtraFieldCopiedToStencil) {
    674      copyUpdatedImmutableFlags();
    675    }
    676  }
    677 
    678  void setUsesArgumentsIntrinsics() {
    679    immutableFlags_.setFlag(ImmutableFlags::UsesArgumentsIntrinsics, true);
    680    if (isScriptExtraFieldCopiedToStencil) {
    681      copyUpdatedImmutableFlags();
    682    }
    683  }
    684 
    685  uint16_t length() const { return length_; }
    686  void setLength(uint16_t length) { length_ = length; }
    687 
    688  void setArgCount(uint16_t args) {
    689    MOZ_ASSERT(!isFunctionFieldCopiedToStencil);
    690    nargs_ = args;
    691  }
    692 
    693  size_t nargs() const { return nargs_; }
    694 
    695  const MemberInitializers& memberInitializers() const {
    696    MOZ_ASSERT(useMemberInitializers());
    697    return memberInitializers_;
    698  }
    699  void setMemberInitializers(MemberInitializers memberInitializers) {
    700    immutableFlags_.setFlag(ImmutableFlags::UseMemberInitializers, true);
    701    memberInitializers_ = memberInitializers;
    702    if (isScriptExtraFieldCopiedToStencil) {
    703      copyUpdatedImmutableFlags();
    704      copyUpdatedMemberInitializers();
    705    }
    706  }
    707 
    708  ScriptIndex index() const { return funcDataIndex_; }
    709 
    710  void finishScriptFlags();
    711  void copyFunctionFields(ScriptStencil& script);
    712  void copyFunctionExtraFields(ScriptStencilExtra& scriptExtra);
    713 
    714  // * setCtorFunctionHasThisBinding can be called to a class constructor
    715  //   with a lazy function, while parsing enclosing class
    716  // * setIsInlinableLargeFunction can be called by BCE to update flags of the
    717  //   previous top-level function, but only in self-hosted mode.
    718  void copyUpdatedImmutableFlags();
    719 
    720  // * setCtorToStringEnd bcan be called to a class constructor with a lazy
    721  //   function, while parsing enclosing class
    722  void copyUpdatedExtent();
    723 
    724  // * setMemberInitializers can be called to a class constructor with a lazy
    725  //   function, while emitting enclosing script
    726  void copyUpdatedMemberInitializers();
    727 
    728  // * setEnclosingScopeForInnerLazyFunction can be called to a lazy function,
    729  //   while emitting enclosing script
    730  void copyUpdatedEnclosingScopeIndex();
    731 
    732  // * setInferredName can be called to a lazy function, while emitting
    733  //   enclosing script
    734  // * setGuessedAtom can be called to both lazy/non-lazy functions,
    735  //   while running NameFunctions
    736  void copyUpdatedAtomAndFlags();
    737 
    738  // * setWasEmitted can be called to a lazy function, while emitting
    739  //   enclosing script
    740  void copyUpdatedWasEmitted();
    741 };
    742 
    743 #undef FLAG_GETTER_SETTER
    744 #undef IMMUTABLE_FLAG_GETTER_SETTER
    745 
    746 inline FunctionBox* SharedContext::asFunctionBox() {
    747  MOZ_ASSERT(isFunctionBox());
    748  return static_cast<FunctionBox*>(this);
    749 }
    750 
    751 inline SuspendableContext* SharedContext::asSuspendableContext() {
    752  MOZ_ASSERT(isSuspendableContext());
    753  return static_cast<SuspendableContext*>(this);
    754 }
    755 
    756 }  // namespace frontend
    757 }  // namespace js
    758 
    759 #endif /* frontend_SharedContext_h */