aboutsummaryrefslogtreecommitdiffstats
path: root/components/script
diff options
context:
space:
mode:
Diffstat (limited to 'components/script')
-rw-r--r--components/script/dom/bindings/codegen/CodegenRust.py89
-rw-r--r--components/script/dom/bindings/reflector.rs9
-rw-r--r--components/script/dom/bindings/root.rs58
-rw-r--r--components/script/dom/bindings/trace.rs33
-rw-r--r--components/script/dom/promise.rs4
-rw-r--r--components/script/dom/windowproxy.rs4
-rw-r--r--components/script/lib.rs1
7 files changed, 119 insertions, 79 deletions
diff --git a/components/script/dom/bindings/codegen/CodegenRust.py b/components/script/dom/bindings/codegen/CodegenRust.py
index ce1487d5fa6..7f56c3b2f15 100644
--- a/components/script/dom/bindings/codegen/CodegenRust.py
+++ b/components/script/dom/bindings/codegen/CodegenRust.py
@@ -2632,35 +2632,6 @@ class CGConstructorEnabled(CGAbstractMethod):
return CGList((CGGeneric(cond) for cond in conditions), " &&\n")
-def CreateBindingJSObject(descriptor):
- assert not descriptor.isGlobal()
- create = "let raw = Box::into_raw(object);\nlet _rt = RootedTraceable::new(&*raw);\n"
- if descriptor.proxy:
- create += """
-let handler = RegisterBindings::PROXY_HANDLERS[PrototypeList::Proxies::%s as usize];
-rooted!(in(*cx) let private = PrivateValue(raw as *const libc::c_void));
-let obj = NewProxyObject(*cx, handler,
- Handle::from_raw(UndefinedHandleValue),
- proto.get());
-assert!(!obj.is_null());
-SetProxyReservedSlot(obj, 0, &private.get());
-rooted!(in(*cx) let obj = obj);\
-""" % (descriptor.name)
- else:
- create += ("rooted!(in(*cx) let obj = JS_NewObjectWithGivenProto(\n"
- " *cx, &Class.base as *const JSClass, proto.handle()));\n"
- "assert!(!obj.is_null());\n"
- "\n"
- "let val = PrivateValue(raw as *const libc::c_void);\n"
- "\n"
- "JS_SetReservedSlot(obj.get(), DOM_OBJECT_SLOT, &val);")
- if descriptor.weakReferenceable:
- create += """
-let val = PrivateValue(ptr::null());
-JS_SetReservedSlot(obj.get(), DOM_WEAK_SLOT, &val);"""
- return create
-
-
def InitUnforgeablePropertiesOnHolder(descriptor, properties):
"""
Define the unforgeable properties on the unforgeable holder for
@@ -2738,23 +2709,62 @@ class CGWrapMethod(CGAbstractMethod):
def definition_body(self):
unforgeable = CopyUnforgeablePropertiesToInstance(self.descriptor)
- create = CreateBindingJSObject(self.descriptor)
+ if self.descriptor.proxy:
+ create = """
+let handler = RegisterBindings::PROXY_HANDLERS[PrototypeList::Proxies::%(concreteType)s as usize];
+rooted!(in(*cx) let obj = NewProxyObject(
+ *cx,
+ handler,
+ Handle::from_raw(UndefinedHandleValue),
+ proto.get(),
+));
+assert!(!obj.is_null());
+SetProxyReservedSlot(
+ obj.get(),
+ 0,
+ &PrivateValue(&*raw as *const %(concreteType)s as *const libc::c_void),
+);
+"""
+ else:
+ create = """
+rooted!(in(*cx) let obj = JS_NewObjectWithGivenProto(
+ *cx,
+ &Class.base,
+ proto.handle(),
+));
+assert!(!obj.is_null());
+JS_SetReservedSlot(
+ obj.get(),
+ DOM_OBJECT_SLOT,
+ &PrivateValue(&*raw as *const %(concreteType)s as *const libc::c_void),
+);
+"""
+ create = create % {"concreteType": self.descriptor.concreteType}
+ if self.descriptor.weakReferenceable:
+ create += """
+let val = PrivateValue(ptr::null());
+JS_SetReservedSlot(obj.get(), DOM_WEAK_SLOT, &val);
+"""
+
return CGGeneric("""\
+let raw = Root::new(MaybeUnreflectedDom::from_box(object));
+
let scope = scope.reflector().get_jsobject();
assert!(!scope.get().is_null());
assert!(((*get_object_class(scope.get())).flags & JSCLASS_IS_GLOBAL) != 0);
+let _ac = JSAutoRealm::new(*cx, scope.get());
rooted!(in(*cx) let mut proto = ptr::null_mut::<JSObject>());
-let _ac = JSAutoRealm::new(*cx, scope.get());
GetProtoObject(cx, scope, proto.handle_mut());
assert!(!proto.is_null());
%(createObject)s
+raw.init_reflector(obj.get());
%(copyUnforgeable)s
-(*raw).init_reflector(obj.get());
-DomRoot::from_ref(&*raw)""" % {'copyUnforgeable': unforgeable, 'createObject': create})
+DomRoot::from_ref(&*raw)\
+""" % {'copyUnforgeable': unforgeable, 'createObject': create})
class CGWrapGlobalMethod(CGAbstractMethod):
@@ -2773,6 +2783,7 @@ class CGWrapGlobalMethod(CGAbstractMethod):
def definition_body(self):
values = {
+ "concreteType": self.descriptor.concreteType,
"unforgeable": CopyUnforgeablePropertiesToInstance(self.descriptor)
}
@@ -2786,19 +2797,18 @@ class CGWrapGlobalMethod(CGAbstractMethod):
values["members"] = "\n".join(members)
return CGGeneric("""\
-let raw = Box::into_raw(object);
-let _rt = RootedTraceable::new(&*raw);
+let raw = Root::new(MaybeUnreflectedDom::from_box(object));
rooted!(in(*cx) let mut obj = ptr::null_mut::<JSObject>());
create_global_object(
cx,
&Class.base,
- raw as *const libc::c_void,
+ &*raw as *const %(concreteType)s as *const libc::c_void,
_trace,
obj.handle_mut());
assert!(!obj.is_null());
-(*raw).init_reflector(obj.get());
+raw.init_reflector(obj.get());
let _ac = JSAutoRealm::new(*cx, obj.get());
rooted!(in(*cx) let mut proto = ptr::null_mut::<JSObject>());
@@ -6060,8 +6070,10 @@ def generate_imports(config, cgthings, descriptors, callbacks=None, dictionaries
'crate::dom::bindings::reflector::DomObject',
'crate::dom::bindings::root::Dom',
'crate::dom::bindings::root::DomRoot',
- 'crate::dom::bindings::root::OptionalHeapSetter',
'crate::dom::bindings::root::DomSlice',
+ 'crate::dom::bindings::root::MaybeUnreflectedDom',
+ 'crate::dom::bindings::root::OptionalHeapSetter',
+ 'crate::dom::bindings::root::Root',
'crate::dom::bindings::utils::AsVoidPtr',
'crate::dom::bindings::utils::DOMClass',
'crate::dom::bindings::utils::DOMJSClass',
@@ -6086,7 +6098,6 @@ def generate_imports(config, cgthings, descriptors, callbacks=None, dictionaries
'crate::dom::bindings::utils::set_dictionary_property',
'crate::dom::bindings::utils::trace_global',
'crate::dom::bindings::trace::JSTraceable',
- 'crate::dom::bindings::trace::RootedTraceable',
'crate::dom::bindings::trace::RootedTraceableBox',
'crate::dom::bindings::callback::CallSetup',
'crate::dom::bindings::callback::CallbackContainer',
diff --git a/components/script/dom/bindings/reflector.rs b/components/script/dom/bindings/reflector.rs
index 2b5a4987eb5..78635b2be31 100644
--- a/components/script/dom/bindings/reflector.rs
+++ b/components/script/dom/bindings/reflector.rs
@@ -6,6 +6,7 @@
use crate::dom::bindings::conversions::DerivedFrom;
use crate::dom::bindings::root::DomRoot;
+use crate::dom::bindings::trace::JSTraceable;
use crate::dom::globalscope::GlobalScope;
use crate::script_runtime::JSContext;
use js::jsapi::{Heap, JSObject};
@@ -53,7 +54,7 @@ impl Reflector {
}
/// Initialize the reflector. (May be called only once.)
- pub fn set_jsobject(&mut self, object: *mut JSObject) {
+ pub unsafe fn set_jsobject(&self, object: *mut JSObject) {
assert!(self.object.get().is_null());
assert!(!object.is_null());
self.object.set(object);
@@ -75,7 +76,7 @@ impl Reflector {
}
/// A trait to provide access to the `Reflector` for a DOM object.
-pub trait DomObject: 'static {
+pub trait DomObject: JSTraceable + 'static {
/// Returns the receiver's reflector.
fn reflector(&self) -> &Reflector;
@@ -97,11 +98,11 @@ impl DomObject for Reflector {
/// A trait to initialize the `Reflector` for a DOM object.
pub trait MutDomObject: DomObject {
/// Initializes the Reflector
- fn init_reflector(&mut self, obj: *mut JSObject);
+ unsafe fn init_reflector(&self, obj: *mut JSObject);
}
impl MutDomObject for Reflector {
- fn init_reflector(&mut self, obj: *mut JSObject) {
+ unsafe fn init_reflector(&self, obj: *mut JSObject) {
self.set_jsobject(obj)
}
}
diff --git a/components/script/dom/bindings/root.rs b/components/script/dom/bindings/root.rs
index 19df89df53f..1fea453e35a 100644
--- a/components/script/dom/bindings/root.rs
+++ b/components/script/dom/bindings/root.rs
@@ -62,7 +62,7 @@ where
/// It cannot outlive its associated `RootCollection`, and it gives
/// out references which cannot outlive this new `Root`.
#[allow(unrooted_must_root)]
- unsafe fn new(value: T) -> Self {
+ pub unsafe fn new(value: T) -> Self {
debug_assert!(thread_state::get().is_script());
STACK_ROOTS.with(|ref root_list| {
let root_list = &*root_list.get().unwrap();
@@ -99,6 +99,32 @@ where
}
}
+unsafe impl<T> StableTraceObject for MaybeUnreflectedDom<T>
+where
+ T: DomObject,
+{
+ fn stable_trace_object<'a>(&'a self) -> *const dyn JSTraceable {
+ // The JSTraceable impl for Reflector doesn't actually do anything,
+ // so we need this shenanigan to actually trace the reflector of the
+ // T pointer in Dom<T>.
+ #[allow(unrooted_must_root)]
+ struct MaybeUnreflectedStackRoot<T>(T);
+ unsafe impl<T> JSTraceable for MaybeUnreflectedStackRoot<T>
+ where
+ T: DomObject,
+ {
+ unsafe fn trace(&self, tracer: *mut JSTracer) {
+ if self.0.reflector().get_jsobject().is_null() {
+ self.0.trace(tracer);
+ } else {
+ trace_reflector(tracer, "on stack", &self.0.reflector());
+ }
+ }
+ }
+ unsafe { &*(self.ptr.as_ptr() as *const T as *const MaybeUnreflectedStackRoot<T>) }
+ }
+}
+
impl<T> Deref for Root<T>
where
T: Deref + StableTraceObject,
@@ -341,6 +367,36 @@ unsafe impl<T: DomObject> JSTraceable for Dom<T> {
}
}
+/// A traced reference to a DOM object that may not be reflected yet.
+#[unrooted_must_root_lint::must_root]
+pub struct MaybeUnreflectedDom<T> {
+ ptr: ptr::NonNull<T>,
+}
+
+impl<T> MaybeUnreflectedDom<T>
+where
+ T: DomObject,
+{
+ #[allow(unrooted_must_root)]
+ pub unsafe fn from_box(value: Box<T>) -> Self {
+ Self {
+ ptr: Box::into_raw_non_null(value),
+ }
+ }
+}
+
+impl<T> Deref for MaybeUnreflectedDom<T>
+where
+ T: DomObject,
+{
+ type Target = T;
+
+ fn deref(&self) -> &T {
+ debug_assert!(thread_state::get().is_script());
+ unsafe { &*self.ptr.as_ptr() }
+ }
+}
+
/// An unrooted reference to a DOM object for use in layout. `Layout*Helpers`
/// traits must be implemented on this.
#[unrooted_must_root_lint::allow_unrooted_interior]
diff --git a/components/script/dom/bindings/trace.rs b/components/script/dom/bindings/trace.rs
index 5e99e78d03d..631731e39a6 100644
--- a/components/script/dom/bindings/trace.rs
+++ b/components/script/dom/bindings/trace.rs
@@ -918,35 +918,6 @@ impl RootedTraceableSet {
/// 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.
-#[derive(JSTraceable)]
-pub struct RootedTraceable<'a, T: 'static + JSTraceable> {
- ptr: &'a T,
-}
-
-impl<'a, T: JSTraceable + 'static> RootedTraceable<'a, T> {
- /// DomRoot a JSTraceable thing for the life of this RootedTraceable
- pub fn new(traceable: &'a T) -> RootedTraceable<'a, T> {
- unsafe {
- RootedTraceableSet::add(traceable);
- }
- RootedTraceable { ptr: traceable }
- }
-}
-
-impl<'a, T: JSTraceable + 'static> Drop for RootedTraceable<'a, T> {
- fn drop(&mut self) {
- unsafe {
- RootedTraceableSet::remove(self.ptr);
- }
- }
-}
-
-/// 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.
#[unrooted_must_root_lint::allow_unrooted_interior]
pub struct RootedTraceableBox<T: 'static + JSTraceable> {
ptr: *mut T,
@@ -959,12 +930,12 @@ unsafe impl<T: JSTraceable + 'static> JSTraceable for RootedTraceableBox<T> {
}
impl<T: JSTraceable + 'static> RootedTraceableBox<T> {
- /// DomRoot a JSTraceable thing for the life of this RootedTraceable
+ /// DomRoot a JSTraceable thing for the life of this RootedTraceableBox
pub fn new(traceable: T) -> RootedTraceableBox<T> {
Self::from_box(Box::new(traceable))
}
- /// Consumes a boxed JSTraceable and roots it for the life of this RootedTraceable.
+ /// Consumes a boxed JSTraceable and roots it for the life of this RootedTraceableBox.
pub fn from_box(boxed_traceable: Box<T>) -> RootedTraceableBox<T> {
let traceable = Box::into_raw(boxed_traceable);
unsafe {
diff --git a/components/script/dom/promise.rs b/components/script/dom/promise.rs
index f3671a5057f..37baedcc663 100644
--- a/components/script/dom/promise.rs
+++ b/components/script/dom/promise.rs
@@ -109,8 +109,8 @@ impl Promise {
reflector: Reflector::new(),
permanent_js_root: Heap::default(),
};
- let mut promise = Rc::new(promise);
- Rc::get_mut(&mut promise).unwrap().init_reflector(obj.get());
+ let promise = Rc::new(promise);
+ promise.init_reflector(obj.get());
promise.initialize(cx);
promise
}
diff --git a/components/script/dom/windowproxy.rs b/components/script/dom/windowproxy.rs
index 8abbbb480d6..4155d3626a2 100644
--- a/components/script/dom/windowproxy.rs
+++ b/components/script/dom/windowproxy.rs
@@ -166,7 +166,7 @@ impl WindowProxy {
// Create a new browsing context.
let current = Some(window.global().pipeline_id());
- let mut window_proxy = Box::new(WindowProxy::new_inherited(
+ let window_proxy = Box::new(WindowProxy::new_inherited(
browsing_context_id,
top_level_browsing_context_id,
current,
@@ -212,7 +212,7 @@ impl WindowProxy {
let cx = global_to_clone_from.get_cx();
// Create a new browsing context.
- let mut window_proxy = Box::new(WindowProxy::new_inherited(
+ let window_proxy = Box::new(WindowProxy::new_inherited(
browsing_context_id,
top_level_browsing_context_id,
None,
diff --git a/components/script/lib.rs b/components/script/lib.rs
index c01fd6dbd60..1a3ba6a2557 100644
--- a/components/script/lib.rs
+++ b/components/script/lib.rs
@@ -2,6 +2,7 @@
* 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/. */
+#![feature(box_into_raw_non_null)]
#![feature(const_fn)]
#![feature(core_intrinsics)]
#![feature(drain_filter)]