summaryrefslogtreecommitdiffstats
path: root/js/public/RealmOptions.h
diff options
context:
space:
mode:
Diffstat (limited to 'js/public/RealmOptions.h')
-rw-r--r--js/public/RealmOptions.h414
1 files changed, 414 insertions, 0 deletions
diff --git a/js/public/RealmOptions.h b/js/public/RealmOptions.h
new file mode 100644
index 0000000000..2f5cef8d6c
--- /dev/null
+++ b/js/public/RealmOptions.h
@@ -0,0 +1,414 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * vim: set ts=8 sts=2 et sw=2 tw=80:
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/*
+ * Options specified when creating a realm to determine its behavior, immutable
+ * options determining the behavior of an existing realm, and mutable options on
+ * an existing realm that may be changed when desired.
+ */
+
+#ifndef js_RealmOptions_h
+#define js_RealmOptions_h
+
+#include "mozilla/Assertions.h" // MOZ_ASSERT
+
+#include "jstypes.h" // JS_PUBLIC_API
+
+#include "js/Class.h" // JSTraceOp
+
+struct JS_PUBLIC_API JSContext;
+class JS_PUBLIC_API JSObject;
+
+namespace JS {
+
+class JS_PUBLIC_API Compartment;
+class JS_PUBLIC_API Realm;
+class JS_PUBLIC_API Zone;
+
+} // namespace JS
+
+namespace JS {
+
+/**
+ * Specification for which compartment/zone a newly created realm should use.
+ */
+enum class CompartmentSpecifier {
+ // Create a new realm and compartment in the single runtime wide system
+ // zone. The meaning of this zone is left to the embedder.
+ NewCompartmentInSystemZone,
+
+ // Create a new realm and compartment in a particular existing zone.
+ NewCompartmentInExistingZone,
+
+ // Create a new zone/compartment.
+ NewCompartmentAndZone,
+
+ // Create a new realm in an existing compartment.
+ ExistingCompartment,
+};
+
+/**
+ * Specification for whether weak refs should be enabled and if so whether the
+ * FinalizationRegistry.cleanupSome method should be present.
+ */
+enum class WeakRefSpecifier {
+ Disabled,
+ EnabledWithCleanupSome,
+ EnabledWithoutCleanupSome
+};
+
+/**
+ * RealmCreationOptions specifies options relevant to creating a new realm, that
+ * are either immutable characteristics of that realm or that are discarded
+ * after the realm has been created.
+ *
+ * Access to these options on an existing realm is read-only: if you need
+ * particular selections, you must make them before you create the realm.
+ */
+class JS_PUBLIC_API RealmCreationOptions {
+ public:
+ RealmCreationOptions() : comp_(nullptr) {}
+
+ JSTraceOp getTrace() const { return traceGlobal_; }
+ RealmCreationOptions& setTrace(JSTraceOp op) {
+ traceGlobal_ = op;
+ return *this;
+ }
+
+ Zone* zone() const {
+ MOZ_ASSERT(compSpec_ == CompartmentSpecifier::NewCompartmentInExistingZone);
+ return zone_;
+ }
+ Compartment* compartment() const {
+ MOZ_ASSERT(compSpec_ == CompartmentSpecifier::ExistingCompartment);
+ return comp_;
+ }
+ CompartmentSpecifier compartmentSpecifier() const { return compSpec_; }
+
+ // Set the compartment/zone to use for the realm. See CompartmentSpecifier
+ // above.
+ RealmCreationOptions& setNewCompartmentInSystemZone();
+ RealmCreationOptions& setNewCompartmentInExistingZone(JSObject* obj);
+ RealmCreationOptions& setNewCompartmentAndZone();
+ RealmCreationOptions& setExistingCompartment(JSObject* obj);
+ RealmCreationOptions& setExistingCompartment(Compartment* compartment);
+
+ // Certain compartments are implementation details of the embedding, and
+ // references to them should never leak out to script. This flag causes this
+ // realm to skip firing onNewGlobalObject and makes addDebuggee a no-op for
+ // this global.
+ //
+ // Debugger visibility is per-compartment, not per-realm (it's only practical
+ // to enforce visibility on compartment boundaries), so if a realm is being
+ // created in an extant compartment, its requested visibility must match that
+ // of the compartment.
+ bool invisibleToDebugger() const { return invisibleToDebugger_; }
+ RealmCreationOptions& setInvisibleToDebugger(bool flag) {
+ invisibleToDebugger_ = flag;
+ return *this;
+ }
+
+ // Determines whether this realm should preserve JIT code on non-shrinking
+ // GCs.
+ bool preserveJitCode() const { return preserveJitCode_; }
+ RealmCreationOptions& setPreserveJitCode(bool flag) {
+ preserveJitCode_ = flag;
+ return *this;
+ }
+
+ // Determines whether 1) the global Atomic property is defined and atomic
+ // operations are supported, and 2) whether shared-memory operations are
+ // supported.
+ bool getSharedMemoryAndAtomicsEnabled() const;
+ RealmCreationOptions& setSharedMemoryAndAtomicsEnabled(bool flag);
+
+ // Determines (if getSharedMemoryAndAtomicsEnabled() is true) whether the
+ // global SharedArrayBuffer property is defined. If the property is not
+ // defined, shared array buffer functionality can only be invoked if the
+ // host/embedding specifically acts to expose it.
+ //
+ // This option defaults to true: embeddings unable to tolerate a global
+ // SharedAraryBuffer property must opt out of it.
+ bool defineSharedArrayBufferConstructor() const {
+ return defineSharedArrayBufferConstructor_;
+ }
+ RealmCreationOptions& setDefineSharedArrayBufferConstructor(bool flag) {
+ defineSharedArrayBufferConstructor_ = flag;
+ return *this;
+ }
+
+ // Structured clone operations support the cloning of shared memory objects
+ // (SharedArrayBuffer or or a shared WASM Memory object) *optionally* -- at
+ // the discretion of the embedder code that performs the cloning. When a
+ // structured clone operation encounters a shared memory object and cloning
+ // shared memory objects has not been enabled, the clone fails and an
+ // error is thrown.
+ //
+ // In the web embedding context, shared memory object cloning is disabled
+ // either because
+ //
+ // 1) *no* way of supporting it is available (because the
+ // Cross-Origin-Opener-Policy and Cross-Origin-Embedder-Policy HTTP
+ // headers are not respected to force the page into its own process), or
+ // 2) the aforementioned HTTP headers don't specify that the page should be
+ // opened in its own process.
+ //
+ // These two scenarios demand different error messages, and this option can be
+ // used to specify which scenario is in play.
+ //
+ // In the former case, if COOP/COEP support is not enabled, set this option to
+ // false. (This is the default.)
+ //
+ // In the latter case, if COOP/COEP weren't used to force this page into its
+ // own process, set this option to true.
+ //
+ // (Embeddings that are not the web and do not wish to support structured
+ // cloning of shared memory objects will get a "bad" web-centric error message
+ // no matter what. At present, SpiderMonkey does not offer a way for such
+ // embeddings to use an embedding-specific error message.)
+ bool getCoopAndCoepEnabled() const;
+ RealmCreationOptions& setCoopAndCoepEnabled(bool flag);
+
+ WeakRefSpecifier getWeakRefsEnabled() const { return weakRefs_; }
+ RealmCreationOptions& setWeakRefsEnabled(WeakRefSpecifier spec) {
+ weakRefs_ = spec;
+ return *this;
+ }
+
+ bool getToSourceEnabled() const { return toSource_; }
+ RealmCreationOptions& setToSourceEnabled(bool flag) {
+ toSource_ = flag;
+ return *this;
+ }
+
+ bool getPropertyErrorMessageFixEnabled() const {
+ return propertyErrorMessageFix_;
+ }
+ RealmCreationOptions& setPropertyErrorMessageFixEnabled(bool flag) {
+ propertyErrorMessageFix_ = flag;
+ return *this;
+ }
+
+ bool getIteratorHelpersEnabled() const { return iteratorHelpers_; }
+ RealmCreationOptions& setIteratorHelpersEnabled(bool flag) {
+ iteratorHelpers_ = flag;
+ return *this;
+ }
+
+ bool getShadowRealmsEnabled() const { return shadowRealms_; }
+ RealmCreationOptions& setShadowRealmsEnabled(bool flag) {
+ shadowRealms_ = flag;
+ return *this;
+ }
+
+#ifdef NIGHTLY_BUILD
+ bool getArrayGroupingEnabled() const { return arrayGrouping_; }
+ RealmCreationOptions& setArrayGroupingEnabled(bool flag) {
+ arrayGrouping_ = flag;
+ return *this;
+ }
+
+ bool getWellFormedUnicodeStringsEnabled() const {
+ return wellFormedUnicodeStrings_;
+ }
+ RealmCreationOptions& setWellFormedUnicodeStringsEnabled(bool flag) {
+ wellFormedUnicodeStrings_ = flag;
+ return *this;
+ }
+#endif
+
+ bool getArrayFromAsyncEnabled() const { return arrayFromAsync_; }
+ RealmCreationOptions& setArrayFromAsyncEnabled(bool flag) {
+ arrayFromAsync_ = flag;
+ return *this;
+ }
+
+ bool getChangeArrayByCopyEnabled() const { return changeArrayByCopy_; }
+ RealmCreationOptions& setChangeArrayByCopyEnabled(bool flag) {
+ changeArrayByCopy_ = flag;
+ return *this;
+ }
+
+#ifdef ENABLE_NEW_SET_METHODS
+ bool getNewSetMethodsEnabled() const { return newSetMethods_; }
+ RealmCreationOptions& setNewSetMethodsEnabled(bool flag) {
+ newSetMethods_ = flag;
+ return *this;
+ }
+#endif
+
+ // This flag doesn't affect JS engine behavior. It is used by Gecko to
+ // mark whether content windows and workers are "Secure Context"s. See
+ // https://w3c.github.io/webappsec-secure-contexts/
+ // https://bugzilla.mozilla.org/show_bug.cgi?id=1162772#c34
+ bool secureContext() const { return secureContext_; }
+ RealmCreationOptions& setSecureContext(bool flag) {
+ secureContext_ = flag;
+ return *this;
+ }
+
+ // Non-standard option to freeze certain builtin constructors and seal their
+ // prototypes. Also defines these constructors on the global as non-writable
+ // and non-configurable.
+ bool freezeBuiltins() const { return freezeBuiltins_; }
+ RealmCreationOptions& setFreezeBuiltins(bool flag) {
+ freezeBuiltins_ = flag;
+ return *this;
+ }
+
+ uint64_t profilerRealmID() const { return profilerRealmID_; }
+ RealmCreationOptions& setProfilerRealmID(uint64_t id) {
+ profilerRealmID_ = id;
+ return *this;
+ }
+
+ private:
+ JSTraceOp traceGlobal_ = nullptr;
+ CompartmentSpecifier compSpec_ = CompartmentSpecifier::NewCompartmentAndZone;
+ union {
+ Compartment* comp_;
+ Zone* zone_;
+ };
+ uint64_t profilerRealmID_ = 0;
+ WeakRefSpecifier weakRefs_ = WeakRefSpecifier::Disabled;
+ bool invisibleToDebugger_ = false;
+ bool preserveJitCode_ = false;
+ bool sharedMemoryAndAtomics_ = false;
+ bool defineSharedArrayBufferConstructor_ = true;
+ bool coopAndCoep_ = false;
+ bool toSource_ = false;
+ bool propertyErrorMessageFix_ = false;
+ bool iteratorHelpers_ = false;
+ bool shadowRealms_ = false;
+#ifdef NIGHTLY_BUILD
+ bool arrayGrouping_ = false;
+ // Pref for String.prototype.{is,to}WellFormed() methods.
+ bool wellFormedUnicodeStrings_ = false;
+#endif
+ bool arrayFromAsync_ = true;
+ bool changeArrayByCopy_ = false;
+#ifdef ENABLE_NEW_SET_METHODS
+ bool newSetMethods_ = false;
+#endif
+ bool secureContext_ = false;
+ bool freezeBuiltins_ = false;
+};
+
+/**
+ * RealmBehaviors specifies behaviors of a realm that can be changed after the
+ * realm's been created.
+ */
+class JS_PUBLIC_API RealmBehaviors {
+ public:
+ RealmBehaviors() = default;
+
+ // For certain globals, we know enough about the code that will run in them
+ // that we can discard script source entirely.
+ bool discardSource() const { return discardSource_; }
+ RealmBehaviors& setDiscardSource(bool flag) {
+ discardSource_ = flag;
+ return *this;
+ }
+
+ bool clampAndJitterTime() const { return clampAndJitterTime_; }
+ RealmBehaviors& setClampAndJitterTime(bool flag) {
+ clampAndJitterTime_ = flag;
+ return *this;
+ }
+
+ bool shouldResistFingerprinting() const {
+ return shouldResistFingerprinting_;
+ }
+ RealmBehaviors& setShouldResistFingerprinting(bool flag) {
+ shouldResistFingerprinting_ = flag;
+ return *this;
+ }
+
+ class Override {
+ public:
+ Override() : mode_(Default) {}
+
+ bool get(bool defaultValue) const {
+ if (mode_ == Default) {
+ return defaultValue;
+ }
+ return mode_ == ForceTrue;
+ }
+
+ void set(bool overrideValue) {
+ mode_ = overrideValue ? ForceTrue : ForceFalse;
+ }
+
+ void reset() { mode_ = Default; }
+
+ private:
+ enum Mode { Default, ForceTrue, ForceFalse };
+
+ Mode mode_;
+ };
+
+ // A Realm can stop being "live" in all the ways that matter before its global
+ // is actually GCed. Consumers that tear down parts of a Realm or its global
+ // before that point should set isNonLive accordingly.
+ bool isNonLive() const { return isNonLive_; }
+ RealmBehaviors& setNonLive() {
+ isNonLive_ = true;
+ return *this;
+ }
+
+ private:
+ bool discardSource_ = false;
+ bool clampAndJitterTime_ = true;
+ bool shouldResistFingerprinting_ = false;
+ bool isNonLive_ = false;
+};
+
+/**
+ * RealmOptions specifies realm characteristics: both those that can't be
+ * changed on a realm once it's been created (RealmCreationOptions), and those
+ * that can be changed on an existing realm (RealmBehaviors).
+ */
+class JS_PUBLIC_API RealmOptions {
+ public:
+ explicit RealmOptions() : creationOptions_(), behaviors_() {}
+
+ RealmOptions(const RealmCreationOptions& realmCreation,
+ const RealmBehaviors& realmBehaviors)
+ : creationOptions_(realmCreation), behaviors_(realmBehaviors) {}
+
+ // RealmCreationOptions specify fundamental realm characteristics that must
+ // be specified when the realm is created, that can't be changed after the
+ // realm is created.
+ RealmCreationOptions& creationOptions() { return creationOptions_; }
+ const RealmCreationOptions& creationOptions() const {
+ return creationOptions_;
+ }
+
+ // RealmBehaviors specify realm characteristics that can be changed after
+ // the realm is created.
+ RealmBehaviors& behaviors() { return behaviors_; }
+ const RealmBehaviors& behaviors() const { return behaviors_; }
+
+ private:
+ RealmCreationOptions creationOptions_;
+ RealmBehaviors behaviors_;
+};
+
+extern JS_PUBLIC_API const RealmCreationOptions& RealmCreationOptionsRef(
+ Realm* realm);
+
+extern JS_PUBLIC_API const RealmCreationOptions& RealmCreationOptionsRef(
+ JSContext* cx);
+
+extern JS_PUBLIC_API const RealmBehaviors& RealmBehaviorsRef(Realm* realm);
+
+extern JS_PUBLIC_API const RealmBehaviors& RealmBehaviorsRef(JSContext* cx);
+
+extern JS_PUBLIC_API void SetRealmNonLive(Realm* realm);
+
+} // namespace JS
+
+#endif // js_RealmOptions_h