diff options
author | Anthony Ramine <n.oxyde@gmail.com> | 2017-09-27 13:44:07 +0200 |
---|---|---|
committer | Anthony Ramine <n.oxyde@gmail.com> | 2017-09-27 13:44:07 +0200 |
commit | a6d01c92d9a8a8d67cd8164916c86bf1928098f8 (patch) | |
tree | a6f72636d2ad7230c16a5083780bd4df55ce7915 /components/script/dom/bindings/root.rs | |
parent | 0160aaeeea848f685ba090b4541646b0429a37e1 (diff) | |
download | servo-a6d01c92d9a8a8d67cd8164916c86bf1928098f8.tar.gz servo-a6d01c92d9a8a8d67cd8164916c86bf1928098f8.zip |
Reorder things in dom::bindings::root
The type DomRoot<T> is now the first one defined in it.
Diffstat (limited to 'components/script/dom/bindings/root.rs')
-rw-r--r-- | components/script/dom/bindings/root.rs | 410 |
1 files changed, 205 insertions, 205 deletions
diff --git a/components/script/dom/bindings/root.rs b/components/script/dom/bindings/root.rs index 251b17c3054..6f1dbcc2735 100644 --- a/components/script/dom/bindings/root.rs +++ b/components/script/dom/bindings/root.rs @@ -47,6 +47,211 @@ use std::ptr; use std::rc::Rc; use style::thread_state; +/// A rooted reference to a DOM object. +/// +/// The JS value is pinned for the duration of this object's lifetime; roots +/// are additive, so this object's destruction will not invalidate other roots +/// for the same JS value. `Root`s cannot outlive the associated +/// `RootCollection` object. +#[allow(unrooted_must_root)] +#[allow_unrooted_interior] +pub struct DomRoot<T: DomObject> { + /// Reference to rooted value that must not outlive this container + ptr: Dom<T>, + /// List that ensures correct dynamic root ordering + root_list: *const RootCollection, +} + +impl<T: Castable> DomRoot<T> { + /// Cast a DOM object root upwards to one of the interfaces it derives from. + pub fn upcast<U>(root: DomRoot<T>) -> DomRoot<U> + where U: Castable, + T: DerivedFrom<U> + { + unsafe { mem::transmute(root) } + } + + /// Cast a DOM object root downwards to one of the interfaces it might implement. + pub fn downcast<U>(root: DomRoot<T>) -> Option<DomRoot<U>> + where U: DerivedFrom<T> + { + if root.is::<U>() { + Some(unsafe { mem::transmute(root) }) + } else { + None + } + } +} + +impl<T: DomObject> DomRoot<T> { + /// Create a new stack-bounded root for the provided JS-owned value. + /// It cannot outlive its associated `RootCollection`, and it gives + /// out references which cannot outlive this new `Root`. + #[allow(unrooted_must_root)] + unsafe fn new(unrooted: Dom<T>) -> DomRoot<T> { + debug_assert!(thread_state::get().is_script()); + STACK_ROOTS.with(|ref collection| { + let RootCollectionPtr(collection) = collection.get().unwrap(); + (*collection).root(unrooted.reflector()); + DomRoot { + ptr: unrooted, + root_list: collection, + } + }) + } + + /// Generate a new root from a reference + pub fn from_ref(unrooted: &T) -> DomRoot<T> { + unsafe { DomRoot::new(Dom::from_ref(unrooted)) } + } +} + +impl<T: DomObject> Deref for DomRoot<T> { + type Target = T; + fn deref(&self) -> &T { + debug_assert!(thread_state::get().is_script()); + &self.ptr + } +} + +impl<T: DomObject + HeapSizeOf> HeapSizeOf for DomRoot<T> { + fn heap_size_of_children(&self) -> usize { + (**self).heap_size_of_children() + } +} + +impl<T: DomObject> PartialEq for DomRoot<T> { + fn eq(&self, other: &Self) -> bool { + self.ptr == other.ptr + } +} + +impl<T: DomObject> Clone for DomRoot<T> { + fn clone(&self) -> DomRoot<T> { + DomRoot::from_ref(&*self) + } +} + +unsafe impl<T: DomObject> JSTraceable for DomRoot<T> { + unsafe fn trace(&self, _: *mut JSTracer) { + // Already traced. + } +} + +impl<T: DomObject> Drop for DomRoot<T> { + fn drop(&mut self) { + unsafe { + (*self.root_list).unroot(self.reflector()); + } + } +} + +/// A rooting mechanism for reflectors on the stack. +/// LIFO is not required. +/// +/// See also [*Exact Stack Rooting - Storing a GCPointer on the CStack*] +/// (https://developer.mozilla.org/en-US/docs/Mozilla/Projects/SpiderMonkey/Internals/GC/Exact_Stack_Rooting). +pub struct RootCollection { + roots: UnsafeCell<Vec<*const Reflector>>, +} + +/// A pointer to a RootCollection, for use in global variables. +pub struct RootCollectionPtr(pub *const RootCollection); + +impl Copy for RootCollectionPtr {} +impl Clone for RootCollectionPtr { + fn clone(&self) -> RootCollectionPtr { + *self + } +} + +impl RootCollection { + /// Create an empty collection of roots + pub fn new() -> RootCollection { + debug_assert!(thread_state::get().is_script()); + RootCollection { + roots: UnsafeCell::new(vec![]), + } + } + + /// Start tracking a stack-based root + unsafe fn root(&self, untracked_reflector: *const Reflector) { + debug_assert!(thread_state::get().is_script()); + let roots = &mut *self.roots.get(); + roots.push(untracked_reflector); + assert!(!(*untracked_reflector).get_jsobject().is_null()) + } + + /// Stop tracking a stack-based reflector, asserting if it isn't found. + unsafe fn unroot(&self, tracked_reflector: *const Reflector) { + assert!(!tracked_reflector.is_null()); + assert!(!(*tracked_reflector).get_jsobject().is_null()); + debug_assert!(thread_state::get().is_script()); + let roots = &mut *self.roots.get(); + match roots.iter().rposition(|r| *r == tracked_reflector) { + Some(idx) => { + roots.remove(idx); + }, + None => panic!("Can't remove a root that was never rooted!"), + } + } +} + +/// SM Callback that traces the rooted reflectors +pub unsafe fn trace_roots(tracer: *mut JSTracer) { + debug!("tracing stack roots"); + STACK_ROOTS.with(|ref collection| { + let RootCollectionPtr(collection) = collection.get().unwrap(); + let collection = &*(*collection).roots.get(); + for root in collection { + trace_reflector(tracer, "on stack", &**root); + } + }); +} + +/// Get a reference out of a rooted value. +pub trait RootedReference<'root> { + /// The type of the reference. + type Ref: 'root; + /// Obtain a reference out of the rooted value. + fn r(&'root self) -> Self::Ref; +} + +impl<'root, T: DomObject + 'root> RootedReference<'root> for DomRoot<T> { + type Ref = &'root T; + fn r(&'root self) -> &'root T { + self + } +} + +impl<'root, T: DomObject + 'root> RootedReference<'root> for Dom<T> { + type Ref = &'root T; + fn r(&'root self) -> &'root T { + &self + } +} + +impl<'root, T: JSTraceable + DomObject + 'root> RootedReference<'root> for [Dom<T>] { + type Ref = &'root [&'root T]; + fn r(&'root self) -> &'root [&'root T] { + unsafe { mem::transmute(self) } + } +} + +impl<'root, T: DomObject + 'root> RootedReference<'root> for Rc<T> { + type Ref = &'root T; + fn r(&'root self) -> &'root T { + self + } +} + +impl<'root, T: RootedReference<'root> + 'root> RootedReference<'root> for Option<T> { + type Ref = Option<T::Ref>; + fn r(&'root self) -> Option<T::Ref> { + self.as_ref().map(RootedReference::r) + } +} + /// A traced reference to a DOM object /// /// This type is critical to making garbage collection work with the DOM, @@ -88,13 +293,6 @@ impl<T: DomObject> Dom<T> { } } -impl<'root, T: DomObject + 'root> RootedReference<'root> for Dom<T> { - type Ref = &'root T; - fn r(&'root self) -> &'root T { - &self - } -} - impl<T: DomObject> Deref for Dom<T> { type Target = T; @@ -460,204 +658,6 @@ impl<T: DomObject> LayoutDom<T> { } } -/// Get a reference out of a rooted value. -pub trait RootedReference<'root> { - /// The type of the reference. - type Ref: 'root; - /// Obtain a reference out of the rooted value. - fn r(&'root self) -> Self::Ref; -} - -impl<'root, T: JSTraceable + DomObject + 'root> RootedReference<'root> for [Dom<T>] { - type Ref = &'root [&'root T]; - fn r(&'root self) -> &'root [&'root T] { - unsafe { mem::transmute(self) } - } -} - -impl<'root, T: DomObject + 'root> RootedReference<'root> for Rc<T> { - type Ref = &'root T; - fn r(&'root self) -> &'root T { - self - } -} - -impl<'root, T: RootedReference<'root> + 'root> RootedReference<'root> for Option<T> { - type Ref = Option<T::Ref>; - fn r(&'root self) -> Option<T::Ref> { - self.as_ref().map(RootedReference::r) - } -} - -/// A rooting mechanism for reflectors on the stack. -/// LIFO is not required. -/// -/// See also [*Exact Stack Rooting - Storing a GCPointer on the CStack*] -/// (https://developer.mozilla.org/en-US/docs/Mozilla/Projects/SpiderMonkey/Internals/GC/Exact_Stack_Rooting). -pub struct RootCollection { - roots: UnsafeCell<Vec<*const Reflector>>, -} - -/// A pointer to a RootCollection, for use in global variables. -pub struct RootCollectionPtr(pub *const RootCollection); - -impl Copy for RootCollectionPtr {} -impl Clone for RootCollectionPtr { - fn clone(&self) -> RootCollectionPtr { - *self - } -} - -impl RootCollection { - /// Create an empty collection of roots - pub fn new() -> RootCollection { - debug_assert!(thread_state::get().is_script()); - RootCollection { - roots: UnsafeCell::new(vec![]), - } - } - - /// Start tracking a stack-based root - unsafe fn root(&self, untracked_reflector: *const Reflector) { - debug_assert!(thread_state::get().is_script()); - let roots = &mut *self.roots.get(); - roots.push(untracked_reflector); - assert!(!(*untracked_reflector).get_jsobject().is_null()) - } - - /// Stop tracking a stack-based reflector, asserting if it isn't found. - unsafe fn unroot(&self, tracked_reflector: *const Reflector) { - assert!(!tracked_reflector.is_null()); - assert!(!(*tracked_reflector).get_jsobject().is_null()); - debug_assert!(thread_state::get().is_script()); - let roots = &mut *self.roots.get(); - match roots.iter().rposition(|r| *r == tracked_reflector) { - Some(idx) => { - roots.remove(idx); - }, - None => panic!("Can't remove a root that was never rooted!"), - } - } -} - -/// SM Callback that traces the rooted reflectors -pub unsafe fn trace_roots(tracer: *mut JSTracer) { - debug!("tracing stack roots"); - STACK_ROOTS.with(|ref collection| { - let RootCollectionPtr(collection) = collection.get().unwrap(); - let collection = &*(*collection).roots.get(); - for root in collection { - trace_reflector(tracer, "on stack", &**root); - } - }); -} - -/// A rooted reference to a DOM object. -/// -/// The JS value is pinned for the duration of this object's lifetime; roots -/// are additive, so this object's destruction will not invalidate other roots -/// for the same JS value. `Root`s cannot outlive the associated -/// `RootCollection` object. -#[allow(unrooted_must_root)] -#[allow_unrooted_interior] -pub struct DomRoot<T: DomObject> { - /// Reference to rooted value that must not outlive this container - ptr: Dom<T>, - /// List that ensures correct dynamic root ordering - root_list: *const RootCollection, -} - -impl<T: Castable> DomRoot<T> { - /// Cast a DOM object root upwards to one of the interfaces it derives from. - pub fn upcast<U>(root: DomRoot<T>) -> DomRoot<U> - where U: Castable, - T: DerivedFrom<U> - { - unsafe { mem::transmute(root) } - } - - /// Cast a DOM object root downwards to one of the interfaces it might implement. - pub fn downcast<U>(root: DomRoot<T>) -> Option<DomRoot<U>> - where U: DerivedFrom<T> - { - if root.is::<U>() { - Some(unsafe { mem::transmute(root) }) - } else { - None - } - } -} - -impl<T: DomObject> DomRoot<T> { - /// Create a new stack-bounded root for the provided JS-owned value. - /// It cannot outlive its associated `RootCollection`, and it gives - /// out references which cannot outlive this new `Root`. - #[allow(unrooted_must_root)] - unsafe fn new(unrooted: Dom<T>) -> DomRoot<T> { - debug_assert!(thread_state::get().is_script()); - STACK_ROOTS.with(|ref collection| { - let RootCollectionPtr(collection) = collection.get().unwrap(); - (*collection).root(unrooted.reflector()); - DomRoot { - ptr: unrooted, - root_list: collection, - } - }) - } - - /// Generate a new root from a reference - pub fn from_ref(unrooted: &T) -> DomRoot<T> { - unsafe { DomRoot::new(Dom::from_ref(unrooted)) } - } -} - -impl<'root, T: DomObject + 'root> RootedReference<'root> for DomRoot<T> { - type Ref = &'root T; - fn r(&'root self) -> &'root T { - self - } -} - -impl<T: DomObject> Deref for DomRoot<T> { - type Target = T; - fn deref(&self) -> &T { - debug_assert!(thread_state::get().is_script()); - &self.ptr - } -} - -impl<T: DomObject + HeapSizeOf> HeapSizeOf for DomRoot<T> { - fn heap_size_of_children(&self) -> usize { - (**self).heap_size_of_children() - } -} - -impl<T: DomObject> PartialEq for DomRoot<T> { - fn eq(&self, other: &Self) -> bool { - self.ptr == other.ptr - } -} - -impl<T: DomObject> Clone for DomRoot<T> { - fn clone(&self) -> DomRoot<T> { - DomRoot::from_ref(&*self) - } -} - -impl<T: DomObject> Drop for DomRoot<T> { - fn drop(&mut self) { - unsafe { - (*self.root_list).unroot(self.reflector()); - } - } -} - -unsafe impl<T: DomObject> JSTraceable for DomRoot<T> { - unsafe fn trace(&self, _: *mut JSTracer) { - // Already traced. - } -} - /// Helper trait for safer manipulations of Option<Heap<T>> values. pub trait OptionalHeapSetter { type Value; |