diff --git a/servo/components/script/dom/bindings/js.rs b/servo/components/script/dom/bindings/js.rs index 9a4f17b426a2..f591bb8b9967 100644 --- a/servo/components/script/dom/bindings/js.rs +++ b/servo/components/script/dom/bindings/js.rs @@ -40,6 +40,7 @@ use std::mem; use std::ops::Deref; use std::ptr; use util::mem::HeapSizeOf; +use util::task_state; /// A traced reference to a DOM object /// @@ -64,6 +65,7 @@ impl HeapSizeOf for JS { impl JS { /// Returns `LayoutJS` containing the same pointer. pub unsafe fn to_layout(&self) -> LayoutJS { + debug_assert!(task_state::get().is_layout()); LayoutJS { ptr: self.ptr.clone() } @@ -79,6 +81,7 @@ impl JS { /// XXX Not a great API. Should be a call on Root instead #[allow(unrooted_must_root)] pub fn from_rooted(root: &Root) -> JS { + debug_assert!(task_state::get().is_script()); JS { ptr: unsafe { NonZero::new(&**root) } } @@ -86,6 +89,7 @@ impl JS { /// Create a JS from a &T #[allow(unrooted_must_root)] pub fn from_ref(obj: &T) -> JS { + debug_assert!(task_state::get().is_script()); JS { ptr: unsafe { NonZero::new(&*obj) } } @@ -96,6 +100,7 @@ impl Deref for JS { type Target = T; fn deref(&self) -> &T { + debug_assert!(task_state::get().is_script()); // We can only have &JS from a rooted thing, so it's safe to deref // it to &T. unsafe { &**self.ptr } @@ -118,11 +123,13 @@ pub struct LayoutJS { impl LayoutJS { /// Cast a DOM object root upwards to one of the interfaces it derives from. pub fn upcast(&self) -> LayoutJS where U: Castable, T: DerivedFrom { + debug_assert!(task_state::get().is_layout()); unsafe { mem::transmute_copy(self) } } /// Cast a DOM object downwards to one of the interfaces it might implement. pub fn downcast(&self) -> Option> where U: DerivedFrom { + debug_assert!(task_state::get().is_layout()); unsafe { if (*self.unsafe_get()).is::() { Some(mem::transmute_copy(self)) @@ -136,6 +143,7 @@ impl LayoutJS { impl LayoutJS { /// Get the reflector. pub unsafe fn get_jsobject(&self) -> *mut JSObject { + debug_assert!(task_state::get().is_layout()); (**self.ptr).reflector().get_jsobject().get() } } @@ -170,6 +178,7 @@ impl Clone for JS { #[inline] #[allow(unrooted_must_root)] fn clone(&self) -> JS { + debug_assert!(task_state::get().is_script()); JS { ptr: self.ptr.clone() } @@ -179,6 +188,7 @@ impl Clone for JS { impl Clone for LayoutJS { #[inline] fn clone(&self) -> LayoutJS { + debug_assert!(task_state::get().is_layout()); LayoutJS { ptr: self.ptr.clone() } @@ -190,6 +200,7 @@ impl LayoutJS { /// `Node` pointer. pub unsafe fn from_trusted_node_address(inner: TrustedNodeAddress) -> LayoutJS { + debug_assert!(task_state::get().is_layout()); let TrustedNodeAddress(addr) = inner; LayoutJS { ptr: NonZero::new(addr as *const Node) @@ -224,6 +235,7 @@ pub struct MutHeapJSVal { impl MutHeapJSVal { /// Create a new `MutHeapJSVal`. pub fn new() -> MutHeapJSVal { + debug_assert!(task_state::get().is_script()); MutHeapJSVal { val: UnsafeCell::new(Heap::default()), } @@ -232,6 +244,7 @@ impl MutHeapJSVal { /// Set this `MutHeapJSVal` to the given value, calling write barriers as /// appropriate. pub fn set(&self, val: JSVal) { + debug_assert!(task_state::get().is_script()); unsafe { let cell = self.val.get(); (*cell).set(val); @@ -240,6 +253,7 @@ impl MutHeapJSVal { /// Get the value in this `MutHeapJSVal`, calling read barriers as appropriate. pub fn get(&self) -> JSVal { + debug_assert!(task_state::get().is_script()); unsafe { (*self.val.get()).get() } } } @@ -259,6 +273,7 @@ pub struct MutHeap { impl MutHeap> { /// Create a new `MutHeap`. pub fn new(initial: &T) -> MutHeap> { + debug_assert!(task_state::get().is_script()); MutHeap { val: UnsafeCell::new(JS::from_ref(initial)), } @@ -266,6 +281,7 @@ impl MutHeap> { /// Set this `MutHeap` to the given value. pub fn set(&self, val: &T) { + debug_assert!(task_state::get().is_script()); unsafe { *self.val.get() = JS::from_ref(val); } @@ -273,6 +289,7 @@ impl MutHeap> { /// Get the value in this `MutHeap`. pub fn get(&self) -> Root { + debug_assert!(task_state::get().is_script()); unsafe { ptr::read(self.val.get()).root() } @@ -317,6 +334,7 @@ pub struct MutNullableHeap { impl MutNullableHeap> { /// Create a new `MutNullableHeap`. pub fn new(initial: Option<&T>) -> MutNullableHeap> { + debug_assert!(task_state::get().is_script()); MutNullableHeap { ptr: UnsafeCell::new(initial.map(JS::from_ref)) } @@ -327,6 +345,7 @@ impl MutNullableHeap> { pub fn or_init(&self, cb: F) -> Root where F: FnOnce() -> Root { + debug_assert!(task_state::get().is_script()); match self.get() { Some(inner) => inner, None => { @@ -341,12 +360,14 @@ impl MutNullableHeap> { /// For use by layout, which can't use safe types like Temporary. #[allow(unrooted_must_root)] pub unsafe fn get_inner_as_layout(&self) -> Option> { + debug_assert!(task_state::get().is_layout()); ptr::read(self.ptr.get()).map(|js| js.to_layout()) } /// Get a rooted value out of this object #[allow(unrooted_must_root)] pub fn get(&self) -> Option> { + debug_assert!(task_state::get().is_script()); unsafe { ptr::read(self.ptr.get()).map(|o| o.root()) } @@ -354,11 +375,13 @@ impl MutNullableHeap> { /// Get a rooted value out of this object pub fn get_rooted(&self) -> Option> { + debug_assert!(task_state::get().is_script()); self.get() } /// Set this `MutNullableHeap` to the given value. pub fn set(&self, val: Option<&T>) { + debug_assert!(task_state::get().is_script()); unsafe { *self.ptr.get() = val.map(|p| JS::from_ref(p)); } @@ -385,6 +408,7 @@ impl<'a, T: Reflectable> PartialEq> for MutNullableHeap> { impl Default for MutNullableHeap { #[allow(unrooted_must_root)] fn default() -> MutNullableHeap { + debug_assert!(task_state::get().is_script()); MutNullableHeap { ptr: UnsafeCell::new(None) } @@ -403,6 +427,7 @@ impl LayoutJS { /// the only method that be safely accessed from layout. (The fact that /// this is unsafe is what necessitates the layout wrappers.) pub unsafe fn unsafe_get(&self) -> *const T { + debug_assert!(task_state::get().is_layout()); *self.ptr } } @@ -454,6 +479,7 @@ impl Clone for RootCollectionPtr { impl RootCollection { /// Create an empty collection of roots pub fn new() -> RootCollection { + debug_assert!(task_state::get().is_script()); RootCollection { roots: UnsafeCell::new(vec!()), } @@ -461,6 +487,7 @@ impl RootCollection { /// Start tracking a stack-based root fn root<'b>(&self, untracked_reflector: *const Reflector) { + debug_assert!(task_state::get().is_script()); unsafe { let mut roots = &mut *self.roots.get(); roots.push(untracked_reflector); @@ -470,6 +497,7 @@ impl RootCollection { /// Stop tracking a stack-based root, asserting if the reflector isn't found fn unroot<'b, T: Reflectable>(&self, rooted: &Root) { + debug_assert!(task_state::get().is_script()); unsafe { let mut roots = &mut *self.roots.get(); let old_reflector = &*rooted.r().reflector(); @@ -530,6 +558,7 @@ impl Root { /// out references which cannot outlive this new `Root`. pub fn new(unrooted: NonZero<*const T>) -> Root { + debug_assert!(task_state::get().is_script()); STACK_ROOTS.with(|ref collection| { let RootCollectionPtr(collection) = collection.get().unwrap(); unsafe { (*collection).root(&*(**unrooted).reflector()) } @@ -555,6 +584,7 @@ impl Root { impl Deref for Root { type Target = T; fn deref(&self) -> &T { + debug_assert!(task_state::get().is_script()); unsafe { &**self.ptr.deref() } } }