js/src/vm/GlobalObject.h

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

     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/. */
     7 #ifndef vm_GlobalObject_h
     8 #define vm_GlobalObject_h
    10 #include "jsarray.h"
    11 #include "jsbool.h"
    12 #include "jsexn.h"
    13 #include "jsfun.h"
    14 #include "jsnum.h"
    16 #include "builtin/RegExp.h"
    17 #include "js/Vector.h"
    18 #include "vm/ArrayBufferObject.h"
    19 #include "vm/ErrorObject.h"
    21 extern JSObject *
    22 js_InitObjectClass(JSContext *cx, js::HandleObject obj);
    24 extern JSObject *
    25 js_InitFunctionClass(JSContext *cx, js::HandleObject obj);
    27 extern JSObject *
    28 js_InitTypedArrayClasses(JSContext *cx, js::HandleObject obj);
    30 extern JSObject *
    31 js_InitSharedArrayBufferClass(JSContext *cx, js::HandleObject obj);
    33 namespace js {
    35 class Debugger;
    36 class TypedObjectModuleObject;
    38 /*
    39  * Global object slots are reserved as follows:
    40  *
    41  * [0, APPLICATION_SLOTS)
    42  *   Pre-reserved slots in all global objects set aside for the embedding's
    43  *   use. As with all reserved slots these start out as UndefinedValue() and
    44  *   are traced for GC purposes. Apart from that the engine never touches
    45  *   these slots, so the embedding can do whatever it wants with them.
    46  * [APPLICATION_SLOTS, APPLICATION_SLOTS + JSProto_LIMIT)
    47  *   Stores the original value of the constructor for the corresponding
    48  *   JSProtoKey.
    49  * [APPLICATION_SLOTS + JSProto_LIMIT, APPLICATION_SLOTS + 2 * JSProto_LIMIT)
    50  *   Stores the prototype, if any, for the constructor for the corresponding
    51  *   JSProtoKey offset from JSProto_LIMIT.
    52  * [APPLICATION_SLOTS + 2 * JSProto_LIMIT, APPLICATION_SLOTS + 3 * JSProto_LIMIT)
    53  *   Stores the current value of the global property named for the JSProtoKey
    54  *   for the corresponding JSProtoKey offset from 2 * JSProto_LIMIT.
    55  * [APPLICATION_SLOTS + 3 * JSProto_LIMIT, RESERVED_SLOTS)
    56  *   Various one-off values: ES5 13.2.3's [[ThrowTypeError]], RegExp statics,
    57  *   the original eval for this global object (implementing |var eval =
    58  *   otherWindow.eval; eval(...)| as an indirect eval), a bit indicating
    59  *   whether this object has been cleared (see JS_ClearScope), and a cache for
    60  *   whether eval is allowed (per the global's Content Security Policy).
    61  *
    62  * The first two JSProto_LIMIT-sized ranges are necessary to implement
    63  * js::FindClassObject, and spec language speaking in terms of "the original
    64  * Array prototype object", or "as if by the expression new Array()" referring
    65  * to the original Array constructor. The third range stores the (writable and
    66  * even deletable) Object, Array, &c. properties (although a slot won't be used
    67  * again if its property is deleted and readded).
    68  */
    69 class GlobalObject : public JSObject
    70 {
    71     /* Count of slots set aside for application use. */
    72     static const unsigned APPLICATION_SLOTS = 3;
    74     /*
    75      * Count of slots to store built-in constructors, prototypes, and initial
    76      * visible properties for the constructors.
    77      */
    78     static const unsigned STANDARD_CLASS_SLOTS  = JSProto_LIMIT * 3;
    80     /* Various function values needed by the engine. */
    81     static const unsigned EVAL                    = APPLICATION_SLOTS + STANDARD_CLASS_SLOTS;
    82     static const unsigned CREATE_DATAVIEW_FOR_THIS = EVAL + 1;
    83     static const unsigned THROWTYPEERROR          = CREATE_DATAVIEW_FOR_THIS + 1;
    84     static const unsigned PROTO_GETTER            = THROWTYPEERROR + 1;
    86     /*
    87      * Instances of the internal createArrayFromBuffer function used by the
    88      * typed array code, one per typed array element type.
    89      */
    90     static const unsigned FROM_BUFFER_UINT8 = PROTO_GETTER + 1;
    91     static const unsigned FROM_BUFFER_INT8 = FROM_BUFFER_UINT8 + 1;
    92     static const unsigned FROM_BUFFER_UINT16 = FROM_BUFFER_INT8 + 1;
    93     static const unsigned FROM_BUFFER_INT16 = FROM_BUFFER_UINT16 + 1;
    94     static const unsigned FROM_BUFFER_UINT32 = FROM_BUFFER_INT16 + 1;
    95     static const unsigned FROM_BUFFER_INT32 = FROM_BUFFER_UINT32 + 1;
    96     static const unsigned FROM_BUFFER_FLOAT32 = FROM_BUFFER_INT32 + 1;
    97     static const unsigned FROM_BUFFER_FLOAT64 = FROM_BUFFER_FLOAT32 + 1;
    98     static const unsigned FROM_BUFFER_UINT8CLAMPED = FROM_BUFFER_FLOAT64 + 1;
   100     /* One-off properties stored after slots for built-ins. */
   101     static const unsigned ARRAY_ITERATOR_PROTO  = FROM_BUFFER_UINT8CLAMPED + 1;
   102     static const unsigned STRING_ITERATOR_PROTO  = ARRAY_ITERATOR_PROTO + 1;
   103     static const unsigned LEGACY_GENERATOR_OBJECT_PROTO = STRING_ITERATOR_PROTO + 1;
   104     static const unsigned STAR_GENERATOR_OBJECT_PROTO = LEGACY_GENERATOR_OBJECT_PROTO + 1;
   105     static const unsigned MAP_ITERATOR_PROTO      = STAR_GENERATOR_OBJECT_PROTO + 1;
   106     static const unsigned SET_ITERATOR_PROTO      = MAP_ITERATOR_PROTO + 1;
   107     static const unsigned COLLATOR_PROTO          = SET_ITERATOR_PROTO + 1;
   108     static const unsigned NUMBER_FORMAT_PROTO     = COLLATOR_PROTO + 1;
   109     static const unsigned DATE_TIME_FORMAT_PROTO  = NUMBER_FORMAT_PROTO + 1;
   110     static const unsigned REGEXP_STATICS          = DATE_TIME_FORMAT_PROTO + 1;
   111     static const unsigned WARNED_WATCH_DEPRECATED = REGEXP_STATICS + 1;
   112     static const unsigned WARNED_PROTO_SETTING_SLOW = WARNED_WATCH_DEPRECATED + 1;
   113     static const unsigned RUNTIME_CODEGEN_ENABLED = WARNED_PROTO_SETTING_SLOW + 1;
   114     static const unsigned DEBUGGERS               = RUNTIME_CODEGEN_ENABLED + 1;
   115     static const unsigned INTRINSICS              = DEBUGGERS + 1;
   116     static const unsigned FLOAT32X4_TYPE_DESCR   = INTRINSICS + 1;
   117     static const unsigned INT32X4_TYPE_DESCR     = FLOAT32X4_TYPE_DESCR + 1;
   118     static const unsigned FOR_OF_PIC_CHAIN        = INT32X4_TYPE_DESCR + 1;
   120     /* Total reserved-slot count for global objects. */
   121     static const unsigned RESERVED_SLOTS = FOR_OF_PIC_CHAIN + 1;
   123     /*
   124      * The slot count must be in the public API for JSCLASS_GLOBAL_FLAGS, and
   125      * we won't expose GlobalObject, so just assert that the two values are
   126      * synchronized.
   127      */
   128     static_assert(JSCLASS_GLOBAL_SLOT_COUNT == RESERVED_SLOTS,
   129                   "global object slot counts are inconsistent");
   131     /* Initialize the Function and Object classes.  Must only be called once! */
   132     JSObject *
   133     initFunctionAndObjectClasses(JSContext *cx);
   135     void setThrowTypeError(JSFunction *fun) {
   136         JS_ASSERT(getSlotRef(THROWTYPEERROR).isUndefined());
   137         setSlot(THROWTYPEERROR, ObjectValue(*fun));
   138     }
   140     void setOriginalEval(JSObject *evalobj) {
   141         JS_ASSERT(getSlotRef(EVAL).isUndefined());
   142         setSlot(EVAL, ObjectValue(*evalobj));
   143     }
   145     void setProtoGetter(JSFunction *protoGetter) {
   146         JS_ASSERT(getSlotRef(PROTO_GETTER).isUndefined());
   147         setSlot(PROTO_GETTER, ObjectValue(*protoGetter));
   148     }
   150     void setIntrinsicsHolder(JSObject *obj) {
   151         JS_ASSERT(getSlotRef(INTRINSICS).isUndefined());
   152         setSlot(INTRINSICS, ObjectValue(*obj));
   153     }
   155     // Emit the specified warning if the given slot in |obj|'s global isn't
   156     // true, then set the slot to true.  Thus calling this method warns once
   157     // for each global object it's called on, and every other call does
   158     // nothing.
   159     static bool
   160     warnOnceAbout(JSContext *cx, HandleObject obj, uint32_t slot, unsigned errorNumber);
   162   public:
   163     Value getConstructor(JSProtoKey key) const {
   164         JS_ASSERT(key <= JSProto_LIMIT);
   165         return getSlot(APPLICATION_SLOTS + key);
   166     }
   167     static bool ensureConstructor(JSContext *cx, Handle<GlobalObject*> global, JSProtoKey key);
   168     static bool resolveConstructor(JSContext *cx, Handle<GlobalObject*> global, JSProtoKey key);
   169     static bool initBuiltinConstructor(JSContext *cx, Handle<GlobalObject*> global,
   170                                        JSProtoKey key, HandleObject ctor, HandleObject proto);
   172     void setConstructor(JSProtoKey key, const Value &v) {
   173         JS_ASSERT(key <= JSProto_LIMIT);
   174         setSlot(APPLICATION_SLOTS + key, v);
   175     }
   177     Value getPrototype(JSProtoKey key) const {
   178         JS_ASSERT(key <= JSProto_LIMIT);
   179         return getSlot(APPLICATION_SLOTS + JSProto_LIMIT + key);
   180     }
   182     void setPrototype(JSProtoKey key, const Value &value) {
   183         JS_ASSERT(key <= JSProto_LIMIT);
   184         setSlot(APPLICATION_SLOTS + JSProto_LIMIT + key, value);
   185     }
   187     static uint32_t constructorPropertySlot(JSProtoKey key) {
   188         JS_ASSERT(key <= JSProto_LIMIT);
   189         return APPLICATION_SLOTS + JSProto_LIMIT * 2 + key;
   190     }
   192     Value getConstructorPropertySlot(JSProtoKey key) {
   193         return getSlot(constructorPropertySlot(key));
   194     }
   196     void setConstructorPropertySlot(JSProtoKey key, const Value &ctor) {
   197         setSlot(constructorPropertySlot(key), ctor);
   198     }
   200     bool classIsInitialized(JSProtoKey key) const {
   201         bool inited = !getConstructor(key).isUndefined();
   202         JS_ASSERT(inited == !getPrototype(key).isUndefined());
   203         return inited;
   204     }
   206     bool functionObjectClassesInitialized() const {
   207         bool inited = classIsInitialized(JSProto_Function);
   208         JS_ASSERT(inited == classIsInitialized(JSProto_Object));
   209         return inited;
   210     }
   212     /*
   213      * Lazy standard classes need a way to indicate they have been initialized.
   214      * Otherwise, when we delete them, we might accidentally recreate them via
   215      * a lazy initialization. We use the presence of an object in the
   216      * getConstructor(key) reserved slot to indicate that they've been
   217      * initialized.
   218      *
   219      * Note: A few builtin objects, like JSON and Math, are not constructors,
   220      * so getConstructor is a bit of a misnomer.
   221      */
   222     bool isStandardClassResolved(JSProtoKey key) const {
   223         // If the constructor is undefined, then it hasn't been initialized.
   224         MOZ_ASSERT(getConstructor(key).isUndefined() ||
   225                    getConstructor(key).isObject());
   226         return !getConstructor(key).isUndefined();
   227     }
   229     bool isStandardClassResolved(const js::Class *clasp) const {
   230         JSProtoKey key = JSCLASS_CACHED_PROTO_KEY(clasp);
   231         return isStandardClassResolved(key);
   232     }
   234   private:
   235     void setDetailsForKey(JSProtoKey key, JSObject *ctor, JSObject *proto) {
   236         JS_ASSERT(getConstructor(key).isUndefined());
   237         JS_ASSERT(getPrototype(key).isUndefined());
   238         JS_ASSERT(getConstructorPropertySlot(key).isUndefined());
   239         setConstructor(key, ObjectValue(*ctor));
   240         setPrototype(key, ObjectValue(*proto));
   241         setConstructorPropertySlot(key, ObjectValue(*ctor));
   242     }
   244     void setObjectClassDetails(JSFunction *ctor, JSObject *proto) {
   245         setDetailsForKey(JSProto_Object, ctor, proto);
   246     }
   248     void setFunctionClassDetails(JSFunction *ctor, JSObject *proto) {
   249         setDetailsForKey(JSProto_Function, ctor, proto);
   250     }
   252     bool arrayClassInitialized() const {
   253         return classIsInitialized(JSProto_Array);
   254     }
   256     bool booleanClassInitialized() const {
   257         return classIsInitialized(JSProto_Boolean);
   258     }
   259     bool numberClassInitialized() const {
   260         return classIsInitialized(JSProto_Number);
   261     }
   262     bool stringClassInitialized() const {
   263         return classIsInitialized(JSProto_String);
   264     }
   265     bool regexpClassInitialized() const {
   266         return classIsInitialized(JSProto_RegExp);
   267     }
   268     bool arrayBufferClassInitialized() const {
   269         return classIsInitialized(JSProto_ArrayBuffer);
   270     }
   271     bool sharedArrayBufferClassInitialized() const {
   272         return classIsInitialized(JSProto_SharedArrayBuffer);
   273     }
   274     bool errorClassesInitialized() const {
   275         return classIsInitialized(JSProto_Error);
   276     }
   277     bool dataViewClassInitialized() const {
   278         return classIsInitialized(JSProto_DataView);
   279     }
   280     bool typedArrayClassesInitialized() const {
   281         // This alias exists only for clarity: in reality all the typed array
   282         // classes constitute a (semi-)coherent whole.
   283         return classIsInitialized(JSProto_DataView);
   284     }
   286     Value createArrayFromBufferHelper(uint32_t slot) const {
   287         JS_ASSERT(typedArrayClassesInitialized());
   288         JS_ASSERT(FROM_BUFFER_UINT8 <= slot && slot <= FROM_BUFFER_UINT8CLAMPED);
   289         return getSlot(slot);
   290     }
   292     void setCreateArrayFromBufferHelper(uint32_t slot, Handle<JSFunction*> fun) {
   293         JS_ASSERT(getSlotRef(slot).isUndefined());
   294         setSlot(slot, ObjectValue(*fun));
   295     }
   297   public:
   298     /* XXX Privatize me! */
   299     void setCreateDataViewForThis(Handle<JSFunction*> fun) {
   300         JS_ASSERT(getSlotRef(CREATE_DATAVIEW_FOR_THIS).isUndefined());
   301         setSlot(CREATE_DATAVIEW_FOR_THIS, ObjectValue(*fun));
   302     }
   304     template<typename T>
   305     inline void setCreateArrayFromBuffer(Handle<JSFunction*> fun);
   307   public:
   308     static GlobalObject *create(JSContext *cx, const Class *clasp);
   310     /*
   311      * Create a constructor function with the specified name and length using
   312      * ctor, a method which creates objects with the given class.
   313      */
   314     JSFunction *
   315     createConstructor(JSContext *cx, JSNative ctor, JSAtom *name, unsigned length,
   316                       gc::AllocKind kind = JSFunction::FinalizeKind);
   318     /*
   319      * Create an object to serve as [[Prototype]] for instances of the given
   320      * class, using |Object.prototype| as its [[Prototype]].  Users creating
   321      * prototype objects with particular internal structure (e.g. reserved
   322      * slots guaranteed to contain values of particular types) must immediately
   323      * complete the minimal initialization to make the returned object safe to
   324      * touch.
   325      */
   326     JSObject *createBlankPrototype(JSContext *cx, const js::Class *clasp);
   328     /*
   329      * Identical to createBlankPrototype, but uses proto as the [[Prototype]]
   330      * of the returned blank prototype.
   331      */
   332     JSObject *createBlankPrototypeInheriting(JSContext *cx, const js::Class *clasp, JSObject &proto);
   334     JSObject *getOrCreateObjectPrototype(JSContext *cx) {
   335         if (functionObjectClassesInitialized())
   336             return &getPrototype(JSProto_Object).toObject();
   337         Rooted<GlobalObject*> self(cx, this);
   338         if (!initFunctionAndObjectClasses(cx))
   339             return nullptr;
   340         return &self->getPrototype(JSProto_Object).toObject();
   341     }
   343     JSObject *getOrCreateFunctionPrototype(JSContext *cx) {
   344         if (functionObjectClassesInitialized())
   345             return &getPrototype(JSProto_Function).toObject();
   346         Rooted<GlobalObject*> self(cx, this);
   347         if (!initFunctionAndObjectClasses(cx))
   348             return nullptr;
   349         return &self->getPrototype(JSProto_Function).toObject();
   350     }
   352     static JSObject *getOrCreateArrayPrototype(JSContext *cx, Handle<GlobalObject*> global) {
   353         if (!ensureConstructor(cx, global, JSProto_Array))
   354             return nullptr;
   355         return &global->getPrototype(JSProto_Array).toObject();
   356     }
   358     JSObject *maybeGetArrayPrototype() {
   359         if (arrayClassInitialized())
   360             return &getPrototype(JSProto_Array).toObject();
   361         return nullptr;
   362     }
   364     static JSObject *getOrCreateBooleanPrototype(JSContext *cx, Handle<GlobalObject*> global) {
   365         if (!ensureConstructor(cx, global, JSProto_Boolean))
   366             return nullptr;
   367         return &global->getPrototype(JSProto_Boolean).toObject();
   368     }
   370     static JSObject *getOrCreateNumberPrototype(JSContext *cx, Handle<GlobalObject*> global) {
   371         if (!ensureConstructor(cx, global, JSProto_Number))
   372             return nullptr;
   373         return &global->getPrototype(JSProto_Number).toObject();
   374     }
   376     static JSObject *getOrCreateStringPrototype(JSContext *cx, Handle<GlobalObject*> global) {
   377         if (!ensureConstructor(cx, global, JSProto_String))
   378             return nullptr;
   379         return &global->getPrototype(JSProto_String).toObject();
   380     }
   382     static JSObject *getOrCreateRegExpPrototype(JSContext *cx, Handle<GlobalObject*> global) {
   383         if (!ensureConstructor(cx, global, JSProto_RegExp))
   384             return nullptr;
   385         return &global->getPrototype(JSProto_RegExp).toObject();
   386     }
   388     JSObject *maybeGetRegExpPrototype() {
   389         if (regexpClassInitialized())
   390             return &getPrototype(JSProto_RegExp).toObject();
   391         return nullptr;
   392     }
   394     static JSObject *getOrCreateArrayBufferPrototype(JSContext *cx, Handle<GlobalObject*> global) {
   395         if (!ensureConstructor(cx, global, JSProto_ArrayBuffer))
   396             return nullptr;
   397         return &global->getPrototype(JSProto_ArrayBuffer).toObject();
   398     }
   400     JSObject *getOrCreateSharedArrayBufferPrototype(JSContext *cx, Handle<GlobalObject*> global) {
   401         if (!ensureConstructor(cx, global, JSProto_SharedArrayBuffer))
   402             return nullptr;
   403         return &global->getPrototype(JSProto_SharedArrayBuffer).toObject();
   404     }
   406     static JSObject *getOrCreateCustomErrorPrototype(JSContext *cx,
   407                                                      Handle<GlobalObject*> global,
   408                                                      JSExnType exnType)
   409     {
   410         JSProtoKey key = GetExceptionProtoKey(exnType);
   411         if (!ensureConstructor(cx, global, key))
   412             return nullptr;
   413         return &global->getPrototype(key).toObject();
   414     }
   416     JSObject *getOrCreateIntlObject(JSContext *cx) {
   417         return getOrCreateObject(cx, APPLICATION_SLOTS + JSProto_Intl, initIntlObject);
   418     }
   420     JSObject *getOrCreateTypedObjectModule(JSContext *cx) {
   421         return getOrCreateObject(cx, APPLICATION_SLOTS + JSProto_TypedObject, initTypedObjectModule);
   422     }
   424     void setFloat32x4TypeDescr(JSObject &obj) {
   425         JS_ASSERT(getSlotRef(FLOAT32X4_TYPE_DESCR).isUndefined());
   426         setSlot(FLOAT32X4_TYPE_DESCR, ObjectValue(obj));
   427     }
   429     JSObject &float32x4TypeDescr() {
   430         JS_ASSERT(getSlotRef(FLOAT32X4_TYPE_DESCR).isObject());
   431         return getSlotRef(FLOAT32X4_TYPE_DESCR).toObject();
   432     }
   434     void setInt32x4TypeDescr(JSObject &obj) {
   435         JS_ASSERT(getSlotRef(INT32X4_TYPE_DESCR).isUndefined());
   436         setSlot(INT32X4_TYPE_DESCR, ObjectValue(obj));
   437     }
   439     JSObject &int32x4TypeDescr() {
   440         JS_ASSERT(getSlotRef(INT32X4_TYPE_DESCR).isObject());
   441         return getSlotRef(INT32X4_TYPE_DESCR).toObject();
   442     }
   444     TypedObjectModuleObject &getTypedObjectModule() const;
   446     JSObject *getIteratorPrototype() {
   447         return &getPrototype(JSProto_Iterator).toObject();
   448     }
   450     JSObject *getOrCreateCollatorPrototype(JSContext *cx) {
   451         return getOrCreateObject(cx, COLLATOR_PROTO, initCollatorProto);
   452     }
   454     JSObject *getOrCreateNumberFormatPrototype(JSContext *cx) {
   455         return getOrCreateObject(cx, NUMBER_FORMAT_PROTO, initNumberFormatProto);
   456     }
   458     JSObject *getOrCreateDateTimeFormatPrototype(JSContext *cx) {
   459         return getOrCreateObject(cx, DATE_TIME_FORMAT_PROTO, initDateTimeFormatProto);
   460     }
   462   private:
   463     typedef bool (*ObjectInitOp)(JSContext *cx, Handle<GlobalObject*> global);
   465     JSObject *getOrCreateObject(JSContext *cx, unsigned slot, ObjectInitOp init) {
   466         Value v = getSlotRef(slot);
   467         if (v.isObject())
   468             return &v.toObject();
   469         Rooted<GlobalObject*> self(cx, this);
   470         if (!init(cx, self))
   471             return nullptr;
   472         return &self->getSlot(slot).toObject();
   473     }
   475   public:
   476     static JSObject *getOrCreateIteratorPrototype(JSContext *cx,
   477                                                   Handle<GlobalObject*> global)
   478     {
   479         if (!ensureConstructor(cx, global, JSProto_Iterator))
   480             return nullptr;
   481         return &global->getSlot(APPLICATION_SLOTS + JSProto_LIMIT + JSProto_Iterator).toObject();
   482     }
   484     static JSObject *getOrCreateArrayIteratorPrototype(JSContext *cx,
   485                                                        Handle<GlobalObject*> global)
   486     {
   487         if (!ensureConstructor(cx, global, JSProto_Iterator))
   488             return nullptr;
   489         return &global->getSlot(ARRAY_ITERATOR_PROTO).toObject();
   490     }
   492     static JSObject *getOrCreateStringIteratorPrototype(JSContext *cx,
   493                                                         Handle<GlobalObject*> global)
   494     {
   495         if (!ensureConstructor(cx, global, JSProto_Iterator))
   496             return nullptr;
   497         return &global->getSlot(STRING_ITERATOR_PROTO).toObject();
   498     }
   500     static JSObject *getOrCreateLegacyGeneratorObjectPrototype(JSContext *cx,
   501                                                                Handle<GlobalObject*> global)
   502     {
   503         if (!ensureConstructor(cx, global, JSProto_Iterator))
   504             return nullptr;
   505         return &global->getSlot(LEGACY_GENERATOR_OBJECT_PROTO).toObject();
   506     }
   508     static JSObject *getOrCreateStarGeneratorObjectPrototype(JSContext *cx,
   509                                                              Handle<GlobalObject*> global)
   510     {
   511         if (!ensureConstructor(cx, global, JSProto_Iterator))
   512             return nullptr;
   513         return &global->getSlot(STAR_GENERATOR_OBJECT_PROTO).toObject();
   514     }
   516     static JSObject *getOrCreateStarGeneratorFunctionPrototype(JSContext *cx,
   517                                                                Handle<GlobalObject*> global)
   518     {
   519         if (!ensureConstructor(cx, global, JSProto_Iterator))
   520             return nullptr;
   521         return &global->getSlot(APPLICATION_SLOTS + JSProto_LIMIT + JSProto_GeneratorFunction).toObject();
   522     }
   524     static JSObject *getOrCreateStarGeneratorFunction(JSContext *cx,
   525                                                       Handle<GlobalObject*> global)
   526     {
   527         if (!ensureConstructor(cx, global, JSProto_Iterator))
   528             return nullptr;
   529         return &global->getSlot(APPLICATION_SLOTS + JSProto_GeneratorFunction).toObject();
   530     }
   532     static JSObject *getOrCreateMapIteratorPrototype(JSContext *cx,
   533                                                      Handle<GlobalObject*> global)
   534     {
   535         return global->getOrCreateObject(cx, MAP_ITERATOR_PROTO, initMapIteratorProto);
   536     }
   538     static JSObject *getOrCreateSetIteratorPrototype(JSContext *cx,
   539                                                      Handle<GlobalObject*> global)
   540     {
   541         return global->getOrCreateObject(cx, SET_ITERATOR_PROTO, initSetIteratorProto);
   542     }
   544     JSObject *getOrCreateDataViewPrototype(JSContext *cx) {
   545         Rooted<GlobalObject*> self(cx, this);
   546         if (!ensureConstructor(cx, self, JSProto_DataView))
   547             return nullptr;
   548         return &self->getPrototype(JSProto_DataView).toObject();
   549     }
   551     JSObject *intrinsicsHolder() {
   552         JS_ASSERT(!getSlot(INTRINSICS).isUndefined());
   553         return &getSlot(INTRINSICS).toObject();
   554     }
   556     bool maybeGetIntrinsicValue(jsid id, Value *vp) {
   557         JSObject *holder = intrinsicsHolder();
   559         if (Shape *shape = holder->nativeLookupPure(id)) {
   560             *vp = holder->getSlot(shape->slot());
   561             return true;
   562         }
   563         return false;
   564     }
   565     bool maybeGetIntrinsicValue(PropertyName *name, Value *vp) {
   566         return maybeGetIntrinsicValue(NameToId(name), vp);
   567     }
   569     static bool getIntrinsicValue(JSContext *cx, Handle<GlobalObject*> global,
   570                                   HandlePropertyName name, MutableHandleValue value)
   571     {
   572         if (global->maybeGetIntrinsicValue(name, value.address()))
   573             return true;
   574         if (!cx->runtime()->cloneSelfHostedValue(cx, name, value))
   575             return false;
   576         RootedId id(cx, NameToId(name));
   577         return global->addIntrinsicValue(cx, id, value);
   578     }
   580     bool addIntrinsicValue(JSContext *cx, HandleId id, HandleValue value);
   582     bool setIntrinsicValue(JSContext *cx, PropertyName *name, HandleValue value) {
   583 #ifdef DEBUG
   584         RootedObject self(cx, this);
   585         JS_ASSERT(cx->runtime()->isSelfHostingGlobal(self));
   586 #endif
   587         RootedObject holder(cx, intrinsicsHolder());
   588         RootedValue valCopy(cx, value);
   589         return JSObject::setProperty(cx, holder, holder, name, &valCopy, false);
   590     }
   592     bool getSelfHostedFunction(JSContext *cx, HandleAtom selfHostedName, HandleAtom name,
   593                                unsigned nargs, MutableHandleValue funVal);
   595     RegExpStatics *getRegExpStatics() const {
   596         JSObject &resObj = getSlot(REGEXP_STATICS).toObject();
   597         return static_cast<RegExpStatics *>(resObj.getPrivate(/* nfixed = */ 1));
   598     }
   600     JSObject *getThrowTypeError() const {
   601         JS_ASSERT(functionObjectClassesInitialized());
   602         return &getSlot(THROWTYPEERROR).toObject();
   603     }
   605     Value createDataViewForThis() const {
   606         JS_ASSERT(dataViewClassInitialized());
   607         return getSlot(CREATE_DATAVIEW_FOR_THIS);
   608     }
   610     template<typename T>
   611     inline Value createArrayFromBuffer() const;
   613     Value protoGetter() const {
   614         JS_ASSERT(functionObjectClassesInitialized());
   615         return getSlot(PROTO_GETTER);
   616     }
   618     static bool isRuntimeCodeGenEnabled(JSContext *cx, Handle<GlobalObject*> global);
   620     // Warn about use of the deprecated watch/unwatch functions in the global
   621     // in which |obj| was created, if no prior warning was given.
   622     static bool warnOnceAboutWatch(JSContext *cx, HandleObject obj) {
   623         // Temporarily disabled until we've provided a watch/unwatch workaround for
   624         // debuggers like Firebug (bug 934669).
   625         //return warnOnceAbout(cx, obj, WARNED_WATCH_DEPRECATED, JSMSG_OBJECT_WATCH_DEPRECATED);
   626         return true;
   627     }
   629     // Warn about use of the given __proto__ setter to attempt to mutate an
   630     // object's [[Prototype]], if no prior warning was given.
   631     static bool warnOnceAboutPrototypeMutation(JSContext *cx, HandleObject protoSetter) {
   632         return warnOnceAbout(cx, protoSetter, WARNED_PROTO_SETTING_SLOW, JSMSG_PROTO_SETTING_SLOW);
   633     }
   635     static bool getOrCreateEval(JSContext *cx, Handle<GlobalObject*> global,
   636                                 MutableHandleObject eval);
   638     // Infallibly test whether the given value is the eval function for this global.
   639     bool valueIsEval(Value val);
   641     // Implemented in jsiter.cpp.
   642     static bool initIteratorClasses(JSContext *cx, Handle<GlobalObject*> global);
   644     // Implemented in builtin/MapObject.cpp.
   645     static bool initMapIteratorProto(JSContext *cx, Handle<GlobalObject*> global);
   646     static bool initSetIteratorProto(JSContext *cx, Handle<GlobalObject*> global);
   648     // Implemented in Intl.cpp.
   649     static bool initIntlObject(JSContext *cx, Handle<GlobalObject*> global);
   650     static bool initCollatorProto(JSContext *cx, Handle<GlobalObject*> global);
   651     static bool initNumberFormatProto(JSContext *cx, Handle<GlobalObject*> global);
   652     static bool initDateTimeFormatProto(JSContext *cx, Handle<GlobalObject*> global);
   654     // Implemented in builtin/TypedObject.cpp
   655     static bool initTypedObjectModule(JSContext *cx, Handle<GlobalObject*> global);
   657     static bool initStandardClasses(JSContext *cx, Handle<GlobalObject*> global);
   659     typedef js::Vector<js::Debugger *, 0, js::SystemAllocPolicy> DebuggerVector;
   661     /*
   662      * The collection of Debugger objects debugging this global. If this global
   663      * is not a debuggee, this returns either nullptr or an empty vector.
   664      */
   665     DebuggerVector *getDebuggers();
   667     /*
   668      * The same, but create the empty vector if one does not already
   669      * exist. Returns nullptr only on OOM.
   670      */
   671     static DebuggerVector *getOrCreateDebuggers(JSContext *cx, Handle<GlobalObject*> global);
   673     inline JSObject *getForOfPICObject() {
   674         Value forOfPIC = getReservedSlot(FOR_OF_PIC_CHAIN);
   675         if (forOfPIC.isUndefined())
   676             return nullptr;
   677         return &forOfPIC.toObject();
   678     }
   679     static JSObject *getOrCreateForOfPICObject(JSContext *cx, Handle<GlobalObject*> global);
   681     static bool addDebugger(JSContext *cx, Handle<GlobalObject*> global, Debugger *dbg);
   682 };
   684 template<>
   685 inline void
   686 GlobalObject::setCreateArrayFromBuffer<uint8_t>(Handle<JSFunction*> fun)
   687 {
   688     setCreateArrayFromBufferHelper(FROM_BUFFER_UINT8, fun);
   689 }
   691 template<>
   692 inline void
   693 GlobalObject::setCreateArrayFromBuffer<int8_t>(Handle<JSFunction*> fun)
   694 {
   695     setCreateArrayFromBufferHelper(FROM_BUFFER_INT8, fun);
   696 }
   698 template<>
   699 inline void
   700 GlobalObject::setCreateArrayFromBuffer<uint16_t>(Handle<JSFunction*> fun)
   701 {
   702     setCreateArrayFromBufferHelper(FROM_BUFFER_UINT16, fun);
   703 }
   705 template<>
   706 inline void
   707 GlobalObject::setCreateArrayFromBuffer<int16_t>(Handle<JSFunction*> fun)
   708 {
   709     setCreateArrayFromBufferHelper(FROM_BUFFER_INT16, fun);
   710 }
   712 template<>
   713 inline void
   714 GlobalObject::setCreateArrayFromBuffer<uint32_t>(Handle<JSFunction*> fun)
   715 {
   716     setCreateArrayFromBufferHelper(FROM_BUFFER_UINT32, fun);
   717 }
   719 template<>
   720 inline void
   721 GlobalObject::setCreateArrayFromBuffer<int32_t>(Handle<JSFunction*> fun)
   722 {
   723     setCreateArrayFromBufferHelper(FROM_BUFFER_INT32, fun);
   724 }
   726 template<>
   727 inline void
   728 GlobalObject::setCreateArrayFromBuffer<float>(Handle<JSFunction*> fun)
   729 {
   730     setCreateArrayFromBufferHelper(FROM_BUFFER_FLOAT32, fun);
   731 }
   733 template<>
   734 inline void
   735 GlobalObject::setCreateArrayFromBuffer<double>(Handle<JSFunction*> fun)
   736 {
   737     setCreateArrayFromBufferHelper(FROM_BUFFER_FLOAT64, fun);
   738 }
   740 template<>
   741 inline void
   742 GlobalObject::setCreateArrayFromBuffer<uint8_clamped>(Handle<JSFunction*> fun)
   743 {
   744     setCreateArrayFromBufferHelper(FROM_BUFFER_UINT8CLAMPED, fun);
   745 }
   747 template<>
   748 inline Value
   749 GlobalObject::createArrayFromBuffer<uint8_t>() const
   750 {
   751     return createArrayFromBufferHelper(FROM_BUFFER_UINT8);
   752 }
   754 template<>
   755 inline Value
   756 GlobalObject::createArrayFromBuffer<int8_t>() const
   757 {
   758     return createArrayFromBufferHelper(FROM_BUFFER_INT8);
   759 }
   761 template<>
   762 inline Value
   763 GlobalObject::createArrayFromBuffer<uint16_t>() const
   764 {
   765     return createArrayFromBufferHelper(FROM_BUFFER_UINT16);
   766 }
   768 template<>
   769 inline Value
   770 GlobalObject::createArrayFromBuffer<int16_t>() const
   771 {
   772     return createArrayFromBufferHelper(FROM_BUFFER_INT16);
   773 }
   775 template<>
   776 inline Value
   777 GlobalObject::createArrayFromBuffer<uint32_t>() const
   778 {
   779     return createArrayFromBufferHelper(FROM_BUFFER_UINT32);
   780 }
   782 template<>
   783 inline Value
   784 GlobalObject::createArrayFromBuffer<int32_t>() const
   785 {
   786     return createArrayFromBufferHelper(FROM_BUFFER_INT32);
   787 }
   789 template<>
   790 inline Value
   791 GlobalObject::createArrayFromBuffer<float>() const
   792 {
   793     return createArrayFromBufferHelper(FROM_BUFFER_FLOAT32);
   794 }
   796 template<>
   797 inline Value
   798 GlobalObject::createArrayFromBuffer<double>() const
   799 {
   800     return createArrayFromBufferHelper(FROM_BUFFER_FLOAT64);
   801 }
   803 template<>
   804 inline Value
   805 GlobalObject::createArrayFromBuffer<uint8_clamped>() const
   806 {
   807     return createArrayFromBufferHelper(FROM_BUFFER_UINT8CLAMPED);
   808 }
   810 /*
   811  * Define ctor.prototype = proto as non-enumerable, non-configurable, and
   812  * non-writable; define proto.constructor = ctor as non-enumerable but
   813  * configurable and writable.
   814  */
   815 extern bool
   816 LinkConstructorAndPrototype(JSContext *cx, JSObject *ctor, JSObject *proto);
   818 /*
   819  * Define properties, then functions, on the object, then brand for tracing
   820  * benefits.
   821  */
   822 extern bool
   823 DefinePropertiesAndBrand(JSContext *cx, JSObject *obj,
   824                          const JSPropertySpec *ps, const JSFunctionSpec *fs);
   826 typedef HashSet<GlobalObject *, DefaultHasher<GlobalObject *>, SystemAllocPolicy> GlobalObjectSet;
   828 /*
   829  * Convenience templates to generic constructor and prototype creation functions
   830  * for ClassSpecs.
   831  */
   833 template<JSNative ctor, size_t atomOffset, unsigned length>
   834 JSObject *
   835 GenericCreateConstructor(JSContext *cx, JSProtoKey key)
   836 {
   837     JSAtom *atom = AtomStateOffsetToName(cx->names(), atomOffset);
   838     return cx->global()->createConstructor(cx, ctor, atom, length);
   839 }
   841 template<const Class *clasp>
   842 JSObject *
   843 GenericCreatePrototype(JSContext *cx, JSProtoKey key)
   844 {
   845     return cx->global()->createBlankPrototype(cx, clasp);
   846 }
   848 } // namespace js
   850 template<>
   851 inline bool
   852 JSObject::is<js::GlobalObject>() const
   853 {
   854     return !!(getClass()->flags & JSCLASS_IS_GLOBAL);
   855 }
   857 #endif /* vm_GlobalObject_h */

mercurial