diff options
author | bors-servo <metajack+bors@gmail.com> | 2015-10-16 08:05:59 -0600 |
---|---|---|
committer | bors-servo <metajack+bors@gmail.com> | 2015-10-16 08:05:59 -0600 |
commit | 7c7dbde0f4372037aac3635b8d81531ca9cdced3 (patch) | |
tree | 3d79eaaa41515448e95248343e22fd5232b48ee4 /components/script/dom | |
parent | ed7ddaa97a962a36c0e2ebab1f256fbd807cca3f (diff) | |
parent | 9de42c893541aa87c563ab534e0c5209cca251fd (diff) | |
download | servo-7c7dbde0f4372037aac3635b8d81531ca9cdced3.tar.gz servo-7c7dbde0f4372037aac3635b8d81531ca9cdced3.zip |
Auto merge of #8026 - eefriedman:js-rooting, r=nox
Fix uses of JS<T> as a type on the stack
`JS<T>` belongs on the heap, and only on the heap. This is a collection of fixes so that code uses either `Root<T>` or `&T` to pass around garbage-collected pointers.
Ideally, we could completely ban constructing a `JS<T>` outside of constructor functions, but we aren't quite there yet.
<!-- Reviewable:start -->
[<img src="https://reviewable.io/review_button.png" height=40 alt="Review on Reviewable"/>](https://reviewable.io/reviews/servo/servo/8026)
<!-- Reviewable:end -->
Diffstat (limited to 'components/script/dom')
-rw-r--r-- | components/script/dom/attr.rs | 4 | ||||
-rw-r--r-- | components/script/dom/bindings/js.rs | 126 | ||||
-rw-r--r-- | components/script/dom/browsercontext.rs | 2 | ||||
-rw-r--r-- | components/script/dom/canvasrenderingcontext2d.rs | 4 | ||||
-rw-r--r-- | components/script/dom/document.rs | 13 | ||||
-rw-r--r-- | components/script/dom/event.rs | 4 | ||||
-rw-r--r-- | components/script/dom/filereader.rs | 6 | ||||
-rw-r--r-- | components/script/dom/htmlcanvaselement.rs | 63 | ||||
-rw-r--r-- | components/script/dom/htmlinputelement.rs | 2 | ||||
-rw-r--r-- | components/script/dom/mouseevent.rs | 2 | ||||
-rw-r--r-- | components/script/dom/node.rs | 46 | ||||
-rw-r--r-- | components/script/dom/nodeiterator.rs | 16 | ||||
-rw-r--r-- | components/script/dom/nodelist.rs | 34 | ||||
-rw-r--r-- | components/script/dom/storageevent.rs | 2 | ||||
-rw-r--r-- | components/script/dom/treewalker.rs | 32 | ||||
-rw-r--r-- | components/script/dom/uievent.rs | 2 | ||||
-rw-r--r-- | components/script/dom/webglprogram.rs | 2 | ||||
-rw-r--r-- | components/script/dom/webglrenderingcontext.rs | 16 |
18 files changed, 197 insertions, 179 deletions
diff --git a/components/script/dom/attr.rs b/components/script/dom/attr.rs index 465ed0f4042..8f545dac744 100644 --- a/components/script/dom/attr.rs +++ b/components/script/dom/attr.rs @@ -180,7 +180,7 @@ impl Attr { name: name, namespace: namespace, prefix: prefix, - owner: MutNullableHeap::new(owner.map(JS::from_ref)), + owner: MutNullableHeap::new(owner), } } @@ -315,7 +315,7 @@ impl Attr { } (old, new) => assert!(old == new) } - self.owner.set(owner.map(JS::from_ref)) + self.owner.set(owner); } pub fn owner(&self) -> Option<Root<Element>> { diff --git a/components/script/dom/bindings/js.rs b/components/script/dom/bindings/js.rs index 16fa12e7189..aea80d88431 100644 --- a/components/script/dom/bindings/js.rs +++ b/components/script/dom/bindings/js.rs @@ -32,13 +32,19 @@ use js::jsapi::{Heap, JSObject, JSTracer}; use js::jsval::JSVal; use layout_interface::TrustedNodeAddress; use script_task::STACK_ROOTS; -use std::cell::{Cell, UnsafeCell}; +use std::cell::UnsafeCell; use std::default::Default; use std::ops::Deref; +use std::ptr; use util::mem::HeapSizeOf; -/// A traced reference to a DOM object. Must only be used as a field in other -/// DOM objects. +/// A traced reference to a DOM object +/// +/// This type is critical to making garbage collection work with the DOM, +/// but it is very dangerous; if garbage collection happens with a `JS<T>` +/// on the stack, the `JS<T>` can point to freed memory. +/// +/// This should only be used as a field in other DOM objects. #[must_root] pub struct JS<T> { ptr: NonZero<*const T> @@ -54,12 +60,13 @@ impl<T> HeapSizeOf for JS<T> { impl<T> JS<T> { /// Returns `LayoutJS<T>` containing the same pointer. - pub unsafe fn to_layout(self) -> LayoutJS<T> { + pub unsafe fn to_layout(&self) -> LayoutJS<T> { LayoutJS { ptr: self.ptr.clone() } } } + impl<T: Reflectable> JS<T> { /// Root this JS-owned value to prevent its collection as garbage. pub fn root(&self) -> Root<T> { @@ -109,8 +116,6 @@ impl<T: Reflectable> LayoutJS<T> { } } -impl<T> Copy for JS<T> {} - impl<T> Copy for LayoutJS<T> {} impl<T> PartialEq for JS<T> { @@ -205,73 +210,76 @@ impl MutHeapJSVal { /// A holder that provides interior mutability for GC-managed values such as -/// `JS<T>`. +/// `JS<T>`. Essentially a `Cell<JS<T>>`, but safer. +/// +/// This should only be used as a field in other DOM objects; see warning +/// on `JS<T>`. #[must_root] #[derive(JSTraceable)] -#[derive(HeapSizeOf)] -pub struct MutHeap<T: HeapGCValue + Copy> { - val: Cell<T>, +pub struct MutHeap<T: HeapGCValue> { + val: UnsafeCell<T>, } -impl<T: HeapGCValue + Copy> MutHeap<T> { +impl<T: Reflectable> MutHeap<JS<T>> { /// Create a new `MutHeap`. - pub fn new(initial: T) -> MutHeap<T> { + pub fn new(initial: &T) -> MutHeap<JS<T>> { MutHeap { - val: Cell::new(initial), + val: UnsafeCell::new(JS::from_ref(initial)), } } /// Set this `MutHeap` to the given value. - pub fn set(&self, val: T) { - self.val.set(val) + pub fn set(&self, val: &T) { + unsafe { + *self.val.get() = JS::from_ref(val); + } } /// Set the value in this `MutHeap`. - pub fn get(&self) -> T { - self.val.get() + pub fn get(&self) -> Root<T> { + unsafe { + ptr::read(self.val.get()).root() + } + } +} + +impl<T: HeapGCValue> HeapSizeOf for MutHeap<T> { + fn heap_size_of_children(&self) -> usize { + // See comment on HeapSizeOf for JS<T>. + 0 } } -/// A mutable holder for GC-managed values such as `JSval` and `JS<T>`, with -/// nullability represented by an enclosing Option wrapper. Must be used in -/// place of traditional internal mutability to ensure that the proper GC -/// barriers are enforced. +/// A holder that provides interior mutability for GC-managed values such as +/// `JS<T>`, with nullability represented by an enclosing Option wrapper. +/// Essentially a `Cell<Option<JS<T>>>`, but safer. +/// +/// This should only be used as a field in other DOM objects; see warning +/// on `JS<T>`. #[must_root] -#[derive(JSTraceable, HeapSizeOf)] -pub struct MutNullableHeap<T: HeapGCValue + Copy> { - ptr: Cell<Option<T>> +#[derive(JSTraceable)] +pub struct MutNullableHeap<T: HeapGCValue> { + ptr: UnsafeCell<Option<T>> } -impl<T: HeapGCValue + Copy> MutNullableHeap<T> { +impl<T: Reflectable> MutNullableHeap<JS<T>> { /// Create a new `MutNullableHeap`. - pub fn new(initial: Option<T>) -> MutNullableHeap<T> { + pub fn new(initial: Option<&T>) -> MutNullableHeap<JS<T>> { MutNullableHeap { - ptr: Cell::new(initial) + ptr: UnsafeCell::new(initial.map(JS::from_ref)) } } - /// Set this `MutNullableHeap` to the given value. - pub fn set(&self, val: Option<T>) { - self.ptr.set(val); - } - - /// Retrieve a copy of the current optional inner value. - pub fn get(&self) -> Option<T> { - self.ptr.get() - } -} - -impl<T: Reflectable> MutNullableHeap<JS<T>> { /// Retrieve a copy of the current inner value. If it is `None`, it is /// initialized with the result of `cb` first. pub fn or_init<F>(&self, cb: F) -> Root<T> where F: FnOnce() -> Root<T> { match self.get() { - Some(inner) => Root::from_rooted(inner), + Some(inner) => inner, None => { let inner = cb(); - self.set(Some(JS::from_rooted(&inner))); + self.set(Some(&inner)); inner }, } @@ -280,25 +288,45 @@ impl<T: Reflectable> MutNullableHeap<JS<T>> { /// Retrieve a copy of the inner optional `JS<T>` as `LayoutJS<T>`. /// For use by layout, which can't use safe types like Temporary. pub unsafe fn get_inner_as_layout(&self) -> Option<LayoutJS<T>> { - self.ptr.get().map(|js| js.to_layout()) + ptr::read(self.ptr.get()).map(|js| js.to_layout()) + } + + /// Get a rooted value out of this object + pub fn get(&self) -> Option<Root<T>> { + unsafe { + ptr::read(self.ptr.get()).map(|o| o.root()) + } } /// Get a rooted value out of this object - // FIXME(#6684) pub fn get_rooted(&self) -> Option<Root<T>> { - self.get().map(|o| o.root()) + self.get() + } + + /// Set this `MutNullableHeap` to the given value. + pub fn set(&self, val: Option<&T>) { + unsafe { + *self.ptr.get() = val.map(|p| JS::from_ref(p)); + } } } -impl<T: HeapGCValue + Copy> Default for MutNullableHeap<T> { +impl<T: HeapGCValue> Default for MutNullableHeap<T> { #[allow(unrooted_must_root)] fn default() -> MutNullableHeap<T> { MutNullableHeap { - ptr: Cell::new(None) + ptr: UnsafeCell::new(None) } } } +impl<T: HeapGCValue> HeapSizeOf for MutNullableHeap<T> { + fn heap_size_of_children(&self) -> usize { + // See comment on HeapSizeOf for JS<T>. + 0 + } +} + impl<T: Reflectable> LayoutJS<T> { /// Returns an unsafe pointer to the interior of this JS object. This is /// the only method that be safely accessed from layout. (The fact that @@ -435,12 +463,6 @@ impl<T: Reflectable> Root<T> { pub fn r(&self) -> &T { &**self } - - /// Generate a new root from a JS<T> reference - #[allow(unrooted_must_root)] - pub fn from_rooted(js: JS<T>) -> Root<T> { - js.root() - } } impl<T: Reflectable> Deref for Root<T> { diff --git a/components/script/dom/browsercontext.rs b/components/script/dom/browsercontext.rs index 3df44a5ba9b..af2bfbdc81e 100644 --- a/components/script/dom/browsercontext.rs +++ b/components/script/dom/browsercontext.rs @@ -54,7 +54,7 @@ impl BrowsingContext { } pub fn frame_element(&self) -> Option<Root<Element>> { - self.frame_element.map(Root::from_rooted) + self.frame_element.as_ref().map(JS::root) } pub fn window_proxy(&self) -> *mut JSObject { diff --git a/components/script/dom/canvasrenderingcontext2d.rs b/components/script/dom/canvasrenderingcontext2d.rs index 3664574814e..89d07cf815c 100644 --- a/components/script/dom/canvasrenderingcontext2d.rs +++ b/components/script/dom/canvasrenderingcontext2d.rs @@ -763,7 +763,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { serialize(rgba, &mut result).unwrap(); StringOrCanvasGradientOrCanvasPattern::eString(result) }, - CanvasFillOrStrokeStyle::Gradient(gradient) => { + CanvasFillOrStrokeStyle::Gradient(ref gradient) => { StringOrCanvasGradientOrCanvasPattern::eCanvasGradient(gradient.root()) }, } @@ -803,7 +803,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { serialize(rgba, &mut result).unwrap(); StringOrCanvasGradientOrCanvasPattern::eString(result) }, - CanvasFillOrStrokeStyle::Gradient(gradient) => { + CanvasFillOrStrokeStyle::Gradient(ref gradient) => { StringOrCanvasGradientOrCanvasPattern::eCanvasGradient(gradient.root()) }, } diff --git a/components/script/dom/document.rs b/components/script/dom/document.rs index 0419895233b..175cc68ea9d 100644 --- a/components/script/dom/document.rs +++ b/components/script/dom/document.rs @@ -297,7 +297,7 @@ impl Document { .filter_map(HTMLBaseElementCast::to_root) .filter(|element| ElementCast::from_ref(&**element).has_attribute(&atom!("href"))) .next(); - self.base_element.set(base.map(|element| JS::from_ref(&*element))); + self.base_element.set(base.r()); } pub fn quirks_mode(&self) -> QuirksMode { @@ -506,7 +506,7 @@ impl Document { /// Request that the given element receive focus once the current transaction is complete. pub fn request_focus(&self, elem: &Element) { if elem.is_focusable_area() { - self.possibly_focused.set(Some(JS::from_ref(elem))) + self.possibly_focused.set(Some(elem)) } } @@ -520,7 +520,7 @@ impl Document { node.set_focus_state(false); } - self.focused.set(self.possibly_focused.get()); + self.focused.set(self.possibly_focused.get().r()); if let Some(ref elem) = self.focused.get_rooted() { let node = NodeCast::from_ref(elem.r()); @@ -852,7 +852,7 @@ impl Document { } pub fn set_current_script(&self, script: Option<&HTMLScriptElement>) { - self.current_script.set(script.map(JS::from_ref)); + self.current_script.set(script); } pub fn trigger_mozbrowser_event(&self, event: MozBrowserEvent) { @@ -959,7 +959,7 @@ impl Document { } pub fn set_current_parser(&self, script: Option<&ServoHTMLParser>) { - self.current_parser.set(script.map(JS::from_ref)); + self.current_parser.set(script); } pub fn get_current_parser(&self) -> Option<Root<ServoHTMLParser>> { @@ -1119,8 +1119,7 @@ impl Document { let new_doc = Document::new( &*self.window(), None, doctype, None, None, DocumentSource::NotFromParser, DocumentLoader::new(&self.loader())); - new_doc.appropriate_template_contents_owner_document.set( - Some(JS::from_ref(&*new_doc))); + new_doc.appropriate_template_contents_owner_document.set(Some(&new_doc)); new_doc }) } diff --git a/components/script/dom/event.rs b/components/script/dom/event.rs index c3a8a52dc55..10118923f56 100644 --- a/components/script/dom/event.rs +++ b/components/script/dom/event.rs @@ -106,12 +106,12 @@ impl Event { #[inline] pub fn set_current_target(&self, val: &EventTarget) { - self.current_target.set(Some(JS::from_ref(val))); + self.current_target.set(Some(val)); } #[inline] pub fn set_target(&self, val: &EventTarget) { - self.target.set(Some(JS::from_ref(val))); + self.target.set(Some(val)); } #[inline] diff --git a/components/script/dom/filereader.rs b/components/script/dom/filereader.rs index 3ae20361ab6..a659908f31c 100644 --- a/components/script/dom/filereader.rs +++ b/components/script/dom/filereader.rs @@ -116,7 +116,7 @@ impl FileReader { let global = fr.global.root(); let exception = DOMException::new(global.r(), error); - fr.error.set(Some(JS::from_rooted(&exception))); + fr.error.set(Some(&exception)); fr.dispatch_progress_event("error".to_owned(), 0, None); return_on_abort!(); @@ -292,7 +292,7 @@ impl FileReaderMethods for FileReader { let global = self.global.root(); let exception = DOMException::new(global.r(), DOMErrorName::AbortError); - self.error.set(Some(JS::from_rooted(&exception))); + self.error.set(Some(&exception)); self.terminate_ongoing_reading(); // Steps 5 & 6 @@ -346,7 +346,7 @@ impl FileReader { if blob.IsClosed() { let global = self.global.root(); let exception = DOMException::new(global.r(), DOMErrorName::InvalidStateError); - self.error.set(Some(JS::from_rooted(&exception))); + self.error.set(Some(&exception)); self.dispatch_progress_event("error".to_owned(), 0, None); return Ok(()); diff --git a/components/script/dom/htmlcanvaselement.rs b/components/script/dom/htmlcanvaselement.rs index f698f42fe26..2fffe51134f 100644 --- a/components/script/dom/htmlcanvaselement.rs +++ b/components/script/dom/htmlcanvaselement.rs @@ -4,13 +4,14 @@ use canvas_traits::{CanvasMsg, FromLayoutMsg}; use dom::attr::Attr; +use dom::bindings::cell::DOMRefCell; use dom::bindings::codegen::Bindings::HTMLCanvasElementBinding; use dom::bindings::codegen::Bindings::HTMLCanvasElementBinding::HTMLCanvasElementMethods; use dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLContextAttributes; use dom::bindings::codegen::InheritTypes::{ElementCast, HTMLElementCast}; use dom::bindings::codegen::UnionTypes::CanvasRenderingContext2DOrWebGLRenderingContext; use dom::bindings::global::GlobalRef; -use dom::bindings::js::{HeapGCValue, JS, LayoutJS, MutNullableHeap, Root}; +use dom::bindings::js::{HeapGCValue, JS, LayoutJS, Root}; use dom::bindings::utils::{Reflectable}; use dom::canvasrenderingcontext2d::{CanvasRenderingContext2D, LayoutCanvasRenderingContext2DHelpers}; use dom::document::Document; @@ -24,7 +25,6 @@ use ipc_channel::ipc::{self, IpcSender}; use js::jsapi::{HandleValue, JSContext}; use offscreen_gl_context::GLContextAttributes; use std::cell::Cell; -use std::default::Default; use std::iter::repeat; use util::str::{DOMString, parse_unsigned_integer}; @@ -32,7 +32,7 @@ const DEFAULT_WIDTH: u32 = 300; const DEFAULT_HEIGHT: u32 = 150; #[must_root] -#[derive(JSTraceable, Clone, Copy, HeapSizeOf)] +#[derive(JSTraceable, Clone, HeapSizeOf)] pub enum CanvasContext { Context2d(JS<CanvasRenderingContext2D>), WebGL(JS<WebGLRenderingContext>), @@ -43,7 +43,7 @@ impl HeapGCValue for CanvasContext {} #[dom_struct] pub struct HTMLCanvasElement { htmlelement: HTMLElement, - context: MutNullableHeap<CanvasContext>, + context: DOMRefCell<Option<CanvasContext>>, width: Cell<u32>, height: Cell<u32>, } @@ -59,9 +59,8 @@ impl HTMLCanvasElement { prefix: Option<DOMString>, document: &Document) -> HTMLCanvasElement { HTMLCanvasElement { - htmlelement: - HTMLElement::new_inherited(localName, prefix, document), - context: Default::default(), + htmlelement: HTMLElement::new_inherited(localName, prefix, document), + context: DOMRefCell::new(None), width: Cell::new(DEFAULT_WIDTH), height: Cell::new(DEFAULT_HEIGHT), } @@ -77,10 +76,10 @@ impl HTMLCanvasElement { fn recreate_contexts(&self) { let size = self.get_size(); - if let Some(context) = self.context.get() { - match context { - CanvasContext::Context2d(context) => context.root().r().recreate(size), - CanvasContext::WebGL(context) => context.root().r().recreate(size), + if let Some(ref context) = *self.context.borrow() { + match *context { + CanvasContext::Context2d(ref context) => context.root().r().recreate(size), + CanvasContext::WebGL(ref context) => context.root().r().recreate(size), } } } @@ -105,10 +104,10 @@ impl LayoutHTMLCanvasElementHelpers for LayoutJS<HTMLCanvasElement> { #[allow(unsafe_code)] unsafe fn get_renderer_id(&self) -> Option<usize> { let ref canvas = *self.unsafe_get(); - canvas.context.get().map(|context| { - match context { - CanvasContext::Context2d(context) => context.to_layout().get_renderer_id(), - CanvasContext::WebGL(context) => context.to_layout().get_renderer_id(), + canvas.context.borrow_for_layout().as_ref().map(|context| { + match *context { + CanvasContext::Context2d(ref context) => context.to_layout().get_renderer_id(), + CanvasContext::WebGL(ref context) => context.to_layout().get_renderer_id(), } }) } @@ -116,10 +115,10 @@ impl LayoutHTMLCanvasElementHelpers for LayoutJS<HTMLCanvasElement> { #[allow(unsafe_code)] unsafe fn get_ipc_renderer(&self) -> Option<IpcSender<CanvasMsg>> { let ref canvas = *self.unsafe_get(); - canvas.context.get().map(|context| { - match context { - CanvasContext::Context2d(context) => context.to_layout().get_ipc_renderer(), - CanvasContext::WebGL(context) => context.to_layout().get_ipc_renderer(), + canvas.context.borrow_for_layout().as_ref().map(|context| { + match *context { + CanvasContext::Context2d(ref context) => context.to_layout().get_ipc_renderer(), + CanvasContext::WebGL(ref context) => context.to_layout().get_ipc_renderer(), } }) } @@ -138,24 +137,24 @@ impl LayoutHTMLCanvasElementHelpers for LayoutJS<HTMLCanvasElement> { impl HTMLCanvasElement { pub fn ipc_renderer(&self) -> Option<IpcSender<CanvasMsg>> { - self.context.get().map(|context| { - match context { - CanvasContext::Context2d(context) => context.root().r().ipc_renderer(), - CanvasContext::WebGL(context) => context.root().r().ipc_renderer(), + self.context.borrow().as_ref().map(|context| { + match *context { + CanvasContext::Context2d(ref context) => context.root().r().ipc_renderer(), + CanvasContext::WebGL(ref context) => context.root().r().ipc_renderer(), } }) } pub fn get_or_init_2d_context(&self) -> Option<Root<CanvasRenderingContext2D>> { - if self.context.get().is_none() { + if self.context.borrow().is_none() { let window = window_from_node(self); let size = self.get_size(); let context = CanvasRenderingContext2D::new(GlobalRef::Window(window.r()), self, size); - self.context.set(Some(CanvasContext::Context2d(JS::from_rooted(&context)))); + *self.context.borrow_mut() = Some(CanvasContext::Context2d(JS::from_rooted(&context))); } - match self.context.get().unwrap() { - CanvasContext::Context2d(context) => Some(context.root()), + match *self.context.borrow().as_ref().unwrap() { + CanvasContext::Context2d(ref context) => Some(context.root()), _ => None, } } @@ -163,7 +162,7 @@ impl HTMLCanvasElement { pub fn get_or_init_webgl_context(&self, cx: *mut JSContext, attrs: Option<HandleValue>) -> Option<Root<WebGLRenderingContext>> { - if self.context.get().is_none() { + if self.context.borrow().is_none() { let window = window_from_node(self); let size = self.get_size(); @@ -180,12 +179,12 @@ impl HTMLCanvasElement { let maybe_ctx = WebGLRenderingContext::new(GlobalRef::Window(window.r()), self, size, attrs); - self.context.set(maybe_ctx.map( |ctx| CanvasContext::WebGL(JS::from_rooted(&ctx)))); + *self.context.borrow_mut() = maybe_ctx.map( |ctx| CanvasContext::WebGL(JS::from_rooted(&ctx))); } - if let Some(context) = self.context.get() { - match context { - CanvasContext::WebGL(context) => Some(context.root()), + if let Some(ref context) = *self.context.borrow() { + match *context { + CanvasContext::WebGL(ref context) => Some(context.root()), _ => None, } } else { diff --git a/components/script/dom/htmlinputelement.rs b/components/script/dom/htmlinputelement.rs index cc0aabdc9cb..cdfe8716775 100644 --- a/components/script/dom/htmlinputelement.rs +++ b/components/script/dom/htmlinputelement.rs @@ -758,7 +758,7 @@ impl Activatable for HTMLInputElement { InputType::InputRadio => { // We want to restore state only if the element had been changed in the first place if cache.was_mutable { - let old_checked: Option<Root<HTMLInputElement>> = cache.checked_radio.map(|t| t.root()); + let old_checked = cache.checked_radio.as_ref().map(|t| t.root()); let name = self.get_radio_group_name(); match old_checked { Some(ref o) => { diff --git a/components/script/dom/mouseevent.rs b/components/script/dom/mouseevent.rs index 5f05fc97b77..eb57489c1e4 100644 --- a/components/script/dom/mouseevent.rs +++ b/components/script/dom/mouseevent.rs @@ -205,6 +205,6 @@ impl MouseEventMethods for MouseEvent { self.shift_key.set(shiftKeyArg); self.meta_key.set(metaKeyArg); self.button.set(buttonArg); - self.related_target.set(relatedTargetArg.map(JS::from_ref)); + self.related_target.set(relatedTargetArg); } } diff --git a/components/script/dom/node.rs b/components/script/dom/node.rs index d5e7f5c6e83..daacdd09fa0 100644 --- a/components/script/dom/node.rs +++ b/components/script/dom/node.rs @@ -271,32 +271,32 @@ impl Node { match prev_sibling { None => { assert!(Some(*before) == self.first_child.get_rooted().r()); - self.first_child.set(Some(JS::from_ref(new_child))); + self.first_child.set(Some(new_child)); }, Some(ref prev_sibling) => { - prev_sibling.next_sibling.set(Some(JS::from_ref(new_child))); - new_child.prev_sibling.set(Some(JS::from_ref(prev_sibling.r()))); + prev_sibling.next_sibling.set(Some(new_child)); + new_child.prev_sibling.set(Some(prev_sibling.r())); }, } - before.prev_sibling.set(Some(JS::from_ref(new_child))); - new_child.next_sibling.set(Some(JS::from_ref(before))); + before.prev_sibling.set(Some(new_child)); + new_child.next_sibling.set(Some(before)); }, None => { let last_child = self.GetLastChild(); match last_child { - None => self.first_child.set(Some(JS::from_ref(new_child))), + None => self.first_child.set(Some(new_child)), Some(ref last_child) => { assert!(last_child.next_sibling.get().is_none()); - last_child.r().next_sibling.set(Some(JS::from_ref(new_child))); - new_child.prev_sibling.set(Some(JS::from_rooted(&last_child))); + last_child.r().next_sibling.set(Some(new_child)); + new_child.prev_sibling.set(Some(&last_child)); } } - self.last_child.set(Some(JS::from_ref(new_child))); + self.last_child.set(Some(new_child)); }, } - new_child.parent_node.set(Some(JS::from_ref(self))); + new_child.parent_node.set(Some(self)); let parent_in_doc = self.is_in_doc(); for node in new_child.traverse_preorder() { @@ -315,19 +315,19 @@ impl Node { let prev_sibling = child.GetPreviousSibling(); match prev_sibling { None => { - self.first_child.set(child.next_sibling.get()); + self.first_child.set(child.next_sibling.get().r()); } Some(ref prev_sibling) => { - prev_sibling.next_sibling.set(child.next_sibling.get()); + prev_sibling.next_sibling.set(child.next_sibling.get().r()); } } let next_sibling = child.GetNextSibling(); match next_sibling { None => { - self.last_child.set(child.prev_sibling.get()); + self.last_child.set(child.prev_sibling.get().r()); } Some(ref next_sibling) => { - next_sibling.prev_sibling.set(child.prev_sibling.get()); + next_sibling.prev_sibling.set(child.prev_sibling.get().r()); } } @@ -591,7 +591,7 @@ impl Node { match self.parent_node.get() { None => return, Some(parent) => parent, - }.root(); + }; for sibling in parent.r().children() { sibling.r().set_has_dirty_siblings(true); @@ -660,7 +660,7 @@ impl Node { pub fn is_parent_of(&self, child: &Node) -> bool { match child.parent_node.get() { - Some(ref parent) => parent.root().r() == self, + Some(ref parent) => parent.r() == self, None => false, } } @@ -689,7 +689,7 @@ impl Node { // Step 2. let parent = match parent.get() { None => return Ok(()), - Some(ref parent) => parent.root(), + Some(parent) => parent, }; // Step 3. @@ -702,7 +702,7 @@ impl Node { let viable_previous_sibling = match viable_previous_sibling { Some(ref viable_previous_sibling) => viable_previous_sibling.next_sibling.get(), None => parent.first_child.get(), - }.map(|s| s.root()); + }; // Step 6. try!(Node::pre_insert(&node, &parent, viable_previous_sibling.r())); @@ -718,7 +718,7 @@ impl Node { // Step 2. let parent = match parent.get() { None => return Ok(()), - Some(ref parent) => parent.root(), + Some(parent) => parent, }; // Step 3. @@ -745,7 +745,7 @@ impl Node { let doc = self.owner_doc(); let node = try!(doc.r().node_from_nodes_and_strings(nodes)); // Step 3. - parent_node.root().r().ReplaceChild(node.r(), self).map(|_| ()) + parent_node.r().ReplaceChild(node.r(), self).map(|_| ()) }, } } @@ -823,11 +823,11 @@ impl Node { } pub fn owner_doc(&self) -> Root<Document> { - self.owner_doc.get().unwrap().root() + self.owner_doc.get().unwrap() } pub fn set_owner_doc(&self, document: &Document) { - self.owner_doc.set(Some(JS::from_ref(document))); + self.owner_doc.set(Some(document)); } pub fn is_in_html_doc(&self) -> bool { @@ -1367,7 +1367,7 @@ impl Node { last_child: Default::default(), next_sibling: Default::default(), prev_sibling: Default::default(), - owner_doc: MutNullableHeap::new(doc.map(JS::from_ref)), + owner_doc: MutNullableHeap::new(doc), child_list: Default::default(), children_count: Cell::new(0u32), flags: Cell::new(flags), diff --git a/components/script/dom/nodeiterator.rs b/components/script/dom/nodeiterator.rs index 34ec3f6c658..c7152231776 100644 --- a/components/script/dom/nodeiterator.rs +++ b/components/script/dom/nodeiterator.rs @@ -36,7 +36,7 @@ impl NodeIterator { NodeIterator { reflector_: Reflector::new(), root_node: JS::from_ref(root_node), - reference_node: MutHeap::new(JS::from_ref(root_node)), + reference_node: MutHeap::new(root_node), pointer_before_reference_node: Cell::new(true), what_to_show: what_to_show, filter: filter @@ -87,7 +87,7 @@ impl NodeIteratorMethods for NodeIterator { // https://dom.spec.whatwg.org/#dom-nodeiterator-referencenode fn ReferenceNode(&self) -> Root<Node> { - self.reference_node.get().root() + self.reference_node.get() } // https://dom.spec.whatwg.org/#dom-nodeiterator-pointerbeforereferencenode @@ -99,7 +99,7 @@ impl NodeIteratorMethods for NodeIterator { fn NextNode(&self) -> Fallible<Option<Root<Node>>> { // https://dom.spec.whatwg.org/#concept-NodeIterator-traverse // Step 1. - let node = self.reference_node.get().root(); + let node = self.reference_node.get(); // Step 2. let mut before_node = self.pointer_before_reference_node.get(); @@ -114,7 +114,7 @@ impl NodeIteratorMethods for NodeIterator { // Step 3-3. if result == NodeFilterConstants::FILTER_ACCEPT { // Step 4. - self.reference_node.set(JS::from_ref(node.r())); + self.reference_node.set(node.r()); self.pointer_before_reference_node.set(before_node); return Ok(Some(node)); @@ -129,7 +129,7 @@ impl NodeIteratorMethods for NodeIterator { // Step 3-3. if result == NodeFilterConstants::FILTER_ACCEPT { // Step 4. - self.reference_node.set(JS::from_ref(following_node.r())); + self.reference_node.set(following_node.r()); self.pointer_before_reference_node.set(before_node); return Ok(Some(following_node)); @@ -143,7 +143,7 @@ impl NodeIteratorMethods for NodeIterator { fn PreviousNode(&self) -> Fallible<Option<Root<Node>>> { // https://dom.spec.whatwg.org/#concept-NodeIterator-traverse // Step 1. - let node = self.reference_node.get().root(); + let node = self.reference_node.get(); // Step 2. let mut before_node = self.pointer_before_reference_node.get(); @@ -158,7 +158,7 @@ impl NodeIteratorMethods for NodeIterator { // Step 3-3. if result == NodeFilterConstants::FILTER_ACCEPT { // Step 4. - self.reference_node.set(JS::from_ref(node.r())); + self.reference_node.set(node.r()); self.pointer_before_reference_node.set(before_node); return Ok(Some(node)); @@ -174,7 +174,7 @@ impl NodeIteratorMethods for NodeIterator { // Step 3-3. if result == NodeFilterConstants::FILTER_ACCEPT { // Step 4. - self.reference_node.set(JS::from_ref(preceding_node.r())); + self.reference_node.set(preceding_node.r()); self.pointer_before_reference_node.set(before_node); return Ok(Some(preceding_node)); diff --git a/components/script/dom/nodelist.rs b/components/script/dom/nodelist.rs index d997cad2558..b5db05945ca 100644 --- a/components/script/dom/nodelist.rs +++ b/components/script/dom/nodelist.rs @@ -6,7 +6,7 @@ use dom::bindings::codegen::Bindings::NodeBinding::NodeMethods; use dom::bindings::codegen::Bindings::NodeListBinding; use dom::bindings::codegen::Bindings::NodeListBinding::NodeListMethods; use dom::bindings::global::GlobalRef; -use dom::bindings::js::{JS, MutNullableHeap, Root}; +use dom::bindings::js::{JS, MutNullableHeap, Root, RootedReference}; use dom::bindings::utils::{Reflector, reflect_dom_object}; use dom::node::{ChildrenMutation, Node}; use dom::window::Window; @@ -64,7 +64,7 @@ impl NodeListMethods for NodeList { fn Item(&self, index: u32) -> Option<Root<Node>> { match self.list_type { NodeListType::Simple(ref elems) => { - elems.get(index as usize).map(|node| Root::from_rooted(*node)) + elems.get(index as usize).map(|node| node.root()) }, NodeListType::Children(ref list) => list.item(index), } @@ -103,8 +103,7 @@ impl ChildrenList { let last_visited = node.GetFirstChild(); ChildrenList { node: JS::from_ref(node), - last_visited: - MutNullableHeap::new(last_visited.as_ref().map(JS::from_rooted)), + last_visited: MutNullableHeap::new(last_visited.r()), last_index: Cell::new(0u32), } } @@ -127,14 +126,14 @@ impl ChildrenList { let last_index = self.last_index.get(); if index == last_index { // Item is last visited child, no need to update last visited. - return Some(self.last_visited.get().unwrap().root()); + return Some(self.last_visited.get().unwrap()); } let last_visited = if index - 1u32 == last_index { // Item is last visited's next sibling. - self.last_visited.get().unwrap().root().GetNextSibling().unwrap() + self.last_visited.get().unwrap().GetNextSibling().unwrap() } else if last_index > 0 && index == last_index - 1u32 { // Item is last visited's previous sibling. - self.last_visited.get().unwrap().root().GetPreviousSibling().unwrap() + self.last_visited.get().unwrap().GetPreviousSibling().unwrap() } else if index > last_index { if index == len - 1u32 { // Item is parent's last child, not worth updating last visited. @@ -142,7 +141,7 @@ impl ChildrenList { } if index <= last_index + (len - last_index) / 2u32 { // Item is closer to the last visited child and follows it. - self.last_visited.get().unwrap().root() + self.last_visited.get().unwrap() .inclusively_following_siblings() .nth((index - last_index) as usize).unwrap() } else { @@ -154,7 +153,7 @@ impl ChildrenList { } } else if index >= last_index / 2u32 { // Item is closer to the last visited child and precedes it. - self.last_visited.get().unwrap().root() + self.last_visited.get().unwrap() .inclusively_preceding_siblings() .nth((last_index - index) as usize).unwrap() } else { @@ -165,7 +164,7 @@ impl ChildrenList { .nth(index as usize) .unwrap() }; - self.last_visited.set(Some(JS::from_rooted(&last_visited))); + self.last_visited.set(Some(last_visited.r())); self.last_index.set(index); Some(last_visited) } @@ -178,7 +177,7 @@ impl ChildrenList { } let index = list.last_index.get(); if index < len { - list.last_visited.set(Some(JS::from_ref(added[index as usize]))); + list.last_visited.set(Some(added[index as usize])); } else if index / 2u32 >= len { // If last index is twice as large as the number of added nodes, // updating only it means that less nodes will be traversed if @@ -187,7 +186,7 @@ impl ChildrenList { } else { // If last index is not twice as large but still larger, // it's better to update it to the number of added nodes. - list.last_visited.set(Some(JS::from_ref(next))); + list.last_visited.set(Some(next)); list.last_index.set(len); } } @@ -198,7 +197,7 @@ impl ChildrenList { added: &[&Node], next: Option<&Node>) { let index = list.last_index.get(); - if removed == &*list.last_visited.get().unwrap().root() { + if removed == &*list.last_visited.get().unwrap() { let visited = match (prev, added, next) { (None, _, None) => { // Such cases where parent had only one child should @@ -213,7 +212,7 @@ impl ChildrenList { prev }, }; - list.last_visited.set(Some(JS::from_ref(visited))); + list.last_visited.set(Some(visited)); } else if added.len() != 1 { // The replaced child isn't the last visited one, and there are // 0 or more than 1 nodes to replace it. Special care must be @@ -250,13 +249,13 @@ impl ChildrenList { self.last_visited.set(None); self.last_index.set(0u32); } else if index < len as u32 { - self.last_visited.set(Some(JS::from_ref(added[index as usize]))); + self.last_visited.set(Some(added[index as usize])); } else { // Setting last visited to parent's last child serves no purpose, // so the middle is arbitrarily chosen here in case the caller // wants random access. let middle = len / 2; - self.last_visited.set(Some(JS::from_ref(added[middle]))); + self.last_visited.set(Some(added[middle])); self.last_index.set(middle as u32); } }, @@ -264,8 +263,7 @@ impl ChildrenList { } fn reset(&self) { - self.last_visited.set( - self.node.root().GetFirstChild().map(|node| JS::from_rooted(&node))); + self.last_visited.set(self.node.root().GetFirstChild().as_ref().map(Root::r)); self.last_index.set(0u32); } } diff --git a/components/script/dom/storageevent.rs b/components/script/dom/storageevent.rs index 76e697b2861..d9f1f60e395 100644 --- a/components/script/dom/storageevent.rs +++ b/components/script/dom/storageevent.rs @@ -37,7 +37,7 @@ impl StorageEvent { oldValue: oldValue, newValue: newValue, url: url, - storageArea: MutNullableHeap::new(storageArea.map(JS::from_ref)) + storageArea: MutNullableHeap::new(storageArea) } } diff --git a/components/script/dom/treewalker.rs b/components/script/dom/treewalker.rs index eb30ab5ff4b..7f4646a1618 100644 --- a/components/script/dom/treewalker.rs +++ b/components/script/dom/treewalker.rs @@ -35,7 +35,7 @@ impl TreeWalker { TreeWalker { reflector_: Reflector::new(), root_node: JS::from_ref(root_node), - current_node: MutHeap::new(JS::from_ref(root_node)), + current_node: MutHeap::new(root_node), what_to_show: what_to_show, filter: filter } @@ -85,18 +85,18 @@ impl TreeWalkerMethods for TreeWalker { // https://dom.spec.whatwg.org/#dom-treewalker-currentnode fn CurrentNode(&self) -> Root<Node> { - self.current_node.get().root() + self.current_node.get() } // https://dom.spec.whatwg.org/#dom-treewalker-currentnode fn SetCurrentNode(&self, node: &Node) { - self.current_node.set(JS::from_ref(node)); + self.current_node.set(node); } // https://dom.spec.whatwg.org/#dom-treewalker-parentnode fn ParentNode(&self) -> Fallible<Option<Root<Node>>> { // "1. Let node be the value of the currentNode attribute." - let mut node = self.current_node.get().root(); + let mut node = self.current_node.get(); // "2. While node is not null and is not root, run these substeps:" while !self.is_root_node(node.r()) { // "1. Let node be node's parent." @@ -106,7 +106,7 @@ impl TreeWalkerMethods for TreeWalker { // "2. If node is not null and filtering node returns FILTER_ACCEPT, // then set the currentNode attribute to node, return node." if NodeFilterConstants::FILTER_ACCEPT == try!(self.accept_node(node.r())) { - self.current_node.set(JS::from_rooted(&node)); + self.current_node.set(&node); return Ok(Some(node)) } }, @@ -148,7 +148,7 @@ impl TreeWalkerMethods for TreeWalker { // https://dom.spec.whatwg.org/#dom-treewalker-previousnode fn PreviousNode(&self) -> Fallible<Option<Root<Node>>> { // "1. Let node be the value of the currentNode attribute." - let mut node = self.current_node.get().root(); + let mut node = self.current_node.get(); // "2. While node is not root, run these substeps:" while !self.is_root_node(node.r()) { // "1. Let sibling be the previous sibling of node." @@ -170,7 +170,7 @@ impl TreeWalkerMethods for TreeWalker { _ if node.GetFirstChild().is_some() => node = node.GetLastChild().unwrap(), NodeFilterConstants::FILTER_ACCEPT => { - self.current_node.set(JS::from_rooted(&node)); + self.current_node.set(&node); return Ok(Some(node)) }, _ => break @@ -194,7 +194,7 @@ impl TreeWalkerMethods for TreeWalker { // "5. Filter node and if the return value is FILTER_ACCEPT, then // set the currentNode attribute to node and return node." if NodeFilterConstants::FILTER_ACCEPT == try!(self.accept_node(node.r())) { - self.current_node.set(JS::from_rooted(&node)); + self.current_node.set(&node); return Ok(Some(node)) } } @@ -205,7 +205,7 @@ impl TreeWalkerMethods for TreeWalker { // https://dom.spec.whatwg.org/#dom-treewalker-nextnode fn NextNode(&self) -> Fallible<Option<Root<Node>>> { // "1. Let node be the value of the currentNode attribute." - let mut node = self.current_node.get().root(); + let mut node = self.current_node.get(); // "2. Let result be FILTER_ACCEPT." let mut result = NodeFilterConstants::FILTER_ACCEPT; // "3. Run these substeps:" @@ -225,7 +225,7 @@ impl TreeWalkerMethods for TreeWalker { // "3. If result is FILTER_ACCEPT, then // set the currentNode attribute to node and return node." if NodeFilterConstants::FILTER_ACCEPT == result { - self.current_node.set(JS::from_rooted(&node)); + self.current_node.set(&node); return Ok(Some(node)) } } @@ -243,7 +243,7 @@ impl TreeWalkerMethods for TreeWalker { // "4. If result is FILTER_ACCEPT, then // set the currentNode attribute to node and return node." if NodeFilterConstants::FILTER_ACCEPT == result { - self.current_node.set(JS::from_rooted(&node)); + self.current_node.set(&node); return Ok(Some(node)) } } @@ -267,7 +267,7 @@ impl TreeWalker { { // "To **traverse children** of type *type*, run these steps:" // "1. Let node be the value of the currentNode attribute." - let cur = self.current_node.get().root(); + let cur = self.current_node.get(); // "2. Set node to node's first child if type is first, and node's last child if type is last." // "3. If node is null, return null." @@ -284,7 +284,7 @@ impl TreeWalker { // "2. If result is FILTER_ACCEPT, then set the currentNode // attribute to node and return node." NodeFilterConstants::FILTER_ACCEPT => { - self.current_node.set(JS::from_rooted(&node)); + self.current_node.set(&node); return Ok(Some(Root::from_ref(node.r()))) }, // "3. If result is FILTER_SKIP, run these subsubsteps:" @@ -342,7 +342,7 @@ impl TreeWalker { { // "To **traverse siblings** of type *type* run these steps:" // "1. Let node be the value of the currentNode attribute." - let mut node = self.current_node.get().root(); + let mut node = self.current_node.get(); // "2. If node is root, return null." if self.is_root_node(node.r()) { return Ok(None) @@ -361,7 +361,7 @@ impl TreeWalker { // "3. If result is FILTER_ACCEPT, then set the currentNode // attribute to node and return node." if NodeFilterConstants::FILTER_ACCEPT == result { - self.current_node.set(JS::from_rooted(&node)); + self.current_node.set(&node); return Ok(Some(node)) } @@ -447,7 +447,7 @@ impl TreeWalker { } fn is_current_node(&self, node: &Node) -> bool { - JS::from_ref(node) == self.current_node.get() + node == &*self.current_node.get() } } diff --git a/components/script/dom/uievent.rs b/components/script/dom/uievent.rs index a28783bc6e4..f01f8476356 100644 --- a/components/script/dom/uievent.rs +++ b/components/script/dom/uievent.rs @@ -92,7 +92,7 @@ impl UIEventMethods for UIEvent { } event.InitEvent(type_, can_bubble, cancelable); - self.view.set(view.map(JS::from_ref)); + self.view.set(view); self.detail.set(detail); } } diff --git a/components/script/dom/webglprogram.rs b/components/script/dom/webglprogram.rs index 37dfc3d7904..997f48c96b4 100644 --- a/components/script/dom/webglprogram.rs +++ b/components/script/dom/webglprogram.rs @@ -86,7 +86,7 @@ impl WebGLProgram { return Err(WebGLError::InvalidOperation); } - shader_slot.set(Some(JS::from_ref(shader))); + shader_slot.set(Some(shader)); self.renderer.send(CanvasMsg::WebGL(CanvasWebGLMsg::AttachShader(self.id, shader.id()))).unwrap(); diff --git a/components/script/dom/webglrenderingcontext.rs b/components/script/dom/webglrenderingcontext.rs index f5a3569da13..0b968b4b42f 100644 --- a/components/script/dom/webglrenderingcontext.rs +++ b/components/script/dom/webglrenderingcontext.rs @@ -12,7 +12,7 @@ use dom::bindings::codegen::InheritTypes::{EventCast, EventTargetCast, NodeCast} use dom::bindings::codegen::UnionTypes::ImageDataOrHTMLImageElementOrHTMLCanvasElementOrHTMLVideoElement; use dom::bindings::conversions::ToJSValConvertible; use dom::bindings::global::{GlobalField, GlobalRef}; -use dom::bindings::js::{JS, LayoutJS, Root}; +use dom::bindings::js::{JS, LayoutJS, MutNullableHeap, Root}; use dom::bindings::utils::{Reflector, reflect_dom_object}; use dom::event::{EventBubbles, EventCancelable}; use dom::htmlcanvaselement::HTMLCanvasElement; @@ -78,8 +78,8 @@ pub struct WebGLRenderingContext { canvas: JS<HTMLCanvasElement>, last_error: Cell<Option<WebGLError>>, texture_unpacking_settings: Cell<TextureUnpacking>, - bound_texture_2d: Cell<Option<JS<WebGLTexture>>>, - bound_texture_cube_map: Cell<Option<JS<WebGLTexture>>>, + bound_texture_2d: MutNullableHeap<JS<WebGLTexture>>, + bound_texture_cube_map: MutNullableHeap<JS<WebGLTexture>>, } impl WebGLRenderingContext { @@ -104,8 +104,8 @@ impl WebGLRenderingContext { canvas: JS::from_ref(canvas), last_error: Cell::new(None), texture_unpacking_settings: Cell::new(CONVERT_COLORSPACE), - bound_texture_2d: Cell::new(None), - bound_texture_cube_map: Cell::new(None), + bound_texture_2d: MutNullableHeap::new(None), + bound_texture_cube_map: MutNullableHeap::new(None), } }) } @@ -149,8 +149,8 @@ impl WebGLRenderingContext { pub fn bound_texture_for(&self, target: u32) -> Option<Root<WebGLTexture>> { match target { - constants::TEXTURE_2D => self.bound_texture_2d.get().map(|t| t.root()), - constants::TEXTURE_CUBE_MAP => self.bound_texture_cube_map.get().map(|t| t.root()), + constants::TEXTURE_2D => self.bound_texture_2d.get_rooted(), + constants::TEXTURE_CUBE_MAP => self.bound_texture_cube_map.get_rooted(), _ => unreachable!(), } @@ -360,7 +360,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { if let Some(texture) = texture { match texture.bind(target) { - Ok(_) => slot.set(Some(JS::from_ref(texture))), + Ok(_) => slot.set(Some(texture)), Err(err) => return self.webgl_error(err), } } else { |