1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/js/src/vm/GlobalObject.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,857 @@ 1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- 1.5 + * vim: set ts=8 sts=4 et sw=4 tw=99: 1.6 + * This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +#ifndef vm_GlobalObject_h 1.11 +#define vm_GlobalObject_h 1.12 + 1.13 +#include "jsarray.h" 1.14 +#include "jsbool.h" 1.15 +#include "jsexn.h" 1.16 +#include "jsfun.h" 1.17 +#include "jsnum.h" 1.18 + 1.19 +#include "builtin/RegExp.h" 1.20 +#include "js/Vector.h" 1.21 +#include "vm/ArrayBufferObject.h" 1.22 +#include "vm/ErrorObject.h" 1.23 + 1.24 +extern JSObject * 1.25 +js_InitObjectClass(JSContext *cx, js::HandleObject obj); 1.26 + 1.27 +extern JSObject * 1.28 +js_InitFunctionClass(JSContext *cx, js::HandleObject obj); 1.29 + 1.30 +extern JSObject * 1.31 +js_InitTypedArrayClasses(JSContext *cx, js::HandleObject obj); 1.32 + 1.33 +extern JSObject * 1.34 +js_InitSharedArrayBufferClass(JSContext *cx, js::HandleObject obj); 1.35 + 1.36 +namespace js { 1.37 + 1.38 +class Debugger; 1.39 +class TypedObjectModuleObject; 1.40 + 1.41 +/* 1.42 + * Global object slots are reserved as follows: 1.43 + * 1.44 + * [0, APPLICATION_SLOTS) 1.45 + * Pre-reserved slots in all global objects set aside for the embedding's 1.46 + * use. As with all reserved slots these start out as UndefinedValue() and 1.47 + * are traced for GC purposes. Apart from that the engine never touches 1.48 + * these slots, so the embedding can do whatever it wants with them. 1.49 + * [APPLICATION_SLOTS, APPLICATION_SLOTS + JSProto_LIMIT) 1.50 + * Stores the original value of the constructor for the corresponding 1.51 + * JSProtoKey. 1.52 + * [APPLICATION_SLOTS + JSProto_LIMIT, APPLICATION_SLOTS + 2 * JSProto_LIMIT) 1.53 + * Stores the prototype, if any, for the constructor for the corresponding 1.54 + * JSProtoKey offset from JSProto_LIMIT. 1.55 + * [APPLICATION_SLOTS + 2 * JSProto_LIMIT, APPLICATION_SLOTS + 3 * JSProto_LIMIT) 1.56 + * Stores the current value of the global property named for the JSProtoKey 1.57 + * for the corresponding JSProtoKey offset from 2 * JSProto_LIMIT. 1.58 + * [APPLICATION_SLOTS + 3 * JSProto_LIMIT, RESERVED_SLOTS) 1.59 + * Various one-off values: ES5 13.2.3's [[ThrowTypeError]], RegExp statics, 1.60 + * the original eval for this global object (implementing |var eval = 1.61 + * otherWindow.eval; eval(...)| as an indirect eval), a bit indicating 1.62 + * whether this object has been cleared (see JS_ClearScope), and a cache for 1.63 + * whether eval is allowed (per the global's Content Security Policy). 1.64 + * 1.65 + * The first two JSProto_LIMIT-sized ranges are necessary to implement 1.66 + * js::FindClassObject, and spec language speaking in terms of "the original 1.67 + * Array prototype object", or "as if by the expression new Array()" referring 1.68 + * to the original Array constructor. The third range stores the (writable and 1.69 + * even deletable) Object, Array, &c. properties (although a slot won't be used 1.70 + * again if its property is deleted and readded). 1.71 + */ 1.72 +class GlobalObject : public JSObject 1.73 +{ 1.74 + /* Count of slots set aside for application use. */ 1.75 + static const unsigned APPLICATION_SLOTS = 3; 1.76 + 1.77 + /* 1.78 + * Count of slots to store built-in constructors, prototypes, and initial 1.79 + * visible properties for the constructors. 1.80 + */ 1.81 + static const unsigned STANDARD_CLASS_SLOTS = JSProto_LIMIT * 3; 1.82 + 1.83 + /* Various function values needed by the engine. */ 1.84 + static const unsigned EVAL = APPLICATION_SLOTS + STANDARD_CLASS_SLOTS; 1.85 + static const unsigned CREATE_DATAVIEW_FOR_THIS = EVAL + 1; 1.86 + static const unsigned THROWTYPEERROR = CREATE_DATAVIEW_FOR_THIS + 1; 1.87 + static const unsigned PROTO_GETTER = THROWTYPEERROR + 1; 1.88 + 1.89 + /* 1.90 + * Instances of the internal createArrayFromBuffer function used by the 1.91 + * typed array code, one per typed array element type. 1.92 + */ 1.93 + static const unsigned FROM_BUFFER_UINT8 = PROTO_GETTER + 1; 1.94 + static const unsigned FROM_BUFFER_INT8 = FROM_BUFFER_UINT8 + 1; 1.95 + static const unsigned FROM_BUFFER_UINT16 = FROM_BUFFER_INT8 + 1; 1.96 + static const unsigned FROM_BUFFER_INT16 = FROM_BUFFER_UINT16 + 1; 1.97 + static const unsigned FROM_BUFFER_UINT32 = FROM_BUFFER_INT16 + 1; 1.98 + static const unsigned FROM_BUFFER_INT32 = FROM_BUFFER_UINT32 + 1; 1.99 + static const unsigned FROM_BUFFER_FLOAT32 = FROM_BUFFER_INT32 + 1; 1.100 + static const unsigned FROM_BUFFER_FLOAT64 = FROM_BUFFER_FLOAT32 + 1; 1.101 + static const unsigned FROM_BUFFER_UINT8CLAMPED = FROM_BUFFER_FLOAT64 + 1; 1.102 + 1.103 + /* One-off properties stored after slots for built-ins. */ 1.104 + static const unsigned ARRAY_ITERATOR_PROTO = FROM_BUFFER_UINT8CLAMPED + 1; 1.105 + static const unsigned STRING_ITERATOR_PROTO = ARRAY_ITERATOR_PROTO + 1; 1.106 + static const unsigned LEGACY_GENERATOR_OBJECT_PROTO = STRING_ITERATOR_PROTO + 1; 1.107 + static const unsigned STAR_GENERATOR_OBJECT_PROTO = LEGACY_GENERATOR_OBJECT_PROTO + 1; 1.108 + static const unsigned MAP_ITERATOR_PROTO = STAR_GENERATOR_OBJECT_PROTO + 1; 1.109 + static const unsigned SET_ITERATOR_PROTO = MAP_ITERATOR_PROTO + 1; 1.110 + static const unsigned COLLATOR_PROTO = SET_ITERATOR_PROTO + 1; 1.111 + static const unsigned NUMBER_FORMAT_PROTO = COLLATOR_PROTO + 1; 1.112 + static const unsigned DATE_TIME_FORMAT_PROTO = NUMBER_FORMAT_PROTO + 1; 1.113 + static const unsigned REGEXP_STATICS = DATE_TIME_FORMAT_PROTO + 1; 1.114 + static const unsigned WARNED_WATCH_DEPRECATED = REGEXP_STATICS + 1; 1.115 + static const unsigned WARNED_PROTO_SETTING_SLOW = WARNED_WATCH_DEPRECATED + 1; 1.116 + static const unsigned RUNTIME_CODEGEN_ENABLED = WARNED_PROTO_SETTING_SLOW + 1; 1.117 + static const unsigned DEBUGGERS = RUNTIME_CODEGEN_ENABLED + 1; 1.118 + static const unsigned INTRINSICS = DEBUGGERS + 1; 1.119 + static const unsigned FLOAT32X4_TYPE_DESCR = INTRINSICS + 1; 1.120 + static const unsigned INT32X4_TYPE_DESCR = FLOAT32X4_TYPE_DESCR + 1; 1.121 + static const unsigned FOR_OF_PIC_CHAIN = INT32X4_TYPE_DESCR + 1; 1.122 + 1.123 + /* Total reserved-slot count for global objects. */ 1.124 + static const unsigned RESERVED_SLOTS = FOR_OF_PIC_CHAIN + 1; 1.125 + 1.126 + /* 1.127 + * The slot count must be in the public API for JSCLASS_GLOBAL_FLAGS, and 1.128 + * we won't expose GlobalObject, so just assert that the two values are 1.129 + * synchronized. 1.130 + */ 1.131 + static_assert(JSCLASS_GLOBAL_SLOT_COUNT == RESERVED_SLOTS, 1.132 + "global object slot counts are inconsistent"); 1.133 + 1.134 + /* Initialize the Function and Object classes. Must only be called once! */ 1.135 + JSObject * 1.136 + initFunctionAndObjectClasses(JSContext *cx); 1.137 + 1.138 + void setThrowTypeError(JSFunction *fun) { 1.139 + JS_ASSERT(getSlotRef(THROWTYPEERROR).isUndefined()); 1.140 + setSlot(THROWTYPEERROR, ObjectValue(*fun)); 1.141 + } 1.142 + 1.143 + void setOriginalEval(JSObject *evalobj) { 1.144 + JS_ASSERT(getSlotRef(EVAL).isUndefined()); 1.145 + setSlot(EVAL, ObjectValue(*evalobj)); 1.146 + } 1.147 + 1.148 + void setProtoGetter(JSFunction *protoGetter) { 1.149 + JS_ASSERT(getSlotRef(PROTO_GETTER).isUndefined()); 1.150 + setSlot(PROTO_GETTER, ObjectValue(*protoGetter)); 1.151 + } 1.152 + 1.153 + void setIntrinsicsHolder(JSObject *obj) { 1.154 + JS_ASSERT(getSlotRef(INTRINSICS).isUndefined()); 1.155 + setSlot(INTRINSICS, ObjectValue(*obj)); 1.156 + } 1.157 + 1.158 + // Emit the specified warning if the given slot in |obj|'s global isn't 1.159 + // true, then set the slot to true. Thus calling this method warns once 1.160 + // for each global object it's called on, and every other call does 1.161 + // nothing. 1.162 + static bool 1.163 + warnOnceAbout(JSContext *cx, HandleObject obj, uint32_t slot, unsigned errorNumber); 1.164 + 1.165 + public: 1.166 + Value getConstructor(JSProtoKey key) const { 1.167 + JS_ASSERT(key <= JSProto_LIMIT); 1.168 + return getSlot(APPLICATION_SLOTS + key); 1.169 + } 1.170 + static bool ensureConstructor(JSContext *cx, Handle<GlobalObject*> global, JSProtoKey key); 1.171 + static bool resolveConstructor(JSContext *cx, Handle<GlobalObject*> global, JSProtoKey key); 1.172 + static bool initBuiltinConstructor(JSContext *cx, Handle<GlobalObject*> global, 1.173 + JSProtoKey key, HandleObject ctor, HandleObject proto); 1.174 + 1.175 + void setConstructor(JSProtoKey key, const Value &v) { 1.176 + JS_ASSERT(key <= JSProto_LIMIT); 1.177 + setSlot(APPLICATION_SLOTS + key, v); 1.178 + } 1.179 + 1.180 + Value getPrototype(JSProtoKey key) const { 1.181 + JS_ASSERT(key <= JSProto_LIMIT); 1.182 + return getSlot(APPLICATION_SLOTS + JSProto_LIMIT + key); 1.183 + } 1.184 + 1.185 + void setPrototype(JSProtoKey key, const Value &value) { 1.186 + JS_ASSERT(key <= JSProto_LIMIT); 1.187 + setSlot(APPLICATION_SLOTS + JSProto_LIMIT + key, value); 1.188 + } 1.189 + 1.190 + static uint32_t constructorPropertySlot(JSProtoKey key) { 1.191 + JS_ASSERT(key <= JSProto_LIMIT); 1.192 + return APPLICATION_SLOTS + JSProto_LIMIT * 2 + key; 1.193 + } 1.194 + 1.195 + Value getConstructorPropertySlot(JSProtoKey key) { 1.196 + return getSlot(constructorPropertySlot(key)); 1.197 + } 1.198 + 1.199 + void setConstructorPropertySlot(JSProtoKey key, const Value &ctor) { 1.200 + setSlot(constructorPropertySlot(key), ctor); 1.201 + } 1.202 + 1.203 + bool classIsInitialized(JSProtoKey key) const { 1.204 + bool inited = !getConstructor(key).isUndefined(); 1.205 + JS_ASSERT(inited == !getPrototype(key).isUndefined()); 1.206 + return inited; 1.207 + } 1.208 + 1.209 + bool functionObjectClassesInitialized() const { 1.210 + bool inited = classIsInitialized(JSProto_Function); 1.211 + JS_ASSERT(inited == classIsInitialized(JSProto_Object)); 1.212 + return inited; 1.213 + } 1.214 + 1.215 + /* 1.216 + * Lazy standard classes need a way to indicate they have been initialized. 1.217 + * Otherwise, when we delete them, we might accidentally recreate them via 1.218 + * a lazy initialization. We use the presence of an object in the 1.219 + * getConstructor(key) reserved slot to indicate that they've been 1.220 + * initialized. 1.221 + * 1.222 + * Note: A few builtin objects, like JSON and Math, are not constructors, 1.223 + * so getConstructor is a bit of a misnomer. 1.224 + */ 1.225 + bool isStandardClassResolved(JSProtoKey key) const { 1.226 + // If the constructor is undefined, then it hasn't been initialized. 1.227 + MOZ_ASSERT(getConstructor(key).isUndefined() || 1.228 + getConstructor(key).isObject()); 1.229 + return !getConstructor(key).isUndefined(); 1.230 + } 1.231 + 1.232 + bool isStandardClassResolved(const js::Class *clasp) const { 1.233 + JSProtoKey key = JSCLASS_CACHED_PROTO_KEY(clasp); 1.234 + return isStandardClassResolved(key); 1.235 + } 1.236 + 1.237 + private: 1.238 + void setDetailsForKey(JSProtoKey key, JSObject *ctor, JSObject *proto) { 1.239 + JS_ASSERT(getConstructor(key).isUndefined()); 1.240 + JS_ASSERT(getPrototype(key).isUndefined()); 1.241 + JS_ASSERT(getConstructorPropertySlot(key).isUndefined()); 1.242 + setConstructor(key, ObjectValue(*ctor)); 1.243 + setPrototype(key, ObjectValue(*proto)); 1.244 + setConstructorPropertySlot(key, ObjectValue(*ctor)); 1.245 + } 1.246 + 1.247 + void setObjectClassDetails(JSFunction *ctor, JSObject *proto) { 1.248 + setDetailsForKey(JSProto_Object, ctor, proto); 1.249 + } 1.250 + 1.251 + void setFunctionClassDetails(JSFunction *ctor, JSObject *proto) { 1.252 + setDetailsForKey(JSProto_Function, ctor, proto); 1.253 + } 1.254 + 1.255 + bool arrayClassInitialized() const { 1.256 + return classIsInitialized(JSProto_Array); 1.257 + } 1.258 + 1.259 + bool booleanClassInitialized() const { 1.260 + return classIsInitialized(JSProto_Boolean); 1.261 + } 1.262 + bool numberClassInitialized() const { 1.263 + return classIsInitialized(JSProto_Number); 1.264 + } 1.265 + bool stringClassInitialized() const { 1.266 + return classIsInitialized(JSProto_String); 1.267 + } 1.268 + bool regexpClassInitialized() const { 1.269 + return classIsInitialized(JSProto_RegExp); 1.270 + } 1.271 + bool arrayBufferClassInitialized() const { 1.272 + return classIsInitialized(JSProto_ArrayBuffer); 1.273 + } 1.274 + bool sharedArrayBufferClassInitialized() const { 1.275 + return classIsInitialized(JSProto_SharedArrayBuffer); 1.276 + } 1.277 + bool errorClassesInitialized() const { 1.278 + return classIsInitialized(JSProto_Error); 1.279 + } 1.280 + bool dataViewClassInitialized() const { 1.281 + return classIsInitialized(JSProto_DataView); 1.282 + } 1.283 + bool typedArrayClassesInitialized() const { 1.284 + // This alias exists only for clarity: in reality all the typed array 1.285 + // classes constitute a (semi-)coherent whole. 1.286 + return classIsInitialized(JSProto_DataView); 1.287 + } 1.288 + 1.289 + Value createArrayFromBufferHelper(uint32_t slot) const { 1.290 + JS_ASSERT(typedArrayClassesInitialized()); 1.291 + JS_ASSERT(FROM_BUFFER_UINT8 <= slot && slot <= FROM_BUFFER_UINT8CLAMPED); 1.292 + return getSlot(slot); 1.293 + } 1.294 + 1.295 + void setCreateArrayFromBufferHelper(uint32_t slot, Handle<JSFunction*> fun) { 1.296 + JS_ASSERT(getSlotRef(slot).isUndefined()); 1.297 + setSlot(slot, ObjectValue(*fun)); 1.298 + } 1.299 + 1.300 + public: 1.301 + /* XXX Privatize me! */ 1.302 + void setCreateDataViewForThis(Handle<JSFunction*> fun) { 1.303 + JS_ASSERT(getSlotRef(CREATE_DATAVIEW_FOR_THIS).isUndefined()); 1.304 + setSlot(CREATE_DATAVIEW_FOR_THIS, ObjectValue(*fun)); 1.305 + } 1.306 + 1.307 + template<typename T> 1.308 + inline void setCreateArrayFromBuffer(Handle<JSFunction*> fun); 1.309 + 1.310 + public: 1.311 + static GlobalObject *create(JSContext *cx, const Class *clasp); 1.312 + 1.313 + /* 1.314 + * Create a constructor function with the specified name and length using 1.315 + * ctor, a method which creates objects with the given class. 1.316 + */ 1.317 + JSFunction * 1.318 + createConstructor(JSContext *cx, JSNative ctor, JSAtom *name, unsigned length, 1.319 + gc::AllocKind kind = JSFunction::FinalizeKind); 1.320 + 1.321 + /* 1.322 + * Create an object to serve as [[Prototype]] for instances of the given 1.323 + * class, using |Object.prototype| as its [[Prototype]]. Users creating 1.324 + * prototype objects with particular internal structure (e.g. reserved 1.325 + * slots guaranteed to contain values of particular types) must immediately 1.326 + * complete the minimal initialization to make the returned object safe to 1.327 + * touch. 1.328 + */ 1.329 + JSObject *createBlankPrototype(JSContext *cx, const js::Class *clasp); 1.330 + 1.331 + /* 1.332 + * Identical to createBlankPrototype, but uses proto as the [[Prototype]] 1.333 + * of the returned blank prototype. 1.334 + */ 1.335 + JSObject *createBlankPrototypeInheriting(JSContext *cx, const js::Class *clasp, JSObject &proto); 1.336 + 1.337 + JSObject *getOrCreateObjectPrototype(JSContext *cx) { 1.338 + if (functionObjectClassesInitialized()) 1.339 + return &getPrototype(JSProto_Object).toObject(); 1.340 + Rooted<GlobalObject*> self(cx, this); 1.341 + if (!initFunctionAndObjectClasses(cx)) 1.342 + return nullptr; 1.343 + return &self->getPrototype(JSProto_Object).toObject(); 1.344 + } 1.345 + 1.346 + JSObject *getOrCreateFunctionPrototype(JSContext *cx) { 1.347 + if (functionObjectClassesInitialized()) 1.348 + return &getPrototype(JSProto_Function).toObject(); 1.349 + Rooted<GlobalObject*> self(cx, this); 1.350 + if (!initFunctionAndObjectClasses(cx)) 1.351 + return nullptr; 1.352 + return &self->getPrototype(JSProto_Function).toObject(); 1.353 + } 1.354 + 1.355 + static JSObject *getOrCreateArrayPrototype(JSContext *cx, Handle<GlobalObject*> global) { 1.356 + if (!ensureConstructor(cx, global, JSProto_Array)) 1.357 + return nullptr; 1.358 + return &global->getPrototype(JSProto_Array).toObject(); 1.359 + } 1.360 + 1.361 + JSObject *maybeGetArrayPrototype() { 1.362 + if (arrayClassInitialized()) 1.363 + return &getPrototype(JSProto_Array).toObject(); 1.364 + return nullptr; 1.365 + } 1.366 + 1.367 + static JSObject *getOrCreateBooleanPrototype(JSContext *cx, Handle<GlobalObject*> global) { 1.368 + if (!ensureConstructor(cx, global, JSProto_Boolean)) 1.369 + return nullptr; 1.370 + return &global->getPrototype(JSProto_Boolean).toObject(); 1.371 + } 1.372 + 1.373 + static JSObject *getOrCreateNumberPrototype(JSContext *cx, Handle<GlobalObject*> global) { 1.374 + if (!ensureConstructor(cx, global, JSProto_Number)) 1.375 + return nullptr; 1.376 + return &global->getPrototype(JSProto_Number).toObject(); 1.377 + } 1.378 + 1.379 + static JSObject *getOrCreateStringPrototype(JSContext *cx, Handle<GlobalObject*> global) { 1.380 + if (!ensureConstructor(cx, global, JSProto_String)) 1.381 + return nullptr; 1.382 + return &global->getPrototype(JSProto_String).toObject(); 1.383 + } 1.384 + 1.385 + static JSObject *getOrCreateRegExpPrototype(JSContext *cx, Handle<GlobalObject*> global) { 1.386 + if (!ensureConstructor(cx, global, JSProto_RegExp)) 1.387 + return nullptr; 1.388 + return &global->getPrototype(JSProto_RegExp).toObject(); 1.389 + } 1.390 + 1.391 + JSObject *maybeGetRegExpPrototype() { 1.392 + if (regexpClassInitialized()) 1.393 + return &getPrototype(JSProto_RegExp).toObject(); 1.394 + return nullptr; 1.395 + } 1.396 + 1.397 + static JSObject *getOrCreateArrayBufferPrototype(JSContext *cx, Handle<GlobalObject*> global) { 1.398 + if (!ensureConstructor(cx, global, JSProto_ArrayBuffer)) 1.399 + return nullptr; 1.400 + return &global->getPrototype(JSProto_ArrayBuffer).toObject(); 1.401 + } 1.402 + 1.403 + JSObject *getOrCreateSharedArrayBufferPrototype(JSContext *cx, Handle<GlobalObject*> global) { 1.404 + if (!ensureConstructor(cx, global, JSProto_SharedArrayBuffer)) 1.405 + return nullptr; 1.406 + return &global->getPrototype(JSProto_SharedArrayBuffer).toObject(); 1.407 + } 1.408 + 1.409 + static JSObject *getOrCreateCustomErrorPrototype(JSContext *cx, 1.410 + Handle<GlobalObject*> global, 1.411 + JSExnType exnType) 1.412 + { 1.413 + JSProtoKey key = GetExceptionProtoKey(exnType); 1.414 + if (!ensureConstructor(cx, global, key)) 1.415 + return nullptr; 1.416 + return &global->getPrototype(key).toObject(); 1.417 + } 1.418 + 1.419 + JSObject *getOrCreateIntlObject(JSContext *cx) { 1.420 + return getOrCreateObject(cx, APPLICATION_SLOTS + JSProto_Intl, initIntlObject); 1.421 + } 1.422 + 1.423 + JSObject *getOrCreateTypedObjectModule(JSContext *cx) { 1.424 + return getOrCreateObject(cx, APPLICATION_SLOTS + JSProto_TypedObject, initTypedObjectModule); 1.425 + } 1.426 + 1.427 + void setFloat32x4TypeDescr(JSObject &obj) { 1.428 + JS_ASSERT(getSlotRef(FLOAT32X4_TYPE_DESCR).isUndefined()); 1.429 + setSlot(FLOAT32X4_TYPE_DESCR, ObjectValue(obj)); 1.430 + } 1.431 + 1.432 + JSObject &float32x4TypeDescr() { 1.433 + JS_ASSERT(getSlotRef(FLOAT32X4_TYPE_DESCR).isObject()); 1.434 + return getSlotRef(FLOAT32X4_TYPE_DESCR).toObject(); 1.435 + } 1.436 + 1.437 + void setInt32x4TypeDescr(JSObject &obj) { 1.438 + JS_ASSERT(getSlotRef(INT32X4_TYPE_DESCR).isUndefined()); 1.439 + setSlot(INT32X4_TYPE_DESCR, ObjectValue(obj)); 1.440 + } 1.441 + 1.442 + JSObject &int32x4TypeDescr() { 1.443 + JS_ASSERT(getSlotRef(INT32X4_TYPE_DESCR).isObject()); 1.444 + return getSlotRef(INT32X4_TYPE_DESCR).toObject(); 1.445 + } 1.446 + 1.447 + TypedObjectModuleObject &getTypedObjectModule() const; 1.448 + 1.449 + JSObject *getIteratorPrototype() { 1.450 + return &getPrototype(JSProto_Iterator).toObject(); 1.451 + } 1.452 + 1.453 + JSObject *getOrCreateCollatorPrototype(JSContext *cx) { 1.454 + return getOrCreateObject(cx, COLLATOR_PROTO, initCollatorProto); 1.455 + } 1.456 + 1.457 + JSObject *getOrCreateNumberFormatPrototype(JSContext *cx) { 1.458 + return getOrCreateObject(cx, NUMBER_FORMAT_PROTO, initNumberFormatProto); 1.459 + } 1.460 + 1.461 + JSObject *getOrCreateDateTimeFormatPrototype(JSContext *cx) { 1.462 + return getOrCreateObject(cx, DATE_TIME_FORMAT_PROTO, initDateTimeFormatProto); 1.463 + } 1.464 + 1.465 + private: 1.466 + typedef bool (*ObjectInitOp)(JSContext *cx, Handle<GlobalObject*> global); 1.467 + 1.468 + JSObject *getOrCreateObject(JSContext *cx, unsigned slot, ObjectInitOp init) { 1.469 + Value v = getSlotRef(slot); 1.470 + if (v.isObject()) 1.471 + return &v.toObject(); 1.472 + Rooted<GlobalObject*> self(cx, this); 1.473 + if (!init(cx, self)) 1.474 + return nullptr; 1.475 + return &self->getSlot(slot).toObject(); 1.476 + } 1.477 + 1.478 + public: 1.479 + static JSObject *getOrCreateIteratorPrototype(JSContext *cx, 1.480 + Handle<GlobalObject*> global) 1.481 + { 1.482 + if (!ensureConstructor(cx, global, JSProto_Iterator)) 1.483 + return nullptr; 1.484 + return &global->getSlot(APPLICATION_SLOTS + JSProto_LIMIT + JSProto_Iterator).toObject(); 1.485 + } 1.486 + 1.487 + static JSObject *getOrCreateArrayIteratorPrototype(JSContext *cx, 1.488 + Handle<GlobalObject*> global) 1.489 + { 1.490 + if (!ensureConstructor(cx, global, JSProto_Iterator)) 1.491 + return nullptr; 1.492 + return &global->getSlot(ARRAY_ITERATOR_PROTO).toObject(); 1.493 + } 1.494 + 1.495 + static JSObject *getOrCreateStringIteratorPrototype(JSContext *cx, 1.496 + Handle<GlobalObject*> global) 1.497 + { 1.498 + if (!ensureConstructor(cx, global, JSProto_Iterator)) 1.499 + return nullptr; 1.500 + return &global->getSlot(STRING_ITERATOR_PROTO).toObject(); 1.501 + } 1.502 + 1.503 + static JSObject *getOrCreateLegacyGeneratorObjectPrototype(JSContext *cx, 1.504 + Handle<GlobalObject*> global) 1.505 + { 1.506 + if (!ensureConstructor(cx, global, JSProto_Iterator)) 1.507 + return nullptr; 1.508 + return &global->getSlot(LEGACY_GENERATOR_OBJECT_PROTO).toObject(); 1.509 + } 1.510 + 1.511 + static JSObject *getOrCreateStarGeneratorObjectPrototype(JSContext *cx, 1.512 + Handle<GlobalObject*> global) 1.513 + { 1.514 + if (!ensureConstructor(cx, global, JSProto_Iterator)) 1.515 + return nullptr; 1.516 + return &global->getSlot(STAR_GENERATOR_OBJECT_PROTO).toObject(); 1.517 + } 1.518 + 1.519 + static JSObject *getOrCreateStarGeneratorFunctionPrototype(JSContext *cx, 1.520 + Handle<GlobalObject*> global) 1.521 + { 1.522 + if (!ensureConstructor(cx, global, JSProto_Iterator)) 1.523 + return nullptr; 1.524 + return &global->getSlot(APPLICATION_SLOTS + JSProto_LIMIT + JSProto_GeneratorFunction).toObject(); 1.525 + } 1.526 + 1.527 + static JSObject *getOrCreateStarGeneratorFunction(JSContext *cx, 1.528 + Handle<GlobalObject*> global) 1.529 + { 1.530 + if (!ensureConstructor(cx, global, JSProto_Iterator)) 1.531 + return nullptr; 1.532 + return &global->getSlot(APPLICATION_SLOTS + JSProto_GeneratorFunction).toObject(); 1.533 + } 1.534 + 1.535 + static JSObject *getOrCreateMapIteratorPrototype(JSContext *cx, 1.536 + Handle<GlobalObject*> global) 1.537 + { 1.538 + return global->getOrCreateObject(cx, MAP_ITERATOR_PROTO, initMapIteratorProto); 1.539 + } 1.540 + 1.541 + static JSObject *getOrCreateSetIteratorPrototype(JSContext *cx, 1.542 + Handle<GlobalObject*> global) 1.543 + { 1.544 + return global->getOrCreateObject(cx, SET_ITERATOR_PROTO, initSetIteratorProto); 1.545 + } 1.546 + 1.547 + JSObject *getOrCreateDataViewPrototype(JSContext *cx) { 1.548 + Rooted<GlobalObject*> self(cx, this); 1.549 + if (!ensureConstructor(cx, self, JSProto_DataView)) 1.550 + return nullptr; 1.551 + return &self->getPrototype(JSProto_DataView).toObject(); 1.552 + } 1.553 + 1.554 + JSObject *intrinsicsHolder() { 1.555 + JS_ASSERT(!getSlot(INTRINSICS).isUndefined()); 1.556 + return &getSlot(INTRINSICS).toObject(); 1.557 + } 1.558 + 1.559 + bool maybeGetIntrinsicValue(jsid id, Value *vp) { 1.560 + JSObject *holder = intrinsicsHolder(); 1.561 + 1.562 + if (Shape *shape = holder->nativeLookupPure(id)) { 1.563 + *vp = holder->getSlot(shape->slot()); 1.564 + return true; 1.565 + } 1.566 + return false; 1.567 + } 1.568 + bool maybeGetIntrinsicValue(PropertyName *name, Value *vp) { 1.569 + return maybeGetIntrinsicValue(NameToId(name), vp); 1.570 + } 1.571 + 1.572 + static bool getIntrinsicValue(JSContext *cx, Handle<GlobalObject*> global, 1.573 + HandlePropertyName name, MutableHandleValue value) 1.574 + { 1.575 + if (global->maybeGetIntrinsicValue(name, value.address())) 1.576 + return true; 1.577 + if (!cx->runtime()->cloneSelfHostedValue(cx, name, value)) 1.578 + return false; 1.579 + RootedId id(cx, NameToId(name)); 1.580 + return global->addIntrinsicValue(cx, id, value); 1.581 + } 1.582 + 1.583 + bool addIntrinsicValue(JSContext *cx, HandleId id, HandleValue value); 1.584 + 1.585 + bool setIntrinsicValue(JSContext *cx, PropertyName *name, HandleValue value) { 1.586 +#ifdef DEBUG 1.587 + RootedObject self(cx, this); 1.588 + JS_ASSERT(cx->runtime()->isSelfHostingGlobal(self)); 1.589 +#endif 1.590 + RootedObject holder(cx, intrinsicsHolder()); 1.591 + RootedValue valCopy(cx, value); 1.592 + return JSObject::setProperty(cx, holder, holder, name, &valCopy, false); 1.593 + } 1.594 + 1.595 + bool getSelfHostedFunction(JSContext *cx, HandleAtom selfHostedName, HandleAtom name, 1.596 + unsigned nargs, MutableHandleValue funVal); 1.597 + 1.598 + RegExpStatics *getRegExpStatics() const { 1.599 + JSObject &resObj = getSlot(REGEXP_STATICS).toObject(); 1.600 + return static_cast<RegExpStatics *>(resObj.getPrivate(/* nfixed = */ 1)); 1.601 + } 1.602 + 1.603 + JSObject *getThrowTypeError() const { 1.604 + JS_ASSERT(functionObjectClassesInitialized()); 1.605 + return &getSlot(THROWTYPEERROR).toObject(); 1.606 + } 1.607 + 1.608 + Value createDataViewForThis() const { 1.609 + JS_ASSERT(dataViewClassInitialized()); 1.610 + return getSlot(CREATE_DATAVIEW_FOR_THIS); 1.611 + } 1.612 + 1.613 + template<typename T> 1.614 + inline Value createArrayFromBuffer() const; 1.615 + 1.616 + Value protoGetter() const { 1.617 + JS_ASSERT(functionObjectClassesInitialized()); 1.618 + return getSlot(PROTO_GETTER); 1.619 + } 1.620 + 1.621 + static bool isRuntimeCodeGenEnabled(JSContext *cx, Handle<GlobalObject*> global); 1.622 + 1.623 + // Warn about use of the deprecated watch/unwatch functions in the global 1.624 + // in which |obj| was created, if no prior warning was given. 1.625 + static bool warnOnceAboutWatch(JSContext *cx, HandleObject obj) { 1.626 + // Temporarily disabled until we've provided a watch/unwatch workaround for 1.627 + // debuggers like Firebug (bug 934669). 1.628 + //return warnOnceAbout(cx, obj, WARNED_WATCH_DEPRECATED, JSMSG_OBJECT_WATCH_DEPRECATED); 1.629 + return true; 1.630 + } 1.631 + 1.632 + // Warn about use of the given __proto__ setter to attempt to mutate an 1.633 + // object's [[Prototype]], if no prior warning was given. 1.634 + static bool warnOnceAboutPrototypeMutation(JSContext *cx, HandleObject protoSetter) { 1.635 + return warnOnceAbout(cx, protoSetter, WARNED_PROTO_SETTING_SLOW, JSMSG_PROTO_SETTING_SLOW); 1.636 + } 1.637 + 1.638 + static bool getOrCreateEval(JSContext *cx, Handle<GlobalObject*> global, 1.639 + MutableHandleObject eval); 1.640 + 1.641 + // Infallibly test whether the given value is the eval function for this global. 1.642 + bool valueIsEval(Value val); 1.643 + 1.644 + // Implemented in jsiter.cpp. 1.645 + static bool initIteratorClasses(JSContext *cx, Handle<GlobalObject*> global); 1.646 + 1.647 + // Implemented in builtin/MapObject.cpp. 1.648 + static bool initMapIteratorProto(JSContext *cx, Handle<GlobalObject*> global); 1.649 + static bool initSetIteratorProto(JSContext *cx, Handle<GlobalObject*> global); 1.650 + 1.651 + // Implemented in Intl.cpp. 1.652 + static bool initIntlObject(JSContext *cx, Handle<GlobalObject*> global); 1.653 + static bool initCollatorProto(JSContext *cx, Handle<GlobalObject*> global); 1.654 + static bool initNumberFormatProto(JSContext *cx, Handle<GlobalObject*> global); 1.655 + static bool initDateTimeFormatProto(JSContext *cx, Handle<GlobalObject*> global); 1.656 + 1.657 + // Implemented in builtin/TypedObject.cpp 1.658 + static bool initTypedObjectModule(JSContext *cx, Handle<GlobalObject*> global); 1.659 + 1.660 + static bool initStandardClasses(JSContext *cx, Handle<GlobalObject*> global); 1.661 + 1.662 + typedef js::Vector<js::Debugger *, 0, js::SystemAllocPolicy> DebuggerVector; 1.663 + 1.664 + /* 1.665 + * The collection of Debugger objects debugging this global. If this global 1.666 + * is not a debuggee, this returns either nullptr or an empty vector. 1.667 + */ 1.668 + DebuggerVector *getDebuggers(); 1.669 + 1.670 + /* 1.671 + * The same, but create the empty vector if one does not already 1.672 + * exist. Returns nullptr only on OOM. 1.673 + */ 1.674 + static DebuggerVector *getOrCreateDebuggers(JSContext *cx, Handle<GlobalObject*> global); 1.675 + 1.676 + inline JSObject *getForOfPICObject() { 1.677 + Value forOfPIC = getReservedSlot(FOR_OF_PIC_CHAIN); 1.678 + if (forOfPIC.isUndefined()) 1.679 + return nullptr; 1.680 + return &forOfPIC.toObject(); 1.681 + } 1.682 + static JSObject *getOrCreateForOfPICObject(JSContext *cx, Handle<GlobalObject*> global); 1.683 + 1.684 + static bool addDebugger(JSContext *cx, Handle<GlobalObject*> global, Debugger *dbg); 1.685 +}; 1.686 + 1.687 +template<> 1.688 +inline void 1.689 +GlobalObject::setCreateArrayFromBuffer<uint8_t>(Handle<JSFunction*> fun) 1.690 +{ 1.691 + setCreateArrayFromBufferHelper(FROM_BUFFER_UINT8, fun); 1.692 +} 1.693 + 1.694 +template<> 1.695 +inline void 1.696 +GlobalObject::setCreateArrayFromBuffer<int8_t>(Handle<JSFunction*> fun) 1.697 +{ 1.698 + setCreateArrayFromBufferHelper(FROM_BUFFER_INT8, fun); 1.699 +} 1.700 + 1.701 +template<> 1.702 +inline void 1.703 +GlobalObject::setCreateArrayFromBuffer<uint16_t>(Handle<JSFunction*> fun) 1.704 +{ 1.705 + setCreateArrayFromBufferHelper(FROM_BUFFER_UINT16, fun); 1.706 +} 1.707 + 1.708 +template<> 1.709 +inline void 1.710 +GlobalObject::setCreateArrayFromBuffer<int16_t>(Handle<JSFunction*> fun) 1.711 +{ 1.712 + setCreateArrayFromBufferHelper(FROM_BUFFER_INT16, fun); 1.713 +} 1.714 + 1.715 +template<> 1.716 +inline void 1.717 +GlobalObject::setCreateArrayFromBuffer<uint32_t>(Handle<JSFunction*> fun) 1.718 +{ 1.719 + setCreateArrayFromBufferHelper(FROM_BUFFER_UINT32, fun); 1.720 +} 1.721 + 1.722 +template<> 1.723 +inline void 1.724 +GlobalObject::setCreateArrayFromBuffer<int32_t>(Handle<JSFunction*> fun) 1.725 +{ 1.726 + setCreateArrayFromBufferHelper(FROM_BUFFER_INT32, fun); 1.727 +} 1.728 + 1.729 +template<> 1.730 +inline void 1.731 +GlobalObject::setCreateArrayFromBuffer<float>(Handle<JSFunction*> fun) 1.732 +{ 1.733 + setCreateArrayFromBufferHelper(FROM_BUFFER_FLOAT32, fun); 1.734 +} 1.735 + 1.736 +template<> 1.737 +inline void 1.738 +GlobalObject::setCreateArrayFromBuffer<double>(Handle<JSFunction*> fun) 1.739 +{ 1.740 + setCreateArrayFromBufferHelper(FROM_BUFFER_FLOAT64, fun); 1.741 +} 1.742 + 1.743 +template<> 1.744 +inline void 1.745 +GlobalObject::setCreateArrayFromBuffer<uint8_clamped>(Handle<JSFunction*> fun) 1.746 +{ 1.747 + setCreateArrayFromBufferHelper(FROM_BUFFER_UINT8CLAMPED, fun); 1.748 +} 1.749 + 1.750 +template<> 1.751 +inline Value 1.752 +GlobalObject::createArrayFromBuffer<uint8_t>() const 1.753 +{ 1.754 + return createArrayFromBufferHelper(FROM_BUFFER_UINT8); 1.755 +} 1.756 + 1.757 +template<> 1.758 +inline Value 1.759 +GlobalObject::createArrayFromBuffer<int8_t>() const 1.760 +{ 1.761 + return createArrayFromBufferHelper(FROM_BUFFER_INT8); 1.762 +} 1.763 + 1.764 +template<> 1.765 +inline Value 1.766 +GlobalObject::createArrayFromBuffer<uint16_t>() const 1.767 +{ 1.768 + return createArrayFromBufferHelper(FROM_BUFFER_UINT16); 1.769 +} 1.770 + 1.771 +template<> 1.772 +inline Value 1.773 +GlobalObject::createArrayFromBuffer<int16_t>() const 1.774 +{ 1.775 + return createArrayFromBufferHelper(FROM_BUFFER_INT16); 1.776 +} 1.777 + 1.778 +template<> 1.779 +inline Value 1.780 +GlobalObject::createArrayFromBuffer<uint32_t>() const 1.781 +{ 1.782 + return createArrayFromBufferHelper(FROM_BUFFER_UINT32); 1.783 +} 1.784 + 1.785 +template<> 1.786 +inline Value 1.787 +GlobalObject::createArrayFromBuffer<int32_t>() const 1.788 +{ 1.789 + return createArrayFromBufferHelper(FROM_BUFFER_INT32); 1.790 +} 1.791 + 1.792 +template<> 1.793 +inline Value 1.794 +GlobalObject::createArrayFromBuffer<float>() const 1.795 +{ 1.796 + return createArrayFromBufferHelper(FROM_BUFFER_FLOAT32); 1.797 +} 1.798 + 1.799 +template<> 1.800 +inline Value 1.801 +GlobalObject::createArrayFromBuffer<double>() const 1.802 +{ 1.803 + return createArrayFromBufferHelper(FROM_BUFFER_FLOAT64); 1.804 +} 1.805 + 1.806 +template<> 1.807 +inline Value 1.808 +GlobalObject::createArrayFromBuffer<uint8_clamped>() const 1.809 +{ 1.810 + return createArrayFromBufferHelper(FROM_BUFFER_UINT8CLAMPED); 1.811 +} 1.812 + 1.813 +/* 1.814 + * Define ctor.prototype = proto as non-enumerable, non-configurable, and 1.815 + * non-writable; define proto.constructor = ctor as non-enumerable but 1.816 + * configurable and writable. 1.817 + */ 1.818 +extern bool 1.819 +LinkConstructorAndPrototype(JSContext *cx, JSObject *ctor, JSObject *proto); 1.820 + 1.821 +/* 1.822 + * Define properties, then functions, on the object, then brand for tracing 1.823 + * benefits. 1.824 + */ 1.825 +extern bool 1.826 +DefinePropertiesAndBrand(JSContext *cx, JSObject *obj, 1.827 + const JSPropertySpec *ps, const JSFunctionSpec *fs); 1.828 + 1.829 +typedef HashSet<GlobalObject *, DefaultHasher<GlobalObject *>, SystemAllocPolicy> GlobalObjectSet; 1.830 + 1.831 +/* 1.832 + * Convenience templates to generic constructor and prototype creation functions 1.833 + * for ClassSpecs. 1.834 + */ 1.835 + 1.836 +template<JSNative ctor, size_t atomOffset, unsigned length> 1.837 +JSObject * 1.838 +GenericCreateConstructor(JSContext *cx, JSProtoKey key) 1.839 +{ 1.840 + JSAtom *atom = AtomStateOffsetToName(cx->names(), atomOffset); 1.841 + return cx->global()->createConstructor(cx, ctor, atom, length); 1.842 +} 1.843 + 1.844 +template<const Class *clasp> 1.845 +JSObject * 1.846 +GenericCreatePrototype(JSContext *cx, JSProtoKey key) 1.847 +{ 1.848 + return cx->global()->createBlankPrototype(cx, clasp); 1.849 +} 1.850 + 1.851 +} // namespace js 1.852 + 1.853 +template<> 1.854 +inline bool 1.855 +JSObject::is<js::GlobalObject>() const 1.856 +{ 1.857 + return !!(getClass()->flags & JSCLASS_IS_GLOBAL); 1.858 +} 1.859 + 1.860 +#endif /* vm_GlobalObject_h */