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/. */
10 #include "js/shadow/Realm.h" // JS::shadow::Realm
12 #include "js/GCPolicyAPI.h"
13 #include "js/TypeDecls.h" // forward-declaration of JS::Realm
15 /************************************************************************/
19 // Data associated with a global object. In the browser each frame has its
24 JS_PUBLIC_API
void TraceRealm(JSTracer
* trc
, JS::Realm
* realm
,
30 class JS_PUBLIC_API AutoRequireNoGC
;
32 // Each Realm holds a weak reference to its GlobalObject.
34 struct GCPolicy
<Realm
*> : public NonGCPointerPolicy
<Realm
*> {
35 static void trace(JSTracer
* trc
, Realm
** vp
, const char* name
) {
37 ::js::gc::TraceRealm(trc
, *vp
, name
);
42 // Get the current realm, if any. The ECMAScript spec calls this "the current
44 extern JS_PUBLIC_API Realm
* GetCurrentRealmOrNull(JSContext
* cx
);
46 // Return the compartment that contains a given realm.
47 inline JS::Compartment
* GetCompartmentForRealm(Realm
* realm
) {
48 return shadow::Realm::get(realm
)->compartment();
51 // Return an object's realm. All objects except cross-compartment wrappers are
52 // created in a particular realm, which never changes. Returns null if obj is
53 // a cross-compartment wrapper.
54 extern JS_PUBLIC_API Realm
* GetObjectRealmOrNull(JSObject
* obj
);
56 // Get the value of the "private data" internal field of the given Realm.
57 // This field is initially null and is set using SetRealmPrivate.
58 // It's a pointer to embeddding-specific data that SpiderMonkey never uses.
59 extern JS_PUBLIC_API
void* GetRealmPrivate(Realm
* realm
);
61 // Set the "private data" internal field of the given Realm.
62 extern JS_PUBLIC_API
void SetRealmPrivate(Realm
* realm
, void* data
);
64 typedef void (*DestroyRealmCallback
)(JSFreeOp
* fop
, Realm
* realm
);
66 // Set the callback SpiderMonkey calls just before garbage-collecting a realm.
67 // Embeddings can use this callback to free private data associated with the
68 // realm via SetRealmPrivate.
70 // By the time this is called, the global object for the realm has already been
72 extern JS_PUBLIC_API
void SetDestroyRealmCallback(
73 JSContext
* cx
, DestroyRealmCallback callback
);
75 using RealmNameCallback
= void (*)(JSContext
* cx
, Realm
* realm
, char* buf
,
77 const JS::AutoRequireNoGC
& nogc
);
79 // Set the callback SpiderMonkey calls to get the name of a realm, for
81 extern JS_PUBLIC_API
void SetRealmNameCallback(JSContext
* cx
,
82 RealmNameCallback callback
);
84 // Get the global object for the given realm. This only returns nullptr during
85 // GC, between collecting the global object and destroying the Realm.
86 extern JS_PUBLIC_API JSObject
* GetRealmGlobalOrNull(Realm
* realm
);
88 // Initialize standard JS class constructors, prototypes, and any top-level
89 // functions and constants associated with the standard classes (e.g. isNaN
91 extern JS_PUBLIC_API
bool InitRealmStandardClasses(JSContext
* cx
);
94 * Ways to get various per-Realm objects. All the getters declared below operate
95 * on the JSContext's current Realm.
98 extern JS_PUBLIC_API JSObject
* GetRealmObjectPrototype(JSContext
* cx
);
100 extern JS_PUBLIC_API JSObject
* GetRealmFunctionPrototype(JSContext
* cx
);
102 extern JS_PUBLIC_API JSObject
* GetRealmArrayPrototype(JSContext
* cx
);
104 extern JS_PUBLIC_API JSObject
* GetRealmErrorPrototype(JSContext
* cx
);
106 extern JS_PUBLIC_API JSObject
* GetRealmIteratorPrototype(JSContext
* cx
);
108 // Returns an object that represents the realm, that can be referred from
109 // other realm/compartment.
110 // See the consumer in `MaybeCrossOriginObjectMixins::EnsureHolder` for details.
111 extern JS_PUBLIC_API JSObject
* GetRealmKeyObject(JSContext
* cx
);
113 // Implements https://tc39.github.io/ecma262/#sec-getfunctionrealm
114 // 7.3.22 GetFunctionRealm ( obj )
116 // WARNING: may return a realm in a different compartment!
118 // Will throw an exception and return nullptr when a security wrapper or revoked
119 // proxy is encountered.
120 extern JS_PUBLIC_API Realm
* GetFunctionRealm(JSContext
* cx
,
121 HandleObject objArg
);
123 /** NB: This API is infallible; a nullptr return value does not indicate error.
125 * |target| must not be a cross-compartment wrapper because CCWs are not
126 * associated with a single realm.
128 * Entering a realm roots the realm and its global object until the matching
129 * JS::LeaveRealm() call.
131 extern JS_PUBLIC_API
JS::Realm
* EnterRealm(JSContext
* cx
, JSObject
* target
);
133 extern JS_PUBLIC_API
void LeaveRealm(JSContext
* cx
, JS::Realm
* oldRealm
);
138 * At any time, a JSContext has a current (possibly-nullptr) realm. The
139 * preferred way to change the current realm is with JSAutoRealm:
141 * void foo(JSContext* cx, JSObject* obj) {
142 * // in some realm 'r'
144 * JSAutoRealm ar(cx, obj); // constructor enters
145 * // in the realm of 'obj'
146 * } // destructor leaves
147 * // back in realm 'r'
150 * The object passed to JSAutoRealm must *not* be a cross-compartment wrapper,
151 * because CCWs are not associated with a single realm.
153 * For more complicated uses that don't neatly fit in a C++ stack frame, the
154 * realm can be entered and left using separate function calls:
156 * void foo(JSContext* cx, JSObject* obj) {
158 * JS::Realm* oldRealm = JS::EnterRealm(cx, obj);
159 * // in the realm of 'obj'
160 * JS::LeaveRealm(cx, oldRealm);
161 * // back in 'oldRealm'
164 * Note: these calls must still execute in a LIFO manner w.r.t all other
165 * enter/leave calls on the context. Furthermore, only the return value of a
166 * JS::EnterRealm call may be passed as the 'oldRealm' argument of
167 * the corresponding JS::LeaveRealm call.
169 * Entering a realm roots the realm and its global object for the lifetime of
173 class MOZ_RAII JS_PUBLIC_API JSAutoRealm
{
175 JS::Realm
* oldRealm_
;
178 JSAutoRealm(JSContext
* cx
, JSObject
* target
);
179 JSAutoRealm(JSContext
* cx
, JSScript
* target
);
183 class MOZ_RAII JS_PUBLIC_API JSAutoNullableRealm
{
185 JS::Realm
* oldRealm_
;
188 explicit JSAutoNullableRealm(JSContext
* cx
, JSObject
* targetOrNull
);
189 ~JSAutoNullableRealm();