tor-browser

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

EnvironmentObject.h (66869B)


      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 vm_EnvironmentObject_h
      8 #define vm_EnvironmentObject_h
      9 
     10 #include <type_traits>
     11 
     12 #include "frontend/NameAnalysisTypes.h"
     13 #include "gc/Barrier.h"
     14 #include "gc/WeakMap.h"
     15 #include "js/GCHashTable.h"
     16 #include "vm/ArgumentsObject.h"
     17 #include "vm/GlobalObject.h"
     18 #include "vm/JSObject.h"
     19 #include "vm/ProxyObject.h"
     20 #include "vm/Scope.h"
     21 #include "vm/ScopeKind.h"  // ScopeKind
     22 
     23 namespace JS {
     24 class JS_PUBLIC_API EnvironmentChain;
     25 enum class SupportUnscopables : bool;
     26 };  // namespace JS
     27 
     28 namespace js {
     29 
     30 class AbstractGeneratorObject;
     31 class IndirectBindingMap;
     32 class ModuleObject;
     33 
     34 // Return the name being accessed by the given ALIASEDVAR op. This function is
     35 // relatively slow so it should not be used on hot paths.
     36 extern PropertyName* EnvironmentCoordinateNameSlow(JSScript* script,
     37                                                   jsbytecode* pc);
     38 
     39 /*** Environment objects ****************************************************/
     40 
     41 // clang-format off
     42 /*
     43 * [SMDOC] Environment Objects
     44 *
     45 * About environments
     46 * ------------------
     47 *
     48 * See also: https://tc39.es/ecma262/#sec-environment-records
     49 *
     50 * Scoping in ES is specified in terms of "Environment Records". There's a
     51 * global Environment Record per realm, and a new Environment Record is created
     52 * whenever control enters a function, block, or other scope.
     53 *
     54 * A "Lexical Environment" is a list of nested Environment Records, innermost
     55 * first: everything that's in scope. Throughout SpiderMonkey, "environment"
     56 * means a Lexical Environment.
     57 *
     58 * N.B.: "Scope" means something different: a static scope, the compile-time
     59 * analogue of an environment. See Scope.h.
     60 *
     61 * How SpiderMonkey represents environments
     62 * ----------------------------------------
     63 *
     64 * Some environments are stored as JSObjects. Several kinds of objects
     65 * represent environments:
     66 *
     67 *   JSObject
     68 *    |
     69 *    +--NativeObject
     70 *    |   |
     71 *    |   +--EnvironmentObject          Engine-internal environment
     72 *    |   |   |
     73 *    |   |   +--CallObject             Environment of entire function
     74 *    |   |   |
     75 *    |   |   +--VarEnvironmentObject   See VarScope in Scope.h.
     76 *    |   |   |
     77 *    |   |   +--(DisposableEnvironmentObject)
     78 *    |   |   |   |                     Environment for `using x = ...`
     79 *    |   |   |   |                     (exists only when
     80 *    |   |   |   |                      ENABLE_EXPLICIT_RESOURCE_MANAGEMENT is
     81 *    |   |   |   |                      defined)
     82 *    |   |   |   |
     83 *    |   |   |   +--ModuleEnvironmentObject
     84 *    |   |   |   |
     85 *    |   |   |   +--LexicalEnvironmentObject
     86 *    |   |   |       |
     87 *    |   |   |       +--ScopedLexicalEnvironmentObject
     88 *    |   |   |       |   |             Non-extensible lexical environment
     89 *    |   |   |       |   |
     90 *    |   |   |       |   +--BlockLexicalEnvironmentObject
     91 *    |   |   |       |   |   |         Blocks and such: syntactic,
     92 *    |   |   |       |   |   |         non-extensible
     93 *    |   |   |       |   |   |
     94 *    |   |   |       |   |   +--NamedLambdaObject
     95 *    |   |   |       |   |             Environment for `(function f(){...})`
     96 *    |   |   |       |   |             containing only a binding for `f`
     97 *    |   |   |       |   |
     98 *    |   |   |       |   +--ClassBodyLexicalEnvironmentObject
     99 *    |   |   |       |                 Environment for class body, containing
    100 *    |   |   |       |                 private names, private brands, and
    101 *    |   |   |       |                 static initializers list
    102 *    |   |   |       |
    103 *    |   |   |       +--ExtensibleLexicalEnvironmentObject
    104 *    |   |   |           |
    105 *    |   |   |           +--GlobalLexicalEnvironmentObject
    106 *    |   |   |           |             Top-level let/const/class in scripts
    107 *    |   |   |           |
    108 *    |   |   |           +--NonSyntacticLexicalEnvironmentObject
    109 *    |   |   |                         See "Non-syntactic environments" below
    110 *    |   |   |
    111 *    |   |   +--NonSyntacticVariablesObject
    112 *    |   |   |                         See "Non-syntactic environments" below
    113 *    |   |   |
    114 *    |   |   +--WithEnvironmentObject  Presents object properties as bindings
    115 *    |   |   |
    116 *    |   |   +--RuntimeLexicalErrorObject
    117 *    |   |                             Special value represents uninitialized
    118 *    |   |                             lexical slots
    119 *    |   |
    120 *    |   +--GlobalObject               The global environment (dynamically
    121 *    |                                 presents its properties as bindings)
    122 *    +--ProxyObject
    123 *        |
    124 *        +--DebugEnvironmentProxy      Environment for debugger eval-in-frame
    125 *
    126 * EnvironmentObjects are technically real JSObjects but only belong on the
    127 * environment chain (that is, fp->environmentChain() or fun->environment()).
    128 * They are never exposed to scripts.
    129 *
    130 * Note that reserved slots in any base classes shown above are fixed for all
    131 * derived classes. So e.g. EnvironmentObject::enclosingEnvironment() can
    132 * simply access a fixed slot without further dynamic type information.
    133 *
    134 * When the current environment is represented by an object, the stack frame
    135 * has a pointer to that object (see AbstractFramePtr::environmentChain()).
    136 * However, that isn't always the case. Where possible, we store binding values
    137 * in JS stack slots. For block and function scopes where all bindings can be
    138 * stored in stack slots, nothing is allocated in the heap; there is no
    139 * environment object.
    140 *
    141 * Full information about the environment chain is always recoverable:
    142 * EnvironmentIter can do it, and we construct a fake environment for debugger
    143 * eval-in-frame (see "Debug environment objects" below).
    144 *
    145 * Syntactic Environments
    146 * ----------------------
    147 *
    148 * Environments may be syntactic, i.e., corresponding to source text, or
    149 * non-syntactic, i.e., specially created by embedding. The distinction is
    150 * necessary to maintain invariants about the environment chain: non-syntactic
    151 * environments may not occur in arbitrary positions in the chain.
    152 *
    153 * CallObject, ModuleEnvironmentObject, BlockLexicalEnvironmentObject, and
    154 * GlobalLexicalEnvironmentObject always represent syntactic
    155 * environments. (CallObject is considered syntactic even when it's used as the
    156 * scope of strict eval code.) WithEnvironmentObject is syntactic when it's
    157 * used to represent the scope of a `with` block.
    158 *
    159 *
    160 * Non-syntactic Environments
    161 * --------------------------
    162 *
    163 * A non-syntactic environment is one that was not created due to JS source
    164 * code. On the scope chain, a single NonSyntactic GlobalScope maps to 0+
    165 * non-syntactic environment objects. This is contrasted with syntactic
    166 * environments, where each scope corresponds to 0 or 1 environment object.
    167 *
    168 * There are 3 kinds of dynamic environment objects:
    169 *
    170 * 1. WithEnvironmentObject
    171 *
    172 *    When the embedding compiles or executes a script, it has the option to
    173 *    pass in a vector of objects to be used as the initial env chain, ordered
    174 *    from outermost env to innermost env. Each of those objects is wrapped by
    175 *    a WithEnvironmentObject.
    176 *
    177 *    The innermost object passed in by the embedding becomes a qualified
    178 *    variables object that captures 'var' bindings. That is, it wraps the
    179 *    holder object of 'var' bindings.
    180 *
    181 *    Does not hold 'let' or 'const' bindings.
    182 *
    183 *    The embedding can specify whether these non-syntactic WithEnvironment
    184 *    objects support Symbol.unscopables similar to syntactic 'with' statements
    185 *    in JS. In Firefox, we support Symbol.unscopables only for DOM event
    186 *    handlers because this is required by the spec.
    187 *
    188 * 2. NonSyntacticVariablesObject
    189 *
    190 *    When the embedding wants qualified 'var' bindings and unqualified
    191 *    bareword assignments to go on a different object than the global
    192 *    object. While any object can be made into a qualified variables object,
    193 *    only the GlobalObject and NonSyntacticVariablesObject are considered
    194 *    unqualified variables objects.
    195 *
    196 *    Unlike WithEnvironmentObjects that delegate to the object they wrap,
    197 *    this object is itself the holder of 'var' bindings.
    198 *
    199 *    Does not hold 'let' or 'const' bindings.
    200 *
    201 * 3. NonSyntacticLexicalEnvironmentObject
    202 *
    203 *    Each non-syntactic object used as a qualified variables object needs to
    204 *    enclose a non-syntactic lexical environment to hold 'let' and 'const'
    205 *    bindings. There is a bijection per realm between the non-syntactic
    206 *    variables objects and their non-syntactic LexicalEnvironmentObjects.
    207 *
    208 *    Does not hold 'var' bindings.
    209 *
    210 * The embedding (Gecko) and debugger uses non-syntactic envs for various
    211 * things, all of which are detailed below. All env chain listings below are,
    212 * from top to bottom, outermost to innermost.
    213 *
    214 * A. JSM loading
    215 *
    216 * Most JSMs are loaded into a shared system global in order to save the memory
    217 * consumption and avoid CCWs. To support this, a NonSyntacticVariablesObject
    218 * is used for each JSM to provide a basic form of isolation.
    219 * NonSyntacticLexicalEnvironmentObject and
    220 * NonSyntacticVariablesObject are allocated for each JSM, and
    221 * NonSyntacticLexicalEnvironmentObject holds lexical variables and
    222 * NonSyntacticVariablesObject holds qualified variables. JSMs cannot have
    223 * unqualified names, but if unqualified names are used by subscript, they
    224 * goes to NonSyntacticVariablesObject (see C.3 and C.4).
    225 * They have the following env chain:
    226 *
    227 *   SystemGlobal
    228 *       |
    229 *   GlobalLexicalEnvironmentObject[this=global]
    230 *       |
    231 *   NonSyntacticVariablesObject (qualified 'var's (and unqualified names))
    232 *       |
    233 *   NonSyntacticLexicalEnvironmentObject[this=nsvo] (lexical vars)
    234 *
    235 * B.1. Frame scripts with unique scope
    236 *
    237 * XUL frame scripts with unique scope are loaded in the same global as
    238 * JSMs, with a NonSyntacticVariablesObject as a "polluting global" for
    239 * both qualified 'var' variables and unqualified names, and a with
    240 * environment wrapping a message manager object, and
    241 * NonSyntacticLexicalEnvironmentObject holding the message manager as `this`,
    242 * that holds lexical variables.
    243 * These environment objects, except for globals, are created for each
    244 * execution of js::ExecuteInFrameScriptEnvironment.
    245 *
    246 *   SystemGlobal
    247 *       |
    248 *   GlobalLexicalEnvironmentObject[this=global]
    249 *       |
    250 *   NonSyntacticVariablesObject (qualified 'var's and unqualified names)
    251 *       |
    252 *   WithEnvironmentObject [SupportUnscopables=No] wrapping messageManager
    253 *       |
    254 *   NonSyntacticLexicalEnvironmentObject[this=messageManager] (lexical vars)
    255 *
    256 * B.2. Frame scripts without unique scope
    257 *
    258 * XUL frame scripts without unique scope are loaded in the same global as
    259 * JSMs with JS_ExecuteScript, with a with environment wrapping a message
    260 * manager object for qualified 'var' variables, and
    261 * NonSyntacticLexicalEnvironmentObject holding the message manager as `this`,
    262 * that holds lexical variables.
    263 * The environment chain is associated with the message manager object
    264 * and cached for subsequent executions.
    265 *
    266 *   SystemGlobal (unqualified names)
    267 *       |
    268 *   GlobalLexicalEnvironmentObject[this=global]
    269 *       |
    270 *   WithEnvironmentObject [SupportUnscopables=No] wrapping messageManager
    271 *     (qualified 'var's)
    272 *       |
    273 *   NonSyntacticLexicalEnvironmentObject[this=messageManager] (lexical vars)
    274 *
    275 * C.1 Subscript loading into a target object
    276 *
    277 * Subscripts may be loaded into a target object and it's associated global.
    278 * NonSyntacticLexicalEnvironmentObject holds lexical variables and
    279 * WithEnvironmentObject holds qualified variables. Unqualified names goes
    280 * to the target object's global.
    281 * They have the following env chain:
    282 *
    283 *   Target object's global (unqualified names)
    284 *       |
    285 *   GlobalLexicalEnvironmentObject[this=global]
    286 *       |
    287 *   WithEnvironmentObject [SupportUnscopables=No] wrapping target
    288 *     (qualified 'var's)
    289 *       |
    290 *   NonSyntacticLexicalEnvironmentObject[this=target] (lexical vars)
    291 *
    292 * C.2 Subscript loading into global this
    293 *
    294 * Subscript may be loaded into global this. In this case no extra environment
    295 * object is created.
    296 *
    297 *   global (qualified 'var's and unqualified names)
    298 *       |
    299 *   GlobalLexicalEnvironmentObject[this=global] (lexical vars)
    300 *
    301 * C.3 Subscript loading into a target object in JSM
    302 *
    303 * The target object of a subscript load may be in a JSM, in which case we will
    304 * also have the NonSyntacticVariablesObject on the chain.
    305 * NonSyntacticLexicalEnvironmentObject for target object holds lexical
    306 * variables and WithEnvironmentObject holds qualified variables.
    307 * Unqualified names goes to NonSyntacticVariablesObject.
    308 *
    309 *   SystemGlobal
    310 *       |
    311 *   GlobalLexicalEnvironmentObject[this=global]
    312 *       |
    313 *   NonSyntacticVariablesObject (unqualified names)
    314 *       |
    315 *   NonSyntacticLexicalEnvironmentObject[this=nsvo]
    316 *       |
    317 *   WithEnvironmentObject [SupportUnscopables=No] wrapping target
    318 *     (qualified 'var's)
    319 *       |
    320 *   NonSyntacticLexicalEnvironmentObject[this=target] (lexical vars)
    321 *
    322 * C.4 Subscript loading into per-JSM this
    323 *
    324 * Subscript may be loaded into global this.  In this case no extra environment
    325 * object is created.
    326 *
    327 *   SystemGlobal
    328 *       |
    329 *   GlobalLexicalEnvironmentObject[this=global]
    330 *       |
    331 *   NonSyntacticVariablesObject (qualified 'var's and unqualified names)
    332 *       |
    333 *   NonSyntacticLexicalEnvironmentObject[this=nsvo] (lexical vars)
    334 *
    335 * C.5. Subscript loading into a target object in a frame script with unique
    336 *      scope
    337 *
    338 * Subscript may be loaded into a target object inside a frame script
    339 * environment.  If the frame script has an unique scope, the subscript inherits
    340 * the unique scope, with additional WithEnvironmentObject and NSLEO are
    341 * created for qualified variables.
    342 *
    343 *   SystemGlobal
    344 *       |
    345 *   GlobalLexicalEnvironmentObject[this=global]
    346 *       |
    347 *   NonSyntacticVariablesObject (unqualified names)
    348 *       |
    349 *   WithEnvironmentObject [SupportUnscopables=No] wrapping messageManager
    350 *       |
    351 *   NonSyntacticLexicalEnvironmentObject[this=messageManager]
    352 *       |
    353 *   WithEnvironmentObject [SupportUnscopables=No] wrapping target
    354 *     (qualified 'var's)
    355 *       |
    356 *   NonSyntacticLexicalEnvironmentObject[this=target] (lexical vars)
    357 *
    358 * C.6. Subscript loading into a target object in a frame script without unique
    359 *      scope
    360 *
    361 * If the frame script doesn't have an unique scope, the subscript uses the
    362 * global scope, with additional WithEnvironmentObject and NSLEO are
    363 * created for qualified variables.
    364 *
    365 *   SystemGlobal (unqualified names)
    366 *       |
    367 *   GlobalLexicalEnvironmentObject[this=global]
    368 *       |
    369 *   WithEnvironmentObject [SupportUnscopables=No] wrapping target
    370 *     (qualified 'var's)
    371 *       |
    372 *   NonSyntacticLexicalEnvironmentObject[this=target] (lexical vars)
    373 *
    374 * C.7. Subscript loading into a frame script with unique scope
    375 *
    376 * If a subscript doesn't use a target object and the frame script has an
    377 * unique scope, the subscript uses the same environment as the frame script.
    378 *
    379 *   SystemGlobal
    380 *       |
    381 *   GlobalLexicalEnvironmentObject[this=global]
    382 *       |
    383 *   NonSyntacticVariablesObject (qualified 'var's and unqualified names)
    384 *       |
    385 *   WithEnvironmentObject [SupportUnscopables=No] wrapping messageManager
    386 *       |
    387 *   NonSyntacticLexicalEnvironmentObject[this=messageManager] (lexical vars)
    388 *
    389 * C.8. Subscript loading into a frame script without unique scope
    390 *
    391 * If a subscript doesn't use a target object and the frame script doesn't have
    392 * an unique scope, the subscript uses the global scope.
    393 *
    394 *   SystemGlobal (qualified 'var's and unqualified names)
    395 *       |
    396 *   GlobalLexicalEnvironmentObject[this=global] (lexical vars)
    397 *
    398 * D.1. DOM event handlers without direct eval
    399 *
    400 * DOM event handlers are compiled as functions with HTML elements on the
    401 * environment chain. For a chain of elements e0, e1, ..., eN, where innerrmost
    402 * element is the target element, enclosing elements are such as forms, and the
    403 * outermost one is the document.
    404 * If the DOM event handlers don't have direct eval, the function's scopes are
    405 * optimized and frame slots are used for qualified 'var's and lexical vars.
    406 * NonSyntacticLexicalEnvironmentObject's `this` value is not used, given
    407 * the function's `this` value is used instead:
    408 *
    409 *   global (unqualified names)
    410 *       |
    411 *   GlobalLexicalEnvironmentObject[this=global]
    412 *       |
    413 *   WithEnvironmentObject [SupportUnscopables=Yes] wrapping eN
    414 *       |
    415 *      ...
    416 *       |
    417 *   WithEnvironmentObject [SupportUnscopables=Yes] wrapping e1
    418 *       |
    419 *   WithEnvironmentObject [SupportUnscopables=Yes] wrapping e0
    420 *       |
    421 *   NonSyntacticLexicalEnvironmentObject [this=*unused*]
    422 *
    423 * D.2. DOM event handlers with direct eval
    424 *
    425 * If DOM event handlers have direct eval, the function's scopes are allocated
    426 * as environment object:
    427 *
    428 *   global (unqualified names)
    429 *       |
    430 *   GlobalLexicalEnvironmentObject[this=global]
    431 *       |
    432 *      ...
    433 *       |
    434 *   WithEnvironmentObject [SupportUnscopables=Yes] wrapping e1
    435 *       |
    436 *   WithEnvironmentObject [SupportUnscopables=Yes] wrapping e0
    437 *       |
    438 *   NonSyntacticLexicalEnvironmentObject [this=*unused*]
    439 *       |
    440 *   CallObject (qualified 'var's)
    441 *       |
    442 *   BlockLexicalEnvironmentObject (lexical vars)
    443 *
    444 * E.1. Debugger.Frame.prototype.evalWithBindings
    445 *
    446 * Debugger.Frame.prototype.evalWithBindings uses WithEnvironmentObject for
    447 * given bindings, and the frame's enclosing scope.
    448 *
    449 * If qualified 'var's or unqualified names conflict with the bindings object's
    450 * properties, they go to the WithEnvironmentObject.
    451 *
    452 * If the frame is function, it has the following env chain.
    453 * lexical variables are optimized and uses frame slots, regardless of the name
    454 * conflicts with bindings:
    455 *
    456 *   global (unqualified names)
    457 *       |
    458 *   [DebugProxy] GlobalLexicalEnvironmentObject[this=global]
    459 *       |
    460 *   [DebugProxy] CallObject (qualified 'var's)
    461 *       |
    462 *   WithEnvironmentObject [SupportUnscopables=No] wrapping bindings
    463 *     (conflicting 'var's and names)
    464 *
    465 * If the script has direct eval, BlockLexicalEnvironmentObject is created for
    466 * it:
    467 *
    468 *   global (unqualified names)
    469 *       |
    470 *   [DebugProxy] GlobalLexicalEnvironmentObject[this=global]
    471 *       |
    472 *   [DebugProxy] CallObject (qualified 'var's)
    473 *       |
    474 *   WithEnvironmentObject [SupportUnscopables=No] wrapping bindings
    475 *     (conflicting 'var's and names)
    476 *       |
    477 *   BlockLexicalEnvironmentObject (lexical vars, and conflicting lexical vars)
    478 *
    479 * NOTE: Debugger.Frame.prototype.eval uses the frame's enclosing scope only,
    480 *       and it doesn't use any dynamic environment, but still uses
    481 *       non-syntactic scope to perform `eval` operation.
    482 *
    483 * E.2. Debugger.Object.prototype.executeInGlobalWithBindings
    484 *
    485 * Debugger.Object.prototype.executeInGlobalWithBindings uses
    486 * WithEnvironmentObject for given bindings, and the object's global scope.
    487 *
    488 * If `options.useInnerBindings` is not true, if bindings conflict with
    489 * qualified 'var's or global lexicals, those bindings are shadowed and not
    490 * stored into the bindings object wrapped by WithEnvironmentObject.
    491 *
    492 *   global (qualified 'var's and unqualified names)
    493 *       |
    494 *   GlobalLexicalEnvironmentObject[this=global] (lexical vars)
    495 *       |
    496 *   WithEnvironmentObject [SupportUnscopables=No] wrapping object with
    497 *     not-conflicting bindings
    498 *
    499 * If `options.useInnerBindings` is true, all bindings are stored into the
    500 * bindings object wrapped by WithEnvironmentObject, and they shadow globals
    501 *
    502 *   global (qualified 'var's and unqualified names)
    503 *       |
    504 *   GlobalLexicalEnvironmentObject[this=global] (lexical vars)
    505 *       |
    506 *   WithEnvironmentObject [SupportUnscopables=No] wrapping object with all
    507 *     bindings
    508 *
    509 * NOTE: If `options.useInnerBindings` is true, and if lexical variable names
    510 *       conflict with the bindings object's properties, the write on them
    511 *       within declarations is done for the GlobalLexicalEnvironmentObject,
    512 *       but the write within assignments and the read on lexicals are done
    513 *       from the WithEnvironmentObject (bug 1841964 and bug 1847219).
    514 *
    515 *   // bindings = { x: 10, y: 20 };
    516 *
    517 *   let x = 11; // written to GlobalLexicalEnvironmentObject
    518 *   x;          // read from WithEnvironmentObject
    519 *   let y;
    520 *   y = 21;     // written to WithEnvironmentObject
    521 *   y;          // read from WithEnvironmentObject
    522 *
    523 * NOTE: Debugger.Object.prototype.executeInGlobal uses the object's global
    524 *       scope only, and it doesn't use any dynamic environment or
    525 *       non-syntactic scope.
    526 * NOTE: If no extra bindings are used by script,
    527 *       Debugger.Object.prototype.executeInGlobalWithBindings uses the object's
    528 *       global scope only, and it doesn't use any dynamic environment or
    529 *       non-syntactic scope.
    530 *
    531 */
    532 // clang-format on
    533 
    534 class EnvironmentObject : public NativeObject {
    535 protected:
    536  // The enclosing environment. Either another EnvironmentObject, a
    537  // GlobalObject, or a non-syntactic environment object.
    538  static const uint32_t ENCLOSING_ENV_SLOT = 0;
    539 
    540  inline void setAliasedBinding(uint32_t slot, const Value& v);
    541 
    542 public:
    543  // Since every env chain terminates with a global object, whether
    544  // GlobalObject or a non-syntactic one, and since those objects do not
    545  // derive EnvironmentObject (they have completely different layouts), the
    546  // enclosing environment of an EnvironmentObject is necessarily non-null.
    547  JSObject& enclosingEnvironment() const {
    548    return getReservedSlot(ENCLOSING_ENV_SLOT).toObject();
    549  }
    550 
    551  void initEnclosingEnvironment(JSObject* enclosing) {
    552    initReservedSlot(ENCLOSING_ENV_SLOT, ObjectOrNullValue(enclosing));
    553  }
    554 
    555  static bool nonExtensibleIsFixedSlot(EnvironmentCoordinate ec) {
    556    // For non-extensible environment objects isFixedSlot(slot) is equivalent to
    557    // slot < MAX_FIXED_SLOTS.
    558    return ec.slot() < MAX_FIXED_SLOTS;
    559  }
    560  static size_t nonExtensibleDynamicSlotIndex(EnvironmentCoordinate ec) {
    561    MOZ_ASSERT(!nonExtensibleIsFixedSlot(ec));
    562    return ec.slot() - MAX_FIXED_SLOTS;
    563  }
    564 
    565  // Get or set a name contained in this environment.
    566  inline const Value& aliasedBinding(EnvironmentCoordinate ec);
    567 
    568  const Value& aliasedBinding(const BindingIter& bi) {
    569    MOZ_ASSERT(bi.location().kind() == BindingLocation::Kind::Environment);
    570    return getSlot(bi.location().slot());
    571  }
    572 
    573  inline void setAliasedBinding(EnvironmentCoordinate ec, const Value& v);
    574 
    575  inline void setAliasedBinding(const BindingIter& bi, const Value& v);
    576 
    577  // For JITs.
    578  static size_t offsetOfEnclosingEnvironment() {
    579    return getFixedSlotOffset(ENCLOSING_ENV_SLOT);
    580  }
    581 
    582  static uint32_t enclosingEnvironmentSlot() { return ENCLOSING_ENV_SLOT; }
    583 
    584  const char* typeString() const;
    585 
    586 #if defined(DEBUG) || defined(JS_JITSPEW)
    587  void dump();
    588 #endif /* defined(DEBUG) || defined(JS_JITSPEW) */
    589 };
    590 
    591 #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT
    592 class DisposableEnvironmentObject : public EnvironmentObject {
    593 protected:
    594  static constexpr uint32_t DISPOSABLE_RESOURCE_STACK_SLOT = 1;
    595 
    596 public:
    597  static constexpr uint32_t RESERVED_SLOTS = 2;
    598 
    599  ArrayObject* getOrCreateDisposeCapability(JSContext* cx);
    600 
    601  // Used to get the Disposable objects within the
    602  // lexical scope, it returns a ArrayObject if there
    603  // is a non empty list of Disposables, else
    604  // UndefinedValue.
    605  JS::Value getDisposables();
    606 
    607  void clearDisposables();
    608 
    609  // For JITs
    610  static size_t offsetOfDisposeCapability() {
    611    return getFixedSlotOffset(DISPOSABLE_RESOURCE_STACK_SLOT);
    612  }
    613 };
    614 #endif
    615 
    616 class CallObject : public EnvironmentObject {
    617 protected:
    618  static constexpr uint32_t CALLEE_SLOT = 1;
    619 
    620  static CallObject* create(JSContext* cx, HandleScript script,
    621                            HandleObject enclosing, gc::Heap heap,
    622                            gc::AllocSite* site = nullptr);
    623 
    624 public:
    625  static const JSClass class_;
    626 
    627  static constexpr uint32_t RESERVED_SLOTS = 2;
    628  static constexpr ObjectFlags OBJECT_FLAGS = {ObjectFlag::QualifiedVarObj};
    629 
    630  /* These functions are internal and are exposed only for JITs. */
    631 
    632  /*
    633   * Construct a bare-bones call object given a shape.
    634   * The call object must be further initialized to be usable.
    635   */
    636  static CallObject* createWithShape(JSContext* cx, Handle<SharedShape*> shape,
    637                                     gc::Heap heap = gc::Heap::Default);
    638 
    639  static CallObject* createTemplateObject(JSContext* cx, HandleScript script,
    640                                          HandleObject enclosing);
    641 
    642  static CallObject* createForFrame(JSContext* cx, AbstractFramePtr frame,
    643                                    gc::AllocSite* site);
    644 
    645  static CallObject* createHollowForDebug(JSContext* cx, HandleFunction callee);
    646 
    647  // If `env` or any enclosing environment is a CallObject, return that
    648  // CallObject; else null.
    649  //
    650  // `env` may be a DebugEnvironmentProxy, but not a hollow environment.
    651  static CallObject* find(JSObject* env);
    652 
    653  /*
    654   * When an aliased formal (var accessed by nested closures) is also
    655   * aliased by the arguments object, it must of course exist in one
    656   * canonical location and that location is always the CallObject. For this
    657   * to work, the ArgumentsObject stores special MagicValue in its array for
    658   * forwarded-to-CallObject variables. This MagicValue's payload is the
    659   * slot of the CallObject to access.
    660   */
    661  const Value& aliasedFormalFromArguments(const Value& argsValue) {
    662    return getSlot(ArgumentsObject::SlotFromMagicScopeSlotValue(argsValue));
    663  }
    664  inline void setAliasedFormalFromArguments(const Value& argsValue,
    665                                            const Value& v);
    666 
    667  JSFunction& callee() const {
    668    return getReservedSlot(CALLEE_SLOT).toObject().as<JSFunction>();
    669  }
    670 
    671  /* For jit access. */
    672  static size_t offsetOfCallee() { return getFixedSlotOffset(CALLEE_SLOT); }
    673 
    674  static size_t calleeSlot() { return CALLEE_SLOT; }
    675 };
    676 
    677 class VarEnvironmentObject : public EnvironmentObject {
    678  static constexpr uint32_t SCOPE_SLOT = 1;
    679 
    680  static VarEnvironmentObject* createInternal(JSContext* cx,
    681                                              Handle<SharedShape*> shape,
    682                                              HandleObject enclosing,
    683                                              gc::Heap heap);
    684 
    685  static VarEnvironmentObject* create(JSContext* cx, Handle<Scope*> scope,
    686                                      HandleObject enclosing, gc::Heap heap);
    687 
    688  void initScope(Scope* scope) {
    689    initReservedSlot(SCOPE_SLOT, PrivateGCThingValue(scope));
    690  }
    691 
    692 public:
    693  static const JSClass class_;
    694 
    695  static constexpr uint32_t RESERVED_SLOTS = 2;
    696  static constexpr ObjectFlags OBJECT_FLAGS = {ObjectFlag::QualifiedVarObj};
    697 
    698  static VarEnvironmentObject* createForFrame(JSContext* cx,
    699                                              Handle<Scope*> scope,
    700                                              AbstractFramePtr frame);
    701  static VarEnvironmentObject* createHollowForDebug(JSContext* cx,
    702                                                    Handle<Scope*> scope);
    703  static VarEnvironmentObject* createTemplateObject(JSContext* cx,
    704                                                    Handle<VarScope*> scope);
    705  static VarEnvironmentObject* createWithoutEnclosing(JSContext* cx,
    706                                                      Handle<VarScope*> scope);
    707 
    708  Scope& scope() const {
    709    Value v = getReservedSlot(SCOPE_SLOT);
    710    MOZ_ASSERT(v.isPrivateGCThing());
    711    Scope& s = *static_cast<Scope*>(v.toGCThing());
    712    MOZ_ASSERT(s.is<VarScope>() || s.is<EvalScope>());
    713    return s;
    714  }
    715 
    716  bool isForEval() const { return scope().is<EvalScope>(); }
    717  bool isForNonStrictEval() const { return scope().kind() == ScopeKind::Eval; }
    718 };
    719 
    720 #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT
    721 class ModuleEnvironmentObject : public DisposableEnvironmentObject {
    722 #else
    723 class ModuleEnvironmentObject : public EnvironmentObject {
    724 #endif
    725 #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT
    726  static constexpr uint32_t MODULE_SLOT =
    727      DisposableEnvironmentObject::RESERVED_SLOTS;
    728 #else
    729  static constexpr uint32_t MODULE_SLOT = 1;
    730 #endif
    731 
    732  static const ObjectOps objectOps_;
    733  static const JSClassOps classOps_;
    734 
    735 public:
    736  using EnvironmentObject::setAliasedBinding;
    737 
    738  static const JSClass class_;
    739 
    740 #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT
    741  // While there are only 3 reserved slots, this needs to be set to 4, given
    742  // there are some code expect the number of fixed slot to be same as the
    743  // number of reserved slots for the lexical environments (bug 1913864).
    744  static constexpr uint32_t RESERVED_SLOTS =
    745      DisposableEnvironmentObject::RESERVED_SLOTS + 2;
    746 #else
    747  static constexpr uint32_t RESERVED_SLOTS = 2;
    748 #endif
    749 
    750  static constexpr ObjectFlags OBJECT_FLAGS = {ObjectFlag::NotExtensible,
    751                                               ObjectFlag::QualifiedVarObj};
    752 
    753  static ModuleEnvironmentObject* create(JSContext* cx,
    754                                         Handle<ModuleObject*> module);
    755  static ModuleEnvironmentObject* createSynthetic(JSContext* cx,
    756                                                  Handle<ModuleObject*> module);
    757 
    758  ModuleObject& module() const;
    759  IndirectBindingMap& importBindings() const;
    760 
    761  bool createImportBinding(JSContext* cx, Handle<JSAtom*> importName,
    762                           Handle<ModuleObject*> module,
    763                           Handle<JSAtom*> exportName);
    764 
    765  bool hasImportBinding(Handle<PropertyName*> name);
    766 
    767  bool lookupImport(jsid name, ModuleEnvironmentObject** envOut,
    768                    mozilla::Maybe<PropertyInfo>* propOut);
    769 
    770  // If `env` or any enclosing environment is a ModuleEnvironmentObject,
    771  // return that ModuleEnvironmentObject; else null.
    772  //
    773  // `env` may be a DebugEnvironmentProxy, but not a hollow environment.
    774  static ModuleEnvironmentObject* find(JSObject* env);
    775 
    776  uint32_t firstSyntheticValueSlot() { return RESERVED_SLOTS; }
    777 
    778 private:
    779  static bool lookupProperty(JSContext* cx, HandleObject obj, HandleId id,
    780                             MutableHandleObject objp, PropertyResult* propp);
    781  static bool hasProperty(JSContext* cx, HandleObject obj, HandleId id,
    782                          bool* foundp);
    783  static bool getProperty(JSContext* cx, HandleObject obj, HandleValue receiver,
    784                          HandleId id, MutableHandleValue vp);
    785  static bool setProperty(JSContext* cx, HandleObject obj, HandleId id,
    786                          HandleValue v, HandleValue receiver,
    787                          JS::ObjectOpResult& result);
    788  static bool getOwnPropertyDescriptor(
    789      JSContext* cx, HandleObject obj, HandleId id,
    790      MutableHandle<mozilla::Maybe<PropertyDescriptor>> desc);
    791  static bool deleteProperty(JSContext* cx, HandleObject obj, HandleId id,
    792                             ObjectOpResult& result);
    793  static bool newEnumerate(JSContext* cx, HandleObject obj,
    794                           MutableHandleIdVector properties,
    795                           bool enumerableOnly);
    796 };
    797 
    798 class WasmInstanceEnvironmentObject : public EnvironmentObject {
    799  // Currently WasmInstanceScopes do not use their scopes in a
    800  // meaningful way. However, it is an invariant of DebugEnvironments that
    801  // environments kept in those maps have live scopes, thus this strong
    802  // reference.
    803  static constexpr uint32_t SCOPE_SLOT = 1;
    804 
    805 public:
    806  static const JSClass class_;
    807 
    808  static constexpr uint32_t RESERVED_SLOTS = 2;
    809  static constexpr ObjectFlags OBJECT_FLAGS = {ObjectFlag::NotExtensible};
    810 
    811  static WasmInstanceEnvironmentObject* createHollowForDebug(
    812      JSContext* cx, Handle<WasmInstanceScope*> scope);
    813  WasmInstanceScope& scope() const {
    814    Value v = getReservedSlot(SCOPE_SLOT);
    815    MOZ_ASSERT(v.isPrivateGCThing());
    816    return *static_cast<WasmInstanceScope*>(v.toGCThing());
    817  }
    818 };
    819 
    820 class WasmFunctionCallObject : public EnvironmentObject {
    821  // Currently WasmFunctionCallObjects do not use their scopes in a
    822  // meaningful way. However, it is an invariant of DebugEnvironments that
    823  // environments kept in those maps have live scopes, thus this strong
    824  // reference.
    825  static constexpr uint32_t SCOPE_SLOT = 1;
    826 
    827 public:
    828  static const JSClass class_;
    829 
    830  // TODO Check what Debugger behavior should be when it evaluates a
    831  // var declaration.
    832  static constexpr uint32_t RESERVED_SLOTS = 2;
    833  static constexpr ObjectFlags OBJECT_FLAGS = {ObjectFlag::NotExtensible};
    834 
    835  static WasmFunctionCallObject* createHollowForDebug(
    836      JSContext* cx, HandleObject enclosing, Handle<WasmFunctionScope*> scope);
    837  WasmFunctionScope& scope() const {
    838    Value v = getReservedSlot(SCOPE_SLOT);
    839    MOZ_ASSERT(v.isPrivateGCThing());
    840    return *static_cast<WasmFunctionScope*>(v.toGCThing());
    841  }
    842 };
    843 
    844 // Abstract base class for environments that can contain let/const bindings,
    845 // plus a few other kinds of environments, such as `catch` blocks, that have
    846 // similar behavior.
    847 #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT
    848 class LexicalEnvironmentObject : public DisposableEnvironmentObject {
    849 #else
    850 class LexicalEnvironmentObject : public EnvironmentObject {
    851 #endif
    852 protected:
    853  // Global and non-syntactic lexical environments need to store a 'this'
    854  // object and all other lexical environments have a fixed shape and store a
    855  // backpointer to the LexicalScope.
    856  //
    857  // Since the two sets are disjoint, we only use one slot to save space.
    858 #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT
    859  static constexpr uint32_t THIS_VALUE_OR_SCOPE_SLOT =
    860      DisposableEnvironmentObject::RESERVED_SLOTS;
    861 #else
    862  static constexpr uint32_t THIS_VALUE_OR_SCOPE_SLOT = 1;
    863 #endif
    864 
    865 public:
    866  static const JSClass class_;
    867 
    868 #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT
    869  // See comment on RESERVED_SLOTS in ModuleEnvironmentObject.
    870  static constexpr uint32_t RESERVED_SLOTS =
    871      DisposableEnvironmentObject::RESERVED_SLOTS + 2;
    872 #else
    873  static constexpr uint32_t RESERVED_SLOTS = 2;
    874 #endif
    875 
    876 protected:
    877  static LexicalEnvironmentObject* create(JSContext* cx,
    878                                          Handle<SharedShape*> shape,
    879                                          HandleObject enclosing, gc::Heap heap,
    880                                          gc::AllocSite* site = nullptr);
    881 
    882 public:
    883  // Is this the global lexical scope?
    884  bool isGlobal() const { return enclosingEnvironment().is<GlobalObject>(); }
    885 
    886  // Global and non-syntactic lexical scopes are extensible. All other
    887  // lexical scopes are not.
    888  bool isExtensible() const;
    889 
    890  // Is this a syntactic (i.e. corresponds to a source text) lexical
    891  // environment?
    892  bool isSyntactic() const { return !isExtensible() || isGlobal(); }
    893 };
    894 
    895 // A non-extensible lexical environment.
    896 //
    897 // Used for blocks (ScopeKind::Lexical) and several other scope kinds,
    898 // including Catch, NamedLambda, FunctionLexical, and ClassBody.
    899 class ScopedLexicalEnvironmentObject : public LexicalEnvironmentObject {
    900 public:
    901  static constexpr ObjectFlags OBJECT_FLAGS = {ObjectFlag::NotExtensible};
    902 
    903  Scope& scope() const {
    904    Value v = getReservedSlot(THIS_VALUE_OR_SCOPE_SLOT);
    905    MOZ_ASSERT(!isExtensible() && v.isPrivateGCThing());
    906    return *static_cast<Scope*>(v.toGCThing());
    907  }
    908 
    909  bool isClassBody() const { return scope().kind() == ScopeKind::ClassBody; }
    910 
    911  void initScope(Scope* scope) {
    912    initReservedSlot(THIS_VALUE_OR_SCOPE_SLOT, PrivateGCThingValue(scope));
    913  }
    914 };
    915 
    916 class BlockLexicalEnvironmentObject : public ScopedLexicalEnvironmentObject {
    917 protected:
    918  static BlockLexicalEnvironmentObject* create(JSContext* cx,
    919                                               Handle<LexicalScope*> scope,
    920                                               HandleObject enclosing,
    921                                               gc::Heap heap,
    922                                               gc::AllocSite* site = nullptr);
    923 
    924 public:
    925  static constexpr ObjectFlags OBJECT_FLAGS = {ObjectFlag::NotExtensible};
    926 
    927  static BlockLexicalEnvironmentObject* createForFrame(
    928      JSContext* cx, Handle<LexicalScope*> scope, AbstractFramePtr frame);
    929 
    930  static BlockLexicalEnvironmentObject* createHollowForDebug(
    931      JSContext* cx, Handle<LexicalScope*> scope);
    932 
    933  static BlockLexicalEnvironmentObject* createTemplateObject(
    934      JSContext* cx, Handle<LexicalScope*> scope);
    935 
    936  static BlockLexicalEnvironmentObject* createWithoutEnclosing(
    937      JSContext* cx, Handle<LexicalScope*> scope);
    938 
    939  // Create a new BlockLexicalEnvironmentObject with the same enclosing env and
    940  // variable values as this.
    941  static BlockLexicalEnvironmentObject* clone(
    942      JSContext* cx, Handle<BlockLexicalEnvironmentObject*> env);
    943 
    944  // Create a new BlockLexicalEnvironmentObject with the same enclosing env as
    945  // this, with all variables uninitialized.
    946  static BlockLexicalEnvironmentObject* recreate(
    947      JSContext* cx, Handle<BlockLexicalEnvironmentObject*> env);
    948 
    949  // The LexicalScope that created this environment.
    950  LexicalScope& scope() const {
    951    return ScopedLexicalEnvironmentObject::scope().as<LexicalScope>();
    952  }
    953 };
    954 
    955 class NamedLambdaObject : public BlockLexicalEnvironmentObject {
    956  static NamedLambdaObject* create(JSContext* cx, HandleFunction callee,
    957                                   HandleObject enclosing, gc::Heap heap,
    958                                   gc::AllocSite* site = nullptr);
    959 
    960 public:
    961  static NamedLambdaObject* createTemplateObject(JSContext* cx,
    962                                                 HandleFunction callee);
    963 
    964  static NamedLambdaObject* createWithoutEnclosing(JSContext* cx,
    965                                                   HandleFunction callee,
    966                                                   gc::Heap heap);
    967 
    968  static NamedLambdaObject* createForFrame(JSContext* cx,
    969                                           AbstractFramePtr frame,
    970                                           gc::AllocSite* site);
    971 
    972  // For JITs.
    973  static size_t lambdaSlot();
    974 
    975  static size_t offsetOfLambdaSlot() {
    976    return getFixedSlotOffset(lambdaSlot());
    977  }
    978 };
    979 
    980 class ClassBodyLexicalEnvironmentObject
    981    : public ScopedLexicalEnvironmentObject {
    982  static ClassBodyLexicalEnvironmentObject* create(
    983      JSContext* cx, Handle<ClassBodyScope*> scope, HandleObject enclosing,
    984      gc::Heap heap);
    985 
    986 public:
    987  static ClassBodyLexicalEnvironmentObject* createForFrame(
    988      JSContext* cx, Handle<ClassBodyScope*> scope, AbstractFramePtr frame);
    989 
    990  static ClassBodyLexicalEnvironmentObject* createTemplateObject(
    991      JSContext* cx, Handle<ClassBodyScope*> scope);
    992 
    993  static ClassBodyLexicalEnvironmentObject* createWithoutEnclosing(
    994      JSContext* cx, Handle<ClassBodyScope*> scope);
    995 
    996  // The ClassBodyScope that created this environment.
    997  ClassBodyScope& scope() const {
    998    return ScopedLexicalEnvironmentObject::scope().as<ClassBodyScope>();
    999  }
   1000 
   1001  static uint32_t privateBrandSlot() { return JSSLOT_FREE(&class_); }
   1002 };
   1003 
   1004 /*
   1005 * Prepare a |this| object to be returned to script. This includes replacing
   1006 * Windows with their corresponding WindowProxy.
   1007 */
   1008 JSObject* GetThisObject(JSObject* obj);
   1009 
   1010 // Global and non-syntactic lexical environments are extensible.
   1011 class ExtensibleLexicalEnvironmentObject : public LexicalEnvironmentObject {
   1012 public:
   1013  JSObject* thisObject() const;
   1014 
   1015  // For a given global object or JSMEnvironment `obj`, return the associated
   1016  // global lexical or non-syntactic lexical environment, where top-level `let`
   1017  // bindings are added.
   1018  static ExtensibleLexicalEnvironmentObject* forVarEnvironment(JSObject* obj);
   1019 
   1020 protected:
   1021  void initThisObject(JSObject* obj) {
   1022    MOZ_ASSERT(isGlobal() || !isSyntactic());
   1023    JSObject* thisObj = GetThisObject(obj);
   1024    initReservedSlot(THIS_VALUE_OR_SCOPE_SLOT, ObjectValue(*thisObj));
   1025  }
   1026 };
   1027 
   1028 // The global lexical environment, where global let/const/class bindings are
   1029 // added.
   1030 class GlobalLexicalEnvironmentObject
   1031    : public ExtensibleLexicalEnvironmentObject {
   1032 public:
   1033  static GlobalLexicalEnvironmentObject* create(JSContext* cx,
   1034                                                Handle<GlobalObject*> global);
   1035 
   1036  GlobalObject& global() const {
   1037    return enclosingEnvironment().as<GlobalObject>();
   1038  }
   1039 
   1040  void setWindowProxyThisObject(JSObject* obj);
   1041 
   1042  static constexpr size_t offsetOfThisValueSlot() {
   1043    return getFixedSlotOffset(THIS_VALUE_OR_SCOPE_SLOT);
   1044  }
   1045 };
   1046 
   1047 // Non-standard. See "Non-syntactic Environments" above.
   1048 class NonSyntacticLexicalEnvironmentObject
   1049    : public ExtensibleLexicalEnvironmentObject {
   1050 public:
   1051  static NonSyntacticLexicalEnvironmentObject* create(JSContext* cx,
   1052                                                      HandleObject enclosing,
   1053                                                      HandleObject thisv);
   1054 };
   1055 
   1056 // A non-syntactic dynamic scope object that captures non-lexical
   1057 // bindings. That is, a scope object that captures both qualified var
   1058 // assignments and unqualified bareword assignments. Its parent is always the
   1059 // global lexical environment.
   1060 //
   1061 // See the long "Non-syntactic Environments" comment above.
   1062 class NonSyntacticVariablesObject : public EnvironmentObject {
   1063 public:
   1064  static const JSClass class_;
   1065 
   1066  static constexpr uint32_t RESERVED_SLOTS = 1;
   1067  static constexpr ObjectFlags OBJECT_FLAGS = {ObjectFlag::QualifiedVarObj};
   1068 
   1069  static NonSyntacticVariablesObject* create(JSContext* cx);
   1070 };
   1071 
   1072 NonSyntacticLexicalEnvironmentObject* CreateNonSyntacticEnvironmentChain(
   1073    JSContext* cx, const JS::EnvironmentChain& envChain);
   1074 
   1075 // With environment objects on the run-time environment chain.
   1076 class WithEnvironmentObject : public EnvironmentObject {
   1077  static constexpr uint32_t OBJECT_SLOT = 1;
   1078  static constexpr uint32_t THIS_SLOT = 2;
   1079  // For syntactic with-environments this slot stores the js::Scope*.
   1080  // For non-syntactic with-environments it stores a boolean indicating whether
   1081  // we need to look up and use Symbol.unscopables.
   1082  static constexpr uint32_t SCOPE_OR_SUPPORT_UNSCOPABLES_SLOT = 3;
   1083 
   1084 public:
   1085  static const JSClass class_;
   1086 
   1087  static constexpr uint32_t RESERVED_SLOTS = 4;
   1088  static constexpr ObjectFlags OBJECT_FLAGS = {};
   1089 
   1090  static WithEnvironmentObject* create(
   1091      JSContext* cx, HandleObject object, HandleObject enclosing,
   1092      Handle<WithScope*> scope, JS::SupportUnscopables supportUnscopables);
   1093  static WithEnvironmentObject* createNonSyntactic(
   1094      JSContext* cx, HandleObject object, HandleObject enclosing,
   1095      JS::SupportUnscopables supportUnscopables);
   1096 
   1097  /* Return the 'o' in 'with (o)'. */
   1098  JSObject& object() const;
   1099 
   1100  /* Return object for GetThisValue. */
   1101  JSObject* withThis() const;
   1102 
   1103  /*
   1104   * Return whether this object is a syntactic with object.  If not, this is
   1105   * a With object we inserted between the outermost syntactic scope and the
   1106   * global object to wrap the environment chain someone explicitly passed
   1107   * via JSAPI to CompileFunction or script evaluation.
   1108   */
   1109  bool isSyntactic() const;
   1110 
   1111  // Whether Symbol.unscopables must be supported for this with-environment.
   1112  // This always returns true for syntactic with-environments.
   1113  bool supportUnscopables() const;
   1114 
   1115  // For syntactic with environment objects, the with scope.
   1116  WithScope& scope() const;
   1117 
   1118  static constexpr size_t objectSlot() { return OBJECT_SLOT; }
   1119 
   1120  static constexpr size_t thisSlot() { return THIS_SLOT; }
   1121 
   1122  // For JITs.
   1123  static constexpr size_t offsetOfThisSlot() {
   1124    return getFixedSlotOffset(THIS_SLOT);
   1125  }
   1126 };
   1127 
   1128 // Internal environment object used by JSOp::BindUnqualifiedName upon
   1129 // encountering an uninitialized lexical slot or an assignment to a 'const'
   1130 // binding.
   1131 //
   1132 // ES6 lexical bindings cannot be accessed in any way (throwing
   1133 // ReferenceErrors) until initialized. Normally, NAME operations
   1134 // unconditionally check for uninitialized lexical slots. When getting or
   1135 // looking up names, this can be done without slowing down normal operations
   1136 // on the return value. When setting names, however, we do not want to pollute
   1137 // all set-property paths with uninitialized lexical checks. For setting names
   1138 // (i.e. JSOp::SetName), we emit an accompanying, preceding
   1139 // JSOp::BindUnqualifiedName which finds the right scope on which to set the
   1140 // name. Moreover, when the name on the scope is an uninitialized lexical, we
   1141 // cannot throw eagerly, as the spec demands that the error be thrown after
   1142 // evaluating the RHS of assignments. Instead, this sentinel scope object is
   1143 // pushed on the stack. Attempting to access anything on this scope throws the
   1144 // appropriate ReferenceError.
   1145 //
   1146 // ES6 'const' bindings induce a runtime error when assigned to outside
   1147 // of initialization, regardless of strictness.
   1148 class RuntimeLexicalErrorObject : public EnvironmentObject {
   1149  static const unsigned ERROR_SLOT = 1;
   1150 
   1151 public:
   1152  static const unsigned RESERVED_SLOTS = 2;
   1153  static const JSClass class_;
   1154 
   1155  static RuntimeLexicalErrorObject* create(JSContext* cx,
   1156                                           HandleObject enclosing,
   1157                                           unsigned errorNumber);
   1158 
   1159  unsigned errorNumber() { return getReservedSlot(ERROR_SLOT).toInt32(); }
   1160 };
   1161 
   1162 /****************************************************************************/
   1163 
   1164 // A environment iterator describes the active environments starting from an
   1165 // environment, scope pair. This pair may be derived from the current point of
   1166 // execution in a frame. If derived in such a fashion, the EnvironmentIter
   1167 // tracks whether the current scope is within the extent of this initial
   1168 // frame.  Here, "frame" means a single activation of: a function, eval, or
   1169 // global code.
   1170 class MOZ_RAII EnvironmentIter {
   1171  Rooted<ScopeIter> si_;
   1172  RootedObject env_;
   1173  AbstractFramePtr frame_;
   1174 
   1175  void incrementScopeIter();
   1176  void settle();
   1177 
   1178  // No value semantics.
   1179  EnvironmentIter(const EnvironmentIter& ei) = delete;
   1180 
   1181 public:
   1182  // Constructing from a copy of an existing EnvironmentIter.
   1183  EnvironmentIter(JSContext* cx, const EnvironmentIter& ei);
   1184 
   1185  // Constructing from an environment, scope pair. All environments
   1186  // considered not to be withinInitialFrame, since no frame is given.
   1187  EnvironmentIter(JSContext* cx, JSObject* env, Scope* scope);
   1188 
   1189  // Constructing from a frame. Places the EnvironmentIter on the innermost
   1190  // environment at pc.
   1191  EnvironmentIter(JSContext* cx, AbstractFramePtr frame, const jsbytecode* pc);
   1192 
   1193  // Constructing from an environment, scope and frame. The frame is given
   1194  // to initialize to proper enclosing environment/scope.
   1195  EnvironmentIter(JSContext* cx, JSObject* env, Scope* scope,
   1196                  AbstractFramePtr frame);
   1197 
   1198  bool done() const { return si_.done(); }
   1199 
   1200  explicit operator bool() const { return !done(); }
   1201 
   1202  void operator++(int) {
   1203    if (hasAnyEnvironmentObject()) {
   1204      env_ = &env_->as<EnvironmentObject>().enclosingEnvironment();
   1205    }
   1206    incrementScopeIter();
   1207    settle();
   1208  }
   1209 
   1210  EnvironmentIter& operator++() {
   1211    operator++(1);
   1212    return *this;
   1213  }
   1214 
   1215  // If done():
   1216  JSObject& enclosingEnvironment() const;
   1217 
   1218  // If !done():
   1219  bool hasNonSyntacticEnvironmentObject() const;
   1220 
   1221  bool hasSyntacticEnvironment() const { return si_.hasSyntacticEnvironment(); }
   1222 
   1223  bool hasAnyEnvironmentObject() const {
   1224    return hasNonSyntacticEnvironmentObject() || hasSyntacticEnvironment();
   1225  }
   1226 
   1227  EnvironmentObject& environment() const {
   1228    MOZ_ASSERT(hasAnyEnvironmentObject());
   1229    return env_->as<EnvironmentObject>();
   1230  }
   1231 
   1232  Scope& scope() const { return *si_.scope(); }
   1233 
   1234  Scope* maybeScope() const {
   1235    if (si_) {
   1236      return si_.scope();
   1237    }
   1238    return nullptr;
   1239  }
   1240 
   1241  JSFunction& callee() const { return env_->as<CallObject>().callee(); }
   1242 
   1243  bool withinInitialFrame() const { return !!frame_; }
   1244 
   1245  AbstractFramePtr initialFrame() const {
   1246    MOZ_ASSERT(withinInitialFrame());
   1247    return frame_;
   1248  }
   1249 
   1250  AbstractFramePtr maybeInitialFrame() const { return frame_; }
   1251 };
   1252 
   1253 // The key in MissingEnvironmentMap.
   1254 //
   1255 //   * For live frames, maps live frames to their synthesized environments.
   1256 //   * For completely optimized-out environments, maps the Scope to their
   1257 //     synthesized environments.
   1258 //
   1259 // The env we synthesize for Scopes are read-only, but the parent links can be
   1260 // used when accessing closed-over bindings held by the enclosing environments.
   1261 // Thus these environments need to be distinct for multiple execution for the
   1262 // same scope.  Otherwise looking up the MissingEnvironmentMap can yield
   1263 // the environment for previous execution, which holds different values in the
   1264 // variables.
   1265 //
   1266 // Completely optimized out environments lack the frame, and they can't be
   1267 // distinguished by the frame pointers. Note that even if the frame
   1268 // corresponding to the Scope is live on the stack, it is unsound to synthesize
   1269 // environment from that live frame.
   1270 //
   1271 // If the frame is missing, the nearestEnvId_ field is used for distinguishing
   1272 // the missing environments across multiple executions.
   1273 // The nearestEnvId_ field holds the ID of environment object that encloses this
   1274 // environment.
   1275 //
   1276 // The goal of distinguishing the environments is to avoid mixing up the
   1277 // variables in these enclosing environments, thus using these environment
   1278 // object pointers should be sufficient.
   1279 // For example, if there's no enclosing local environment which has an
   1280 // environment object, nearestEnvId_ will point to the global environment
   1281 // object, and all executions for the same scope will alias, but there's no need
   1282 // to distinguish between them.
   1283 class DebugEnvironments;
   1284 
   1285 class MissingEnvironmentKey {
   1286  friend class LiveEnvironmentVal;
   1287 
   1288  // The corresponding frame for the environment.
   1289  // This can be null for function etc.
   1290  AbstractFramePtr frame_;
   1291 
   1292  // The corresponding scope for the environment.
   1293  // This is shared betwen all executions.
   1294  Scope* scope_;
   1295 
   1296  // The ID of the nearest enclosing environment object's DebugEnvironmentProxy
   1297  // if any.  Used only if frame_ is null, to distinguish between multiple
   1298  // execution on the same scope.
   1299  uint64_t nearestEnvId_;
   1300 
   1301 public:
   1302  MissingEnvironmentKey()
   1303      : frame_(NullFramePtr()), scope_(nullptr), nearestEnvId_(0) {}
   1304 
   1305  MissingEnvironmentKey(AbstractFramePtr frame, Scope* scope)
   1306      : frame_(frame), scope_(scope), nearestEnvId_(0) {
   1307    MOZ_ASSERT(frame);
   1308  }
   1309 
   1310  bool initFromEnvironmentIter(JSContext* cx, const EnvironmentIter& ei);
   1311 
   1312  AbstractFramePtr frame() const { return frame_; }
   1313  Scope* scope() const { return scope_; }
   1314 
   1315  void updateScope(Scope* scope) { scope_ = scope; }
   1316  void updateFrame(AbstractFramePtr frame) { frame_ = frame; }
   1317 
   1318  // For use as hash policy.
   1319  using Lookup = MissingEnvironmentKey;
   1320  static HashNumber hash(MissingEnvironmentKey sk);
   1321  static bool match(MissingEnvironmentKey sk1, MissingEnvironmentKey sk2);
   1322  bool operator!=(const MissingEnvironmentKey& other) const {
   1323    return frame_ != other.frame_ || nearestEnvId_ != other.nearestEnvId_ ||
   1324           scope_ != other.scope_;
   1325  }
   1326  static void rekey(MissingEnvironmentKey& k,
   1327                    const MissingEnvironmentKey& newKey) {
   1328    k = newKey;
   1329  }
   1330 };
   1331 
   1332 // The value in LiveEnvironmentMap, mapped from by live environment objects.
   1333 class LiveEnvironmentVal {
   1334  friend class DebugEnvironments;
   1335  friend class MissingEnvironmentKey;
   1336 
   1337  AbstractFramePtr frame_;
   1338  HeapPtr<Scope*> scope_;
   1339  // See LiveEnvironmentVal::staticAsserts.
   1340  uint64_t padding_ = 0;
   1341 
   1342  static void staticAsserts();
   1343 
   1344 public:
   1345  explicit LiveEnvironmentVal(const EnvironmentIter& ei)
   1346      : frame_(ei.initialFrame()), scope_(ei.maybeScope()) {
   1347    (void)padding_;
   1348  }
   1349 
   1350  AbstractFramePtr frame() const { return frame_; }
   1351 
   1352  void updateFrame(AbstractFramePtr frame) { frame_ = frame; }
   1353 
   1354  bool traceWeak(JSTracer* trc);
   1355 };
   1356 
   1357 /****************************************************************************/
   1358 
   1359 /*
   1360 * [SMDOC] Debug environment objects
   1361 *
   1362 * The frontend optimizes unaliased variables into stack slots and can optimize
   1363 * away whole EnvironmentObjects. So when the debugger wants to perform an
   1364 * unexpected eval-in-frame (or otherwise access the environment),
   1365 * `fp->environmentChain` is often incomplete. This is a problem: a major use
   1366 * case for eval-in-frame is to access the local variables in debuggee code.
   1367 *
   1368 * Even when all EnvironmentObjects exist, giving complete information for all
   1369 * bindings, stack and heap, there's another issue: eval-in-frame code can
   1370 * create closures that capture stack locals. The variable slots go away when
   1371 * the frame is popped, but the closure, which uses them, may survive.
   1372 *
   1373 * To solve both problems, eval-in-frame code is compiled and run against a
   1374 * "debug environment chain" of DebugEnvironmentProxy objects rather than real
   1375 * EnvironmentObjects. The `GetDebugEnvironmentFor` functions below create
   1376 * these proxies, one to sit in front of each existing EnvironmentObject. They
   1377 * also create bogus "hollow" EnvironmentObjects to stand in for environments
   1378 * that were optimized away; and proxies for those. The frontend sees these
   1379 * environments as something like `with` scopes, and emits deoptimized bytecode
   1380 * instructions for all variable accesses.
   1381 *
   1382 * When eval-in-frame code runs, `fp->environmentChain` points to this chain of
   1383 * proxies. On each variable access, the proxy laboriously figures out what to
   1384 * do. See e.g. `DebuggerEnvironmentProxyHandler::handleUnaliasedAccess`.
   1385 *
   1386 * There's a limit to what the proxies can manage, since they're proxying
   1387 * environments that are already optimized. Some debugger operations, like
   1388 * redefining a lexical binding, can fail when a true direct eval would
   1389 * succeed. Even plain variable accesses can throw, if the variable has been
   1390 * optimized away.
   1391 *
   1392 * To support accessing stack variables after they've gone out of scope, we
   1393 * copy the variables to the heap as they leave scope. See
   1394 * `DebugEnvironments::onPopCall` and `onPopLexical`.
   1395 *
   1396 * `GetDebugEnvironmentFor*` guarantees that the same DebugEnvironmentProxy is
   1397 * always produced for the same underlying environment (optimized or not!).
   1398 * This is maintained by some bookkeeping information stored in
   1399 * `DebugEnvironments`.
   1400 */
   1401 
   1402 extern JSObject* GetDebugEnvironmentForFunction(JSContext* cx,
   1403                                                HandleFunction fun);
   1404 
   1405 extern JSObject* GetDebugEnvironmentForSuspendedGenerator(
   1406    JSContext* cx, JSScript* script, AbstractGeneratorObject& genObj);
   1407 
   1408 extern JSObject* GetDebugEnvironmentForFrame(JSContext* cx,
   1409                                             AbstractFramePtr frame,
   1410                                             jsbytecode* pc);
   1411 
   1412 extern JSObject* GetDebugEnvironmentForGlobalLexicalEnvironment(JSContext* cx);
   1413 extern Scope* GetEnvironmentScope(const JSObject& env);
   1414 
   1415 /* Provides debugger access to a environment. */
   1416 class DebugEnvironmentProxy : public ProxyObject {
   1417  /*
   1418   * The enclosing environment on the dynamic environment chain. This slot is
   1419   * analogous to the ENCLOSING_ENV_SLOT of a EnvironmentObject.
   1420   */
   1421  static const unsigned ENCLOSING_SLOT = 0;
   1422 
   1423  /*
   1424   * NullValue or a dense array holding the unaliased variables of a function
   1425   * frame that has been popped.
   1426   */
   1427  static const unsigned SNAPSHOT_SLOT = 1;
   1428 
   1429 public:
   1430  static DebugEnvironmentProxy* create(JSContext* cx, EnvironmentObject& env,
   1431                                       HandleObject enclosing);
   1432 
   1433  // NOTE: The environment may be a debug hollow with invalid
   1434  // enclosingEnvironment. Always use the enclosingEnvironment accessor on
   1435  // the DebugEnvironmentProxy in order to walk the environment chain.
   1436  EnvironmentObject& environment() const;
   1437  JSObject& enclosingEnvironment() const;
   1438 
   1439  // May only be called for proxies to function call objects or modules
   1440  // with top-level-await.
   1441  ArrayObject* maybeSnapshot() const;
   1442  void initSnapshot(ArrayObject& snapshot);
   1443 
   1444  // Currently, the 'declarative' environments are function, module, and
   1445  // lexical environments.
   1446  bool isForDeclarative() const;
   1447 
   1448  // Get a property by 'id', but returns sentinel values instead of throwing
   1449  // on exceptional cases.
   1450  static bool getMaybeSentinelValue(JSContext* cx,
   1451                                    Handle<DebugEnvironmentProxy*> env,
   1452                                    HandleId id, MutableHandleValue vp);
   1453 
   1454  // Returns true iff this is a function environment with its own this-binding
   1455  // (all functions except arrow functions).
   1456  bool isFunctionEnvironmentWithThis();
   1457 
   1458  // Does this debug environment not have a real counterpart or was never
   1459  // live (and thus does not have a synthesized EnvironmentObject or a
   1460  // snapshot)?
   1461  bool isOptimizedOut() const;
   1462 
   1463 #if defined(DEBUG) || defined(JS_JITSPEW)
   1464  void dump();
   1465 #endif /* defined(DEBUG) || defined(JS_JITSPEW) */
   1466 };
   1467 
   1468 /* Maintains per-realm debug environment bookkeeping information. */
   1469 class DebugEnvironments {
   1470  Zone* zone_;
   1471 
   1472  /* The map from (non-debug) environments to debug environments. */
   1473  using ProxiedEnvironmentsMap = WeakMap<JSObject*, JSObject*, ZoneAllocPolicy>;
   1474  ProxiedEnvironmentsMap proxiedEnvs;
   1475 
   1476  /*
   1477   * The map from live frames which have optimized-away environments to the
   1478   * corresponding debug environments.
   1479   */
   1480  using MissingEnvironmentMap =
   1481      HashMap<MissingEnvironmentKey, WeakHeapPtr<DebugEnvironmentProxy*>,
   1482              MissingEnvironmentKey, ZoneAllocPolicy>;
   1483  MissingEnvironmentMap missingEnvs;
   1484 
   1485  /*
   1486   * The map from environment objects of live frames to the live frame. This
   1487   * map updated lazily whenever the debugger needs the information. In
   1488   * between two lazy updates, liveEnvs becomes incomplete (but not invalid,
   1489   * onPop* removes environments as they are popped). Thus, two consecutive
   1490   * debugger lazy updates of liveEnvs need only fill in the new
   1491   * environments.
   1492   */
   1493  using LiveEnvironmentMap =
   1494      GCHashMap<WeakHeapPtr<JSObject*>, LiveEnvironmentVal,
   1495                StableCellHasher<WeakHeapPtr<JSObject*>>, ZoneAllocPolicy>;
   1496  LiveEnvironmentMap liveEnvs;
   1497 
   1498 public:
   1499  DebugEnvironments(JSContext* cx, Zone* zone);
   1500  ~DebugEnvironments();
   1501 
   1502  Zone* zone() const { return zone_; }
   1503 
   1504 private:
   1505  static DebugEnvironments* ensureRealmData(JSContext* cx);
   1506 
   1507  template <typename Environment, typename Scope>
   1508  static void onPopGeneric(JSContext* cx, const EnvironmentIter& ei);
   1509 
   1510 public:
   1511  void trace(JSTracer* trc);
   1512  void traceWeak(JSTracer* trc);
   1513  void finish();
   1514 #ifdef JS_GC_ZEAL
   1515  void checkHashTablesAfterMovingGC();
   1516 #endif
   1517 
   1518  // If a live frame has a synthesized entry in missingEnvs, make sure it's not
   1519  // collected.
   1520  void traceLiveFrame(JSTracer* trc, AbstractFramePtr frame);
   1521 
   1522  static DebugEnvironmentProxy* hasDebugEnvironment(JSContext* cx,
   1523                                                    EnvironmentObject& env);
   1524  static bool addDebugEnvironment(JSContext* cx, Handle<EnvironmentObject*> env,
   1525                                  Handle<DebugEnvironmentProxy*> debugEnv);
   1526 
   1527  static bool getExistingDebugEnvironment(JSContext* cx,
   1528                                          const EnvironmentIter& ei,
   1529                                          DebugEnvironmentProxy** out);
   1530  static bool addDebugEnvironment(JSContext* cx, const EnvironmentIter& ei,
   1531                                  Handle<DebugEnvironmentProxy*> debugEnv);
   1532 
   1533  static bool updateLiveEnvironments(JSContext* cx);
   1534  static LiveEnvironmentVal* hasLiveEnvironment(EnvironmentObject& env);
   1535  static void unsetPrevUpToDateUntil(JSContext* cx, AbstractFramePtr frame);
   1536 
   1537  // When a frame bails out from Ion to Baseline, there might be missing
   1538  // envs keyed on, and live envs containing, the old
   1539  // RematerializedFrame. Forward those values to the new BaselineFrame.
   1540  static void forwardLiveFrame(JSContext* cx, AbstractFramePtr from,
   1541                               AbstractFramePtr to);
   1542 
   1543  // When an environment is popped, we store a snapshot of its bindings that
   1544  // live on the frame.
   1545  //
   1546  // This is done during frame unwinding, which cannot handle errors
   1547  // gracefully. Errors result in no snapshot being set on the
   1548  // DebugEnvironmentProxy.
   1549  static void takeFrameSnapshot(JSContext* cx,
   1550                                Handle<DebugEnvironmentProxy*> debugEnv,
   1551                                AbstractFramePtr frame);
   1552 
   1553  // In debug-mode, these must be called whenever exiting a scope that might
   1554  // have stack-allocated locals.
   1555  static void onPopCall(JSContext* cx, AbstractFramePtr frame);
   1556  static void onPopVar(JSContext* cx, const EnvironmentIter& ei);
   1557  static void onPopLexical(JSContext* cx, const EnvironmentIter& ei);
   1558  static void onPopLexical(JSContext* cx, AbstractFramePtr frame,
   1559                           const jsbytecode* pc);
   1560  static void onPopWith(AbstractFramePtr frame);
   1561  static void onPopModule(JSContext* cx, const EnvironmentIter& ei);
   1562  static void onRealmUnsetIsDebuggee(Realm* realm);
   1563 };
   1564 
   1565 } /* namespace js */
   1566 
   1567 template <>
   1568 inline bool JSObject::is<js::EnvironmentObject>() const {
   1569  return is<js::CallObject>() || is<js::VarEnvironmentObject>() ||
   1570         is<js::ModuleEnvironmentObject>() ||
   1571         is<js::WasmInstanceEnvironmentObject>() ||
   1572         is<js::WasmFunctionCallObject>() ||
   1573         is<js::LexicalEnvironmentObject>() ||
   1574         is<js::WithEnvironmentObject>() ||
   1575         is<js::NonSyntacticVariablesObject>() ||
   1576         is<js::RuntimeLexicalErrorObject>();
   1577 }
   1578 
   1579 #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT
   1580 template <>
   1581 inline bool JSObject::is<js::DisposableEnvironmentObject>() const {
   1582  return is<js::LexicalEnvironmentObject>() ||
   1583         is<js::ModuleEnvironmentObject>();
   1584 }
   1585 #endif
   1586 
   1587 template <>
   1588 inline bool JSObject::is<js::ScopedLexicalEnvironmentObject>() const {
   1589  return is<js::LexicalEnvironmentObject>() &&
   1590         !as<js::LexicalEnvironmentObject>().isExtensible();
   1591 }
   1592 
   1593 template <>
   1594 inline bool JSObject::is<js::BlockLexicalEnvironmentObject>() const {
   1595  return is<js::ScopedLexicalEnvironmentObject>() &&
   1596         !as<js::ScopedLexicalEnvironmentObject>().isClassBody();
   1597 }
   1598 
   1599 template <>
   1600 inline bool JSObject::is<js::ClassBodyLexicalEnvironmentObject>() const {
   1601  return is<js::ScopedLexicalEnvironmentObject>() &&
   1602         as<js::ScopedLexicalEnvironmentObject>().isClassBody();
   1603 }
   1604 
   1605 template <>
   1606 inline bool JSObject::is<js::ExtensibleLexicalEnvironmentObject>() const {
   1607  return is<js::LexicalEnvironmentObject>() &&
   1608         as<js::LexicalEnvironmentObject>().isExtensible();
   1609 }
   1610 
   1611 template <>
   1612 inline bool JSObject::is<js::GlobalLexicalEnvironmentObject>() const {
   1613  return is<js::LexicalEnvironmentObject>() &&
   1614         as<js::LexicalEnvironmentObject>().isGlobal();
   1615 }
   1616 
   1617 template <>
   1618 inline bool JSObject::is<js::NonSyntacticLexicalEnvironmentObject>() const {
   1619  return is<js::LexicalEnvironmentObject>() &&
   1620         !as<js::LexicalEnvironmentObject>().isSyntactic();
   1621 }
   1622 
   1623 template <>
   1624 inline bool JSObject::is<js::NamedLambdaObject>() const {
   1625  return is<js::BlockLexicalEnvironmentObject>() &&
   1626         as<js::BlockLexicalEnvironmentObject>().scope().isNamedLambda();
   1627 }
   1628 
   1629 template <>
   1630 bool JSObject::is<js::DebugEnvironmentProxy>() const;
   1631 
   1632 namespace js {
   1633 
   1634 inline bool IsSyntacticEnvironment(JSObject* env) {
   1635  if (!env->is<EnvironmentObject>()) {
   1636    return false;
   1637  }
   1638 
   1639  if (env->is<WithEnvironmentObject>()) {
   1640    return env->as<WithEnvironmentObject>().isSyntactic();
   1641  }
   1642 
   1643  if (env->is<LexicalEnvironmentObject>()) {
   1644    return env->as<LexicalEnvironmentObject>().isSyntactic();
   1645  }
   1646 
   1647  if (env->is<NonSyntacticVariablesObject>()) {
   1648    return false;
   1649  }
   1650 
   1651  return true;
   1652 }
   1653 
   1654 inline JSObject* MaybeUnwrapWithEnvironment(JSObject* env) {
   1655  if (env->is<WithEnvironmentObject>()) {
   1656    return &env->as<WithEnvironmentObject>().object();
   1657  }
   1658  return env;
   1659 }
   1660 
   1661 template <typename SpecificEnvironment>
   1662 inline bool IsFrameInitialEnvironment(AbstractFramePtr frame,
   1663                                      SpecificEnvironment& env) {
   1664  // A frame's initial environment is the innermost environment
   1665  // corresponding to the scope chain from frame.script()->bodyScope() to
   1666  // frame.script()->outermostScope(). This environment must be on the chain
   1667  // for the frame to be considered initialized. That is, it must be on the
   1668  // chain for the environment chain to fully match the scope chain at the
   1669  // start of execution in the frame.
   1670  //
   1671  // This logic must be in sync with the HAS_INITIAL_ENV logic in
   1672  // BaselineStackBuilder::buildBaselineFrame.
   1673 
   1674  // A function frame's CallObject, if present, is always the initial
   1675  // environment.
   1676  if constexpr (std::is_same_v<SpecificEnvironment, CallObject>) {
   1677    return true;
   1678  }
   1679 
   1680  // For an eval frame, the VarEnvironmentObject, if present, is always the
   1681  // initial environment.
   1682  if constexpr (std::is_same_v<SpecificEnvironment, VarEnvironmentObject>) {
   1683    if (frame.isEvalFrame()) {
   1684      return true;
   1685    }
   1686  }
   1687 
   1688  // For named lambda frames without CallObjects (i.e., no binding in the
   1689  // body of the function was closed over), the NamedLambdaObject
   1690  // corresponding to the named lambda scope is the initial environment.
   1691  if constexpr (std::is_same_v<SpecificEnvironment, NamedLambdaObject>) {
   1692    if (frame.isFunctionFrame() &&
   1693        frame.callee()->needsNamedLambdaEnvironment() &&
   1694        !frame.callee()->needsCallObject()) {
   1695      LexicalScope* namedLambdaScope = frame.script()->maybeNamedLambdaScope();
   1696      return &env.scope() == namedLambdaScope;
   1697    }
   1698  }
   1699 
   1700  return false;
   1701 }
   1702 
   1703 WithEnvironmentObject* CreateObjectsForEnvironmentChain(
   1704    JSContext* cx, const JS::EnvironmentChain& envChain,
   1705    HandleObject terminatingEnv);
   1706 
   1707 ModuleObject* GetModuleObjectForScript(JSScript* script);
   1708 
   1709 ModuleEnvironmentObject* GetModuleEnvironmentForScript(JSScript* script);
   1710 
   1711 [[nodiscard]] bool GetThisValueForDebuggerFrameMaybeOptimizedOut(
   1712    JSContext* cx, AbstractFramePtr frame, const jsbytecode* pc,
   1713    MutableHandleValue res);
   1714 [[nodiscard]] bool GetThisValueForDebuggerSuspendedGeneratorMaybeOptimizedOut(
   1715    JSContext* cx, AbstractGeneratorObject& genObj, JSScript* script,
   1716    MutableHandleValue res);
   1717 
   1718 [[nodiscard]] bool GlobalOrEvalDeclInstantiation(JSContext* cx,
   1719                                                 HandleObject envChain,
   1720                                                 HandleScript script,
   1721                                                 GCThingIndex lastFun);
   1722 
   1723 [[nodiscard]] bool InitFunctionEnvironmentObjects(JSContext* cx,
   1724                                                  AbstractFramePtr frame);
   1725 
   1726 [[nodiscard]] bool PushVarEnvironmentObject(JSContext* cx, Handle<Scope*> scope,
   1727                                            AbstractFramePtr frame);
   1728 
   1729 #ifdef DEBUG
   1730 bool AnalyzeEntrainedVariables(JSContext* cx, HandleScript script);
   1731 #endif
   1732 
   1733 extern JSObject* MaybeOptimizeBindUnqualifiedGlobalName(GlobalObject* global,
   1734                                                        PropertyName* name);
   1735 }  // namespace js
   1736 
   1737 #endif /* vm_EnvironmentObject_h */