aboutsummaryrefslogtreecommitdiffstats
path: root/components/script/dom/bindings
diff options
context:
space:
mode:
Diffstat (limited to 'components/script/dom/bindings')
-rw-r--r--components/script/dom/bindings/callback.rs295
-rw-r--r--components/script/dom/bindings/constructor.rs51
-rw-r--r--components/script/dom/bindings/conversions.rs97
-rw-r--r--components/script/dom/bindings/guard.rs96
-rw-r--r--components/script/dom/bindings/import.rs159
-rw-r--r--components/script/dom/bindings/interface.rs696
-rw-r--r--components/script/dom/bindings/iterable.rs180
-rw-r--r--components/script/dom/bindings/mod.rs33
-rw-r--r--components/script/dom/bindings/namespace.rs62
-rw-r--r--components/script/dom/bindings/principals.rs123
-rw-r--r--components/script/dom/bindings/proxyhandler.rs292
-rw-r--r--components/script/dom/bindings/reflector.rs69
-rw-r--r--components/script/dom/bindings/settings_stack.rs143
-rw-r--r--components/script/dom/bindings/trace.rs70
-rw-r--r--components/script/dom/bindings/utils.rs111
-rw-r--r--components/script/dom/bindings/weakref.rs2
16 files changed, 57 insertions, 2422 deletions
diff --git a/components/script/dom/bindings/callback.rs b/components/script/dom/bindings/callback.rs
deleted file mode 100644
index 6a54255822f..00000000000
--- a/components/script/dom/bindings/callback.rs
+++ /dev/null
@@ -1,295 +0,0 @@
-/* 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 https://mozilla.org/MPL/2.0/. */
-
-//! Base classes to work with IDL callbacks.
-
-use std::default::Default;
-use std::ffi::CString;
-use std::mem::drop;
-use std::rc::Rc;
-
-use js::jsapi::{
- AddRawValueRoot, EnterRealm, Heap, IsCallable, JSObject, LeaveRealm, Realm, RemoveRawValueRoot,
-};
-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};
-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::DomHelpers;
-use crate::dom::globalscope::GlobalScopeHelpers;
-use crate::realms::{InRealm, enter_realm};
-use crate::script_runtime::{CanGc, JSContext};
-
-/// The exception handling used for a call.
-#[derive(Clone, Copy, PartialEq)]
-pub(crate) enum ExceptionHandling {
- /// Report any exception and don't throw it to the caller code.
- Report,
- /// Throw any exception to the caller code.
- Rethrow,
-}
-
-/// A common base class for representing IDL callback function and
-/// callback interface types.
-#[derive(JSTraceable)]
-#[cfg_attr(crown, crown::unrooted_must_root_lint::must_root)]
-pub(crate) struct CallbackObject<D: DomTypes> {
- /// The underlying `JSObject`.
- callback: Heap<*mut JSObject>,
- permanent_js_root: Heap<JSVal>,
-
- /// The ["callback context"], that is, the global to use as incumbent
- /// global when calling the callback.
- ///
- /// Looking at the WebIDL standard, it appears as though there would always
- /// be a value here, but [sometimes] callback functions are created by
- /// hand-waving without defining the value of the callback context, and
- /// without any JavaScript code on the stack to grab an incumbent global
- /// from.
- ///
- /// ["callback context"]: https://heycam.github.io/webidl/#dfn-callback-context
- /// [sometimes]: https://github.com/whatwg/html/issues/2248
- incumbent: Option<Dom<D::GlobalScope>>,
-}
-
-impl<D: DomTypes> CallbackObject<D> {
- #[cfg_attr(crown, allow(crown::unrooted_must_root))]
- // These are used by the bindings and do not need `default()` functions.
- #[allow(clippy::new_without_default)]
- fn new() -> Self {
- Self {
- callback: Heap::default(),
- permanent_js_root: Heap::default(),
- incumbent: D::GlobalScope::incumbent().map(|i| Dom::from_ref(&*i)),
- }
- }
-
- pub(crate) fn get(&self) -> *mut JSObject {
- self.callback.get()
- }
-
- #[allow(unsafe_code)]
- unsafe fn init(&mut self, cx: JSContext, callback: *mut JSObject) {
- self.callback.set(callback);
- self.permanent_js_root.set(ObjectValue(callback));
- assert!(AddRawValueRoot(
- *cx,
- self.permanent_js_root.get_unsafe(),
- b"CallbackObject::root\n".as_c_char_ptr()
- ));
- }
-}
-
-impl<D: DomTypes> Drop for CallbackObject<D> {
- #[allow(unsafe_code)]
- fn drop(&mut self) {
- unsafe {
- if let Some(cx) = Runtime::get() {
- RemoveRawValueRoot(cx.as_ptr(), self.permanent_js_root.get_unsafe());
- }
- }
- }
-}
-
-impl<D: DomTypes> PartialEq for CallbackObject<D> {
- fn eq(&self, other: &CallbackObject<D>) -> bool {
- self.callback.get() == other.callback.get()
- }
-}
-
-/// A trait to be implemented by concrete IDL callback function and
-/// callback interface types.
-pub(crate) trait CallbackContainer<D: DomTypes> {
- /// Create a new CallbackContainer object for the given `JSObject`.
- unsafe fn new(cx: JSContext, callback: *mut JSObject) -> Rc<Self>;
- /// Returns the underlying `CallbackObject`.
- fn callback_holder(&self) -> &CallbackObject<D>;
- /// Returns the underlying `JSObject`.
- fn callback(&self) -> *mut JSObject {
- self.callback_holder().get()
- }
- /// Returns the ["callback context"], that is, the global to use as
- /// incumbent global when calling the callback.
- ///
- /// ["callback context"]: https://heycam.github.io/webidl/#dfn-callback-context
- fn incumbent(&self) -> Option<&D::GlobalScope> {
- self.callback_holder().incumbent.as_deref()
- }
-}
-
-/// A common base class for representing IDL callback function types.
-#[derive(JSTraceable, PartialEq)]
-#[cfg_attr(crown, crown::unrooted_must_root_lint::must_root)]
-pub(crate) struct CallbackFunction<D: DomTypes> {
- object: CallbackObject<D>,
-}
-
-impl<D: DomTypes> CallbackFunction<D> {
- /// Create a new `CallbackFunction` for this object.
- #[cfg_attr(crown, allow(crown::unrooted_must_root))]
- // These are used by the bindings and do not need `default()` functions.
- #[allow(clippy::new_without_default)]
- pub(crate) fn new() -> Self {
- Self {
- object: CallbackObject::new(),
- }
- }
-
- /// Returns the underlying `CallbackObject`.
- pub(crate) fn callback_holder(&self) -> &CallbackObject<D> {
- &self.object
- }
-
- /// Initialize the callback function with a value.
- /// Should be called once this object is done moving.
- pub(crate) unsafe fn init(&mut self, cx: JSContext, callback: *mut JSObject) {
- self.object.init(cx, callback);
- }
-}
-
-/// A common base class for representing IDL callback interface types.
-#[derive(JSTraceable, PartialEq)]
-#[cfg_attr(crown, crown::unrooted_must_root_lint::must_root)]
-pub(crate) struct CallbackInterface<D: DomTypes> {
- object: CallbackObject<D>,
-}
-
-impl<D: DomTypes> CallbackInterface<D> {
- /// Create a new CallbackInterface object for the given `JSObject`.
- // These are used by the bindings and do not need `default()` functions.
- #[allow(clippy::new_without_default)]
- pub(crate) fn new() -> Self {
- Self {
- object: CallbackObject::new(),
- }
- }
-
- /// Returns the underlying `CallbackObject`.
- pub(crate) fn callback_holder(&self) -> &CallbackObject<D> {
- &self.object
- }
-
- /// Initialize the callback function with a value.
- /// Should be called once this object is done moving.
- pub(crate) unsafe fn init(&mut self, cx: JSContext, callback: *mut JSObject) {
- self.object.init(cx, callback);
- }
-
- /// Returns the property with the given `name`, if it is a callable object,
- /// or an error otherwise.
- pub(crate) fn get_callable_property(&self, cx: JSContext, name: &str) -> Fallible<JSVal> {
- rooted!(in(*cx) let mut callable = UndefinedValue());
- rooted!(in(*cx) let obj = self.callback_holder().get());
- unsafe {
- let c_name = CString::new(name).unwrap();
- if !JS_GetProperty(*cx, obj.handle(), c_name.as_ptr(), callable.handle_mut()) {
- return Err(Error::JSFailed);
- }
-
- if !callable.is_object() || !IsCallable(callable.to_object()) {
- return Err(Error::Type(format!(
- "The value of the {} property is not callable",
- name
- )));
- }
- }
- Ok(callable.get())
- }
-}
-
-pub(crate) use script_bindings::callback::ThisReflector;
-
-/// Wraps the reflector for `p` into the realm of `cx`.
-pub(crate) fn wrap_call_this_value<T: ThisReflector>(
- cx: JSContext,
- p: &T,
- mut rval: MutableHandleValue,
-) -> bool {
- rooted!(in(*cx) let mut obj = p.jsobject());
- assert!(!obj.is_null());
-
- unsafe {
- if !JS_WrapObject(*cx, obj.handle_mut()) {
- return false;
- }
- }
-
- rval.set(ObjectValue(*obj));
- true
-}
-
-/// A class that performs whatever setup we need to safely make a call while
-/// this class is on the stack. After `new` returns, the call is safe to make.
-pub(crate) struct CallSetup<D: DomTypes> {
- /// The global for reporting exceptions. This is the global object of the
- /// (possibly wrapped) callback object.
- exception_global: DomRoot<D::GlobalScope>,
- /// The `JSContext` used for the call.
- cx: JSContext,
- /// The realm we were in before the call.
- old_realm: *mut Realm,
- /// The exception handling used for the call.
- handling: ExceptionHandling,
- /// <https://heycam.github.io/webidl/#es-invoking-callback-functions>
- /// steps 8 and 18.2.
- entry_script: Option<GenericAutoEntryScript<D>>,
- /// <https://heycam.github.io/webidl/#es-invoking-callback-functions>
- /// steps 9 and 18.1.
- incumbent_script: Option<GenericAutoIncumbentScript<D>>,
-}
-
-impl<D: DomTypes> CallSetup<D> {
- /// Performs the setup needed to make a call.
- #[cfg_attr(crown, allow(crown::unrooted_must_root))]
- pub(crate) fn new<T: CallbackContainer<D>>(callback: &T, handling: ExceptionHandling) -> Self {
- let global = unsafe { D::GlobalScope::from_object(callback.callback()) };
- if let Some(window) = global.downcast::<D::Window>() {
- window.Document().ensure_safe_to_run_script_or_layout();
- }
- let cx = D::GlobalScope::get_cx();
-
- let aes = GenericAutoEntryScript::<D>::new(&global);
- let ais = callback.incumbent().map(GenericAutoIncumbentScript::new);
- CallSetup {
- exception_global: global,
- cx,
- old_realm: unsafe { EnterRealm(*cx, callback.callback()) },
- handling,
- entry_script: Some(aes),
- incumbent_script: ais,
- }
- }
-
- /// Returns the `JSContext` used for the call.
- pub(crate) fn get_context(&self) -> JSContext {
- self.cx
- }
-}
-
-impl<D: DomTypes> Drop for CallSetup<D> {
- fn drop(&mut self) {
- unsafe {
- LeaveRealm(*self.cx, self.old_realm);
- }
- if self.handling == ExceptionHandling::Report {
- let ar = enter_realm(&*self.exception_global);
- <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/constructor.rs b/components/script/dom/bindings/constructor.rs
index ae9305f0767..138dd4520d0 100644
--- a/components/script/dom/bindings/constructor.rs
+++ b/components/script/dom/bindings/constructor.rs
@@ -11,6 +11,7 @@ use js::glue::{UnwrapObjectDynamic, UnwrapObjectStatic};
use js::jsapi::{CallArgs, CurrentGlobalOrNull, JSAutoRealm, JSObject};
use js::rust::wrappers::{JS_SetPrototype, JS_WrapObject};
use js::rust::{HandleObject, MutableHandleObject, MutableHandleValue};
+use script_bindings::interface::get_desired_proto;
use super::utils::ProtoOrIfaceArray;
use crate::dom::bindings::codegen::Bindings::WindowBinding::WindowMethods;
@@ -40,9 +41,8 @@ use crate::dom::bindings::codegen::Bindings::{
};
use crate::dom::bindings::codegen::PrototypeList;
use crate::dom::bindings::conversions::DerivedFrom;
-use crate::dom::bindings::error::{Error, throw_constructor_without_new, throw_dom_exception};
+use crate::dom::bindings::error::{Error, throw_dom_exception};
use crate::dom::bindings::inheritance::Castable;
-use crate::dom::bindings::interface::get_desired_proto;
use crate::dom::bindings::reflector::DomObject;
use crate::dom::bindings::root::DomRoot;
use crate::dom::create::create_native_html_element;
@@ -55,7 +55,7 @@ use crate::script_runtime::{CanGc, JSContext, JSContext as SafeJSContext};
use crate::script_thread::ScriptThread;
/// <https://html.spec.whatwg.org/multipage/#htmlconstructor>
-unsafe fn html_constructor(
+fn html_constructor(
cx: JSContext,
global: &GlobalScope,
call_args: &CallArgs,
@@ -75,7 +75,9 @@ unsafe fn html_constructor(
// The new_target might be a cross-compartment wrapper. Get the underlying object
// so we can do the spec's object-identity checks.
- rooted!(in(*cx) let new_target_unwrapped = UnwrapObjectDynamic(call_args.new_target().to_object(), *cx, true));
+ rooted!(in(*cx) let new_target_unwrapped = unsafe {
+ UnwrapObjectDynamic(call_args.new_target().to_object(), *cx, true)
+ });
if new_target_unwrapped.is_null() {
throw_dom_exception(
cx,
@@ -114,7 +116,7 @@ unsafe fn html_constructor(
// Step 4. Let isValue be null.
let mut is_value = None;
- rooted!(in(*cx) let callee = UnwrapObjectStatic(call_args.callee()));
+ rooted!(in(*cx) let callee = unsafe { UnwrapObjectStatic(call_args.callee()) });
if callee.is_null() {
throw_dom_exception(cx, global, Error::Security, can_gc);
return Err(());
@@ -123,7 +125,7 @@ unsafe fn html_constructor(
{
let _ac = JSAutoRealm::new(*cx, callee.get());
rooted!(in(*cx) let mut constructor = ptr::null_mut::<JSObject>());
- rooted!(in(*cx) let global_object = CurrentGlobalOrNull(*cx));
+ rooted!(in(*cx) let global_object = unsafe { CurrentGlobalOrNull(*cx) });
// Step 5. If definition's local name is equal to definition's name
// (i.e., definition is for an autonomous custom element):
@@ -233,13 +235,15 @@ unsafe fn html_constructor(
};
rooted!(in(*cx) let mut element = result.reflector().get_jsobject().get());
- if !JS_WrapObject(*cx, element.handle_mut()) {
- return Err(());
- }
+ unsafe {
+ if !JS_WrapObject(*cx, element.handle_mut()) {
+ return Err(());
+ }
- JS_SetPrototype(*cx, element.handle(), prototype.handle());
+ JS_SetPrototype(*cx, element.handle(), prototype.handle());
- result.to_jsval(*cx, MutableHandleValue::from_raw(call_args.rval()));
+ result.to_jsval(*cx, MutableHandleValue::from_raw(call_args.rval()));
+ }
Ok(())
}
@@ -395,7 +399,7 @@ pub(crate) fn push_new_element_queue() {
ScriptThread::push_new_element_queue();
}
-pub(crate) unsafe fn call_html_constructor<T: DerivedFrom<Element> + DomObject>(
+pub(crate) fn call_html_constructor<T: DerivedFrom<Element> + DomObject>(
cx: JSContext,
args: &CallArgs,
global: &GlobalScope,
@@ -418,26 +422,3 @@ pub(crate) unsafe fn call_html_constructor<T: DerivedFrom<Element> + DomObject>(
)
.is_ok()
}
-
-pub(crate) unsafe fn call_default_constructor<D: crate::DomTypes>(
- cx: JSContext,
- args: &CallArgs,
- global: &D::GlobalScope,
- proto_id: PrototypeList::ID,
- ctor_name: &str,
- creator: unsafe fn(JSContext, HandleObject, *mut ProtoOrIfaceArray),
- constructor: impl FnOnce(JSContext, &CallArgs, &D::GlobalScope, HandleObject) -> bool,
-) -> bool {
- if !args.is_constructing() {
- throw_constructor_without_new(cx, ctor_name);
- return false;
- }
-
- rooted!(in(*cx) let mut desired_proto = ptr::null_mut::<JSObject>());
- let proto_result = get_desired_proto(cx, args, proto_id, creator, desired_proto.handle_mut());
- if proto_result.is_err() {
- return false;
- }
-
- constructor(cx, args, global, desired_proto.handle())
-}
diff --git a/components/script/dom/bindings/conversions.rs b/components/script/dom/bindings/conversions.rs
index 0ea59e6ee83..f01357fda55 100644
--- a/components/script/dom/bindings/conversions.rs
+++ b/components/script/dom/bindings/conversions.rs
@@ -37,48 +37,15 @@ use std::ffi;
pub(crate) use js::conversions::{
ConversionBehavior, ConversionResult, FromJSValConvertible, ToJSValConvertible,
};
-use js::glue::GetProxyReservedSlot;
-use js::jsapi::{Heap, IsWindowProxy, JS_IsExceptionPending, JSContext, JSObject};
+use js::jsapi::{JS_IsExceptionPending, JSContext, JSObject};
use js::jsval::UndefinedValue;
-use js::rust::wrappers::{IsArrayObject, JS_GetProperty, JS_HasProperty};
-use js::rust::{HandleObject, HandleValue, MutableHandleValue};
-pub(crate) use script_bindings::conversions::*;
+use js::rust::wrappers::{JS_GetProperty, JS_HasProperty};
+use js::rust::{HandleObject, MutableHandleValue};
+pub(crate) use script_bindings::conversions::{is_dom_proxy, *};
use crate::dom::bindings::error::{Error, Fallible};
use crate::dom::bindings::reflector::DomObject;
use crate::dom::bindings::root::DomRoot;
-use crate::dom::bindings::trace::{JSTraceable, RootedTraceableBox};
-
-impl<T: ToJSValConvertible + JSTraceable> ToJSValConvertible for RootedTraceableBox<T> {
- #[inline]
- unsafe fn to_jsval(&self, cx: *mut JSContext, rval: MutableHandleValue) {
- let value = &**self;
- value.to_jsval(cx, rval);
- }
-}
-
-impl<T> FromJSValConvertible for RootedTraceableBox<Heap<T>>
-where
- T: FromJSValConvertible + js::rust::GCMethods + Copy,
- Heap<T>: JSTraceable + Default,
-{
- type Config = T::Config;
-
- unsafe fn from_jsval(
- cx: *mut JSContext,
- value: HandleValue,
- config: Self::Config,
- ) -> Result<ConversionResult<Self>, ()> {
- T::from_jsval(cx, value, config).map(|result| match result {
- ConversionResult::Success(inner) => {
- ConversionResult::Success(RootedTraceableBox::from_box(Heap::boxed(inner)))
- },
- ConversionResult::Failure(msg) => ConversionResult::Failure(msg),
- })
- }
-}
-
-pub(crate) use script_bindings::conversions::is_dom_proxy;
/// Get a `DomRoot<T>` for the given DOM object, unwrapping any wrapper
/// around it first, and checking if the object is of the correct type.
@@ -104,43 +71,6 @@ where
unsafe { root_from_object(obj.get(), cx) }
}
-/// Returns whether `value` is an array-like object (Array, FileList,
-/// HTMLCollection, HTMLFormControlsCollection, HTMLOptionsCollection,
-/// NodeList).
-pub(crate) unsafe fn is_array_like<D: crate::DomTypes>(
- cx: *mut JSContext,
- value: HandleValue,
-) -> bool {
- let mut is_array = false;
- assert!(IsArrayObject(cx, value, &mut is_array));
- if is_array {
- return true;
- }
-
- let object: *mut JSObject = match FromJSValConvertible::from_jsval(cx, value, ()).unwrap() {
- ConversionResult::Success(object) => object,
- _ => return false,
- };
-
- if root_from_object::<D::FileList>(object, cx).is_ok() {
- return true;
- }
- if root_from_object::<D::HTMLCollection>(object, cx).is_ok() {
- return true;
- }
- if root_from_object::<D::HTMLFormControlsCollection>(object, cx).is_ok() {
- return true;
- }
- if root_from_object::<D::HTMLOptionsCollection>(object, cx).is_ok() {
- return true;
- }
- if root_from_object::<D::NodeList>(object, cx).is_ok() {
- return true;
- }
-
- false
-}
-
/// Get a property from a JS object.
pub(crate) unsafe fn get_property_jsval(
cx: *mut JSContext,
@@ -191,22 +121,3 @@ where
Err(()) => Err(Error::JSFailed),
}
}
-
-/// Get a `DomRoot<T>` for a WindowProxy accessible from a `HandleValue`.
-/// Caller is responsible for throwing a JS exception if needed in case of error.
-pub(crate) unsafe fn windowproxy_from_handlevalue<D: crate::DomTypes>(
- v: HandleValue,
- _cx: *mut JSContext,
-) -> Result<DomRoot<D::WindowProxy>, ()> {
- if !v.get().is_object() {
- return Err(());
- }
- let object = v.get().to_object();
- if !IsWindowProxy(object) {
- return Err(());
- }
- let mut value = UndefinedValue();
- GetProxyReservedSlot(object, 0, &mut value);
- let ptr = value.to_private() as *const D::WindowProxy;
- Ok(DomRoot::from_ref(&*ptr))
-}
diff --git a/components/script/dom/bindings/guard.rs b/components/script/dom/bindings/guard.rs
deleted file mode 100644
index 16b5187abef..00000000000
--- a/components/script/dom/bindings/guard.rs
+++ /dev/null
@@ -1,96 +0,0 @@
-/* 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 https://mozilla.org/MPL/2.0/. */
-
-//! Machinery to conditionally expose things.
-
-use js::rust::HandleObject;
-use script_bindings::codegen::Globals::Globals;
-use servo_config::prefs::get;
-
-use crate::DomTypes;
-use crate::dom::bindings::interface::is_exposed_in;
-use crate::dom::globalscope::GlobalScopeHelpers;
-use crate::realms::{AlreadyInRealm, InRealm};
-use crate::script_runtime::JSContext;
-
-/// A container with a list of conditions.
-pub(crate) struct Guard<T: Clone + Copy> {
- conditions: &'static [Condition],
- value: T,
-}
-
-impl<T: Clone + Copy> Guard<T> {
- /// Construct a new guarded value.
- pub(crate) const fn new(conditions: &'static [Condition], value: T) -> Self {
- Guard { conditions, value }
- }
-
- /// Expose the value if the conditions are satisfied.
- ///
- /// The passed handle is the object on which the value may be exposed.
- pub(crate) fn expose<D: DomTypes>(
- &self,
- cx: JSContext,
- obj: HandleObject,
- global: HandleObject,
- ) -> Option<T> {
- let mut exposed_on_global = false;
- let conditions_satisfied = self.conditions.iter().all(|c| match c {
- Condition::Satisfied => {
- exposed_on_global = true;
- true
- },
- // If there are multiple Exposed conditions, we just need one of them to be true
- Condition::Exposed(globals) => {
- exposed_on_global |= is_exposed_in(global, *globals);
- true
- },
- _ => c.is_satisfied::<D>(cx, obj, global),
- });
-
- if conditions_satisfied && exposed_on_global {
- Some(self.value)
- } else {
- None
- }
- }
-}
-
-/// A condition to expose things.
-#[derive(Clone, Copy)]
-pub(crate) enum Condition {
- /// The condition is satisfied if the function returns true.
- Func(fn(JSContext, HandleObject) -> bool),
- /// The condition is satisfied if the preference is set.
- Pref(&'static str),
- // The condition is satisfied if the interface is exposed in the global.
- Exposed(Globals),
- SecureContext(),
- /// The condition is always satisfied.
- Satisfied,
-}
-
-fn is_secure_context<D: DomTypes>(cx: JSContext) -> bool {
- unsafe {
- let in_realm_proof = AlreadyInRealm::assert_for_cx(JSContext::from_ptr(*cx));
- D::GlobalScope::from_context(*cx, InRealm::Already(&in_realm_proof)).is_secure_context()
- }
-}
-
-impl Condition {
- pub(crate) fn is_satisfied<D: DomTypes>(
- &self,
- cx: JSContext,
- obj: HandleObject,
- global: HandleObject,
- ) -> bool {
- match *self {
- Condition::Pref(name) => get().get_value(name).try_into().unwrap_or(false),
- Condition::Func(f) => f(cx, obj),
- Condition::Exposed(globals) => is_exposed_in(global, globals),
- Condition::SecureContext() => is_secure_context::<D>(cx),
- Condition::Satisfied => true,
- }
- }
-}
diff --git a/components/script/dom/bindings/import.rs b/components/script/dom/bindings/import.rs
index 71ba5e4c994..5042eba1c05 100644
--- a/components/script/dom/bindings/import.rs
+++ b/components/script/dom/bindings/import.rs
@@ -2,169 +2,24 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
-#[allow(unused_imports)]
pub(crate) mod base {
pub(crate) use std::ptr;
- pub(crate) use std::rc::Rc;
- pub(crate) use js::error::throw_type_error;
- pub(crate) use js::jsapi::{
- CurrentGlobalOrNull, HandleValue as RawHandleValue, HandleValueArray, Heap, IsCallable,
- JS_NewObject, JSContext, JSObject,
- };
- pub(crate) use js::jsval::{JSVal, NullValue, ObjectOrNullValue, ObjectValue, UndefinedValue};
- pub(crate) use js::panic::maybe_resume_unwind;
- pub(crate) use js::rust::wrappers::{Call, JS_WrapValue};
- pub(crate) use js::rust::{HandleObject, HandleValue, MutableHandleObject, MutableHandleValue};
- pub(crate) use script_bindings::lock::ThreadUnsafeOnceLock;
+ pub(crate) use js::rust::{HandleObject, MutableHandleObject};
- pub(crate) use crate::dom::bindings::callback::{
- CallSetup, CallbackContainer, CallbackFunction, CallbackInterface, CallbackObject,
- ExceptionHandling, ThisReflector, wrap_call_this_value,
- };
- pub(crate) use crate::dom::bindings::codegen::Bindings::AudioNodeBinding::{
- ChannelCountMode, ChannelCountModeValues, ChannelInterpretation,
- ChannelInterpretationValues,
- };
- pub(crate) use crate::dom::bindings::codegen::DomTypes::DomTypes;
- pub(crate) use crate::dom::bindings::codegen::{GenericUnionTypes, UnionTypes};
- pub(crate) use crate::dom::bindings::conversions::{
- ConversionBehavior, ConversionResult, FromJSValConvertible, StringificationBehavior,
- ToJSValConvertible, root_from_handlevalue,
- };
- pub(crate) use crate::dom::bindings::error::Error::JSFailed;
- pub(crate) use crate::dom::bindings::error::{Fallible, throw_dom_exception};
- pub(crate) use crate::dom::bindings::num::Finite;
- pub(crate) use crate::dom::bindings::proxyhandler::CrossOriginProperties;
- pub(crate) use crate::dom::bindings::reflector::{DomGlobalGeneric, DomObject};
- pub(crate) use crate::dom::bindings::root::DomRoot;
- pub(crate) use crate::dom::bindings::str::{ByteString, DOMString, USVString};
- pub(crate) use crate::dom::bindings::trace::RootedTraceableBox;
- pub(crate) use crate::dom::bindings::utils::{
- DomHelpers, get_dictionary_property, set_dictionary_property,
- };
- pub(crate) use crate::dom::globalscope::{GlobalScope, GlobalScopeHelpers};
- pub(crate) use crate::dom::promise::PromiseHelpers;
- pub(crate) use crate::realms::{AlreadyInRealm, InRealm};
pub(crate) use crate::script_runtime::{CanGc, JSContext as SafeJSContext};
}
-#[allow(unused_imports)]
pub(crate) mod module {
- pub(crate) use std::cmp;
- pub(crate) use std::ffi::CString;
- pub(crate) use std::ptr::NonNull;
-
- pub(crate) use js::glue::{
- CreateProxyHandler, GetProxyReservedSlot, JS_GetReservedSlot, ProxyTraps,
- SetProxyReservedSlot,
- };
- pub(crate) use js::jsapi::{
- __BindgenBitfieldUnit, CallArgs, GCContext, GetRealmErrorPrototype,
- GetRealmFunctionPrototype, GetRealmIteratorPrototype, GetRealmObjectPrototype,
- GetWellKnownSymbol, Handle as RawHandle, HandleId as RawHandleId,
- HandleObject as RawHandleObject, JS_AtomizeAndPinString, JS_ForwardGetPropertyTo,
- JS_GetPropertyDescriptorById, JS_HasPropertyById, JS_NewPlainObject, JS_SetReservedSlot,
- JSAutoRealm, JSCLASS_FOREGROUND_FINALIZE, JSCLASS_RESERVED_SLOTS_SHIFT, JSClass,
- JSClassOps, JSFunctionSpec, JSITER_HIDDEN, JSITER_OWNONLY, JSITER_SYMBOLS,
- JSJitGetterCallArgs, JSJitInfo, JSJitInfo__bindgen_ty_1, JSJitInfo__bindgen_ty_2,
- JSJitInfo__bindgen_ty_3, JSJitInfo_AliasSet, JSJitInfo_ArgType, JSJitInfo_OpType,
- JSJitMethodCallArgs, JSJitSetterCallArgs, JSNativeWrapper, JSPROP_ENUMERATE,
- JSPROP_PERMANENT, JSPROP_READONLY, JSPropertySpec, JSPropertySpec_Accessor,
- JSPropertySpec_AccessorsOrValue, JSPropertySpec_AccessorsOrValue_Accessors,
- JSPropertySpec_Kind, JSPropertySpec_Name, JSPropertySpec_ValueWrapper,
- JSPropertySpec_ValueWrapper__bindgen_ty_1, JSPropertySpec_ValueWrapper_Type, JSTracer,
- JSTypedMethodJitInfo, JSValueType, MutableHandle as RawMutableHandle,
- MutableHandleIdVector as RawMutableHandleIdVector,
- MutableHandleObject as RawMutableHandleObject, MutableHandleValue as RawMutableHandleValue,
- ObjectOpResult, PropertyDescriptor, SymbolCode, UndefinedHandleValue, jsid,
- };
- pub(crate) use js::jsval::PrivateValue;
- pub(crate) use js::panic::wrap_panic;
- pub(crate) use js::rust::wrappers::{
- AppendToIdVector, Call, GetPropertyKeys, JS_CopyOwnPropertiesAndPrivateFields,
- JS_DefineProperty, JS_DefinePropertyById2, JS_GetProperty,
- JS_InitializePropertiesFromCompatibleNativeObject, JS_NewObjectWithGivenProto,
- JS_NewObjectWithoutMetadata, JS_SetImmutablePrototype, JS_SetProperty, JS_SetPrototype,
- JS_WrapObject, NewProxyObject, RUST_INTERNED_STRING_TO_JSID, RUST_SYMBOL_TO_JSID,
- int_to_jsid,
- };
- pub(crate) use js::rust::{
- CustomAutoRooterGuard, GCMethods, Handle, MutableHandle, get_context_realm,
- get_object_class, get_object_realm,
- };
- pub(crate) use js::typedarray::{
- ArrayBuffer, ArrayBufferView, Float32Array, Float64Array, Uint8Array, Uint8ClampedArray,
- };
- pub(crate) use js::{
- JS_CALLEE, JSCLASS_GLOBAL_SLOT_COUNT, JSCLASS_IS_DOMJSCLASS, JSCLASS_IS_GLOBAL,
- JSCLASS_RESERVED_SLOTS_MASK, jsapi, typedarray,
- };
- pub(crate) use script_bindings::codegen::Globals::Globals;
- pub(crate) use script_bindings::constant::{ConstantSpec, ConstantVal};
- pub(crate) use script_bindings::finalize::{
- finalize_common, finalize_global, finalize_weak_referenceable,
- };
- 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 script_bindings::codegen::PrototypeList;
+ pub(crate) use script_bindings::conversions::IDLInterface;
+ pub(crate) use script_bindings::utils::DOMClass;
pub(crate) use super::base::*;
- pub(crate) use crate::dom::bindings::codegen::Bindings::AnalyserNodeBinding::AnalyserOptions;
- pub(crate) use crate::dom::bindings::codegen::Bindings::AudioNodeBinding::{
- AudioNode_Binding, ChannelCountMode, ChannelCountModeValues, ChannelInterpretation,
- ChannelInterpretationValues,
- };
- pub(crate) use crate::dom::bindings::codegen::Bindings::EventTargetBinding::EventTarget_Binding;
- pub(crate) use crate::dom::bindings::codegen::{
- InterfaceObjectMap, PrototypeList, RegisterBindings,
- };
- pub(crate) use crate::dom::bindings::constructor::{
- call_default_constructor, call_html_constructor, pop_current_element_queue,
- push_new_element_queue,
- };
- pub(crate) use crate::dom::bindings::conversions::{
- DOM_OBJECT_SLOT, IDLInterface, StringificationBehavior, ToJSValConvertible, is_array_like,
- jsid_to_string, native_from_handlevalue, native_from_object_static,
- };
- pub(crate) use crate::dom::bindings::error::{
- Error, ErrorResult, throw_constructor_without_new,
- };
- pub(crate) use crate::dom::bindings::guard::{Condition, Guard};
- pub(crate) use crate::dom::bindings::inheritance::Castable;
- pub(crate) use crate::dom::bindings::interface::{
- ConstructorClassHook, InterfaceConstructorBehavior, NonCallbackInterfaceObjectClass,
- ProtoOrIfaceIndex, create_callback_interface_object, create_global_object,
- create_interface_prototype_object, create_named_constructors,
- create_noncallback_interface_object, define_dom_interface, define_guarded_methods,
- define_guarded_properties, get_desired_proto, get_per_interface_object_handle,
- is_exposed_in,
- };
- 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,
- };
- pub(crate) use crate::dom::bindings::proxyhandler;
- pub(crate) use crate::dom::bindings::proxyhandler::{
- ensure_expando_object, get_expando_object, set_property_descriptor,
- };
+ pub(crate) use crate::dom::bindings::iterable::IterableIterator;
pub(crate) use crate::dom::bindings::reflector::{
DomObjectIteratorWrap, DomObjectWrap, Reflector,
};
- pub(crate) use crate::dom::bindings::root::{Dom, DomSlice, MaybeUnreflectedDom, Root};
- pub(crate) use crate::dom::bindings::trace::JSTraceable;
- pub(crate) use crate::dom::bindings::utils::{
- AsVoidPtr, DOM_PROTO_UNFORGEABLE_HOLDER_SLOT, DOMClass, DOMJSClass, JSCLASS_DOM_GLOBAL,
- ProtoOrIfaceArray, enumerate_global, exception_to_promise, generic_getter,
- generic_lenient_getter, generic_lenient_setter, generic_method, generic_setter,
- generic_static_promise_method, get_array_index_from_id, get_property_on_prototype,
- has_property_on_prototype, resolve_global, trace_global,
- };
- pub(crate) use crate::dom::bindings::weakref::{DOM_WEAK_SLOT, WeakReferenceable};
- pub(crate) use crate::dom::types::{AnalyserNode, AudioNode, BaseAudioContext, EventTarget};
- pub(crate) use crate::mem::malloc_size_of_including_raw_self;
- pub(crate) use crate::realms::{AlreadyInRealm, InRealm};
- pub(crate) use crate::script_runtime::CanGc;
+ pub(crate) use crate::dom::bindings::root::{Dom, Root};
+ pub(crate) use crate::dom::bindings::weakref::WeakReferenceable;
}
diff --git a/components/script/dom/bindings/interface.rs b/components/script/dom/bindings/interface.rs
deleted file mode 100644
index d1c191be3a4..00000000000
--- a/components/script/dom/bindings/interface.rs
+++ /dev/null
@@ -1,696 +0,0 @@
-/* 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 https://mozilla.org/MPL/2.0/. */
-
-//! Machinery to initialise interface prototype objects and interface objects.
-
-use std::convert::TryFrom;
-use std::ffi::CStr;
-use std::ptr;
-
-use js::error::throw_type_error;
-use js::glue::UncheckedUnwrapObject;
-use js::jsapi::JS::CompartmentIterResult;
-use js::jsapi::{
- CallArgs, CheckedUnwrapStatic, Compartment, CompartmentSpecifier, CurrentGlobalOrNull,
- GetFunctionRealm, GetNonCCWObjectGlobal, GetRealmGlobalOrNull, GetWellKnownSymbol,
- HandleObject as RawHandleObject, IsSharableCompartment, IsSystemCompartment,
- JS_AtomizeAndPinString, JS_GetFunctionObject, JS_GetProperty, JS_IterateCompartments,
- JS_NewFunction, JS_NewGlobalObject, JS_NewObject, JS_NewPlainObject, JS_NewStringCopyN,
- JS_SetReservedSlot, JS_WrapObject, JSAutoRealm, JSClass, JSClassOps, JSContext,
- JSFUN_CONSTRUCTOR, JSFunctionSpec, JSObject, JSPROP_PERMANENT, JSPROP_READONLY,
- JSPROP_RESOLVING, JSPropertySpec, JSString, JSTracer, ObjectOps, OnNewGlobalHookOption,
- SymbolCode, TrueHandleValue, Value, jsid,
-};
-use js::jsval::{JSVal, NullValue, PrivateValue};
-use js::rust::wrappers::{
- JS_DefineProperty, JS_DefineProperty3, JS_DefineProperty4, JS_DefineProperty5,
- JS_DefinePropertyById5, JS_FireOnNewGlobalObject, JS_LinkConstructorAndPrototype,
- JS_NewObjectWithGivenProto, RUST_SYMBOL_TO_JSID,
-};
-use js::rust::{
- HandleObject, HandleValue, MutableHandleObject, RealmOptions, define_methods,
- define_properties, get_object_class, is_dom_class, maybe_wrap_object,
-};
-use script_bindings::constant::{ConstantSpec, define_constants};
-use servo_url::MutableOrigin;
-
-use crate::DomTypes;
-use crate::dom::bindings::codegen::InterfaceObjectMap::Globals;
-use crate::dom::bindings::codegen::PrototypeList;
-use crate::dom::bindings::conversions::{DOM_OBJECT_SLOT, get_dom_class};
-use crate::dom::bindings::guard::Guard;
-use crate::dom::bindings::principals::ServoJSPrincipals;
-use crate::dom::bindings::utils::{
- DOM_PROTOTYPE_SLOT, DOMJSClass, JSCLASS_DOM_GLOBAL, ProtoOrIfaceArray, get_proto_or_iface_array,
-};
-use crate::script_runtime::JSContext as SafeJSContext;
-
-/// The class of a non-callback interface object.
-#[derive(Clone, Copy)]
-pub(crate) struct NonCallbackInterfaceObjectClass {
- /// The SpiderMonkey class structure.
- pub(crate) _class: JSClass,
- /// The prototype id of that interface, used in the hasInstance hook.
- pub(crate) _proto_id: PrototypeList::ID,
- /// The prototype depth of that interface, used in the hasInstance hook.
- pub(crate) _proto_depth: u16,
- /// The string representation of the object.
- pub(crate) representation: &'static [u8],
-}
-
-unsafe impl Sync for NonCallbackInterfaceObjectClass {}
-
-impl NonCallbackInterfaceObjectClass {
- /// Create a new `NonCallbackInterfaceObjectClass` structure.
- pub(crate) const fn new(
- constructor_behavior: &'static InterfaceConstructorBehavior,
- string_rep: &'static [u8],
- proto_id: PrototypeList::ID,
- proto_depth: u16,
- ) -> NonCallbackInterfaceObjectClass {
- NonCallbackInterfaceObjectClass {
- _class: JSClass {
- name: c"Function".as_ptr(),
- flags: 0,
- cOps: &constructor_behavior.0,
- spec: 0 as *const _,
- ext: 0 as *const _,
- oOps: &OBJECT_OPS,
- },
- _proto_id: proto_id,
- _proto_depth: proto_depth,
- representation: string_rep,
- }
- }
-
- /// cast own reference to `JSClass` reference
- pub(crate) fn as_jsclass(&self) -> &JSClass {
- unsafe { &*(self as *const _ as *const JSClass) }
- }
-}
-
-/// A constructor class hook.
-pub(crate) type ConstructorClassHook =
- unsafe extern "C" fn(cx: *mut JSContext, argc: u32, vp: *mut Value) -> bool;
-
-/// The constructor behavior of a non-callback interface object.
-pub(crate) struct InterfaceConstructorBehavior(JSClassOps);
-
-impl InterfaceConstructorBehavior {
- /// An interface constructor that unconditionally throws a type error.
- pub(crate) const fn throw() -> Self {
- InterfaceConstructorBehavior(JSClassOps {
- addProperty: None,
- delProperty: None,
- enumerate: None,
- newEnumerate: None,
- resolve: None,
- mayResolve: None,
- finalize: None,
- call: Some(invalid_constructor),
- construct: Some(invalid_constructor),
- trace: None,
- })
- }
-
- /// An interface constructor that calls a native Rust function.
- pub(crate) const fn call(hook: ConstructorClassHook) -> Self {
- InterfaceConstructorBehavior(JSClassOps {
- addProperty: None,
- delProperty: None,
- enumerate: None,
- newEnumerate: None,
- resolve: None,
- mayResolve: None,
- finalize: None,
- call: Some(non_new_constructor),
- construct: Some(hook),
- trace: None,
- })
- }
-}
-
-/// A trace hook.
-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<D: DomTypes>(
- cx: SafeJSContext,
- class: &'static JSClass,
- private: *const libc::c_void,
- trace: TraceHook,
- mut rval: MutableHandleObject,
- origin: &MutableOrigin,
-) {
- assert!(rval.is_null());
-
- let mut options = RealmOptions::default();
- options.creationOptions_.traceGlobal_ = Some(trace);
- options.creationOptions_.sharedMemoryAndAtomics_ = false;
- select_compartment(cx, &mut options);
-
- let principal = ServoJSPrincipals::new::<D>(origin);
-
- rval.set(JS_NewGlobalObject(
- *cx,
- class,
- principal.as_raw(),
- OnNewGlobalHookOption::DontFireOnNewGlobalHook,
- &*options,
- ));
- assert!(!rval.is_null());
-
- // Initialize the reserved slots before doing anything that can GC, to
- // avoid getting trace hooks called on a partially initialized object.
- let private_val = PrivateValue(private);
- JS_SetReservedSlot(rval.get(), DOM_OBJECT_SLOT, &private_val);
- let proto_array: Box<ProtoOrIfaceArray> =
- Box::new([ptr::null_mut::<JSObject>(); PrototypeList::PROTO_OR_IFACE_LENGTH]);
- let val = PrivateValue(Box::into_raw(proto_array) as *const libc::c_void);
- JS_SetReservedSlot(rval.get(), DOM_PROTOTYPE_SLOT, &val);
-
- let _ac = JSAutoRealm::new(*cx, rval.get());
- 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(crate) fn create_callback_interface_object<D: DomTypes>(
- cx: SafeJSContext,
- global: HandleObject,
- constants: &[Guard<&[ConstantSpec]>],
- name: &CStr,
- mut rval: MutableHandleObject,
-) {
- assert!(!constants.is_empty());
- unsafe {
- rval.set(JS_NewObject(*cx, ptr::null()));
- }
- assert!(!rval.is_null());
- define_guarded_constants::<D>(cx, rval.handle(), constants, global);
- define_name(cx, rval.handle(), name);
- define_on_global_object(cx, global, name, rval.handle());
-}
-
-/// Create the interface prototype object of a non-callback interface.
-#[allow(clippy::too_many_arguments)]
-pub(crate) fn create_interface_prototype_object<D: DomTypes>(
- cx: SafeJSContext,
- global: HandleObject,
- proto: HandleObject,
- class: &'static JSClass,
- regular_methods: &[Guard<&'static [JSFunctionSpec]>],
- regular_properties: &[Guard<&'static [JSPropertySpec]>],
- constants: &[Guard<&[ConstantSpec]>],
- unscopable_names: &[&CStr],
- mut rval: MutableHandleObject,
-) {
- create_object::<D>(
- cx,
- global,
- proto,
- class,
- regular_methods,
- regular_properties,
- constants,
- rval.reborrow(),
- );
-
- if !unscopable_names.is_empty() {
- rooted!(in(*cx) let mut unscopable_obj = ptr::null_mut::<JSObject>());
- create_unscopable_object(cx, unscopable_names, unscopable_obj.handle_mut());
- unsafe {
- let unscopable_symbol = GetWellKnownSymbol(*cx, SymbolCode::unscopables);
- assert!(!unscopable_symbol.is_null());
-
- rooted!(in(*cx) let mut unscopable_id: jsid);
- RUST_SYMBOL_TO_JSID(unscopable_symbol, unscopable_id.handle_mut());
-
- assert!(JS_DefinePropertyById5(
- *cx,
- rval.handle(),
- unscopable_id.handle(),
- unscopable_obj.handle(),
- JSPROP_READONLY as u32
- ))
- }
- }
-}
-
-/// Create and define the interface object of a non-callback interface.
-#[allow(clippy::too_many_arguments)]
-pub(crate) fn create_noncallback_interface_object<D: DomTypes>(
- cx: SafeJSContext,
- global: HandleObject,
- proto: HandleObject,
- class: &'static NonCallbackInterfaceObjectClass,
- static_methods: &[Guard<&'static [JSFunctionSpec]>],
- static_properties: &[Guard<&'static [JSPropertySpec]>],
- constants: &[Guard<&[ConstantSpec]>],
- interface_prototype_object: HandleObject,
- name: &CStr,
- length: u32,
- legacy_window_alias_names: &[&CStr],
- mut rval: MutableHandleObject,
-) {
- create_object::<D>(
- cx,
- global,
- proto,
- class.as_jsclass(),
- static_methods,
- static_properties,
- constants,
- rval.reborrow(),
- );
- unsafe {
- assert!(JS_LinkConstructorAndPrototype(
- *cx,
- rval.handle(),
- interface_prototype_object
- ));
- }
- define_name(cx, rval.handle(), name);
- define_length(cx, rval.handle(), i32::try_from(length).expect("overflow"));
- define_on_global_object(cx, global, name, rval.handle());
-
- if is_exposed_in(global, Globals::WINDOW) {
- for legacy_window_alias in legacy_window_alias_names {
- define_on_global_object(cx, global, legacy_window_alias, rval.handle());
- }
- }
-}
-
-/// Create and define the named constructors of a non-callback interface.
-pub(crate) fn create_named_constructors(
- cx: SafeJSContext,
- global: HandleObject,
- named_constructors: &[(ConstructorClassHook, &CStr, u32)],
- interface_prototype_object: HandleObject,
-) {
- rooted!(in(*cx) let mut constructor = ptr::null_mut::<JSObject>());
-
- for &(native, name, arity) in named_constructors {
- unsafe {
- let fun = JS_NewFunction(*cx, Some(native), arity, JSFUN_CONSTRUCTOR, name.as_ptr());
- assert!(!fun.is_null());
- constructor.set(JS_GetFunctionObject(fun));
- assert!(!constructor.is_null());
-
- assert!(JS_DefineProperty3(
- *cx,
- constructor.handle(),
- c"prototype".as_ptr(),
- interface_prototype_object,
- (JSPROP_PERMANENT | JSPROP_READONLY) as u32
- ));
- }
-
- define_on_global_object(cx, global, name, constructor.handle());
- }
-}
-
-/// Create a new object with a unique type.
-#[allow(clippy::too_many_arguments)]
-pub(crate) fn create_object<D: DomTypes>(
- cx: SafeJSContext,
- global: HandleObject,
- proto: HandleObject,
- class: &'static JSClass,
- methods: &[Guard<&'static [JSFunctionSpec]>],
- properties: &[Guard<&'static [JSPropertySpec]>],
- constants: &[Guard<&[ConstantSpec]>],
- mut rval: MutableHandleObject,
-) {
- unsafe {
- rval.set(JS_NewObjectWithGivenProto(*cx, class, proto));
- }
- assert!(!rval.is_null());
- define_guarded_methods::<D>(cx, rval.handle(), methods, global);
- define_guarded_properties::<D>(cx, rval.handle(), properties, global);
- define_guarded_constants::<D>(cx, rval.handle(), constants, global);
-}
-
-/// Conditionally define constants on an object.
-pub(crate) fn define_guarded_constants<D: DomTypes>(
- cx: SafeJSContext,
- obj: HandleObject,
- constants: &[Guard<&[ConstantSpec]>],
- global: HandleObject,
-) {
- for guard in constants {
- if let Some(specs) = guard.expose::<D>(cx, obj, global) {
- define_constants(cx, obj, specs);
- }
- }
-}
-
-/// Conditionally define methods on an object.
-pub(crate) fn define_guarded_methods<D: DomTypes>(
- cx: SafeJSContext,
- obj: HandleObject,
- methods: &[Guard<&'static [JSFunctionSpec]>],
- global: HandleObject,
-) {
- for guard in methods {
- if let Some(specs) = guard.expose::<D>(cx, obj, global) {
- unsafe {
- define_methods(*cx, obj, specs).unwrap();
- }
- }
- }
-}
-
-/// Conditionally define properties on an object.
-pub(crate) fn define_guarded_properties<D: DomTypes>(
- cx: SafeJSContext,
- obj: HandleObject,
- properties: &[Guard<&'static [JSPropertySpec]>],
- global: HandleObject,
-) {
- for guard in properties {
- if let Some(specs) = guard.expose::<D>(cx, obj, global) {
- unsafe {
- define_properties(*cx, obj, specs).unwrap();
- }
- }
- }
-}
-
-/// Returns whether an interface with exposure set given by `globals` should
-/// be exposed in the global object `obj`.
-pub(crate) fn is_exposed_in(object: HandleObject, globals: Globals) -> bool {
- unsafe {
- let unwrapped = UncheckedUnwrapObject(object.get(), /* stopAtWindowProxy = */ false);
- let dom_class = get_dom_class(unwrapped).unwrap();
- globals.contains(dom_class.global)
- }
-}
-
-/// Define a property with a given name on the global object. Should be called
-/// through the resolve hook.
-pub(crate) fn define_on_global_object(
- cx: SafeJSContext,
- global: HandleObject,
- name: &CStr,
- obj: HandleObject,
-) {
- unsafe {
- assert!(JS_DefineProperty3(
- *cx,
- global,
- name.as_ptr(),
- obj,
- JSPROP_RESOLVING
- ));
- }
-}
-
-const OBJECT_OPS: ObjectOps = ObjectOps {
- lookupProperty: None,
- defineProperty: None,
- hasProperty: None,
- getProperty: None,
- setProperty: None,
- getOwnPropertyDescriptor: None,
- deleteProperty: None,
- getElements: None,
- funToString: Some(fun_to_string_hook),
-};
-
-unsafe extern "C" fn fun_to_string_hook(
- cx: *mut JSContext,
- obj: RawHandleObject,
- _is_to_source: bool,
-) -> *mut JSString {
- let js_class = get_object_class(obj.get());
- assert!(!js_class.is_null());
- let repr = (*(js_class as *const NonCallbackInterfaceObjectClass)).representation;
- assert!(!repr.is_empty());
- let ret = JS_NewStringCopyN(cx, repr.as_ptr() as *const libc::c_char, repr.len());
- assert!(!ret.is_null());
- ret
-}
-
-fn create_unscopable_object(cx: SafeJSContext, names: &[&CStr], mut rval: MutableHandleObject) {
- assert!(!names.is_empty());
- assert!(rval.is_null());
- unsafe {
- rval.set(JS_NewPlainObject(*cx));
- assert!(!rval.is_null());
- for &name in names {
- assert!(JS_DefineProperty(
- *cx,
- rval.handle(),
- name.as_ptr(),
- HandleValue::from_raw(TrueHandleValue),
- JSPROP_READONLY as u32,
- ));
- }
- }
-}
-
-fn define_name(cx: SafeJSContext, obj: HandleObject, name: &CStr) {
- unsafe {
- rooted!(in(*cx) let name = JS_AtomizeAndPinString(*cx, name.as_ptr()));
- assert!(!name.is_null());
- assert!(JS_DefineProperty4(
- *cx,
- obj,
- c"name".as_ptr(),
- name.handle(),
- JSPROP_READONLY as u32
- ));
- }
-}
-
-fn define_length(cx: SafeJSContext, obj: HandleObject, length: i32) {
- unsafe {
- assert!(JS_DefineProperty5(
- *cx,
- obj,
- c"length".as_ptr(),
- length,
- JSPROP_READONLY as u32
- ));
- }
-}
-
-unsafe extern "C" fn invalid_constructor(
- cx: *mut JSContext,
- _argc: libc::c_uint,
- _vp: *mut JSVal,
-) -> bool {
- throw_type_error(cx, "Illegal constructor.");
- false
-}
-
-unsafe extern "C" fn non_new_constructor(
- cx: *mut JSContext,
- _argc: libc::c_uint,
- _vp: *mut JSVal,
-) -> bool {
- throw_type_error(cx, "This constructor needs to be called with `new`.");
- false
-}
-
-pub(crate) enum ProtoOrIfaceIndex {
- ID(PrototypeList::ID),
- Constructor(PrototypeList::Constructor),
-}
-
-impl From<ProtoOrIfaceIndex> for usize {
- fn from(index: ProtoOrIfaceIndex) -> usize {
- match index {
- ProtoOrIfaceIndex::ID(id) => id as usize,
- ProtoOrIfaceIndex::Constructor(constructor) => constructor as usize,
- }
- }
-}
-
-pub(crate) fn get_per_interface_object_handle(
- cx: SafeJSContext,
- global: HandleObject,
- id: ProtoOrIfaceIndex,
- creator: unsafe fn(SafeJSContext, HandleObject, *mut ProtoOrIfaceArray),
- mut rval: MutableHandleObject,
-) {
- unsafe {
- assert!(((*get_object_class(global.get())).flags & JSCLASS_DOM_GLOBAL) != 0);
-
- /* Check to see whether the interface objects are already installed */
- let proto_or_iface_array = get_proto_or_iface_array(global.get());
- let index: usize = id.into();
- rval.set((*proto_or_iface_array)[index]);
- if !rval.get().is_null() {
- return;
- }
-
- creator(cx, global, proto_or_iface_array);
- rval.set((*proto_or_iface_array)[index]);
- assert!(!rval.get().is_null());
- }
-}
-
-pub(crate) fn define_dom_interface(
- cx: SafeJSContext,
- global: HandleObject,
- id: ProtoOrIfaceIndex,
- creator: unsafe fn(SafeJSContext, HandleObject, *mut ProtoOrIfaceArray),
- enabled: fn(SafeJSContext, HandleObject) -> bool,
-) {
- assert!(!global.get().is_null());
-
- if !enabled(cx, global) {
- return;
- }
-
- rooted!(in(*cx) let mut proto = ptr::null_mut::<JSObject>());
- get_per_interface_object_handle(cx, global, id, creator, proto.handle_mut());
- assert!(!proto.is_null());
-}
-
-fn get_proto_id_for_new_target(new_target: HandleObject) -> Option<PrototypeList::ID> {
- unsafe {
- let new_target_class = get_object_class(*new_target);
- if is_dom_class(&*new_target_class) {
- let domjsclass: *const DOMJSClass = new_target_class as *const DOMJSClass;
- let dom_class = &(*domjsclass).dom_class;
- return Some(dom_class.interface_chain[dom_class.depth as usize]);
- }
- None
- }
-}
-
-pub(crate) fn get_desired_proto(
- cx: SafeJSContext,
- args: &CallArgs,
- proto_id: PrototypeList::ID,
- creator: unsafe fn(SafeJSContext, HandleObject, *mut ProtoOrIfaceArray),
- mut desired_proto: MutableHandleObject,
-) -> Result<(), ()> {
- unsafe {
- // This basically implements
- // https://heycam.github.io/webidl/#internally-create-a-new-object-implementing-the-interface
- // step 3.
-
- assert!(args.is_constructing());
-
- // The desired prototype depends on the actual constructor that was invoked,
- // which is passed to us as the newTarget in the callargs. We want to do
- // something akin to the ES6 specification's GetProtototypeFromConstructor (so
- // get .prototype on the newTarget, with a fallback to some sort of default).
-
- // First, a fast path for the case when the the constructor is in fact one of
- // our DOM constructors. This is safe because on those the "constructor"
- // property is non-configurable and non-writable, so we don't have to do the
- // slow JS_GetProperty call.
- rooted!(in(*cx) let mut new_target = args.new_target().to_object());
- rooted!(in(*cx) let original_new_target = *new_target);
- // See whether we have a known DOM constructor here, such that we can take a
- // fast path.
- let target_proto_id = get_proto_id_for_new_target(new_target.handle()).or_else(|| {
- // We might still have a cross-compartment wrapper for a known DOM
- // constructor. CheckedUnwrapStatic is fine here, because we're looking for
- // DOM constructors and those can't be cross-origin objects.
- new_target.set(CheckedUnwrapStatic(*new_target));
- if !new_target.is_null() && *new_target != *original_new_target {
- get_proto_id_for_new_target(new_target.handle())
- } else {
- None
- }
- });
-
- if let Some(proto_id) = target_proto_id {
- let global = GetNonCCWObjectGlobal(*new_target);
- let proto_or_iface_cache = get_proto_or_iface_array(global);
- desired_proto.set((*proto_or_iface_cache)[proto_id as usize]);
- if *new_target != *original_new_target && !JS_WrapObject(*cx, desired_proto.into()) {
- return Err(());
- }
- return Ok(());
- }
-
- // Slow path. This basically duplicates the ES6 spec's
- // GetPrototypeFromConstructor except that instead of taking a string naming
- // the fallback prototype we determine the fallback based on the proto id we
- // were handed.
- rooted!(in(*cx) let mut proto_val = NullValue());
- if !JS_GetProperty(
- *cx,
- original_new_target.handle().into(),
- c"prototype".as_ptr(),
- proto_val.handle_mut().into(),
- ) {
- return Err(());
- }
-
- if proto_val.is_object() {
- desired_proto.set(proto_val.to_object());
- return Ok(());
- }
-
- // Fall back to getting the proto for our given proto id in the realm that
- // GetFunctionRealm(newTarget) returns.
- let realm = GetFunctionRealm(*cx, new_target.handle().into());
-
- if realm.is_null() {
- return Err(());
- }
-
- {
- let _realm = JSAutoRealm::new(*cx, GetRealmGlobalOrNull(realm));
- rooted!(in(*cx) let global = CurrentGlobalOrNull(*cx));
- get_per_interface_object_handle(
- cx,
- global.handle(),
- ProtoOrIfaceIndex::ID(proto_id),
- creator,
- desired_proto.reborrow(),
- );
- if desired_proto.is_null() {
- return Err(());
- }
- }
-
- maybe_wrap_object(*cx, desired_proto);
- Ok(())
- }
-}
diff --git a/components/script/dom/bindings/iterable.rs b/components/script/dom/bindings/iterable.rs
deleted file mode 100644
index c81551f7960..00000000000
--- a/components/script/dom/bindings/iterable.rs
+++ /dev/null
@@ -1,180 +0,0 @@
-/* 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 https://mozilla.org/MPL/2.0/. */
-
-#![allow(unsafe_code)]
-
-//! Implementation of `iterable<...>` and `iterable<..., ...>` WebIDL declarations.
-
-use std::cell::Cell;
-use std::marker::PhantomData;
-use std::ptr;
-use std::ptr::NonNull;
-
-use dom_struct::dom_struct;
-use js::conversions::ToJSValConvertible;
-use js::jsapi::{Heap, JSObject};
-use js::jsval::UndefinedValue;
-use js::rust::{HandleObject, HandleValue, MutableHandleObject};
-use script_bindings::conversions::IDLInterface;
-pub(crate) use script_bindings::iterable::*;
-use script_bindings::utils::DOMClass;
-
-use crate::DomTypes;
-use crate::dom::bindings::codegen::Bindings::IterableIteratorBinding::{
- IterableKeyAndValueResult, IterableKeyOrValueResult,
-};
-use crate::dom::bindings::error::Fallible;
-use crate::dom::bindings::reflector::{
- 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};
-
-/// An iterator over the iterable entries of a given DOM interface.
-#[dom_struct]
-pub(crate) struct IterableIterator<
- D: DomTypes,
- T: DomObjectIteratorWrap<D> + JSTraceable + Iterable + DomGlobalGeneric<D>,
-> {
- reflector: Reflector,
- iterable: Dom<T>,
- type_: IteratorType,
- index: Cell<u32>,
- _marker: NoTrace<PhantomData<D>>,
-}
-
-impl<D: DomTypes, T: DomObjectIteratorWrap<D> + JSTraceable + Iterable> IterableIterator<D, T> {
- pub fn global_(&self, realm: InRealm) -> DomRoot<D::GlobalScope> {
- <Self as DomGlobalGeneric<D>>::global_(self, realm)
- }
-}
-
-impl<
- D: DomTypes,
- T: DomObjectIteratorWrap<D>
- + JSTraceable
- + Iterable
- + DomGlobalGeneric<D>
- + IDLInterface
- + IteratorDerives,
-> IDLInterface for IterableIterator<D, T>
-{
- fn derives(class: &'static DOMClass) -> bool {
- <T as IteratorDerives>::derives(class)
- }
-}
-
-impl<D: DomTypes, T: DomObjectIteratorWrap<D> + JSTraceable + Iterable + DomGlobalGeneric<D>>
- IterableIterator<D, T>
-{
- /// Create a new iterator instance for the provided iterable DOM interface.
- pub(crate) fn new(iterable: &T, type_: IteratorType, realm: InRealm) -> DomRoot<Self> {
- let iterator = Box::new(IterableIterator {
- reflector: Reflector::new(),
- type_,
- iterable: Dom::from_ref(iterable),
- index: Cell::new(0),
- _marker: NoTrace(PhantomData),
- });
- <D as DomHelpers<D>>::reflect_dom_object(iterator, &*iterable.global_(realm), CanGc::note())
- }
-
- /// Return the next value from the iterable object.
- #[allow(non_snake_case)]
- pub(crate) fn Next(&self, cx: JSContext) -> Fallible<NonNull<JSObject>> {
- let index = self.index.get();
- rooted!(in(*cx) let mut value = UndefinedValue());
- rooted!(in(*cx) let mut rval = ptr::null_mut::<JSObject>());
- let result = if index >= self.iterable.get_iterable_length() {
- dict_return(cx, rval.handle_mut(), true, value.handle())
- } else {
- match self.type_ {
- IteratorType::Keys => {
- unsafe {
- self.iterable
- .get_key_at_index(index)
- .to_jsval(*cx, value.handle_mut());
- }
- dict_return(cx, rval.handle_mut(), false, value.handle())
- },
- IteratorType::Values => {
- unsafe {
- self.iterable
- .get_value_at_index(index)
- .to_jsval(*cx, value.handle_mut());
- }
- dict_return(cx, rval.handle_mut(), false, value.handle())
- },
- IteratorType::Entries => {
- rooted!(in(*cx) let mut key = UndefinedValue());
- unsafe {
- self.iterable
- .get_key_at_index(index)
- .to_jsval(*cx, key.handle_mut());
- self.iterable
- .get_value_at_index(index)
- .to_jsval(*cx, value.handle_mut());
- }
- key_and_value_return(cx, rval.handle_mut(), key.handle(), value.handle())
- },
- }
- };
- self.index.set(index + 1);
- result.map(|_| NonNull::new(rval.get()).expect("got a null pointer"))
- }
-}
-
-impl<D: DomTypes, T: DomObjectIteratorWrap<D> + JSTraceable + Iterable + DomGlobalGeneric<D>>
- DomObjectWrap<D> for IterableIterator<D, T>
-{
- const WRAP: unsafe fn(
- JSContext,
- &D::GlobalScope,
- Option<HandleObject>,
- Box<Self>,
- CanGc,
- ) -> Root<Dom<Self>> = T::ITER_WRAP;
-}
-
-fn dict_return(
- cx: JSContext,
- mut result: MutableHandleObject,
- done: bool,
- value: HandleValue,
-) -> Fallible<()> {
- let mut dict = IterableKeyOrValueResult::empty();
- dict.done = done;
- dict.value.set(value.get());
- rooted!(in(*cx) let mut dict_value = UndefinedValue());
- unsafe {
- dict.to_jsval(*cx, dict_value.handle_mut());
- }
- result.set(dict_value.to_object());
- Ok(())
-}
-
-fn key_and_value_return(
- cx: JSContext,
- mut result: MutableHandleObject,
- key: HandleValue,
- value: HandleValue,
-) -> Fallible<()> {
- let mut dict = IterableKeyAndValueResult::empty();
- dict.done = false;
- dict.value = Some(
- vec![key, value]
- .into_iter()
- .map(|handle| RootedTraceableBox::from_box(Heap::boxed(handle.get())))
- .collect(),
- );
- rooted!(in(*cx) let mut dict_value = UndefinedValue());
- unsafe {
- dict.to_jsval(*cx, dict_value.handle_mut());
- }
- result.set(dict_value.to_object());
- Ok(())
-}
diff --git a/components/script/dom/bindings/mod.rs b/components/script/dom/bindings/mod.rs
index b4234e0cc39..ae9e26e8a54 100644
--- a/components/script/dom/bindings/mod.rs
+++ b/components/script/dom/bindings/mod.rs
@@ -135,7 +135,6 @@
#![deny(non_snake_case)]
pub(crate) mod buffer_source;
-pub(crate) mod callback;
#[allow(dead_code)]
pub(crate) mod cell;
pub(crate) mod constructor;
@@ -143,13 +142,9 @@ pub(crate) mod conversions;
pub(crate) mod error;
pub(crate) mod frozenarray;
pub(crate) mod function;
-pub(crate) mod guard;
pub(crate) mod import;
pub(crate) mod inheritance;
-pub(crate) mod interface;
-pub(crate) mod iterable;
pub(crate) mod like;
-pub(crate) mod namespace;
pub(crate) mod principals;
pub(crate) mod proxyhandler;
pub(crate) mod refcounted;
@@ -165,7 +160,7 @@ pub(crate) mod utils;
pub(crate) mod weakref;
pub(crate) mod xmlname;
-pub(crate) use script_bindings::num;
+pub(crate) use script_bindings::{callback, iterable, num};
/// Generated JS-Rust bindings.
#[allow(missing_docs, non_snake_case)]
@@ -173,13 +168,7 @@ pub(crate) mod codegen {
pub(crate) mod DomTypeHolder {
include!(concat!(env!("BINDINGS_OUT_DIR"), "/DomTypeHolder.rs"));
}
- pub(crate) mod DomTypes {
- include!(concat!(env!("BINDINGS_OUT_DIR"), "/DomTypes.rs"));
- }
- #[allow(dead_code)]
- pub(crate) mod GenericBindings {
- include!(concat!(env!("BINDINGS_OUT_DIR"), "/Bindings/mod.rs"));
- }
+ pub(crate) use script_bindings::codegen::GenericBindings;
#[allow(dead_code)]
pub(crate) mod Bindings {
include!(concat!(
@@ -189,30 +178,14 @@ pub(crate) mod codegen {
}
pub(crate) mod InterfaceObjectMap {
include!(concat!(env!("BINDINGS_OUT_DIR"), "/InterfaceObjectMap.rs"));
- pub(crate) use script_bindings::codegen::Globals::Globals;
}
- #[allow(dead_code)]
pub(crate) mod ConcreteInheritTypes {
include!(concat!(
env!("BINDINGS_OUT_DIR"),
"/ConcreteInheritTypes.rs"
));
}
- pub(crate) use script_bindings::codegen::PrototypeList;
- pub(crate) mod RegisterBindings {
- include!(concat!(env!("BINDINGS_OUT_DIR"), "/RegisterBindings.rs"));
- }
- #[allow(
- non_camel_case_types,
- unused_imports,
- unused_variables,
- clippy::large_enum_variant,
- clippy::upper_case_acronyms,
- clippy::enum_variant_names
- )]
- pub(crate) mod GenericUnionTypes {
- include!(concat!(env!("BINDINGS_OUT_DIR"), "/GenericUnionTypes.rs"));
- }
+ pub(crate) use script_bindings::codegen::{PrototypeList, RegisterBindings};
#[allow(dead_code)]
pub(crate) mod UnionTypes {
include!(concat!(env!("BINDINGS_OUT_DIR"), "/UnionTypes.rs"));
diff --git a/components/script/dom/bindings/namespace.rs b/components/script/dom/bindings/namespace.rs
deleted file mode 100644
index ad0a5801519..00000000000
--- a/components/script/dom/bindings/namespace.rs
+++ /dev/null
@@ -1,62 +0,0 @@
-/* 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 https://mozilla.org/MPL/2.0/. */
-
-//! Machinery to initialise namespace objects.
-
-use std::ffi::CStr;
-use std::ptr;
-
-use js::jsapi::{JSClass, JSFunctionSpec};
-use js::rust::{HandleObject, MutableHandleObject};
-use script_bindings::constant::ConstantSpec;
-
-use crate::DomTypes;
-use crate::dom::bindings::guard::Guard;
-use crate::dom::bindings::interface::{create_object, define_on_global_object};
-use crate::script_runtime::JSContext;
-
-/// The class of a namespace object.
-#[derive(Clone, Copy)]
-pub(crate) struct NamespaceObjectClass(JSClass);
-
-unsafe impl Sync for NamespaceObjectClass {}
-
-impl NamespaceObjectClass {
- /// Create a new `NamespaceObjectClass` structure.
- pub(crate) const unsafe fn new(name: &'static CStr) -> Self {
- NamespaceObjectClass(JSClass {
- name: name.as_ptr(),
- flags: 0,
- cOps: 0 as *mut _,
- spec: ptr::null(),
- ext: ptr::null(),
- oOps: ptr::null(),
- })
- }
-}
-
-/// Create a new namespace object.
-#[allow(clippy::too_many_arguments)]
-pub(crate) fn create_namespace_object<D: DomTypes>(
- cx: JSContext,
- global: HandleObject,
- proto: HandleObject,
- class: &'static NamespaceObjectClass,
- methods: &[Guard<&'static [JSFunctionSpec]>],
- constants: &[Guard<&'static [ConstantSpec]>],
- name: &CStr,
- mut rval: MutableHandleObject,
-) {
- create_object::<D>(
- cx,
- global,
- proto,
- &class.0,
- methods,
- &[],
- constants,
- rval.reborrow(),
- );
- define_on_global_object(cx, global, name, rval.handle());
-}
diff --git a/components/script/dom/bindings/principals.rs b/components/script/dom/bindings/principals.rs
index e51a98e454a..0594b77022c 100644
--- a/components/script/dom/bindings/principals.rs
+++ b/components/script/dom/bindings/principals.rs
@@ -2,132 +2,17 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
-use std::marker::PhantomData;
-use std::mem::ManuallyDrop;
-use std::ops::Deref;
use std::ptr::NonNull;
-use js::glue::{
- CreateRustJSPrincipals, DestroyRustJSPrincipals, GetRustJSPrincipalsPrivate,
- JSPrincipalsCallbacks,
-};
+use js::glue::{DestroyRustJSPrincipals, GetRustJSPrincipalsPrivate, JSPrincipalsCallbacks};
use js::jsapi::{
- JS_DropPrincipals, JS_HoldPrincipals, JS_ReadUint32Pair, JSContext, JSPrincipals,
- JSStructuredCloneReader, JSStructuredCloneWriter,
+ JS_ReadUint32Pair, JSContext, JSPrincipals, JSStructuredCloneReader, JSStructuredCloneWriter,
};
-use js::rust::Runtime;
+use script_bindings::principals::{ServoJSPrincipals, ServoJSPrincipalsRef};
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<D: DomTypes>(origin: &MutableOrigin) -> Self {
- unsafe {
- let private: Box<MutableOrigin> = Box::new(origin.clone());
- 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))
- }
- }
-
- /// Construct `Self` from a raw `*mut JSPrincipals`, incrementing its
- /// reference count.
- #[inline]
- pub(crate) unsafe fn from_raw_nonnull(raw: NonNull<JSPrincipals>) -> Self {
- JS_HoldPrincipals(raw.as_ptr());
- Self(raw)
- }
-
- #[inline]
- pub(crate) unsafe fn origin(&self) -> MutableOrigin {
- let origin = GetRustJSPrincipalsPrivate(self.0.as_ptr()) as *mut MutableOrigin;
- (*origin).clone()
- }
-
- #[inline]
- pub(crate) fn as_raw_nonnull(&self) -> NonNull<JSPrincipals> {
- self.0
- }
-
- #[inline]
- pub(crate) fn as_raw(&self) -> *mut JSPrincipals {
- self.0.as_ptr()
- }
-}
-
-impl Clone for ServoJSPrincipals {
- #[inline]
- fn clone(&self) -> Self {
- unsafe { Self::from_raw_nonnull(self.as_raw_nonnull()) }
- }
-}
-
-impl Drop for ServoJSPrincipals {
- #[inline]
- fn drop(&mut self) {
- if let Some(cx) = Runtime::get() {
- unsafe { JS_DropPrincipals(cx.as_ptr(), self.as_raw()) };
- }
- }
-}
-
-/// A borrowed reference to Servo's `JSPrincipals` instance. Does not update the
-/// reference count on creation and deletion.
-pub(crate) struct ServoJSPrincipalsRef<'a>(ManuallyDrop<ServoJSPrincipals>, PhantomData<&'a ()>);
-
-impl ServoJSPrincipalsRef<'_> {
- /// Construct `Self` from a raw `NonNull<JSPrincipals>`.
- ///
- /// # Safety
- ///
- /// `ServoJSPrincipalsRef` does not update the reference count of the
- /// wrapped `JSPrincipals` object. It's up to the caller to ensure the
- /// returned `ServoJSPrincipalsRef` object or any clones are not used past
- /// the lifetime of the wrapped object.
- #[inline]
- pub(crate) unsafe fn from_raw_nonnull(raw: NonNull<JSPrincipals>) -> Self {
- // Don't use `ServoJSPrincipals::from_raw_nonnull`; we don't want to
- // update the reference count
- Self(ManuallyDrop::new(ServoJSPrincipals(raw)), PhantomData)
- }
-
- /// Construct `Self` from a raw `*mut JSPrincipals`.
- ///
- /// # Safety
- ///
- /// The behavior is undefined if `raw` is null. See also
- /// [`Self::from_raw_nonnull`].
- #[inline]
- pub(crate) unsafe fn from_raw_unchecked(raw: *mut JSPrincipals) -> Self {
- Self::from_raw_nonnull(NonNull::new_unchecked(raw))
- }
-}
-
-impl Clone for ServoJSPrincipalsRef<'_> {
- #[inline]
- fn clone(&self) -> Self {
- Self(ManuallyDrop::new(ServoJSPrincipals(self.0.0)), PhantomData)
- }
-}
-
-impl Deref for ServoJSPrincipalsRef<'_> {
- type Target = ServoJSPrincipals;
-
- #[inline]
- fn deref(&self) -> &Self::Target {
- &self.0
- }
-}
+use crate::DomTypeHolder;
#[allow(unused)]
pub(crate) unsafe extern "C" fn destroy_servo_jsprincipal(principals: *mut JSPrincipals) {
diff --git a/components/script/dom/bindings/proxyhandler.rs b/components/script/dom/bindings/proxyhandler.rs
index 5dfe0839502..2e203a81fa9 100644
--- a/components/script/dom/bindings/proxyhandler.rs
+++ b/components/script/dom/bindings/proxyhandler.rs
@@ -6,30 +6,12 @@
#![deny(missing_docs)]
-use std::ptr;
-
-use js::conversions::ToJSValConvertible;
-use js::glue::{GetProxyHandler, InvokeGetOwnPropertyDescriptor};
-use js::jsapi;
-use js::jsapi::{
- 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,
-};
-use js::jsval::UndefinedValue;
-use js::rust::{HandleObject, HandleValue, MutableHandle, MutableHandleObject, get_context_realm};
+use js::jsapi::{GetObjectRealmOrNull, GetRealmPrincipals, HandleObject as RawHandleObject};
+use js::rust::get_context_realm;
+use script_bindings::principals::ServoJSPrincipalsRef;
pub(crate) use script_bindings::proxyhandler::*;
-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::utils::DomHelpers;
-use crate::dom::globalscope::GlobalScopeHelpers;
-use crate::realms::{AlreadyInRealm, InRealm};
-use crate::script_runtime::{CanGc, JSContext as SafeJSContext};
+use crate::script_runtime::JSContext as SafeJSContext;
/// <https://html.spec.whatwg.org/multipage/#isplatformobjectsameorigin-(-o-)>
pub(crate) unsafe fn is_platform_object_same_origin(
@@ -64,269 +46,3 @@ pub(crate) unsafe fn is_platform_object_same_origin(
result
}
-
-/// Report a cross-origin denial for a property, Always returns `false`, so it
-/// can be used as `return report_cross_origin_denial(...);`.
-///
-/// 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<D: DomTypes>(
- cx: SafeJSContext,
- id: RawHandleId,
- access: &str,
-) -> bool {
- debug!(
- "permission denied to {} property {} on cross-origin object",
- access,
- id_to_source(cx, id).as_deref().unwrap_or("< error >"),
- );
- let in_realm_proof = AlreadyInRealm::assert_for_cx(cx);
- if !JS_IsExceptionPending(*cx) {
- let global = D::GlobalScope::from_context(*cx, InRealm::Already(&in_realm_proof));
- // TODO: include `id` and `access` in the exception message
- <D as DomHelpers<D>>::throw_dom_exception(cx, &global, Error::Security, CanGc::note());
- }
- false
-}
-
-/// 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<D: DomTypes>(
- cx: *mut JSContext,
- proxy: RawHandleObject,
- id: RawHandleId,
- v: RawHandleValue,
- receiver: RawHandleValue,
- result: *mut ObjectOpResult,
-) -> bool {
- let cx = SafeJSContext::from_ptr(cx);
-
- 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.
- let _ac = JSAutoRealm::new(*cx, proxy.get());
-
- // OrdinarySet
- // <https://tc39.es/ecma262/#sec-ordinaryset>
- rooted!(in(*cx) let mut own_desc = PropertyDescriptor::default());
- let mut is_none = false;
- if !InvokeGetOwnPropertyDescriptor(
- GetProxyHandler(*proxy),
- *cx,
- proxy,
- id,
- own_desc.handle_mut().into(),
- &mut is_none,
- ) {
- return false;
- }
-
- js::jsapi::SetPropertyIgnoringNamedGetter(
- *cx,
- proxy,
- id,
- v,
- receiver,
- own_desc.handle().into(),
- result,
- )
-}
-
-/// Implementation of `[[GetPrototypeOf]]` for [`Location`].
-///
-/// [`Location`]: https://html.spec.whatwg.org/multipage/#location-getprototypeof
-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),
- proto: RawMutableHandleObject,
-) -> bool {
- // > 1. If ! IsPlatformObjectSameOrigin(this) is true, then return ! OrdinaryGetPrototypeOf(this).
- if is_platform_object_same_origin(cx, proxy) {
- let ac = JSAutoRealm::new(*cx, proxy.get());
- let global = D::GlobalScope::from_context(*cx, InRealm::Entered(&ac));
- get_proto_object(
- cx,
- global.reflector().get_jsobject(),
- MutableHandleObject::from_raw(proto),
- );
- return !proto.is_null();
- }
-
- // > 2. Return null.
- proto.set(ptr::null_mut());
- 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<D: DomTypes>(
- cx: SafeJSContext,
- proxy: RawHandleObject,
- receiver: RawHandleValue,
- id: RawHandleId,
- vp: RawMutableHandleValue,
-) -> bool {
- // > 1. Let `desc` be `? O.[[GetOwnProperty]](P)`.
- rooted!(in(*cx) let mut descriptor = PropertyDescriptor::default());
- let mut is_none = false;
- if !InvokeGetOwnPropertyDescriptor(
- GetProxyHandler(*proxy),
- *cx,
- proxy,
- id,
- descriptor.handle_mut().into(),
- &mut is_none,
- ) {
- return false;
- }
-
- // > 2. Assert: `desc` is not undefined.
- assert!(
- !is_none,
- "Callees should throw in all cases when they are not finding \
- a property decriptor"
- );
-
- // > 3. If `! IsDataDescriptor(desc)` is true, then return `desc.[[Value]]`.
- if is_data_descriptor(&descriptor) {
- vp.set(descriptor.value_);
- return true;
- }
-
- // > 4. Assert: `IsAccessorDescriptor(desc)` is `true`.
- assert!(is_accessor_descriptor(&descriptor));
-
- // > 5. Let `getter` be `desc.[[Get]]`.
- // >
- // > 6. If `getter` is `undefined`, then throw a `SecurityError`
- // > `DOMException`.
- 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::<D>(cx, id, "get");
- }
-
- rooted!(in(*cx) let mut getter_jsval = UndefinedValue());
- getter.get().to_jsval(*cx, getter_jsval.handle_mut());
-
- // > 7. Return `? Call(getter, Receiver)`.
- jsapi::Call(
- *cx,
- receiver,
- getter_jsval.handle().into(),
- &jsapi::HandleValueArray::empty(),
- vp,
- )
-}
-
-/// Implementation of [`CrossOriginSet`].
-///
-/// `cx` and `proxy` are expected to be different-Realm here. `proxy` is a proxy
-/// 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<D: DomTypes>(
- cx: SafeJSContext,
- proxy: RawHandleObject,
- id: RawHandleId,
- v: RawHandleValue,
- receiver: RawHandleValue,
- result: *mut ObjectOpResult,
-) -> bool {
- // > 1. Let desc be ? O.[[GetOwnProperty]](P).
- rooted!(in(*cx) let mut descriptor = PropertyDescriptor::default());
- let mut is_none = false;
- if !InvokeGetOwnPropertyDescriptor(
- GetProxyHandler(*proxy),
- *cx,
- proxy,
- id,
- descriptor.handle_mut().into(),
- &mut is_none,
- ) {
- return false;
- }
-
- // > 2. Assert: desc is not undefined.
- assert!(
- !is_none,
- "Callees should throw in all cases when they are not finding \
- a property decriptor"
- );
-
- // > 3. If desc.[[Set]] is present and its value is not undefined,
- // > then: [...]
- rooted!(in(*cx) let mut setter = ptr::null_mut::<JSObject>());
- get_setter_object(&descriptor, setter.handle_mut().into());
- if setter.get().is_null() {
- // > 4. Throw a "SecurityError" DOMException.
- return report_cross_origin_denial::<D>(cx, id, "set");
- }
-
- rooted!(in(*cx) let mut setter_jsval = UndefinedValue());
- setter.get().to_jsval(*cx, setter_jsval.handle_mut());
-
- // > 3.1. Perform ? Call(setter, Receiver, «V»).
- // >
- // > 3.2. Return true.
- rooted!(in(*cx) let mut ignored = UndefinedValue());
- if !jsapi::Call(
- *cx,
- receiver,
- setter_jsval.handle().into(),
- // FIXME: Our binding lacks `HandleValueArray(Handle<Value>)`
- // <https://searchfox.org/mozilla-central/rev/072710086ddfe25aa2962c8399fefb2304e8193b/js/public/ValueArray.h#54-55>
- &jsapi::HandleValueArray {
- length_: 1,
- elements_: v.ptr,
- },
- ignored.handle_mut().into(),
- ) {
- return false;
- }
-
- (*result).code_ = 0 /* OkCode */;
- true
-}
-
-/// 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<D: DomTypes>(
- cx: SafeJSContext,
- _proxy: RawHandleObject,
- id: RawHandleId,
- desc: RawMutableHandle<PropertyDescriptor>,
- is_none: &mut bool,
-) -> bool {
- assert!(*is_none, "why are we being called?");
-
- // > 1. If P is `then`, `@@toStringTag`, `@@hasInstance`, or
- // > `@@isConcatSpreadable`, then return `PropertyDescriptor{ [[Value]]:
- // > undefined, [[Writable]]: false, [[Enumerable]]: false,
- // > [[Configurable]]: true }`.
- if is_cross_origin_allowlisted_prop(cx, id) {
- set_property_descriptor(
- MutableHandle::from_raw(desc),
- HandleValue::undefined(),
- jsapi::JSPROP_READONLY as u32,
- is_none,
- );
- return true;
- }
-
- // > 2. Throw a `SecurityError` `DOMException`.
- report_cross_origin_denial::<D>(cx, id, "access")
-}
diff --git a/components/script/dom/bindings/reflector.rs b/components/script/dom/bindings/reflector.rs
index 3593578a66f..0a5afbce487 100644
--- a/components/script/dom/bindings/reflector.rs
+++ b/components/script/dom/bindings/reflector.rs
@@ -5,15 +5,14 @@
//! The `Reflector` struct.
use js::rust::HandleObject;
+use script_bindings::interfaces::GlobalScopeHelpers;
use crate::DomTypes;
use crate::dom::bindings::conversions::DerivedFrom;
-use crate::dom::bindings::iterable::{Iterable, IterableIterator};
-use crate::dom::bindings::root::{Dom, DomRoot, Root};
-use crate::dom::bindings::trace::JSTraceable;
-use crate::dom::globalscope::{GlobalScope, GlobalScopeHelpers};
-use crate::realms::{AlreadyInRealm, InRealm};
-use crate::script_runtime::{CanGc, JSContext};
+use crate::dom::bindings::root::DomRoot;
+use crate::dom::globalscope::GlobalScope;
+use crate::realms::InRealm;
+use crate::script_runtime::CanGc;
/// Create the reflector for a new DOM object and yield ownership to the
/// reflector.
@@ -42,31 +41,6 @@ where
unsafe { T::WRAP(D::GlobalScope::get_cx(), global_scope, proto, obj, can_gc) }
}
-pub(crate) trait DomGlobalGeneric<D: DomTypes>: DomObject {
- /// Returns the [`GlobalScope`] of the realm that the [`DomObject`] was created in. If this
- /// object is a `Node`, this will be different from it's owning `Document` if adopted by. For
- /// `Node`s it's almost always better to use `NodeTraits::owning_global`.
- fn global_(&self, realm: InRealm) -> DomRoot<D::GlobalScope>
- where
- Self: Sized,
- {
- D::GlobalScope::from_reflector(self, realm)
- }
-
- /// Returns the [`GlobalScope`] of the realm that the [`DomObject`] was created in. If this
- /// object is a `Node`, this will be different from it's owning `Document` if adopted by. For
- /// `Node`s it's almost always better to use `NodeTraits::owning_global`.
- fn global(&self) -> DomRoot<D::GlobalScope>
- where
- Self: Sized,
- {
- let realm = AlreadyInRealm::assert_for_cx(D::GlobalScope::get_cx());
- D::GlobalScope::from_reflector(self, InRealm::already(&realm))
- }
-}
-
-impl<D: DomTypes, T: DomObject> DomGlobalGeneric<D> for T {}
-
pub(crate) trait DomGlobal {
fn global_(&self, realm: InRealm) -> DomRoot<GlobalScope>;
fn global(&self) -> DomRoot<GlobalScope>;
@@ -81,35 +55,4 @@ impl<T: DomGlobalGeneric<crate::DomTypeHolder>> DomGlobal for T {
}
}
-pub(crate) use script_bindings::reflector::{DomObject, MutDomObject, Reflector};
-
-/// A trait to provide a function pointer to wrap function for DOM objects.
-pub(crate) trait DomObjectWrap<D: DomTypes>:
- Sized + DomObject + DomGlobalGeneric<D>
-{
- /// Function pointer to the general wrap function type
- #[allow(clippy::type_complexity)]
- const WRAP: unsafe fn(
- JSContext,
- &D::GlobalScope,
- Option<HandleObject>,
- Box<Self>,
- CanGc,
- ) -> Root<Dom<Self>>;
-}
-
-/// A trait to provide a function pointer to wrap function for
-/// DOM iterator interfaces.
-pub(crate) trait DomObjectIteratorWrap<D: DomTypes>:
- DomObjectWrap<D> + JSTraceable + Iterable
-{
- /// Function pointer to the wrap function for `IterableIterator<T>`
- #[allow(clippy::type_complexity)]
- const ITER_WRAP: unsafe fn(
- JSContext,
- &D::GlobalScope,
- Option<HandleObject>,
- Box<IterableIterator<D, Self>>,
- CanGc,
- ) -> Root<Dom<IterableIterator<D, Self>>>;
-}
+pub(crate) use script_bindings::reflector::*;
diff --git a/components/script/dom/bindings/settings_stack.rs b/components/script/dom/bindings/settings_stack.rs
index 1284931c349..8e00d03a953 100644
--- a/components/script/dom/bindings/settings_stack.rs
+++ b/components/script/dom/bindings/settings_stack.rs
@@ -3,36 +3,20 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
use std::cell::RefCell;
-use std::marker::PhantomData;
-use std::thread;
-use js::jsapi::{GetScriptedCallerGlobal, HideScriptedCaller, JSTracer, UnhideScriptedCaller};
+use js::jsapi::{GetScriptedCallerGlobal, JSTracer};
use js::rust::Runtime;
+use script_bindings::settings_stack::*;
-use crate::DomTypes;
-use crate::dom::bindings::root::{Dom, DomRoot};
+//use script_bindings::interfaces::{DomHelpers, GlobalScopeHelpers};
+use crate::dom::bindings::root::DomRoot;
use crate::dom::bindings::trace::JSTraceable;
-use crate::dom::bindings::utils::DomHelpers;
-use crate::dom::globalscope::{GlobalScope, GlobalScopeHelpers};
-use crate::script_runtime::CanGc;
+use crate::dom::globalscope::GlobalScope;
thread_local!(pub(super) static STACK: RefCell<Vec<StackEntry<crate::DomTypeHolder>>> = const {
RefCell::new(Vec::new())
});
-#[derive(Debug, Eq, JSTraceable, PartialEq)]
-enum StackEntryKind {
- Incumbent,
- Entry,
-}
-
-#[cfg_attr(crown, allow(crown::unrooted_must_root))]
-#[derive(JSTraceable)]
-pub(crate) struct StackEntry<D: DomTypes> {
- global: Dom<D::GlobalScope>,
- kind: StackEntryKind,
-}
-
/// Traces the script settings stack.
pub(crate) unsafe fn trace(tracer: *mut JSTracer) {
STACK.with(|stack| {
@@ -46,61 +30,6 @@ pub(crate) fn is_execution_stack_empty() -> bool {
pub(crate) type AutoEntryScript = GenericAutoEntryScript<crate::DomTypeHolder>;
-/// RAII struct that pushes and pops entries from the script settings stack.
-pub(crate) struct GenericAutoEntryScript<D: DomTypes> {
- global: DomRoot<D::GlobalScope>,
- #[cfg(feature = "tracing")]
- #[allow(dead_code)]
- span: tracing::span::EnteredSpan,
-}
-
-impl<D: DomTypes> GenericAutoEntryScript<D> {
- /// <https://html.spec.whatwg.org/multipage/#prepare-to-run-script>
- pub(crate) fn new(global: &D::GlobalScope) -> Self {
- let settings_stack = <D as DomHelpers<D>>::settings_stack();
- settings_stack.with(|stack| {
- trace!("Prepare to run script with {:p}", global);
- let mut stack = stack.borrow_mut();
- stack.push(StackEntry {
- global: Dom::from_ref(global),
- kind: StackEntryKind::Entry,
- });
- Self {
- global: DomRoot::from_ref(global),
- #[cfg(feature = "tracing")]
- span: tracing::info_span!(
- "ScriptEvaluate",
- servo_profiling = true,
- url = global.get_url().to_string(),
- )
- .entered(),
- }
- })
- }
-}
-
-impl<D: DomTypes> Drop for GenericAutoEntryScript<D> {
- /// <https://html.spec.whatwg.org/multipage/#clean-up-after-running-script>
- fn drop(&mut self) {
- let settings_stack = <D as DomHelpers<D>>::settings_stack();
- settings_stack.with(|stack| {
- let mut stack = stack.borrow_mut();
- let entry = stack.pop().unwrap();
- assert_eq!(
- &*entry.global as *const D::GlobalScope, &*self.global as *const D::GlobalScope,
- "Dropped AutoEntryScript out of order."
- );
- assert_eq!(entry.kind, StackEntryKind::Entry);
- trace!("Clean up after running script with {:p}", &*entry.global);
- });
-
- // Step 5
- if !thread::panicking() && incumbent_global().is_none() {
- self.global.perform_a_microtask_checkpoint(CanGc::note());
- }
- }
-}
-
/// Returns the ["entry"] global object.
///
/// ["entry"]: https://html.spec.whatwg.org/multipage/#entry
@@ -117,67 +46,7 @@ pub(crate) fn entry_global() -> DomRoot<GlobalScope> {
.unwrap()
}
-/// RAII struct that pushes and pops entries from the script settings stack.
-pub(crate) struct GenericAutoIncumbentScript<D: DomTypes> {
- global: usize,
- _marker: PhantomData<D>,
-}
-
-pub(crate) type AutoIncumbentScript = GenericAutoIncumbentScript<crate::DomTypeHolder>;
-
-impl<D: DomTypes> GenericAutoIncumbentScript<D> {
- /// <https://html.spec.whatwg.org/multipage/#prepare-to-run-a-callback>
- pub(crate) fn new(global: &D::GlobalScope) -> Self {
- // Step 2-3.
- unsafe {
- let cx =
- Runtime::get().expect("Creating a new incumbent script after runtime shutdown");
- HideScriptedCaller(cx.as_ptr());
- }
- let settings_stack = <D as DomHelpers<D>>::settings_stack();
- settings_stack.with(|stack| {
- trace!("Prepare to run a callback with {:p}", global);
- // Step 1.
- let mut stack = stack.borrow_mut();
- stack.push(StackEntry {
- global: Dom::from_ref(global),
- kind: StackEntryKind::Incumbent,
- });
- Self {
- global: global as *const _ as usize,
- _marker: PhantomData,
- }
- })
- }
-}
-
-impl<D: DomTypes> Drop for GenericAutoIncumbentScript<D> {
- /// <https://html.spec.whatwg.org/multipage/#clean-up-after-running-a-callback>
- fn drop(&mut self) {
- let settings_stack = <D as DomHelpers<D>>::settings_stack();
- settings_stack.with(|stack| {
- // Step 4.
- let mut stack = stack.borrow_mut();
- let entry = stack.pop().unwrap();
- // Step 3.
- assert_eq!(
- &*entry.global as *const D::GlobalScope as usize, self.global,
- "Dropped AutoIncumbentScript out of order."
- );
- assert_eq!(entry.kind, StackEntryKind::Incumbent);
- trace!(
- "Clean up after running a callback with {:p}",
- &*entry.global
- );
- });
- unsafe {
- // Step 1-2.
- if let Some(cx) = Runtime::get() {
- UnhideScriptedCaller(cx.as_ptr());
- }
- }
- }
-}
+pub type AutoIncumbentScript = GenericAutoIncumbentScript<crate::DomTypeHolder>;
/// Returns the ["incumbent"] global object.
///
diff --git a/components/script/dom/bindings/trace.rs b/components/script/dom/bindings/trace.rs
index b0c65b9fd9d..5d48e4c4e0f 100644
--- a/components/script/dom/bindings/trace.rs
+++ b/components/script/dom/bindings/trace.rs
@@ -33,15 +33,12 @@ use std::collections::HashMap;
use std::collections::hash_map::RandomState;
use std::fmt::Display;
use std::hash::{BuildHasher, Hash};
-use std::mem;
-use std::ops::{Deref, DerefMut};
/// A trait to allow tracing (only) DOM objects.
pub(crate) use js::gc::Traceable as JSTraceable;
use js::glue::{CallScriptTracer, CallStringTracer, CallValueTracer};
use js::jsapi::{GCTraceKindToAscii, Heap, JSScript, JSString, JSTracer, TraceKind};
use js::jsval::JSVal;
-use js::rust::{GCMethods, Handle};
use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
pub(crate) use script_bindings::trace::*;
@@ -267,70 +264,3 @@ unsafe impl<T: DomObject> JSTraceable for Trusted<T> {
// Do nothing
}
}
-
-/// Roots any JSTraceable thing
-///
-/// If you have a valid DomObject, use DomRoot.
-/// If you have GC things like *mut JSObject or JSVal, use rooted!.
-/// If you have an arbitrary number of DomObjects to root, use rooted_vec!.
-/// If you know what you're doing, use this.
-#[cfg_attr(crown, crown::unrooted_must_root_lint::allow_unrooted_interior)]
-pub(crate) struct RootedTraceableBox<T: JSTraceable + 'static>(js::gc::RootedTraceableBox<T>);
-
-unsafe impl<T: JSTraceable + 'static> JSTraceable for RootedTraceableBox<T> {
- unsafe fn trace(&self, tracer: *mut JSTracer) {
- self.0.trace(tracer);
- }
-}
-
-impl<T: JSTraceable + 'static> RootedTraceableBox<T> {
- /// DomRoot a JSTraceable thing for the life of this RootedTraceableBox
- pub(crate) fn new(traceable: T) -> RootedTraceableBox<T> {
- Self(js::gc::RootedTraceableBox::new(traceable))
- }
-
- /// Consumes a boxed JSTraceable and roots it for the life of this RootedTraceableBox.
- pub(crate) fn from_box(boxed_traceable: Box<T>) -> RootedTraceableBox<T> {
- Self(js::gc::RootedTraceableBox::from_box(boxed_traceable))
- }
-}
-
-impl<T> RootedTraceableBox<Heap<T>>
-where
- Heap<T>: JSTraceable + 'static,
- T: GCMethods + Copy,
-{
- pub(crate) fn handle(&self) -> Handle<T> {
- self.0.handle()
- }
-}
-
-impl<T: JSTraceable + MallocSizeOf> MallocSizeOf for RootedTraceableBox<T> {
- fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
- // Briefly resurrect the real Box value so we can rely on the existing calculations.
- // Then immediately forget about it again to avoid dropping the box.
- let inner = unsafe { Box::from_raw(self.0.ptr()) };
- let size = inner.size_of(ops);
- mem::forget(inner);
- size
- }
-}
-
-impl<T: JSTraceable + Default> Default for RootedTraceableBox<T> {
- fn default() -> RootedTraceableBox<T> {
- RootedTraceableBox::new(T::default())
- }
-}
-
-impl<T: JSTraceable> Deref for RootedTraceableBox<T> {
- type Target = T;
- fn deref(&self) -> &T {
- self.0.deref()
- }
-}
-
-impl<T: JSTraceable> DerefMut for RootedTraceableBox<T> {
- fn deref_mut(&mut self) -> &mut T {
- self.0.deref_mut()
- }
-}
diff --git a/components/script/dom/bindings/utils.rs b/components/script/dom/bindings/utils.rs
index 5f16d3a96d2..f97a7d9a130 100644
--- a/components/script/dom/bindings/utils.rs
+++ b/components/script/dom/bindings/utils.rs
@@ -6,17 +6,15 @@
use std::cell::RefCell;
use std::thread::LocalKey;
-use std::{ptr, slice};
use js::conversions::ToJSValConvertible;
use js::glue::{IsWrapper, JSPrincipalsCallbacks, UnwrapObjectDynamic, UnwrapObjectStatic};
use js::jsapi::{
- CallArgs, DOMCallbacks, HandleId as RawHandleId, HandleObject as RawHandleObject,
- JS_DeprecatedStringHasLatin1Chars, JS_EnumerateStandardClasses, JS_FreezeObject,
- JS_GetLatin1StringCharsAndLength, JS_IsGlobalObject, JS_ResolveStandardClass, JSContext,
- JSObject, MutableHandleIdVector as RawMutableHandleIdVector,
+ CallArgs, DOMCallbacks, HandleObject as RawHandleObject, JS_FreezeObject, JSContext, JSObject,
};
-use js::rust::{Handle, HandleObject, MutableHandleValue, get_object_class, is_dom_class};
+use js::rust::{HandleObject, MutableHandleValue, get_object_class, is_dom_class};
+use script_bindings::interfaces::DomHelpers;
+use script_bindings::settings_stack::StackEntry;
use crate::DomTypes;
use crate::dom::bindings::codegen::{InterfaceObjectMap, PrototypeList};
@@ -29,7 +27,7 @@ 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::settings_stack;
use crate::dom::globalscope::GlobalScope;
use crate::dom::windowproxy::WindowProxyHandler;
use crate::realms::InRealm;
@@ -105,61 +103,6 @@ fn is_platform_object(
}
}
-/// Enumerate lazy properties of a global object.
-pub(crate) unsafe extern "C" fn enumerate_global<D: DomTypes>(
- cx: *mut JSContext,
- obj: RawHandleObject,
- _props: RawMutableHandleIdVector,
- _enumerable_only: bool,
-) -> bool {
- assert!(JS_IsGlobalObject(obj.get()));
- if !JS_EnumerateStandardClasses(cx, obj) {
- return false;
- }
- 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<D: DomTypes>(
- cx: *mut JSContext,
- obj: RawHandleObject,
- id: RawHandleId,
- rval: *mut bool,
-) -> bool {
- assert!(JS_IsGlobalObject(obj.get()));
- if !JS_ResolveStandardClass(cx, obj, id, rval) {
- return false;
- }
- if *rval {
- return true;
- }
- if !id.is_string() {
- *rval = false;
- return true;
- }
-
- let string = id.to_string();
- if !JS_DeprecatedStringHasLatin1Chars(string) {
- *rval = false;
- return true;
- }
- let mut length = 0;
- let ptr = JS_GetLatin1StringCharsAndLength(cx, ptr::null(), string, &mut length);
- assert!(!ptr.is_null());
- let bytes = slice::from_raw_parts(ptr, length);
-
- 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 {
- *rval = false;
- }
- true
-}
-
unsafe extern "C" fn instance_class_has_proto_at_depth(
clasp: *const js::jsapi::JSClass,
proto_id: u32,
@@ -175,48 +118,6 @@ pub(crate) const DOM_CALLBACKS: DOMCallbacks = DOMCallbacks {
instanceClassMatchesProto: Some(instance_class_has_proto_at_depth),
};
-/// 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,
- can_gc: CanGc,
- );
-
- unsafe fn call_html_constructor<T: DerivedFrom<D::Element> + DomObject>(
- cx: SafeJSContext,
- args: &CallArgs,
- global: &D::GlobalScope,
- proto_id: crate::dom::bindings::codegen::PrototypeList::ID,
- creator: unsafe fn(SafeJSContext, HandleObject, *mut ProtoOrIfaceArray),
- can_gc: CanGc,
- ) -> 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 {
fn throw_dom_exception(
cx: SafeJSContext,
@@ -227,7 +128,7 @@ impl DomHelpers<crate::DomTypeHolder> for crate::DomTypeHolder {
throw_dom_exception(cx, global, result, can_gc)
}
- unsafe fn call_html_constructor<
+ fn call_html_constructor<
T: DerivedFrom<<crate::DomTypeHolder as DomTypes>::Element> + DomObject,
>(
cx: SafeJSContext,
diff --git a/components/script/dom/bindings/weakref.rs b/components/script/dom/bindings/weakref.rs
index 1c86b68c706..c1cb012b7c2 100644
--- a/components/script/dom/bindings/weakref.rs
+++ b/components/script/dom/bindings/weakref.rs
@@ -8,7 +8,7 @@ use std::ops::{Deref, DerefMut, Drop};
use js::jsapi::JSTracer;
use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
-pub use script_bindings::weakref::*;
+pub(crate) use script_bindings::weakref::*;
use crate::dom::bindings::cell::DomRefCell;
use crate::dom::bindings::root::DomRoot;