diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
commit | 36d22d82aa202bb199967e9512281e9a53db42c9 (patch) | |
tree | 105e8c98ddea1c1e4784a60a5a6410fa416be2de /js/public/RealmOptions.h | |
parent | Initial commit. (diff) | |
download | firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.tar.xz firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.zip |
Adding upstream version 115.7.0esr.upstream/115.7.0esr
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'js/public/RealmOptions.h')
-rw-r--r-- | js/public/RealmOptions.h | 414 |
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 |