diff options
author | yvt <i@yvt.jp> | 2021-07-06 09:10:33 +0900 |
---|---|---|
committer | yvt <i@yvt.jp> | 2021-07-06 09:10:33 +0900 |
commit | 5871d09c26dcee3cc75c2dd1b7efc8ce208bbb45 (patch) | |
tree | 0fdd49cb0219a9c670e36396efd9c69f156fcf29 /components/script/dom | |
parent | 42d7892d88d8e97ca20aa3557b2f03f739f17b89 (diff) | |
download | servo-5871d09c26dcee3cc75c2dd1b7efc8ce208bbb45.tar.gz servo-5871d09c26dcee3cc75c2dd1b7efc8ce208bbb45.zip |
fix(script): one compartment for each script thread (agent)
Documents in the same agent[1] can share and exchange JS and DOM objects
freely, so putting them in separate compartments would require almost
every instance of `Dom` to be able to handle cross-compartment
references.
[1]: https://html.spec.whatwg.org/multipage/webappapis.html#integration-with-the-javascript-agent-formalism
Diffstat (limited to 'components/script/dom')
-rw-r--r-- | components/script/dom/bindings/interface.rs | 42 |
1 files changed, 42 insertions, 0 deletions
diff --git a/components/script/dom/bindings/interface.rs b/components/script/dom/bindings/interface.rs index 1085a137428..82303f800ba 100644 --- a/components/script/dom/bindings/interface.rs +++ b/components/script/dom/bindings/interface.rs @@ -16,6 +16,10 @@ use js::glue::UncheckedUnwrapObject; use js::jsapi::GetWellKnownSymbol; use js::jsapi::HandleObject as RawHandleObject; use js::jsapi::{jsid, JSClass, JSClassOps}; +use js::jsapi::{ + Compartment, CompartmentSpecifier, IsSharableCompartment, IsSystemCompartment, + JS_IterateCompartments, JS::CompartmentIterResult, +}; use js::jsapi::{JSAutoRealm, JSContext, JSFunctionSpec, JSObject, JSFUN_CONSTRUCTOR}; use js::jsapi::{JSPropertySpec, JSString, JSTracer, JS_AtomizeAndPinString}; use js::jsapi::{JS_GetFunctionObject, JS_NewFunction, JS_NewGlobalObject}; @@ -139,6 +143,7 @@ pub unsafe fn create_global_object( options.creationOptions_.traceGlobal_ = Some(trace); options.creationOptions_.sharedMemoryAndAtomics_ = false; options.creationOptions_.streams_ = true; + select_compartment(cx, &mut options); rval.set(JS_NewGlobalObject( *cx, @@ -162,6 +167,43 @@ pub unsafe fn create_global_object( JS_FireOnNewGlobalObject(*cx, rval.handle()); } +/// Choose the compartment to create a new global object in. +fn select_compartment(cx: SafeJSContext, options: &mut RealmOptions) { + type Data = *mut Compartment; + unsafe extern "C" fn callback( + _cx: *mut JSContext, + data: *mut libc::c_void, + compartment: *mut Compartment, + ) -> CompartmentIterResult { + let data = data as *mut Data; + + if !IsSharableCompartment(compartment) || IsSystemCompartment(compartment) { + return CompartmentIterResult::KeepGoing; + } + + // Choose any sharable, non-system compartment in this context to allow + // same-agent documents to share JS and DOM objects. + *data = compartment; + CompartmentIterResult::Stop + } + + let mut compartment: Data = ptr::null_mut(); + unsafe { + JS_IterateCompartments( + *cx, + (&mut compartment) as *mut Data as *mut libc::c_void, + Some(callback), + ); + } + + if compartment.is_null() { + options.creationOptions_.compSpec_ = CompartmentSpecifier::NewCompartmentAndZone; + } else { + options.creationOptions_.compSpec_ = CompartmentSpecifier::ExistingCompartment; + options.creationOptions_.__bindgen_anon_1.comp_ = compartment; + } +} + /// Create and define the interface object of a callback interface. pub fn create_callback_interface_object( cx: SafeJSContext, |