Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/js/src/vm/EnvironmentObject.h
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2
 * vim: set ts=8 sts=4 et sw=4 tw=99:
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 "builtin/ModuleObject.h"
11
#include "frontend/NameAnalysisTypes.h"
12
#include "gc/Barrier.h"
13
#include "gc/WeakMap.h"
14
#include "js/GCHashTable.h"
15
#include "vm/ArgumentsObject.h"
16
#include "vm/GlobalObject.h"
17
#include "vm/JSContext.h"
18
#include "vm/JSObject.h"
19
#include "vm/ProxyObject.h"
20
#include "vm/Scope.h"
21
22
namespace js {
23
24
class ModuleObject;
25
typedef Handle<ModuleObject*> HandleModuleObject;
26
27
/*
28
 * Return a shape representing the static scope containing the variable
29
 * accessed by the ALIASEDVAR op at 'pc'.
30
 */
31
extern Shape*
32
EnvironmentCoordinateToEnvironmentShape(JSScript* script, jsbytecode* pc);
33
34
/* Return the name being accessed by the given ALIASEDVAR op. */
35
extern PropertyName*
36
EnvironmentCoordinateName(EnvironmentCoordinateNameCache& cache, JSScript* script, jsbytecode* pc);
37
38
/* Return the function script accessed by the given ALIASEDVAR op, or nullptr. */
39
extern JSScript*
40
EnvironmentCoordinateFunctionScript(JSScript* script, jsbytecode* pc);
41
42
43
/*** Environment objects *****************************************************/
44
45
46
/*** Environment objects *****************************************************/
47
48
/*
49
 * [SMDOC] Environment Objects
50
 *
51
 * About environments
52
 * ------------------
53
 *
54
 * (See also: ecma262 rev c7952de (19 Aug 2016) 8.1 "Lexical Environments".)
55
 *
56
 * Scoping in ES is specified in terms of "Environment Records". There's a
57
 * global Environment Record per realm, and a new Environment Record is created
58
 * whenever control enters a function, block, or other scope.
59
 *
60
 * A "Lexical Environment" is a list of nested Environment Records, innermost
61
 * first: everything that's in scope. Throughout SpiderMonkey, "environment"
62
 * means a Lexical Environment.
63
 *
64
 * N.B.: "Scope" means something different: a static scope, the compile-time
65
 * analogue of an environment. See Scope.h.
66
 *
67
 * How SpiderMonkey represents environments
68
 * ----------------------------------------
69
 *
70
 * Some environments are stored as JSObjects. Several kinds of objects
71
 * represent environments:
72
 *
73
 *   JSObject
74
 *    |
75
 *    +--NativeObject
76
 *    |   |
77
 *    |   +--EnvironmentObject             Engine-internal environment
78
 *    |   |   |
79
 *    |   |   +--CallObject                    Environment of entire function
80
 *    |   |   |
81
 *    |   |   +--ModuleEnvironmentObject       Module top-level environment
82
 *    |   |   |
83
 *    |   |   +--LexicalEnvironmentObject      Lexical (block) environment
84
 *    |   |   |   |
85
 *    |   |   |   +--NamedLambdaObject             Environment for `(function f(){...})`
86
 *    |   |   |                                        containing only a binding for `f`
87
 *    |   |   +--VarEnvironmentObject          See VarScope in Scope.h.
88
 *    |   |   |
89
 *    |   |   +--WithEnvironmentObject         Presents object properties as bindings
90
 *    |   |   |
91
 *    |   |   +--NonSyntacticVariablesObject   See "Non-syntactic environments" below
92
 *    |   |
93
 *    |   +--GlobalObject                  The global environment
94
 *    |
95
 *    +--ProxyObject
96
 *        |
97
 *        +--DebugEnvironmentProxy         Environment for debugger eval-in-frame
98
 *
99
 * EnvironmentObjects are technically real JSObjects but only belong on the
100
 * environment chain (that is, fp->environmentChain() or fun->environment()).
101
 * They are never exposed to scripts.
102
 *
103
 * Note that reserved slots in any base classes shown above are fixed for all
104
 * derived classes. So e.g. EnvironmentObject::enclosingEnvironment() can
105
 * simply access a fixed slot without further dynamic type information.
106
 *
107
 * When the current environment is represented by an object, the stack frame
108
 * has a pointer to that object (see AbstractFramePtr::environmentChain()).
109
 * However, that isn't always the case. Where possible, we store binding values
110
 * in JS stack slots. For block and function scopes where all bindings can be
111
 * stored in stack slots, nothing is allocated in the heap; there is no
112
 * environment object.
113
 *
114
 * Full information about the environment chain is always recoverable:
115
 * EnvironmentIter can do it, and we construct a fake environment for debugger
116
 * eval-in-frame (see "Debug environment objects" below).
117
 *
118
 * Syntactic Environments
119
 * ----------------------
120
 *
121
 * Environments may be syntactic, i.e., corresponding to source text, or
122
 * non-syntactic, i.e., specially created by embedding. The distinction is
123
 * necessary to maintain invariants about the environment chain: non-syntactic
124
 * environments may not occur in arbitrary positions in the chain.
125
 *
126
 * CallObject, ModuleEnvironmentObject, and LexicalEnvironmentObject always
127
 * represent syntactic environments. (CallObject is considered syntactic even
128
 * when it's used as the scope of strict eval code.) WithEnvironmentObject is
129
 * syntactic when it's used to represent the scope of a `with` block.
130
 *
131
 *
132
 * Non-syntactic Environments
133
 * --------------------------
134
 *
135
 * A non-syntactic environment is one that was not created due to JS source
136
 * code. On the scope chain, a single NonSyntactic GlobalScope maps to 0+
137
 * non-syntactic environment objects. This is contrasted with syntactic
138
 * environments, where each scope corresponds to 0 or 1 environment object.
139
 *
140
 * There are 3 kinds of dynamic environment objects:
141
 *
142
 * 1. WithEnvironmentObject
143
 *
144
 *    When the embedding compiles or executes a script, it has the option to
145
 *    pass in a vector of objects to be used as the initial env chain, ordered
146
 *    from outermost env to innermost env. Each of those objects is wrapped by
147
 *    a WithEnvironmentObject.
148
 *
149
 *    The innermost object passed in by the embedding becomes a qualified
150
 *    variables object that captures 'var' bindings. That is, it wraps the
151
 *    holder object of 'var' bindings.
152
 *
153
 *    Does not hold 'let' or 'const' bindings.
154
 *
155
 * 2. NonSyntacticVariablesObject
156
 *
157
 *    When the embedding wants qualified 'var' bindings and unqualified
158
 *    bareword assignments to go on a different object than the global
159
 *    object. While any object can be made into a qualified variables object,
160
 *    only the GlobalObject and NonSyntacticVariablesObject are considered
161
 *    unqualified variables objects.
162
 *
163
 *    Unlike WithEnvironmentObjects that delegate to the object they wrap,
164
 *    this object is itself the holder of 'var' bindings.
165
 *
166
 *    Does not hold 'let' or 'const' bindings.
167
 *
168
 * 3. LexicalEnvironmentObject
169
 *
170
 *    Each non-syntactic object used as a qualified variables object needs to
171
 *    enclose a non-syntactic LexicalEnvironmentObject to hold 'let' and
172
 *    'const' bindings. There is a bijection per compartment between the
173
 *    non-syntactic variables objects and their non-syntactic
174
 *    LexicalEnvironmentObjects.
175
 *
176
 *    Does not hold 'var' bindings.
177
 *
178
 * The embedding (Gecko) uses non-syntactic envs for various things, some of
179
 * which are detailed below. All env chain listings below are, from top to
180
 * bottom, outermost to innermost.
181
 *
182
 * A. Component loading
183
 *
184
 * Components may be loaded in a shared global mode where most JSMs share a
185
 * single global in order to save on memory and avoid CCWs. To support this, a
186
 * NonSyntacticVariablesObject is used for each JSM to provide a basic form of
187
 * isolation. They have the following env chain:
188
 *
189
 *   BackstagePass global
190
 *       |
191
 *   LexicalEnvironmentObject[this=global]
192
 *       |
193
 *   NonSyntacticVariablesObject
194
 *       |
195
 *   LexicalEnvironmentObject[this=nsvo]
196
 *
197
 * B.1 Subscript loading
198
 *
199
 * Subscripts may be loaded into a target object and it's associated global.
200
 * They have the following env chain:
201
 *
202
 *   Target object's global
203
 *       |
204
 *   LexicalEnvironmentObject[this=global]
205
 *       |
206
 *   WithEnvironmentObject wrapping target
207
 *       |
208
 *   LexicalEnvironmentObject[this=target]
209
 *
210
 * B.2 Subscript loading (Shared-global JSM)
211
 *
212
 * The target object of a subscript load may be in a JSM with a shared global,
213
 * in which case we will also have the NonSyntacticVariablesObject on the
214
 * chain.
215
 *
216
 *   Target object's global
217
 *       |
218
 *   LexicalEnvironmentObject[this=global]
219
 *       |
220
 *   NonSyntacticVariablesObject
221
 *       |
222
 *   LexicalEnvironmentObject[this=nsvo]
223
 *       |
224
 *   WithEnvironmentObject wrapping target
225
 *       |
226
 *   LexicalEnvironmentObject[this=target]
227
 *
228
 * D. Frame scripts
229
 *
230
 * XUL frame scripts are loaded in the same global as components, with a
231
 * NonSyntacticVariablesObject as a "polluting global", and a with environment
232
 * wrapping a message manager object. This is done exclusively in
233
 * js::ExecuteInScopeChainAndReturnNewScope.
234
 *
235
 *   BackstagePass global
236
 *       |
237
 *   LexicalEnvironmentObject[this=global]
238
 *       |
239
 *   NonSyntacticVariablesObject
240
 *       |
241
 *   WithEnvironmentObject wrapping messageManager
242
 *       |
243
 *   LexicalEnvironmentObject[this=messageManager]
244
 *
245
 * D. XBL and DOM event handlers
246
 *
247
 * XBL methods are compiled as functions with XUL elements on the env chain,
248
 * and DOM event handlers are compiled as functions with HTML elements on the
249
 * env chain. For a chain of elements e0,e1,...:
250
 *
251
 *      ...
252
 *       |
253
 *   WithEnvironmentObject wrapping e1
254
 *       |
255
 *   WithEnvironmentObject wrapping e0
256
 *       |
257
 *   LexicalEnvironmentObject
258
 *
259
 */
260
261
class EnvironmentObject : public NativeObject
262
{
263
  protected:
264
    // The enclosing environment. Either another EnvironmentObject, a
265
    // GlobalObject, or a non-syntactic environment object.
266
    static const uint32_t ENCLOSING_ENV_SLOT = 0;
267
268
    inline void setAliasedBinding(JSContext* cx, uint32_t slot, PropertyName* name,
269
                                  const Value& v);
270
271
0
    void setEnclosingEnvironment(JSObject* enclosing) {
272
0
        setReservedSlot(ENCLOSING_ENV_SLOT, ObjectOrNullValue(enclosing));
273
0
    }
274
275
  public:
276
    // Since every env chain terminates with a global object, whether
277
    // GlobalObject or a non-syntactic one, and since those objects do not
278
    // derive EnvironmentObject (they have completely different layouts), the
279
    // enclosing environment of an EnvironmentObject is necessarily non-null.
280
9.74M
    JSObject& enclosingEnvironment() const {
281
9.74M
        return getReservedSlot(ENCLOSING_ENV_SLOT).toObject();
282
9.74M
    }
283
284
163
    void initEnclosingEnvironment(JSObject* enclosing) {
285
163
        initReservedSlot(ENCLOSING_ENV_SLOT, ObjectOrNullValue(enclosing));
286
163
    }
287
288
    // Get or set a name contained in this environment.
289
31
    const Value& aliasedBinding(EnvironmentCoordinate ec) {
290
31
        return getSlot(ec.slot());
291
31
    }
292
293
0
    const Value& aliasedBinding(const BindingIter& bi) {
294
0
        MOZ_ASSERT(bi.location().kind() == BindingLocation::Kind::Environment);
295
0
        return getSlot(bi.location().slot());
296
0
    }
297
298
    inline void setAliasedBinding(JSContext* cx, EnvironmentCoordinate ec, PropertyName* name,
299
                                  const Value& v);
300
301
    inline void setAliasedBinding(JSContext* cx, const BindingIter& bi, const Value& v);
302
303
    // For JITs.
304
2
    static size_t offsetOfEnclosingEnvironment() {
305
2
        return getFixedSlotOffset(ENCLOSING_ENV_SLOT);
306
2
    }
307
308
0
    static uint32_t enclosingEnvironmentSlot() {
309
0
        return ENCLOSING_ENV_SLOT;
310
0
    }
311
};
312
313
class CallObject : public EnvironmentObject
314
{
315
  protected:
316
    static const uint32_t CALLEE_SLOT = 1;
317
318
    static CallObject* create(JSContext* cx, HandleScript script, HandleFunction callee,
319
                              HandleObject enclosing);
320
321
  public:
322
    static const uint32_t RESERVED_SLOTS = 2;
323
    static const Class class_;
324
325
    /* These functions are internal and are exposed only for JITs. */
326
327
    /*
328
     * Construct a bare-bones call object given a shape and a non-singleton
329
     * group.  The call object must be further initialized to be usable.
330
     */
331
    static CallObject* create(JSContext* cx, HandleShape shape, HandleObjectGroup group);
332
333
    /*
334
     * Construct a bare-bones call object given a shape and make it into
335
     * a singleton.  The call object must be initialized to be usable.
336
     */
337
    static CallObject* createSingleton(JSContext* cx, HandleShape shape);
338
339
    static CallObject* createTemplateObject(JSContext* cx, HandleScript script,
340
                                            HandleObject enclosing, gc::InitialHeap heap);
341
342
    static CallObject* create(JSContext* cx, HandleFunction callee, HandleObject enclosing);
343
    static CallObject* create(JSContext* cx, AbstractFramePtr frame);
344
345
    static CallObject* createHollowForDebug(JSContext* cx, HandleFunction callee);
346
347
    /*
348
     * When an aliased formal (var accessed by nested closures) is also
349
     * aliased by the arguments object, it must of course exist in one
350
     * canonical location and that location is always the CallObject. For this
351
     * to work, the ArgumentsObject stores special MagicValue in its array for
352
     * forwarded-to-CallObject variables. This MagicValue's payload is the
353
     * slot of the CallObject to access.
354
     */
355
0
    const Value& aliasedFormalFromArguments(const Value& argsValue) {
356
0
        return getSlot(ArgumentsObject::SlotFromMagicScopeSlotValue(argsValue));
357
0
    }
358
    inline void setAliasedFormalFromArguments(JSContext* cx, const Value& argsValue, jsid id,
359
                                              const Value& v);
360
361
0
    JSFunction& callee() const {
362
0
        return getReservedSlot(CALLEE_SLOT).toObject().as<JSFunction>();
363
0
    }
364
365
    /* For jit access. */
366
0
    static size_t offsetOfCallee() {
367
0
        return getFixedSlotOffset(CALLEE_SLOT);
368
0
    }
369
370
0
    static size_t calleeSlot() {
371
0
        return CALLEE_SLOT;
372
0
    }
373
};
374
375
class VarEnvironmentObject : public EnvironmentObject
376
{
377
    static const uint32_t SCOPE_SLOT = 1;
378
379
    static VarEnvironmentObject* create(JSContext* cx, HandleShape shape, HandleObject enclosing,
380
                                        gc::InitialHeap heap);
381
382
1
    void initScope(Scope* scope) {
383
1
        initReservedSlot(SCOPE_SLOT, PrivateGCThingValue(scope));
384
1
    }
385
386
  public:
387
    static const uint32_t RESERVED_SLOTS = 2;
388
    static const Class class_;
389
390
    static VarEnvironmentObject* create(JSContext* cx, HandleScope scope, AbstractFramePtr frame);
391
    static VarEnvironmentObject* createHollowForDebug(JSContext* cx, Handle<VarScope*> scope);
392
393
0
    Scope& scope() const {
394
0
        Value v = getReservedSlot(SCOPE_SLOT);
395
0
        MOZ_ASSERT(v.isPrivateGCThing());
396
0
        Scope& s = *static_cast<Scope*>(v.toGCThing());
397
0
        MOZ_ASSERT(s.is<VarScope>() || s.is<EvalScope>());
398
0
        return s;
399
0
    }
400
401
0
    bool isForEval() const {
402
0
        return scope().is<EvalScope>();
403
0
    }
404
};
405
406
class ModuleEnvironmentObject : public EnvironmentObject
407
{
408
    static const uint32_t MODULE_SLOT = 1;
409
410
    static const ObjectOps objectOps_;
411
    static const ClassOps classOps_;
412
413
  public:
414
    static const Class class_;
415
416
    static const uint32_t RESERVED_SLOTS = 2;
417
418
    static ModuleEnvironmentObject* create(JSContext* cx, HandleModuleObject module);
419
    ModuleObject& module();
420
    IndirectBindingMap& importBindings();
421
422
    bool createImportBinding(JSContext* cx, HandleAtom importName, HandleModuleObject module,
423
                             HandleAtom exportName);
424
425
    bool hasImportBinding(HandlePropertyName name);
426
427
    bool lookupImport(jsid name, ModuleEnvironmentObject** envOut, Shape** shapeOut);
428
429
    void fixEnclosingEnvironmentAfterCompartmentMerge(GlobalObject& global);
430
431
  private:
432
    static bool lookupProperty(JSContext* cx, HandleObject obj, HandleId id,
433
                               MutableHandleObject objp, MutableHandle<PropertyResult> propp);
434
    static bool hasProperty(JSContext* cx, HandleObject obj, HandleId id, bool* foundp);
435
    static bool getProperty(JSContext* cx, HandleObject obj, HandleValue receiver, HandleId id,
436
                            MutableHandleValue vp);
437
    static bool setProperty(JSContext* cx, HandleObject obj, HandleId id, HandleValue v,
438
                            HandleValue receiver, JS::ObjectOpResult& result);
439
    static bool getOwnPropertyDescriptor(JSContext* cx, HandleObject obj, HandleId id,
440
                                         MutableHandle<PropertyDescriptor> desc);
441
    static bool deleteProperty(JSContext* cx, HandleObject obj, HandleId id,
442
                               ObjectOpResult& result);
443
    static bool newEnumerate(JSContext* cx, HandleObject obj, AutoIdVector& properties,
444
                             bool enumerableOnly);
445
};
446
447
typedef Rooted<ModuleEnvironmentObject*> RootedModuleEnvironmentObject;
448
typedef Handle<ModuleEnvironmentObject*> HandleModuleEnvironmentObject;
449
typedef MutableHandle<ModuleEnvironmentObject*> MutableHandleModuleEnvironmentObject;
450
451
class WasmInstanceEnvironmentObject : public EnvironmentObject
452
{
453
    // Currently WasmInstanceScopes do not use their scopes in a
454
    // meaningful way. However, it is an invariant of DebugEnvironments that
455
    // environments kept in those maps have live scopes, thus this strong
456
    // reference.
457
    static const uint32_t SCOPE_SLOT = 1;
458
459
  public:
460
    static const Class class_;
461
462
    static const uint32_t RESERVED_SLOTS = 2;
463
464
    static WasmInstanceEnvironmentObject* createHollowForDebug(JSContext* cx,
465
                                                               Handle<WasmInstanceScope*> scope);
466
0
    WasmInstanceScope& scope() const {
467
0
        Value v = getReservedSlot(SCOPE_SLOT);
468
0
        MOZ_ASSERT(v.isPrivateGCThing());
469
0
        return *static_cast<WasmInstanceScope*>(v.toGCThing());
470
0
    }
471
};
472
473
class WasmFunctionCallObject : public EnvironmentObject
474
{
475
    // Currently WasmFunctionCallObjects do not use their scopes in a
476
    // meaningful way. However, it is an invariant of DebugEnvironments that
477
    // environments kept in those maps have live scopes, thus this strong
478
    // reference.
479
    static const uint32_t SCOPE_SLOT = 1;
480
481
  public:
482
    static const Class class_;
483
484
    static const uint32_t RESERVED_SLOTS = 2;
485
486
    static WasmFunctionCallObject* createHollowForDebug(JSContext* cx, HandleObject enclosing,
487
                                                        Handle<WasmFunctionScope*> scope);
488
0
    WasmFunctionScope& scope() const {
489
0
        Value v = getReservedSlot(SCOPE_SLOT);
490
0
        MOZ_ASSERT(v.isPrivateGCThing());
491
0
        return *static_cast<WasmFunctionScope*>(v.toGCThing());
492
0
    }
493
};
494
495
class LexicalEnvironmentObject : public EnvironmentObject
496
{
497
    // Global and non-syntactic lexical environments need to store a 'this'
498
    // value and all other lexical environments have a fixed shape and store a
499
    // backpointer to the LexicalScope.
500
    //
501
    // Since the two sets are disjoint, we only use one slot to save space.
502
    static const unsigned THIS_VALUE_OR_SCOPE_SLOT = 1;
503
504
  public:
505
    static const unsigned RESERVED_SLOTS = 2;
506
    static const Class class_;
507
508
  private:
509
    static LexicalEnvironmentObject* createTemplateObject(JSContext* cx, HandleShape shape,
510
                                                          HandleObject enclosing,
511
                                                          gc::InitialHeap heap);
512
513
14
    void initThisValue(JSObject* obj) {
514
14
        MOZ_ASSERT(isGlobal() || !isSyntactic());
515
14
        initReservedSlot(THIS_VALUE_OR_SCOPE_SLOT, GetThisValue(obj));
516
14
    }
517
518
49
    void initScopeUnchecked(LexicalScope* scope) {
519
49
        initReservedSlot(THIS_VALUE_OR_SCOPE_SLOT, PrivateGCThingValue(scope));
520
49
    }
521
522
0
    void initScope(LexicalScope* scope) {
523
0
        MOZ_ASSERT(!isGlobal());
524
0
        MOZ_ASSERT(isSyntactic());
525
0
        initScopeUnchecked(scope);
526
0
    }
527
528
  public:
529
    static LexicalEnvironmentObject* create(JSContext* cx, Handle<LexicalScope*> scope,
530
                                            HandleObject enclosing, gc::InitialHeap heap);
531
    static LexicalEnvironmentObject* create(JSContext* cx, Handle<LexicalScope*> scope,
532
                                            AbstractFramePtr frame);
533
    static LexicalEnvironmentObject* createGlobal(JSContext* cx, Handle<GlobalObject*> global);
534
    static LexicalEnvironmentObject* createNonSyntactic(JSContext* cx, HandleObject enclosing,
535
                                                        HandleObject thisv);
536
    static LexicalEnvironmentObject* createHollowForDebug(JSContext* cx,
537
                                                          Handle<LexicalScope*> scope);
538
539
    // Create a new LexicalEnvironmentObject with the same enclosing env and
540
    // variable values as this.
541
    static LexicalEnvironmentObject* clone(JSContext* cx, Handle<LexicalEnvironmentObject*> env);
542
543
    // Create a new LexicalEnvironmentObject with the same enclosing env as
544
    // this, with all variables uninitialized.
545
    static LexicalEnvironmentObject* recreate(JSContext* cx, Handle<LexicalEnvironmentObject*> env);
546
547
    // For non-extensible lexical environments, the LexicalScope that created
548
    // this environment. Otherwise asserts.
549
0
    LexicalScope& scope() const {
550
0
        Value v = getReservedSlot(THIS_VALUE_OR_SCOPE_SLOT);
551
0
        MOZ_ASSERT(!isExtensible() && v.isPrivateGCThing());
552
0
        return *static_cast<LexicalScope*>(v.toGCThing());
553
0
    }
554
555
    // Is this the global lexical scope?
556
48
    bool isGlobal() const {
557
48
        return enclosingEnvironment().is<GlobalObject>();
558
48
    }
559
560
0
    GlobalObject& global() const {
561
0
        return enclosingEnvironment().as<GlobalObject>();
562
0
    }
563
564
    // Global and non-syntactic lexical scopes are extensible. All other
565
    // lexical scopes are not.
566
    bool isExtensible() const;
567
568
    // Is this a syntactic (i.e. corresponds to a source text) lexical
569
    // environment?
570
97
    bool isSyntactic() const {
571
97
        return !isExtensible() || isGlobal();
572
97
    }
573
574
    // For extensible lexical environments, the 'this' value for its
575
    // scope. Otherwise asserts.
576
    Value thisValue() const;
577
};
578
579
class NamedLambdaObject : public LexicalEnvironmentObject
580
{
581
    static NamedLambdaObject* create(JSContext* cx, HandleFunction callee,
582
                                     HandleFunction replacement,
583
                                     HandleObject enclosing, gc::InitialHeap heap);
584
585
  public:
586
    static NamedLambdaObject* createTemplateObject(JSContext* cx, HandleFunction callee,
587
                                                   gc::InitialHeap heap);
588
589
    static NamedLambdaObject* create(JSContext* cx, AbstractFramePtr frame);
590
    static NamedLambdaObject* create(JSContext* cx, AbstractFramePtr frame,
591
                                     HandleFunction replacement);
592
593
    // For JITs.
594
    static size_t lambdaSlot();
595
};
596
597
// A non-syntactic dynamic scope object that captures non-lexical
598
// bindings. That is, a scope object that captures both qualified var
599
// assignments and unqualified bareword assignments. Its parent is always the
600
// global lexical environment.
601
//
602
// This is used in ExecuteInGlobalAndReturnScope and sits in front of the
603
// global scope to store 'var' bindings, and to store fresh properties created
604
// by assignments to undeclared variables that otherwise would have gone on
605
// the global object.
606
class NonSyntacticVariablesObject : public EnvironmentObject
607
{
608
  public:
609
    static const unsigned RESERVED_SLOTS = 1;
610
    static const Class class_;
611
612
    static NonSyntacticVariablesObject* create(JSContext* cx);
613
};
614
615
extern bool
616
CreateNonSyntacticEnvironmentChain(JSContext* cx, JS::AutoObjectVector& envChain,
617
                                   MutableHandleObject env, MutableHandleScope scope);
618
619
// With environment objects on the run-time environment chain.
620
class WithEnvironmentObject : public EnvironmentObject
621
{
622
    static const unsigned OBJECT_SLOT = 1;
623
    static const unsigned THIS_SLOT = 2;
624
    static const unsigned SCOPE_SLOT = 3;
625
626
  public:
627
    static const unsigned RESERVED_SLOTS = 4;
628
    static const Class class_;
629
630
    static WithEnvironmentObject* create(JSContext* cx, HandleObject object, HandleObject enclosing,
631
                                         Handle<WithScope*> scope);
632
    static WithEnvironmentObject* createNonSyntactic(JSContext* cx, HandleObject object,
633
                                                     HandleObject enclosing);
634
635
    /* Return the 'o' in 'with (o)'. */
636
    JSObject& object() const;
637
638
    /* Return object for GetThisValue. */
639
    JSObject* withThis() const;
640
641
    /*
642
     * Return whether this object is a syntactic with object.  If not, this is
643
     * a With object we inserted between the outermost syntactic scope and the
644
     * global object to wrap the environment chain someone explicitly passed
645
     * via JSAPI to CompileFunction or script evaluation.
646
     */
647
    bool isSyntactic() const;
648
649
    // For syntactic with environment objects, the with scope.
650
    WithScope& scope() const;
651
652
0
    static inline size_t objectSlot() {
653
0
        return OBJECT_SLOT;
654
0
    }
655
656
0
    static inline size_t thisSlot() {
657
0
        return THIS_SLOT;
658
0
    }
659
};
660
661
// Internal scope object used by JSOP_BINDNAME upon encountering an
662
// uninitialized lexical slot or an assignment to a 'const' binding.
663
//
664
// ES6 lexical bindings cannot be accessed in any way (throwing
665
// ReferenceErrors) until initialized. Normally, NAME operations
666
// unconditionally check for uninitialized lexical slots. When getting or
667
// looking up names, this can be done without slowing down normal operations
668
// on the return value. When setting names, however, we do not want to pollute
669
// all set-property paths with uninitialized lexical checks. For setting names
670
// (i.e. JSOP_SETNAME), we emit an accompanying, preceding JSOP_BINDNAME which
671
// finds the right scope on which to set the name. Moreover, when the name on
672
// the scope is an uninitialized lexical, we cannot throw eagerly, as the spec
673
// demands that the error be thrown after evaluating the RHS of
674
// assignments. Instead, this sentinel scope object is pushed on the stack.
675
// Attempting to access anything on this scope throws the appropriate
676
// ReferenceError.
677
//
678
// ES6 'const' bindings induce a runtime error when assigned to outside
679
// of initialization, regardless of strictness.
680
class RuntimeLexicalErrorObject : public EnvironmentObject
681
{
682
    static const unsigned ERROR_SLOT = 1;
683
684
  public:
685
    static const unsigned RESERVED_SLOTS = 2;
686
    static const Class class_;
687
688
    static RuntimeLexicalErrorObject* create(JSContext* cx, HandleObject enclosing,
689
                                             unsigned errorNumber);
690
691
0
    unsigned errorNumber() {
692
0
        return getReservedSlot(ERROR_SLOT).toInt32();
693
0
    }
694
};
695
696
697
/*****************************************************************************/
698
699
// A environment iterator describes the active environments starting from an
700
// environment, scope pair. This pair may be derived from the current point of
701
// execution in a frame. If derived in such a fashion, the EnvironmentIter
702
// tracks whether the current scope is within the extent of this initial
703
// frame.  Here, "frame" means a single activation of: a function, eval, or
704
// global code.
705
class MOZ_RAII EnvironmentIter
706
{
707
    Rooted<ScopeIter> si_;
708
    RootedObject env_;
709
    AbstractFramePtr frame_;
710
711
    void incrementScopeIter();
712
    void settle();
713
714
    // No value semantics.
715
    EnvironmentIter(const EnvironmentIter& ei) = delete;
716
717
  public:
718
    // Constructing from a copy of an existing EnvironmentIter.
719
    EnvironmentIter(JSContext* cx, const EnvironmentIter& ei
720
                    MOZ_GUARD_OBJECT_NOTIFIER_PARAM);
721
722
    // Constructing from an environment, scope pair. All environments
723
    // considered not to be withinInitialFrame, since no frame is given.
724
    EnvironmentIter(JSContext* cx, JSObject* env, Scope* scope
725
                    MOZ_GUARD_OBJECT_NOTIFIER_PARAM);
726
727
    // Constructing from a frame. Places the EnvironmentIter on the innermost
728
    // environment at pc.
729
    EnvironmentIter(JSContext* cx, AbstractFramePtr frame, jsbytecode* pc
730
                    MOZ_GUARD_OBJECT_NOTIFIER_PARAM);
731
732
    // Constructing from an environment, scope and frame. The frame is given
733
    // to initialize to proper enclosing environment/scope.
734
    EnvironmentIter(JSContext* cx, JSObject* env, Scope* scope, AbstractFramePtr frame
735
                    MOZ_GUARD_OBJECT_NOTIFIER_PARAM);
736
737
738
0
    bool done() const {
739
0
        return si_.done();
740
0
    }
741
742
0
    explicit operator bool() const {
743
0
        return !done();
744
0
    }
745
746
189
    void operator++(int) {
747
189
        if (hasAnyEnvironmentObject()) {
748
41
            env_ = &env_->as<EnvironmentObject>().enclosingEnvironment();
749
41
        }
750
189
        incrementScopeIter();
751
189
        settle();
752
189
    }
753
754
0
    EnvironmentIter& operator++() {
755
0
        operator++(1);
756
0
        return *this;
757
0
    }
758
759
    // If done():
760
    JSObject& enclosingEnvironment() const;
761
762
    // If !done():
763
    bool hasNonSyntacticEnvironmentObject() const;
764
765
174
    bool hasSyntacticEnvironment() const {
766
174
        return si_.hasSyntacticEnvironment();
767
174
    }
768
769
189
    bool hasAnyEnvironmentObject() const {
770
189
        return hasNonSyntacticEnvironmentObject() || hasSyntacticEnvironment();
771
189
    }
772
773
0
    EnvironmentObject& environment() const {
774
0
        MOZ_ASSERT(hasAnyEnvironmentObject());
775
0
        return env_->as<EnvironmentObject>();
776
0
    }
777
778
360
    Scope& scope() const {
779
360
        return *si_.scope();
780
360
    }
781
782
0
    Scope* maybeScope() const {
783
0
        if (si_) {
784
0
            return si_.scope();
785
0
        }
786
0
        return nullptr;
787
0
    }
788
789
0
    JSFunction& callee() const {
790
0
        return env_->as<CallObject>().callee();
791
0
    }
792
793
343
    bool withinInitialFrame() const {
794
343
        return !!frame_;
795
343
    }
796
797
23
    AbstractFramePtr initialFrame() const {
798
23
        MOZ_ASSERT(withinInitialFrame());
799
23
        return frame_;
800
23
    }
801
802
0
    AbstractFramePtr maybeInitialFrame() const {
803
0
        return frame_;
804
0
    }
805
806
    MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
807
};
808
809
// The key in MissingEnvironmentMap. For live frames, maps live frames to
810
// their synthesized environments. For completely optimized-out environments,
811
// maps the Scope to their synthesized environments. The env we synthesize for
812
// Scopes are read-only, and we never use their parent links, so they don't
813
// need to be distinct.
814
//
815
// That is, completely optimized out environments can't be distinguished by
816
// frame. Note that even if the frame corresponding to the Scope is live on
817
// the stack, it is unsound to synthesize an environment from that live
818
// frame. In other words, the provenance of the environment chain is from
819
// allocated closures (i.e., allocation sites) and is irrecoverable from
820
// simple stack inspection (i.e., call sites).
821
class MissingEnvironmentKey
822
{
823
    friend class LiveEnvironmentVal;
824
825
    AbstractFramePtr frame_;
826
    Scope* scope_;
827
828
  public:
829
    explicit MissingEnvironmentKey(const EnvironmentIter& ei)
830
      : frame_(ei.maybeInitialFrame()),
831
        scope_(ei.maybeScope())
832
0
    { }
833
834
    MissingEnvironmentKey(AbstractFramePtr frame, Scope* scope)
835
      : frame_(frame),
836
        scope_(scope)
837
0
    { }
838
839
0
    AbstractFramePtr frame() const { return frame_; }
840
0
    Scope* scope() const { return scope_; }
841
842
0
    void updateScope(Scope* scope) { scope_ = scope; }
843
0
    void updateFrame(AbstractFramePtr frame) { frame_ = frame; }
844
845
    // For use as hash policy.
846
    typedef MissingEnvironmentKey Lookup;
847
    static HashNumber hash(MissingEnvironmentKey sk);
848
    static bool match(MissingEnvironmentKey sk1, MissingEnvironmentKey sk2);
849
0
    bool operator!=(const MissingEnvironmentKey& other) const {
850
0
        return frame_ != other.frame_ || scope_ != other.scope_;
851
0
    }
852
0
    static void rekey(MissingEnvironmentKey& k, const MissingEnvironmentKey& newKey) {
853
0
        k = newKey;
854
0
    }
855
};
856
857
// The value in LiveEnvironmentMap, mapped from by live environment objects.
858
class LiveEnvironmentVal
859
{
860
    friend class DebugEnvironments;
861
    friend class MissingEnvironmentKey;
862
863
    AbstractFramePtr frame_;
864
    HeapPtr<Scope*> scope_;
865
866
    static void staticAsserts();
867
868
  public:
869
    explicit LiveEnvironmentVal(const EnvironmentIter& ei)
870
      : frame_(ei.initialFrame()),
871
        scope_(ei.maybeScope())
872
0
    { }
873
874
0
    AbstractFramePtr frame() const { return frame_; }
875
0
    Scope* scope() const { return scope_; }
876
877
0
    void updateFrame(AbstractFramePtr frame) { frame_ = frame; }
878
879
    bool needsSweep();
880
};
881
882
883
/*****************************************************************************/
884
885
/*
886
 * Debug environment objects
887
 *
888
 * The debugger effectively turns every opcode into a potential direct eval.
889
 * Naively, this would require creating a EnvironmentObject for every
890
 * call/block scope and using JSOP_GETALIASEDVAR for every access. To optimize
891
 * this, the engine assumes there is no debugger and optimizes scope access
892
 * and creation accordingly. When the debugger wants to perform an unexpected
893
 * eval-in-frame (or other, similar environment-requiring operations),
894
 * fp->environmentChain is now incomplete.
895
 *
896
 * To resolve this, the debugger first calls GetDebugEnvironmentFor* to
897
 * synthesize a "debug env chain". A debug env chain is just a chain of
898
 * objects that fill in missing environments and protect the engine from
899
 * unexpected access. (The latter means that some debugger operations, like
900
 * redefining a lexical binding, can fail when a true eval would succeed.) To
901
 * do both of these things, GetDebugEnvironmentFor* creates a new proxy
902
 * DebugEnvironmentProxy to sit in front of every existing EnvironmentObject.
903
 *
904
 * GetDebugEnvironmentFor* ensures the invariant that the same
905
 * DebugEnvironmentProxy is always produced for the same underlying
906
 * environment (optimized or not!). This is maintained by some bookkeeping
907
 * information stored in DebugEnvironments.
908
 */
909
910
extern JSObject*
911
GetDebugEnvironmentForFunction(JSContext* cx, HandleFunction fun);
912
913
extern JSObject*
914
GetDebugEnvironmentForFrame(JSContext* cx, AbstractFramePtr frame, jsbytecode* pc);
915
916
extern JSObject*
917
GetDebugEnvironmentForGlobalLexicalEnvironment(JSContext* cx);
918
919
/* Provides debugger access to a environment. */
920
class DebugEnvironmentProxy : public ProxyObject
921
{
922
    /*
923
     * The enclosing environment on the dynamic environment chain. This slot is analogous
924
     * to the ENCLOSING_ENV_SLOT of a EnvironmentObject.
925
     */
926
    static const unsigned ENCLOSING_SLOT = 0;
927
928
    /*
929
     * NullValue or a dense array holding the unaliased variables of a function
930
     * frame that has been popped.
931
     */
932
    static const unsigned SNAPSHOT_SLOT = 1;
933
934
  public:
935
    static DebugEnvironmentProxy* create(JSContext* cx, EnvironmentObject& env,
936
                                         HandleObject enclosing);
937
938
    // NOTE: The environment may be a debug hollow with invalid
939
    // enclosingEnvironment. Always use the enclosingEnvironment accessor on
940
    // the DebugEnvironmentProxy in order to walk the environment chain.
941
    EnvironmentObject& environment() const;
942
    JSObject& enclosingEnvironment() const;
943
944
    /* May only be called for proxies to function call objects. */
945
    ArrayObject* maybeSnapshot() const;
946
    void initSnapshot(ArrayObject& snapshot);
947
948
    // Currently, the 'declarative' environments are function, module, and
949
    // lexical environments.
950
    bool isForDeclarative() const;
951
952
    // Get a property by 'id', but returns sentinel values instead of throwing
953
    // on exceptional cases.
954
    static bool getMaybeSentinelValue(JSContext* cx, Handle<DebugEnvironmentProxy*> env,
955
                                      HandleId id, MutableHandleValue vp);
956
957
    // Returns true iff this is a function environment with its own this-binding
958
    // (all functions except arrow functions).
959
    bool isFunctionEnvironmentWithThis();
960
961
    // Does this debug environment not have a real counterpart or was never
962
    // live (and thus does not have a synthesized EnvironmentObject or a
963
    // snapshot)?
964
    bool isOptimizedOut() const;
965
};
966
967
/* Maintains per-realm debug environment bookkeeping information. */
968
class DebugEnvironments
969
{
970
    Zone* zone_;
971
972
    /* The map from (non-debug) environments to debug environments. */
973
    ObjectWeakMap proxiedEnvs;
974
975
    /*
976
     * The map from live frames which have optimized-away environments to the
977
     * corresponding debug environments.
978
     */
979
    typedef HashMap<MissingEnvironmentKey,
980
                    ReadBarrieredDebugEnvironmentProxy,
981
                    MissingEnvironmentKey,
982
                    ZoneAllocPolicy> MissingEnvironmentMap;
983
    MissingEnvironmentMap missingEnvs;
984
985
    /*
986
     * The map from environment objects of live frames to the live frame. This
987
     * map updated lazily whenever the debugger needs the information. In
988
     * between two lazy updates, liveEnvs becomes incomplete (but not invalid,
989
     * onPop* removes environments as they are popped). Thus, two consecutive
990
     * debugger lazy updates of liveEnvs need only fill in the new
991
     * environments.
992
     */
993
    typedef GCHashMap<ReadBarriered<JSObject*>,
994
                      LiveEnvironmentVal,
995
                      MovableCellHasher<ReadBarriered<JSObject*>>,
996
                      ZoneAllocPolicy> LiveEnvironmentMap;
997
    LiveEnvironmentMap liveEnvs;
998
999
  public:
1000
    DebugEnvironments(JSContext* cx, Zone* zone);
1001
    ~DebugEnvironments();
1002
1003
0
    Zone* zone() const { return zone_; }
1004
1005
  private:
1006
    static DebugEnvironments* ensureRealmData(JSContext* cx);
1007
1008
    template <typename Environment, typename Scope>
1009
    static void onPopGeneric(JSContext* cx, const EnvironmentIter& ei);
1010
1011
  public:
1012
    void trace(JSTracer* trc);
1013
    void sweep();
1014
    void finish();
1015
#ifdef JS_GC_ZEAL
1016
    void checkHashTablesAfterMovingGC();
1017
#endif
1018
1019
    // If a live frame has a synthesized entry in missingEnvs, make sure it's not
1020
    // collected.
1021
    void traceLiveFrame(JSTracer* trc, AbstractFramePtr frame);
1022
1023
    static DebugEnvironmentProxy* hasDebugEnvironment(JSContext* cx, EnvironmentObject& env);
1024
    static bool addDebugEnvironment(JSContext* cx, Handle<EnvironmentObject*> env,
1025
                                    Handle<DebugEnvironmentProxy*> debugEnv);
1026
1027
    static DebugEnvironmentProxy* hasDebugEnvironment(JSContext* cx, const EnvironmentIter& ei);
1028
    static bool addDebugEnvironment(JSContext* cx, const EnvironmentIter& ei,
1029
                                    Handle<DebugEnvironmentProxy*> debugEnv);
1030
1031
    static bool updateLiveEnvironments(JSContext* cx);
1032
    static LiveEnvironmentVal* hasLiveEnvironment(EnvironmentObject& env);
1033
    static void unsetPrevUpToDateUntil(JSContext* cx, AbstractFramePtr frame);
1034
1035
    // When a frame bails out from Ion to Baseline, there might be missing
1036
    // envs keyed on, and live envs containing, the old
1037
    // RematerializedFrame. Forward those values to the new BaselineFrame.
1038
    static void forwardLiveFrame(JSContext* cx, AbstractFramePtr from, AbstractFramePtr to);
1039
1040
    // When an environment is popped, we store a snapshot of its bindings that
1041
    // live on the frame.
1042
    //
1043
    // This is done during frame unwinding, which cannot handle errors
1044
    // gracefully. Errors result in no snapshot being set on the
1045
    // DebugEnvironmentProxy.
1046
    static void takeFrameSnapshot(JSContext* cx, Handle<DebugEnvironmentProxy*> debugEnv,
1047
                                  AbstractFramePtr frame);
1048
1049
    // In debug-mode, these must be called whenever exiting a scope that might
1050
    // have stack-allocated locals.
1051
    static void onPopCall(JSContext* cx, AbstractFramePtr frame);
1052
    static void onPopVar(JSContext* cx, const EnvironmentIter& ei);
1053
    static void onPopVar(JSContext* cx, AbstractFramePtr frame, jsbytecode* pc);
1054
    static void onPopLexical(JSContext* cx, const EnvironmentIter& ei);
1055
    static void onPopLexical(JSContext* cx, AbstractFramePtr frame, jsbytecode* pc);
1056
    static void onPopWith(AbstractFramePtr frame);
1057
    static void onRealmUnsetIsDebuggee(Realm* realm);
1058
};
1059
1060
}  /* namespace js */
1061
1062
template <>
1063
inline bool
1064
JSObject::is<js::EnvironmentObject>() const
1065
9.74M
{
1066
9.74M
    return is<js::CallObject>() ||
1067
9.74M
           is<js::VarEnvironmentObject>() ||
1068
9.74M
           is<js::ModuleEnvironmentObject>() ||
1069
9.74M
           is<js::WasmInstanceEnvironmentObject>() ||
1070
9.74M
           is<js::WasmFunctionCallObject>() ||
1071
9.74M
           is<js::LexicalEnvironmentObject>() ||
1072
9.74M
           is<js::WithEnvironmentObject>() ||
1073
9.74M
           is<js::NonSyntacticVariablesObject>() ||
1074
9.74M
           is<js::RuntimeLexicalErrorObject>();
1075
9.74M
}
1076
1077
template<>
1078
bool
1079
JSObject::is<js::DebugEnvironmentProxy>() const;
1080
1081
namespace js {
1082
1083
inline bool
1084
IsSyntacticEnvironment(JSObject* env)
1085
142
{
1086
142
    if (!env->is<EnvironmentObject>()) {
1087
0
        return false;
1088
0
    }
1089
142
1090
142
    if (env->is<WithEnvironmentObject>()) {
1091
0
        return env->as<WithEnvironmentObject>().isSyntactic();
1092
0
    }
1093
142
1094
142
    if (env->is<LexicalEnvironmentObject>()) {
1095
97
        return env->as<LexicalEnvironmentObject>().isSyntactic();
1096
97
    }
1097
45
1098
45
    if (env->is<NonSyntacticVariablesObject>()) {
1099
0
        return false;
1100
0
    }
1101
45
1102
45
    return true;
1103
45
}
1104
1105
inline bool
1106
IsExtensibleLexicalEnvironment(JSObject* env)
1107
21
{
1108
21
    return env->is<LexicalEnvironmentObject>() &&
1109
21
           env->as<LexicalEnvironmentObject>().isExtensible();
1110
21
}
1111
1112
inline bool
1113
IsGlobalLexicalEnvironment(JSObject* env)
1114
3
{
1115
3
    return env->is<LexicalEnvironmentObject>() &&
1116
3
           env->as<LexicalEnvironmentObject>().isGlobal();
1117
3
}
1118
1119
inline bool
1120
IsNSVOLexicalEnvironment(JSObject* env)
1121
0
{
1122
0
    return env->is<LexicalEnvironmentObject>() &&
1123
0
           env->as<LexicalEnvironmentObject>().enclosingEnvironment()
1124
0
                                              .is<NonSyntacticVariablesObject>();
1125
0
}
1126
1127
inline JSObject*
1128
MaybeUnwrapWithEnvironment(JSObject* env)
1129
0
{
1130
0
    if (env->is<WithEnvironmentObject>()) {
1131
0
        return &env->as<WithEnvironmentObject>().object();
1132
0
    }
1133
0
    return env;
1134
0
}
1135
1136
template <typename SpecificEnvironment>
1137
inline bool
1138
IsFrameInitialEnvironment(AbstractFramePtr frame, SpecificEnvironment& env)
1139
142
{
1140
142
    // A frame's initial environment is the innermost environment
1141
142
    // corresponding to the scope chain from frame.script()->bodyScope() to
1142
142
    // frame.script()->outermostScope(). This environment must be on the chain
1143
142
    // for the frame to be considered initialized. That is, it must be on the
1144
142
    // chain for the environment chain to fully match the scope chain at the
1145
142
    // start of execution in the frame.
1146
142
    //
1147
142
    // This logic must be in sync with the HAS_INITIAL_ENV logic in
1148
142
    // InitFromBailout.
1149
142
1150
142
    // A function frame's CallObject, if present, is always the initial
1151
142
    // environment.
1152
142
    if (mozilla::IsSame<SpecificEnvironment, CallObject>::value) {
1153
92
        return true;
1154
92
    }
1155
50
1156
50
    // For an eval frame, the VarEnvironmentObject, if present, is always the
1157
50
    // initial environment.
1158
50
    if (mozilla::IsSame<SpecificEnvironment, VarEnvironmentObject>::value &&
1159
50
        frame.isEvalFrame())
1160
0
    {
1161
0
        return true;
1162
0
    }
1163
50
1164
50
    // For named lambda frames without CallObjects (i.e., no binding in the
1165
50
    // body of the function was closed over), the LexicalEnvironmentObject
1166
50
    // corresponding to the named lambda scope is the initial environment.
1167
50
    if (mozilla::IsSame<SpecificEnvironment, NamedLambdaObject>::value &&
1168
50
        frame.isFunctionFrame() &&
1169
50
        frame.callee()->needsNamedLambdaEnvironment() &&
1170
50
        !frame.callee()->needsCallObject())
1171
0
    {
1172
0
        LexicalScope* namedLambdaScope = frame.script()->maybeNamedLambdaScope();
1173
0
        return &env.template as<LexicalEnvironmentObject>().scope() == namedLambdaScope;
1174
0
    }
1175
50
1176
50
    return false;
1177
50
}
bool js::IsFrameInitialEnvironment<js::LexicalEnvironmentObject>(js::AbstractFramePtr, js::LexicalEnvironmentObject&)
Line
Count
Source
1139
49
{
1140
49
    // A frame's initial environment is the innermost environment
1141
49
    // corresponding to the scope chain from frame.script()->bodyScope() to
1142
49
    // frame.script()->outermostScope(). This environment must be on the chain
1143
49
    // for the frame to be considered initialized. That is, it must be on the
1144
49
    // chain for the environment chain to fully match the scope chain at the
1145
49
    // start of execution in the frame.
1146
49
    //
1147
49
    // This logic must be in sync with the HAS_INITIAL_ENV logic in
1148
49
    // InitFromBailout.
1149
49
1150
49
    // A function frame's CallObject, if present, is always the initial
1151
49
    // environment.
1152
49
    if (mozilla::IsSame<SpecificEnvironment, CallObject>::value) {
1153
0
        return true;
1154
0
    }
1155
49
1156
49
    // For an eval frame, the VarEnvironmentObject, if present, is always the
1157
49
    // initial environment.
1158
49
    if (mozilla::IsSame<SpecificEnvironment, VarEnvironmentObject>::value &&
1159
49
        frame.isEvalFrame())
1160
0
    {
1161
0
        return true;
1162
0
    }
1163
49
1164
49
    // For named lambda frames without CallObjects (i.e., no binding in the
1165
49
    // body of the function was closed over), the LexicalEnvironmentObject
1166
49
    // corresponding to the named lambda scope is the initial environment.
1167
49
    if (mozilla::IsSame<SpecificEnvironment, NamedLambdaObject>::value &&
1168
49
        frame.isFunctionFrame() &&
1169
49
        frame.callee()->needsNamedLambdaEnvironment() &&
1170
49
        !frame.callee()->needsCallObject())
1171
0
    {
1172
0
        LexicalScope* namedLambdaScope = frame.script()->maybeNamedLambdaScope();
1173
0
        return &env.template as<LexicalEnvironmentObject>().scope() == namedLambdaScope;
1174
0
    }
1175
49
1176
49
    return false;
1177
49
}
Unexecuted instantiation: bool js::IsFrameInitialEnvironment<js::NamedLambdaObject>(js::AbstractFramePtr, js::NamedLambdaObject&)
bool js::IsFrameInitialEnvironment<js::CallObject>(js::AbstractFramePtr, js::CallObject&)
Line
Count
Source
1139
92
{
1140
92
    // A frame's initial environment is the innermost environment
1141
92
    // corresponding to the scope chain from frame.script()->bodyScope() to
1142
92
    // frame.script()->outermostScope(). This environment must be on the chain
1143
92
    // for the frame to be considered initialized. That is, it must be on the
1144
92
    // chain for the environment chain to fully match the scope chain at the
1145
92
    // start of execution in the frame.
1146
92
    //
1147
92
    // This logic must be in sync with the HAS_INITIAL_ENV logic in
1148
92
    // InitFromBailout.
1149
92
1150
92
    // A function frame's CallObject, if present, is always the initial
1151
92
    // environment.
1152
92
    if (mozilla::IsSame<SpecificEnvironment, CallObject>::value) {
1153
92
        return true;
1154
92
    }
1155
0
1156
0
    // For an eval frame, the VarEnvironmentObject, if present, is always the
1157
0
    // initial environment.
1158
0
    if (mozilla::IsSame<SpecificEnvironment, VarEnvironmentObject>::value &&
1159
0
        frame.isEvalFrame())
1160
0
    {
1161
0
        return true;
1162
0
    }
1163
0
1164
0
    // For named lambda frames without CallObjects (i.e., no binding in the
1165
0
    // body of the function was closed over), the LexicalEnvironmentObject
1166
0
    // corresponding to the named lambda scope is the initial environment.
1167
0
    if (mozilla::IsSame<SpecificEnvironment, NamedLambdaObject>::value &&
1168
0
        frame.isFunctionFrame() &&
1169
0
        frame.callee()->needsNamedLambdaEnvironment() &&
1170
0
        !frame.callee()->needsCallObject())
1171
0
    {
1172
0
        LexicalScope* namedLambdaScope = frame.script()->maybeNamedLambdaScope();
1173
0
        return &env.template as<LexicalEnvironmentObject>().scope() == namedLambdaScope;
1174
0
    }
1175
0
1176
0
    return false;
1177
0
}
bool js::IsFrameInitialEnvironment<js::VarEnvironmentObject>(js::AbstractFramePtr, js::VarEnvironmentObject&)
Line
Count
Source
1139
1
{
1140
1
    // A frame's initial environment is the innermost environment
1141
1
    // corresponding to the scope chain from frame.script()->bodyScope() to
1142
1
    // frame.script()->outermostScope(). This environment must be on the chain
1143
1
    // for the frame to be considered initialized. That is, it must be on the
1144
1
    // chain for the environment chain to fully match the scope chain at the
1145
1
    // start of execution in the frame.
1146
1
    //
1147
1
    // This logic must be in sync with the HAS_INITIAL_ENV logic in
1148
1
    // InitFromBailout.
1149
1
1150
1
    // A function frame's CallObject, if present, is always the initial
1151
1
    // environment.
1152
1
    if (mozilla::IsSame<SpecificEnvironment, CallObject>::value) {
1153
0
        return true;
1154
0
    }
1155
1
1156
1
    // For an eval frame, the VarEnvironmentObject, if present, is always the
1157
1
    // initial environment.
1158
1
    if (mozilla::IsSame<SpecificEnvironment, VarEnvironmentObject>::value &&
1159
1
        frame.isEvalFrame())
1160
0
    {
1161
0
        return true;
1162
0
    }
1163
1
1164
1
    // For named lambda frames without CallObjects (i.e., no binding in the
1165
1
    // body of the function was closed over), the LexicalEnvironmentObject
1166
1
    // corresponding to the named lambda scope is the initial environment.
1167
1
    if (mozilla::IsSame<SpecificEnvironment, NamedLambdaObject>::value &&
1168
1
        frame.isFunctionFrame() &&
1169
1
        frame.callee()->needsNamedLambdaEnvironment() &&
1170
1
        !frame.callee()->needsCallObject())
1171
0
    {
1172
0
        LexicalScope* namedLambdaScope = frame.script()->maybeNamedLambdaScope();
1173
0
        return &env.template as<LexicalEnvironmentObject>().scope() == namedLambdaScope;
1174
0
    }
1175
1
1176
1
    return false;
1177
1
}
Unexecuted instantiation: bool js::IsFrameInitialEnvironment<js::WithEnvironmentObject>(js::AbstractFramePtr, js::WithEnvironmentObject&)
1178
1179
extern bool
1180
CreateObjectsForEnvironmentChain(JSContext* cx, AutoObjectVector& chain,
1181
                                 HandleObject terminatingEnv,
1182
                                 MutableHandleObject envObj);
1183
1184
ModuleObject* GetModuleObjectForScript(JSScript* script);
1185
1186
ModuleEnvironmentObject* GetModuleEnvironmentForScript(JSScript* script);
1187
1188
MOZ_MUST_USE bool
1189
GetThisValueForDebuggerMaybeOptimizedOut(JSContext* cx, AbstractFramePtr frame,
1190
                                         jsbytecode* pc, MutableHandleValue res);
1191
1192
MOZ_MUST_USE bool
1193
CheckVarNameConflict(JSContext* cx, Handle<LexicalEnvironmentObject*> lexicalEnv,
1194
                     HandlePropertyName name);
1195
1196
MOZ_MUST_USE bool
1197
CheckCanDeclareGlobalBinding(JSContext* cx, Handle<GlobalObject*> global,
1198
                             HandlePropertyName name, bool isFunction);
1199
1200
MOZ_MUST_USE bool
1201
CheckLexicalNameConflict(JSContext* cx, Handle<LexicalEnvironmentObject*> lexicalEnv,
1202
                         HandleObject varObj, HandlePropertyName name);
1203
1204
MOZ_MUST_USE bool
1205
CheckGlobalDeclarationConflicts(JSContext* cx, HandleScript script,
1206
                                Handle<LexicalEnvironmentObject*> lexicalEnv,
1207
                                HandleObject varObj);
1208
1209
MOZ_MUST_USE bool
1210
CheckEvalDeclarationConflicts(JSContext* cx, HandleScript script, HandleObject envChain,
1211
                              HandleObject varObj);
1212
1213
MOZ_MUST_USE bool
1214
InitFunctionEnvironmentObjects(JSContext* cx, AbstractFramePtr frame);
1215
1216
MOZ_MUST_USE bool
1217
PushVarEnvironmentObject(JSContext* cx, HandleScope scope, AbstractFramePtr frame);
1218
1219
MOZ_MUST_USE bool
1220
GetFrameEnvironmentAndScope(JSContext* cx, AbstractFramePtr frame, jsbytecode* pc,
1221
                            MutableHandleObject env, MutableHandleScope scope);
1222
1223
#ifdef DEBUG
1224
bool
1225
AnalyzeEntrainedVariables(JSContext* cx, HandleScript script);
1226
#endif
1227
1228
} // namespace js
1229
1230
#endif /* vm_EnvironmentObject_h */