diff options
Diffstat (limited to 'components/script/dom')
-rw-r--r-- | components/script/dom/bindings/interface.rs | 42 | ||||
-rw-r--r-- | components/script/dom/windowproxy.rs | 12 |
2 files changed, 47 insertions, 7 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, diff --git a/components/script/dom/windowproxy.rs b/components/script/dom/windowproxy.rs index e37e561af06..0f92e4b3367 100644 --- a/components/script/dom/windowproxy.rs +++ b/components/script/dom/windowproxy.rs @@ -637,13 +637,11 @@ impl WindowProxy { // The old window proxy no longer owns this browsing context. SetProxyReservedSlot(old_js_proxy.get(), 0, &PrivateValue(ptr::null_mut())); - // Brain transpant the window proxy. - // We need to do this, because the Window and WindowProxy - // objects need to be in the same realm. - // JS_TransplantObject does this by copying the contents - // of the old window proxy to the new window proxy, then - // making the old window proxy a cross-realm wrapper - // pointing to the new window proxy. + // Brain transpant the window proxy. Brain transplantation is + // usually done to move a window proxy between compartments, but + // that's not what we are doing here. We need to do this just + // because we want to replace the wrapper's `ProxyTraps`, but we + // don't want to update its identity. rooted!(in(*cx) let new_js_proxy = NewWindowProxy(*cx, window_jsobject, handler)); debug!( "Transplanting proxy from {:p} to {:p}.", |