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/. */
8 * Options specified when creating a realm to determine its behavior, immutable
9 * options determining the behavior of an existing realm, and mutable options on
10 * an existing realm that may be changed when desired.
13 #ifndef js_RealmOptions_h
14 #define js_RealmOptions_h
16 #include "mozilla/Assertions.h" // MOZ_ASSERT
17 #include "mozilla/Maybe.h"
19 #include "jstypes.h" // JS_PUBLIC_API
21 #include "js/Class.h" // JSTraceOp
22 #include "js/RefCounted.h"
24 struct JS_PUBLIC_API JSContext
;
25 class JS_PUBLIC_API JSObject
;
29 class JS_PUBLIC_API Compartment
;
30 class JS_PUBLIC_API Realm
;
31 class JS_PUBLIC_API Zone
;
38 * Specification for which compartment/zone a newly created realm should use.
40 enum class CompartmentSpecifier
{
41 // Create a new realm and compartment in the single runtime wide system
42 // zone. The meaning of this zone is left to the embedder.
43 NewCompartmentInSystemZone
,
45 // Create a new realm and compartment in a particular existing zone.
46 NewCompartmentInExistingZone
,
48 // Create a new zone/compartment.
49 NewCompartmentAndZone
,
51 // Create a new realm in an existing compartment.
55 struct LocaleString
: js::RefCounted
<LocaleString
> {
58 explicit LocaleString(const char* chars
) : chars_(chars
) {}
60 auto chars() const { return chars_
; }
64 * RealmCreationOptions specifies options relevant to creating a new realm, that
65 * are either immutable characteristics of that realm or that are discarded
66 * after the realm has been created.
68 * Access to these options on an existing realm is read-only: if you need
69 * particular selections, you must make them before you create the realm.
71 class JS_PUBLIC_API RealmCreationOptions
{
73 RealmCreationOptions() : comp_(nullptr) {}
75 JSTraceOp
getTrace() const { return traceGlobal_
; }
76 RealmCreationOptions
& setTrace(JSTraceOp op
) {
82 MOZ_ASSERT(compSpec_
== CompartmentSpecifier::NewCompartmentInExistingZone
);
85 Compartment
* compartment() const {
86 MOZ_ASSERT(compSpec_
== CompartmentSpecifier::ExistingCompartment
);
89 CompartmentSpecifier
compartmentSpecifier() const { return compSpec_
; }
91 // Set the compartment/zone to use for the realm. See CompartmentSpecifier
93 RealmCreationOptions
& setNewCompartmentInSystemZone();
94 RealmCreationOptions
& setNewCompartmentInExistingZone(JSObject
* obj
);
95 RealmCreationOptions
& setNewCompartmentAndZone();
96 RealmCreationOptions
& setExistingCompartment(JSObject
* obj
);
97 RealmCreationOptions
& setExistingCompartment(Compartment
* compartment
);
99 // Certain compartments are implementation details of the embedding, and
100 // references to them should never leak out to script. This flag causes this
101 // realm to skip firing onNewGlobalObject and makes addDebuggee a no-op for
104 // Debugger visibility is per-compartment, not per-realm (it's only practical
105 // to enforce visibility on compartment boundaries), so if a realm is being
106 // created in an extant compartment, its requested visibility must match that
107 // of the compartment.
108 bool invisibleToDebugger() const { return invisibleToDebugger_
; }
109 RealmCreationOptions
& setInvisibleToDebugger(bool flag
) {
110 invisibleToDebugger_
= flag
;
114 // Determines whether this realm should preserve JIT code on non-shrinking
116 bool preserveJitCode() const { return preserveJitCode_
; }
117 RealmCreationOptions
& setPreserveJitCode(bool flag
) {
118 preserveJitCode_
= flag
;
122 // Determines whether 1) the global Atomic property is defined and atomic
123 // operations are supported, and 2) whether shared-memory operations are
125 bool getSharedMemoryAndAtomicsEnabled() const;
126 RealmCreationOptions
& setSharedMemoryAndAtomicsEnabled(bool flag
);
128 // Determines (if getSharedMemoryAndAtomicsEnabled() is true) whether the
129 // global SharedArrayBuffer property is defined. If the property is not
130 // defined, shared array buffer functionality can only be invoked if the
131 // host/embedding specifically acts to expose it.
133 // This option defaults to true: embeddings unable to tolerate a global
134 // SharedAraryBuffer property must opt out of it.
135 bool defineSharedArrayBufferConstructor() const {
136 return defineSharedArrayBufferConstructor_
;
138 RealmCreationOptions
& setDefineSharedArrayBufferConstructor(bool flag
) {
139 defineSharedArrayBufferConstructor_
= flag
;
143 // Structured clone operations support the cloning of shared memory objects
144 // (SharedArrayBuffer or or a shared WASM Memory object) *optionally* -- at
145 // the discretion of the embedder code that performs the cloning. When a
146 // structured clone operation encounters a shared memory object and cloning
147 // shared memory objects has not been enabled, the clone fails and an
150 // In the web embedding context, shared memory object cloning is disabled
153 // 1) *no* way of supporting it is available (because the
154 // Cross-Origin-Opener-Policy and Cross-Origin-Embedder-Policy HTTP
155 // headers are not respected to force the page into its own process), or
156 // 2) the aforementioned HTTP headers don't specify that the page should be
157 // opened in its own process.
159 // These two scenarios demand different error messages, and this option can be
160 // used to specify which scenario is in play.
162 // In the former case, if COOP/COEP support is not enabled, set this option to
163 // false. (This is the default.)
165 // In the latter case, if COOP/COEP weren't used to force this page into its
166 // own process, set this option to true.
168 // (Embeddings that are not the web and do not wish to support structured
169 // cloning of shared memory objects will get a "bad" web-centric error message
170 // no matter what. At present, SpiderMonkey does not offer a way for such
171 // embeddings to use an embedding-specific error message.)
172 bool getCoopAndCoepEnabled() const;
173 RealmCreationOptions
& setCoopAndCoepEnabled(bool flag
);
175 bool getToSourceEnabled() const { return toSource_
; }
176 RealmCreationOptions
& setToSourceEnabled(bool flag
) {
181 // This flag doesn't affect JS engine behavior. It is used by Gecko to
182 // mark whether content windows and workers are "Secure Context"s. See
183 // https://w3c.github.io/webappsec-secure-contexts/
184 // https://bugzilla.mozilla.org/show_bug.cgi?id=1162772#c34
185 bool secureContext() const { return secureContext_
; }
186 RealmCreationOptions
& setSecureContext(bool flag
) {
187 secureContext_
= flag
;
191 // Non-standard option to freeze certain builtin constructors and seal their
192 // prototypes. Also defines these constructors on the global as non-writable
193 // and non-configurable.
194 bool freezeBuiltins() const { return freezeBuiltins_
; }
195 RealmCreationOptions
& setFreezeBuiltins(bool flag
) {
196 freezeBuiltins_
= flag
;
200 // Force all date/time methods in JavaScript to use the UTC timezone for
201 // fingerprinting protection.
202 bool forceUTC() const { return forceUTC_
; }
203 RealmCreationOptions
& setForceUTC(bool flag
) {
208 RefPtr
<LocaleString
> locale() const { return locale_
; }
209 RealmCreationOptions
& setLocaleCopyZ(const char* locale
);
211 // Always use the fdlibm implementation of math functions instead of the
212 // platform native libc implementations. Useful for fingerprinting protection
213 // and cross-platform consistency.
214 bool alwaysUseFdlibm() const { return alwaysUseFdlibm_
; }
215 RealmCreationOptions
& setAlwaysUseFdlibm(bool flag
) {
216 alwaysUseFdlibm_
= flag
;
220 uint64_t profilerRealmID() const { return profilerRealmID_
; }
221 RealmCreationOptions
& setProfilerRealmID(uint64_t id
) {
222 profilerRealmID_
= id
;
227 JSTraceOp traceGlobal_
= nullptr;
228 CompartmentSpecifier compSpec_
= CompartmentSpecifier::NewCompartmentAndZone
;
233 uint64_t profilerRealmID_
= 0;
234 RefPtr
<LocaleString
> locale_
;
235 bool invisibleToDebugger_
= false;
236 bool preserveJitCode_
= false;
237 bool sharedMemoryAndAtomics_
= false;
238 bool defineSharedArrayBufferConstructor_
= true;
239 bool coopAndCoep_
= false;
240 bool toSource_
= false;
242 bool secureContext_
= false;
243 bool freezeBuiltins_
= false;
244 bool forceUTC_
= false;
245 bool alwaysUseFdlibm_
= false;
248 // This is a wrapper for mozilla::RTPCallerType, that can't easily
249 // be exposed to the JS engine for layering reasons.
250 struct RTPCallerTypeToken
{
255 * RealmBehaviors specifies behaviors of a realm that can be changed after the
256 * realm's been created.
258 class JS_PUBLIC_API RealmBehaviors
{
260 RealmBehaviors() = default;
262 // When a JS::ReduceMicrosecondTimePrecisionCallback callback is defined via
263 // JS::SetReduceMicrosecondTimePrecisionCallback, a JS::RTPCallerTypeToken (a
264 // wrapper for mozilla::RTPCallerType) needs to be set for every Realm.
265 mozilla::Maybe
<RTPCallerTypeToken
> reduceTimerPrecisionCallerType() const {
266 return rtpCallerType
;
268 RealmBehaviors
& setReduceTimerPrecisionCallerType(RTPCallerTypeToken type
) {
269 rtpCallerType
= mozilla::Some(type
);
273 // For certain globals, we know enough about the code that will run in them
274 // that we can discard script source entirely.
275 bool discardSource() const { return discardSource_
; }
276 RealmBehaviors
& setDiscardSource(bool flag
) {
277 discardSource_
= flag
;
281 bool clampAndJitterTime() const { return clampAndJitterTime_
; }
282 RealmBehaviors
& setClampAndJitterTime(bool flag
) {
283 clampAndJitterTime_
= flag
;
287 // A Realm can stop being "live" in all the ways that matter before its global
288 // is actually GCed. Consumers that tear down parts of a Realm or its global
289 // before that point should set isNonLive accordingly.
290 bool isNonLive() const { return isNonLive_
; }
291 RealmBehaviors
& setNonLive() {
297 mozilla::Maybe
<RTPCallerTypeToken
> rtpCallerType
;
298 bool discardSource_
= false;
299 bool clampAndJitterTime_
= true;
300 bool isNonLive_
= false;
304 * RealmOptions specifies realm characteristics: both those that can't be
305 * changed on a realm once it's been created (RealmCreationOptions), and those
306 * that can be changed on an existing realm (RealmBehaviors).
308 class JS_PUBLIC_API RealmOptions
{
310 explicit RealmOptions() : creationOptions_(), behaviors_() {}
312 RealmOptions(const RealmCreationOptions
& realmCreation
,
313 const RealmBehaviors
& realmBehaviors
)
314 : creationOptions_(realmCreation
), behaviors_(realmBehaviors
) {}
316 // RealmCreationOptions specify fundamental realm characteristics that must
317 // be specified when the realm is created, that can't be changed after the
319 RealmCreationOptions
& creationOptions() { return creationOptions_
; }
320 const RealmCreationOptions
& creationOptions() const {
321 return creationOptions_
;
324 // RealmBehaviors specify realm characteristics that can be changed after
325 // the realm is created.
326 RealmBehaviors
& behaviors() { return behaviors_
; }
327 const RealmBehaviors
& behaviors() const { return behaviors_
; }
330 RealmCreationOptions creationOptions_
;
331 RealmBehaviors behaviors_
;
334 extern JS_PUBLIC_API
const RealmCreationOptions
& RealmCreationOptionsRef(
337 extern JS_PUBLIC_API
const RealmCreationOptions
& RealmCreationOptionsRef(
340 extern JS_PUBLIC_API
const RealmBehaviors
& RealmBehaviorsRef(Realm
* realm
);
342 extern JS_PUBLIC_API
const RealmBehaviors
& RealmBehaviorsRef(JSContext
* cx
);
344 extern JS_PUBLIC_API
void SetRealmNonLive(Realm
* realm
);
346 // This behaves like RealmBehaviors::setReduceTimerPrecisionCallerType, but
347 // can be used even after the Realm has already been created.
348 extern JS_PUBLIC_API
void SetRealmReduceTimerPrecisionCallerType(
349 Realm
* realm
, RTPCallerTypeToken type
);
353 #endif // js_RealmOptions_h