no bug - Import translations from android-l10n r=release a=l10n CLOSED TREE
[gecko.git] / js / src / vm / GlobalObject.cpp
bloba91a44fa6823add880e0f157d74644090f600570
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 * vim: set ts=8 sts=2 et sw=2 tw=80:
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 #include "vm/GlobalObject.h"
9 #include "jsapi.h"
10 #include "jsfriendapi.h"
12 #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT
13 # include "builtin/AsyncDisposableStackObject.h"
14 #endif
15 #include "builtin/AtomicsObject.h"
16 #include "builtin/BigInt.h"
17 #include "builtin/DataViewObject.h"
18 #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT
19 # include "builtin/DisposableStackObject.h"
20 #endif
21 #ifdef JS_HAS_INTL_API
22 # include "builtin/intl/Collator.h"
23 # include "builtin/intl/DateTimeFormat.h"
24 # include "builtin/intl/DisplayNames.h"
25 # include "builtin/intl/ListFormat.h"
26 # include "builtin/intl/Locale.h"
27 # include "builtin/intl/NumberFormat.h"
28 # include "builtin/intl/PluralRules.h"
29 # include "builtin/intl/RelativeTimeFormat.h"
30 # include "builtin/intl/Segmenter.h"
31 #endif
32 #include "builtin/FinalizationRegistryObject.h"
33 #include "builtin/MapObject.h"
34 #include "builtin/ShadowRealm.h"
35 #include "builtin/Symbol.h"
36 #ifdef JS_HAS_TEMPORAL_API
37 # include "builtin/temporal/Duration.h"
38 # include "builtin/temporal/Instant.h"
39 # include "builtin/temporal/PlainDate.h"
40 # include "builtin/temporal/PlainDateTime.h"
41 # include "builtin/temporal/PlainMonthDay.h"
42 # include "builtin/temporal/PlainTime.h"
43 # include "builtin/temporal/PlainYearMonth.h"
44 # include "builtin/temporal/Temporal.h"
45 # include "builtin/temporal/TemporalNow.h"
46 # include "builtin/temporal/ZonedDateTime.h"
47 #endif
48 #include "builtin/WeakMapObject.h"
49 #include "builtin/WeakRefObject.h"
50 #include "builtin/WeakSetObject.h"
51 #include "debugger/DebugAPI.h"
52 #include "frontend/CompilationStencil.h"
53 #include "gc/FinalizationObservers.h"
54 #include "gc/GC.h"
55 #include "gc/GCContext.h"
56 #include "js/friend/ErrorMessages.h" // js::GetErrorMessage, JSMSG_*
57 #include "js/friend/WindowProxy.h" // js::ToWindowProxyIfWindow
58 #include "js/Prefs.h" // JS::Prefs
59 #include "js/PropertyAndElement.h" // JS_DefineFunctions, JS_DefineProperties
60 #include "js/ProtoKey.h"
61 #include "vm/AsyncFunction.h"
62 #include "vm/AsyncIteration.h"
63 #include "vm/BooleanObject.h"
64 #include "vm/Compartment.h"
65 #include "vm/DateObject.h"
66 #include "vm/EnvironmentObject.h"
67 #include "vm/ErrorObject.h"
68 #include "vm/GeneratorObject.h"
69 #include "vm/JSContext.h"
70 #include "vm/NumberObject.h"
71 #include "vm/PIC.h"
72 #include "vm/PlainObject.h"
73 #include "vm/RegExpObject.h"
74 #include "vm/RegExpStatics.h"
75 #include "vm/SelfHosting.h"
76 #include "vm/StringObject.h"
77 #include "wasm/WasmFeatures.h"
78 #include "wasm/WasmJS.h"
79 #ifdef ENABLE_RECORD_TUPLE
80 # include "vm/RecordType.h"
81 # include "vm/TupleType.h"
82 #endif
84 #include "gc/GCContext-inl.h"
85 #include "vm/JSObject-inl.h"
86 #include "vm/Realm-inl.h"
88 using namespace js;
90 namespace js {
92 extern const JSClass IntlClass;
93 extern const JSClass JSONClass;
94 extern const JSClass MathClass;
95 extern const JSClass ReflectClass;
97 } // namespace js
99 static constexpr const JSClass* const protoTable[JSProto_LIMIT] = {
100 #define INIT_FUNC(name, clasp) clasp,
101 #define INIT_FUNC_DUMMY(name, clasp) nullptr,
102 JS_FOR_PROTOTYPES(INIT_FUNC, INIT_FUNC_DUMMY)
103 #undef INIT_FUNC_DUMMY
104 #undef INIT_FUNC
107 JS_PUBLIC_API const JSClass* js::ProtoKeyToClass(JSProtoKey key) {
108 MOZ_ASSERT(key < JSProto_LIMIT);
109 return protoTable[key];
112 static bool IsAsyncIteratorHelpersEnabled() {
113 #ifdef NIGHTLY_BUILD
114 return JS::Prefs::experimental_async_iterator_helpers();
115 #else
116 return false;
117 #endif
120 /* static */
121 bool GlobalObject::skipDeselectedConstructor(JSContext* cx, JSProtoKey key) {
122 switch (key) {
123 case JSProto_Null:
124 case JSProto_Object:
125 case JSProto_Function:
126 case JSProto_BoundFunction:
127 case JSProto_Array:
128 case JSProto_Boolean:
129 case JSProto_JSON:
130 case JSProto_Date:
131 case JSProto_Math:
132 case JSProto_Number:
133 case JSProto_String:
134 case JSProto_RegExp:
135 case JSProto_Error:
136 case JSProto_InternalError:
137 case JSProto_Iterator:
138 case JSProto_AggregateError:
139 #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT
140 case JSProto_SuppressedError:
141 case JSProto_DisposableStack:
142 case JSProto_AsyncDisposableStack:
143 #endif
144 case JSProto_EvalError:
145 case JSProto_RangeError:
146 case JSProto_ReferenceError:
147 case JSProto_SyntaxError:
148 case JSProto_TypeError:
149 case JSProto_URIError:
150 case JSProto_DebuggeeWouldRun:
151 case JSProto_CompileError:
152 case JSProto_LinkError:
153 case JSProto_RuntimeError:
154 case JSProto_ArrayBuffer:
155 case JSProto_Int8Array:
156 case JSProto_Uint8Array:
157 case JSProto_Int16Array:
158 case JSProto_Uint16Array:
159 case JSProto_Int32Array:
160 case JSProto_Uint32Array:
161 case JSProto_Float32Array:
162 case JSProto_Float64Array:
163 case JSProto_Uint8ClampedArray:
164 case JSProto_BigInt64Array:
165 case JSProto_BigUint64Array:
166 case JSProto_BigInt:
167 case JSProto_Proxy:
168 case JSProto_WeakMap:
169 case JSProto_Map:
170 case JSProto_Set:
171 case JSProto_DataView:
172 case JSProto_Symbol:
173 case JSProto_Reflect:
174 case JSProto_WeakSet:
175 case JSProto_TypedArray:
176 case JSProto_SavedFrame:
177 case JSProto_Promise:
178 case JSProto_AsyncFunction:
179 case JSProto_GeneratorFunction:
180 case JSProto_AsyncGeneratorFunction:
181 #ifdef ENABLE_RECORD_TUPLE
182 case JSProto_Record:
183 case JSProto_Tuple:
184 #endif
185 return false;
187 case JSProto_WebAssembly:
188 return !wasm::HasSupport(cx);
190 case JSProto_WasmModule:
191 case JSProto_WasmInstance:
192 case JSProto_WasmMemory:
193 case JSProto_WasmTable:
194 case JSProto_WasmGlobal:
195 case JSProto_WasmTag:
196 #ifdef ENABLE_WASM_TYPE_REFLECTIONS
197 case JSProto_WasmFunction:
198 #endif
199 #ifdef ENABLE_WASM_JSPI
200 case JSProto_WasmSuspending:
201 #endif
202 case JSProto_WasmException:
203 return false;
205 #ifdef JS_HAS_INTL_API
206 case JSProto_Intl:
207 case JSProto_Collator:
208 case JSProto_DateTimeFormat:
209 case JSProto_DisplayNames:
210 case JSProto_Locale:
211 case JSProto_ListFormat:
212 case JSProto_NumberFormat:
213 case JSProto_PluralRules:
214 case JSProto_RelativeTimeFormat:
215 return false;
217 case JSProto_Segmenter:
218 # if defined(MOZ_ICU4X)
219 return false;
220 # else
221 return true;
222 # endif
223 #endif
225 #ifdef JS_HAS_TEMPORAL_API
226 case JSProto_Temporal:
227 case JSProto_Duration:
228 case JSProto_Instant:
229 case JSProto_PlainDate:
230 case JSProto_PlainDateTime:
231 case JSProto_PlainMonthDay:
232 case JSProto_PlainTime:
233 case JSProto_PlainYearMonth:
234 case JSProto_TemporalNow:
235 case JSProto_ZonedDateTime:
236 return false;
237 #endif
239 // Return true if the given constructor has been disabled at run-time.
240 case JSProto_Atomics:
241 case JSProto_SharedArrayBuffer:
242 return !cx->realm()->creationOptions().getSharedMemoryAndAtomicsEnabled();
244 case JSProto_WeakRef:
245 case JSProto_FinalizationRegistry:
246 return JS::GetWeakRefsEnabled() == JS::WeakRefSpecifier::Disabled;
248 case JSProto_AsyncIterator:
249 return !IsAsyncIteratorHelpersEnabled();
251 case JSProto_ShadowRealm:
252 return !JS::Prefs::experimental_shadow_realms();
254 case JSProto_Float16Array:
255 return !JS::Prefs::experimental_float16array();
257 default:
258 MOZ_CRASH("unexpected JSProtoKey");
262 static bool ShouldFreezeBuiltin(JSProtoKey key) {
263 // We can't freeze Reflect because JS_InitReflectParse defines Reflect.parse.
264 if (key == JSProto_Reflect) {
265 return false;
267 // We can't freeze Date because some browser tests use the Sinon library which
268 // redefines Date.now.
269 if (key == JSProto_Date) {
270 return false;
272 return true;
275 static unsigned GetAttrsForResolvedGlobal(GlobalObject* global,
276 JSProtoKey key) {
277 unsigned attrs = JSPROP_RESOLVING;
278 if (global->realm()->creationOptions().freezeBuiltins() &&
279 ShouldFreezeBuiltin(key)) {
280 attrs |= JSPROP_PERMANENT | JSPROP_READONLY;
282 return attrs;
285 /* static*/
286 bool GlobalObject::resolveConstructor(JSContext* cx,
287 Handle<GlobalObject*> global,
288 JSProtoKey key, IfClassIsDisabled mode) {
289 MOZ_ASSERT(key != JSProto_Null);
290 MOZ_ASSERT(key != JSProto_BoundFunction,
291 "bound functions don't have their own proto object");
292 MOZ_ASSERT(!global->isStandardClassResolved(key));
293 MOZ_ASSERT(cx->compartment() == global->compartment());
295 // |global| must be same-compartment but make sure we're in its realm: the
296 // code below relies on this.
297 AutoRealm ar(cx, global);
299 // Prohibit collection of allocation metadata. Metadata builders shouldn't
300 // need to observe lazily-constructed prototype objects coming into
301 // existence. And assertions start to fail when the builder itself attempts
302 // an allocation that re-entrantly tries to create the same prototype.
303 AutoSuppressAllocationMetadataBuilder suppressMetadata(cx);
305 // Constructor resolution may execute self-hosted scripts. These
306 // self-hosted scripts do not call out to user code by construction. Allow
307 // all scripts to execute, even in debuggee compartments that are paused.
308 AutoSuppressDebuggeeNoExecuteChecks suppressNX(cx);
310 // Some classes can be disabled at compile time, others at run time;
311 // if a feature is compile-time disabled, clasp is null.
312 const JSClass* clasp = ProtoKeyToClass(key);
313 if (!clasp || skipDeselectedConstructor(cx, key)) {
314 if (mode == IfClassIsDisabled::Throw) {
315 JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
316 JSMSG_CONSTRUCTOR_DISABLED,
317 clasp ? clasp->name : "constructor");
318 return false;
320 return true;
323 // Class spec must have a constructor defined.
324 if (!clasp->specDefined()) {
325 return true;
328 bool isObjectOrFunction = key == JSProto_Function || key == JSProto_Object;
330 // We need to create the prototype first, and immediately stash it in the
331 // slot. This is so the following bootstrap ordering is possible:
332 // * Object.prototype
333 // * Function.prototype
334 // * Function
335 // * Object
337 // We get the above when Object is resolved before Function. If Function
338 // is resolved before Object, we'll end up re-entering resolveConstructor
339 // for Function, which is a problem. So if Function is being resolved
340 // before Object.prototype exists, we just resolve Object instead, since we
341 // know that Function will also be resolved before we return.
342 if (key == JSProto_Function && !global->hasPrototype(JSProto_Object)) {
343 return resolveConstructor(cx, global, JSProto_Object,
344 IfClassIsDisabled::DoNothing);
347 // %IteratorPrototype%.map.[[Prototype]] is %Generator% and
348 // %Generator%.prototype.[[Prototype]] is %IteratorPrototype%.
349 if (key == JSProto_GeneratorFunction &&
350 !global->hasPrototype(JSProto_Iterator)) {
351 if (!getOrCreateIteratorPrototype(cx, global)) {
352 return false;
355 // If iterator helpers are enabled, populating %IteratorPrototype% will
356 // have recursively gone through here.
357 if (global->isStandardClassResolved(key)) {
358 return true;
362 // We don't always have a prototype (i.e. Math and JSON). If we don't,
363 // |createPrototype|, |prototypeFunctions|, and |prototypeProperties|
364 // should all be null.
365 RootedObject proto(cx);
366 if (ClassObjectCreationOp createPrototype =
367 clasp->specCreatePrototypeHook()) {
368 proto = createPrototype(cx, key);
369 if (!proto) {
370 return false;
373 if (isObjectOrFunction) {
374 // Make sure that creating the prototype didn't recursively resolve
375 // our own constructor. We can't just assert that there's no
376 // prototype; OOMs can result in incomplete resolutions in which
377 // the prototype is saved but not the constructor. So use the same
378 // criteria that protects entry into this function.
379 MOZ_ASSERT(!global->isStandardClassResolved(key));
381 global->setPrototype(key, proto);
385 // Create the constructor.
386 RootedObject ctor(cx, clasp->specCreateConstructorHook()(cx, key));
387 if (!ctor) {
388 return false;
391 RootedId id(cx, NameToId(ClassName(key, cx)));
392 if (isObjectOrFunction) {
393 if (clasp->specShouldDefineConstructor()) {
394 RootedValue ctorValue(cx, ObjectValue(*ctor));
395 unsigned attrs = GetAttrsForResolvedGlobal(global, key);
396 if (!DefineDataProperty(cx, global, id, ctorValue, attrs)) {
397 return false;
401 global->setConstructor(key, ctor);
404 if (const JSFunctionSpec* funs = clasp->specPrototypeFunctions()) {
405 if (!JS_DefineFunctions(cx, proto, funs)) {
406 return false;
409 if (const JSPropertySpec* props = clasp->specPrototypeProperties()) {
410 if (!JS_DefineProperties(cx, proto, props)) {
411 return false;
414 if (const JSFunctionSpec* funs = clasp->specConstructorFunctions()) {
415 if (!JS_DefineFunctions(cx, ctor, funs)) {
416 return false;
419 if (const JSPropertySpec* props = clasp->specConstructorProperties()) {
420 if (!JS_DefineProperties(cx, ctor, props)) {
421 return false;
425 // If the prototype exists, link it with the constructor.
426 if (proto && !LinkConstructorAndPrototype(cx, ctor, proto)) {
427 return false;
430 // Call the post-initialization hook, if provided.
431 if (FinishClassInitOp finishInit = clasp->specFinishInitHook()) {
432 if (!finishInit(cx, ctor, proto)) {
433 return false;
437 if (ShouldFreezeBuiltin(key)) {
438 if (!JS::MaybeFreezeCtorAndPrototype(cx, ctor, proto)) {
439 return false;
443 // If the prototype exists, mark the object as used as a prototype to enable
444 // Watchtower observation of protos which may not yet actually have an
445 // instance which yet uses it as a proto!
447 // You might well be asking: "Why not set IsUsedAsPrototype when constructing
448 // the proto object?". This ends up leading to a fair amount of complexity in
449 // how standard protos are linked together and the properties we want to
450 // enforce. Generally, it's fine if we don't watch for mutations on protos
451 // until they get exposed to user code.
452 if (proto && !JSObject::setFlag(cx, proto, ObjectFlag::IsUsedAsPrototype)) {
453 return false;
456 if (!isObjectOrFunction) {
457 // Any operations that modifies the global object should be placed
458 // after any other fallible operations.
460 // Fallible operation that modifies the global object.
461 if (clasp->specShouldDefineConstructor()) {
462 bool shouldReallyDefine = true;
464 // On the web, it isn't presently possible to expose the global
465 // "SharedArrayBuffer" property unless the page is cross-site-isolated.
466 // Only define this constructor if an option on the realm indicates that
467 // it should be defined.
468 if (key == JSProto_SharedArrayBuffer) {
469 const JS::RealmCreationOptions& options =
470 global->realm()->creationOptions();
472 MOZ_ASSERT(options.getSharedMemoryAndAtomicsEnabled(),
473 "shouldn't be defining SharedArrayBuffer if shared memory "
474 "is disabled");
476 shouldReallyDefine = options.defineSharedArrayBufferConstructor();
479 if (shouldReallyDefine) {
480 RootedValue ctorValue(cx, ObjectValue(*ctor));
481 unsigned attrs = GetAttrsForResolvedGlobal(global, key);
482 if (!DefineDataProperty(cx, global, id, ctorValue, attrs)) {
483 return false;
488 // Infallible operations that modify the global object.
489 global->setConstructor(key, ctor);
490 if (proto) {
491 global->setPrototype(key, proto);
495 return true;
498 // Resolve a "globalThis" self-referential property if necessary,
499 // per a stage-3 proposal. https://github.com/tc39/ecma262/pull/702
501 // We could also do this in |FinishObjectClassInit| to trim the global
502 // resolve hook. Unfortunately, |ToWindowProxyIfWindow| doesn't work then:
503 // the browser's |nsGlobalWindow::SetNewDocument| invokes Object init
504 // *before* it sets the global's WindowProxy using |js::SetWindowProxy|.
506 // Refactoring global object creation code to support this approach is a
507 // challenge for another day.
508 /* static */
509 bool GlobalObject::maybeResolveGlobalThis(JSContext* cx,
510 Handle<GlobalObject*> global,
511 bool* resolved) {
512 if (!global->data().globalThisResolved) {
513 RootedValue v(cx, ObjectValue(*ToWindowProxyIfWindow(global)));
514 if (!DefineDataProperty(cx, global, cx->names().globalThis, v,
515 JSPROP_RESOLVING)) {
516 return false;
519 *resolved = true;
520 global->data().globalThisResolved = true;
523 return true;
526 /* static */
527 JSObject* GlobalObject::createBuiltinProto(JSContext* cx,
528 Handle<GlobalObject*> global,
529 ProtoKind kind, ObjectInitOp init) {
530 if (!init(cx, global)) {
531 return nullptr;
534 return &global->getBuiltinProto(kind);
537 JSObject* GlobalObject::createBuiltinProto(JSContext* cx,
538 Handle<GlobalObject*> global,
539 ProtoKind kind, Handle<JSAtom*> tag,
540 ObjectInitWithTagOp init) {
541 if (!init(cx, global, tag)) {
542 return nullptr;
545 return &global->getBuiltinProto(kind);
548 static bool ThrowTypeError(JSContext* cx, unsigned argc, Value* vp) {
549 ThrowTypeErrorBehavior(cx);
550 return false;
553 /* static */
554 JSObject* GlobalObject::getOrCreateThrowTypeError(
555 JSContext* cx, Handle<GlobalObject*> global) {
556 if (JSFunction* fun = global->data().throwTypeError) {
557 return fun;
560 // Construct the unique [[%ThrowTypeError%]] function object, used only for
561 // "callee" and "caller" accessors on strict mode arguments objects. (The
562 // spec also uses this for "arguments" and "caller" on various functions,
563 // but we're experimenting with implementing them using accessors on
564 // |Function.prototype| right now.)
566 RootedFunction throwTypeError(
567 cx, NewNativeFunction(cx, ThrowTypeError, 0, nullptr));
568 if (!throwTypeError || !PreventExtensions(cx, throwTypeError)) {
569 return nullptr;
572 // The "length" property of %ThrowTypeError% is non-configurable.
573 Rooted<PropertyDescriptor> nonConfigurableDesc(cx,
574 PropertyDescriptor::Empty());
575 nonConfigurableDesc.setConfigurable(false);
577 RootedId lengthId(cx, NameToId(cx->names().length));
578 ObjectOpResult lengthResult;
579 if (!NativeDefineProperty(cx, throwTypeError, lengthId, nonConfigurableDesc,
580 lengthResult)) {
581 return nullptr;
583 MOZ_ASSERT(lengthResult);
585 // The "name" property of %ThrowTypeError% is non-configurable, adjust
586 // the default property attributes accordingly.
587 RootedId nameId(cx, NameToId(cx->names().name));
588 ObjectOpResult nameResult;
589 if (!NativeDefineProperty(cx, throwTypeError, nameId, nonConfigurableDesc,
590 nameResult)) {
591 return nullptr;
593 MOZ_ASSERT(nameResult);
595 global->data().throwTypeError.init(throwTypeError);
596 return throwTypeError;
599 GlobalObject* GlobalObject::createInternal(JSContext* cx,
600 const JSClass* clasp) {
601 MOZ_ASSERT(clasp->flags & JSCLASS_IS_GLOBAL);
602 MOZ_ASSERT(clasp->isTrace(JS_GlobalObjectTraceHook));
604 ObjectFlags objectFlags = {
605 ObjectFlag::QualifiedVarObj,
606 ObjectFlag::GenerationCountedGlobal,
609 JSObject* obj =
610 NewTenuredObjectWithGivenProto(cx, clasp, nullptr, objectFlags);
611 if (!obj) {
612 return nullptr;
615 Rooted<GlobalObject*> global(cx, &obj->as<GlobalObject>());
617 // Global holds both variables qualified with `var` and those that are not.
618 MOZ_ASSERT(global->isUnqualifiedVarObj());
619 MOZ_ASSERT(global->isQualifiedVarObj());
621 // Global objects support generation counts.
622 MOZ_ASSERT(global->isGenerationCountedGlobal());
625 auto data = cx->make_unique<GlobalObjectData>(cx->zone());
626 if (!data) {
627 return nullptr;
629 // Note: it's important for the realm's global to be initialized at the
630 // same time as the global's GlobalObjectData, because we free the global's
631 // data when Realm::global_ is cleared.
632 cx->realm()->initGlobal(*global);
633 InitReservedSlot(global, GLOBAL_DATA_SLOT, data.release(),
634 MemoryUse::GlobalObjectData);
637 Rooted<GlobalLexicalEnvironmentObject*> lexical(
638 cx, GlobalLexicalEnvironmentObject::create(cx, global));
639 if (!lexical) {
640 return nullptr;
642 global->data().lexicalEnvironment.init(lexical);
644 Rooted<GlobalScope*> emptyGlobalScope(
645 cx, GlobalScope::createEmpty(cx, ScopeKind::Global));
646 if (!emptyGlobalScope) {
647 return nullptr;
649 global->data().emptyGlobalScope.init(emptyGlobalScope);
651 if (!GlobalObject::createIntrinsicsHolder(cx, global)) {
652 return nullptr;
655 return global;
658 /* static */
659 GlobalObject* GlobalObject::new_(JSContext* cx, const JSClass* clasp,
660 JSPrincipals* principals,
661 JS::OnNewGlobalHookOption hookOption,
662 const JS::RealmOptions& options) {
663 MOZ_ASSERT(!cx->isExceptionPending());
664 MOZ_ASSERT_IF(cx->zone(), !cx->zone()->isAtomsZone());
666 // If we are creating a new global in an existing compartment, make sure the
667 // compartment has a live global at all times (by rooting it here).
668 // See bug 1530364.
669 Rooted<GlobalObject*> existingGlobal(cx);
670 const JS::RealmCreationOptions& creationOptions = options.creationOptions();
671 if (creationOptions.compartmentSpecifier() ==
672 JS::CompartmentSpecifier::ExistingCompartment) {
673 Compartment* comp = creationOptions.compartment();
674 existingGlobal = &comp->firstGlobal();
677 Realm* realm = NewRealm(cx, principals, options);
678 if (!realm) {
679 return nullptr;
682 Rooted<GlobalObject*> global(cx);
684 AutoRealmUnchecked ar(cx, realm);
685 global = GlobalObject::createInternal(cx, clasp);
686 if (!global) {
687 return nullptr;
690 // Make transactional initialization of these constructors by discarding the
691 // incompletely initialized global if an error occur. This also ensures the
692 // global's prototype chain is initialized (in FinishObjectClassInit).
693 if (!ensureConstructor(cx, global, JSProto_Object) ||
694 !ensureConstructor(cx, global, JSProto_Function)) {
695 return nullptr;
698 // Create a shape for plain objects with zero slots. This is required to be
699 // present in case allocating dynamic slots for objects fails, so we can
700 // leave a valid object in the heap.
701 if (!createPlainObjectShapeWithDefaultProto(cx, gc::AllocKind::OBJECT0)) {
702 return nullptr;
705 realm->clearInitializingGlobal();
706 if (hookOption == JS::FireOnNewGlobalHook) {
707 JS_FireOnNewGlobalObject(cx, global);
711 return global;
714 GlobalScope& GlobalObject::emptyGlobalScope() const {
715 return *data().emptyGlobalScope;
718 bool GlobalObject::valueIsEval(const Value& val) {
719 return val.isObject() && data().eval == &val.toObject();
722 /* static */
723 bool GlobalObject::initStandardClasses(JSContext* cx,
724 Handle<GlobalObject*> global) {
725 /* Define a top-level property 'undefined' with the undefined value. */
726 if (!DefineDataProperty(
727 cx, global, cx->names().undefined, UndefinedHandleValue,
728 JSPROP_PERMANENT | JSPROP_READONLY | JSPROP_RESOLVING)) {
729 return false;
732 // Resolve a "globalThis" self-referential property if necessary.
733 bool resolved;
734 if (!GlobalObject::maybeResolveGlobalThis(cx, global, &resolved)) {
735 return false;
738 for (size_t k = 0; k < JSProto_LIMIT; ++k) {
739 JSProtoKey key = static_cast<JSProtoKey>(k);
740 if (key != JSProto_Null && key != JSProto_BoundFunction &&
741 !global->isStandardClassResolved(key)) {
742 if (!resolveConstructor(cx, global, static_cast<JSProtoKey>(k),
743 IfClassIsDisabled::DoNothing)) {
744 return false;
748 return true;
751 /* static */
752 JSFunction* GlobalObject::createConstructor(JSContext* cx, Native ctor,
753 JSAtom* nameArg, unsigned length,
754 gc::AllocKind kind,
755 const JSJitInfo* jitInfo) {
756 Rooted<JSAtom*> name(cx, nameArg);
757 JSFunction* fun = NewNativeConstructor(cx, ctor, length, name, kind);
758 if (!fun) {
759 return nullptr;
762 if (jitInfo) {
763 fun->setJitInfo(jitInfo);
766 return fun;
769 static NativeObject* CreateBlankProto(JSContext* cx, const JSClass* clasp,
770 HandleObject proto,
771 ObjectFlags objFlags) {
772 MOZ_ASSERT(!clasp->isJSFunction());
774 if (clasp == &PlainObject::class_) {
775 // NOTE: There should be no reason currently to support this. It could
776 // however be added later if needed.
777 MOZ_ASSERT(objFlags.isEmpty());
778 return NewPlainObjectWithProto(cx, proto, TenuredObject);
781 return NewTenuredObjectWithGivenProto(cx, clasp, proto, objFlags);
784 /* static */
785 NativeObject* GlobalObject::createBlankPrototype(JSContext* cx,
786 Handle<GlobalObject*> global,
787 const JSClass* clasp,
788 ObjectFlags objFlags) {
789 RootedObject objectProto(cx, &global->getObjectPrototype());
790 return CreateBlankProto(cx, clasp, objectProto, objFlags);
793 /* static */
794 NativeObject* GlobalObject::createBlankPrototypeInheriting(JSContext* cx,
795 const JSClass* clasp,
796 HandleObject proto) {
797 return CreateBlankProto(cx, clasp, proto, ObjectFlags());
800 bool js::LinkConstructorAndPrototype(JSContext* cx, JSObject* ctor_,
801 JSObject* proto_, unsigned prototypeAttrs,
802 unsigned constructorAttrs) {
803 RootedObject ctor(cx, ctor_), proto(cx, proto_);
805 RootedValue protoVal(cx, ObjectValue(*proto));
806 RootedValue ctorVal(cx, ObjectValue(*ctor));
808 return DefineDataProperty(cx, ctor, cx->names().prototype, protoVal,
809 prototypeAttrs) &&
810 DefineDataProperty(cx, proto, cx->names().constructor, ctorVal,
811 constructorAttrs);
814 bool js::DefinePropertiesAndFunctions(JSContext* cx, HandleObject obj,
815 const JSPropertySpec* ps,
816 const JSFunctionSpec* fs) {
817 if (ps && !JS_DefineProperties(cx, obj, ps)) {
818 return false;
820 if (fs && !JS_DefineFunctions(cx, obj, fs)) {
821 return false;
823 return true;
826 bool js::DefineToStringTag(JSContext* cx, HandleObject obj, JSAtom* tag) {
827 RootedId toStringTagId(
828 cx, PropertyKey::Symbol(cx->wellKnownSymbols().toStringTag));
829 RootedValue tagString(cx, StringValue(tag));
830 return DefineDataProperty(cx, obj, toStringTagId, tagString, JSPROP_READONLY);
833 /* static */
834 NativeObject* GlobalObject::getOrCreateForOfPICObject(
835 JSContext* cx, Handle<GlobalObject*> global) {
836 cx->check(global);
837 NativeObject* forOfPIC = global->getForOfPICObject();
838 if (forOfPIC) {
839 return forOfPIC;
842 forOfPIC = ForOfPIC::createForOfPICObject(cx, global);
843 if (!forOfPIC) {
844 return nullptr;
846 global->data().forOfPICChain.init(forOfPIC);
847 return forOfPIC;
850 /* static */
851 JSObject* GlobalObject::getOrCreateRealmKeyObject(
852 JSContext* cx, Handle<GlobalObject*> global) {
853 cx->check(global);
854 if (PlainObject* key = global->data().realmKeyObject) {
855 return key;
858 PlainObject* key = NewPlainObject(cx);
859 if (!key) {
860 return nullptr;
863 global->data().realmKeyObject.init(key);
864 return key;
867 /* static */
868 RegExpStatics* GlobalObject::getRegExpStatics(JSContext* cx,
869 Handle<GlobalObject*> global) {
870 MOZ_ASSERT(cx);
872 if (!global->regExpRealm().regExpStatics) {
873 auto statics = RegExpStatics::create(cx);
874 if (!statics) {
875 return nullptr;
877 global->regExpRealm().regExpStatics = std::move(statics);
880 return global->regExpRealm().regExpStatics.get();
883 gc::FinalizationRegistryGlobalData*
884 GlobalObject::getOrCreateFinalizationRegistryData() {
885 if (!data().finalizationRegistryData) {
886 data().finalizationRegistryData =
887 MakeUnique<gc::FinalizationRegistryGlobalData>(zone());
890 return maybeFinalizationRegistryData();
893 #ifndef NIGHTLY_BUILD
894 bool GlobalObject::addToVarNames(JSContext* cx, JS::Handle<JSAtom*> name) {
895 MOZ_ASSERT(name);
897 if (!data().varNames.put(name)) {
898 ReportOutOfMemory(cx);
899 return false;
902 return true;
904 #endif
906 /* static */
907 bool GlobalObject::createIntrinsicsHolder(JSContext* cx,
908 Handle<GlobalObject*> global) {
909 Rooted<NativeObject*> intrinsicsHolder(
910 cx, NewPlainObjectWithProto(cx, nullptr, TenuredObject));
911 if (!intrinsicsHolder) {
912 return false;
915 // Install the intrinsics holder on the global.
916 global->data().intrinsicsHolder.init(intrinsicsHolder);
917 return true;
920 /* static */
921 bool GlobalObject::getSelfHostedFunction(JSContext* cx,
922 Handle<GlobalObject*> global,
923 Handle<PropertyName*> selfHostedName,
924 Handle<JSAtom*> name, unsigned nargs,
925 MutableHandleValue funVal) {
926 if (global->maybeGetIntrinsicValue(selfHostedName, funVal.address(), cx)) {
927 RootedFunction fun(cx, &funVal.toObject().as<JSFunction>());
928 if (fun->fullExplicitName() == name) {
929 return true;
932 if (fun->fullExplicitName() == selfHostedName) {
933 // This function was initially cloned because it was called by
934 // other self-hosted code, so the clone kept its self-hosted name,
935 // instead of getting the name it's intended to have in content
936 // compartments. This can happen when a lazy builtin is initialized
937 // after self-hosted code for another builtin used the same
938 // function. In that case, we need to change the function's name,
939 // which is ok because it can't have been exposed to content
940 // before.
941 fun->setAtom(name);
942 return true;
945 // The function might be installed multiple times on the same or
946 // different builtins, under different property names, so its name
947 // might be neither "selfHostedName" nor "name". In that case, its
948 // canonical name must've been set using the `_SetCanonicalName`
949 // intrinsic.
950 cx->runtime()->assertSelfHostedFunctionHasCanonicalName(selfHostedName);
951 return true;
954 // Don't collect metadata for self-hosted functions or intrinsics.
955 // This is similar to the suppression in GlobalObject::resolveConstructor.
956 AutoSuppressAllocationMetadataBuilder suppressMetadata(cx);
958 JSRuntime* runtime = cx->runtime();
959 frontend::ScriptIndex index =
960 runtime->getSelfHostedScriptIndexRange(selfHostedName)->start;
961 JSFunction* fun =
962 runtime->selfHostStencil().instantiateSelfHostedLazyFunction(
963 cx, runtime->selfHostStencilInput().atomCache, index, name);
964 if (!fun) {
965 return false;
967 MOZ_ASSERT(fun->nargs() == nargs);
968 funVal.setObject(*fun);
970 return GlobalObject::addIntrinsicValue(cx, global, selfHostedName, funVal);
973 /* static */
974 bool GlobalObject::getIntrinsicValueSlow(JSContext* cx,
975 Handle<GlobalObject*> global,
976 Handle<PropertyName*> name,
977 MutableHandleValue value) {
978 // Don't collect metadata for self-hosted functions or intrinsics.
979 // This is similar to the suppression in GlobalObject::resolveConstructor.
980 AutoSuppressAllocationMetadataBuilder suppressMetadata(cx);
982 // If this is a C++ intrinsic, simply define the function on the intrinsics
983 // holder.
984 if (const JSFunctionSpec* spec = js::FindIntrinsicSpec(name)) {
985 RootedId id(cx, NameToId(name));
986 RootedFunction fun(cx, JS::NewFunctionFromSpec(cx, spec, id));
987 if (!fun) {
988 return false;
990 fun->setIsIntrinsic();
992 value.setObject(*fun);
993 return GlobalObject::addIntrinsicValue(cx, global, name, value);
996 if (!cx->runtime()->getSelfHostedValue(cx, name, value)) {
997 return false;
1000 // It's possible in certain edge cases that cloning the value ended up
1001 // defining the intrinsic. For instance, cloning can call NewArray, which
1002 // resolves Array.prototype, which defines some self-hosted functions. If this
1003 // happens we use the value already defined on the intrinsics holder.
1004 if (global->maybeGetIntrinsicValue(name, value.address(), cx)) {
1005 return true;
1008 return GlobalObject::addIntrinsicValue(cx, global, name, value);
1011 /* static */
1012 bool GlobalObject::addIntrinsicValue(JSContext* cx,
1013 Handle<GlobalObject*> global,
1014 Handle<PropertyName*> name,
1015 HandleValue value) {
1016 Rooted<NativeObject*> holder(cx, &global->getIntrinsicsHolder());
1018 RootedId id(cx, NameToId(name));
1019 MOZ_ASSERT(!holder->containsPure(id));
1021 constexpr PropertyFlags propFlags = {PropertyFlag::Configurable,
1022 PropertyFlag::Writable};
1023 uint32_t slot;
1024 if (!NativeObject::addProperty(cx, holder, id, propFlags, &slot)) {
1025 return false;
1027 holder->initSlot(slot, value);
1028 return true;
1031 /* static */
1032 JSObject* GlobalObject::createIteratorPrototype(JSContext* cx,
1033 Handle<GlobalObject*> global) {
1034 if (!ensureConstructor(cx, global, JSProto_Iterator)) {
1035 return nullptr;
1037 JSObject* proto = &global->getPrototype(JSProto_Iterator);
1038 return proto;
1041 /* static */
1042 JSObject* GlobalObject::createAsyncIteratorPrototype(
1043 JSContext* cx, Handle<GlobalObject*> global) {
1044 if (!IsAsyncIteratorHelpersEnabled()) {
1045 return getOrCreateBuiltinProto(cx, global, ProtoKind::AsyncIteratorProto,
1046 initAsyncIteratorProto);
1049 if (!ensureConstructor(cx, global, JSProto_AsyncIterator)) {
1050 return nullptr;
1052 JSObject* proto = &global->getPrototype(JSProto_AsyncIterator);
1053 global->initBuiltinProto(ProtoKind::AsyncIteratorProto, proto);
1054 return proto;
1057 void GlobalObject::releaseData(JS::GCContext* gcx) {
1058 GlobalObjectData* data = maybeData();
1059 setReservedSlot(GLOBAL_DATA_SLOT, PrivateValue(nullptr));
1060 gcx->delete_(this, data, MemoryUse::GlobalObjectData);
1063 GlobalObjectData::GlobalObjectData(Zone* zone)
1064 #ifndef NIGHTLY_BUILD
1065 : varNames(zone)
1066 #endif
1070 GlobalObjectData::~GlobalObjectData() = default;
1072 void GlobalObjectData::trace(JSTracer* trc, GlobalObject* global) {
1073 #ifndef NIGHTLY_BUILD
1074 // Atoms are always tenured so don't need to be traced during minor GC.
1075 if (trc->runtime()->heapState() != JS::HeapState::MinorCollecting) {
1076 varNames.trace(trc);
1078 #endif
1080 for (auto& ctorWithProto : builtinConstructors) {
1081 TraceNullableEdge(trc, &ctorWithProto.constructor, "global-builtin-ctor");
1082 TraceNullableEdge(trc, &ctorWithProto.prototype,
1083 "global-builtin-ctor-proto");
1086 for (auto& proto : builtinProtos) {
1087 TraceNullableEdge(trc, &proto, "global-builtin-proto");
1090 TraceNullableEdge(trc, &emptyGlobalScope, "global-empty-scope");
1092 TraceNullableEdge(trc, &lexicalEnvironment, "global-lexical-env");
1093 TraceNullableEdge(trc, &windowProxy, "global-window-proxy");
1094 TraceNullableEdge(trc, &intrinsicsHolder, "global-intrinsics-holder");
1095 TraceNullableEdge(trc, &computedIntrinsicsHolder,
1096 "global-computed-intrinsics-holder");
1097 TraceNullableEdge(trc, &forOfPICChain, "global-for-of-pic");
1098 TraceNullableEdge(trc, &sourceURLsHolder, "global-source-urls");
1099 TraceNullableEdge(trc, &realmKeyObject, "global-realm-key");
1100 TraceNullableEdge(trc, &throwTypeError, "global-throw-type-error");
1101 TraceNullableEdge(trc, &eval, "global-eval");
1102 TraceNullableEdge(trc, &emptyIterator, "global-empty-iterator");
1104 TraceNullableEdge(trc, &arrayShapeWithDefaultProto, "global-array-shape");
1106 for (auto& shape : plainObjectShapesWithDefaultProto) {
1107 TraceNullableEdge(trc, &shape, "global-plain-shape");
1110 TraceNullableEdge(trc, &functionShapeWithDefaultProto,
1111 "global-function-shape");
1112 TraceNullableEdge(trc, &extendedFunctionShapeWithDefaultProto,
1113 "global-ext-function-shape");
1115 TraceNullableEdge(trc, &boundFunctionShapeWithDefaultProto,
1116 "global-bound-function-shape");
1118 regExpRealm.trace(trc);
1120 TraceNullableEdge(trc, &mappedArgumentsTemplate, "mapped-arguments-template");
1121 TraceNullableEdge(trc, &unmappedArgumentsTemplate,
1122 "unmapped-arguments-template");
1124 TraceNullableEdge(trc, &iterResultTemplate, "iter-result-template_");
1125 TraceNullableEdge(trc, &iterResultWithoutPrototypeTemplate,
1126 "iter-result-without-prototype-template");
1128 TraceNullableEdge(trc, &selfHostingScriptSource,
1129 "self-hosting-script-source");
1131 if (finalizationRegistryData) {
1132 finalizationRegistryData->trace(trc);
1136 void GlobalObjectData::addSizeOfIncludingThis(
1137 mozilla::MallocSizeOf mallocSizeOf, JS::ClassInfo* info) const {
1138 info->objectsMallocHeapGlobalData += mallocSizeOf(this);
1140 if (regExpRealm.regExpStatics) {
1141 info->objectsMallocHeapGlobalData +=
1142 regExpRealm.regExpStatics->sizeOfIncludingThis(mallocSizeOf);
1145 #ifndef NIGHTLY_BUILD
1146 info->objectsMallocHeapGlobalVarNamesSet +=
1147 varNames.shallowSizeOfExcludingThis(mallocSizeOf);
1148 #endif