diff options
Diffstat (limited to 'components/script')
25 files changed, 175 insertions, 573 deletions
diff --git a/components/script/dom/audionode.rs b/components/script/dom/audionode.rs index 422b517bc94..4e572dda437 100644 --- a/components/script/dom/audionode.rs +++ b/components/script/dom/audionode.rs @@ -5,6 +5,9 @@ use std::cell::Cell; use dom_struct::dom_struct; +use script_bindings::codegen::InheritTypes::{ + AudioNodeTypeId, AudioScheduledSourceNodeTypeId, EventTargetTypeId, +}; use servo_media::audio::graph::NodeId; use servo_media::audio::node::{ AudioNodeInit, AudioNodeMessage, ChannelCountMode as ServoMediaChannelCountMode, ChannelInfo, @@ -17,9 +20,6 @@ use crate::dom::baseaudiocontext::BaseAudioContext; use crate::dom::bindings::codegen::Bindings::AudioNodeBinding::{ AudioNodeMethods, AudioNodeOptions, ChannelCountMode, ChannelInterpretation, }; -use crate::dom::bindings::codegen::InheritTypes::{ - AudioNodeTypeId, AudioScheduledSourceNodeTypeId, EventTargetTypeId, -}; use crate::dom::bindings::error::{Error, ErrorResult, Fallible}; use crate::dom::bindings::inheritance::Castable; use crate::dom::bindings::root::{Dom, DomRoot}; diff --git a/components/script/dom/bindings/callback.rs b/components/script/dom/bindings/callback.rs index 7a28451763f..6a54255822f 100644 --- a/components/script/dom/bindings/callback.rs +++ b/components/script/dom/bindings/callback.rs @@ -16,14 +16,15 @@ use js::jsval::{JSVal, ObjectValue, UndefinedValue}; use js::rust::wrappers::{JS_GetProperty, JS_WrapObject}; use js::rust::{MutableHandleValue, Runtime}; use script_bindings::interfaces::DocumentHelpers; +use script_bindings::utils::AsCCharPtrPtr; use crate::DomTypes; use crate::dom::bindings::codegen::Bindings::WindowBinding::Window_Binding::WindowMethods; -use crate::dom::bindings::error::{Error, Fallible, report_pending_exception}; +use crate::dom::bindings::error::{Error, Fallible}; use crate::dom::bindings::inheritance::Castable; use crate::dom::bindings::root::{Dom, DomRoot}; use crate::dom::bindings::settings_stack::{GenericAutoEntryScript, GenericAutoIncumbentScript}; -use crate::dom::bindings::utils::AsCCharPtrPtr; +use crate::dom::bindings::utils::DomHelpers; use crate::dom::globalscope::GlobalScopeHelpers; use crate::realms::{InRealm, enter_realm}; use crate::script_runtime::{CanGc, JSContext}; @@ -281,7 +282,12 @@ impl<D: DomTypes> Drop for CallSetup<D> { } if self.handling == ExceptionHandling::Report { let ar = enter_realm(&*self.exception_global); - report_pending_exception(self.cx, true, InRealm::Entered(&ar), CanGc::note()); + <D as DomHelpers<D>>::report_pending_exception( + self.cx, + true, + InRealm::Entered(&ar), + CanGc::note(), + ); } drop(self.incumbent_script.take()); drop(self.entry_script.take().unwrap()); diff --git a/components/script/dom/bindings/import.rs b/components/script/dom/bindings/import.rs index fb893af33f4..71ba5e4c994 100644 --- a/components/script/dom/bindings/import.rs +++ b/components/script/dom/bindings/import.rs @@ -107,6 +107,7 @@ pub(crate) mod module { }; pub(crate) use script_bindings::interfaces::*; pub(crate) use script_bindings::record::Record; + pub(crate) use script_bindings::reflector::DomObject; pub(crate) use servo_config::pref; pub(crate) use super::base::*; @@ -140,7 +141,7 @@ pub(crate) mod module { define_guarded_properties, get_desired_proto, get_per_interface_object_handle, is_exposed_in, }; - pub(crate) use crate::dom::bindings::iterable::{Iterable, IteratorType}; + pub(crate) use crate::dom::bindings::iterable::{Iterable, IterableIterator, IteratorType}; pub(crate) use crate::dom::bindings::like::{Maplike, Setlike}; pub(crate) use crate::dom::bindings::namespace::{ NamespaceObjectClass, create_namespace_object, diff --git a/components/script/dom/bindings/inheritance.rs b/components/script/dom/bindings/inheritance.rs index ef60378d55b..bb68b4b08f1 100644 --- a/components/script/dom/bindings/inheritance.rs +++ b/components/script/dom/bindings/inheritance.rs @@ -3,11 +3,4 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ pub(crate) use script_bindings::codegen::InheritTypes::*; -pub(crate) use script_bindings::inheritance::Castable; - -#[allow(missing_docs)] -pub(crate) trait HasParent { - #[cfg_attr(crown, crown::unrooted_must_root_lint::must_root)] - type Parent; - fn as_parent(&self) -> &Self::Parent; -} +pub(crate) use script_bindings::inheritance::{Castable, HasParent}; diff --git a/components/script/dom/bindings/interface.rs b/components/script/dom/bindings/interface.rs index 835d2f7f0be..d1c191be3a4 100644 --- a/components/script/dom/bindings/interface.rs +++ b/components/script/dom/bindings/interface.rs @@ -135,7 +135,7 @@ impl InterfaceConstructorBehavior { pub(crate) type TraceHook = unsafe extern "C" fn(trc: *mut JSTracer, obj: *mut JSObject); /// Create a global object with the given class. -pub(crate) unsafe fn create_global_object( +pub(crate) unsafe fn create_global_object<D: DomTypes>( cx: SafeJSContext, class: &'static JSClass, private: *const libc::c_void, @@ -150,7 +150,7 @@ pub(crate) unsafe fn create_global_object( options.creationOptions_.sharedMemoryAndAtomics_ = false; select_compartment(cx, &mut options); - let principal = ServoJSPrincipals::new(origin); + let principal = ServoJSPrincipals::new::<D>(origin); rval.set(JS_NewGlobalObject( *cx, diff --git a/components/script/dom/bindings/iterable.rs b/components/script/dom/bindings/iterable.rs index d97dfeeddbe..c81551f7960 100644 --- a/components/script/dom/bindings/iterable.rs +++ b/components/script/dom/bindings/iterable.rs @@ -26,10 +26,11 @@ use crate::dom::bindings::codegen::Bindings::IterableIteratorBinding::{ }; use crate::dom::bindings::error::Fallible; use crate::dom::bindings::reflector::{ - DomGlobalGeneric, DomObjectIteratorWrap, DomObjectWrap, Reflector, reflect_dom_object, + DomGlobalGeneric, DomObjectIteratorWrap, DomObjectWrap, Reflector, }; use crate::dom::bindings::root::{Dom, DomRoot, Root}; use crate::dom::bindings::trace::{JSTraceable, NoTrace, RootedTraceableBox}; +use crate::dom::bindings::utils::DomHelpers; use crate::realms::InRealm; use crate::script_runtime::{CanGc, JSContext}; @@ -79,7 +80,7 @@ impl<D: DomTypes, T: DomObjectIteratorWrap<D> + JSTraceable + Iterable + DomGlob index: Cell::new(0), _marker: NoTrace(PhantomData), }); - reflect_dom_object(iterator, &*iterable.global_(realm), CanGc::note()) + <D as DomHelpers<D>>::reflect_dom_object(iterator, &*iterable.global_(realm), CanGc::note()) } /// Return the next value from the iterable object. diff --git a/components/script/dom/bindings/mod.rs b/components/script/dom/bindings/mod.rs index 833915c0b98..b4234e0cc39 100644 --- a/components/script/dom/bindings/mod.rs +++ b/components/script/dom/bindings/mod.rs @@ -191,7 +191,6 @@ pub(crate) mod codegen { include!(concat!(env!("BINDINGS_OUT_DIR"), "/InterfaceObjectMap.rs")); pub(crate) use script_bindings::codegen::Globals::Globals; } - pub(crate) use script_bindings::codegen::InheritTypes; #[allow(dead_code)] pub(crate) mod ConcreteInheritTypes { include!(concat!( diff --git a/components/script/dom/bindings/principals.rs b/components/script/dom/bindings/principals.rs index b037fcb0709..e51a98e454a 100644 --- a/components/script/dom/bindings/principals.rs +++ b/components/script/dom/bindings/principals.rs @@ -19,16 +19,21 @@ use js::rust::Runtime; use servo_url::MutableOrigin; use super::structuredclone::StructuredCloneTags; +use crate::dom::bindings::utils::DomHelpers; +use crate::{DomTypeHolder, DomTypes}; /// An owned reference to Servo's `JSPrincipals` instance. #[repr(transparent)] pub(crate) struct ServoJSPrincipals(NonNull<JSPrincipals>); impl ServoJSPrincipals { - pub(crate) fn new(origin: &MutableOrigin) -> Self { + pub(crate) fn new<D: DomTypes>(origin: &MutableOrigin) -> Self { unsafe { let private: Box<MutableOrigin> = Box::new(origin.clone()); - let raw = CreateRustJSPrincipals(&PRINCIPALS_CALLBACKS, Box::into_raw(private) as _); + let raw = CreateRustJSPrincipals( + <D as DomHelpers<D>>::principals_callbacks(), + Box::into_raw(private) as _, + ); // The created `JSPrincipals` object has an initial reference // count of zero, so the following code will set it to one Self::from_raw_nonnull(NonNull::new_unchecked(raw)) @@ -175,14 +180,14 @@ pub(crate) unsafe extern "C" fn read_jsprincipal( let Ok(origin) = bincode::deserialize(&bytes[..]) else { return false; }; - let principal = ServoJSPrincipals::new(&origin); + let principal = ServoJSPrincipals::new::<DomTypeHolder>(&origin); *principals = principal.as_raw(); // we transferred ownership of principal to the caller std::mem::forget(principal); true } -const PRINCIPALS_CALLBACKS: JSPrincipalsCallbacks = JSPrincipalsCallbacks { +pub(crate) const PRINCIPALS_CALLBACKS: JSPrincipalsCallbacks = JSPrincipalsCallbacks { write: Some(write_jsprincipal), isSystemOrAddonPrincipal: Some(principals_is_system_or_addon_principal), }; diff --git a/components/script/dom/bindings/proxyhandler.rs b/components/script/dom/bindings/proxyhandler.rs index 1ef83119e53..5dfe0839502 100644 --- a/components/script/dom/bindings/proxyhandler.rs +++ b/components/script/dom/bindings/proxyhandler.rs @@ -6,199 +6,31 @@ #![deny(missing_docs)] -use std::ffi::CStr; -use std::os::raw::c_char; use std::ptr; use js::conversions::ToJSValConvertible; -use js::glue::{ - GetProxyHandler, GetProxyHandlerFamily, GetProxyPrivate, InvokeGetOwnPropertyDescriptor, - SetProxyPrivate, -}; +use js::glue::{GetProxyHandler, InvokeGetOwnPropertyDescriptor}; use js::jsapi; use js::jsapi::{ - DOMProxyShadowsResult, GetObjectRealmOrNull, GetRealmPrincipals, GetStaticPrototype, - GetWellKnownSymbol, Handle as RawHandle, HandleId as RawHandleId, - HandleObject as RawHandleObject, HandleValue as RawHandleValue, JS_AtomizeAndPinString, - JS_DefinePropertyById, JS_GetOwnPropertyDescriptorById, JS_IsExceptionPending, JSAutoRealm, - JSContext, JSErrNum, JSFunctionSpec, JSObject, JSPropertySpec, - MutableHandle as RawMutableHandle, MutableHandleIdVector as RawMutableHandleIdVector, + GetObjectRealmOrNull, GetRealmPrincipals, HandleId as RawHandleId, + HandleObject as RawHandleObject, HandleValue as RawHandleValue, JS_IsExceptionPending, + JSAutoRealm, JSContext, JSObject, MutableHandle as RawMutableHandle, MutableHandleObject as RawMutableHandleObject, MutableHandleValue as RawMutableHandleValue, - ObjectOpResult, PropertyDescriptor, SetDOMProxyInformation, SymbolCode, jsid, -}; -use js::jsid::SymbolId; -use js::jsval::{ObjectValue, UndefinedValue}; -use js::rust::wrappers::{ - AppendToIdVector, JS_AlreadyHasOwnPropertyById, JS_NewObjectWithGivenProto, - RUST_INTERNED_STRING_TO_JSID, SetDataPropertyDescriptor, -}; -use js::rust::{ - Handle, HandleObject, HandleValue, MutableHandle, MutableHandleObject, get_context_realm, + ObjectOpResult, PropertyDescriptor, }; +use js::jsval::UndefinedValue; +use js::rust::{HandleObject, HandleValue, MutableHandle, MutableHandleObject, get_context_realm}; +pub(crate) use script_bindings::proxyhandler::*; -use crate::dom::bindings::conversions::{is_dom_proxy, jsid_to_string, jsstring_to_str}; -use crate::dom::bindings::error::{Error, throw_dom_exception}; +use crate::DomTypes; +use crate::dom::bindings::error::Error; use crate::dom::bindings::principals::ServoJSPrincipalsRef; use crate::dom::bindings::reflector::DomObject; -use crate::dom::bindings::str::DOMString; -use crate::dom::bindings::utils::delete_property_by_id; -use crate::dom::globalscope::{GlobalScope, GlobalScopeHelpers}; +use crate::dom::bindings::utils::DomHelpers; +use crate::dom::globalscope::GlobalScopeHelpers; use crate::realms::{AlreadyInRealm, InRealm}; use crate::script_runtime::{CanGc, JSContext as SafeJSContext}; -/// Determine if this id shadows any existing properties for this proxy. -pub(crate) unsafe extern "C" fn shadow_check_callback( - cx: *mut JSContext, - object: RawHandleObject, - id: RawHandleId, -) -> DOMProxyShadowsResult { - // TODO: support OverrideBuiltins when #12978 is fixed. - - rooted!(in(cx) let mut expando = ptr::null_mut::<JSObject>()); - get_expando_object(object, expando.handle_mut()); - if !expando.get().is_null() { - let mut has_own = false; - let raw_id = Handle::from_raw(id); - - if !JS_AlreadyHasOwnPropertyById(cx, expando.handle(), raw_id, &mut has_own) { - return DOMProxyShadowsResult::ShadowCheckFailed; - } - - if has_own { - return DOMProxyShadowsResult::ShadowsViaDirectExpando; - } - } - - // Our expando, if any, didn't shadow, so we're not shadowing at all. - DOMProxyShadowsResult::DoesntShadow -} - -/// Initialize the infrastructure for DOM proxy objects. -pub(crate) unsafe fn init() { - SetDOMProxyInformation( - GetProxyHandlerFamily(), - Some(shadow_check_callback), - ptr::null(), - ); -} - -/// Defines an expando on the given `proxy`. -pub(crate) unsafe extern "C" fn define_property( - cx: *mut JSContext, - proxy: RawHandleObject, - id: RawHandleId, - desc: RawHandle<PropertyDescriptor>, - result: *mut ObjectOpResult, -) -> bool { - rooted!(in(cx) let mut expando = ptr::null_mut::<JSObject>()); - ensure_expando_object(cx, proxy, expando.handle_mut()); - JS_DefinePropertyById(cx, expando.handle().into(), id, desc, result) -} - -/// Deletes an expando off the given `proxy`. -pub(crate) unsafe extern "C" fn delete( - cx: *mut JSContext, - proxy: RawHandleObject, - id: RawHandleId, - bp: *mut ObjectOpResult, -) -> bool { - rooted!(in(cx) let mut expando = ptr::null_mut::<JSObject>()); - get_expando_object(proxy, expando.handle_mut()); - if expando.is_null() { - (*bp).code_ = 0 /* OkCode */; - return true; - } - - delete_property_by_id(cx, expando.handle(), Handle::from_raw(id), bp) -} - -/// Controls whether the Extensible bit can be changed -pub(crate) unsafe extern "C" fn prevent_extensions( - _cx: *mut JSContext, - _proxy: RawHandleObject, - result: *mut ObjectOpResult, -) -> bool { - (*result).code_ = JSErrNum::JSMSG_CANT_PREVENT_EXTENSIONS as ::libc::uintptr_t; - true -} - -/// Reports whether the object is Extensible -pub(crate) unsafe extern "C" fn is_extensible( - _cx: *mut JSContext, - _proxy: RawHandleObject, - succeeded: *mut bool, -) -> bool { - *succeeded = true; - true -} - -/// If `proxy` (underneath any functionally-transparent wrapper proxies) has as -/// its `[[GetPrototypeOf]]` trap the ordinary `[[GetPrototypeOf]]` behavior -/// defined for ordinary objects, set `*is_ordinary` to true and store `obj`'s -/// prototype in `proto`. Otherwise set `*isOrdinary` to false. In case of -/// error, both outparams have unspecified value. -/// -/// This implementation always handles the case of the ordinary -/// `[[GetPrototypeOf]]` behavior. An alternative implementation will be -/// necessary for maybe-cross-origin objects. -pub(crate) unsafe extern "C" fn get_prototype_if_ordinary( - _: *mut JSContext, - proxy: RawHandleObject, - is_ordinary: *mut bool, - proto: RawMutableHandleObject, -) -> bool { - *is_ordinary = true; - proto.set(GetStaticPrototype(proxy.get())); - true -} - -/// Get the expando object, or null if there is none. -pub(crate) unsafe fn get_expando_object(obj: RawHandleObject, mut expando: MutableHandleObject) { - assert!(is_dom_proxy(obj.get())); - let val = &mut UndefinedValue(); - GetProxyPrivate(obj.get(), val); - expando.set(if val.is_undefined() { - ptr::null_mut() - } else { - val.to_object() - }); -} - -/// Get the expando object, or create it if it doesn't exist yet. -/// Fails on JSAPI failure. -pub(crate) unsafe fn ensure_expando_object( - cx: *mut JSContext, - obj: RawHandleObject, - mut expando: MutableHandleObject, -) { - assert!(is_dom_proxy(obj.get())); - get_expando_object(obj, expando.reborrow()); - if expando.is_null() { - expando.set(JS_NewObjectWithGivenProto( - cx, - ptr::null_mut(), - HandleObject::null(), - )); - assert!(!expando.is_null()); - - SetProxyPrivate(obj.get(), &ObjectValue(expando.get())); - } -} - -/// Set the property descriptor's object to `obj` and set it to enumerable, -/// and writable if `readonly` is true. -pub(crate) fn set_property_descriptor( - desc: MutableHandle<PropertyDescriptor>, - value: HandleValue, - attrs: u32, - is_none: &mut bool, -) { - unsafe { - SetDataPropertyDescriptor(desc, value, attrs); - } - *is_none = false; -} - /// <https://html.spec.whatwg.org/multipage/#isplatformobjectsameorigin-(-o-)> pub(crate) unsafe fn is_platform_object_same_origin( cx: SafeJSContext, @@ -239,7 +71,7 @@ pub(crate) unsafe fn is_platform_object_same_origin( /// What this function does corresponds to the operations in /// <https://html.spec.whatwg.org/multipage/#the-location-interface> denoted as /// "Throw a `SecurityError` DOMException". -pub(crate) unsafe fn report_cross_origin_denial( +pub(crate) unsafe fn report_cross_origin_denial<D: DomTypes>( cx: SafeJSContext, id: RawHandleId, access: &str, @@ -251,75 +83,17 @@ pub(crate) unsafe fn report_cross_origin_denial( ); let in_realm_proof = AlreadyInRealm::assert_for_cx(cx); if !JS_IsExceptionPending(*cx) { - let global = GlobalScope::from_context(*cx, InRealm::Already(&in_realm_proof)); + let global = D::GlobalScope::from_context(*cx, InRealm::Already(&in_realm_proof)); // TODO: include `id` and `access` in the exception message - throw_dom_exception(cx, &global, Error::Security, CanGc::note()); + <D as DomHelpers<D>>::throw_dom_exception(cx, &global, Error::Security, CanGc::note()); } false } -unsafe fn id_to_source(cx: SafeJSContext, id: RawHandleId) -> Option<DOMString> { - rooted!(in(*cx) let mut value = UndefinedValue()); - rooted!(in(*cx) let mut jsstr = ptr::null_mut::<jsapi::JSString>()); - jsapi::JS_IdToValue(*cx, id.get(), value.handle_mut().into()) - .then(|| { - jsstr.set(jsapi::JS_ValueToSource(*cx, value.handle().into())); - jsstr.get() - }) - .and_then(ptr::NonNull::new) - .map(|jsstr| jsstring_to_str(*cx, jsstr)) -} - -/// Property and method specs that correspond to the elements of -/// [`CrossOriginProperties(O)`]. -/// -/// [`CrossOriginProperties(O)`]: https://html.spec.whatwg.org/multipage/#crossoriginproperties-(-o-) -pub(crate) struct CrossOriginProperties { - pub(crate) attributes: &'static [JSPropertySpec], - pub(crate) methods: &'static [JSFunctionSpec], -} - -impl CrossOriginProperties { - /// Enumerate the property keys defined by `self`. - fn keys(&self) -> impl Iterator<Item = *const c_char> + '_ { - // Safety: All cross-origin property keys are strings, not symbols - self.attributes - .iter() - .map(|spec| unsafe { spec.name.string_ }) - .chain(self.methods.iter().map(|spec| unsafe { spec.name.string_ })) - .filter(|ptr| !ptr.is_null()) - } -} - -/// Implementation of [`CrossOriginOwnPropertyKeys`]. -/// -/// [`CrossOriginOwnPropertyKeys`]: https://html.spec.whatwg.org/multipage/#crossoriginownpropertykeys-(-o-) -pub(crate) unsafe fn cross_origin_own_property_keys( - cx: SafeJSContext, - _proxy: RawHandleObject, - cross_origin_properties: &'static CrossOriginProperties, - props: RawMutableHandleIdVector, -) -> bool { - // > 2. For each `e` of `! CrossOriginProperties(O)`, append - // > `e.[[Property]]` to `keys`. - for key in cross_origin_properties.keys() { - rooted!(in(*cx) let rooted = JS_AtomizeAndPinString(*cx, key)); - rooted!(in(*cx) let mut rooted_jsid: jsid); - RUST_INTERNED_STRING_TO_JSID(*cx, rooted.handle().get(), rooted_jsid.handle_mut()); - AppendToIdVector(props, rooted_jsid.handle()); - } - - // > 3. Return the concatenation of `keys` and `« "then", @@toStringTag, - // > @@hasInstance, @@isConcatSpreadable »`. - append_cross_origin_allowlisted_prop_keys(cx, props); - - true -} - /// Implementation of `[[Set]]` for [`Location`]. /// /// [`Location`]: https://html.spec.whatwg.org/multipage/#location-set -pub(crate) unsafe extern "C" fn maybe_cross_origin_set_rawcx( +pub(crate) unsafe extern "C" fn maybe_cross_origin_set_rawcx<D: DomTypes>( cx: *mut JSContext, proxy: RawHandleObject, id: RawHandleId, @@ -329,8 +103,8 @@ pub(crate) unsafe extern "C" fn maybe_cross_origin_set_rawcx( ) -> bool { let cx = SafeJSContext::from_ptr(cx); - if !is_platform_object_same_origin(cx, proxy) { - return cross_origin_set(cx, proxy, id, v, receiver, result); + if !<D as DomHelpers<D>>::is_platform_object_same_origin(cx, proxy) { + return cross_origin_set::<D>(cx, proxy, id, v, receiver, result); } // Safe to enter the Realm of proxy now. @@ -362,21 +136,10 @@ pub(crate) unsafe extern "C" fn maybe_cross_origin_set_rawcx( ) } -pub(crate) unsafe extern "C" fn maybe_cross_origin_get_prototype_if_ordinary_rawcx( - _: *mut JSContext, - _proxy: RawHandleObject, - is_ordinary: *mut bool, - _proto: RawMutableHandleObject, -) -> bool { - // We have a custom `[[GetPrototypeOf]]`, so return `false` - *is_ordinary = false; - true -} - /// Implementation of `[[GetPrototypeOf]]` for [`Location`]. /// /// [`Location`]: https://html.spec.whatwg.org/multipage/#location-getprototypeof -pub(crate) unsafe fn maybe_cross_origin_get_prototype<D: crate::DomTypes>( +pub(crate) unsafe fn maybe_cross_origin_get_prototype<D: DomTypes>( cx: SafeJSContext, proxy: RawHandleObject, get_proto_object: unsafe fn(cx: SafeJSContext, global: HandleObject, rval: MutableHandleObject), @@ -399,46 +162,13 @@ pub(crate) unsafe fn maybe_cross_origin_get_prototype<D: crate::DomTypes>( true } -/// Implementation of `[[SetPrototypeOf]]` for [`Location`] and [`WindowProxy`]. -/// -/// [`Location`]: https://html.spec.whatwg.org/multipage/#location-setprototypeof -/// [`WindowProxy`]: https://html.spec.whatwg.org/multipage/#windowproxy-setprototypeof -pub(crate) unsafe extern "C" fn maybe_cross_origin_set_prototype_rawcx( - cx: *mut JSContext, - proxy: RawHandleObject, - proto: RawHandleObject, - result: *mut ObjectOpResult, -) -> bool { - // > 1. Return `! SetImmutablePrototype(this, V)`. - // - // <https://tc39.es/ecma262/#sec-set-immutable-prototype>: - // - // > 1. Assert: Either `Type(V)` is Object or `Type(V)` is Null. - // - // > 2. Let current be `? O.[[GetPrototypeOf]]()`. - rooted!(in(cx) let mut current = ptr::null_mut::<JSObject>()); - if !jsapi::GetObjectProto(cx, proxy, current.handle_mut().into()) { - return false; - } - - // > 3. If `SameValue(V, current)` is true, return true. - if proto.get() == current.get() { - (*result).code_ = 0 /* OkCode */; - return true; - } - - // > 4. Return false. - (*result).code_ = JSErrNum::JSMSG_CANT_SET_PROTO as usize; - true -} - /// Implementation of [`CrossOriginGet`]. /// /// `cx` and `proxy` are expected to be different-Realm here. `proxy` is a proxy /// for a maybe-cross-origin object. /// /// [`CrossOriginGet`]: https://html.spec.whatwg.org/multipage/#crossoriginget-(-o,-p,-receiver-) -pub(crate) unsafe fn cross_origin_get( +pub(crate) unsafe fn cross_origin_get<D: DomTypes>( cx: SafeJSContext, proxy: RawHandleObject, receiver: RawHandleValue, @@ -482,7 +212,7 @@ pub(crate) unsafe fn cross_origin_get( rooted!(in(*cx) let mut getter = ptr::null_mut::<JSObject>()); get_getter_object(&descriptor, getter.handle_mut().into()); if getter.get().is_null() { - return report_cross_origin_denial(cx, id, "get"); + return report_cross_origin_denial::<D>(cx, id, "get"); } rooted!(in(*cx) let mut getter_jsval = UndefinedValue()); @@ -504,7 +234,7 @@ pub(crate) unsafe fn cross_origin_get( /// for a maybe-cross-origin object. /// /// [`CrossOriginSet`]: https://html.spec.whatwg.org/multipage/#crossoriginset-(-o,-p,-v,-receiver-) -pub(crate) unsafe fn cross_origin_set( +pub(crate) unsafe fn cross_origin_set<D: DomTypes>( cx: SafeJSContext, proxy: RawHandleObject, id: RawHandleId, @@ -539,7 +269,7 @@ pub(crate) unsafe fn cross_origin_set( get_setter_object(&descriptor, setter.handle_mut().into()); if setter.get().is_null() { // > 4. Throw a "SecurityError" DOMException. - return report_cross_origin_denial(cx, id, "set"); + return report_cross_origin_denial::<D>(cx, id, "set"); } rooted!(in(*cx) let mut setter_jsval = UndefinedValue()); @@ -568,86 +298,13 @@ pub(crate) unsafe fn cross_origin_set( true } -unsafe fn get_getter_object(d: &PropertyDescriptor, out: RawMutableHandleObject) { - if d.hasGetter_() { - out.set(d.getter_); - } -} - -unsafe fn get_setter_object(d: &PropertyDescriptor, out: RawMutableHandleObject) { - if d.hasSetter_() { - out.set(d.setter_); - } -} - -/// <https://tc39.es/ecma262/#sec-isaccessordescriptor> -fn is_accessor_descriptor(d: &PropertyDescriptor) -> bool { - d.hasSetter_() || d.hasGetter_() -} - -/// <https://tc39.es/ecma262/#sec-isdatadescriptor> -fn is_data_descriptor(d: &PropertyDescriptor) -> bool { - d.hasWritable_() || d.hasValue_() -} - -/// Evaluate `CrossOriginGetOwnPropertyHelper(proxy, id) != null`. -/// SpiderMonkey-specific. -/// -/// `cx` and `proxy` are expected to be different-Realm here. `proxy` is a proxy -/// for a maybe-cross-origin object. -pub(crate) unsafe fn cross_origin_has_own( - cx: SafeJSContext, - _proxy: RawHandleObject, - cross_origin_properties: &'static CrossOriginProperties, - id: RawHandleId, - bp: *mut bool, -) -> bool { - // TODO: Once we have the slot for the holder, it'd be more efficient to - // use `ensure_cross_origin_property_holder`. We'll need `_proxy` to - // do that. - *bp = jsid_to_string(*cx, Handle::from_raw(id)).is_some_and(|key| { - cross_origin_properties.keys().any(|defined_key| { - let defined_key = CStr::from_ptr(defined_key); - defined_key.to_bytes() == key.as_bytes() - }) - }); - - true -} - -/// Implementation of [`CrossOriginGetOwnPropertyHelper`]. -/// -/// `cx` and `proxy` are expected to be different-Realm here. `proxy` is a proxy -/// for a maybe-cross-origin object. -/// -/// [`CrossOriginGetOwnPropertyHelper`]: https://html.spec.whatwg.org/multipage/#crossorigingetownpropertyhelper-(-o,-p-) -pub(crate) unsafe fn cross_origin_get_own_property_helper( - cx: SafeJSContext, - proxy: RawHandleObject, - cross_origin_properties: &'static CrossOriginProperties, - id: RawHandleId, - desc: RawMutableHandle<PropertyDescriptor>, - is_none: &mut bool, -) -> bool { - rooted!(in(*cx) let mut holder = ptr::null_mut::<JSObject>()); - - ensure_cross_origin_property_holder( - cx, - proxy, - cross_origin_properties, - holder.handle_mut().into(), - ); - - JS_GetOwnPropertyDescriptorById(*cx, holder.handle().into(), id, desc, is_none) -} - /// Implementation of [`CrossOriginPropertyFallback`]. /// /// `cx` and `proxy` are expected to be different-Realm here. `proxy` is a proxy /// for a maybe-cross-origin object. /// /// [`CrossOriginPropertyFallback`]: https://html.spec.whatwg.org/multipage/#crossoriginpropertyfallback-(-p-) -pub(crate) unsafe fn cross_origin_property_fallback( +pub(crate) unsafe fn cross_origin_property_fallback<D: DomTypes>( cx: SafeJSContext, _proxy: RawHandleObject, id: RawHandleId, @@ -671,96 +328,5 @@ pub(crate) unsafe fn cross_origin_property_fallback( } // > 2. Throw a `SecurityError` `DOMException`. - report_cross_origin_denial(cx, id, "access") -} - -const ALLOWLISTED_SYMBOL_CODES: &[SymbolCode] = &[ - SymbolCode::toStringTag, - SymbolCode::hasInstance, - SymbolCode::isConcatSpreadable, -]; - -unsafe fn is_cross_origin_allowlisted_prop(cx: SafeJSContext, id: RawHandleId) -> bool { - if jsid_to_string(*cx, Handle::from_raw(id)).is_some_and(|st| st == "then") { - return true; - } - - rooted!(in(*cx) let mut allowed_id: jsid); - ALLOWLISTED_SYMBOL_CODES.iter().any(|&allowed_code| { - allowed_id.set(SymbolId(GetWellKnownSymbol(*cx, allowed_code))); - // `jsid`s containing `JS::Symbol *` can be compared by - // referential equality - allowed_id.get().asBits_ == id.asBits_ - }) -} - -/// Append `« "then", @@toStringTag, @@hasInstance, @@isConcatSpreadable »` to -/// `props`. This is used to implement [`CrossOriginOwnPropertyKeys`]. -/// -/// [`CrossOriginOwnPropertyKeys`]: https://html.spec.whatwg.org/multipage/#crossoriginownpropertykeys-(-o-) -unsafe fn append_cross_origin_allowlisted_prop_keys( - cx: SafeJSContext, - props: RawMutableHandleIdVector, -) { - rooted!(in(*cx) let mut id: jsid); - - let jsstring = JS_AtomizeAndPinString(*cx, c"then".as_ptr()); - rooted!(in(*cx) let rooted = jsstring); - RUST_INTERNED_STRING_TO_JSID(*cx, rooted.handle().get(), id.handle_mut()); - AppendToIdVector(props, id.handle()); - - for &allowed_code in ALLOWLISTED_SYMBOL_CODES.iter() { - id.set(SymbolId(GetWellKnownSymbol(*cx, allowed_code))); - AppendToIdVector(props, id.handle()); - } -} - -/// Get the holder for cross-origin properties for the current global of the -/// `JSContext`, creating one and storing it in a slot of the proxy object if it -/// doesn't exist yet. -/// -/// This essentially creates a cache of [`CrossOriginGetOwnPropertyHelper`]'s -/// results for all property keys. -/// -/// `cx` and `proxy` are expected to be different-Realm here. `proxy` is a proxy -/// for a maybe-cross-origin object. The `out_holder` return value will always -/// be in the Realm of `cx`. -/// -/// [`CrossOriginGetOwnPropertyHelper`]: https://html.spec.whatwg.org/multipage/#crossorigingetownpropertyhelper-(-o,-p-) -unsafe fn ensure_cross_origin_property_holder( - cx: SafeJSContext, - _proxy: RawHandleObject, - cross_origin_properties: &'static CrossOriginProperties, - out_holder: RawMutableHandleObject, -) -> bool { - // TODO: We don't have the slot to store the holder yet. For now, - // the holder is constructed every time this function is called, - // which is not only inefficient but also deviates from the - // specification in a subtle yet observable way. - - // Create a holder for the current Realm - out_holder.set(jsapi::JS_NewObjectWithGivenProto( - *cx, - ptr::null_mut(), - RawHandleObject::null(), - )); - - if out_holder.get().is_null() || - !jsapi::JS_DefineProperties( - *cx, - out_holder.handle(), - cross_origin_properties.attributes.as_ptr(), - ) || - !jsapi::JS_DefineFunctions( - *cx, - out_holder.handle(), - cross_origin_properties.methods.as_ptr(), - ) - { - return false; - } - - // TODO: Store the holder in the slot that we don't have yet. - - true + report_cross_origin_denial::<D>(cx, id, "access") } diff --git a/components/script/dom/bindings/root.rs b/components/script/dom/bindings/root.rs index 4e8cbf21882..923aa51351d 100644 --- a/components/script/dom/bindings/root.rs +++ b/components/script/dom/bindings/root.rs @@ -57,26 +57,6 @@ impl Drop for ThreadLocalStackRoots<'_> { } } -/// Get a slice of references to DOM objects. -pub(crate) trait DomSlice<T> -where - T: JSTraceable + DomObject, -{ - /// Returns the slice of `T` references. - fn r(&self) -> &[&T]; -} - -impl<T> DomSlice<T> for [Dom<T>] -where - T: JSTraceable + DomObject, -{ - #[inline] - fn r(&self) -> &[&T] { - let _ = mem::transmute::<Dom<T>, &T>; - unsafe { &*(self as *const [Dom<T>] as *const [&T]) } - } -} - pub(crate) trait ToLayout<T> { /// Returns `LayoutDom<T>` containing the same pointer. /// diff --git a/components/script/dom/bindings/utils.rs b/components/script/dom/bindings/utils.rs index f97c7188f32..5f16d3a96d2 100644 --- a/components/script/dom/bindings/utils.rs +++ b/components/script/dom/bindings/utils.rs @@ -5,29 +5,34 @@ //! Various utilities to glue JavaScript and the DOM implementation together. use std::cell::RefCell; -use std::os::raw::c_char; use std::thread::LocalKey; use std::{ptr, slice}; use js::conversions::ToJSValConvertible; -use js::glue::{IsWrapper, UnwrapObjectDynamic, UnwrapObjectStatic}; +use js::glue::{IsWrapper, JSPrincipalsCallbacks, UnwrapObjectDynamic, UnwrapObjectStatic}; use js::jsapi::{ - CallArgs, DOMCallbacks, HandleId as RawHandleId, HandleObject as RawHandleObject, Heap, + CallArgs, DOMCallbacks, HandleId as RawHandleId, HandleObject as RawHandleObject, JS_DeprecatedStringHasLatin1Chars, JS_EnumerateStandardClasses, JS_FreezeObject, JS_GetLatin1StringCharsAndLength, JS_IsGlobalObject, JS_ResolveStandardClass, JSContext, - JSObject, JSTracer, MutableHandleIdVector as RawMutableHandleIdVector, + JSObject, MutableHandleIdVector as RawMutableHandleIdVector, }; use js::rust::{Handle, HandleObject, MutableHandleValue, get_object_class, is_dom_class}; use crate::DomTypes; use crate::dom::bindings::codegen::{InterfaceObjectMap, PrototypeList}; -use crate::dom::bindings::constructor::call_html_constructor; +use crate::dom::bindings::constructor::{ + call_html_constructor, pop_current_element_queue, push_new_element_queue, +}; use crate::dom::bindings::conversions::DerivedFrom; -use crate::dom::bindings::error::{Error, throw_dom_exception}; -use crate::dom::bindings::reflector::DomObject; +use crate::dom::bindings::error::{Error, report_pending_exception, throw_dom_exception}; +use crate::dom::bindings::principals::PRINCIPALS_CALLBACKS; +use crate::dom::bindings::proxyhandler::is_platform_object_same_origin; +use crate::dom::bindings::reflector::{DomObject, DomObjectWrap, reflect_dom_object}; +use crate::dom::bindings::root::DomRoot; use crate::dom::bindings::settings_stack::{self, StackEntry}; -use crate::dom::bindings::trace::trace_object; +use crate::dom::globalscope::GlobalScope; use crate::dom::windowproxy::WindowProxyHandler; +use crate::realms::InRealm; use crate::script_runtime::{CanGc, JSContext as SafeJSContext}; #[derive(JSTraceable, MallocSizeOf)] @@ -100,22 +105,8 @@ fn is_platform_object( } } -/// Trace the resources held by reserved slots of a global object -pub(crate) unsafe fn trace_global(tracer: *mut JSTracer, obj: *mut JSObject) { - let array = get_proto_or_iface_array(obj); - for proto in (*array).iter() { - if !proto.is_null() { - trace_object( - tracer, - "prototype", - &*(proto as *const *mut JSObject as *const Heap<*mut JSObject>), - ); - } - } -} - /// Enumerate lazy properties of a global object. -pub(crate) unsafe extern "C" fn enumerate_global( +pub(crate) unsafe extern "C" fn enumerate_global<D: DomTypes>( cx: *mut JSContext, obj: RawHandleObject, _props: RawMutableHandleIdVector, @@ -125,14 +116,14 @@ pub(crate) unsafe extern "C" fn enumerate_global( if !JS_EnumerateStandardClasses(cx, obj) { return false; } - for init_fun in InterfaceObjectMap::MAP.values() { + for init_fun in <D as DomHelpers<D>>::interface_map().values() { init_fun(SafeJSContext::from_ptr(cx), Handle::from_raw(obj)); } true } /// Resolve a lazy global property, for interface objects and named constructors. -pub(crate) unsafe extern "C" fn resolve_global( +pub(crate) unsafe extern "C" fn resolve_global<D: DomTypes>( cx: *mut JSContext, obj: RawHandleObject, id: RawHandleId, @@ -160,7 +151,7 @@ pub(crate) unsafe extern "C" fn resolve_global( assert!(!ptr.is_null()); let bytes = slice::from_raw_parts(ptr, length); - if let Some(init_fun) = InterfaceObjectMap::MAP.get(bytes) { + if let Some(init_fun) = <D as DomHelpers<D>>::interface_map().get(bytes) { init_fun(SafeJSContext::from_ptr(cx), Handle::from_raw(obj)); *rval = true; } else { @@ -184,30 +175,14 @@ pub(crate) const DOM_CALLBACKS: DOMCallbacks = DOMCallbacks { instanceClassMatchesProto: Some(instance_class_has_proto_at_depth), }; -// Generic method for returning libc::c_void from caller -pub(crate) trait AsVoidPtr { - fn as_void_ptr(&self) -> *const libc::c_void; -} -impl<T> AsVoidPtr for T { - fn as_void_ptr(&self) -> *const libc::c_void { - self as *const T as *const libc::c_void - } -} - -// Generic method for returning c_char from caller -pub(crate) trait AsCCharPtrPtr { - fn as_c_char_ptr(&self) -> *const c_char; -} - -impl AsCCharPtrPtr for [u8] { - fn as_c_char_ptr(&self) -> *const c_char { - self as *const [u8] as *const c_char - } -} - /// Operations that must be invoked from the generated bindings. pub(crate) trait DomHelpers<D: DomTypes> { - fn throw_dom_exception(cx: SafeJSContext, global: &D::GlobalScope, result: Error); + fn throw_dom_exception( + cx: SafeJSContext, + global: &D::GlobalScope, + result: Error, + can_gc: CanGc, + ); unsafe fn call_html_constructor<T: DerivedFrom<D::Element> + DomObject>( cx: SafeJSContext, @@ -219,6 +194,27 @@ pub(crate) trait DomHelpers<D: DomTypes> { ) -> bool; fn settings_stack() -> &'static LocalKey<RefCell<Vec<StackEntry<D>>>>; + + fn principals_callbacks() -> &'static JSPrincipalsCallbacks; + + fn is_platform_object_same_origin(cx: SafeJSContext, obj: RawHandleObject) -> bool; + + fn interface_map() -> &'static phf::Map<&'static [u8], for<'a> fn(SafeJSContext, HandleObject)>; + + fn push_new_element_queue(); + fn pop_current_element_queue(can_gc: CanGc); + + fn reflect_dom_object<T, U>(obj: Box<T>, global: &U, can_gc: CanGc) -> DomRoot<T> + where + T: DomObject + DomObjectWrap<D>, + U: DerivedFrom<D::GlobalScope>; + + fn report_pending_exception( + cx: SafeJSContext, + dispatch_event: bool, + realm: InRealm, + can_gc: CanGc, + ); } impl DomHelpers<crate::DomTypeHolder> for crate::DomTypeHolder { @@ -226,8 +222,9 @@ impl DomHelpers<crate::DomTypeHolder> for crate::DomTypeHolder { cx: SafeJSContext, global: &<crate::DomTypeHolder as DomTypes>::GlobalScope, result: Error, + can_gc: CanGc, ) { - throw_dom_exception(cx, global, result, CanGc::note()) + throw_dom_exception(cx, global, result, can_gc) } unsafe fn call_html_constructor< @@ -246,4 +243,41 @@ impl DomHelpers<crate::DomTypeHolder> for crate::DomTypeHolder { fn settings_stack() -> &'static LocalKey<RefCell<Vec<StackEntry<crate::DomTypeHolder>>>> { &settings_stack::STACK } + + fn principals_callbacks() -> &'static JSPrincipalsCallbacks { + &PRINCIPALS_CALLBACKS + } + + fn is_platform_object_same_origin(cx: SafeJSContext, obj: RawHandleObject) -> bool { + unsafe { is_platform_object_same_origin(cx, obj) } + } + + fn interface_map() -> &'static phf::Map<&'static [u8], for<'a> fn(SafeJSContext, HandleObject)> + { + &InterfaceObjectMap::MAP + } + + fn push_new_element_queue() { + push_new_element_queue() + } + fn pop_current_element_queue(can_gc: CanGc) { + pop_current_element_queue(can_gc) + } + + fn reflect_dom_object<T, U>(obj: Box<T>, global: &U, can_gc: CanGc) -> DomRoot<T> + where + T: DomObject + DomObjectWrap<crate::DomTypeHolder>, + U: DerivedFrom<GlobalScope>, + { + reflect_dom_object(obj, global, can_gc) + } + + fn report_pending_exception( + cx: SafeJSContext, + dispatch_event: bool, + realm: InRealm, + can_gc: CanGc, + ) { + report_pending_exception(cx, dispatch_event, realm, can_gc) + } } diff --git a/components/script/dom/blob.rs b/components/script/dom/blob.rs index 75fa65deff0..d23cb62002e 100644 --- a/components/script/dom/blob.rs +++ b/components/script/dom/blob.rs @@ -243,7 +243,7 @@ impl BlobMethods<crate::DomTypeHolder> for Blob { // https://w3c.github.io/FileAPI/#text-method-algo fn Text(&self, can_gc: CanGc) -> Rc<Promise> { let global = self.global(); - let in_realm_proof = AlreadyInRealm::assert(); + let in_realm_proof = AlreadyInRealm::assert::<crate::DomTypeHolder>(); let p = Promise::new_in_current_realm(InRealm::Already(&in_realm_proof), can_gc); let id = self.get_blob_url_id(); global.read_file_async( @@ -266,7 +266,7 @@ impl BlobMethods<crate::DomTypeHolder> for Blob { // https://w3c.github.io/FileAPI/#arraybuffer-method-algo fn ArrayBuffer(&self, can_gc: CanGc) -> Rc<Promise> { let global = self.global(); - let in_realm_proof = AlreadyInRealm::assert(); + let in_realm_proof = AlreadyInRealm::assert::<crate::DomTypeHolder>(); let p = Promise::new_in_current_realm(InRealm::Already(&in_realm_proof), can_gc); let id = self.get_blob_url_id(); diff --git a/components/script/dom/bluetooth/bluetooth.rs b/components/script/dom/bluetooth/bluetooth.rs index c2732f2e9fb..91b07732630 100644 --- a/components/script/dom/bluetooth/bluetooth.rs +++ b/components/script/dom/bluetooth/bluetooth.rs @@ -300,7 +300,7 @@ where T: AsyncBluetoothListener + DomObject + 'static, F: FnOnce(StringOrUnsignedLong) -> Fallible<UUID>, { - let in_realm_proof = AlreadyInRealm::assert(); + let in_realm_proof = AlreadyInRealm::assert::<crate::DomTypeHolder>(); let p = Promise::new_in_current_realm(InRealm::Already(&in_realm_proof), can_gc); let result_uuid = if let Some(u) = uuid { diff --git a/components/script/dom/characterdata.rs b/components/script/dom/characterdata.rs index fe677a6b7b2..d161fddd8d8 100644 --- a/components/script/dom/characterdata.rs +++ b/components/script/dom/characterdata.rs @@ -6,12 +6,12 @@ use std::cell::LazyCell; use dom_struct::dom_struct; +use script_bindings::codegen::InheritTypes::{CharacterDataTypeId, NodeTypeId, TextTypeId}; use crate::dom::bindings::cell::{DomRefCell, Ref}; use crate::dom::bindings::codegen::Bindings::CharacterDataBinding::CharacterDataMethods; use crate::dom::bindings::codegen::Bindings::NodeBinding::Node_Binding::NodeMethods; use crate::dom::bindings::codegen::Bindings::ProcessingInstructionBinding::ProcessingInstructionMethods; -use crate::dom::bindings::codegen::InheritTypes::{CharacterDataTypeId, NodeTypeId, TextTypeId}; use crate::dom::bindings::codegen::UnionTypes::NodeOrString; use crate::dom::bindings::error::{Error, ErrorResult, Fallible}; use crate::dom::bindings::inheritance::Castable; diff --git a/components/script/dom/clipboardevent.rs b/components/script/dom/clipboardevent.rs index eccf590e792..3cacb18a28a 100644 --- a/components/script/dom/clipboardevent.rs +++ b/components/script/dom/clipboardevent.rs @@ -41,7 +41,7 @@ impl ClipboardEventType { } #[dom_struct] -pub struct ClipboardEvent { +pub(crate) struct ClipboardEvent { event: Event, clipboard_data: MutNullableDom<DataTransfer>, } diff --git a/components/script/dom/document.rs b/components/script/dom/document.rs index 146ef3ffacb..dd521776702 100644 --- a/components/script/dom/document.rs +++ b/components/script/dom/document.rs @@ -4384,7 +4384,7 @@ impl Document { // https://fullscreen.spec.whatwg.org/#dom-element-requestfullscreen pub(crate) fn enter_fullscreen(&self, pending: &Element, can_gc: CanGc) -> Rc<Promise> { // Step 1 - let in_realm_proof = AlreadyInRealm::assert(); + let in_realm_proof = AlreadyInRealm::assert::<crate::DomTypeHolder>(); let promise = Promise::new_in_current_realm(InRealm::Already(&in_realm_proof), can_gc); let mut error = false; @@ -4452,7 +4452,7 @@ impl Document { pub(crate) fn exit_fullscreen(&self, can_gc: CanGc) -> Rc<Promise> { let global = self.global(); // Step 1 - let in_realm_proof = AlreadyInRealm::assert(); + let in_realm_proof = AlreadyInRealm::assert::<crate::DomTypeHolder>(); let promise = Promise::new_in_current_realm(InRealm::Already(&in_realm_proof), can_gc); // Step 2 if self.fullscreen_element.get().is_none() { diff --git a/components/script/dom/globalscope.rs b/components/script/dom/globalscope.rs index cb700d7d4c2..7b8169a06a6 100644 --- a/components/script/dom/globalscope.rs +++ b/components/script/dom/globalscope.rs @@ -2696,7 +2696,7 @@ impl GlobalScope { options: &ImageBitmapOptions, can_gc: CanGc, ) -> Rc<Promise> { - let in_realm_proof = AlreadyInRealm::assert(); + let in_realm_proof = AlreadyInRealm::assert::<crate::DomTypeHolder>(); let p = Promise::new_in_current_realm(InRealm::Already(&in_realm_proof), can_gc); if options.resizeWidth.is_some_and(|w| w == 0) { p.reject_error(Error::InvalidState, can_gc); diff --git a/components/script/dom/htmlmediaelement.rs b/components/script/dom/htmlmediaelement.rs index 94c962968dc..31b0d5c6d5d 100644 --- a/components/script/dom/htmlmediaelement.rs +++ b/components/script/dom/htmlmediaelement.rs @@ -27,6 +27,9 @@ use net_traits::{ ResourceTimingType, }; use pixels::Image; +use script_bindings::codegen::InheritTypes::{ + ElementTypeId, HTMLElementTypeId, HTMLMediaElementTypeId, NodeTypeId, +}; use script_layout_interface::MediaFrame; use servo_config::pref; use servo_media::player::audio::AudioRenderer; @@ -60,9 +63,6 @@ use crate::dom::bindings::codegen::Bindings::ShadowRootBinding::{ use crate::dom::bindings::codegen::Bindings::TextTrackBinding::{TextTrackKind, TextTrackMode}; use crate::dom::bindings::codegen::Bindings::URLBinding::URLMethods; use crate::dom::bindings::codegen::Bindings::WindowBinding::Window_Binding::WindowMethods; -use crate::dom::bindings::codegen::InheritTypes::{ - ElementTypeId, HTMLElementTypeId, HTMLMediaElementTypeId, NodeTypeId, -}; use crate::dom::bindings::codegen::UnionTypes::{ MediaStreamOrBlob, VideoTrackOrAudioTrackOrTextTrack, }; diff --git a/components/script/dom/htmlslotelement.rs b/components/script/dom/htmlslotelement.rs index 2deb6b068e4..022cbbf388a 100644 --- a/components/script/dom/htmlslotelement.rs +++ b/components/script/dom/htmlslotelement.rs @@ -8,6 +8,7 @@ use dom_struct::dom_struct; use html5ever::{LocalName, Prefix, local_name, namespace_url, ns}; use js::gc::RootedVec; use js::rust::HandleObject; +use script_bindings::codegen::InheritTypes::{CharacterDataTypeId, NodeTypeId}; use crate::ScriptThread; use crate::dom::attr::Attr; @@ -19,7 +20,6 @@ use crate::dom::bindings::codegen::Bindings::ShadowRootBinding::ShadowRoot_Bindi use crate::dom::bindings::codegen::Bindings::ShadowRootBinding::{ ShadowRootMode, SlotAssignmentMode, }; -use crate::dom::bindings::codegen::InheritTypes::{CharacterDataTypeId, NodeTypeId}; use crate::dom::bindings::codegen::UnionTypes::ElementOrText; use crate::dom::bindings::inheritance::Castable; use crate::dom::bindings::root::{Dom, DomRoot}; @@ -35,7 +35,7 @@ use crate::script_runtime::CanGc; /// <https://html.spec.whatwg.org/multipage/#the-slot-element> #[dom_struct] -pub struct HTMLSlotElement { +pub(crate) struct HTMLSlotElement { htmlelement: HTMLElement, /// <https://dom.spec.whatwg.org/#slot-assigned-nodes> diff --git a/components/script/dom/mediadevices.rs b/components/script/dom/mediadevices.rs index f2f5a45d09c..78d145103a5 100644 --- a/components/script/dom/mediadevices.rs +++ b/components/script/dom/mediadevices.rs @@ -79,7 +79,7 @@ impl MediaDevicesMethods<crate::DomTypeHolder> for MediaDevices { /// <https://w3c.github.io/mediacapture-main/#dom-mediadevices-enumeratedevices> fn EnumerateDevices(&self, can_gc: CanGc) -> Rc<Promise> { // Step 1. - let in_realm_proof = AlreadyInRealm::assert(); + let in_realm_proof = AlreadyInRealm::assert::<crate::DomTypeHolder>(); let p = Promise::new_in_current_realm(InRealm::Already(&in_realm_proof), can_gc); // Step 2. diff --git a/components/script/dom/mod.rs b/components/script/dom/mod.rs index 717e5a1f5b9..a34e0b44221 100644 --- a/components/script/dom/mod.rs +++ b/components/script/dom/mod.rs @@ -205,6 +205,7 @@ #[macro_use] pub(crate) mod macros; +#[allow(unused_imports)] pub(crate) mod types { include!(concat!(env!("BINDINGS_OUT_DIR"), "/InterfaceTypes.rs")); } diff --git a/components/script/dom/node.rs b/components/script/dom/node.rs index 5cbcbb6f43c..d89263d2bf2 100644 --- a/components/script/dom/node.rs +++ b/components/script/dom/node.rs @@ -28,6 +28,7 @@ use js::rust::HandleObject; use libc::{self, c_void, uintptr_t}; use malloc_size_of::{MallocSizeOf, MallocSizeOfOps}; use pixels::{Image, ImageMetadata}; +use script_bindings::codegen::InheritTypes::DocumentFragmentTypeId; use script_layout_interface::{ GenericLayoutData, HTMLCanvasData, HTMLMediaData, LayoutElementType, LayoutNodeType, QueryMsg, SVGSVGData, StyleData, TrustedNodeAddress, @@ -71,7 +72,6 @@ use crate::dom::bindings::codegen::Bindings::ShadowRootBinding::{ ShadowRootMode, SlotAssignmentMode, }; use crate::dom::bindings::codegen::Bindings::WindowBinding::WindowMethods; -use crate::dom::bindings::codegen::InheritTypes::DocumentFragmentTypeId; use crate::dom::bindings::codegen::UnionTypes::NodeOrString; use crate::dom::bindings::conversions::{self, DerivedFrom}; use crate::dom::bindings::error::{Error, ErrorResult, Fallible}; diff --git a/components/script/dom/permissions.rs b/components/script/dom/permissions.rs index 0be136b8aff..ed611db79a8 100644 --- a/components/script/dom/permissions.rs +++ b/components/script/dom/permissions.rs @@ -95,7 +95,7 @@ impl Permissions { let p = match promise { Some(promise) => promise, None => { - let in_realm_proof = AlreadyInRealm::assert(); + let in_realm_proof = AlreadyInRealm::assert::<crate::DomTypeHolder>(); Promise::new_in_current_realm(InRealm::Already(&in_realm_proof), can_gc) }, }; diff --git a/components/script/dom/window.rs b/components/script/dom/window.rs index 0479f24fac8..4da445c20c6 100644 --- a/components/script/dom/window.rs +++ b/components/script/dom/window.rs @@ -57,6 +57,7 @@ use num_traits::ToPrimitive; use profile_traits::ipc as ProfiledIpc; use profile_traits::mem::ProfilerChan as MemProfilerChan; use profile_traits::time::ProfilerChan as TimeProfilerChan; +use script_bindings::interfaces::WindowHelpers; use script_layout_interface::{ FragmentType, Layout, PendingImageState, QueryMsg, Reflow, ReflowGoal, ReflowRequest, TrustedNodeAddress, combine_id_with_fragment_type, @@ -3122,3 +3123,13 @@ unsafe extern "C" fn dump_js_stack(cx: *mut RawJSContext) { DumpJSStack(cx, true, false, false); } } + +impl WindowHelpers for Window { + fn create_named_properties_object( + cx: JSContext, + proto: HandleObject, + object: MutableHandleObject, + ) { + Self::create_named_properties_object(cx, proto, object) + } +} diff --git a/components/script/realms.rs b/components/script/realms.rs index 434aa93a0a2..1254b604b42 100644 --- a/components/script/realms.rs +++ b/components/script/realms.rs @@ -4,17 +4,18 @@ use js::jsapi::{GetCurrentRealmOrNull, JSAutoRealm}; +use crate::DomTypes; use crate::dom::bindings::reflector::DomObject; -use crate::dom::globalscope::GlobalScope; +use crate::dom::globalscope::GlobalScopeHelpers; use crate::script_runtime::JSContext; pub(crate) struct AlreadyInRealm(()); impl AlreadyInRealm { #![allow(unsafe_code)] - pub(crate) fn assert() -> AlreadyInRealm { + pub(crate) fn assert<D: DomTypes>() -> AlreadyInRealm { unsafe { - assert!(!GetCurrentRealmOrNull(*GlobalScope::get_cx()).is_null()); + assert!(!GetCurrentRealmOrNull(*D::GlobalScope::get_cx()).is_null()); } AlreadyInRealm(()) } @@ -55,9 +56,13 @@ impl InRealm<'_> { } } -pub(crate) fn enter_realm(object: &impl DomObject) -> JSAutoRealm { +pub(crate) fn enter_realm_generic<D: DomTypes>(object: &impl DomObject) -> JSAutoRealm { JSAutoRealm::new( - *GlobalScope::get_cx(), + *D::GlobalScope::get_cx(), object.reflector().get_jsobject().get(), ) } + +pub(crate) fn enter_realm(object: &impl DomObject) -> JSAutoRealm { + enter_realm_generic::<crate::DomTypeHolder>(object) +} |