Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
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 */