LCOV - code coverage report
Current view: top level - js/src/vm - GlobalObject.h (source / functions) Hit Total Coverage
Test: output.info Lines: 173 279 62.0 %
Date: 2017-07-14 16:53:18 Functions: 60 85 70.6 %
Legend: Lines: hit not hit

          Line data    Source code
       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_GlobalObject_h
       8             : #define vm_GlobalObject_h
       9             : 
      10             : #include "jsarray.h"
      11             : #include "jsbool.h"
      12             : #include "jsexn.h"
      13             : #include "jsfun.h"
      14             : #include "jsnum.h"
      15             : 
      16             : #include "js/Vector.h"
      17             : #include "vm/ArrayBufferObject.h"
      18             : #include "vm/ErrorObject.h"
      19             : #include "vm/RegExpStatics.h"
      20             : #include "vm/Runtime.h"
      21             : 
      22             : namespace js {
      23             : 
      24             : class Debugger;
      25             : class TypedObjectModuleObject;
      26             : class LexicalEnvironmentObject;
      27             : 
      28             : class SimdTypeDescr;
      29             : enum class SimdType;
      30             : 
      31             : /*
      32             :  * Global object slots are reserved as follows:
      33             :  *
      34             :  * [0, APPLICATION_SLOTS)
      35             :  *   Pre-reserved slots in all global objects set aside for the embedding's
      36             :  *   use. As with all reserved slots these start out as UndefinedValue() and
      37             :  *   are traced for GC purposes. Apart from that the engine never touches
      38             :  *   these slots, so the embedding can do whatever it wants with them.
      39             :  * [APPLICATION_SLOTS, APPLICATION_SLOTS + JSProto_LIMIT)
      40             :  *   Stores the original value of the constructor for the corresponding
      41             :  *   JSProtoKey.
      42             :  * [APPLICATION_SLOTS + JSProto_LIMIT, APPLICATION_SLOTS + 2 * JSProto_LIMIT)
      43             :  *   Stores the prototype, if any, for the constructor for the corresponding
      44             :  *   JSProtoKey offset from JSProto_LIMIT.
      45             :  * [APPLICATION_SLOTS + 2 * JSProto_LIMIT, RESERVED_SLOTS)
      46             :  *   Various one-off values: ES5 13.2.3's [[ThrowTypeError]], RegExp statics,
      47             :  *   the original eval for this global object (implementing |var eval =
      48             :  *   otherWindow.eval; eval(...)| as an indirect eval), a bit indicating
      49             :  *   whether this object has been cleared (see JS_ClearScope), and a cache for
      50             :  *   whether eval is allowed (per the global's Content Security Policy).
      51             :  *
      52             :  * The two JSProto_LIMIT-sized ranges are necessary to implement
      53             :  * js::FindClassObject, and spec language speaking in terms of "the original
      54             :  * Array prototype object", or "as if by the expression new Array()" referring
      55             :  * to the original Array constructor. The actual (writable and even deletable)
      56             :  * Object, Array, &c. properties are not stored in reserved slots.
      57             :  */
      58             : class GlobalObject : public NativeObject
      59             : {
      60             :     /* Count of slots set aside for application use. */
      61             :     static const unsigned APPLICATION_SLOTS = JSCLASS_GLOBAL_APPLICATION_SLOTS;
      62             : 
      63             :     /*
      64             :      * Count of slots to store built-in prototypes and initial visible
      65             :      * properties for the constructors.
      66             :      */
      67             :     static const unsigned STANDARD_CLASS_SLOTS = JSProto_LIMIT * 2;
      68             : 
      69             :     enum : unsigned {
      70             :         /* Various function values needed by the engine. */
      71             :         EVAL = APPLICATION_SLOTS + STANDARD_CLASS_SLOTS,
      72             :         THROWTYPEERROR,
      73             : 
      74             :         /* One-off properties stored after slots for built-ins. */
      75             :         LEXICAL_ENVIRONMENT,
      76             :         EMPTY_GLOBAL_SCOPE,
      77             :         ITERATOR_PROTO,
      78             :         ARRAY_ITERATOR_PROTO,
      79             :         STRING_ITERATOR_PROTO,
      80             :         LEGACY_GENERATOR_OBJECT_PROTO,
      81             :         STAR_GENERATOR_OBJECT_PROTO,
      82             :         STAR_GENERATOR_FUNCTION_PROTO,
      83             :         STAR_GENERATOR_FUNCTION,
      84             :         ASYNC_FUNCTION_PROTO,
      85             :         ASYNC_FUNCTION,
      86             :         ASYNC_ITERATOR_PROTO,
      87             :         ASYNC_FROM_SYNC_ITERATOR_PROTO,
      88             :         ASYNC_GENERATOR,
      89             :         ASYNC_GENERATOR_FUNCTION,
      90             :         ASYNC_GENERATOR_PROTO,
      91             :         MAP_ITERATOR_PROTO,
      92             :         SET_ITERATOR_PROTO,
      93             :         COLLATOR_PROTO,
      94             :         NUMBER_FORMAT,
      95             :         NUMBER_FORMAT_PROTO,
      96             :         DATE_TIME_FORMAT,
      97             :         DATE_TIME_FORMAT_PROTO,
      98             :         PLURAL_RULES_PROTO,
      99             :         MODULE_PROTO,
     100             :         IMPORT_ENTRY_PROTO,
     101             :         EXPORT_ENTRY_PROTO,
     102             :         REGEXP_STATICS,
     103             :         WARNED_ONCE_FLAGS,
     104             :         RUNTIME_CODEGEN_ENABLED,
     105             :         DEBUGGERS,
     106             :         INTRINSICS,
     107             :         FOR_OF_PIC_CHAIN,
     108             :         MODULE_RESOLVE_HOOK,
     109             :         WINDOW_PROXY,
     110             : 
     111             :         /* Total reserved-slot count for global objects. */
     112             :         RESERVED_SLOTS
     113             :     };
     114             : 
     115             :     /*
     116             :      * The slot count must be in the public API for JSCLASS_GLOBAL_FLAGS, and
     117             :      * we won't expose GlobalObject, so just assert that the two values are
     118             :      * synchronized.
     119             :      */
     120             :     static_assert(JSCLASS_GLOBAL_SLOT_COUNT == RESERVED_SLOTS,
     121             :                   "global object slot counts are inconsistent");
     122             : 
     123             :     enum WarnOnceFlag : int32_t {
     124             :         WARN_WATCH_DEPRECATED                   = 1 << 0,
     125             :     };
     126             : 
     127             :     // Emit the specified warning if the given slot in |obj|'s global isn't
     128             :     // true, then set the slot to true.  Thus calling this method warns once
     129             :     // for each global object it's called on, and every other call does
     130             :     // nothing.
     131             :     static bool
     132             :     warnOnceAbout(JSContext* cx, HandleObject obj, WarnOnceFlag flag, unsigned errorNumber);
     133             : 
     134             : 
     135             :   public:
     136             :     LexicalEnvironmentObject& lexicalEnvironment() const;
     137             :     GlobalScope& emptyGlobalScope() const;
     138             : 
     139         311 :     void setThrowTypeError(JSFunction* fun) {
     140         311 :         MOZ_ASSERT(getSlotRef(THROWTYPEERROR).isUndefined());
     141         311 :         setSlot(THROWTYPEERROR, ObjectValue(*fun));
     142         311 :     }
     143             : 
     144         311 :     void setOriginalEval(JSObject* evalobj) {
     145         311 :         MOZ_ASSERT(getSlotRef(EVAL).isUndefined());
     146         311 :         setSlot(EVAL, ObjectValue(*evalobj));
     147         311 :     }
     148             : 
     149      414844 :     Value getConstructor(JSProtoKey key) const {
     150      414844 :         MOZ_ASSERT(key <= JSProto_LIMIT);
     151      414844 :         return getSlot(APPLICATION_SLOTS + key);
     152             :     }
     153             :     static bool skipDeselectedConstructor(JSContext* cx, JSProtoKey key);
     154             :     static bool ensureConstructor(JSContext* cx, Handle<GlobalObject*> global, JSProtoKey key);
     155             :     static bool resolveConstructor(JSContext* cx, Handle<GlobalObject*> global, JSProtoKey key);
     156             :     static bool initBuiltinConstructor(JSContext* cx, Handle<GlobalObject*> global,
     157             :                                        JSProtoKey key, HandleObject ctor, HandleObject proto);
     158             : 
     159        1702 :     void setConstructor(JSProtoKey key, const Value& v) {
     160        1702 :         MOZ_ASSERT(key <= JSProto_LIMIT);
     161        1702 :         setSlot(APPLICATION_SLOTS + key, v);
     162        1702 :     }
     163             : 
     164      226273 :     Value getPrototype(JSProtoKey key) const {
     165      226273 :         MOZ_ASSERT(key <= JSProto_LIMIT);
     166      226273 :         return getSlot(APPLICATION_SLOTS + JSProto_LIMIT + key);
     167             :     }
     168             : 
     169        1932 :     void setPrototype(JSProtoKey key, const Value& value) {
     170        1932 :         MOZ_ASSERT(key <= JSProto_LIMIT);
     171        1932 :         setSlot(APPLICATION_SLOTS + JSProto_LIMIT + key, value);
     172        1932 :     }
     173             : 
     174       47547 :     bool classIsInitialized(JSProtoKey key) const {
     175       47547 :         bool inited = !getConstructor(key).isUndefined();
     176       47547 :         MOZ_ASSERT(inited == !getPrototype(key).isUndefined());
     177       47547 :         return inited;
     178             :     }
     179             : 
     180       23768 :     bool functionObjectClassesInitialized() const {
     181       23768 :         bool inited = classIsInitialized(JSProto_Function);
     182       23768 :         MOZ_ASSERT(inited == classIsInitialized(JSProto_Object));
     183       23768 :         return inited;
     184             :     }
     185             : 
     186             :     /*
     187             :      * Lazy standard classes need a way to indicate they have been initialized.
     188             :      * Otherwise, when we delete them, we might accidentally recreate them via
     189             :      * a lazy initialization. We use the presence of an object in the
     190             :      * getConstructor(key) reserved slot to indicate that they've been
     191             :      * initialized.
     192             :      *
     193             :      * Note: A few builtin objects, like JSON and Math, are not constructors,
     194             :      * so getConstructor is a bit of a misnomer.
     195             :      */
     196      123468 :     bool isStandardClassResolved(JSProtoKey key) const {
     197             :         // If the constructor is undefined, then it hasn't been initialized.
     198      123468 :         MOZ_ASSERT(getConstructor(key).isUndefined() ||
     199             :                    getConstructor(key).isObject());
     200      123467 :         return !getConstructor(key).isUndefined();
     201             :     }
     202             : 
     203             :     /*
     204             :      * Using a Handle<GlobalObject*> as a Handle<Object*> is always safe as
     205             :      * GlobalObject derives JSObject. However, with C++'s semantics, Handle<T>
     206             :      * is not related to Handle<S>, independent of how S and T are related.
     207             :      * Further, Handle stores an indirect pointer and, again because of C++'s
     208             :      * semantics, T** is not related to S**, independent of how S and T are
     209             :      * related. Since we know that this specific case is safe, we provide a
     210             :      * manual upcast operation here to do the reinterpret_cast in a known-safe
     211             :      * manner.
     212             :      */
     213             :     static HandleObject upcast(Handle<GlobalObject*> global) {
     214             :         return HandleObject::fromMarkedLocation(
     215             :                 reinterpret_cast<JSObject * const*>(global.address()));
     216             :     }
     217             : 
     218             :   private:
     219          11 :     bool arrayClassInitialized() const {
     220          11 :         return classIsInitialized(JSProto_Array);
     221             :     }
     222             : 
     223             :     bool booleanClassInitialized() const {
     224             :         return classIsInitialized(JSProto_Boolean);
     225             :     }
     226             :     bool numberClassInitialized() const {
     227             :         return classIsInitialized(JSProto_Number);
     228             :     }
     229             :     bool stringClassInitialized() const {
     230             :         return classIsInitialized(JSProto_String);
     231             :     }
     232             :     bool regexpClassInitialized() const {
     233             :         return classIsInitialized(JSProto_RegExp);
     234             :     }
     235             :     bool arrayBufferClassInitialized() const {
     236             :         return classIsInitialized(JSProto_ArrayBuffer);
     237             :     }
     238             :     bool sharedArrayBufferClassInitialized() const {
     239             :         return classIsInitialized(JSProto_SharedArrayBuffer);
     240             :     }
     241             :     bool errorClassesInitialized() const {
     242             :         return classIsInitialized(JSProto_Error);
     243             :     }
     244             :     bool dataViewClassInitialized() const {
     245             :         return classIsInitialized(JSProto_DataView);
     246             :     }
     247             : 
     248             :     // Disallow use of unqualified JSObject::create in GlobalObject.
     249             :     static GlobalObject* create(...) = delete;
     250             : 
     251             :     friend struct ::JSRuntime;
     252             :     static GlobalObject* createInternal(JSContext* cx, const Class* clasp);
     253             : 
     254             :   public:
     255             :     static GlobalObject*
     256             :     new_(JSContext* cx, const Class* clasp, JSPrincipals* principals,
     257             :          JS::OnNewGlobalHookOption hookOption, const JS::CompartmentOptions& options);
     258             : 
     259             :     /*
     260             :      * Create a constructor function with the specified name and length using
     261             :      * ctor, a method which creates objects with the given class.
     262             :      */
     263             :     static JSFunction*
     264             :     createConstructor(JSContext* cx,  JSNative ctor, JSAtom* name, unsigned length,
     265             :                       gc::AllocKind kind = gc::AllocKind::FUNCTION,
     266             :                       const JSJitInfo* jitInfo = nullptr);
     267             : 
     268             :     /*
     269             :      * Create an object to serve as [[Prototype]] for instances of the given
     270             :      * class, using |Object.prototype| as its [[Prototype]].  Users creating
     271             :      * prototype objects with particular internal structure (e.g. reserved
     272             :      * slots guaranteed to contain values of particular types) must immediately
     273             :      * complete the minimal initialization to make the returned object safe to
     274             :      * touch.
     275             :      */
     276             :     static NativeObject*
     277             :     createBlankPrototype(JSContext* cx, Handle<GlobalObject*> global, const js::Class* clasp);
     278             : 
     279             :     /*
     280             :      * Identical to createBlankPrototype, but uses proto as the [[Prototype]]
     281             :      * of the returned blank prototype.
     282             :      */
     283             :     static NativeObject*
     284             :     createBlankPrototypeInheriting(JSContext* cx, Handle<GlobalObject*> global,
     285             :                                    const js::Class* clasp, HandleObject proto);
     286             : 
     287             :     template <typename T>
     288             :     static T*
     289         185 :     createBlankPrototype(JSContext* cx, Handle<GlobalObject*> global) {
     290         185 :         NativeObject* res = createBlankPrototype(cx, global, &T::class_);
     291         185 :         return res ? &res->template as<T>() : nullptr;
     292             :     }
     293             : 
     294             :     static NativeObject*
     295       23293 :     getOrCreateObjectPrototype(JSContext* cx, Handle<GlobalObject*> global) {
     296       23293 :         if (global->functionObjectClassesInitialized())
     297       23004 :             return &global->getPrototype(JSProto_Object).toObject().as<NativeObject>();
     298         289 :         if (!ensureConstructor(cx, global, JSProto_Object))
     299           0 :             return nullptr;
     300         288 :         return &global->getPrototype(JSProto_Object).toObject().as<NativeObject>();
     301             :     }
     302             : 
     303             :     static NativeObject*
     304         475 :     getOrCreateFunctionPrototype(JSContext* cx, Handle<GlobalObject*> global) {
     305         475 :         if (global->functionObjectClassesInitialized())
     306         475 :             return &global->getPrototype(JSProto_Function).toObject().as<NativeObject>();
     307           0 :         if (!ensureConstructor(cx, global, JSProto_Object))
     308           0 :             return nullptr;
     309           0 :         return &global->getPrototype(JSProto_Function).toObject().as<NativeObject>();
     310             :     }
     311             : 
     312             :     static NativeObject*
     313         176 :     getOrCreateArrayPrototype(JSContext* cx, Handle<GlobalObject*> global) {
     314         176 :         if (!ensureConstructor(cx, global, JSProto_Array))
     315           0 :             return nullptr;
     316         176 :         return &global->getPrototype(JSProto_Array).toObject().as<NativeObject>();
     317             :     }
     318             : 
     319          11 :     NativeObject* maybeGetArrayPrototype() {
     320          11 :         if (arrayClassInitialized())
     321          11 :             return &getPrototype(JSProto_Array).toObject().as<NativeObject>();
     322           0 :         return nullptr;
     323             :     }
     324             : 
     325             :     static NativeObject*
     326           0 :     getOrCreateBooleanPrototype(JSContext* cx, Handle<GlobalObject*> global) {
     327           0 :         if (!ensureConstructor(cx, global, JSProto_Boolean))
     328           0 :             return nullptr;
     329           0 :         return &global->getPrototype(JSProto_Boolean).toObject().as<NativeObject>();
     330             :     }
     331             : 
     332             :     static NativeObject*
     333          15 :     getOrCreateNumberPrototype(JSContext* cx, Handle<GlobalObject*> global) {
     334          15 :         if (!ensureConstructor(cx, global, JSProto_Number))
     335           0 :             return nullptr;
     336          15 :         return &global->getPrototype(JSProto_Number).toObject().as<NativeObject>();
     337             :     }
     338             : 
     339             :     static NativeObject*
     340         465 :     getOrCreateStringPrototype(JSContext* cx, Handle<GlobalObject*> global) {
     341         465 :         if (!ensureConstructor(cx, global, JSProto_String))
     342           0 :             return nullptr;
     343         465 :         return &global->getPrototype(JSProto_String).toObject().as<NativeObject>();
     344             :     }
     345             : 
     346             :     static NativeObject*
     347           0 :     getOrCreateSymbolPrototype(JSContext* cx, Handle<GlobalObject*> global) {
     348           0 :         if (!ensureConstructor(cx, global, JSProto_Symbol))
     349           0 :             return nullptr;
     350           0 :         return &global->getPrototype(JSProto_Symbol).toObject().as<NativeObject>();
     351             :     }
     352             : 
     353             :     static NativeObject*
     354           0 :     getOrCreatePromisePrototype(JSContext* cx, Handle<GlobalObject*> global) {
     355           0 :         if (!ensureConstructor(cx, global, JSProto_Promise))
     356           0 :             return nullptr;
     357           0 :         return &global->getPrototype(JSProto_Promise).toObject().as<NativeObject>();
     358             :     }
     359             : 
     360             :     static NativeObject*
     361             :     getOrCreateRegExpPrototype(JSContext* cx, Handle<GlobalObject*> global) {
     362             :         if (!ensureConstructor(cx, global, JSProto_RegExp))
     363             :             return nullptr;
     364             :         return &global->getPrototype(JSProto_RegExp).toObject().as<NativeObject>();
     365             :     }
     366             : 
     367             :     JSObject* maybeGetRegExpPrototype() {
     368             :         if (regexpClassInitialized())
     369             :             return &getPrototype(JSProto_RegExp).toObject();
     370             :         return nullptr;
     371             :     }
     372             : 
     373             :     static NativeObject*
     374        2016 :     getOrCreateSavedFramePrototype(JSContext* cx, Handle<GlobalObject*> global) {
     375        2016 :         if (!ensureConstructor(cx, global, JSProto_SavedFrame))
     376           0 :             return nullptr;
     377        2016 :         return &global->getPrototype(JSProto_SavedFrame).toObject().as<NativeObject>();
     378             :     }
     379             : 
     380             :     static JSObject*
     381           0 :     getOrCreateArrayBufferPrototype(JSContext* cx, Handle<GlobalObject*> global) {
     382           0 :         if (!ensureConstructor(cx, global, JSProto_ArrayBuffer))
     383           0 :             return nullptr;
     384           0 :         return &global->getPrototype(JSProto_ArrayBuffer).toObject();
     385             :     }
     386             : 
     387             :     static JSObject*
     388             :     getOrCreateSharedArrayBufferPrototype(JSContext* cx, Handle<GlobalObject*> global) {
     389             :         if (!ensureConstructor(cx, global, JSProto_SharedArrayBuffer))
     390             :             return nullptr;
     391             :         return &global->getPrototype(JSProto_SharedArrayBuffer).toObject();
     392             :     }
     393             : 
     394             :     static JSObject*
     395          90 :     getOrCreateCustomErrorPrototype(JSContext* cx, Handle<GlobalObject*> global,
     396             :                                     JSExnType exnType)
     397             :     {
     398          90 :         JSProtoKey key = GetExceptionProtoKey(exnType);
     399          90 :         if (!ensureConstructor(cx, global, key))
     400           0 :             return nullptr;
     401          90 :         return &global->getPrototype(key).toObject();
     402             :     }
     403             : 
     404             :     static JSFunction*
     405          68 :     getOrCreateErrorConstructor(JSContext* cx, Handle<GlobalObject*> global) {
     406          68 :         if (!ensureConstructor(cx, global, JSProto_Error))
     407           0 :             return nullptr;
     408          68 :         return &global->getConstructor(JSProto_Error).toObject().as<JSFunction>();
     409             :     }
     410             : 
     411             :     static JSObject*
     412          68 :     getOrCreateErrorPrototype(JSContext* cx, Handle<GlobalObject*> global) {
     413          68 :         return getOrCreateCustomErrorPrototype(cx, global, JSEXN_ERR);
     414             :     }
     415             : 
     416             :     static NativeObject*
     417          52 :     getOrCreateSetPrototype(JSContext* cx, Handle<GlobalObject*> global) {
     418          52 :         if (!ensureConstructor(cx, global, JSProto_Set))
     419           0 :             return nullptr;
     420          52 :         return &global->getPrototype(JSProto_Set).toObject().as<NativeObject>();
     421             :     }
     422             : 
     423             :     static NativeObject*
     424           0 :     getOrCreateWeakSetPrototype(JSContext* cx, Handle<GlobalObject*> global) {
     425           0 :         if (!ensureConstructor(cx, global, JSProto_WeakSet))
     426           0 :             return nullptr;
     427           0 :         return &global->getPrototype(JSProto_WeakSet).toObject().as<NativeObject>();
     428             :     }
     429             : 
     430             :     static JSObject*
     431             :     getOrCreateIntlObject(JSContext* cx, Handle<GlobalObject*> global) {
     432             :         return getOrCreateObject(cx, global, APPLICATION_SLOTS + JSProto_Intl, initIntlObject);
     433             :     }
     434             : 
     435             :     static JSObject*
     436          12 :     getOrCreateTypedObjectModule(JSContext* cx, Handle<GlobalObject*> global) {
     437             :         return getOrCreateObject(cx, global, APPLICATION_SLOTS + JSProto_TypedObject,
     438          12 :                                  initTypedObjectModule);
     439             :     }
     440             : 
     441             :     static JSObject*
     442           6 :     getOrCreateSimdGlobalObject(JSContext* cx, Handle<GlobalObject*> global) {
     443           6 :         return getOrCreateObject(cx, global, APPLICATION_SLOTS + JSProto_SIMD, initSimdObject);
     444             :     }
     445             : 
     446             :     // Get the type descriptor for one of the SIMD types.
     447             :     // simdType is one of the JS_SIMDTYPEREPR_* constants.
     448             :     // Implemented in builtin/SIMD.cpp.
     449             :     static SimdTypeDescr*
     450             :     getOrCreateSimdTypeDescr(JSContext* cx, Handle<GlobalObject*> global, SimdType simdType);
     451             : 
     452             :     TypedObjectModuleObject& getTypedObjectModule() const;
     453             : 
     454             :     JSObject* getLegacyIteratorPrototype() {
     455             :         return &getPrototype(JSProto_Iterator).toObject();
     456             :     }
     457             : 
     458             :     static JSObject*
     459           0 :     getOrCreateCollatorPrototype(JSContext* cx, Handle<GlobalObject*> global) {
     460           0 :         return getOrCreateObject(cx, global, COLLATOR_PROTO, initIntlObject);
     461             :     }
     462             : 
     463             :     static JSFunction*
     464           0 :     getOrCreateNumberFormatConstructor(JSContext* cx, Handle<GlobalObject*> global) {
     465           0 :         JSObject* obj = getOrCreateObject(cx, global, NUMBER_FORMAT, initIntlObject);
     466           0 :         return obj ? &obj->as<JSFunction>() : nullptr;
     467             :     }
     468             : 
     469             :     static JSObject*
     470           0 :     getOrCreateNumberFormatPrototype(JSContext* cx, Handle<GlobalObject*> global) {
     471           0 :         return getOrCreateObject(cx, global, NUMBER_FORMAT_PROTO, initIntlObject);
     472             :     }
     473             : 
     474             :     static JSFunction*
     475           0 :     getOrCreateDateTimeFormatConstructor(JSContext* cx, Handle<GlobalObject*> global) {
     476           0 :         JSObject* obj = getOrCreateObject(cx, global, DATE_TIME_FORMAT, initIntlObject);
     477           0 :         return obj ? &obj->as<JSFunction>() : nullptr;
     478             :     }
     479             : 
     480             :     static JSObject*
     481           0 :     getOrCreateDateTimeFormatPrototype(JSContext* cx, Handle<GlobalObject*> global) {
     482           0 :         return getOrCreateObject(cx, global, DATE_TIME_FORMAT_PROTO, initIntlObject);
     483             :     }
     484             : 
     485             :     static JSObject*
     486           0 :     getOrCreatePluralRulesPrototype(JSContext* cx, Handle<GlobalObject*> global) {
     487           0 :         return getOrCreateObject(cx, global, PLURAL_RULES_PROTO, initIntlObject);
     488             :     }
     489             : 
     490             :     static bool ensureModulePrototypesCreated(JSContext *cx, Handle<GlobalObject*> global);
     491             : 
     492          15 :     JSObject* maybeGetModulePrototype() {
     493          15 :         Value value = getSlot(MODULE_PROTO);
     494          15 :         return value.isUndefined() ? nullptr : &value.toObject();
     495             :     }
     496             : 
     497          15 :     JSObject* maybeGetImportEntryPrototype() {
     498          15 :         Value value = getSlot(IMPORT_ENTRY_PROTO);
     499          15 :         return value.isUndefined() ? nullptr : &value.toObject();
     500             :     }
     501             : 
     502          15 :     JSObject* maybeGetExportEntryPrototype() {
     503          15 :         Value value = getSlot(EXPORT_ENTRY_PROTO);
     504          15 :         return value.isUndefined() ? nullptr : &value.toObject();
     505             :     }
     506             : 
     507           0 :     JSObject* getModulePrototype() {
     508           0 :         JSObject* proto = maybeGetModulePrototype();
     509           0 :         MOZ_ASSERT(proto);
     510           0 :         return proto;
     511             :     }
     512             : 
     513           0 :     JSObject* getImportEntryPrototype() {
     514           0 :         JSObject* proto = maybeGetImportEntryPrototype();
     515           0 :         MOZ_ASSERT(proto);
     516           0 :         return proto;
     517             :     }
     518             : 
     519           0 :     JSObject* getExportEntryPrototype() {
     520           0 :         JSObject* proto = maybeGetExportEntryPrototype();
     521           0 :         MOZ_ASSERT(proto);
     522           0 :         return proto;
     523             :     }
     524             : 
     525             :     static JSFunction*
     526          60 :     getOrCreateTypedArrayConstructor(JSContext* cx, Handle<GlobalObject*> global) {
     527          60 :         if (!ensureConstructor(cx, global, JSProto_TypedArray))
     528           0 :             return nullptr;
     529          60 :         return &global->getConstructor(JSProto_TypedArray).toObject().as<JSFunction>();
     530             :     }
     531             : 
     532             :     static JSObject*
     533          60 :     getOrCreateTypedArrayPrototype(JSContext* cx, Handle<GlobalObject*> global) {
     534          60 :         if (!ensureConstructor(cx, global, JSProto_TypedArray))
     535           0 :             return nullptr;
     536          60 :         return &global->getPrototype(JSProto_TypedArray).toObject();
     537             :     }
     538             : 
     539             :   private:
     540             :     typedef bool (*ObjectInitOp)(JSContext* cx, Handle<GlobalObject*> global);
     541             : 
     542             :     static JSObject*
     543        3870 :     getOrCreateObject(JSContext* cx, Handle<GlobalObject*> global, unsigned slot,
     544             :                       ObjectInitOp init)
     545             :     {
     546        3870 :         Value v = global->getSlotRef(slot);
     547        3870 :         if (v.isObject())
     548        3464 :             return &v.toObject();
     549         406 :         if (!init(cx, global))
     550           0 :             return nullptr;
     551         406 :         return &global->getSlot(slot).toObject();
     552             :     }
     553             : 
     554             :   public:
     555             :     static NativeObject*
     556         203 :     getOrCreateIteratorPrototype(JSContext* cx, Handle<GlobalObject*> global) {
     557         203 :         return MaybeNativeObject(getOrCreateObject(cx, global, ITERATOR_PROTO, initIteratorProto));
     558             :     }
     559             : 
     560             :     static NativeObject*
     561        2133 :     getOrCreateArrayIteratorPrototype(JSContext* cx, Handle<GlobalObject*> global) {
     562        2133 :         return MaybeNativeObject(getOrCreateObject(cx, global, ARRAY_ITERATOR_PROTO,
     563        2133 :                                                    initArrayIteratorProto));
     564             :     }
     565             : 
     566             :     static NativeObject*
     567           0 :     getOrCreateStringIteratorPrototype(JSContext* cx, Handle<GlobalObject*> global) {
     568           0 :         return MaybeNativeObject(getOrCreateObject(cx, global, STRING_ITERATOR_PROTO,
     569           0 :                                                    initStringIteratorProto));
     570             :     }
     571             : 
     572             :     static NativeObject*
     573           0 :     getOrCreateLegacyGeneratorObjectPrototype(JSContext* cx, Handle<GlobalObject*> global) {
     574           0 :         return MaybeNativeObject(getOrCreateObject(cx, global, LEGACY_GENERATOR_OBJECT_PROTO,
     575           0 :                                                    initLegacyGeneratorProto));
     576             :     }
     577             : 
     578             :     static NativeObject*
     579           8 :     getOrCreateStarGeneratorObjectPrototype(JSContext* cx, Handle<GlobalObject*> global)
     580             :     {
     581           8 :         return MaybeNativeObject(getOrCreateObject(cx, global, STAR_GENERATOR_OBJECT_PROTO,
     582           8 :                                                    initStarGenerators));
     583             :     }
     584             : 
     585             :     static NativeObject*
     586         959 :     getOrCreateStarGeneratorFunctionPrototype(JSContext* cx, Handle<GlobalObject*> global) {
     587         959 :         return MaybeNativeObject(getOrCreateObject(cx, global, STAR_GENERATOR_FUNCTION_PROTO,
     588         959 :                                                    initStarGenerators));
     589             :     }
     590             : 
     591             :     static JSObject*
     592             :     getOrCreateStarGeneratorFunction(JSContext* cx, Handle<GlobalObject*> global) {
     593             :         return getOrCreateObject(cx, global, STAR_GENERATOR_FUNCTION, initStarGenerators);
     594             :     }
     595             : 
     596             :     static NativeObject*
     597         260 :     getOrCreateAsyncFunctionPrototype(JSContext* cx, Handle<GlobalObject*> global) {
     598         260 :         return MaybeNativeObject(getOrCreateObject(cx, global, ASYNC_FUNCTION_PROTO,
     599         260 :                                                    initAsyncFunction));
     600             :     }
     601             : 
     602             :     static JSObject*
     603             :     getOrCreateAsyncFunction(JSContext* cx, Handle<GlobalObject*> global) {
     604             :         return getOrCreateObject(cx, global, ASYNC_FUNCTION, initAsyncFunction);
     605             :     }
     606             : 
     607             :     static NativeObject*
     608             :     getOrCreateAsyncIteratorPrototype(JSContext* cx, Handle<GlobalObject*> global)
     609             :     {
     610             :         return MaybeNativeObject(getOrCreateObject(cx, global, ASYNC_ITERATOR_PROTO,
     611             :                                                    initAsyncGenerators));
     612             :     }
     613             : 
     614             :     static NativeObject*
     615           0 :     getOrCreateAsyncFromSyncIteratorPrototype(JSContext* cx, Handle<GlobalObject*> global) {
     616           0 :         return MaybeNativeObject(getOrCreateObject(cx, global, ASYNC_FROM_SYNC_ITERATOR_PROTO,
     617           0 :                                                    initAsyncGenerators));
     618             :     }
     619             : 
     620             :     static NativeObject*
     621           0 :     getOrCreateAsyncGenerator(JSContext* cx, Handle<GlobalObject*> global) {
     622           0 :         return MaybeNativeObject(getOrCreateObject(cx, global, ASYNC_GENERATOR,
     623           0 :                                                    initAsyncGenerators));
     624             :     }
     625             : 
     626             :     static JSObject*
     627             :     getOrCreateAsyncGeneratorFunction(JSContext* cx, Handle<GlobalObject*> global) {
     628             :         return getOrCreateObject(cx, global, ASYNC_GENERATOR_FUNCTION, initAsyncGenerators);
     629             :     }
     630             : 
     631             :     static NativeObject*
     632           0 :     getOrCreateAsyncGeneratorPrototype(JSContext* cx, Handle<GlobalObject*> global) {
     633           0 :         return MaybeNativeObject(getOrCreateObject(cx, global, ASYNC_GENERATOR_PROTO,
     634           0 :                                                    initAsyncGenerators));
     635             :     }
     636             : 
     637             :     static JSObject*
     638         207 :     getOrCreateMapIteratorPrototype(JSContext* cx, Handle<GlobalObject*> global) {
     639         207 :         return getOrCreateObject(cx, global, MAP_ITERATOR_PROTO, initMapIteratorProto);
     640             :     }
     641             : 
     642             :     static JSObject*
     643          82 :     getOrCreateSetIteratorPrototype(JSContext* cx, Handle<GlobalObject*> global) {
     644          82 :         return getOrCreateObject(cx, global, SET_ITERATOR_PROTO, initSetIteratorProto);
     645             :     }
     646             : 
     647             :     static JSObject*
     648           0 :     getOrCreateDataViewPrototype(JSContext* cx, Handle<GlobalObject*> global) {
     649           0 :         if (!ensureConstructor(cx, global, JSProto_DataView))
     650           0 :             return nullptr;
     651           0 :         return &global->getPrototype(JSProto_DataView).toObject();
     652             :     }
     653             : 
     654             :     static JSFunction*
     655           0 :     getOrCreatePromiseConstructor(JSContext* cx, Handle<GlobalObject*> global) {
     656           0 :         if (!ensureConstructor(cx, global, JSProto_Promise))
     657           0 :             return nullptr;
     658           0 :         return &global->getConstructor(JSProto_Promise).toObject().as<JSFunction>();
     659             :     }
     660             : 
     661             :     static NativeObject* getIntrinsicsHolder(JSContext* cx, Handle<GlobalObject*> global);
     662             : 
     663         867 :     bool maybeExistingIntrinsicValue(PropertyName* name, Value* vp) {
     664         867 :         Value slot = getReservedSlot(INTRINSICS);
     665             :         // If we're in the self-hosting compartment itself, the
     666             :         // intrinsics-holder isn't initialized at this point.
     667         867 :         if (slot.isUndefined()) {
     668           0 :             *vp = UndefinedValue();
     669           0 :             return false;
     670             :         }
     671             : 
     672         867 :         NativeObject* holder = &slot.toObject().as<NativeObject>();
     673         867 :         Shape* shape = holder->lookupPure(name);
     674         867 :         if (!shape) {
     675         506 :             *vp = UndefinedValue();
     676         506 :             return false;
     677             :         }
     678             : 
     679         361 :         *vp = holder->getSlot(shape->slot());
     680         361 :         return true;
     681             :     }
     682             : 
     683             :     Value existingIntrinsicValue(PropertyName* name) {
     684             :         Value val;
     685             :         mozilla::DebugOnly<bool> exists = maybeExistingIntrinsicValue(name, &val);
     686             :         MOZ_ASSERT(exists, "intrinsic must already have been added to holder");
     687             : 
     688             :         return val;
     689             :     }
     690             : 
     691             :     static bool
     692       39278 :     maybeGetIntrinsicValue(JSContext* cx, Handle<GlobalObject*> global, Handle<PropertyName*> name,
     693             :                            MutableHandleValue vp, bool* exists)
     694             :     {
     695       39278 :         NativeObject* holder = getIntrinsicsHolder(cx, global);
     696       39278 :         if (!holder)
     697           0 :             return false;
     698             : 
     699       39278 :         if (Shape* shape = holder->lookupPure(name)) {
     700       17155 :             vp.set(holder->getSlot(shape->slot()));
     701       17155 :             *exists = true;
     702             :         } else {
     703       22123 :             *exists = false;
     704             :         }
     705             : 
     706       39278 :         return true;
     707             :     }
     708             : 
     709             :     static bool
     710       18374 :     getIntrinsicValue(JSContext* cx, Handle<GlobalObject*> global,
     711             :                       HandlePropertyName name, MutableHandleValue value)
     712             :     {
     713       18374 :         bool exists = false;
     714       18374 :         if (!GlobalObject::maybeGetIntrinsicValue(cx, global, name, value, &exists))
     715           0 :             return false;
     716       18374 :         if (exists)
     717       16093 :             return true;
     718        2281 :         if (!cx->runtime()->cloneSelfHostedValue(cx, name, value))
     719           0 :             return false;
     720        2281 :         return GlobalObject::addIntrinsicValue(cx, global, name, value);
     721             :     }
     722             : 
     723             :     static bool addIntrinsicValue(JSContext* cx, Handle<GlobalObject*> global,
     724             :                                   HandlePropertyName name, HandleValue value);
     725             : 
     726          87 :     static bool setIntrinsicValue(JSContext* cx, Handle<GlobalObject*> global,
     727             :                                   HandlePropertyName name, HandleValue value)
     728             :     {
     729          87 :         MOZ_ASSERT(cx->runtime()->isSelfHostingGlobal(global));
     730         174 :         RootedObject holder(cx, GlobalObject::getIntrinsicsHolder(cx, global));
     731          87 :         if (!holder)
     732           0 :             return false;
     733          87 :         return SetProperty(cx, holder, name, value);
     734             :     }
     735             : 
     736             :     static bool getSelfHostedFunction(JSContext* cx, Handle<GlobalObject*> global,
     737             :                                       HandlePropertyName selfHostedName, HandleAtom name,
     738             :                                       unsigned nargs, MutableHandleValue funVal);
     739             : 
     740             :     bool hasRegExpStatics() const;
     741             :     static RegExpStatics* getRegExpStatics(JSContext* cx,
     742             :                                            Handle<GlobalObject*> global);
     743             :     RegExpStatics* getAlreadyCreatedRegExpStatics() const;
     744             : 
     745           0 :     JSObject* getThrowTypeError() const {
     746           0 :         const Value v = getReservedSlot(THROWTYPEERROR);
     747           0 :         MOZ_ASSERT(v.isObject(),
     748             :                    "attempting to access [[ThrowTypeError]] too early");
     749           0 :         return &v.toObject();
     750             :     }
     751             : 
     752             :     static bool isRuntimeCodeGenEnabled(JSContext* cx, Handle<GlobalObject*> global);
     753             : 
     754             :     // Warn about use of the deprecated watch/unwatch functions in the global
     755             :     // in which |obj| was created, if no prior warning was given.
     756           0 :     static bool warnOnceAboutWatch(JSContext* cx, HandleObject obj) {
     757             :         // Temporarily disabled until we've provided a watch/unwatch workaround for
     758             :         // debuggers like Firebug (bug 934669).
     759             :         //return warnOnceAbout(cx, obj, WARN_WATCH_DEPRECATED, JSMSG_OBJECT_WATCH_DEPRECATED);
     760           0 :         return true;
     761             :     }
     762             : 
     763             :     static bool getOrCreateEval(JSContext* cx, Handle<GlobalObject*> global,
     764             :                                 MutableHandleObject eval);
     765             : 
     766             :     // Infallibly test whether the given value is the eval function for this global.
     767             :     bool valueIsEval(const Value& val);
     768             : 
     769             :     // Implemented in jsiter.cpp.
     770             :     static bool initIteratorProto(JSContext* cx, Handle<GlobalObject*> global);
     771             :     static bool initArrayIteratorProto(JSContext* cx, Handle<GlobalObject*> global);
     772             :     static bool initStringIteratorProto(JSContext* cx, Handle<GlobalObject*> global);
     773             : 
     774             :     // Implemented in vm/GeneratorObject.cpp.
     775             :     static bool initLegacyGeneratorProto(JSContext* cx, Handle<GlobalObject*> global);
     776             :     static bool initStarGenerators(JSContext* cx, Handle<GlobalObject*> global);
     777             : 
     778             :     static bool initAsyncFunction(JSContext* cx, Handle<GlobalObject*> global);
     779             : 
     780             :     static bool initAsyncGenerators(JSContext* cx, Handle<GlobalObject*> global);
     781             : 
     782             :     // Implemented in builtin/MapObject.cpp.
     783             :     static bool initMapIteratorProto(JSContext* cx, Handle<GlobalObject*> global);
     784             :     static bool initSetIteratorProto(JSContext* cx, Handle<GlobalObject*> global);
     785             : 
     786             :     // Implemented in Intl.cpp.
     787             :     static bool initIntlObject(JSContext* cx, Handle<GlobalObject*> global);
     788             :     static bool addPluralRulesConstructor(JSContext* cx, HandleObject intl);
     789             : 
     790             :     // Implemented in builtin/ModuleObject.cpp
     791             :     static bool initModuleProto(JSContext* cx, Handle<GlobalObject*> global);
     792             :     static bool initImportEntryProto(JSContext* cx, Handle<GlobalObject*> global);
     793             :     static bool initExportEntryProto(JSContext* cx, Handle<GlobalObject*> global);
     794             : 
     795             :     // Implemented in builtin/TypedObject.cpp
     796             :     static bool initTypedObjectModule(JSContext* cx, Handle<GlobalObject*> global);
     797             : 
     798             :     // Implemented in builtin/SIMD.cpp
     799             :     static bool initSimdObject(JSContext* cx, Handle<GlobalObject*> global);
     800             :     static bool initSimdType(JSContext* cx, Handle<GlobalObject*> global, SimdType simdType);
     801             : 
     802             :     static bool initStandardClasses(JSContext* cx, Handle<GlobalObject*> global);
     803             :     static bool initSelfHostingBuiltins(JSContext* cx, Handle<GlobalObject*> global,
     804             :                                         const JSFunctionSpec* builtins);
     805             : 
     806             :     typedef js::Vector<js::ReadBarriered<js::Debugger*>, 0, js::SystemAllocPolicy> DebuggerVector;
     807             : 
     808             :     /*
     809             :      * The collection of Debugger objects debugging this global. If this global
     810             :      * is not a debuggee, this returns either nullptr or an empty vector.
     811             :      */
     812             :     DebuggerVector* getDebuggers() const;
     813             : 
     814             :     /*
     815             :      * The same, but create the empty vector if one does not already
     816             :      * exist. Returns nullptr only on OOM.
     817             :      */
     818             :     static DebuggerVector* getOrCreateDebuggers(JSContext* cx, Handle<GlobalObject*> global);
     819             : 
     820          99 :     inline NativeObject* getForOfPICObject() {
     821          99 :         Value forOfPIC = getReservedSlot(FOR_OF_PIC_CHAIN);
     822          99 :         if (forOfPIC.isUndefined())
     823          54 :             return nullptr;
     824          45 :         return &forOfPIC.toObject().as<NativeObject>();
     825             :     }
     826             :     static NativeObject* getOrCreateForOfPICObject(JSContext* cx, Handle<GlobalObject*> global);
     827             : 
     828             :     JSObject* windowProxy() const {
     829             :         return &getReservedSlot(WINDOW_PROXY).toObject();
     830             :     }
     831        9500 :     JSObject* maybeWindowProxy() const {
     832        9500 :         Value v = getReservedSlot(WINDOW_PROXY);
     833        9500 :         MOZ_ASSERT(v.isObject() || v.isUndefined());
     834        9500 :         return v.isObject() ? &v.toObject() : nullptr;
     835             :     }
     836           7 :     void setWindowProxy(JSObject* windowProxy) {
     837           7 :         setReservedSlot(WINDOW_PROXY, ObjectValue(*windowProxy));
     838           7 :     }
     839             : 
     840           0 :     void setModuleResolveHook(HandleFunction hook) {
     841           0 :         MOZ_ASSERT(hook);
     842           0 :         setSlot(MODULE_RESOLVE_HOOK, ObjectValue(*hook));
     843           0 :     }
     844             : 
     845           0 :     JSFunction* moduleResolveHook() {
     846           0 :         Value value = getSlotRef(MODULE_RESOLVE_HOOK);
     847           0 :         if (value.isUndefined())
     848           0 :             return nullptr;
     849             : 
     850           0 :         return &value.toObject().as<JSFunction>();
     851             :     }
     852             : 
     853             :     // Returns either this global's star-generator function prototype, or null
     854             :     // if that object was never created.  Dodgy; for use only in also-dodgy
     855             :     // GlobalHelperThreadState::mergeParseTaskCompartment().
     856             :     JSObject* getStarGeneratorFunctionPrototype();
     857             : };
     858             : 
     859             : /*
     860             :  * Unless otherwise specified, define ctor.prototype = proto as non-enumerable,
     861             :  * non-configurable, and non-writable; and define proto.constructor = ctor as
     862             :  * non-enumerable but configurable and writable.
     863             :  */
     864             : extern bool
     865             : LinkConstructorAndPrototype(JSContext* cx, JSObject* ctor, JSObject* proto,
     866             :                             unsigned prototypeAttrs = JSPROP_PERMANENT | JSPROP_READONLY,
     867             :                             unsigned constructorAttrs = 0);
     868             : 
     869             : /*
     870             :  * Define properties and/or functions on any object. Either ps or fs, or both,
     871             :  * may be null.
     872             :  */
     873             : extern bool
     874             : DefinePropertiesAndFunctions(JSContext* cx, HandleObject obj,
     875             :                              const JSPropertySpec* ps, const JSFunctionSpec* fs);
     876             : 
     877             : typedef HashSet<GlobalObject*, DefaultHasher<GlobalObject*>, SystemAllocPolicy> GlobalObjectSet;
     878             : 
     879             : extern bool
     880             : DefineToStringTag(JSContext *cx, HandleObject obj, JSAtom* tag);
     881             : 
     882             : /*
     883             :  * Convenience templates to generic constructor and prototype creation functions
     884             :  * for ClassSpecs.
     885             :  */
     886             : 
     887             : template<JSNative ctor, unsigned length, gc::AllocKind kind, const JSJitInfo* jitInfo = nullptr>
     888             : JSObject*
     889         664 : GenericCreateConstructor(JSContext* cx, JSProtoKey key)
     890             : {
     891             :     // Note - We duplicate the trick from ClassName() so that we don't need to
     892             :     // include jsatominlines.h here.
     893         664 :     PropertyName* name = (&cx->names().Null)[key];
     894         664 :     return GlobalObject::createConstructor(cx, ctor, name, length, kind, jitInfo);
     895             : }
     896             : 
     897             : inline JSObject*
     898          71 : GenericCreatePrototype(JSContext* cx, JSProtoKey key)
     899             : {
     900          71 :     MOZ_ASSERT(key != JSProto_Object);
     901          71 :     const Class* clasp = ProtoKeyToClass(key);
     902          71 :     MOZ_ASSERT(clasp);
     903          71 :     JSProtoKey protoKey = InheritanceProtoKeyForStandardClass(key);
     904          71 :     if (!GlobalObject::ensureConstructor(cx, cx->global(), protoKey))
     905           0 :         return nullptr;
     906         142 :     RootedObject parentProto(cx, &cx->global()->getPrototype(protoKey).toObject());
     907          71 :     return GlobalObject::createBlankPrototypeInheriting(cx, cx->global(), clasp, parentProto);
     908             : }
     909             : 
     910             : inline JSProtoKey
     911        8066 : StandardProtoKeyOrNull(const JSObject* obj)
     912             : {
     913        8066 :     return JSCLASS_CACHED_PROTO_KEY(obj->getClass());
     914             : }
     915             : 
     916             : JSObject*
     917             : NewSingletonObjectWithFunctionPrototype(JSContext* cx, Handle<GlobalObject*> global);
     918             : 
     919             : } // namespace js
     920             : 
     921             : template<>
     922             : inline bool
     923      292437 : JSObject::is<js::GlobalObject>() const
     924             : {
     925      292437 :     return !!(getClass()->flags & JSCLASS_IS_GLOBAL);
     926             : }
     927             : 
     928             : #endif /* vm_GlobalObject_h */

Generated by: LCOV version 1.13