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