js/src/vm/GlobalObject.h

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

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

mercurial