diff options
author | Josh Matthews <josh@joshmatthews.net> | 2014-03-31 18:41:28 -0400 |
---|---|---|
committer | Josh Matthews <josh@joshmatthews.net> | 2014-05-03 14:18:30 -0400 |
commit | d7b96db33ca8f2b8a162df38e0f00e95f5ea6fa1 (patch) | |
tree | efd1e7f7ec1dd30467c2a67306e1a639837abead /src | |
parent | ffdc3f5b32a345b88eed774848924e862d47c093 (diff) | |
download | servo-d7b96db33ca8f2b8a162df38e0f00e95f5ea6fa1.tar.gz servo-d7b96db33ca8f2b8a162df38e0f00e95f5ea6fa1.zip |
Implement safe rooting strategy via Unrooted, Root, JSRef, and JS.
Diffstat (limited to 'src')
109 files changed, 1569 insertions, 1327 deletions
diff --git a/src/components/main/layout/wrapper.rs b/src/components/main/layout/wrapper.rs index 162c06d52a9..b9532e2d31c 100644 --- a/src/components/main/layout/wrapper.rs +++ b/src/components/main/layout/wrapper.rs @@ -40,7 +40,7 @@ use script::dom::element::{Element, HTMLAreaElementTypeId, HTMLAnchorElementType use script::dom::element::{HTMLLinkElementTypeId}; use script::dom::htmliframeelement::HTMLIFrameElement; use script::dom::htmlimageelement::HTMLImageElement; -use script::dom::node::{DocumentNodeTypeId, ElementNodeTypeId, Node, NodeTypeId, NodeHelpers}; +use script::dom::node::{DocumentNodeTypeId, ElementNodeTypeId, Node, NodeTypeId, LayoutNodeHelpers}; use script::dom::text::Text; use servo_msg::constellation_msg::{PipelineId, SubpageId}; use servo_util::namespace; @@ -163,7 +163,7 @@ impl<'ln> TLayoutNode for LayoutNode<'ln> { } fn type_id(&self) -> Option<NodeTypeId> { - Some(self.node.type_id()) + Some(self.node.type_id_for_layout()) } unsafe fn get_jsmanaged<'a>(&'a self) -> &'a JS<Node> { diff --git a/src/components/script/dom/attr.rs b/src/components/script/dom/attr.rs index 5b5fc39d1c9..d6c2d530862 100644 --- a/src/components/script/dom/attr.rs +++ b/src/components/script/dom/attr.rs @@ -4,7 +4,7 @@ use dom::bindings::codegen::BindingDeclarations::AttrBinding; use dom::bindings::codegen::InheritTypes::NodeCast; -use dom::bindings::js::{JS, JSRef}; +use dom::bindings::js::{JS, JSRef, Unrooted, RootCollection}; use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object}; use dom::element::Element; use dom::node::Node; @@ -45,7 +45,7 @@ impl Reflectable for Attr { impl Attr { fn new_inherited(local_name: DOMString, value: DOMString, name: DOMString, namespace: Namespace, - prefix: Option<DOMString>, owner: JS<Element>) -> Attr { + prefix: Option<DOMString>, owner: &JSRef<Element>) -> Attr { Attr { reflector_: Reflector::new(), local_name: local_name, @@ -53,25 +53,27 @@ impl Attr { name: name, //TODO: Intern attribute names namespace: namespace, prefix: prefix, - owner: owner, + owner: owner.unrooted(), } } pub fn new(window: &JSRef<Window>, local_name: DOMString, value: DOMString, name: DOMString, namespace: Namespace, - prefix: Option<DOMString>, owner: JS<Element>) -> JS<Attr> { + prefix: Option<DOMString>, owner: &JSRef<Element>) -> Unrooted<Attr> { let attr = Attr::new_inherited(local_name, value, name, namespace, prefix, owner); reflect_dom_object(~attr, window, AttrBinding::Wrap) } pub fn set_value(&mut self, set_type: AttrSettingType, value: DOMString) { - let node: JS<Node> = NodeCast::from(&self.owner); + let roots = RootCollection::new(); + let owner = self.owner.root(&roots); + let node: &JSRef<Node> = NodeCast::from_ref(&*owner); let namespace_is_null = self.namespace == namespace::Null; match set_type { ReplacedAttr => { if namespace_is_null { - vtable_for(&node).before_remove_attr(self.local_name.clone(), self.value.clone()); + vtable_for(node).before_remove_attr(self.local_name.clone(), self.value.clone()); } } FirstSetAttr => {} @@ -80,7 +82,7 @@ impl Attr { self.value = value; if namespace_is_null { - vtable_for(&node).after_set_attr(self.local_name.clone(), self.value.clone()); + vtable_for(node).after_set_attr(self.local_name.clone(), self.value.clone()); } } diff --git a/src/components/script/dom/attrlist.rs b/src/components/script/dom/attrlist.rs index ed476897c82..78f8211e3e0 100644 --- a/src/components/script/dom/attrlist.rs +++ b/src/components/script/dom/attrlist.rs @@ -4,7 +4,7 @@ use dom::attr::Attr; use dom::bindings::codegen::BindingDeclarations::AttrListBinding; -use dom::bindings::js::{JS, JSRef}; +use dom::bindings::js::{JS, JSRef, Unrooted}; use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object}; use dom::element::Element; use dom::window::Window; @@ -25,7 +25,7 @@ impl AttrList { } } - pub fn new(window: &JSRef<Window>, elem: &JSRef<Element>) -> JS<AttrList> { + pub fn new(window: &JSRef<Window>, elem: &JSRef<Element>) -> Unrooted<AttrList> { reflect_dom_object(~AttrList::new_inherited(window.unrooted(), elem.unrooted()), window, AttrListBinding::Wrap) } @@ -34,11 +34,11 @@ impl AttrList { self.owner.get().attrs.len() as u32 } - pub fn Item(&self, index: u32) -> Option<JS<Attr>> { - self.owner.get().attrs.as_slice().get(index as uint).map(|x| x.clone()) + pub fn Item(&self, index: u32) -> Option<Unrooted<Attr>> { + self.owner.get().attrs.as_slice().get(index as uint).map(|x| Unrooted::new(x.clone())) } - pub fn IndexedGetter(&self, index: u32, found: &mut bool) -> Option<JS<Attr>> { + pub fn IndexedGetter(&self, index: u32, found: &mut bool) -> Option<Unrooted<Attr>> { let item = self.Item(index); *found = item.is_some(); item diff --git a/src/components/script/dom/bindings/codegen/CodegenRust.py b/src/components/script/dom/bindings/codegen/CodegenRust.py index 5d4f6cc9bf4..30ff08e21ff 100644 --- a/src/components/script/dom/bindings/codegen/CodegenRust.py +++ b/src/components/script/dom/bindings/codegen/CodegenRust.py @@ -1008,6 +1008,13 @@ def typeNeedsCx(type, retVal=False): return True return type.isCallback() or type.isAny() or type.isObject() +def typeRetValNeedsRooting(type): + if type is None: + return False + if type.nullable(): + type = type.inner + return type.isGeckoInterface() and not type.isCallback() + def memberIsCreator(member): return member.getExtendedAttribute("Creator") is not None @@ -1039,7 +1046,7 @@ def getRetvalDeclarationForType(returnType, descriptorProvider): if returnType.isGeckoInterface(): descriptor = descriptorProvider.getDescriptor( returnType.unroll().inner.identifier.name) - result = CGGeneric(descriptor.nativeType) + result = CGGeneric(descriptor.returnType) if returnType.nullable(): result = CGWrapper(result, pre="Option<", post=">") return result @@ -2235,6 +2242,14 @@ class CGCallGenerator(CGThing): self.cgRoot.append(CGGeneric("}")) self.cgRoot.append(CGGeneric("result = result_fallible.unwrap();")) + if typeRetValNeedsRooting(returnType): + rooted_value = CGGeneric("result.root(&roots).root_ref().unrooted()") + if returnType.nullable(): + rooted_value = CGWrapper(rooted_value, pre="result.map(|result| ", post=")") + rooted_value = CGWrapper(rooted_value, pre="let result = ", post=";") + + self.cgRoot.append(rooted_value) + def define(self): return self.cgRoot.define() @@ -4306,7 +4321,7 @@ class CGBindingRoot(CGThing): 'js::glue::{RUST_JS_NumberValue, RUST_JSID_IS_STRING}', 'dom::types::*', 'dom::bindings', - 'dom::bindings::js::{JS, JSRef, RootCollection, RootedReference}', + 'dom::bindings::js::{JS, JSRef, RootCollection, RootedReference, Unrooted}', 'dom::bindings::utils::{CreateDOMGlobal, CreateInterfaceObjects2}', 'dom::bindings::utils::{ConstantSpec, cx_for_dom_object, Default}', 'dom::bindings::utils::{dom_object_slot, DOM_OBJECT_SLOT, DOMClass}', @@ -5277,8 +5292,9 @@ class GlobalGenRoots(): descriptors = config.getDescriptors(register=True, hasInterfaceObject=True) allprotos = [CGGeneric("#![allow(unused_imports)]\n"), CGGeneric("use dom::types::*;\n"), - CGGeneric("use dom::bindings::js::{JS, JSRef};\n"), + CGGeneric("use dom::bindings::js::{JS, JSRef, Unrooted};\n"), CGGeneric("use dom::bindings::trace::JSTraceable;\n"), + CGGeneric("use dom::bindings::utils::Reflectable;\n"), CGGeneric("use serialize::{Encodable, Encoder};\n"), CGGeneric("use js::jsapi::JSTracer;\n\n")] for descriptor in descriptors: @@ -5310,7 +5326,7 @@ class GlobalGenRoots(): } #[inline(always)] - fn to<T: ${toBound}>(base: &JS<T>) -> Option<JS<Self>> { + fn to<T: ${toBound}+Reflectable>(base: &JS<T>) -> Option<JS<Self>> { match base.get().${checkFn}() { true => unsafe { Some(base.clone().transmute()) }, false => None @@ -5318,7 +5334,23 @@ class GlobalGenRoots(): } #[inline(always)] - unsafe fn to_unchecked<T: ${toBound}>(base: &JS<T>) -> JS<Self> { + fn to_ref<'a, 'b, T: ${toBound}+Reflectable>(base: &'a JSRef<'b, T>) -> Option<&'a JSRef<'b, Self>> { + match base.get().${checkFn}() { + true => unsafe { Some(base.transmute()) }, + false => None + } + } + + #[inline(always)] + fn to_mut_ref<'a, 'b, T: ${toBound}+Reflectable>(base: &'a mut JSRef<'b, T>) -> Option<&'a mut JSRef<'b, Self>> { + match base.get().${checkFn}() { + true => unsafe { Some(base.transmute_mut()) }, + false => None + } + } + + #[inline(always)] + unsafe fn to_unchecked<T: ${toBound}+Reflectable>(base: &JS<T>) -> JS<Self> { assert!(base.get().${checkFn}()); base.clone().transmute() } @@ -5330,6 +5362,10 @@ class GlobalGenRoots(): fn from_mut_ref<'a, 'b, T: ${fromBound}>(derived: &'a mut JSRef<'b, T>) -> &'a mut JSRef<'b, Self> { unsafe { derived.transmute_mut() } } + + fn from_unrooted<T: ${fromBound}+Reflectable>(derived: Unrooted<T>) -> Unrooted<Self> { + unsafe { derived.transmute() } + } } ''').substitute({'checkFn': 'is_' + name.lower(), 'castTraitName': name + 'Cast', diff --git a/src/components/script/dom/bindings/codegen/Configuration.py b/src/components/script/dom/bindings/codegen/Configuration.py index a1ccb460ee2..eedb200c75e 100644 --- a/src/components/script/dom/bindings/codegen/Configuration.py +++ b/src/components/script/dom/bindings/codegen/Configuration.py @@ -133,6 +133,7 @@ class Descriptor(DescriptorProvider): else: nativeTypeDefault = 'JS<%s>' % ifaceName + self.returnType = "Unrooted<%s>" % ifaceName self.nativeType = desc.get('nativeType', nativeTypeDefault) self.concreteType = desc.get('concreteType', ifaceName) self.needsAbstract = desc.get('needsAbstract', []) diff --git a/src/components/script/dom/bindings/js.rs b/src/components/script/dom/bindings/js.rs index dac459f9c03..2386777cac9 100644 --- a/src/components/script/dom/bindings/js.rs +++ b/src/components/script/dom/bindings/js.rs @@ -10,8 +10,52 @@ use layout_interface::TrustedNodeAddress; use std::cast; use std::cell::{Cell, RefCell}; use std::ptr; -//use std::ops::{Deref, DerefMut}; +/// A type that represents a JS-owned value that may or may not be rooted. +/// Importantly, it requires rooting in order to interact with the value in any way. +/// Can be assigned into JS-owned member fields (ie. JS<T> types) safely via the +/// `JS<T>::assign` method or `OptionalAssignable::assign` (for Option<JS<T>> fields). +pub struct Unrooted<T> { + inner: JS<T> +} + +impl<T> Eq for Unrooted<T> { + fn eq(&self, other: &Unrooted<T>) -> bool { + self.inner == other.inner + } +} + +impl<T: Reflectable> Unrooted<T> { + /// Create a new Unrooted value from a JS-owned value. + pub fn new(inner: JS<T>) -> Unrooted<T> { + Unrooted { + inner: inner + } + } + + /// Create a new Unrooted value from a rooted value. + pub fn new_rooted<'a>(root: &JSRef<'a, T>) -> Unrooted<T> { + Unrooted { + inner: root.unrooted() + } + } + + /// Root this unrooted value. + pub fn root<'a, 'b>(self, collection: &'a RootCollection) -> Root<'a, 'b, T> { + collection.new_root(&self.inner) + } + + unsafe fn inner(&self) -> JS<T> { + self.inner.clone() + } + + //XXXjdm It would be lovely if this could be private. + pub unsafe fn transmute<To>(self) -> Unrooted<To> { + cast::transmute(self) + } +} + +/// A rooted, JS-owned value. Must only be used as a field in other JS-owned types. pub struct JS<T> { ptr: RefCell<*mut T> } @@ -32,12 +76,15 @@ impl <T> Clone for JS<T> { } impl<T: Reflectable> JS<T> { + /// Create a new JS-reflected DOM object; returns an Unrooted type because the new value + /// is not safe to use until it is rooted. pub fn new(obj: ~T, window: &JSRef<Window>, - wrap_fn: extern "Rust" fn(*JSContext, &JSRef<Window>, ~T) -> JS<T>) -> JS<T> { - wrap_fn(window.get().get_cx(), window, obj) + wrap_fn: extern "Rust" fn(*JSContext, &JSRef<Window>, ~T) -> JS<T>) -> Unrooted<T> { + Unrooted::new(wrap_fn(window.get().get_cx(), window, obj)) } + /// Create a new JS-owned value wrapped from a raw Rust pointer. pub unsafe fn from_raw(raw: *mut T) -> JS<T> { JS { ptr: RefCell::new(raw) @@ -45,6 +92,7 @@ impl<T: Reflectable> JS<T> { } + /// Create a new JS-owned value wrapped from an address known to be a Node pointer. pub unsafe fn from_trusted_node_address(inner: TrustedNodeAddress) -> JS<T> { let TrustedNodeAddress(addr) = inner; JS { @@ -52,7 +100,8 @@ impl<T: Reflectable> JS<T> { } } - pub fn root<'a>(&self, collection: &'a RootCollection) -> Root<'a, T> { + /// Root this JS-owned value to prevent its collection as garbage. + pub fn root<'a, 'b>(&self, collection: &'a RootCollection) -> Root<'a, 'b, T> { collection.new_root(self) } } @@ -67,7 +116,7 @@ impl<T: Reflectable> Reflectable for JS<T> { } } -impl<T> JS<T> { +impl<T: Reflectable> JS<T> { pub fn get<'a>(&'a self) -> &'a T { let borrowed = self.ptr.borrow(); unsafe { @@ -88,6 +137,13 @@ impl<T> JS<T> { pub unsafe fn unsafe_get(&self) -> *mut T { cast::transmute_copy(&self.ptr) } + + /// Store an unrooted value in this field. This is safe under the assumption that JS<T> + /// values are only used as fields in DOM types that are reachable in the GC graph, + /// so this unrooted value becomes transitively rooted for the lifetime of its new owner. + pub fn assign(&mut self, val: Unrooted<T>) { + *self = unsafe { val.inner() }; + } } impl<From, To> JS<From> { @@ -105,17 +161,86 @@ pub trait RootedReference<T> { fn root_ref<'a>(&'a self) -> Option<JSRef<'a, T>>; } -impl<'a, T: Reflectable> RootedReference<T> for Option<Root<'a, T>> { +impl<'a, 'b, T: Reflectable> RootedReference<T> for Option<Root<'a, 'b, T>> { fn root_ref<'a>(&'a self) -> Option<JSRef<'a, T>> { self.as_ref().map(|root| root.root_ref()) } } +// This trait should never be public; it allows access to unrooted values, and is thus +// easy to misuse. +/*definitely not public*/ trait Assignable<T> { + fn get_js(&self) -> JS<T>; +} + +impl<T> Assignable<T> for JS<T> { + fn get_js(&self) -> JS<T> { + self.clone() + } +} + +impl<'a, T> Assignable<T> for JSRef<'a, T> { + fn get_js(&self) -> JS<T> { + self.unrooted() + } +} + +// Assignable should not be exposed publically, since it's used to +// extract unrooted values in a safe way WHEN USED CORRECTLY. +impl<T: Reflectable> Assignable<T> for Unrooted<T> { + fn get_js(&self) -> JS<T> { + unsafe { self.inner() } + } +} + +pub trait OptionalAssignable<T> { + fn assign(&mut self, val: Option<T>); +} + +impl<T: Assignable<U>, U: Reflectable> OptionalAssignable<T> for Option<JS<U>> { + fn assign(&mut self, val: Option<T>) { + *self = val.map(|val| val.get_js()); + } +} + +pub trait OptionalRootable<T> { + fn root<'a, 'b>(self, roots: &'a RootCollection) -> Option<Root<'a, 'b, T>>; +} + +impl<T: Reflectable> OptionalRootable<T> for Option<Unrooted<T>> { + fn root<'a, 'b>(self, roots: &'a RootCollection) -> Option<Root<'a, 'b, T>> { + self.map(|inner| inner.root(roots)) + } +} + +pub trait ResultRootable<T,U> { + fn root<'a, 'b>(self, roots: &'a RootCollection) -> Result<Root<'a, 'b, T>, U>; +} + +impl<T: Reflectable, U> ResultRootable<T, U> for Result<Unrooted<T>, U> { + fn root<'a, 'b>(self, roots: &'a RootCollection) -> Result<Root<'a, 'b, T>, U> { + self.map(|inner| inner.root(roots)) + } +} + +/// Provides a facility to push unrooted values onto lists of rooted values. This is safe +/// under the assumption that said lists are reachable via the GC graph, and therefore the +/// new values are transitively rooted for the lifetime of their new owner. +pub trait UnrootedPushable<T> { + fn push_unrooted(&mut self, val: Unrooted<T>); +} + +impl<T: Reflectable> UnrootedPushable<T> for Vec<JS<T>> { + fn push_unrooted(&mut self, val: Unrooted<T>) { + unsafe { self.push(val.inner()) }; + } +} + #[deriving(Eq, Clone)] struct RootReference(*JSObject); impl RootReference { - fn new<'a, T: Reflectable>(unrooted: &Root<'a, T>) -> RootReference { + fn new<'a, 'b, T: Reflectable>(unrooted: &Root<'a, 'b, T>) -> RootReference { RootReference(unrooted.rooted()) } @@ -126,6 +251,7 @@ impl RootReference { static MAX_STACK_ROOTS: uint = 10; +/// An opaque, LIFO rooting mechanism. pub struct RootCollection { roots: [Cell<RootReference>, ..MAX_STACK_ROOTS], current: Cell<uint>, @@ -139,7 +265,7 @@ impl RootCollection { } } - fn new_root<'a, T: Reflectable>(&'a self, unrooted: &JS<T>) -> Root<'a, T> { + fn new_root<'a, 'b, T: Reflectable>(&'a self, unrooted: &JS<T>) -> Root<'a, 'b, T> { Root::new(self, unrooted) } @@ -147,13 +273,15 @@ impl RootCollection { let current = self.current.get(); assert!(current < MAX_STACK_ROOTS); self.roots[current].set(unrooted); + debug!(" rooting {:?}", unrooted); self.current.set(current + 1); } - fn root<'a, T: Reflectable>(&self, unrooted: &Root<'a, T>) { + fn root<'a, 'b, T: Reflectable>(&self, unrooted: &Root<'a, 'b, T>) { self.root_impl(RootReference::new(unrooted)); } + /// Root a raw JS pointer. pub fn root_raw(&self, unrooted: *JSObject) { self.root_impl(RootReference(unrooted)); } @@ -162,29 +290,41 @@ impl RootCollection { let mut current = self.current.get(); assert!(current != 0); current -= 1; + debug!("unrooting {:?} (expecting {:?}", self.roots[current].get(), rooted); assert!(self.roots[current].get() == rooted); self.roots[current].set(RootReference::null()); self.current.set(current); } - fn unroot<'a, T: Reflectable>(&self, rooted: &Root<'a, T>) { + fn unroot<'a, 'b, T: Reflectable>(&self, rooted: &Root<'a, 'b, T>) { self.unroot_impl(RootReference::new(rooted)); } + /// Unroot a raw JS pointer. Must occur in reverse order to its rooting. pub fn unroot_raw(&self, rooted: *JSObject) { self.unroot_impl(RootReference(rooted)); } } -pub struct Root<'a, T> { +/// A rooted JS value. 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. Roots cannot outlive the associated RootCollection object. +/// Attempts to transfer ownership of a Root via moving will trigger dynamic unrooting +/// failures due to incorrect ordering. +pub struct Root<'a, 'b, T> { root_list: &'a RootCollection, + jsref: JSRef<'b, T>, ptr: RefCell<*mut T>, } -impl<'a, T: Reflectable> Root<'a, T> { - fn new(roots: &'a RootCollection, unrooted: &JS<T>) -> Root<'a, T> { +impl<'a, 'b, T: Reflectable> Root<'a, 'b, T> { + fn new(roots: &'a RootCollection, unrooted: &JS<T>) -> Root<'a, 'b, T> { let root = Root { root_list: roots, + jsref: JSRef { + ptr: unrooted.ptr.clone(), + chain: unsafe { ::std::cast::transmute_region(&()) }, + }, ptr: unrooted.ptr.clone() }; roots.root(&root); @@ -209,24 +349,27 @@ impl<'a, T: Reflectable> Root<'a, T> { self.reflector().get_jsobject() } + fn internal_root_ref<'a>(&'a self) -> &'a JSRef<'b, T> { + &'a self.jsref + } + + fn mut_internal_root_ref<'a>(&'a mut self) -> &'a mut JSRef<'b, T> { + &'a mut self.jsref + } + pub fn root_ref<'b>(&'b self) -> JSRef<'b,T> { - unsafe { - JSRef { - ptr: self.ptr.clone(), - chain: ::std::cast::transmute_region(&()), - } - } + self.internal_root_ref().clone() } } #[unsafe_destructor] -impl<'a, T: Reflectable> Drop for Root<'a, T> { +impl<'a, 'b, T: Reflectable> Drop for Root<'a, 'b, T> { fn drop(&mut self) { self.root_list.unroot(self); } } -impl<'a, T: Reflectable> Reflectable for Root<'a, T> { +impl<'a, 'b, T: Reflectable> Reflectable for Root<'a, 'b, T> { fn reflector<'a>(&'a self) -> &'a Reflector { self.get().reflector() } @@ -236,17 +379,29 @@ impl<'a, T: Reflectable> Reflectable for Root<'a, T> { } } -/*impl<'a, T> Deref for Root<'a, T> { - fn deref<'a>(&'a self) -> &'a T { +impl<'a, 'b, T: Reflectable> Deref<JSRef<'b, T>> for Root<'a, 'b, T> { + fn deref<'c>(&'c self) -> &'c JSRef<'b, T> { + self.internal_root_ref() + } +} + +impl<'a, 'b, T: Reflectable> DerefMut<JSRef<'b, T>> for Root<'a, 'b, T> { + fn deref_mut<'c>(&'c mut self) -> &'c mut JSRef<'b, T> { + self.mut_internal_root_ref() + } +} + +impl<'a, T: Reflectable> Deref<T> for JSRef<'a, T> { + fn deref<'b>(&'b self) -> &'b T { self.get() } } -impl<'a, T> DerefMut for Root<'a, T> { - fn deref_mut<'a>(&'a mut self) -> &'a mut T { +impl<'a, T: Reflectable> DerefMut<T> for JSRef<'a, T> { + fn deref_mut<'b>(&'b mut self) -> &'b mut T { self.get_mut() } -}*/ +} /// Encapsulates a reference to something that is guaranteed to be alive. This is freely copyable. pub struct JSRef<'a, T> { diff --git a/src/components/script/dom/bindings/utils.rs b/src/components/script/dom/bindings/utils.rs index 7f240070ea1..80aa9c364ee 100644 --- a/src/components/script/dom/bindings/utils.rs +++ b/src/components/script/dom/bindings/utils.rs @@ -5,7 +5,7 @@ use dom::bindings::codegen::PrototypeList; use dom::bindings::codegen::PrototypeList::MAX_PROTO_CHAIN_LENGTH; use dom::bindings::conversions::{FromJSValConvertible, IDLInterface}; -use dom::bindings::js::{JS, JSRef}; +use dom::bindings::js::{JS, JSRef, RootCollection, Unrooted}; use dom::bindings::trace::Untraceable; use dom::browsercontext; use dom::window; @@ -391,7 +391,7 @@ pub fn reflect_dom_object<T: Reflectable> (obj: ~T, window: &JSRef<window::Window>, wrap_fn: extern "Rust" fn(*JSContext, &JSRef<window::Window>, ~T) -> JS<T>) - -> JS<T> { + -> Unrooted<T> { JS::new(obj, window, wrap_fn) } @@ -613,18 +613,20 @@ pub extern fn outerize_global(_cx: *JSContext, obj: JSHandleObject) -> *JSObject } /// Returns the global object of the realm that the given JS object was created in. -pub fn global_object_for_js_object(obj: *JSObject) -> JS<window::Window> { +pub fn global_object_for_js_object(obj: *JSObject) -> Unrooted<window::Window> { unsafe { let global = GetGlobalForObjectCrossCompartment(obj); let clasp = JS_GetClass(global); assert!(((*clasp).flags & (JSCLASS_IS_DOMJSCLASS | JSCLASS_IS_GLOBAL)) != 0); - FromJSValConvertible::from_jsval(ptr::null(), ObjectOrNullValue(global), ()) - .ok().expect("found DOM global that doesn't unwrap to Window") + Unrooted::new( + FromJSValConvertible::from_jsval(ptr::null(), ObjectOrNullValue(global), ()) + .ok().expect("found DOM global that doesn't unwrap to Window")) } } fn cx_for_dom_reflector(obj: *JSObject) -> *JSContext { - let win = global_object_for_js_object(obj); + let roots = RootCollection::new(); + let win = global_object_for_js_object(obj).root(&roots); let js_info = win.get().page().js_info(); match *js_info { Some(ref info) => info.js_context.deref().deref().ptr, diff --git a/src/components/script/dom/blob.rs b/src/components/script/dom/blob.rs index 8dba1775ff6..0399568063d 100644 --- a/src/components/script/dom/blob.rs +++ b/src/components/script/dom/blob.rs @@ -2,7 +2,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -use dom::bindings::js::{JS, JSRef, RootCollection}; +use dom::bindings::js::{JS, JSRef, RootCollection, Unrooted}; use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object}; use dom::bindings::error::Fallible; use dom::bindings::codegen::BindingDeclarations::BlobBinding; @@ -23,7 +23,7 @@ impl Blob { } } - pub fn new(window: &JSRef<Window>) -> JS<Blob> { + pub fn new(window: &JSRef<Window>) -> Unrooted<Blob> { reflect_dom_object(~Blob::new_inherited(window.unrooted()), window, BlobBinding::Wrap) @@ -31,7 +31,7 @@ impl Blob { } impl Blob { - pub fn Constructor(window: &JSRef<Window>) -> Fallible<JS<Blob>> { + pub fn Constructor(window: &JSRef<Window>) -> Fallible<Unrooted<Blob>> { Ok(Blob::new(window)) } @@ -43,7 +43,7 @@ impl Blob { ~"" } - pub fn Slice(&self, _start: Option<i64>, _end: Option<i64>, _contentType: Option<DOMString>) -> JS<Blob> { + pub fn Slice(&self, _start: Option<i64>, _end: Option<i64>, _contentType: Option<DOMString>) -> Unrooted<Blob> { let roots = RootCollection::new(); let window = self.window.root(&roots); Blob::new(&window.root_ref()) diff --git a/src/components/script/dom/browsercontext.rs b/src/components/script/dom/browsercontext.rs index 86540c12a53..fbb63420520 100644 --- a/src/components/script/dom/browsercontext.rs +++ b/src/components/script/dom/browsercontext.rs @@ -2,7 +2,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -use dom::bindings::js::JS; +use dom::bindings::js::{JS, JSRef}; use dom::bindings::trace::Traceable; use dom::bindings::utils::Reflectable; use dom::document::Document; @@ -22,7 +22,7 @@ pub struct BrowserContext { } impl BrowserContext { - pub fn new(document: &JS<Document>) -> BrowserContext { + pub fn new(document: &JSRef<Document>) -> BrowserContext { let mut context = BrowserContext { history: vec!(SessionHistoryEntry::new(document)), active_index: 0, @@ -71,9 +71,9 @@ pub struct SessionHistoryEntry { } impl SessionHistoryEntry { - fn new(document: &JS<Document>) -> SessionHistoryEntry { + fn new(document: &JSRef<Document>) -> SessionHistoryEntry { SessionHistoryEntry { - document: document.clone(), + document: document.unrooted(), children: vec!() } } diff --git a/src/components/script/dom/clientrect.rs b/src/components/script/dom/clientrect.rs index 977c4569bf5..4e4e2dbdcc6 100644 --- a/src/components/script/dom/clientrect.rs +++ b/src/components/script/dom/clientrect.rs @@ -3,7 +3,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use dom::bindings::codegen::BindingDeclarations::ClientRectBinding; -use dom::bindings::js::{JS, JSRef}; +use dom::bindings::js::{JS, JSRef, Unrooted}; use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object}; use dom::window::Window; use servo_util::geometry::Au; @@ -34,7 +34,7 @@ impl ClientRect { pub fn new(window: &JSRef<Window>, top: Au, bottom: Au, - left: Au, right: Au) -> JS<ClientRect> { + left: Au, right: Au) -> Unrooted<ClientRect> { let rect = ClientRect::new_inherited(window.unrooted(), top, bottom, left, right); reflect_dom_object(~rect, window, ClientRectBinding::Wrap) } diff --git a/src/components/script/dom/clientrectlist.rs b/src/components/script/dom/clientrectlist.rs index abd87c47455..a9beec896e8 100644 --- a/src/components/script/dom/clientrectlist.rs +++ b/src/components/script/dom/clientrectlist.rs @@ -3,7 +3,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use dom::bindings::codegen::BindingDeclarations::ClientRectListBinding; -use dom::bindings::js::{JS, JSRef}; +use dom::bindings::js::{JS, JSRef, Unrooted}; use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object}; use dom::clientrect::ClientRect; use dom::window::Window; @@ -17,16 +17,16 @@ pub struct ClientRectList { impl ClientRectList { pub fn new_inherited(window: JS<Window>, - rects: Vec<JS<ClientRect>>) -> ClientRectList { + rects: Vec<JSRef<ClientRect>>) -> ClientRectList { ClientRectList { reflector_: Reflector::new(), - rects: rects, + rects: rects.iter().map(|rect| rect.unrooted()).collect(), window: window, } } pub fn new(window: &JSRef<Window>, - rects: Vec<JS<ClientRect>>) -> JS<ClientRectList> { + rects: Vec<JSRef<ClientRect>>) -> Unrooted<ClientRectList> { reflect_dom_object(~ClientRectList::new_inherited(window.unrooted(), rects), window, ClientRectListBinding::Wrap) } @@ -35,15 +35,15 @@ impl ClientRectList { self.rects.len() as u32 } - pub fn Item(&self, index: u32) -> Option<JS<ClientRect>> { + pub fn Item(&self, index: u32) -> Option<Unrooted<ClientRect>> { if index < self.rects.len() as u32 { - Some(self.rects.get(index as uint).clone()) + Some(Unrooted::new(self.rects.get(index as uint).clone())) } else { None } } - pub fn IndexedGetter(&self, index: u32, found: &mut bool) -> Option<JS<ClientRect>> { + pub fn IndexedGetter(&self, index: u32, found: &mut bool) -> Option<Unrooted<ClientRect>> { *found = index < self.rects.len() as u32; self.Item(index) } diff --git a/src/components/script/dom/comment.rs b/src/components/script/dom/comment.rs index a0786441fe6..779fb6415e9 100644 --- a/src/components/script/dom/comment.rs +++ b/src/components/script/dom/comment.rs @@ -4,7 +4,7 @@ use dom::bindings::codegen::InheritTypes::CommentDerived; use dom::bindings::codegen::BindingDeclarations::CommentBinding; -use dom::bindings::js::{JS, JSRef, RootCollection}; +use dom::bindings::js::{JS, JSRef, RootCollection, Unrooted}; use dom::bindings::error::Fallible; use dom::characterdata::CharacterData; use dom::document::Document; @@ -35,12 +35,12 @@ impl Comment { } } - pub fn new(text: DOMString, document: &JSRef<Document>) -> JS<Comment> { + pub fn new(text: DOMString, document: &JSRef<Document>) -> Unrooted<Comment> { let node = Comment::new_inherited(text, document.unrooted()); Node::reflect_node(~node, document, CommentBinding::Wrap) } - pub fn Constructor(owner: &JSRef<Window>, data: DOMString) -> Fallible<JS<Comment>> { + pub fn Constructor(owner: &JSRef<Window>, data: DOMString) -> Fallible<Unrooted<Comment>> { let roots = RootCollection::new(); let document = owner.get().Document(); let document = document.root(&roots); diff --git a/src/components/script/dom/console.rs b/src/components/script/dom/console.rs index a7908c6bc4f..ce41ed45212 100644 --- a/src/components/script/dom/console.rs +++ b/src/components/script/dom/console.rs @@ -3,7 +3,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use dom::bindings::codegen::BindingDeclarations::ConsoleBinding; -use dom::bindings::js::{JS, JSRef}; +use dom::bindings::js::{JSRef, Unrooted}; use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object}; use dom::window::Window; use servo_util::str::DOMString; @@ -20,7 +20,7 @@ impl Console { } } - pub fn new(window: &JSRef<Window>) -> JS<Console> { + pub fn new(window: &JSRef<Window>) -> Unrooted<Console> { reflect_dom_object(~Console::new_inherited(), window, ConsoleBinding::Wrap) } diff --git a/src/components/script/dom/document.rs b/src/components/script/dom/document.rs index 44b141dcea5..e2984a1bf82 100644 --- a/src/components/script/dom/document.rs +++ b/src/components/script/dom/document.rs @@ -3,11 +3,11 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use dom::bindings::codegen::InheritTypes::{DocumentDerived, EventCast, HTMLElementCast}; -use dom::bindings::codegen::InheritTypes::{DocumentBase, NodeCast, DocumentCast}; use dom::bindings::codegen::InheritTypes::{HTMLHeadElementCast, TextCast, ElementCast}; -use dom::bindings::codegen::InheritTypes::{DocumentTypeCast, HTMLHtmlElementCast}; +use dom::bindings::codegen::InheritTypes::{DocumentTypeCast, HTMLHtmlElementCast, NodeCast}; use dom::bindings::codegen::BindingDeclarations::DocumentBinding; -use dom::bindings::js::{JS, JSRef, RootCollection}; +use dom::bindings::js::{JS, JSRef, RootCollection, Unrooted, OptionalAssignable}; +use dom::bindings::js::OptionalRootable; use dom::bindings::trace::Untraceable; use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object}; use dom::bindings::error::{ErrorResult, Fallible, NotSupported, InvalidCharacter, HierarchyRequest, NamespaceError}; @@ -22,14 +22,14 @@ use dom::element::{HTMLBodyElementTypeId, HTMLFrameSetElementTypeId}; use dom::event::Event; use dom::eventtarget::{EventTarget, NodeTargetTypeId}; use dom::htmlcollection::{HTMLCollection, CollectionFilter}; -use dom::nodelist::NodeList; use dom::htmlelement::HTMLElement; use dom::htmlheadelement::HTMLHeadElement; use dom::htmlhtmlelement::HTMLHtmlElement; use dom::htmltitleelement::HTMLTitleElement; use dom::mouseevent::MouseEvent; -use dom::node::{Node, ElementNodeTypeId, DocumentNodeTypeId, NodeHelpers, INode}; -use dom::node::{CloneChildren, DoNotCloneChildren}; +use dom::node::{Node, ElementNodeTypeId, DocumentNodeTypeId, NodeHelpers, AppendChild}; +use dom::node::{CloneChildren, DoNotCloneChildren, RemoveChild, ReplaceChild}; +use dom::nodelist::NodeList; use dom::text::Text; use dom::processinginstruction::ProcessingInstruction; use dom::uievent::UIEvent; @@ -77,21 +77,19 @@ impl DocumentDerived for EventTarget { } impl Document { - pub fn reflect_document<D: Reflectable+DocumentBase> - (document: ~D, - window: &JSRef<Window>, - wrap_fn: extern "Rust" fn(*JSContext, &JSRef<Window>, ~D) -> JS<D>) - -> JS<D> { + pub fn reflect_document(document: ~Document, + window: &JSRef<Window>, + wrap_fn: extern "Rust" fn(*JSContext, &JSRef<Window>, ~Document) -> JS<Document>) + -> Unrooted<Document> { let roots = RootCollection::new(); assert!(document.reflector().get_jsobject().is_null()); - let raw_doc = reflect_dom_object(document, window, wrap_fn); + let mut raw_doc = reflect_dom_object(document, window, wrap_fn).root(&roots); assert!(raw_doc.reflector().get_jsobject().is_not_null()); - let document = DocumentCast::from(&raw_doc); - let document_root = document.root(&roots); - let mut node: JS<Node> = NodeCast::from(&document); - node.get_mut().set_owner_doc(&document_root.root_ref()); - raw_doc + let mut doc_alias = raw_doc.clone(); + let node: &mut JSRef<Node> = NodeCast::from_mut_ref(&mut doc_alias); + node.get_mut().set_owner_doc(&*raw_doc); + Unrooted::new_rooted(&*raw_doc) } pub fn new_inherited(window: JS<Window>, @@ -124,7 +122,7 @@ impl Document { } } - pub fn new(window: &JSRef<Window>, url: Option<Url>, doctype: IsHTMLDocument, content_type: Option<DOMString>) -> JS<Document> { + pub fn new(window: &JSRef<Window>, url: Option<Url>, doctype: IsHTMLDocument, content_type: Option<DOMString>) -> Unrooted<Document> { let document = Document::new_inherited(window.unrooted(), url, doctype, content_type); Document::reflect_document(~document, window, DocumentBinding::Wrap) } @@ -138,7 +136,7 @@ impl Document { impl Document { // http://dom.spec.whatwg.org/#dom-document - pub fn Constructor(owner: &JSRef<Window>) -> Fallible<JS<Document>> { + pub fn Constructor(owner: &JSRef<Window>) -> Fallible<Unrooted<Document>> { Ok(Document::new(owner, None, NonHTMLDocument, None)) } } @@ -155,13 +153,13 @@ impl Reflectable for Document { impl Document { // http://dom.spec.whatwg.org/#dom-document-implementation - pub fn Implementation(&mut self) -> JS<DOMImplementation> { + pub fn Implementation(&mut self) -> Unrooted<DOMImplementation> { if self.implementation.is_none() { let roots = RootCollection::new(); let window = self.window.root(&roots); - self.implementation = Some(DOMImplementation::new(&window.root_ref())); + self.implementation.assign(Some(DOMImplementation::new(&*window))); } - self.implementation.get_ref().clone() + Unrooted::new(self.implementation.get_ref().clone()) } // http://dom.spec.whatwg.org/#dom-document-url @@ -205,25 +203,29 @@ impl Document { } // http://dom.spec.whatwg.org/#dom-document-doctype - pub fn GetDoctype(&self) -> Option<JS<DocumentType>> { - self.node.children().find(|child| child.is_doctype()) - .map(|node| DocumentTypeCast::to(&node).unwrap()) + pub fn GetDoctype(&self) -> Option<Unrooted<DocumentType>> { + self.node.children().find(|child| { + child.is_doctype() + }).map(|node| { + let doctype: &JSRef<DocumentType> = DocumentTypeCast::to_ref(&node).unwrap(); + Unrooted::new(doctype.unrooted()) + }) } // http://dom.spec.whatwg.org/#dom-document-documentelement - pub fn GetDocumentElement(&self) -> Option<JS<Element>> { - self.node.child_elements().next() + pub fn GetDocumentElement(&self) -> Option<Unrooted<Element>> { + self.node.child_elements().next().map(|elem| Unrooted::new_rooted(&elem)) } // http://dom.spec.whatwg.org/#dom-document-getelementsbytagname - pub fn GetElementsByTagName(&self, abstract_self: &JSRef<Document>, tag_name: DOMString) -> JS<HTMLCollection> { + pub fn GetElementsByTagName(&self, abstract_self: &JSRef<Document>, tag_name: DOMString) -> Unrooted<HTMLCollection> { let roots = RootCollection::new(); let window = self.window.root(&roots); - HTMLCollection::by_tag_name(&window.root_ref(), NodeCast::from_ref(abstract_self), tag_name) + HTMLCollection::by_tag_name(&*window, NodeCast::from_ref(abstract_self), tag_name) } // http://dom.spec.whatwg.org/#dom-document-getelementsbytagnamens - pub fn GetElementsByTagNameNS(&self, abstract_self: &JSRef<Document>, maybe_ns: Option<DOMString>, tag_name: DOMString) -> JS<HTMLCollection> { + pub fn GetElementsByTagNameNS(&self, abstract_self: &JSRef<Document>, maybe_ns: Option<DOMString>, tag_name: DOMString) -> Unrooted<HTMLCollection> { let roots = RootCollection::new(); let window = self.window.root(&roots); @@ -231,28 +233,28 @@ impl Document { Some(namespace) => Namespace::from_str(namespace), None => Null }; - HTMLCollection::by_tag_name_ns(&window.root_ref(), NodeCast::from_ref(abstract_self), tag_name, namespace) + HTMLCollection::by_tag_name_ns(&*window, NodeCast::from_ref(abstract_self), tag_name, namespace) } // http://dom.spec.whatwg.org/#dom-document-getelementsbyclassname - pub fn GetElementsByClassName(&self, abstract_self: &JSRef<Document>, classes: DOMString) -> JS<HTMLCollection> { + pub fn GetElementsByClassName(&self, abstract_self: &JSRef<Document>, classes: DOMString) -> Unrooted<HTMLCollection> { let roots = RootCollection::new(); let window = self.window.root(&roots); - HTMLCollection::by_class_name(&window.root_ref(), NodeCast::from_ref(abstract_self), classes) + HTMLCollection::by_class_name(&*window, NodeCast::from_ref(abstract_self), classes) } // http://dom.spec.whatwg.org/#dom-nonelementparentnode-getelementbyid - pub fn GetElementById(&self, id: DOMString) -> Option<JS<Element>> { + pub fn GetElementById(&self, id: DOMString) -> Option<Unrooted<Element>> { match self.idmap.find_equiv(&id) { None => None, - Some(ref elements) => Some(elements.get(0).clone()), + Some(ref elements) => Some(Unrooted::new(elements.get(0).clone())), } } // http://dom.spec.whatwg.org/#dom-document-createelement pub fn CreateElement(&self, abstract_self: &JSRef<Document>, local_name: DOMString) - -> Fallible<JS<Element>> { + -> Fallible<Unrooted<Element>> { if xml_name_type(local_name) == InvalidXMLName { debug!("Not a valid element name"); return Err(InvalidCharacter); @@ -264,7 +266,7 @@ impl Document { // http://dom.spec.whatwg.org/#dom-document-createelementns pub fn CreateElementNS(&self, abstract_self: &JSRef<Document>, namespace: Option<DOMString>, - qualified_name: DOMString) -> Fallible<JS<Element>> { + qualified_name: DOMString) -> Fallible<Unrooted<Element>> { let ns = Namespace::from_str(null_str_as_empty_ref(&namespace)); match xml_name_type(qualified_name) { InvalidXMLName => { @@ -308,24 +310,24 @@ impl Document { } // http://dom.spec.whatwg.org/#dom-document-createdocumentfragment - pub fn CreateDocumentFragment(&self, abstract_self: &JSRef<Document>) -> JS<DocumentFragment> { + pub fn CreateDocumentFragment(&self, abstract_self: &JSRef<Document>) -> Unrooted<DocumentFragment> { DocumentFragment::new(abstract_self) } // http://dom.spec.whatwg.org/#dom-document-createtextnode pub fn CreateTextNode(&self, abstract_self: &JSRef<Document>, data: DOMString) - -> JS<Text> { + -> Unrooted<Text> { Text::new(data, abstract_self) } // http://dom.spec.whatwg.org/#dom-document-createcomment - pub fn CreateComment(&self, abstract_self: &JSRef<Document>, data: DOMString) -> JS<Comment> { + pub fn CreateComment(&self, abstract_self: &JSRef<Document>, data: DOMString) -> Unrooted<Comment> { Comment::new(data, abstract_self) } // http://dom.spec.whatwg.org/#dom-document-createprocessinginstruction pub fn CreateProcessingInstruction(&self, abstract_self: &JSRef<Document>, target: DOMString, - data: DOMString) -> Fallible<JS<ProcessingInstruction>> { + data: DOMString) -> Fallible<Unrooted<ProcessingInstruction>> { // Step 1. if xml_name_type(target) == InvalidXMLName { return Err(InvalidCharacter); @@ -341,9 +343,9 @@ impl Document { } // http://dom.spec.whatwg.org/#dom-document-importnode - pub fn ImportNode(&self, abstract_self: &JSRef<Document>, node: &JSRef<Node>, deep: bool) -> Fallible<JS<Node>> { + pub fn ImportNode(&self, abstract_self: &JSRef<Document>, node: &JSRef<Node>, deep: bool) -> Fallible<Unrooted<Node>> { // Step 1. - if node.unrooted().is_document() { + if node.is_document() { return Err(NotSupported); } @@ -357,30 +359,29 @@ impl Document { } // http://dom.spec.whatwg.org/#dom-document-adoptnode - pub fn AdoptNode(&self, abstract_self: &JSRef<Document>, node: &JSRef<Node>) -> Fallible<JS<Node>> { + pub fn AdoptNode(&self, abstract_self: &JSRef<Document>, node: &mut JSRef<Node>) -> Fallible<Unrooted<Node>> { // Step 1. - if node.unrooted().is_document() { + if node.is_document() { return Err(NotSupported); } // Step 2. - let mut adoptee = node.clone(); - Node::adopt(&mut adoptee, abstract_self); + Node::adopt(node, abstract_self); // Step 3. - Ok(adoptee.unrooted()) + Ok(Unrooted::new_rooted(node)) } // http://dom.spec.whatwg.org/#dom-document-createevent - pub fn CreateEvent(&self, interface: DOMString) -> Fallible<JS<Event>> { + pub fn CreateEvent(&self, interface: DOMString) -> Fallible<Unrooted<Event>> { let roots = RootCollection::new(); let window = self.window.root(&roots); match interface.to_ascii_lower().as_slice() { // FIXME: Implement CustomEvent (http://dom.spec.whatwg.org/#customevent) - "uievents" | "uievent" => Ok(EventCast::from(&UIEvent::new(&window.root_ref()))), - "mouseevents" | "mouseevent" => Ok(EventCast::from(&MouseEvent::new(&window.root_ref()))), - "htmlevents" | "events" | "event" => Ok(Event::new(&window.root_ref())), + "uievents" | "uievent" => Ok(EventCast::from_unrooted(UIEvent::new(&*window))), + "mouseevents" | "mouseevent" => Ok(EventCast::from_unrooted(MouseEvent::new(&*window))), + "htmlevents" | "events" | "event" => Ok(Event::new(&*window)), _ => Err(NotSupported) } } @@ -388,14 +389,15 @@ impl Document { // http://www.whatwg.org/specs/web-apps/current-work/#document.title pub fn Title(&self, _: &JSRef<Document>) -> DOMString { let mut title = ~""; - self.GetDocumentElement().map(|root| { - let root: JS<Node> = NodeCast::from(&root); - root.traverse_preorder() + let roots = RootCollection::new(); + self.GetDocumentElement().root(&roots).map(|root| { + let root: &JSRef<Node> = NodeCast::from_ref(&*root); + root.traverse_preorder(&roots) .find(|node| node.type_id() == ElementNodeTypeId(HTMLTitleElementTypeId)) .map(|title_elem| { - for child in title_elem.children() { + for child in title_elem.deref().children() { if child.is_text() { - let text: JS<Text> = TextCast::to(&child).unwrap(); + let text: &JSRef<Text> = TextCast::to_ref(&child).unwrap(); title.push_str(text.get().characterdata.data.as_slice()); } } @@ -410,9 +412,9 @@ impl Document { pub fn SetTitle(&self, abstract_self: &JSRef<Document>, title: DOMString) -> ErrorResult { let roots = RootCollection::new(); - self.GetDocumentElement().map(|root| { - let root: JS<Node> = NodeCast::from(&root); - let mut head_node = root.traverse_preorder().find(|child| { + self.GetDocumentElement().root(&roots).map(|root| { + let root: &JSRef<Node> = NodeCast::from_ref(&*root); + let mut head_node = root.traverse_preorder(&roots).find(|child| { child.get().type_id == ElementNodeTypeId(HTMLHeadElementTypeId) }); head_node.as_mut().map(|head| { @@ -422,25 +424,21 @@ impl Document { match title_node { Some(ref mut title_node) => { - for title_child in title_node.children() { - let title_child = title_child.root(&roots); - assert!(title_node.RemoveChild(&mut title_child.root_ref()).is_ok()); + for mut title_child in title_node.children() { + assert!(RemoveChild(&mut *title_node, &mut title_child).is_ok()); } - let new_text = self.CreateTextNode(abstract_self, title.clone()); - let new_text = new_text.root(&roots); + let mut new_text = self.CreateTextNode(abstract_self, title.clone()).root(&roots); - assert!(title_node.AppendChild(NodeCast::from_mut_ref(&mut new_text.root_ref())).is_ok()); + assert!(AppendChild(&mut *title_node, NodeCast::from_mut_ref(&mut *new_text)).is_ok()); }, None => { - let mut new_title: JS<Node> = - NodeCast::from(&HTMLTitleElement::new(~"title", abstract_self)); - let new_title_root = new_title.root(&roots); + let mut new_title = HTMLTitleElement::new(~"title", abstract_self).root(&roots); + let new_title: &mut JSRef<Node> = NodeCast::from_mut_ref(&mut *new_title); - let new_text = self.CreateTextNode(abstract_self, title.clone()); - let new_text = new_text.root(&roots); + let mut new_text = self.CreateTextNode(abstract_self, title.clone()).root(&roots); - assert!(new_title.AppendChild(NodeCast::from_mut_ref(&mut new_text.root_ref())).is_ok()); - assert!(head.AppendChild(&mut new_title_root.root_ref()).is_ok()); + assert!(AppendChild(&mut *new_title, NodeCast::from_mut_ref(&mut *new_text)).is_ok()); + assert!(AppendChild(&mut *head, &mut *new_title).is_ok()); }, } }); @@ -448,33 +446,44 @@ impl Document { Ok(()) } - fn get_html_element(&self) -> Option<JS<HTMLHtmlElement>> { - self.GetDocumentElement().filtered(|root| { - root.get().node.type_id == ElementNodeTypeId(HTMLHtmlElementTypeId) - }).map(|elem| HTMLHtmlElementCast::to(&elem).unwrap()) + fn get_html_element(&self) -> Option<Unrooted<HTMLHtmlElement>> { + let roots = RootCollection::new(); + self.GetDocumentElement().root(&roots).filtered(|root| { + root.node.type_id == ElementNodeTypeId(HTMLHtmlElementTypeId) + }).map(|elem| { + Unrooted::new_rooted(HTMLHtmlElementCast::to_ref(&*elem).unwrap()) + }) } // http://www.whatwg.org/specs/web-apps/current-work/#dom-document-head - pub fn GetHead(&self) -> Option<JS<HTMLHeadElement>> { + pub fn GetHead(&self) -> Option<Unrooted<HTMLHeadElement>> { + let roots = RootCollection::new(); self.get_html_element().and_then(|root| { - let node: JS<Node> = NodeCast::from(&root); + let root = root.root(&roots); + let node: &JSRef<Node> = NodeCast::from_ref(&*root); node.children().find(|child| { child.type_id() == ElementNodeTypeId(HTMLHeadElementTypeId) - }).map(|node| HTMLHeadElementCast::to(&node).unwrap()) + }).map(|node| { + Unrooted::new_rooted(HTMLHeadElementCast::to_ref(&node).unwrap()) + }) }) } // http://www.whatwg.org/specs/web-apps/current-work/#dom-document-body - pub fn GetBody(&self, _: &JSRef<Document>) -> Option<JS<HTMLElement>> { + pub fn GetBody(&self, _: &JSRef<Document>) -> Option<Unrooted<HTMLElement>> { + let roots = RootCollection::new(); self.get_html_element().and_then(|root| { - let node: JS<Node> = NodeCast::from(&root); + let root = root.root(&roots); + let node: &JSRef<Node> = NodeCast::from_ref(&*root); node.children().find(|child| { match child.type_id() { ElementNodeTypeId(HTMLBodyElementTypeId) | ElementNodeTypeId(HTMLFrameSetElementTypeId) => true, _ => false } - }).map(|node| HTMLElementCast::to(&node).unwrap()) + }).map(|node| { + Unrooted::new_rooted(HTMLElementCast::to_ref(&node).unwrap()) + }) }) } @@ -494,28 +503,28 @@ impl Document { } // Step 2. - let old_body: Option<JS<HTMLElement>> = self.GetBody(abstract_self); - if old_body == new_body.as_ref().map(|new_body| new_body.unrooted()) { + let mut old_body = self.GetBody(abstract_self).root(&roots); + //FIXME: covariant lifetime workaround. do not judge. + if old_body.as_ref().map(|body| body.deref()) == new_body.as_ref().map(|a| &*a) { return Ok(()); } // Step 3. - match self.get_html_element() { + match self.get_html_element().root(&roots) { // Step 4. None => return Err(HierarchyRequest), - Some(root) => { + Some(ref mut root) => { let mut new_body_unwrapped = new_body.unwrap(); let new_body: &mut JSRef<Node> = NodeCast::from_mut_ref(&mut new_body_unwrapped); - let mut root: JS<Node> = NodeCast::from(&root); + let root: &mut JSRef<Node> = NodeCast::from_mut_ref(&mut **root); match old_body { - Some(child) => { - let child: JS<Node> = NodeCast::from(&child); - let child = child.root(&roots); + Some(ref mut child) => { + let child: &mut JSRef<Node> = NodeCast::from_mut_ref(&mut **child); - assert!(root.ReplaceChild(new_body, &mut child.root_ref()).is_ok()) + assert!(ReplaceChild(&mut *root, new_body, child).is_ok()) } - None => assert!(root.AppendChild(new_body).is_ok()) + None => assert!(AppendChild(&mut *root, new_body).is_ok()) }; } } @@ -523,20 +532,22 @@ impl Document { } // http://www.whatwg.org/specs/web-apps/current-work/#dom-document-getelementsbyname - pub fn GetElementsByName(&self, name: DOMString) -> JS<NodeList> { + pub fn GetElementsByName(&self, name: DOMString) -> Unrooted<NodeList> { + let roots = RootCollection::new(); + self.createNodeList(|node| { if !node.get().is_element() { return false; } - let element: JS<Element> = ElementCast::to(&node.unrooted()).unwrap(); - element.get_attribute(Null, "name").map_or(false, |attr| { - attr.get().value_ref() == name + let element: &JSRef<Element> = ElementCast::to_ref(node).unwrap(); + element.get_attribute(Null, "name").root(&roots).map_or(false, |mut attr| { + attr.value_ref() == name }) }) } - pub fn Images(&self, abstract_self: &JSRef<Document>) -> JS<HTMLCollection> { + pub fn Images(&self, abstract_self: &JSRef<Document>) -> Unrooted<HTMLCollection> { let roots = RootCollection::new(); let window = self.window.root(&roots); @@ -548,10 +559,10 @@ impl Document { } } let filter = ~ImagesFilter; - HTMLCollection::create(&window.root_ref(), NodeCast::from_ref(abstract_self), filter) + HTMLCollection::create(&*window, NodeCast::from_ref(abstract_self), filter) } - pub fn Embeds(&self, abstract_self: &JSRef<Document>) -> JS<HTMLCollection> { + pub fn Embeds(&self, abstract_self: &JSRef<Document>) -> Unrooted<HTMLCollection> { let roots = RootCollection::new(); let window = self.window.root(&roots); @@ -563,15 +574,15 @@ impl Document { } } let filter = ~EmbedsFilter; - HTMLCollection::create(&window.root_ref(), NodeCast::from_ref(abstract_self), filter) + HTMLCollection::create(&*window, NodeCast::from_ref(abstract_self), filter) } - pub fn Plugins(&self, abstract_self: &JSRef<Document>) -> JS<HTMLCollection> { + pub fn Plugins(&self, abstract_self: &JSRef<Document>) -> Unrooted<HTMLCollection> { // FIXME: https://github.com/mozilla/servo/issues/1847 self.Embeds(abstract_self) } - pub fn Links(&self, abstract_self: &JSRef<Document>) -> JS<HTMLCollection> { + pub fn Links(&self, abstract_self: &JSRef<Document>) -> Unrooted<HTMLCollection> { let roots = RootCollection::new(); let window = self.window.root(&roots); @@ -580,14 +591,14 @@ impl Document { impl CollectionFilter for LinksFilter { fn filter(&self, elem: &JSRef<Element>, _root: &JSRef<Node>) -> bool { (elem.get().local_name == ~"a" || elem.get().local_name == ~"area") && - elem.unrooted().get_attribute(Null, "href").is_some() + elem.get_attribute(Null, "href").is_some() } } let filter = ~LinksFilter; - HTMLCollection::create(&window.root_ref(), NodeCast::from_ref(abstract_self), filter) + HTMLCollection::create(&*window, NodeCast::from_ref(abstract_self), filter) } - pub fn Forms(&self, abstract_self: &JSRef<Document>) -> JS<HTMLCollection> { + pub fn Forms(&self, abstract_self: &JSRef<Document>) -> Unrooted<HTMLCollection> { let roots = RootCollection::new(); let window = self.window.root(&roots); @@ -599,10 +610,10 @@ impl Document { } } let filter = ~FormsFilter; - HTMLCollection::create(&window.root_ref(), NodeCast::from_ref(abstract_self), filter) + HTMLCollection::create(&*window, NodeCast::from_ref(abstract_self), filter) } - pub fn Scripts(&self, abstract_self: &JSRef<Document>) -> JS<HTMLCollection> { + pub fn Scripts(&self, abstract_self: &JSRef<Document>) -> Unrooted<HTMLCollection> { let roots = RootCollection::new(); let window = self.window.root(&roots); @@ -614,10 +625,10 @@ impl Document { } } let filter = ~ScriptsFilter; - HTMLCollection::create(&window.root_ref(), NodeCast::from_ref(abstract_self), filter) + HTMLCollection::create(&*window, NodeCast::from_ref(abstract_self), filter) } - pub fn Anchors(&self, abstract_self: &JSRef<Document>) -> JS<HTMLCollection> { + pub fn Anchors(&self, abstract_self: &JSRef<Document>) -> Unrooted<HTMLCollection> { let roots = RootCollection::new(); let window = self.window.root(&roots); @@ -625,14 +636,14 @@ impl Document { struct AnchorsFilter; impl CollectionFilter for AnchorsFilter { fn filter(&self, elem: &JSRef<Element>, _root: &JSRef<Node>) -> bool { - elem.get().local_name == ~"a" && elem.unrooted().get_attribute(Null, "name").is_some() + elem.get().local_name == ~"a" && elem.get_attribute(Null, "name").is_some() } } let filter = ~AnchorsFilter; - HTMLCollection::create(&window.root_ref(), NodeCast::from_ref(abstract_self), filter) + HTMLCollection::create(&*window, NodeCast::from_ref(abstract_self), filter) } - pub fn Applets(&self, abstract_self: &JSRef<Document>) -> JS<HTMLCollection> { + pub fn Applets(&self, abstract_self: &JSRef<Document>) -> Unrooted<HTMLCollection> { let roots = RootCollection::new(); let window = self.window.root(&roots); @@ -644,40 +655,39 @@ impl Document { } } let filter = ~AppletsFilter; - HTMLCollection::create(&window.root_ref(), NodeCast::from_ref(abstract_self), filter) + HTMLCollection::create(&*window, NodeCast::from_ref(abstract_self), filter) } - pub fn Location(&mut self, _abstract_self: &JSRef<Document>) -> JS<Location> { + pub fn Location(&mut self, _abstract_self: &JSRef<Document>) -> Unrooted<Location> { let roots = RootCollection::new(); let window = self.window.root(&roots); - self.window.get_mut().Location(&window.root_ref()) + self.window.get_mut().Location(&*window) } - pub fn Children(&self, abstract_self: &JSRef<Document>) -> JS<HTMLCollection> { + pub fn Children(&self, abstract_self: &JSRef<Document>) -> Unrooted<HTMLCollection> { let roots = RootCollection::new(); let window = self.window.root(&roots); - HTMLCollection::children(&window.root_ref(), NodeCast::from_ref(abstract_self)) + HTMLCollection::children(&*window, NodeCast::from_ref(abstract_self)) } - pub fn createNodeList(&self, callback: |node: &JSRef<Node>| -> bool) -> JS<NodeList> { + pub fn createNodeList(&self, callback: |node: &JSRef<Node>| -> bool) -> Unrooted<NodeList> { let roots = RootCollection::new(); let window = self.window.root(&roots); let mut nodes = vec!(); - match self.GetDocumentElement() { + match self.GetDocumentElement().root(&roots) { None => {}, Some(root) => { - let root: JS<Node> = NodeCast::from(&root); - for child in root.traverse_preorder() { - let child = child.root(&roots); - if callback(&child.root_ref()) { - nodes.push(child.root_ref().unrooted()); + let root: &JSRef<Node> = NodeCast::from_ref(&*root); + for child in root.traverse_preorder(&roots) { + if callback(&child) { + nodes.push(child); } } } } - NodeList::new_simple_list(&window.root_ref(), nodes) + NodeList::new_simple_list(&*window, nodes) } pub fn content_changed(&self) { @@ -697,12 +707,14 @@ impl Document { pub fn unregister_named_element(&mut self, abstract_self: &JSRef<Element>, id: DOMString) { + let roots = RootCollection::new(); let mut is_empty = false; match self.idmap.find_mut(&id) { None => {}, Some(elements) => { let position = elements.iter() - .position(|element| element == &abstract_self.unrooted()) + .map(|elem| elem.root(&roots)) + .position(|element| &*element == abstract_self) .expect("This element should be in registered."); elements.remove(position); is_empty = elements.is_empty(); @@ -717,26 +729,28 @@ impl Document { pub fn register_named_element(&mut self, element: &JSRef<Element>, id: DOMString) { + let roots = RootCollection::new(); assert!({ - let node: JS<Node> = NodeCast::from(&element.unrooted()); + let node: &JSRef<Node> = NodeCast::from_ref(element); node.is_in_doc() }); // FIXME https://github.com/mozilla/rust/issues/13195 // Use mangle() when it exists again. - let root = self.GetDocumentElement().expect("The element is in the document, so there must be a document element."); + let root = self.GetDocumentElement().expect("The element is in the document, so there must be a document element.").root(&roots); match self.idmap.find_mut(&id) { Some(elements) => { - let new_node = NodeCast::from_ref(element); + let new_node: &JSRef<Node> = NodeCast::from_ref(element); let mut head : uint = 0u; - let root: JS<Node> = NodeCast::from(&root); - for node in root.traverse_preorder() { - match ElementCast::to(&node) { + let root: &JSRef<Node> = NodeCast::from_ref(&*root); + for node in root.traverse_preorder(&roots) { + let elem: Option<&JSRef<Element>> = ElementCast::to_ref(&node); + match elem { Some(elem) => { - if elements.get(head) == &elem { + if elements.get(head) == &elem.unrooted() { head = head + 1; } - if new_node.unrooted() == node || head == elements.len() { + if new_node == &node || head == elements.len() { break; } } diff --git a/src/components/script/dom/documentfragment.rs b/src/components/script/dom/documentfragment.rs index e10e9e1204c..629b68ffdec 100644 --- a/src/components/script/dom/documentfragment.rs +++ b/src/components/script/dom/documentfragment.rs @@ -4,7 +4,7 @@ use dom::bindings::codegen::InheritTypes::{DocumentFragmentDerived, NodeCast}; use dom::bindings::codegen::BindingDeclarations::DocumentFragmentBinding; -use dom::bindings::js::{JS, JSRef, RootCollection}; +use dom::bindings::js::{JS, JSRef, RootCollection, Unrooted}; use dom::bindings::error::Fallible; use dom::document::Document; use dom::eventtarget::{EventTarget, NodeTargetTypeId}; @@ -34,14 +34,14 @@ impl DocumentFragment { } } - pub fn new(document: &JSRef<Document>) -> JS<DocumentFragment> { + pub fn new(document: &JSRef<Document>) -> Unrooted<DocumentFragment> { let node = DocumentFragment::new_inherited(document.unrooted()); Node::reflect_node(~node, document, DocumentFragmentBinding::Wrap) } } impl DocumentFragment { - pub fn Constructor(owner: &JSRef<Window>) -> Fallible<JS<DocumentFragment>> { + pub fn Constructor(owner: &JSRef<Window>) -> Fallible<Unrooted<DocumentFragment>> { let roots = RootCollection::new(); let document = owner.get().Document(); let document = document.root(&roots); @@ -51,9 +51,9 @@ impl DocumentFragment { } impl DocumentFragment { - pub fn Children(&self, abstract_self: &JSRef<DocumentFragment>) -> JS<HTMLCollection> { + pub fn Children(&self, abstract_self: &JSRef<DocumentFragment>) -> Unrooted<HTMLCollection> { let roots = RootCollection::new(); - let window = window_from_node(&abstract_self.unrooted()).root(&roots); + let window = window_from_node(abstract_self).root(&roots); HTMLCollection::children(&window.root_ref(), NodeCast::from_ref(abstract_self)) } } diff --git a/src/components/script/dom/documenttype.rs b/src/components/script/dom/documenttype.rs index dacce041f5c..21b1a784456 100644 --- a/src/components/script/dom/documenttype.rs +++ b/src/components/script/dom/documenttype.rs @@ -4,7 +4,7 @@ use dom::bindings::codegen::InheritTypes::DocumentTypeDerived; use dom::bindings::codegen::BindingDeclarations::DocumentTypeBinding; -use dom::bindings::js::{JS, JSRef}; +use dom::bindings::js::{JS, JSRef, Unrooted}; use dom::document::Document; use dom::eventtarget::{EventTarget, NodeTargetTypeId}; use dom::node::{Node, DoctypeNodeTypeId}; @@ -46,7 +46,7 @@ impl DocumentType { public_id: Option<DOMString>, system_id: Option<DOMString>, document: &JSRef<Document>) - -> JS<DocumentType> { + -> Unrooted<DocumentType> { let documenttype = DocumentType::new_inherited(name, public_id, system_id, diff --git a/src/components/script/dom/domexception.rs b/src/components/script/dom/domexception.rs index db562d08c71..08a8c364deb 100644 --- a/src/components/script/dom/domexception.rs +++ b/src/components/script/dom/domexception.rs @@ -4,7 +4,7 @@ use dom::bindings::codegen::BindingDeclarations::DOMExceptionBinding; use dom::bindings::codegen::BindingDeclarations::DOMExceptionBinding::DOMExceptionConstants; -use dom::bindings::js::{JS, JSRef}; +use dom::bindings::js::{JSRef, Unrooted}; use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object}; use dom::window::Window; use servo_util::str::DOMString; @@ -49,7 +49,7 @@ impl DOMException { } } - pub fn new(window: &JSRef<Window>, code: DOMErrorName) -> JS<DOMException> { + pub fn new(window: &JSRef<Window>, code: DOMErrorName) -> Unrooted<DOMException> { reflect_dom_object(~DOMException::new_inherited(code), window, DOMExceptionBinding::Wrap) } } diff --git a/src/components/script/dom/domimplementation.rs b/src/components/script/dom/domimplementation.rs index e002cf9d28c..7cc9e5ef0d0 100644 --- a/src/components/script/dom/domimplementation.rs +++ b/src/components/script/dom/domimplementation.rs @@ -4,7 +4,7 @@ use dom::bindings::codegen::BindingDeclarations::DOMImplementationBinding; use dom::bindings::codegen::InheritTypes::NodeCast; -use dom::bindings::js::{JS, JSRef, RootCollection}; +use dom::bindings::js::{JS, JSRef, RootCollection, Unrooted, OptionalRootable}; use dom::bindings::utils::{Reflector, Reflectable, reflect_dom_object}; use dom::bindings::error::{Fallible, InvalidCharacter, NamespaceError}; use dom::bindings::utils::{QName, Name, InvalidXMLName, xml_name_type}; @@ -14,7 +14,7 @@ use dom::htmlbodyelement::HTMLBodyElement; use dom::htmlheadelement::HTMLHeadElement; use dom::htmlhtmlelement::HTMLHtmlElement; use dom::htmltitleelement::HTMLTitleElement; -use dom::node::{Node, INode}; +use dom::node::{Node, AppendChild}; use dom::text::Text; use dom::window::Window; use servo_util::str::DOMString; @@ -33,7 +33,7 @@ impl DOMImplementation { } } - pub fn new(owner: &JSRef<Window>) -> JS<DOMImplementation> { + pub fn new(owner: &JSRef<Window>) -> Unrooted<DOMImplementation> { reflect_dom_object(~DOMImplementation::new_inherited(owner.unrooted()), owner, DOMImplementationBinding::Wrap) } @@ -52,7 +52,7 @@ impl Reflectable for DOMImplementation { // http://dom.spec.whatwg.org/#domimplementation impl DOMImplementation { // http://dom.spec.whatwg.org/#dom-domimplementation-createdocumenttype - pub fn CreateDocumentType(&self, qname: DOMString, pubid: DOMString, sysid: DOMString) -> Fallible<JS<DocumentType>> { + pub fn CreateDocumentType(&self, qname: DOMString, pubid: DOMString, sysid: DOMString) -> Fallible<Unrooted<DocumentType>> { let roots = RootCollection::new(); match xml_name_type(qname) { // Step 1. @@ -70,37 +70,39 @@ impl DOMImplementation { // http://dom.spec.whatwg.org/#dom-domimplementation-createdocument pub fn CreateDocument(&self, namespace: Option<DOMString>, qname: DOMString, - mut maybe_doctype: Option<JSRef<DocumentType>>) -> Fallible<JS<Document>> { + mut maybe_doctype: Option<JSRef<DocumentType>>) -> Fallible<Unrooted<Document>> { let roots = RootCollection::new(); let win = self.owner.root(&roots); // Step 1. - let doc = Document::new(&win.root_ref(), None, NonHTMLDocument, None); - let doc_root = doc.root(&roots); - let mut doc_node: JS<Node> = NodeCast::from(&doc); - + let mut doc = Document::new(&win.root_ref(), None, NonHTMLDocument, None).root(&roots); // Step 2-3. let mut maybe_elem = if qname.is_empty() { None } else { - match doc.get().CreateElementNS(&doc_root.root_ref(), namespace, qname) { + match doc.get().CreateElementNS(&*doc, namespace, qname) { Err(error) => return Err(error), Ok(elem) => Some(elem) } }; - // Step 4. - match maybe_doctype { - None => (), - Some(ref mut doctype) => assert!(doc_node.AppendChild(NodeCast::from_mut_ref(doctype)).is_ok()) - } + { + let doc_node: &mut JSRef<Node> = NodeCast::from_mut_ref(&mut *doc); + + // Step 4. + match maybe_doctype { + None => (), + Some(ref mut doctype) => { + assert!(AppendChild(doc_node, NodeCast::from_mut_ref(doctype)).is_ok()) + } + } - // Step 5. - match maybe_elem { - None => (), - Some(ref elem) => { - let elem = elem.root(&roots); - assert!(doc_node.AppendChild(NodeCast::from_mut_ref(&mut elem.root_ref())).is_ok()) + // Step 5. + match maybe_elem.root(&roots) { + None => (), + Some(mut elem) => { + assert!(AppendChild(doc_node, NodeCast::from_mut_ref(&mut *elem)).is_ok()) + } } } @@ -108,65 +110,59 @@ impl DOMImplementation { // FIXME: https://github.com/mozilla/servo/issues/1522 // Step 7. - Ok(doc) + Ok(Unrooted::new_rooted(&*doc)) } // http://dom.spec.whatwg.org/#dom-domimplementation-createhtmldocument - pub fn CreateHTMLDocument(&self, title: Option<DOMString>) -> JS<Document> { + pub fn CreateHTMLDocument(&self, title: Option<DOMString>) -> Unrooted<Document> { let roots = RootCollection::new(); let owner = self.owner.root(&roots); // Step 1-2. - let doc = Document::new(&owner.root_ref(), None, HTMLDocument, None); - let doc_root = doc.root(&roots); - let mut doc_node: JS<Node> = NodeCast::from(&doc); + let mut doc = Document::new(&owner.root_ref(), None, HTMLDocument, None).root(&roots); + let mut doc_alias = doc.clone(); + let doc_node: &mut JSRef<Node> = NodeCast::from_mut_ref(&mut doc_alias); { // Step 3. - let doc_type = DocumentType::new(~"html", None, None, &doc_root.root_ref()); - let doc_type = doc_type.root(&roots); - assert!(doc_node.AppendChild(NodeCast::from_mut_ref(&mut doc_type.root_ref())).is_ok()); + let mut doc_type = DocumentType::new(~"html", None, None, &*doc).root(&roots); + assert!(AppendChild(&mut *doc_node, NodeCast::from_mut_ref(&mut *doc_type)).is_ok()); } { // Step 4. - let mut doc_html = NodeCast::from(&HTMLHtmlElement::new(~"html", &doc_root.root_ref())); - let doc_html_root = {doc_html.root(&roots)}; - assert!(doc_node.AppendChild(&mut doc_html_root.root_ref()).is_ok()); + let mut doc_html = NodeCast::from_unrooted(HTMLHtmlElement::new(~"html", &*doc)).root(&roots); + assert!(AppendChild(&mut *doc_node, &mut *doc_html).is_ok()); { // Step 5. - let mut doc_head = NodeCast::from(&HTMLHeadElement::new(~"head", &doc_root.root_ref())); - let doc_head_root = doc_head.root(&roots); - assert!(doc_html.AppendChild(&mut doc_head_root.root_ref()).is_ok()); + let mut doc_head = NodeCast::from_unrooted(HTMLHeadElement::new(~"head", &*doc)).root(&roots); + assert!(AppendChild(&mut *doc_html, &mut *doc_head).is_ok()); // Step 6. match title { None => (), Some(title_str) => { // Step 6.1. - let mut doc_title = NodeCast::from(&HTMLTitleElement::new(~"title", &doc_root.root_ref())); - let doc_title_root = doc_title.root(&roots); - assert!(doc_head.AppendChild(&mut doc_title_root.root_ref()).is_ok()); + let mut doc_title = NodeCast::from_unrooted(HTMLTitleElement::new(~"title", &*doc)).root(&roots); + assert!(AppendChild(&mut *doc_head, &mut *doc_title).is_ok()); // Step 6.2. - let title_text = Text::new(title_str, &doc_root.root_ref()); - let title_text = title_text.root(&roots); - assert!(doc_title.AppendChild(NodeCast::from_mut_ref(&mut title_text.root_ref())).is_ok()); + let mut title_text = Text::new(title_str, &*doc).root(&roots); + assert!(AppendChild(&mut *doc_title, NodeCast::from_mut_ref(&mut *title_text)).is_ok()); } } } // Step 7. - let doc_body = HTMLBodyElement::new(~"body", &doc_root.root_ref()); - let doc_body = doc_body.root(&roots); - assert!(doc_html.AppendChild(NodeCast::from_mut_ref(&mut doc_body.root_ref())).is_ok()); + let mut doc_body = HTMLBodyElement::new(~"body", &*doc).root(&roots); + assert!(AppendChild(&mut *doc_html, NodeCast::from_mut_ref(&mut *doc_body)).is_ok()); } // Step 8. // FIXME: https://github.com/mozilla/servo/issues/1522 // Step 9. - doc + Unrooted::new_rooted(&*doc) } } diff --git a/src/components/script/dom/domparser.rs b/src/components/script/dom/domparser.rs index d11c7270057..6d77273e11e 100644 --- a/src/components/script/dom/domparser.rs +++ b/src/components/script/dom/domparser.rs @@ -4,7 +4,7 @@ use dom::bindings::codegen::BindingDeclarations::DOMParserBinding; use dom::bindings::codegen::BindingDeclarations::DOMParserBinding::SupportedTypeValues::{Text_html, Text_xml}; -use dom::bindings::js::{JS, JSRef, RootCollection}; +use dom::bindings::js::{JS, JSRef, RootCollection, Unrooted}; use dom::bindings::utils::{Reflector, Reflectable, reflect_dom_object}; use dom::bindings::error::{Fallible, FailureUnknown}; use dom::document::{Document, HTMLDocument, NonHTMLDocument}; @@ -25,19 +25,19 @@ impl DOMParser { } } - pub fn new(owner: &JSRef<Window>) -> JS<DOMParser> { + pub fn new(owner: &JSRef<Window>) -> Unrooted<DOMParser> { reflect_dom_object(~DOMParser::new_inherited(owner.unrooted()), owner, DOMParserBinding::Wrap) } - pub fn Constructor(owner: &JSRef<Window>) -> Fallible<JS<DOMParser>> { + pub fn Constructor(owner: &JSRef<Window>) -> Fallible<Unrooted<DOMParser>> { Ok(DOMParser::new(owner)) } pub fn ParseFromString(&self, _s: DOMString, ty: DOMParserBinding::SupportedType) - -> Fallible<JS<Document>> { + -> Fallible<Unrooted<Document>> { let roots = RootCollection::new(); let owner = self.owner.root(&roots); match ty { diff --git a/src/components/script/dom/element.rs b/src/components/script/dom/element.rs index 179f2c7571d..e0901de01d8 100644 --- a/src/components/script/dom/element.rs +++ b/src/components/script/dom/element.rs @@ -4,11 +4,12 @@ //! Element nodes. -use dom::attr::{Attr, AttrSettingType, ReplacedAttr, FirstSetAttr}; +use dom::attr::{Attr, ReplacedAttr, FirstSetAttr}; use dom::attrlist::AttrList; use dom::bindings::codegen::BindingDeclarations::ElementBinding; use dom::bindings::codegen::InheritTypes::{ElementDerived, NodeCast}; -use dom::bindings::js::{JS, JSRef, RootCollection}; +use dom::bindings::js::{JS, JSRef, RootCollection, Unrooted, UnrootedPushable}; +use dom::bindings::js::{OptionalAssignable, OptionalRootable, Root}; use dom::bindings::utils::{Reflectable, Reflector}; use dom::bindings::error::{ErrorResult, Fallible, NamespaceError, InvalidCharacter}; use dom::bindings::utils::{QName, Name, InvalidXMLName, xml_name_type}; @@ -152,14 +153,15 @@ impl Element { } } - pub fn new(local_name: DOMString, namespace: Namespace, prefix: Option<DOMString>, document: &JSRef<Document>) -> JS<Element> { + pub fn new(local_name: DOMString, namespace: Namespace, prefix: Option<DOMString>, document: &JSRef<Document>) -> Unrooted<Element> { let element = Element::new_inherited(ElementTypeId, local_name, namespace, prefix, document.unrooted()); Node::reflect_node(~element, document, ElementBinding::Wrap) } pub fn html_element_in_html_document(&self) -> bool { + let roots = RootCollection::new(); self.namespace == namespace::HTML && - self.node.owner_doc().get().is_html_document + self.node.owner_doc().root(&roots).is_html_document } } @@ -168,7 +170,7 @@ impl Element { if self.namespace != namespace::HTML { return false } - let owner_doc: *JS<Document> = self.node.owner_doc(); + let owner_doc: *JS<Document> = self.node.owner_doc_for_layout(); let owner_doc: **Document = owner_doc as **Document; (**owner_doc).is_html_document } @@ -189,15 +191,15 @@ impl Element { } pub trait AttributeHandlers { - fn get_attribute(&self, namespace: Namespace, name: &str) -> Option<JS<Attr>>; + fn get_attribute(&self, namespace: Namespace, name: &str) -> Option<Unrooted<Attr>>; fn set_attr(&mut self, name: DOMString, value: DOMString) -> ErrorResult; fn set_attribute(&mut self, namespace: Namespace, name: DOMString, value: DOMString) -> ErrorResult; fn do_set_attribute(&mut self, local_name: DOMString, value: DOMString, name: DOMString, namespace: Namespace, - prefix: Option<DOMString>, cb: |&JS<Attr>| -> bool); - fn SetAttribute(&mut self, name: DOMString, value: DOMString) -> ErrorResult; - fn SetAttributeNS(&mut self, namespace_url: Option<DOMString>, + prefix: Option<DOMString>, cb: |&JSRef<Attr>| -> bool); + fn SetAttribute_(&mut self, name: DOMString, value: DOMString) -> ErrorResult; + fn SetAttributeNS_(&mut self, namespace_url: Option<DOMString>, name: DOMString, value: DOMString) -> ErrorResult; fn remove_attribute(&mut self, namespace: Namespace, name: DOMString) -> ErrorResult; @@ -212,18 +214,18 @@ pub trait AttributeHandlers { fn set_uint_attribute(&mut self, name: &str, value: u32); } -impl AttributeHandlers for JS<Element> { - fn get_attribute(&self, namespace: Namespace, name: &str) -> Option<JS<Attr>> { +impl<'a> AttributeHandlers for JSRef<'a, Element> { + fn get_attribute(&self, namespace: Namespace, name: &str) -> Option<Unrooted<Attr>> { if self.get().html_element_in_html_document() { self.get().attrs.iter().find(|attr| { let attr = attr.get(); name.to_ascii_lower() == attr.local_name && attr.namespace == namespace - }).map(|x| x.clone()) + }).map(|x| Unrooted::new(x.clone())) } else { self.get().attrs.iter().find(|attr| { let attr = attr.get(); name == attr.local_name && attr.namespace == namespace - }).map(|x| x.clone()) + }).map(|x| Unrooted::new(x.clone())) } } @@ -245,10 +247,11 @@ impl AttributeHandlers for JS<Element> { None => {} } - let node: JS<Node> = NodeCast::from(self); - node.get().wait_until_safe_to_modify_dom(); + let self_alias = self.clone(); + let node: &JSRef<Node> = NodeCast::from_ref(&self_alias); + node.wait_until_safe_to_modify_dom(); - let position: |&JS<Attr>| -> bool = + let position: |&JSRef<Attr>| -> bool = if self.get().html_element_in_html_document() { |attr| attr.get().local_name.eq_ignore_ascii_case(local_name) } else { @@ -260,33 +263,31 @@ impl AttributeHandlers for JS<Element> { fn do_set_attribute(&mut self, local_name: DOMString, value: DOMString, name: DOMString, namespace: Namespace, - prefix: Option<DOMString>, cb: |&JS<Attr>| -> bool) { + prefix: Option<DOMString>, cb: |&JSRef<Attr>| -> bool) { let roots = RootCollection::new(); - let node: JS<Node> = NodeCast::from(self); - let idx = self.get().attrs.iter().position(cb); - let (mut attr, set_type): (JS<Attr>, AttrSettingType) = match idx { - Some(idx) => { - let attr = self.get_mut().attrs.get(idx).clone(); - (attr, ReplacedAttr) - } - + let idx = self.get().attrs.iter() + .map(|attr| attr.root(&roots)) + .position(|attr| cb(&*attr)); + let (idx, set_type) = match idx { + Some(idx) => (idx, ReplacedAttr), None => { - let doc = node.get().owner_doc().get(); - let window = doc.window.root(&roots); - let attr = Attr::new(&window.root_ref(), local_name.clone(), value.clone(), - name, namespace.clone(), prefix, self.clone()); - self.get_mut().attrs.push(attr.clone()); - (attr, FirstSetAttr) + let window = window_from_node(self).root(&roots); + let attr = Attr::new(&*window, local_name.clone(), value.clone(), + name, namespace.clone(), prefix, self); + self.get_mut().attrs.push_unrooted(attr); + (self.get().attrs.len() - 1, FirstSetAttr) } }; - attr.get_mut().set_value(set_type, value); + self.get_mut().attrs.get_mut(idx).get_mut().set_value(set_type, value); } // http://dom.spec.whatwg.org/#dom-element-setattribute - fn SetAttribute(&mut self, name: DOMString, value: DOMString) -> ErrorResult { - let node: JS<Node> = NodeCast::from(self); - node.get().wait_until_safe_to_modify_dom(); + fn SetAttribute_(&mut self, name: DOMString, value: DOMString) -> ErrorResult { + { + let node: &JSRef<Node> = NodeCast::from_ref(self); + node.get().wait_until_safe_to_modify_dom(); + } // Step 1. match xml_name_type(name) { @@ -308,10 +309,12 @@ impl AttributeHandlers for JS<Element> { Ok(()) } - fn SetAttributeNS(&mut self, namespace_url: Option<DOMString>, - name: DOMString, value: DOMString) -> ErrorResult { - let node: JS<Node> = NodeCast::from(self); - node.get().wait_until_safe_to_modify_dom(); + fn SetAttributeNS_(&mut self, namespace_url: Option<DOMString>, + name: DOMString, value: DOMString) -> ErrorResult { + { + let node: &JSRef<Node> = NodeCast::from_ref(self); + node.get().wait_until_safe_to_modify_dom(); + } // Step 1. let namespace = Namespace::from_str(null_str_as_empty_ref(&namespace_url)); @@ -368,8 +371,9 @@ impl AttributeHandlers for JS<Element> { fn remove_attribute(&mut self, namespace: Namespace, name: DOMString) -> ErrorResult { let (_, local_name) = get_attribute_parts(name.clone()); - let node: JS<Node> = NodeCast::from(self); - node.get().wait_until_safe_to_modify_dom(); + let self_alias = self.clone(); + let node: &JSRef<Node> = NodeCast::from_ref(&self_alias); + node.wait_until_safe_to_modify_dom(); let idx = self.get().attrs.iter().position(|attr| { attr.get().local_name == local_name @@ -380,7 +384,7 @@ impl AttributeHandlers for JS<Element> { Some(idx) => { if namespace == namespace::Null { let removed_raw_value = self.get().attrs.get(idx).get().Value(); - vtable_for(&node).before_remove_attr(local_name.clone(), removed_raw_value); + vtable_for(node).before_remove_attr(local_name.clone(), removed_raw_value); } self.get_mut().attrs.remove(idx); @@ -391,14 +395,15 @@ impl AttributeHandlers for JS<Element> { } fn notify_attribute_changed(&self, local_name: DOMString) { - let node: JS<Node> = NodeCast::from(self); + let roots = RootCollection::new(); + let node: &JSRef<Node> = NodeCast::from_ref(self); if node.is_in_doc() { let damage = match local_name.as_slice() { "style" | "id" | "class" => MatchSelectorsDocumentDamage, _ => ContentChangedDocumentDamage }; - let document = node.get().owner_doc(); - document.get().damage_and_reflow(damage); + let document = node.owner_doc().root(&roots); + document.deref().damage_and_reflow(damage); } } @@ -417,8 +422,12 @@ impl AttributeHandlers for JS<Element> { } fn get_string_attribute(&self, name: &str) -> DOMString { + let roots = RootCollection::new(); match self.get_attribute(Null, name) { - Some(x) => x.get().Value(), + Some(x) => { + let x = x.root(&roots); + x.deref().Value() + } None => ~"" } } @@ -478,65 +487,72 @@ impl Element { // http://dom.spec.whatwg.org/#dom-element-id pub fn Id(&self, abstract_self: &JSRef<Element>) -> DOMString { - abstract_self.unrooted().get_string_attribute("id") + abstract_self.get_string_attribute("id") } // http://dom.spec.whatwg.org/#dom-element-id pub fn SetId(&mut self, abstract_self: &mut JSRef<Element>, id: DOMString) { - abstract_self.unrooted().set_string_attribute("id", id); + abstract_self.set_string_attribute("id", id); } // http://dom.spec.whatwg.org/#dom-element-classname pub fn ClassName(&self, abstract_self: &JSRef<Element>) -> DOMString { - abstract_self.unrooted().get_string_attribute("class") + abstract_self.get_string_attribute("class") } // http://dom.spec.whatwg.org/#dom-element-classname pub fn SetClassName(&self, abstract_self: &mut JSRef<Element>, class: DOMString) { - abstract_self.unrooted().set_string_attribute("class", class); + abstract_self.set_string_attribute("class", class); } // http://dom.spec.whatwg.org/#dom-element-attributes - pub fn Attributes(&mut self, abstract_self: &JSRef<Element>) -> JS<AttrList> { + pub fn Attributes(&mut self, abstract_self: &JSRef<Element>) -> Unrooted<AttrList> { let roots = RootCollection::new(); match self.attr_list { None => { - let doc = self.node.owner_doc(); - let doc = doc.get(); - let window = doc.window.root(&roots); + let doc = self.node.owner_doc().root(&roots); + let window = doc.deref().window.root(&roots); let list = AttrList::new(&window.root_ref(), abstract_self); - self.attr_list = Some(list.clone()); - list + self.attr_list.assign(Some(list)); + Unrooted::new(self.attr_list.get_ref().clone()) } - Some(ref list) => list.clone() + Some(ref list) => Unrooted::new(list.clone()) } } // http://dom.spec.whatwg.org/#dom-element-getattribute pub fn GetAttribute(&self, abstract_self: &JSRef<Element>, name: DOMString) -> Option<DOMString> { + let roots = RootCollection::new(); let name = if abstract_self.get().html_element_in_html_document() { name.to_ascii_lower() } else { name }; - abstract_self.unrooted().get_attribute(Null, name).map(|s| s.get().Value()) + abstract_self.get_attribute(Null, name) + .map(|s| { + let s = s.root(&roots); + s.deref().Value() + }) } // http://dom.spec.whatwg.org/#dom-element-getattributens pub fn GetAttributeNS(&self, abstract_self: &JSRef<Element>, namespace: Option<DOMString>, local_name: DOMString) -> Option<DOMString> { + let roots = RootCollection::new(); let namespace = Namespace::from_str(null_str_as_empty_ref(&namespace)); - abstract_self.unrooted() - .get_attribute(namespace, local_name) - .map(|attr| attr.get().value.clone()) + abstract_self.get_attribute(namespace, local_name) + .map(|attr| { + let attr = attr.root(&roots); + attr.deref().Value() + }) } // http://dom.spec.whatwg.org/#dom-element-setattribute pub fn SetAttribute(&self, abstract_self: &mut JSRef<Element>, name: DOMString, value: DOMString) -> ErrorResult { - abstract_self.unrooted().SetAttribute(name, value) + abstract_self.SetAttribute_(name, value) } // http://dom.spec.whatwg.org/#dom-element-setattributens @@ -545,7 +561,7 @@ impl Element { namespace_url: Option<DOMString>, name: DOMString, value: DOMString) -> ErrorResult { - abstract_self.unrooted().SetAttributeNS(namespace_url, name, value) + abstract_self.SetAttributeNS_(namespace_url, name, value) } // http://dom.spec.whatwg.org/#dom-element-removeattribute @@ -557,7 +573,7 @@ impl Element { } else { name }; - abstract_self.unrooted().remove_attribute(namespace::Null, name) + abstract_self.remove_attribute(namespace::Null, name) } // http://dom.spec.whatwg.org/#dom-element-removeattributens @@ -566,7 +582,7 @@ impl Element { namespace: Option<DOMString>, localname: DOMString) -> ErrorResult { let namespace = Namespace::from_str(null_str_as_empty_ref(&namespace)); - abstract_self.unrooted().remove_attribute(namespace, localname) + abstract_self.remove_attribute(namespace, localname) } // http://dom.spec.whatwg.org/#dom-element-hasattribute @@ -582,63 +598,55 @@ impl Element { self.GetAttributeNS(abstract_self, namespace, local_name).is_some() } - pub fn GetElementsByTagName(&self, abstract_self: &JSRef<Element>, localname: DOMString) -> JS<HTMLCollection> { + pub fn GetElementsByTagName(&self, abstract_self: &JSRef<Element>, localname: DOMString) -> Unrooted<HTMLCollection> { let roots = RootCollection::new(); - let doc = self.node.owner_doc(); - let doc = doc.get(); - let window = doc.window.root(&roots); - HTMLCollection::by_tag_name(&window.root_ref(), NodeCast::from_ref(abstract_self), localname) + let window = window_from_node(abstract_self).root(&roots); + HTMLCollection::by_tag_name(&*window, NodeCast::from_ref(abstract_self), localname) } pub fn GetElementsByTagNameNS(&self, abstract_self: &JSRef<Element>, maybe_ns: Option<DOMString>, - localname: DOMString) -> JS<HTMLCollection> { + localname: DOMString) -> Unrooted<HTMLCollection> { let roots = RootCollection::new(); - let doc = self.node.owner_doc(); - let doc = doc.get(); let namespace = match maybe_ns { Some(namespace) => Namespace::from_str(namespace), None => Null }; - let window = doc.window.root(&roots); - HTMLCollection::by_tag_name_ns(&window.root_ref(), NodeCast::from_ref(abstract_self), localname, namespace) + let window = window_from_node(abstract_self).root(&roots); + HTMLCollection::by_tag_name_ns(&*window, NodeCast::from_ref(abstract_self), localname, namespace) } - pub fn GetElementsByClassName(&self, abstract_self: &JSRef<Element>, classes: DOMString) -> JS<HTMLCollection> { + pub fn GetElementsByClassName(&self, abstract_self: &JSRef<Element>, classes: DOMString) -> Unrooted<HTMLCollection> { let roots = RootCollection::new(); - let doc = self.node.owner_doc(); - let doc = doc.get(); - let window = doc.window.root(&roots); - HTMLCollection::by_class_name(&window.root_ref(), NodeCast::from_ref(abstract_self), classes) + let window = window_from_node(abstract_self).root(&roots); + HTMLCollection::by_class_name(&*window, NodeCast::from_ref(abstract_self), classes) } // http://dev.w3.org/csswg/cssom-view/#dom-element-getclientrects - pub fn GetClientRects(&self, abstract_self: &JSRef<Element>) -> JS<ClientRectList> { + pub fn GetClientRects(&self, abstract_self: &JSRef<Element>) -> Unrooted<ClientRectList> { let roots = RootCollection::new(); - let doc = self.node.owner_doc(); - let win = doc.get().window.root(&roots); - let node: JS<Node> = NodeCast::from(&abstract_self.unrooted()); + let win = window_from_node(abstract_self).root(&roots); + let node: &JSRef<Node> = NodeCast::from_ref(abstract_self); let rects = node.get_content_boxes(); - let rects = rects.iter().map(|r| { + let rects: ~[Root<ClientRect>] = rects.iter().map(|r| { ClientRect::new( - &win.root_ref(), + &*win, r.origin.y, r.origin.y + r.size.height, r.origin.x, - r.origin.x + r.size.width) + r.origin.x + r.size.width).root(&roots) }).collect(); - ClientRectList::new(&win.root_ref(), rects) + ClientRectList::new(&*win, rects.iter().map(|rect| rect.deref().clone()).collect()) } // http://dev.w3.org/csswg/cssom-view/#dom-element-getboundingclientrect - pub fn GetBoundingClientRect(&self, abstract_self: &JSRef<Element>) -> JS<ClientRect> { + pub fn GetBoundingClientRect(&self, abstract_self: &JSRef<Element>) -> Unrooted<ClientRect> { let roots = RootCollection::new(); - let doc = self.node.owner_doc(); - let win = doc.get().window.root(&roots); - let node: JS<Node> = NodeCast::from(&abstract_self.unrooted()); + let win = window_from_node(abstract_self).root(&roots); + let node: &JSRef<Node> = NodeCast::from_ref(abstract_self); let rect = node.get_bounding_content_box(); ClientRect::new( - &win.root_ref(), + &*win, rect.origin.y, rect.origin.y + rect.size.height, rect.origin.x, @@ -647,16 +655,18 @@ impl Element { pub fn GetInnerHTML(&self, abstract_self: &JSRef<Element>) -> Fallible<DOMString> { //XXX TODO: XML case - Ok(serialize(&mut NodeIterator::new(NodeCast::from(&abstract_self.unrooted()), false, false))) + let roots = RootCollection::new(); + Ok(serialize(&mut NodeIterator::new(&roots, NodeCast::from_ref(abstract_self), false, false))) } pub fn GetOuterHTML(&self, abstract_self: &JSRef<Element>) -> Fallible<DOMString> { - Ok(serialize(&mut NodeIterator::new(NodeCast::from(&abstract_self.unrooted()), true, false))) + let roots = RootCollection::new(); + Ok(serialize(&mut NodeIterator::new(&roots, NodeCast::from_ref(abstract_self), true, false))) } - pub fn Children(&self, abstract_self: &JSRef<Element>) -> JS<HTMLCollection> { + pub fn Children(&self, abstract_self: &JSRef<Element>) -> Unrooted<HTMLCollection> { let roots = RootCollection::new(); - let window = window_from_node(&abstract_self.unrooted()).root(&roots); + let window = window_from_node(abstract_self).root(&roots); HTMLCollection::children(&window.root_ref(), NodeCast::from_ref(abstract_self)) } } @@ -674,10 +684,10 @@ pub fn get_attribute_parts(name: DOMString) -> (Option<~str>, ~str) { (prefix, local_name) } -impl VirtualMethods for JS<Element> { +impl<'a> VirtualMethods for JSRef<'a, Element> { fn super_type(&self) -> Option<~VirtualMethods:> { - let node: JS<Node> = NodeCast::from(self); - Some(~node as ~VirtualMethods:) + let node: &JSRef<Node> = NodeCast::from_ref(self); + Some(~node.clone() as ~VirtualMethods:) } fn after_set_attr(&mut self, name: DOMString, value: DOMString) { @@ -687,20 +697,18 @@ impl VirtualMethods for JS<Element> { _ => (), } - let node: JS<Node> = NodeCast::from(self); match name.as_slice() { "style" => { - let doc = node.get().owner_doc(); + let doc = document_from_node(self).root(&roots); let base_url = doc.get().url().clone(); self.get_mut().style_attribute = Some(style::parse_style_attribute(value, &base_url)) } - "id" if node.is_in_doc() => { - // XXX: this dual declaration are workaround to avoid the compile error: - // "borrowed value does not live long enough" - let mut doc = node.get().owner_doc().clone(); - let doc = doc.get_mut(); - let elem = self.root(&roots); - doc.register_named_element(&elem.root_ref(), value.clone()); + "id" => { + let node: &JSRef<Node> = NodeCast::from_ref(self); + if node.is_in_doc() { + let mut doc = document_from_node(self).root(&roots); + doc.register_named_element(self, value.clone()); + } } _ => () } @@ -715,18 +723,16 @@ impl VirtualMethods for JS<Element> { _ => (), } - let node: JS<Node> = NodeCast::from(self); match name.as_slice() { "style" => { self.get_mut().style_attribute = None } - "id" if node.is_in_doc() => { - // XXX: this dual declaration are workaround to avoid the compile error: - // "borrowed value does not live long enough" - let mut doc = node.get().owner_doc().clone(); - let doc = doc.get_mut(); - let elem = self.root(&roots); - doc.unregister_named_element(&elem.root_ref(), value); + "id" => { + let node: &JSRef<Node> = NodeCast::from_ref(self); + if node.is_in_doc() { + let mut doc = document_from_node(self).root(&roots); + doc.unregister_named_element(self, value); + } } _ => () } @@ -743,9 +749,9 @@ impl VirtualMethods for JS<Element> { match self.get_attribute(Null, "id") { Some(attr) => { - let mut doc = document_from_node(self); - let elem = self.root(&roots); - doc.get_mut().register_named_element(&elem.root_ref(), attr.get().Value()); + let attr = attr.root(&roots); + let mut doc = document_from_node(self).root(&roots); + doc.register_named_element(self, attr.deref().Value()); } _ => () } @@ -758,11 +764,10 @@ impl VirtualMethods for JS<Element> { _ => (), } - match self.get_attribute(Null, "id") { + match self.get_attribute(Null, "id").root(&roots) { Some(attr) => { - let mut doc = document_from_node(self); - let elem = self.root(&roots); - doc.get_mut().unregister_named_element(&elem.root_ref(), attr.get().Value()); + let mut doc = document_from_node(self).root(&roots); + doc.unregister_named_element(self, attr.deref().Value()); } _ => () } diff --git a/src/components/script/dom/event.rs b/src/components/script/dom/event.rs index 89c250dbc95..68f83a5d509 100644 --- a/src/components/script/dom/event.rs +++ b/src/components/script/dom/event.rs @@ -4,7 +4,7 @@ use dom::bindings::codegen::BindingDeclarations::EventBinding; use dom::bindings::codegen::BindingDeclarations::EventBinding::EventConstants; -use dom::bindings::js::{JS, JSRef}; +use dom::bindings::js::{JS, JSRef, Unrooted, RootCollection}; use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object}; use dom::bindings::error::Fallible; use dom::eventtarget::EventTarget; @@ -80,7 +80,7 @@ impl Event { } } - pub fn new(window: &JSRef<Window>) -> JS<Event> { + pub fn new(window: &JSRef<Window>) -> Unrooted<Event> { reflect_dom_object(~Event::new_inherited(HTMLEventTypeId), window, EventBinding::Wrap) @@ -94,12 +94,12 @@ impl Event { self.type_.clone() } - pub fn GetTarget(&self) -> Option<JS<EventTarget>> { - self.target.clone() + pub fn GetTarget(&self) -> Option<Unrooted<EventTarget>> { + self.target.as_ref().map(|target| Unrooted::new(target.clone())) } - pub fn GetCurrentTarget(&self) -> Option<JS<EventTarget>> { - self.current_target.clone() + pub fn GetCurrentTarget(&self) -> Option<Unrooted<EventTarget>> { + self.current_target.as_ref().map(|target| Unrooted::new(target.clone())) } pub fn DefaultPrevented(&self) -> bool { @@ -157,10 +157,11 @@ impl Event { pub fn Constructor(global: &JSRef<Window>, type_: DOMString, - init: &EventBinding::EventInit) -> Fallible<JS<Event>> { - let mut ev = Event::new(global); - ev.get_mut().InitEvent(type_, init.bubbles, init.cancelable); - Ok(ev) + init: &EventBinding::EventInit) -> Fallible<Unrooted<Event>> { + let roots = RootCollection::new(); + let mut ev = Event::new(global).root(&roots); + ev.InitEvent(type_, init.bubbles, init.cancelable); + Ok(Unrooted::new_rooted(&*ev)) } } diff --git a/src/components/script/dom/eventdispatcher.rs b/src/components/script/dom/eventdispatcher.rs index b8fbce59974..9d45b398e02 100644 --- a/src/components/script/dom/eventdispatcher.rs +++ b/src/components/script/dom/eventdispatcher.rs @@ -4,35 +4,32 @@ use dom::bindings::callback::ReportExceptions; use dom::bindings::codegen::InheritTypes::{EventTargetCast, NodeCast, NodeDerived}; -use dom::bindings::js::{JS, JSRef}; +use dom::bindings::js::{JSRef, OptionalAssignable, RootCollection, Root}; use dom::eventtarget::{Capturing, Bubbling, EventTarget}; use dom::event::{Event, PhaseAtTarget, PhaseNone, PhaseBubbling, PhaseCapturing}; use dom::node::{Node, NodeHelpers}; // See http://dom.spec.whatwg.org/#concept-event-dispatch for the full dispatch algorithm -pub fn dispatch_event(target: &JSRef<EventTarget>, - pseudo_target: Option<JSRef<EventTarget>>, - event: &mut JSRef<Event>) -> bool { +pub fn dispatch_event<'a>(target: &JSRef<'a, EventTarget>, + pseudo_target: Option<JSRef<'a, EventTarget>>, + event: &mut JSRef<Event>) -> bool { + let roots = RootCollection::new(); assert!(!event.get().dispatching); { let event = event.get_mut(); - event.target = pseudo_target.map(|pseudo_target| { - pseudo_target.unrooted() - }).or_else(|| { - Some(target.unrooted()) - }); + event.target.assign(Some(pseudo_target.unwrap_or(target.clone()))); event.dispatching = true; } let type_ = event.get().type_.clone(); //TODO: no chain if not participating in a tree - let chain: Vec<JS<EventTarget>> = if target.get().is_node() { - let target_node: JS<Node> = NodeCast::to(&target.unrooted()).unwrap(); + let mut chain: Vec<Root<EventTarget>> = if target.get().is_node() { + let target_node: &JSRef<Node> = NodeCast::to_ref(target).unwrap(); target_node.ancestors().map(|ancestor| { - let ancestor_target: JS<EventTarget> = EventTargetCast::from(&ancestor); - ancestor_target + let ancestor_target: &JSRef<EventTarget> = EventTargetCast::from_ref(&ancestor); + ancestor_target.unrooted().root(&roots) }).collect() } else { vec!() @@ -44,9 +41,9 @@ pub fn dispatch_event(target: &JSRef<EventTarget>, /* capturing */ for cur_target in chain.as_slice().rev_iter() { - let stopped = match cur_target.get().get_listeners_for(type_, Capturing) { + let stopped = match cur_target.get_listeners_for(type_, Capturing) { Some(listeners) => { - event.get_mut().current_target = Some(cur_target.clone()); + event.current_target.assign(Some(cur_target.deref().clone())); for listener in listeners.iter() { //FIXME: this should have proper error handling, or explicitly // drop the exception on the floor @@ -72,7 +69,7 @@ pub fn dispatch_event(target: &JSRef<EventTarget>, { let event = event.get_mut(); event.phase = PhaseAtTarget; - event.current_target = Some(target.unrooted()); + event.current_target.assign(Some(target.clone())); } let opt_listeners = target.get().get_listeners(type_); @@ -95,7 +92,7 @@ pub fn dispatch_event(target: &JSRef<EventTarget>, for cur_target in chain.iter() { let stopped = match cur_target.get().get_listeners_for(type_, Bubbling) { Some(listeners) => { - event.get_mut().current_target = Some(cur_target.clone()); + event.get_mut().current_target.assign(Some(cur_target.deref().clone())); for listener in listeners.iter() { //FIXME: this should have proper error handling or explicitly // drop exceptions on the floor. @@ -116,6 +113,12 @@ pub fn dispatch_event(target: &JSRef<EventTarget>, } } + // Root ordering restrictions mean we need to unroot the chain entries + // in the same order they were rooted. + while chain.len() > 0 { + let _ = chain.pop(); + } + let event = event.get_mut(); event.dispatching = false; event.phase = PhaseNone; diff --git a/src/components/script/dom/eventtarget.rs b/src/components/script/dom/eventtarget.rs index b77834e7cc4..67dc0ac7af9 100644 --- a/src/components/script/dom/eventtarget.rs +++ b/src/components/script/dom/eventtarget.rs @@ -2,7 +2,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -use dom::bindings::js::{JS, JSRef}; +use dom::bindings::js::JSRef; use dom::bindings::utils::{Reflectable, Reflector}; use dom::bindings::error::{Fallible, InvalidState}; use dom::bindings::codegen::BindingDeclarations::EventListenerBinding; @@ -107,10 +107,10 @@ impl EventTarget { self.dispatch_event_with_target(abstract_self, None, event) } - pub fn dispatch_event_with_target(&self, - abstract_self: &JSRef<EventTarget>, - abstract_target: Option<JSRef<EventTarget>>, - event: &mut JSRef<Event>) -> Fallible<bool> { + pub fn dispatch_event_with_target<'a>(&self, + abstract_self: &JSRef<'a, EventTarget>, + abstract_target: Option<JSRef<'a, EventTarget>>, + event: &mut JSRef<Event>) -> Fallible<bool> { if event.get().dispatching || !event.get().initialized { return Err(InvalidState); } @@ -128,7 +128,7 @@ impl Reflectable for EventTarget { } } -impl VirtualMethods for JS<EventTarget> { +impl<'a> VirtualMethods for JSRef<'a, EventTarget> { fn super_type(&self) -> Option<~VirtualMethods:> { None } diff --git a/src/components/script/dom/formdata.rs b/src/components/script/dom/formdata.rs index 4b6d61c1d82..e1a7b0e7ddb 100644 --- a/src/components/script/dom/formdata.rs +++ b/src/components/script/dom/formdata.rs @@ -5,7 +5,7 @@ use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object}; use dom::bindings::error::{Fallible}; use dom::bindings::codegen::BindingDeclarations::FormDataBinding; -use dom::bindings::js::{JS, JSRef}; +use dom::bindings::js::{JS, JSRef, Unrooted}; use dom::blob::Blob; use dom::htmlformelement::HTMLFormElement; use dom::window::Window; @@ -37,12 +37,12 @@ impl FormData { } } - pub fn new(form: Option<JSRef<HTMLFormElement>>, window: &JSRef<Window>) -> JS<FormData> { + pub fn new(form: Option<JSRef<HTMLFormElement>>, window: &JSRef<Window>) -> Unrooted<FormData> { reflect_dom_object(~FormData::new_inherited(form, window.unrooted()), window, FormDataBinding::Wrap) } pub fn Constructor(window: &JSRef<Window>, form: Option<JSRef<HTMLFormElement>>) - -> Fallible<JS<FormData>> { + -> Fallible<Unrooted<FormData>> { Ok(FormData::new(form, window)) } diff --git a/src/components/script/dom/htmlanchorelement.rs b/src/components/script/dom/htmlanchorelement.rs index 7edd9116dea..d03723402eb 100644 --- a/src/components/script/dom/htmlanchorelement.rs +++ b/src/components/script/dom/htmlanchorelement.rs @@ -4,7 +4,7 @@ use dom::bindings::codegen::BindingDeclarations::HTMLAnchorElementBinding; use dom::bindings::codegen::InheritTypes::HTMLAnchorElementDerived; -use dom::bindings::js::{JS, JSRef}; +use dom::bindings::js::{JS, JSRef, Unrooted}; use dom::bindings::error::ErrorResult; use dom::document::Document; use dom::element::HTMLAnchorElementTypeId; @@ -34,7 +34,7 @@ impl HTMLAnchorElement { } } - pub fn new(localName: DOMString, document: &JSRef<Document>) -> JS<HTMLAnchorElement> { + pub fn new(localName: DOMString, document: &JSRef<Document>) -> Unrooted<HTMLAnchorElement> { let element = HTMLAnchorElement::new_inherited(localName, document.unrooted()); Node::reflect_node(~element, document, HTMLAnchorElementBinding::Wrap) } diff --git a/src/components/script/dom/htmlappletelement.rs b/src/components/script/dom/htmlappletelement.rs index d2b9fcf2e80..ea253003fd4 100644 --- a/src/components/script/dom/htmlappletelement.rs +++ b/src/components/script/dom/htmlappletelement.rs @@ -4,7 +4,7 @@ use dom::bindings::codegen::BindingDeclarations::HTMLAppletElementBinding; use dom::bindings::codegen::InheritTypes::HTMLAppletElementDerived; -use dom::bindings::js::{JS, JSRef}; +use dom::bindings::js::{JS, JSRef, Unrooted}; use dom::bindings::error::ErrorResult; use dom::document::Document; use dom::element::HTMLAppletElementTypeId; @@ -34,7 +34,7 @@ impl HTMLAppletElement { } } - pub fn new(localName: DOMString, document: &JSRef<Document>) -> JS<HTMLAppletElement> { + pub fn new(localName: DOMString, document: &JSRef<Document>) -> Unrooted<HTMLAppletElement> { let element = HTMLAppletElement::new_inherited(localName, document.unrooted()); Node::reflect_node(~element, document, HTMLAppletElementBinding::Wrap) } diff --git a/src/components/script/dom/htmlareaelement.rs b/src/components/script/dom/htmlareaelement.rs index f4950d46ad7..d98f2033b77 100644 --- a/src/components/script/dom/htmlareaelement.rs +++ b/src/components/script/dom/htmlareaelement.rs @@ -4,7 +4,7 @@ use dom::bindings::codegen::BindingDeclarations::HTMLAreaElementBinding; use dom::bindings::codegen::InheritTypes::HTMLAreaElementDerived; -use dom::bindings::js::{JS, JSRef}; +use dom::bindings::js::{JS, JSRef, Unrooted}; use dom::bindings::error::ErrorResult; use dom::document::Document; use dom::element::HTMLAreaElementTypeId; @@ -34,7 +34,7 @@ impl HTMLAreaElement { } } - pub fn new(localName: DOMString, document: &JSRef<Document>) -> JS<HTMLAreaElement> { + pub fn new(localName: DOMString, document: &JSRef<Document>) -> Unrooted<HTMLAreaElement> { let element = HTMLAreaElement::new_inherited(localName, document.unrooted()); Node::reflect_node(~element, document, HTMLAreaElementBinding::Wrap) } diff --git a/src/components/script/dom/htmlaudioelement.rs b/src/components/script/dom/htmlaudioelement.rs index 2b0b86a36f1..a4ea33c7052 100644 --- a/src/components/script/dom/htmlaudioelement.rs +++ b/src/components/script/dom/htmlaudioelement.rs @@ -4,7 +4,7 @@ use dom::bindings::codegen::BindingDeclarations::HTMLAudioElementBinding; use dom::bindings::codegen::InheritTypes::HTMLAudioElementDerived; -use dom::bindings::js::{JS, JSRef}; +use dom::bindings::js::{JS, JSRef, Unrooted}; use dom::document::Document; use dom::element::HTMLAudioElementTypeId; use dom::eventtarget::{EventTarget, NodeTargetTypeId}; @@ -33,7 +33,7 @@ impl HTMLAudioElement { } } - pub fn new(localName: DOMString, document: &JSRef<Document>) -> JS<HTMLAudioElement> { + pub fn new(localName: DOMString, document: &JSRef<Document>) -> Unrooted<HTMLAudioElement> { let element = HTMLAudioElement::new_inherited(localName, document.unrooted()); Node::reflect_node(~element, document, HTMLAudioElementBinding::Wrap) } diff --git a/src/components/script/dom/htmlbaseelement.rs b/src/components/script/dom/htmlbaseelement.rs index c7d206f3c65..bfaf1a74410 100644 --- a/src/components/script/dom/htmlbaseelement.rs +++ b/src/components/script/dom/htmlbaseelement.rs @@ -5,7 +5,7 @@ use dom::bindings::codegen::BindingDeclarations::HTMLBaseElementBinding; use dom::bindings::codegen::InheritTypes::HTMLBaseElementDerived; use dom::bindings::error::ErrorResult; -use dom::bindings::js::{JS, JSRef}; +use dom::bindings::js::{JS, JSRef, Unrooted}; use dom::document::Document; use dom::element::HTMLBaseElementTypeId; use dom::eventtarget::{EventTarget, NodeTargetTypeId}; @@ -34,7 +34,7 @@ impl HTMLBaseElement { } } - pub fn new(localName: DOMString, document: &JSRef<Document>) -> JS<HTMLBaseElement> { + pub fn new(localName: DOMString, document: &JSRef<Document>) -> Unrooted<HTMLBaseElement> { let element = HTMLBaseElement::new_inherited(localName, document.unrooted()); Node::reflect_node(~element, document, HTMLBaseElementBinding::Wrap) } diff --git a/src/components/script/dom/htmlbodyelement.rs b/src/components/script/dom/htmlbodyelement.rs index 466c60c6430..22b41c283ba 100644 --- a/src/components/script/dom/htmlbodyelement.rs +++ b/src/components/script/dom/htmlbodyelement.rs @@ -5,7 +5,7 @@ use dom::bindings::codegen::BindingDeclarations::HTMLBodyElementBinding; use dom::bindings::codegen::InheritTypes::HTMLBodyElementDerived; use dom::bindings::error::ErrorResult; -use dom::bindings::js::{JS, JSRef}; +use dom::bindings::js::{JS, JSRef, Unrooted}; use dom::document::Document; use dom::element::HTMLBodyElementTypeId; use dom::eventtarget::{EventTarget, NodeTargetTypeId}; @@ -34,7 +34,7 @@ impl HTMLBodyElement { } } - pub fn new(localName: DOMString, document: &JSRef<Document>) -> JS<HTMLBodyElement> { + pub fn new(localName: DOMString, document: &JSRef<Document>) -> Unrooted<HTMLBodyElement> { let element = HTMLBodyElement::new_inherited(localName, document.unrooted()); Node::reflect_node(~element, document, HTMLBodyElementBinding::Wrap) } diff --git a/src/components/script/dom/htmlbrelement.rs b/src/components/script/dom/htmlbrelement.rs index e537b1b2c2a..5e23734042c 100644 --- a/src/components/script/dom/htmlbrelement.rs +++ b/src/components/script/dom/htmlbrelement.rs @@ -5,7 +5,7 @@ use dom::bindings::codegen::BindingDeclarations::HTMLBRElementBinding; use dom::bindings::codegen::InheritTypes::HTMLBRElementDerived; use dom::bindings::error::ErrorResult; -use dom::bindings::js::{JS, JSRef}; +use dom::bindings::js::{JS, JSRef, Unrooted}; use dom::document::Document; use dom::element::HTMLBRElementTypeId; use dom::eventtarget::{EventTarget, NodeTargetTypeId}; @@ -34,7 +34,7 @@ impl HTMLBRElement { } } - pub fn new(localName: DOMString, document: &JSRef<Document>) -> JS<HTMLBRElement> { + pub fn new(localName: DOMString, document: &JSRef<Document>) -> Unrooted<HTMLBRElement> { let element = HTMLBRElement::new_inherited(localName, document.unrooted()); Node::reflect_node(~element, document, HTMLBRElementBinding::Wrap) } diff --git a/src/components/script/dom/htmlbuttonelement.rs b/src/components/script/dom/htmlbuttonelement.rs index cee5e13946c..30f031f8058 100644 --- a/src/components/script/dom/htmlbuttonelement.rs +++ b/src/components/script/dom/htmlbuttonelement.rs @@ -4,7 +4,7 @@ use dom::bindings::codegen::BindingDeclarations::HTMLButtonElementBinding; use dom::bindings::codegen::InheritTypes::HTMLButtonElementDerived; -use dom::bindings::js::{JS, JSRef, RootCollection}; +use dom::bindings::js::{JS, JSRef, RootCollection, Unrooted}; use dom::bindings::error::ErrorResult; use dom::document::Document; use dom::element::HTMLButtonElementTypeId; @@ -36,7 +36,7 @@ impl HTMLButtonElement { } } - pub fn new(localName: DOMString, document: &JSRef<Document>) -> JS<HTMLButtonElement> { + pub fn new(localName: DOMString, document: &JSRef<Document>) -> Unrooted<HTMLButtonElement> { let element = HTMLButtonElement::new_inherited(localName, document.unrooted()); Node::reflect_node(~element, document, HTMLButtonElementBinding::Wrap) } @@ -59,7 +59,7 @@ impl HTMLButtonElement { Ok(()) } - pub fn GetForm(&self) -> Option<JS<HTMLFormElement>> { + pub fn GetForm(&self) -> Option<Unrooted<HTMLFormElement>> { None } @@ -134,11 +134,10 @@ impl HTMLButtonElement { pub fn SetWillValidate(&mut self, _will_validate: bool) { } - pub fn Validity(&self) -> JS<ValidityState> { + pub fn Validity(&self) -> Unrooted<ValidityState> { let roots = RootCollection::new(); - let doc = self.htmlelement.element.node.owner_doc(); - let doc = doc.get(); - ValidityState::new(&doc.window.root(&roots).root_ref()) + let doc = self.htmlelement.element.node.owner_doc().root(&roots); + ValidityState::new(&*doc.deref().window.root(&roots)) } pub fn SetValidity(&mut self, _validity: JS<ValidityState>) { diff --git a/src/components/script/dom/htmlcanvaselement.rs b/src/components/script/dom/htmlcanvaselement.rs index 4c825780216..469bb8b8643 100644 --- a/src/components/script/dom/htmlcanvaselement.rs +++ b/src/components/script/dom/htmlcanvaselement.rs @@ -4,7 +4,7 @@ use dom::bindings::codegen::BindingDeclarations::HTMLCanvasElementBinding; use dom::bindings::codegen::InheritTypes::HTMLCanvasElementDerived; -use dom::bindings::js::{JS, JSRef}; +use dom::bindings::js::{JS, JSRef, Unrooted}; use dom::bindings::error::{ErrorResult}; use dom::document::Document; use dom::element::HTMLCanvasElementTypeId; @@ -34,7 +34,7 @@ impl HTMLCanvasElement { } } - pub fn new(localName: DOMString, document: &JSRef<Document>) -> JS<HTMLCanvasElement> { + pub fn new(localName: DOMString, document: &JSRef<Document>) -> Unrooted<HTMLCanvasElement> { let element = HTMLCanvasElement::new_inherited(localName, document.unrooted()); Node::reflect_node(~element, document, HTMLCanvasElementBinding::Wrap) } diff --git a/src/components/script/dom/htmlcollection.rs b/src/components/script/dom/htmlcollection.rs index 8529d4daf64..73b4835ff2e 100644 --- a/src/components/script/dom/htmlcollection.rs +++ b/src/components/script/dom/htmlcollection.rs @@ -4,7 +4,7 @@ use dom::bindings::codegen::InheritTypes::{ElementCast, NodeCast}; use dom::bindings::codegen::BindingDeclarations::HTMLCollectionBinding; -use dom::bindings::js::{JS, JSRef, RootCollection}; +use dom::bindings::js::{JS, JSRef, RootCollection, Unrooted}; use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object}; use dom::element::{Element, AttributeHandlers}; use dom::node::{Node, NodeHelpers}; @@ -46,19 +46,19 @@ impl HTMLCollection { } } - pub fn new(window: &JSRef<Window>, collection: CollectionTypeId) -> JS<HTMLCollection> { + pub fn new(window: &JSRef<Window>, collection: CollectionTypeId) -> Unrooted<HTMLCollection> { reflect_dom_object(~HTMLCollection::new_inherited(window.unrooted(), collection), window, HTMLCollectionBinding::Wrap) } } impl HTMLCollection { - pub fn create(window: &JSRef<Window>, root: &JSRef<Node>, filter: ~CollectionFilter) -> JS<HTMLCollection> { + pub fn create(window: &JSRef<Window>, root: &JSRef<Node>, filter: ~CollectionFilter) -> Unrooted<HTMLCollection> { HTMLCollection::new(window, Live(root.unrooted(), filter)) } pub fn by_tag_name(window: &JSRef<Window>, root: &JSRef<Node>, tag: DOMString) - -> JS<HTMLCollection> { + -> Unrooted<HTMLCollection> { struct TagNameFilter { tag: DOMString } @@ -74,7 +74,7 @@ impl HTMLCollection { } pub fn by_tag_name_ns(window: &JSRef<Window>, root: &JSRef<Node>, tag: DOMString, - namespace: Namespace) -> JS<HTMLCollection> { + namespace: Namespace) -> Unrooted<HTMLCollection> { struct TagNameNSFilter { tag: DOMString, namespace: Namespace @@ -92,13 +92,13 @@ impl HTMLCollection { } pub fn by_class_name(window: &JSRef<Window>, root: &JSRef<Node>, classes: DOMString) - -> JS<HTMLCollection> { + -> Unrooted<HTMLCollection> { struct ClassNameFilter { classes: Vec<DOMString> } impl CollectionFilter for ClassNameFilter { fn filter(&self, elem: &JSRef<Element>, _root: &JSRef<Node>) -> bool { - self.classes.iter().all(|class| elem.unrooted().has_class(*class)) + self.classes.iter().all(|class| elem.has_class(*class)) } } let filter = ClassNameFilter { @@ -107,11 +107,11 @@ impl HTMLCollection { HTMLCollection::create(window, root, ~filter) } - pub fn children(window: &JSRef<Window>, root: &JSRef<Node>) -> JS<HTMLCollection> { + pub fn children(window: &JSRef<Window>, root: &JSRef<Node>) -> Unrooted<HTMLCollection> { struct ElementChildFilter; impl CollectionFilter for ElementChildFilter { fn filter(&self, elem: &JSRef<Element>, root: &JSRef<Node>) -> bool { - root.unrooted().is_parent_of(NodeCast::from_ref(elem)) + root.is_parent_of(NodeCast::from_ref(elem)) } } HTMLCollection::create(window, root, ~ElementChildFilter) @@ -125,43 +125,43 @@ impl HTMLCollection { match self.collection { Static(ref elems) => elems.len() as u32, Live(ref root, ref filter) => { - let root_root = root.root(&roots); - root.traverse_preorder() + let root = root.root(&roots); + root.deref().traverse_preorder(&roots) .count(|child| { - let elem: Option<JS<Element>> = ElementCast::to(&child); - elem.map_or(false, |elem| { - let elem = elem.root(&roots); - filter.filter(&elem.root_ref(), &root_root.root_ref()) - }) + let elem: Option<&JSRef<Element>> = ElementCast::to_ref(&child); + elem.map_or(false, |elem| filter.filter(elem, &*root)) }) as u32 } } } // http://dom.spec.whatwg.org/#dom-htmlcollection-item - pub fn Item(&self, index: u32) -> Option<JS<Element>> { + pub fn Item(&self, index: u32) -> Option<Unrooted<Element>> { let roots = RootCollection::new(); match self.collection { Static(ref elems) => elems .as_slice() .get(index as uint) - .map(|elem| elem.clone()), + .map(|elem| Unrooted::new(elem.clone())), Live(ref root, ref filter) => { - let root_root = root.root(&roots); - root.traverse_preorder() - .filter_map(|node| ElementCast::to(&node)) - .filter(|elem| { - let elem = elem.root(&roots); - filter.filter(&elem.root_ref(), &root_root.root_ref()) + let root = root.root(&roots); + root.deref().traverse_preorder(&roots) + .filter_map(|node| { + let elem: Option<&JSRef<Element>> = ElementCast::to_ref(&node); + elem.filtered(|&elem| filter.filter(elem, &*root)) + .and_then(|elem| Some(elem.clone())) }) - .nth(index as uint).clone() + .nth(index as uint) + .clone() + .map(|elem| Unrooted::new_rooted(&elem)) } } } // http://dom.spec.whatwg.org/#dom-htmlcollection-nameditem - pub fn NamedItem(&self, key: DOMString) -> Option<JS<Element>> { + pub fn NamedItem(&self, key: DOMString) -> Option<Unrooted<Element>> { let roots = RootCollection::new(); + // Step 1. if key.is_empty() { return None; @@ -170,35 +170,36 @@ impl HTMLCollection { // Step 2. match self.collection { Static(ref elems) => elems.iter() + .map(|elem| elem.root(&roots)) .find(|elem| { elem.get_string_attribute("name") == key || elem.get_string_attribute("id") == key }) - .map(|maybe_elem| maybe_elem.clone()), + .map(|maybe_elem| Unrooted::new_rooted(&*maybe_elem)), Live(ref root, ref filter) => { - let root_root = root.root(&roots); - root.traverse_preorder() - .filter_map(|node| ElementCast::to(&node)) - .filter(|elem| { - let elem = elem.root(&roots); - filter.filter(&elem.root_ref(), &root_root.root_ref()) + let root = root.root(&roots); + root.deref().traverse_preorder(&roots) + .filter_map(|node| { + let elem: Option<&JSRef<Element>> = ElementCast::to_ref(&node); + elem.filtered(|&elem| filter.filter(elem, &*root)) + .and_then(|elem| Some(elem.clone())) }) .find(|elem| { elem.get_string_attribute("name") == key || elem.get_string_attribute("id") == key }) - .map(|maybe_elem| maybe_elem.clone()) + .map(|maybe_elem| Unrooted::new_rooted(&maybe_elem)) } } } } impl HTMLCollection { - pub fn IndexedGetter(&self, index: u32, found: &mut bool) -> Option<JS<Element>> { + pub fn IndexedGetter(&self, index: u32, found: &mut bool) -> Option<Unrooted<Element>> { let maybe_elem = self.Item(index); *found = maybe_elem.is_some(); maybe_elem } - pub fn NamedGetter(&self, maybe_name: Option<DOMString>, found: &mut bool) -> Option<JS<Element>> { + pub fn NamedGetter(&self, maybe_name: Option<DOMString>, found: &mut bool) -> Option<Unrooted<Element>> { match maybe_name { Some(name) => { let maybe_elem = self.NamedItem(name); diff --git a/src/components/script/dom/htmldataelement.rs b/src/components/script/dom/htmldataelement.rs index b95c77acc07..767b3b18598 100644 --- a/src/components/script/dom/htmldataelement.rs +++ b/src/components/script/dom/htmldataelement.rs @@ -4,7 +4,7 @@ use dom::bindings::codegen::BindingDeclarations::HTMLDataElementBinding; use dom::bindings::codegen::InheritTypes::HTMLDataElementDerived; -use dom::bindings::js::{JS, JSRef}; +use dom::bindings::js::{JS, JSRef, Unrooted}; use dom::bindings::error::ErrorResult; use dom::document::Document; use dom::element::HTMLDataElementTypeId; @@ -34,7 +34,7 @@ impl HTMLDataElement { } } - pub fn new(localName: DOMString, document: &JSRef<Document>) -> JS<HTMLDataElement> { + pub fn new(localName: DOMString, document: &JSRef<Document>) -> Unrooted<HTMLDataElement> { let element = HTMLDataElement::new_inherited(localName, document.unrooted()); Node::reflect_node(~element, document, HTMLDataElementBinding::Wrap) } diff --git a/src/components/script/dom/htmldatalistelement.rs b/src/components/script/dom/htmldatalistelement.rs index b341a34dcb0..e4ac02bd83f 100644 --- a/src/components/script/dom/htmldatalistelement.rs +++ b/src/components/script/dom/htmldatalistelement.rs @@ -4,7 +4,7 @@ use dom::bindings::codegen::BindingDeclarations::HTMLDataListElementBinding; use dom::bindings::codegen::InheritTypes::{HTMLDataListElementDerived, NodeCast}; -use dom::bindings::js::{JS, JSRef, RootCollection}; +use dom::bindings::js::{JS, JSRef, RootCollection, Unrooted}; use dom::document::Document; use dom::element::{Element, HTMLDataListElementTypeId}; use dom::eventtarget::{EventTarget, NodeTargetTypeId}; @@ -34,14 +34,14 @@ impl HTMLDataListElement { } } - pub fn new(localName: DOMString, document: &JSRef<Document>) -> JS<HTMLDataListElement> { + pub fn new(localName: DOMString, document: &JSRef<Document>) -> Unrooted<HTMLDataListElement> { let element = HTMLDataListElement::new_inherited(localName, document.unrooted()); Node::reflect_node(~element, document, HTMLDataListElementBinding::Wrap) } } impl HTMLDataListElement { - pub fn Options(&self, abstract_self: &JSRef<HTMLDataListElement>) -> JS<HTMLCollection> { + pub fn Options(&self, abstract_self: &JSRef<HTMLDataListElement>) -> Unrooted<HTMLCollection> { struct HTMLDataListOptionsFilter; impl CollectionFilter for HTMLDataListOptionsFilter { fn filter(&self, elem: &JSRef<Element>, _root: &JSRef<Node>) -> bool { @@ -51,7 +51,7 @@ impl HTMLDataListElement { let roots = RootCollection::new(); let node: &JSRef<Node> = NodeCast::from_ref(abstract_self); let filter = ~HTMLDataListOptionsFilter; - let window = window_from_node(&node.unrooted()).root(&roots); - HTMLCollection::create(&window.root_ref(), node, filter) + let window = window_from_node(node).root(&roots); + HTMLCollection::create(&*window, node, filter) } } diff --git a/src/components/script/dom/htmldirectoryelement.rs b/src/components/script/dom/htmldirectoryelement.rs index 84ee0b539b6..f4b77ee5cf0 100644 --- a/src/components/script/dom/htmldirectoryelement.rs +++ b/src/components/script/dom/htmldirectoryelement.rs @@ -4,7 +4,7 @@ use dom::bindings::codegen::BindingDeclarations::HTMLDirectoryElementBinding; use dom::bindings::codegen::InheritTypes::HTMLDirectoryElementDerived; -use dom::bindings::js::{JS, JSRef}; +use dom::bindings::js::{JS, JSRef, Unrooted}; use dom::bindings::error::ErrorResult; use dom::document::Document; use dom::element::HTMLDirectoryElementTypeId; @@ -34,7 +34,7 @@ impl HTMLDirectoryElement { } } - pub fn new(localName: DOMString, document: &JSRef<Document>) -> JS<HTMLDirectoryElement> { + pub fn new(localName: DOMString, document: &JSRef<Document>) -> Unrooted<HTMLDirectoryElement> { let element = HTMLDirectoryElement::new_inherited(localName, document.unrooted()); Node::reflect_node(~element, document, HTMLDirectoryElementBinding::Wrap) } diff --git a/src/components/script/dom/htmldivelement.rs b/src/components/script/dom/htmldivelement.rs index 723a2088307..6053582738d 100644 --- a/src/components/script/dom/htmldivelement.rs +++ b/src/components/script/dom/htmldivelement.rs @@ -4,7 +4,7 @@ use dom::bindings::codegen::BindingDeclarations::HTMLDivElementBinding; use dom::bindings::codegen::InheritTypes::HTMLDivElementDerived; -use dom::bindings::js::{JS, JSRef}; +use dom::bindings::js::{JS, JSRef, Unrooted}; use dom::bindings::error::ErrorResult; use dom::document::Document; use dom::element::HTMLDivElementTypeId; @@ -34,7 +34,7 @@ impl HTMLDivElement { } } - pub fn new(localName: DOMString, document: &JSRef<Document>) -> JS<HTMLDivElement> { + pub fn new(localName: DOMString, document: &JSRef<Document>) -> Unrooted<HTMLDivElement> { let element = HTMLDivElement::new_inherited(localName, document.unrooted()); Node::reflect_node(~element, document, HTMLDivElementBinding::Wrap) } diff --git a/src/components/script/dom/htmldlistelement.rs b/src/components/script/dom/htmldlistelement.rs index 8f3523189b7..113547af9d6 100644 --- a/src/components/script/dom/htmldlistelement.rs +++ b/src/components/script/dom/htmldlistelement.rs @@ -4,7 +4,7 @@ use dom::bindings::codegen::BindingDeclarations::HTMLDListElementBinding; use dom::bindings::codegen::InheritTypes::HTMLDListElementDerived; -use dom::bindings::js::{JS, JSRef}; +use dom::bindings::js::{JS, JSRef, Unrooted}; use dom::bindings::error::ErrorResult; use dom::document::Document; use dom::element::HTMLDListElementTypeId; @@ -34,7 +34,7 @@ impl HTMLDListElement { } } - pub fn new(localName: DOMString, document: &JSRef<Document>) -> JS<HTMLDListElement> { + pub fn new(localName: DOMString, document: &JSRef<Document>) -> Unrooted<HTMLDListElement> { let element = HTMLDListElement::new_inherited(localName, document.unrooted()); Node::reflect_node(~element, document, HTMLDListElementBinding::Wrap) } diff --git a/src/components/script/dom/htmlelement.rs b/src/components/script/dom/htmlelement.rs index a7852aec276..d49ce843bd1 100644 --- a/src/components/script/dom/htmlelement.rs +++ b/src/components/script/dom/htmlelement.rs @@ -5,7 +5,7 @@ use dom::bindings::codegen::BindingDeclarations::HTMLElementBinding; use dom::bindings::codegen::InheritTypes::ElementCast; use dom::bindings::codegen::InheritTypes::HTMLElementDerived; -use dom::bindings::js::{JS, JSRef}; +use dom::bindings::js::{JS, JSRef, Unrooted}; use dom::bindings::error::{ErrorResult, Fallible}; use dom::document::Document; use dom::element::{Element, ElementTypeId, HTMLElementTypeId}; @@ -39,7 +39,7 @@ impl HTMLElement { } } - pub fn new(localName: DOMString, document: &JSRef<Document>) -> JS<HTMLElement> { + pub fn new(localName: DOMString, document: &JSRef<Document>) -> Unrooted<HTMLElement> { let element = HTMLElement::new_inherited(HTMLElementTypeId, localName, document.unrooted()); Node::reflect_node(~element, document, HTMLElementBinding::Wrap) } @@ -143,7 +143,7 @@ impl HTMLElement { Ok(()) } - pub fn GetOffsetParent(&self) -> Option<JS<Element>> { + pub fn GetOffsetParent(&self) -> Option<Unrooted<Element>> { None } @@ -164,9 +164,9 @@ impl HTMLElement { } } -impl VirtualMethods for JS<HTMLElement> { +impl<'a> VirtualMethods for JSRef<'a, HTMLElement> { fn super_type(&self) -> Option<~VirtualMethods:> { - let element: JS<Element> = ElementCast::from(self); - Some(~element as ~VirtualMethods:) + let element: &JSRef<Element> = ElementCast::from_ref(self); + Some(~element.clone() as ~VirtualMethods:) } } diff --git a/src/components/script/dom/htmlembedelement.rs b/src/components/script/dom/htmlembedelement.rs index 73a915c4cc7..864e1a1829c 100644 --- a/src/components/script/dom/htmlembedelement.rs +++ b/src/components/script/dom/htmlembedelement.rs @@ -4,7 +4,7 @@ use dom::bindings::codegen::BindingDeclarations::HTMLEmbedElementBinding; use dom::bindings::codegen::InheritTypes::HTMLEmbedElementDerived; -use dom::bindings::js::{JS, JSRef}; +use dom::bindings::js::{JS, JSRef, Unrooted}; use dom::bindings::error::ErrorResult; use dom::document::Document; use dom::element::HTMLEmbedElementTypeId; @@ -34,7 +34,7 @@ impl HTMLEmbedElement { } } - pub fn new(localName: DOMString, document: &JSRef<Document>) -> JS<HTMLEmbedElement> { + pub fn new(localName: DOMString, document: &JSRef<Document>) -> Unrooted<HTMLEmbedElement> { let element = HTMLEmbedElement::new_inherited(localName, document.unrooted()); Node::reflect_node(~element, document, HTMLEmbedElementBinding::Wrap) } @@ -89,7 +89,7 @@ impl HTMLEmbedElement { Ok(()) } - pub fn GetSVGDocument(&self) -> Option<JS<Document>> { + pub fn GetSVGDocument(&self) -> Option<Unrooted<Document>> { None } } diff --git a/src/components/script/dom/htmlfieldsetelement.rs b/src/components/script/dom/htmlfieldsetelement.rs index 3b1141f403e..1bb9146e4e7 100644 --- a/src/components/script/dom/htmlfieldsetelement.rs +++ b/src/components/script/dom/htmlfieldsetelement.rs @@ -4,7 +4,7 @@ use dom::bindings::codegen::BindingDeclarations::HTMLFieldSetElementBinding; use dom::bindings::codegen::InheritTypes::{ElementCast, HTMLFieldSetElementDerived, NodeCast}; -use dom::bindings::js::{JS, JSRef, RootCollection}; +use dom::bindings::js::{JS, JSRef, RootCollection, Unrooted}; use dom::bindings::error::ErrorResult; use dom::document::Document; use dom::element::{Element, HTMLFieldSetElementTypeId}; @@ -37,7 +37,7 @@ impl HTMLFieldSetElement { } } - pub fn new(localName: DOMString, document: &JSRef<Document>) -> JS<HTMLFieldSetElement> { + pub fn new(localName: DOMString, document: &JSRef<Document>) -> Unrooted<HTMLFieldSetElement> { let element = HTMLFieldSetElement::new_inherited(localName, document.unrooted()); Node::reflect_node(~element, document, HTMLFieldSetElementBinding::Wrap) } @@ -52,7 +52,7 @@ impl HTMLFieldSetElement { Ok(()) } - pub fn GetForm(&self) -> Option<JS<HTMLFormElement>> { + pub fn GetForm(&self) -> Option<Unrooted<HTMLFormElement>> { None } @@ -69,33 +69,32 @@ impl HTMLFieldSetElement { } // http://www.whatwg.org/html/#dom-fieldset-elements - pub fn Elements(&self, abstract_self: &JSRef<HTMLFieldSetElement>) -> JS<HTMLCollection> { + pub fn Elements(&self, abstract_self: &JSRef<HTMLFieldSetElement>) -> Unrooted<HTMLCollection> { struct ElementsFilter; impl CollectionFilter for ElementsFilter { fn filter(&self, elem: &JSRef<Element>, root: &JSRef<Node>) -> bool { static tag_names: StaticStringVec = &["button", "fieldset", "input", "keygen", "object", "output", "select", "textarea"]; - let root: &JS<Element> = &ElementCast::to(&root.unrooted()).unwrap(); - &elem.unrooted() != root && tag_names.iter().any(|&tag_name| tag_name == elem.get().local_name) + let root: &JSRef<Element> = ElementCast::to_ref(root).unwrap(); + elem != root && tag_names.iter().any(|&tag_name| tag_name == elem.get().local_name) } } let roots = RootCollection::new(); let node: &JSRef<Node> = NodeCast::from_ref(abstract_self); let filter = ~ElementsFilter; - let window = window_from_node(&node.unrooted()).root(&roots); - HTMLCollection::create(&window.root_ref(), node, filter) + let window = window_from_node(node).root(&roots); + HTMLCollection::create(&*window, node, filter) } pub fn WillValidate(&self) -> bool { false } - pub fn Validity(&self) -> JS<ValidityState> { + pub fn Validity(&self) -> Unrooted<ValidityState> { let roots = RootCollection::new(); - let doc = self.htmlelement.element.node.owner_doc(); - let doc = doc.get(); - let window = doc.window.root(&roots); - ValidityState::new(&window.root_ref()) + let doc = self.htmlelement.element.node.owner_doc().root(&roots); + let window = doc.deref().window.root(&roots); + ValidityState::new(&*window) } pub fn ValidationMessage(&self) -> DOMString { diff --git a/src/components/script/dom/htmlfontelement.rs b/src/components/script/dom/htmlfontelement.rs index f28971e7c43..fefc9c0f4df 100644 --- a/src/components/script/dom/htmlfontelement.rs +++ b/src/components/script/dom/htmlfontelement.rs @@ -4,7 +4,7 @@ use dom::bindings::codegen::BindingDeclarations::HTMLFontElementBinding; use dom::bindings::codegen::InheritTypes::HTMLFontElementDerived; -use dom::bindings::js::{JS, JSRef}; +use dom::bindings::js::{JS, JSRef, Unrooted}; use dom::bindings::error::ErrorResult; use dom::document::Document; use dom::element::HTMLFontElementTypeId; @@ -34,7 +34,7 @@ impl HTMLFontElement { } } - pub fn new(localName: DOMString, document: &JSRef<Document>) -> JS<HTMLFontElement> { + pub fn new(localName: DOMString, document: &JSRef<Document>) -> Unrooted<HTMLFontElement> { let element = HTMLFontElement::new_inherited(localName, document.unrooted()); Node::reflect_node(~element, document, HTMLFontElementBinding::Wrap) } diff --git a/src/components/script/dom/htmlformelement.rs b/src/components/script/dom/htmlformelement.rs index 0e7159c61b9..329b9e07baf 100644 --- a/src/components/script/dom/htmlformelement.rs +++ b/src/components/script/dom/htmlformelement.rs @@ -4,7 +4,7 @@ use dom::bindings::codegen::BindingDeclarations::HTMLFormElementBinding; use dom::bindings::codegen::InheritTypes::HTMLFormElementDerived; -use dom::bindings::js::{JS, JSRef, RootCollection}; +use dom::bindings::js::{JS, JSRef, RootCollection, Unrooted}; use dom::bindings::error::ErrorResult; use dom::document::Document; use dom::element::{Element, HTMLFormElementTypeId}; @@ -35,7 +35,7 @@ impl HTMLFormElement { } } - pub fn new(localName: DOMString, document: &JSRef<Document>) -> JS<HTMLFormElement> { + pub fn new(localName: DOMString, document: &JSRef<Document>) -> Unrooted<HTMLFormElement> { let element = HTMLFormElement::new_inherited(localName, document.unrooted()); Node::reflect_node(~element, document, HTMLFormElementBinding::Wrap) } @@ -114,13 +114,12 @@ impl HTMLFormElement { Ok(()) } - pub fn Elements(&self) -> JS<HTMLCollection> { + pub fn Elements(&self) -> Unrooted<HTMLCollection> { // FIXME: https://github.com/mozilla/servo/issues/1844 let roots = RootCollection::new(); - let doc = self.htmlelement.element.node.owner_doc(); - let doc = doc.get(); - let window = doc.window.root(&roots); - HTMLCollection::new(&window.root_ref(), Static(vec!())) + let doc = self.htmlelement.element.node.owner_doc().root(&roots); + let window = doc.deref().window.root(&roots); + HTMLCollection::new(&*window, Static(vec!())) } pub fn Length(&self) -> i32 { @@ -138,7 +137,7 @@ impl HTMLFormElement { false } - pub fn IndexedGetter(&self, _index: u32, _found: &mut bool) -> JS<Element> { + pub fn IndexedGetter(&self, _index: u32, _found: &mut bool) -> Unrooted<Element> { fail!("Not implemented.") } } diff --git a/src/components/script/dom/htmlframeelement.rs b/src/components/script/dom/htmlframeelement.rs index 535c0398690..180124bf6dd 100644 --- a/src/components/script/dom/htmlframeelement.rs +++ b/src/components/script/dom/htmlframeelement.rs @@ -4,7 +4,7 @@ use dom::bindings::codegen::BindingDeclarations::HTMLFrameElementBinding; use dom::bindings::codegen::InheritTypes::HTMLFrameElementDerived; -use dom::bindings::js::{JS, JSRef}; +use dom::bindings::js::{JS, JSRef, Unrooted}; use dom::bindings::error::ErrorResult; use dom::document::Document; use dom::element::HTMLFrameElementTypeId; @@ -35,7 +35,7 @@ impl HTMLFrameElement { } } - pub fn new(localName: DOMString, document: &JSRef<Document>) -> JS<HTMLFrameElement> { + pub fn new(localName: DOMString, document: &JSRef<Document>) -> Unrooted<HTMLFrameElement> { let element = HTMLFrameElement::new_inherited(localName, document.unrooted()); Node::reflect_node(~element, document, HTMLFrameElementBinding::Wrap) } @@ -90,11 +90,11 @@ impl HTMLFrameElement { Ok(()) } - pub fn GetContentDocument(&self) -> Option<JS<Document>> { + pub fn GetContentDocument(&self) -> Option<Unrooted<Document>> { None } - pub fn GetContentWindow(&self) -> Option<JS<Window>> { + pub fn GetContentWindow(&self) -> Option<Unrooted<Window>> { None } diff --git a/src/components/script/dom/htmlframesetelement.rs b/src/components/script/dom/htmlframesetelement.rs index 29691e01397..9177c197ae8 100644 --- a/src/components/script/dom/htmlframesetelement.rs +++ b/src/components/script/dom/htmlframesetelement.rs @@ -4,7 +4,7 @@ use dom::bindings::codegen::BindingDeclarations::HTMLFrameSetElementBinding; use dom::bindings::codegen::InheritTypes::HTMLFrameSetElementDerived; -use dom::bindings::js::{JS, JSRef}; +use dom::bindings::js::{JS, JSRef, Unrooted}; use dom::bindings::error::ErrorResult; use dom::document::Document; use dom::element::HTMLFrameSetElementTypeId; @@ -34,7 +34,7 @@ impl HTMLFrameSetElement { } } - pub fn new(localName: DOMString, document: &JSRef<Document>) -> JS<HTMLFrameSetElement> { + pub fn new(localName: DOMString, document: &JSRef<Document>) -> Unrooted<HTMLFrameSetElement> { let element = HTMLFrameSetElement::new_inherited(localName, document.unrooted()); Node::reflect_node(~element, document, HTMLFrameSetElementBinding::Wrap) } diff --git a/src/components/script/dom/htmlheadelement.rs b/src/components/script/dom/htmlheadelement.rs index 3f2037d7188..6b10c6078c3 100644 --- a/src/components/script/dom/htmlheadelement.rs +++ b/src/components/script/dom/htmlheadelement.rs @@ -4,7 +4,7 @@ use dom::bindings::codegen::BindingDeclarations::HTMLHeadElementBinding; use dom::bindings::codegen::InheritTypes::HTMLHeadElementDerived; -use dom::bindings::js::{JS, JSRef}; +use dom::bindings::js::{JS, JSRef, Unrooted}; use dom::document::Document; use dom::element::HTMLHeadElementTypeId; use dom::eventtarget::{EventTarget, NodeTargetTypeId}; @@ -33,7 +33,7 @@ impl HTMLHeadElement { } } - pub fn new(localName: DOMString, document: &JSRef<Document>) -> JS<HTMLHeadElement> { + pub fn new(localName: DOMString, document: &JSRef<Document>) -> Unrooted<HTMLHeadElement> { let element = HTMLHeadElement::new_inherited(localName, document.unrooted()); Node::reflect_node(~element, document, HTMLHeadElementBinding::Wrap) } diff --git a/src/components/script/dom/htmlheadingelement.rs b/src/components/script/dom/htmlheadingelement.rs index 40844eb36e5..4574189d7bf 100644 --- a/src/components/script/dom/htmlheadingelement.rs +++ b/src/components/script/dom/htmlheadingelement.rs @@ -4,7 +4,7 @@ use dom::bindings::codegen::BindingDeclarations::HTMLHeadingElementBinding; use dom::bindings::codegen::InheritTypes::HTMLHeadingElementDerived; -use dom::bindings::js::{JS, JSRef}; +use dom::bindings::js::{JS, JSRef, Unrooted}; use dom::document::Document; use dom::element::HTMLHeadingElementTypeId; use dom::eventtarget::{EventTarget, NodeTargetTypeId}; @@ -45,7 +45,7 @@ impl HTMLHeadingElement { } } - pub fn new(localName: DOMString, document: &JSRef<Document>, level: HeadingLevel) -> JS<HTMLHeadingElement> { + pub fn new(localName: DOMString, document: &JSRef<Document>, level: HeadingLevel) -> Unrooted<HTMLHeadingElement> { let element = HTMLHeadingElement::new_inherited(localName, document.unrooted(), level); Node::reflect_node(~element, document, HTMLHeadingElementBinding::Wrap) } diff --git a/src/components/script/dom/htmlhrelement.rs b/src/components/script/dom/htmlhrelement.rs index 28bdd2ed3de..14098388c1d 100644 --- a/src/components/script/dom/htmlhrelement.rs +++ b/src/components/script/dom/htmlhrelement.rs @@ -4,7 +4,7 @@ use dom::bindings::codegen::BindingDeclarations::HTMLHRElementBinding; use dom::bindings::codegen::InheritTypes::HTMLHRElementDerived; -use dom::bindings::js::{JS, JSRef}; +use dom::bindings::js::{JS, JSRef, Unrooted}; use dom::bindings::error::ErrorResult; use dom::document::Document; use dom::element::HTMLHRElementTypeId; @@ -34,7 +34,7 @@ impl HTMLHRElement { } } - pub fn new(localName: DOMString, document: &JSRef<Document>) -> JS<HTMLHRElement> { + pub fn new(localName: DOMString, document: &JSRef<Document>) -> Unrooted<HTMLHRElement> { let element = HTMLHRElement::new_inherited(localName, document.unrooted()); Node::reflect_node(~element, document, HTMLHRElementBinding::Wrap) } diff --git a/src/components/script/dom/htmlhtmlelement.rs b/src/components/script/dom/htmlhtmlelement.rs index 391bf7b2465..1930ce271c2 100644 --- a/src/components/script/dom/htmlhtmlelement.rs +++ b/src/components/script/dom/htmlhtmlelement.rs @@ -4,7 +4,7 @@ use dom::bindings::codegen::BindingDeclarations::HTMLHtmlElementBinding; use dom::bindings::codegen::InheritTypes::HTMLHtmlElementDerived; -use dom::bindings::js::{JS, JSRef}; +use dom::bindings::js::{JS, JSRef, Unrooted}; use dom::bindings::error::ErrorResult; use dom::document::Document; use dom::element::HTMLHtmlElementTypeId; @@ -34,7 +34,7 @@ impl HTMLHtmlElement { } } - pub fn new(localName: DOMString, document: &JSRef<Document>) -> JS<HTMLHtmlElement> { + pub fn new(localName: DOMString, document: &JSRef<Document>) -> Unrooted<HTMLHtmlElement> { let element = HTMLHtmlElement::new_inherited(localName, document.unrooted()); Node::reflect_node(~element, document, HTMLHtmlElementBinding::Wrap) } diff --git a/src/components/script/dom/htmliframeelement.rs b/src/components/script/dom/htmliframeelement.rs index c037f17f9a5..c157e2ad445 100644 --- a/src/components/script/dom/htmliframeelement.rs +++ b/src/components/script/dom/htmliframeelement.rs @@ -5,7 +5,7 @@ use dom::bindings::codegen::BindingDeclarations::HTMLIFrameElementBinding; use dom::bindings::codegen::InheritTypes::{ElementCast, HTMLIFrameElementDerived, HTMLElementCast}; use dom::bindings::error::ErrorResult; -use dom::bindings::js::{JS, JSRef}; +use dom::bindings::js::{JS, JSRef, Unrooted}; use dom::bindings::trace::Untraceable; use dom::document::Document; use dom::element::{HTMLIFrameElementTypeId, Element}; @@ -74,7 +74,7 @@ impl HTMLIFrameElement { } } - pub fn new(localName: DOMString, document: &JSRef<Document>) -> JS<HTMLIFrameElement> { + pub fn new(localName: DOMString, document: &JSRef<Document>) -> Unrooted<HTMLIFrameElement> { let element = HTMLIFrameElement::new_inherited(localName, document.unrooted()); Node::reflect_node(~element, document, HTMLIFrameElementBinding::Wrap) } @@ -106,12 +106,12 @@ impl HTMLIFrameElement { } pub fn Sandbox(&self, abstract_self: &JSRef<HTMLIFrameElement>) -> DOMString { - let element: JS<Element> = ElementCast::from(&abstract_self.unrooted()); + let element: &JSRef<Element> = ElementCast::from_ref(abstract_self); element.get_string_attribute("sandbox") } pub fn SetSandbox(&mut self, abstract_self: &mut JSRef<HTMLIFrameElement>, sandbox: DOMString) { - let mut element: JS<Element> = ElementCast::from(&abstract_self.unrooted()); + let element: &mut JSRef<Element> = ElementCast::from_mut_ref(abstract_self); element.set_string_attribute("sandbox", sandbox); } @@ -139,11 +139,11 @@ impl HTMLIFrameElement { Ok(()) } - pub fn GetContentDocument(&self) -> Option<JS<Document>> { + pub fn GetContentDocument(&self) -> Option<Unrooted<Document>> { None } - pub fn GetContentWindow(&self) -> Option<JS<Window>> { + pub fn GetContentWindow(&self) -> Option<Unrooted<Window>> { None } @@ -195,15 +195,15 @@ impl HTMLIFrameElement { Ok(()) } - pub fn GetSVGDocument(&self) -> Option<JS<Document>> { + pub fn GetSVGDocument(&self) -> Option<Unrooted<Document>> { None } } -impl VirtualMethods for JS<HTMLIFrameElement> { +impl<'a> VirtualMethods for JSRef<'a, HTMLIFrameElement> { fn super_type(&self) -> Option<~VirtualMethods:> { - let htmlelement: JS<HTMLElement> = HTMLElementCast::from(self); - Some(~htmlelement as ~VirtualMethods:) + let htmlelement: &JSRef<HTMLElement> = HTMLElementCast::from_ref(self); + Some(~htmlelement.clone() as ~VirtualMethods:) } fn after_set_attr(&mut self, name: DOMString, value: DOMString) { diff --git a/src/components/script/dom/htmlimageelement.rs b/src/components/script/dom/htmlimageelement.rs index d986f5d07e8..04528c54283 100644 --- a/src/components/script/dom/htmlimageelement.rs +++ b/src/components/script/dom/htmlimageelement.rs @@ -5,7 +5,7 @@ use dom::bindings::codegen::BindingDeclarations::HTMLImageElementBinding; use dom::bindings::codegen::InheritTypes::{NodeCast, ElementCast, HTMLElementCast, HTMLImageElementDerived}; use dom::bindings::error::ErrorResult; -use dom::bindings::js::{JS, JSRef}; +use dom::bindings::js::{JS, JSRef, Unrooted, RootCollection}; use dom::bindings::trace::Untraceable; use dom::document::Document; use dom::element::{Element, HTMLImageElementTypeId}; @@ -43,7 +43,7 @@ impl HTMLImageElement { } } - pub fn new(localName: DOMString, document: &JSRef<Document>) -> JS<HTMLImageElement> { + pub fn new(localName: DOMString, document: &JSRef<Document>) -> Unrooted<HTMLImageElement> { let element = HTMLImageElement::new_inherited(localName, document.unrooted()); Node::reflect_node(~element, document, HTMLImageElementBinding::Wrap) } @@ -57,9 +57,10 @@ impl HTMLImageElement { /// Makes the local `image` member match the status of the `src` attribute and starts /// prefetching the image. This method must be called after `src` is changed. fn update_image(&mut self, value: Option<DOMString>, url: Option<Url>) { + let roots = RootCollection::new(); let elem = &mut self.htmlelement.element; - let document = elem.node.owner_doc(); - let window = document.get().window.get(); + let document = elem.node.owner_doc().root(&roots); + let window = document.deref().window.root(&roots); let image_cache = &window.image_cache_task; match value { None => { @@ -80,22 +81,22 @@ impl HTMLImageElement { } pub fn Alt(&self, abstract_self: &JSRef<HTMLImageElement>) -> DOMString { - let element: JS<Element> = ElementCast::from(&abstract_self.unrooted()); + let element: &JSRef<Element> = ElementCast::from_ref(abstract_self); element.get_string_attribute("alt") } - pub fn SetAlt(&mut self, abstract_self: &JSRef<HTMLImageElement>, alt: DOMString) { - let mut element: JS<Element> = ElementCast::from(&abstract_self.unrooted()); + pub fn SetAlt(&mut self, abstract_self: &mut JSRef<HTMLImageElement>, alt: DOMString) { + let element: &mut JSRef<Element> = ElementCast::from_mut_ref(abstract_self); element.set_string_attribute("alt", alt) } pub fn Src(&self, abstract_self: &JSRef<HTMLImageElement>) -> DOMString { - let element: JS<Element> = ElementCast::from(&abstract_self.unrooted()); + let element: &JSRef<Element> = ElementCast::from_ref(abstract_self); element.get_string_attribute("src") } pub fn SetSrc(&mut self, abstract_self: &mut JSRef<HTMLImageElement>, src: DOMString) { - let mut element: JS<Element> = ElementCast::from(&abstract_self.unrooted()); + let element: &mut JSRef<Element> = ElementCast::from_mut_ref(abstract_self); element.set_url_attribute("src", src) } @@ -108,44 +109,44 @@ impl HTMLImageElement { } pub fn UseMap(&self, abstract_self: &JSRef<HTMLImageElement>) -> DOMString { - let element: JS<Element> = ElementCast::from(&abstract_self.unrooted()); + let element: &JSRef<Element> = ElementCast::from_ref(abstract_self); element.get_string_attribute("useMap") } pub fn SetUseMap(&mut self, abstract_self: &mut JSRef<HTMLImageElement>, use_map: DOMString) { - let mut element: JS<Element> = ElementCast::from(&abstract_self.unrooted()); + let element: &mut JSRef<Element> = ElementCast::from_mut_ref(abstract_self); element.set_string_attribute("useMap", use_map) } pub fn IsMap(&self, abstract_self: &JSRef<HTMLImageElement>) -> bool { - let element: JS<Element> = ElementCast::from(&abstract_self.unrooted()); + let element: &JSRef<Element> = ElementCast::from_ref(abstract_self); from_str::<bool>(element.get_string_attribute("hspace")).unwrap() } pub fn SetIsMap(&self, abstract_self: &mut JSRef<HTMLImageElement>, is_map: bool) { - let mut element: JS<Element> = ElementCast::from(&abstract_self.unrooted()); + let element: &mut JSRef<Element> = ElementCast::from_mut_ref(abstract_self); element.set_string_attribute("isMap", is_map.to_str()) } pub fn Width(&self, abstract_self: &JSRef<HTMLImageElement>) -> u32 { - let node: JS<Node> = NodeCast::from(&abstract_self.unrooted()); + let node: &JSRef<Node> = NodeCast::from_ref(abstract_self); let rect = node.get_bounding_content_box(); to_px(rect.size.width) as u32 } - pub fn SetWidth(&mut self, abstract_self: &JSRef<HTMLImageElement>, width: u32) { - let mut elem: JS<Element> = ElementCast::from(&abstract_self.unrooted()); + pub fn SetWidth(&mut self, abstract_self: &mut JSRef<HTMLImageElement>, width: u32) { + let elem: &mut JSRef<Element> = ElementCast::from_mut_ref(abstract_self); elem.set_uint_attribute("width", width) } pub fn Height(&self, abstract_self: &JSRef<HTMLImageElement>) -> u32 { - let node: JS<Node> = NodeCast::from(&abstract_self.unrooted()); + let node: &JSRef<Node> = NodeCast::from_ref(abstract_self); let rect = node.get_bounding_content_box(); to_px(rect.size.height) as u32 } - pub fn SetHeight(&mut self, abstract_self: &JSRef<HTMLImageElement>, height: u32) { - let mut elem: JS<Element> = ElementCast::from(&abstract_self.unrooted()); + pub fn SetHeight(&mut self, abstract_self: &mut JSRef<HTMLImageElement>, height: u32) { + let elem: &mut JSRef<Element> = ElementCast::from_mut_ref(abstract_self); elem.set_uint_attribute("height", height) } @@ -162,87 +163,88 @@ impl HTMLImageElement { } pub fn Name(&self, abstract_self: &JSRef<HTMLImageElement>) -> DOMString { - let element: JS<Element> = ElementCast::from(&abstract_self.unrooted()); + let element: &JSRef<Element> = ElementCast::from_ref(abstract_self); element.get_string_attribute("name") } pub fn SetName(&mut self, abstract_self: &mut JSRef<HTMLImageElement>, name: DOMString) { - let mut element: JS<Element> = ElementCast::from(&abstract_self.unrooted()); + let element: &mut JSRef<Element> = ElementCast::from_mut_ref(abstract_self); element.set_string_attribute("name", name) } pub fn Align(&self, abstract_self: &JSRef<HTMLImageElement>) -> DOMString { - let element: JS<Element> = ElementCast::from(&abstract_self.unrooted()); + let element: &JSRef<Element> = ElementCast::from_ref(abstract_self); element.get_string_attribute("longdesc") } pub fn SetAlign(&mut self, abstract_self: &mut JSRef<HTMLImageElement>, align: DOMString) { - let mut element: JS<Element> = ElementCast::from(&abstract_self.unrooted()); + let element: &mut JSRef<Element> = ElementCast::from_mut_ref(abstract_self); element.set_string_attribute("align", align) } pub fn Hspace(&self, abstract_self: &JSRef<HTMLImageElement>) -> u32 { - let element: JS<Element> = ElementCast::from(&abstract_self.unrooted()); + let element: &JSRef<Element> = ElementCast::from_ref(abstract_self); from_str::<u32>(element.get_string_attribute("hspace")).unwrap() } pub fn SetHspace(&mut self, abstract_self: &mut JSRef<HTMLImageElement>, hspace: u32) { - let mut element: JS<Element> = ElementCast::from(&abstract_self.unrooted()); + let element: &mut JSRef<Element> = ElementCast::from_mut_ref(abstract_self); element.set_uint_attribute("hspace", hspace) } pub fn Vspace(&self, abstract_self: &JSRef<HTMLImageElement>) -> u32 { - let element: JS<Element> = ElementCast::from(&abstract_self.unrooted()); + let element: &JSRef<Element> = ElementCast::from_ref(abstract_self); from_str::<u32>(element.get_string_attribute("vspace")).unwrap() } pub fn SetVspace(&mut self, abstract_self: &mut JSRef<HTMLImageElement>, vspace: u32) { - let mut element: JS<Element> = ElementCast::from(&abstract_self.unrooted()); + let element: &mut JSRef<Element> = ElementCast::from_mut_ref(abstract_self); element.set_uint_attribute("vspace", vspace) } pub fn LongDesc(&self, abstract_self: &JSRef<HTMLImageElement>) -> DOMString { - let element: JS<Element> = ElementCast::from(&abstract_self.unrooted()); + let element: &JSRef<Element> = ElementCast::from_ref(abstract_self); element.get_string_attribute("longdesc") } pub fn SetLongDesc(&mut self, abstract_self: &mut JSRef<HTMLImageElement>, longdesc: DOMString) { - let mut element: JS<Element> = ElementCast::from(&abstract_self.unrooted()); + let element: &mut JSRef<Element> = ElementCast::from_mut_ref(abstract_self); element.set_string_attribute("longdesc", longdesc) } pub fn Border(&self, abstract_self: &JSRef<HTMLImageElement>) -> DOMString { - let element: JS<Element> = ElementCast::from(&abstract_self.unrooted()); + let element: &JSRef<Element> = ElementCast::from_ref(abstract_self); element.get_string_attribute("border") } pub fn SetBorder(&mut self, abstract_self: &mut JSRef<HTMLImageElement>, border: DOMString) { - let mut element: JS<Element> = ElementCast::from(&abstract_self.unrooted()); + let element: &mut JSRef<Element> = ElementCast::from_mut_ref(abstract_self); element.set_string_attribute("border", border) } } -impl VirtualMethods for JS<HTMLImageElement> { +impl<'a> VirtualMethods for JSRef<'a, HTMLImageElement> { fn super_type(&self) -> Option<~VirtualMethods:> { - let htmlelement: JS<HTMLElement> = HTMLElementCast::from(self); - Some(~htmlelement as ~VirtualMethods:) + let htmlelement: &JSRef<HTMLElement> = HTMLElementCast::from_ref(self); + Some(~htmlelement.clone() as ~VirtualMethods:) } fn after_set_attr(&mut self, name: DOMString, value: DOMString) { + let roots = RootCollection::new(); match self.super_type() { Some(ref mut s) => s.after_set_attr(name.clone(), value.clone()), _ => (), } if "src" == name { - let window = window_from_node(self); + let window = window_from_node(self).root(&roots); let url = Some(window.get().get_url()); self.get_mut().update_image(Some(value), url); } } fn before_remove_attr(&mut self, name: DOMString, value: DOMString) { - match self.super_type() { + match self.super_type() { Some(ref mut s) => s.before_remove_attr(name.clone(), value.clone()), _ => (), } diff --git a/src/components/script/dom/htmlinputelement.rs b/src/components/script/dom/htmlinputelement.rs index 90914fbc7bb..55d8fc7c1a7 100644 --- a/src/components/script/dom/htmlinputelement.rs +++ b/src/components/script/dom/htmlinputelement.rs @@ -4,7 +4,7 @@ use dom::bindings::codegen::BindingDeclarations::HTMLInputElementBinding; use dom::bindings::codegen::InheritTypes::HTMLInputElementDerived; -use dom::bindings::js::{JS, JSRef}; +use dom::bindings::js::{JS, JSRef, Unrooted}; use dom::bindings::error::{ErrorResult, Fallible}; use dom::document::Document; use dom::element::HTMLInputElementTypeId; @@ -34,7 +34,7 @@ impl HTMLInputElement { } } - pub fn new(localName: DOMString, document: &JSRef<Document>) -> JS<HTMLInputElement> { + pub fn new(localName: DOMString, document: &JSRef<Document>) -> Unrooted<HTMLInputElement> { let element = HTMLInputElement::new_inherited(localName, document.unrooted()); Node::reflect_node(~element, document, HTMLInputElementBinding::Wrap) } diff --git a/src/components/script/dom/htmllabelelement.rs b/src/components/script/dom/htmllabelelement.rs index 5c920fd75eb..dcd080f7f24 100644 --- a/src/components/script/dom/htmllabelelement.rs +++ b/src/components/script/dom/htmllabelelement.rs @@ -4,7 +4,7 @@ use dom::bindings::codegen::BindingDeclarations::HTMLLabelElementBinding; use dom::bindings::codegen::InheritTypes::HTMLLabelElementDerived; -use dom::bindings::js::{JS, JSRef}; +use dom::bindings::js::{JS, JSRef, Unrooted}; use dom::document::Document; use dom::element::HTMLLabelElementTypeId; use dom::eventtarget::{EventTarget, NodeTargetTypeId}; @@ -33,7 +33,7 @@ impl HTMLLabelElement { } } - pub fn new(localName: DOMString, document: &JSRef<Document>) -> JS<HTMLLabelElement> { + pub fn new(localName: DOMString, document: &JSRef<Document>) -> Unrooted<HTMLLabelElement> { let element = HTMLLabelElement::new_inherited(localName, document.unrooted()); Node::reflect_node(~element, document, HTMLLabelElementBinding::Wrap) } diff --git a/src/components/script/dom/htmllegendelement.rs b/src/components/script/dom/htmllegendelement.rs index ee6199808eb..696247f40db 100644 --- a/src/components/script/dom/htmllegendelement.rs +++ b/src/components/script/dom/htmllegendelement.rs @@ -4,7 +4,7 @@ use dom::bindings::codegen::BindingDeclarations::HTMLLegendElementBinding; use dom::bindings::codegen::InheritTypes::HTMLLegendElementDerived; -use dom::bindings::js::{JS, JSRef}; +use dom::bindings::js::{JS, JSRef, Unrooted}; use dom::bindings::error::ErrorResult; use dom::document::Document; use dom::element::HTMLLegendElementTypeId; @@ -34,7 +34,7 @@ impl HTMLLegendElement { } } - pub fn new(localName: DOMString, document: &JSRef<Document>) -> JS<HTMLLegendElement> { + pub fn new(localName: DOMString, document: &JSRef<Document>) -> Unrooted<HTMLLegendElement> { let element = HTMLLegendElement::new_inherited(localName, document.unrooted()); Node::reflect_node(~element, document, HTMLLegendElementBinding::Wrap) } diff --git a/src/components/script/dom/htmllielement.rs b/src/components/script/dom/htmllielement.rs index 2a7501b08e9..d3b625e5987 100644 --- a/src/components/script/dom/htmllielement.rs +++ b/src/components/script/dom/htmllielement.rs @@ -4,7 +4,7 @@ use dom::bindings::codegen::BindingDeclarations::HTMLLIElementBinding; use dom::bindings::codegen::InheritTypes::HTMLLIElementDerived; -use dom::bindings::js::{JS, JSRef}; +use dom::bindings::js::{JS, JSRef, Unrooted}; use dom::bindings::error::ErrorResult; use dom::document::Document; use dom::element::HTMLLIElementTypeId; @@ -34,7 +34,7 @@ impl HTMLLIElement { } } - pub fn new(localName: DOMString, document: &JSRef<Document>) -> JS<HTMLLIElement> { + pub fn new(localName: DOMString, document: &JSRef<Document>) -> Unrooted<HTMLLIElement> { let element = HTMLLIElement::new_inherited(localName, document.unrooted()); Node::reflect_node(~element, document, HTMLLIElementBinding::Wrap) } diff --git a/src/components/script/dom/htmllinkelement.rs b/src/components/script/dom/htmllinkelement.rs index 528ea303a2c..3d474d1af64 100644 --- a/src/components/script/dom/htmllinkelement.rs +++ b/src/components/script/dom/htmllinkelement.rs @@ -4,7 +4,7 @@ use dom::bindings::codegen::BindingDeclarations::HTMLLinkElementBinding; use dom::bindings::codegen::InheritTypes::HTMLLinkElementDerived; -use dom::bindings::js::{JS, JSRef}; +use dom::bindings::js::{JS, JSRef, Unrooted}; use dom::bindings::error::ErrorResult; use dom::document::Document; use dom::element::HTMLLinkElementTypeId; @@ -34,7 +34,7 @@ impl HTMLLinkElement { } } - pub fn new(localName: DOMString, document: &JSRef<Document>) -> JS<HTMLLinkElement> { + pub fn new(localName: DOMString, document: &JSRef<Document>) -> Unrooted<HTMLLinkElement> { let element = HTMLLinkElement::new_inherited(localName, document.unrooted()); Node::reflect_node(~element, document, HTMLLinkElementBinding::Wrap) } diff --git a/src/components/script/dom/htmlmainelement.rs b/src/components/script/dom/htmlmainelement.rs index 74bc99c0149..ad9a2c6af1e 100644 --- a/src/components/script/dom/htmlmainelement.rs +++ b/src/components/script/dom/htmlmainelement.rs @@ -4,7 +4,7 @@ use dom::bindings::codegen::BindingDeclarations::HTMLMainElementBinding; use dom::bindings::codegen::InheritTypes::HTMLMainElementDerived; -use dom::bindings::js::{JS, JSRef}; +use dom::bindings::js::{JS, JSRef, Unrooted}; use dom::document::Document; use dom::element::HTMLMainElementTypeId; use dom::eventtarget::{EventTarget, NodeTargetTypeId}; @@ -33,7 +33,7 @@ impl HTMLMainElement { } } - pub fn new(localName: DOMString, document: &JSRef<Document>) -> JS<HTMLMainElement> { + pub fn new(localName: DOMString, document: &JSRef<Document>) -> Unrooted<HTMLMainElement> { let element = HTMLMainElement::new_inherited(localName, document.unrooted()); Node::reflect_node(~element, document, HTMLMainElementBinding::Wrap) } diff --git a/src/components/script/dom/htmlmapelement.rs b/src/components/script/dom/htmlmapelement.rs index aff393505af..18dfd17e88b 100644 --- a/src/components/script/dom/htmlmapelement.rs +++ b/src/components/script/dom/htmlmapelement.rs @@ -4,7 +4,7 @@ use dom::bindings::codegen::BindingDeclarations::HTMLMapElementBinding; use dom::bindings::codegen::InheritTypes::HTMLMapElementDerived; -use dom::bindings::js::{JS, JSRef, RootCollection}; +use dom::bindings::js::{JS, JSRef, RootCollection, Unrooted}; use dom::bindings::error::ErrorResult; use dom::document::Document; use dom::element::HTMLMapElementTypeId; @@ -35,7 +35,7 @@ impl HTMLMapElement { } } - pub fn new(localName: DOMString, document: &JSRef<Document>) -> JS<HTMLMapElement> { + pub fn new(localName: DOMString, document: &JSRef<Document>) -> Unrooted<HTMLMapElement> { let element = HTMLMapElement::new_inherited(localName, document.unrooted()); Node::reflect_node(~element, document, HTMLMapElementBinding::Wrap) } @@ -50,12 +50,11 @@ impl HTMLMapElement { Ok(()) } - pub fn Areas(&self) -> JS<HTMLCollection> { + pub fn Areas(&self) -> Unrooted<HTMLCollection> { let roots = RootCollection::new(); // FIXME: https://github.com/mozilla/servo/issues/1845 - let doc = self.htmlelement.element.node.owner_doc(); - let doc = doc.get(); - let window = doc.window.root(&roots); - HTMLCollection::new(&window.root_ref(), Static(vec!())) + let doc = self.htmlelement.element.node.owner_doc().root(&roots); + let window = doc.deref().window.root(&roots); + HTMLCollection::new(&*window, Static(vec!())) } } diff --git a/src/components/script/dom/htmlmetaelement.rs b/src/components/script/dom/htmlmetaelement.rs index 191a49f2444..737cc6710fc 100644 --- a/src/components/script/dom/htmlmetaelement.rs +++ b/src/components/script/dom/htmlmetaelement.rs @@ -4,7 +4,7 @@ use dom::bindings::codegen::BindingDeclarations::HTMLMetaElementBinding; use dom::bindings::codegen::InheritTypes::HTMLMetaElementDerived; -use dom::bindings::js::{JS, JSRef}; +use dom::bindings::js::{JS, JSRef, Unrooted}; use dom::bindings::error::ErrorResult; use dom::document::Document; use dom::element::HTMLMetaElementTypeId; @@ -34,7 +34,7 @@ impl HTMLMetaElement { } } - pub fn new(localName: DOMString, document: &JSRef<Document>) -> JS<HTMLMetaElement> { + pub fn new(localName: DOMString, document: &JSRef<Document>) -> Unrooted<HTMLMetaElement> { let element = HTMLMetaElement::new_inherited(localName, document.unrooted()); Node::reflect_node(~element, document, HTMLMetaElementBinding::Wrap) } diff --git a/src/components/script/dom/htmlmeterelement.rs b/src/components/script/dom/htmlmeterelement.rs index 19bac1c9797..9d5f699ae14 100644 --- a/src/components/script/dom/htmlmeterelement.rs +++ b/src/components/script/dom/htmlmeterelement.rs @@ -4,7 +4,7 @@ use dom::bindings::codegen::BindingDeclarations::HTMLMeterElementBinding; use dom::bindings::codegen::InheritTypes::HTMLMeterElementDerived; -use dom::bindings::js::{JS, JSRef}; +use dom::bindings::js::{JS, JSRef, Unrooted}; use dom::bindings::error::ErrorResult; use dom::document::Document; use dom::element::HTMLMeterElementTypeId; @@ -34,7 +34,7 @@ impl HTMLMeterElement { } } - pub fn new(localName: DOMString, document: &JSRef<Document>) -> JS<HTMLMeterElement> { + pub fn new(localName: DOMString, document: &JSRef<Document>) -> Unrooted<HTMLMeterElement> { let element = HTMLMeterElement::new_inherited(localName, document.unrooted()); Node::reflect_node(~element, document, HTMLMeterElementBinding::Wrap) } diff --git a/src/components/script/dom/htmlmodelement.rs b/src/components/script/dom/htmlmodelement.rs index b934ef74b86..41ed8244a9d 100644 --- a/src/components/script/dom/htmlmodelement.rs +++ b/src/components/script/dom/htmlmodelement.rs @@ -4,7 +4,7 @@ use dom::bindings::codegen::BindingDeclarations::HTMLModElementBinding; use dom::bindings::codegen::InheritTypes::HTMLModElementDerived; -use dom::bindings::js::{JS, JSRef}; +use dom::bindings::js::{JS, JSRef, Unrooted}; use dom::bindings::error::ErrorResult; use dom::document::Document; use dom::element::HTMLModElementTypeId; @@ -34,7 +34,7 @@ impl HTMLModElement { } } - pub fn new(localName: DOMString, document: &JSRef<Document>) -> JS<HTMLModElement> { + pub fn new(localName: DOMString, document: &JSRef<Document>) -> Unrooted<HTMLModElement> { let element = HTMLModElement::new_inherited(localName, document.unrooted()); Node::reflect_node(~element, document, HTMLModElementBinding::Wrap) } diff --git a/src/components/script/dom/htmlobjectelement.rs b/src/components/script/dom/htmlobjectelement.rs index f3f48cba313..4814ac4b337 100644 --- a/src/components/script/dom/htmlobjectelement.rs +++ b/src/components/script/dom/htmlobjectelement.rs @@ -5,7 +5,7 @@ use dom::bindings::codegen::BindingDeclarations::HTMLObjectElementBinding; use dom::bindings::codegen::InheritTypes::HTMLObjectElementDerived; use dom::bindings::codegen::InheritTypes::{ElementCast, HTMLElementCast}; -use dom::bindings::js::{JS, JSRef, RootCollection}; +use dom::bindings::js::{JS, JSRef, RootCollection, Unrooted}; use dom::bindings::error::ErrorResult; use dom::document::Document; use dom::element::{Element, HTMLObjectElementTypeId}; @@ -47,7 +47,7 @@ impl HTMLObjectElement { } } - pub fn new(localName: DOMString, document: &JSRef<Document>) -> JS<HTMLObjectElement> { + pub fn new(localName: DOMString, document: &JSRef<Document>) -> Unrooted<HTMLObjectElement> { let element = HTMLObjectElement::new_inherited(localName, document.unrooted()); Node::reflect_node(~element, document, HTMLObjectElementBinding::Wrap) } @@ -57,15 +57,16 @@ trait ProcessDataURL { fn process_data_url(&mut self, image_cache: ImageCacheTask, url: Option<Url>); } -impl ProcessDataURL for JS<HTMLObjectElement> { +impl<'a> ProcessDataURL for JSRef<'a, HTMLObjectElement> { // Makes the local `data` member match the status of the `data` attribute and starts /// prefetching the image. This method must be called after `data` is changed. fn process_data_url(&mut self, image_cache: ImageCacheTask, url: Option<Url>) { - let elem: JS<Element> = ElementCast::from(self); + let roots = RootCollection::new(); + let elem: &JSRef<Element> = ElementCast::from_ref(self); // TODO: support other values - match (elem.get_attribute(Null, "type").map(|x| x.get().Value()), - elem.get_attribute(Null, "data").map(|x| x.get().Value())) { + match (elem.get_attribute(Null, "type").map(|x| x.root(&roots).Value()), + elem.get_attribute(Null, "data").map(|x| x.root(&roots).Value())) { (None, Some(uri)) => { if is_image_data(uri) { let data_url = parse_url(uri, url); @@ -111,7 +112,7 @@ impl HTMLObjectElement { Ok(()) } - pub fn GetForm(&self) -> Option<JS<HTMLFormElement>> { + pub fn GetForm(&self) -> Option<Unrooted<HTMLFormElement>> { None } @@ -131,11 +132,11 @@ impl HTMLObjectElement { Ok(()) } - pub fn GetContentDocument(&self) -> Option<JS<Document>> { + pub fn GetContentDocument(&self) -> Option<Unrooted<Document>> { None } - pub fn GetContentWindow(&self) -> Option<JS<Window>> { + pub fn GetContentWindow(&self) -> Option<Unrooted<Window>> { None } @@ -143,11 +144,10 @@ impl HTMLObjectElement { false } - pub fn Validity(&self) -> JS<ValidityState> { + pub fn Validity(&self) -> Unrooted<ValidityState> { let roots = RootCollection::new(); - let doc = self.htmlelement.element.node.owner_doc(); - let doc = doc.get(); - let window = doc.window.root(&roots); + let doc = self.htmlelement.element.node.owner_doc().root(&roots); + let window = doc.deref().window.root(&roots); ValidityState::new(&window.root_ref()) } @@ -242,25 +242,26 @@ impl HTMLObjectElement { Ok(()) } - pub fn GetSVGDocument(&self) -> Option<JS<Document>> { + pub fn GetSVGDocument(&self) -> Option<Unrooted<Document>> { None } } -impl VirtualMethods for JS<HTMLObjectElement> { +impl<'a> VirtualMethods for JSRef<'a, HTMLObjectElement> { fn super_type(&self) -> Option<~VirtualMethods:> { - let htmlelement: JS<HTMLElement> = HTMLElementCast::from(self); - Some(~htmlelement as ~VirtualMethods:) + let htmlelement: &JSRef<HTMLElement> = HTMLElementCast::from_ref(self); + Some(~htmlelement.clone() as ~VirtualMethods:) } fn after_set_attr(&mut self, name: DOMString, value: DOMString) { + let roots = RootCollection::new(); match self.super_type() { Some(ref mut s) => s.after_set_attr(name.clone(), value), _ => (), } if "data" == name { - let window = window_from_node(self); + let window = window_from_node(self).root(&roots); let url = Some(window.get().get_url()); self.process_data_url(window.get().image_cache_task.clone(), url); } diff --git a/src/components/script/dom/htmlolistelement.rs b/src/components/script/dom/htmlolistelement.rs index a62acc013c6..1330e2cbd40 100644 --- a/src/components/script/dom/htmlolistelement.rs +++ b/src/components/script/dom/htmlolistelement.rs @@ -4,7 +4,7 @@ use dom::bindings::codegen::BindingDeclarations::HTMLOListElementBinding; use dom::bindings::codegen::InheritTypes::HTMLOListElementDerived; -use dom::bindings::js::{JS, JSRef}; +use dom::bindings::js::{JS, JSRef, Unrooted}; use dom::bindings::error::ErrorResult; use dom::document::Document; use dom::element::HTMLOListElementTypeId; @@ -34,7 +34,7 @@ impl HTMLOListElement { } } - pub fn new(localName: DOMString, document: &JSRef<Document>) -> JS<HTMLOListElement> { + pub fn new(localName: DOMString, document: &JSRef<Document>) -> Unrooted<HTMLOListElement> { let element = HTMLOListElement::new_inherited(localName, document.unrooted()); Node::reflect_node(~element, document, HTMLOListElementBinding::Wrap) } diff --git a/src/components/script/dom/htmloptgroupelement.rs b/src/components/script/dom/htmloptgroupelement.rs index 3ef4df88ab9..d5eab9bec46 100644 --- a/src/components/script/dom/htmloptgroupelement.rs +++ b/src/components/script/dom/htmloptgroupelement.rs @@ -4,7 +4,7 @@ use dom::bindings::codegen::BindingDeclarations::HTMLOptGroupElementBinding; use dom::bindings::codegen::InheritTypes::HTMLOptGroupElementDerived; -use dom::bindings::js::{JS, JSRef}; +use dom::bindings::js::{JS, JSRef, Unrooted}; use dom::bindings::error::ErrorResult; use dom::document::Document; use dom::element::HTMLOptGroupElementTypeId; @@ -34,7 +34,7 @@ impl HTMLOptGroupElement { } } - pub fn new(localName: DOMString, document: &JSRef<Document>) -> JS<HTMLOptGroupElement> { + pub fn new(localName: DOMString, document: &JSRef<Document>) -> Unrooted<HTMLOptGroupElement> { let element = HTMLOptGroupElement::new_inherited(localName, document.unrooted()); Node::reflect_node(~element, document, HTMLOptGroupElementBinding::Wrap) } diff --git a/src/components/script/dom/htmloptionelement.rs b/src/components/script/dom/htmloptionelement.rs index 5119ce17b73..bf1f594009e 100644 --- a/src/components/script/dom/htmloptionelement.rs +++ b/src/components/script/dom/htmloptionelement.rs @@ -4,7 +4,7 @@ use dom::bindings::codegen::BindingDeclarations::HTMLOptionElementBinding; use dom::bindings::codegen::InheritTypes::HTMLOptionElementDerived; -use dom::bindings::js::{JS, JSRef}; +use dom::bindings::js::{JS, JSRef, Unrooted}; use dom::bindings::error::ErrorResult; use dom::document::Document; use dom::element::HTMLOptionElementTypeId; @@ -35,7 +35,7 @@ impl HTMLOptionElement { } } - pub fn new(localName: DOMString, document: &JSRef<Document>) -> JS<HTMLOptionElement> { + pub fn new(localName: DOMString, document: &JSRef<Document>) -> Unrooted<HTMLOptionElement> { let element = HTMLOptionElement::new_inherited(localName, document.unrooted()); Node::reflect_node(~element, document, HTMLOptionElementBinding::Wrap) } @@ -50,7 +50,7 @@ impl HTMLOptionElement { Ok(()) } - pub fn GetForm(&self) -> Option<JS<HTMLFormElement>> { + pub fn GetForm(&self) -> Option<Unrooted<HTMLFormElement>> { None } diff --git a/src/components/script/dom/htmloutputelement.rs b/src/components/script/dom/htmloutputelement.rs index 4f5dae6d8c0..a72d9410d20 100644 --- a/src/components/script/dom/htmloutputelement.rs +++ b/src/components/script/dom/htmloutputelement.rs @@ -4,7 +4,7 @@ use dom::bindings::codegen::BindingDeclarations::HTMLOutputElementBinding; use dom::bindings::codegen::InheritTypes::HTMLOutputElementDerived; -use dom::bindings::js::{JS, JSRef, RootCollection}; +use dom::bindings::js::{JS, JSRef, RootCollection, Unrooted}; use dom::bindings::error::ErrorResult; use dom::document::Document; use dom::element::HTMLOutputElementTypeId; @@ -36,14 +36,14 @@ impl HTMLOutputElement { } } - pub fn new(localName: DOMString, document: &JSRef<Document>) -> JS<HTMLOutputElement> { + pub fn new(localName: DOMString, document: &JSRef<Document>) -> Unrooted<HTMLOutputElement> { let element = HTMLOutputElement::new_inherited(localName, document.unrooted()); Node::reflect_node(~element, document, HTMLOutputElementBinding::Wrap) } } impl HTMLOutputElement { - pub fn GetForm(&self) -> Option<JS<HTMLFormElement>> { + pub fn GetForm(&self) -> Option<Unrooted<HTMLFormElement>> { None } @@ -82,12 +82,11 @@ impl HTMLOutputElement { pub fn SetWillValidate(&mut self, _will_validate: bool) { } - pub fn Validity(&self) -> JS<ValidityState> { + pub fn Validity(&self) -> Unrooted<ValidityState> { let roots = RootCollection::new(); - let doc = self.htmlelement.element.node.owner_doc(); - let doc = doc.get(); - let window = doc.window.root(&roots); - ValidityState::new(&window.root_ref()) + let doc = self.htmlelement.element.node.owner_doc().root(&roots); + let window = doc.deref().window.root(&roots); + ValidityState::new(&*window) } pub fn SetValidity(&mut self, _validity: JS<ValidityState>) { diff --git a/src/components/script/dom/htmlparagraphelement.rs b/src/components/script/dom/htmlparagraphelement.rs index b473a81613e..d5dafd6abda 100644 --- a/src/components/script/dom/htmlparagraphelement.rs +++ b/src/components/script/dom/htmlparagraphelement.rs @@ -4,7 +4,7 @@ use dom::bindings::codegen::BindingDeclarations::HTMLParagraphElementBinding; use dom::bindings::codegen::InheritTypes::HTMLParagraphElementDerived; -use dom::bindings::js::{JS, JSRef}; +use dom::bindings::js::{JS, JSRef, Unrooted}; use dom::bindings::error::ErrorResult; use dom::document::Document; use dom::element::HTMLParagraphElementTypeId; @@ -34,7 +34,7 @@ impl HTMLParagraphElement { } } - pub fn new(localName: DOMString, document: &JSRef<Document>) -> JS<HTMLParagraphElement> { + pub fn new(localName: DOMString, document: &JSRef<Document>) -> Unrooted<HTMLParagraphElement> { let element = HTMLParagraphElement::new_inherited(localName, document.unrooted()); Node::reflect_node(~element, document, HTMLParagraphElementBinding::Wrap) } diff --git a/src/components/script/dom/htmlparamelement.rs b/src/components/script/dom/htmlparamelement.rs index c33b68fc932..db4d9ec1b89 100644 --- a/src/components/script/dom/htmlparamelement.rs +++ b/src/components/script/dom/htmlparamelement.rs @@ -4,7 +4,7 @@ use dom::bindings::codegen::BindingDeclarations::HTMLParamElementBinding; use dom::bindings::codegen::InheritTypes::HTMLParamElementDerived; -use dom::bindings::js::{JS, JSRef}; +use dom::bindings::js::{JS, JSRef, Unrooted}; use dom::bindings::error::ErrorResult; use dom::document::Document; use dom::element::HTMLParamElementTypeId; @@ -34,7 +34,7 @@ impl HTMLParamElement { } } - pub fn new(localName: DOMString, document: &JSRef<Document>) -> JS<HTMLParamElement> { + pub fn new(localName: DOMString, document: &JSRef<Document>) -> Unrooted<HTMLParamElement> { let element = HTMLParamElement::new_inherited(localName, document.unrooted()); Node::reflect_node(~element, document, HTMLParamElementBinding::Wrap) } diff --git a/src/components/script/dom/htmlpreelement.rs b/src/components/script/dom/htmlpreelement.rs index cfbc2ddc3fe..e2c404074bd 100644 --- a/src/components/script/dom/htmlpreelement.rs +++ b/src/components/script/dom/htmlpreelement.rs @@ -4,7 +4,7 @@ use dom::bindings::codegen::BindingDeclarations::HTMLPreElementBinding; use dom::bindings::codegen::InheritTypes::HTMLPreElementDerived; -use dom::bindings::js::{JS, JSRef}; +use dom::bindings::js::{JS, JSRef, Unrooted}; use dom::bindings::error::ErrorResult; use dom::document::Document; use dom::element::HTMLPreElementTypeId; @@ -34,7 +34,7 @@ impl HTMLPreElement { } } - pub fn new(localName: DOMString, document: &JSRef<Document>) -> JS<HTMLPreElement> { + pub fn new(localName: DOMString, document: &JSRef<Document>) -> Unrooted<HTMLPreElement> { let element = HTMLPreElement::new_inherited(localName, document.unrooted()); Node::reflect_node(~element, document, HTMLPreElementBinding::Wrap) } diff --git a/src/components/script/dom/htmlprogresselement.rs b/src/components/script/dom/htmlprogresselement.rs index ec76ab7d41d..024025afa6d 100644 --- a/src/components/script/dom/htmlprogresselement.rs +++ b/src/components/script/dom/htmlprogresselement.rs @@ -4,7 +4,7 @@ use dom::bindings::codegen::BindingDeclarations::HTMLProgressElementBinding; use dom::bindings::codegen::InheritTypes::HTMLProgressElementDerived; -use dom::bindings::js::{JS, JSRef}; +use dom::bindings::js::{JS, JSRef, Unrooted}; use dom::bindings::error::{ErrorResult, Fallible}; use dom::document::Document; use dom::element::HTMLProgressElementTypeId; @@ -34,7 +34,7 @@ impl HTMLProgressElement { } } - pub fn new(localName: DOMString, document: &JSRef<Document>) -> JS<HTMLProgressElement> { + pub fn new(localName: DOMString, document: &JSRef<Document>) -> Unrooted<HTMLProgressElement> { let element = HTMLProgressElement::new_inherited(localName, document.unrooted()); Node::reflect_node(~element, document, HTMLProgressElementBinding::Wrap) } diff --git a/src/components/script/dom/htmlquoteelement.rs b/src/components/script/dom/htmlquoteelement.rs index 0ec36d39711..9c67c2ac2f4 100644 --- a/src/components/script/dom/htmlquoteelement.rs +++ b/src/components/script/dom/htmlquoteelement.rs @@ -4,7 +4,7 @@ use dom::bindings::codegen::BindingDeclarations::HTMLQuoteElementBinding; use dom::bindings::codegen::InheritTypes::HTMLQuoteElementDerived; -use dom::bindings::js::{JS, JSRef}; +use dom::bindings::js::{JS, JSRef, Unrooted}; use dom::bindings::error::ErrorResult; use dom::document::Document; use dom::element::HTMLQuoteElementTypeId; @@ -34,7 +34,7 @@ impl HTMLQuoteElement { } } - pub fn new(localName: DOMString, document: &JSRef<Document>) -> JS<HTMLQuoteElement> { + pub fn new(localName: DOMString, document: &JSRef<Document>) -> Unrooted<HTMLQuoteElement> { let element = HTMLQuoteElement::new_inherited(localName, document.unrooted()); Node::reflect_node(~element, document, HTMLQuoteElementBinding::Wrap) } diff --git a/src/components/script/dom/htmlscriptelement.rs b/src/components/script/dom/htmlscriptelement.rs index 3be3739542a..808b05a12cf 100644 --- a/src/components/script/dom/htmlscriptelement.rs +++ b/src/components/script/dom/htmlscriptelement.rs @@ -5,7 +5,7 @@ use dom::bindings::codegen::BindingDeclarations::HTMLScriptElementBinding; use dom::bindings::codegen::InheritTypes::HTMLScriptElementDerived; use dom::bindings::codegen::InheritTypes::ElementCast; -use dom::bindings::js::{JS, JSRef}; +use dom::bindings::js::{JS, JSRef, Unrooted}; use dom::bindings::error::ErrorResult; use dom::document::Document; use dom::element::{HTMLScriptElementTypeId, Element, AttributeHandlers}; @@ -35,7 +35,7 @@ impl HTMLScriptElement { } } - pub fn new(localName: DOMString, document: &JSRef<Document>) -> JS<HTMLScriptElement> { + pub fn new(localName: DOMString, document: &JSRef<Document>) -> Unrooted<HTMLScriptElement> { let element = HTMLScriptElement::new_inherited(localName, document.unrooted()); Node::reflect_node(~element, document, HTMLScriptElementBinding::Wrap) } @@ -43,7 +43,7 @@ impl HTMLScriptElement { impl HTMLScriptElement { pub fn Src(&self, abstract_self: &JSRef<HTMLScriptElement>) -> DOMString { - let element: JS<Element> = ElementCast::from(&abstract_self.unrooted()); + let element: &JSRef<Element> = ElementCast::from_ref(abstract_self); element.get_url_attribute("src") } diff --git a/src/components/script/dom/htmlselectelement.rs b/src/components/script/dom/htmlselectelement.rs index 53a738e1a97..666cb529774 100644 --- a/src/components/script/dom/htmlselectelement.rs +++ b/src/components/script/dom/htmlselectelement.rs @@ -5,7 +5,7 @@ use dom::bindings::codegen::BindingDeclarations::HTMLSelectElementBinding; use dom::bindings::codegen::InheritTypes::HTMLSelectElementDerived; use dom::bindings::codegen::UnionTypes::{HTMLElementOrLong, HTMLOptionElementOrHTMLOptGroupElement}; -use dom::bindings::js::{JS, JSRef, RootCollection}; +use dom::bindings::js::{JS, JSRef, RootCollection, Unrooted}; use dom::bindings::error::ErrorResult; use dom::document::Document; use dom::element::{Element, HTMLSelectElementTypeId}; @@ -38,7 +38,7 @@ impl HTMLSelectElement { } } - pub fn new(localName: DOMString, document: &JSRef<Document>) -> JS<HTMLSelectElement> { + pub fn new(localName: DOMString, document: &JSRef<Document>) -> Unrooted<HTMLSelectElement> { let element = HTMLSelectElement::new_inherited(localName, document.unrooted()); Node::reflect_node(~element, document, HTMLSelectElementBinding::Wrap) } @@ -61,7 +61,7 @@ impl HTMLSelectElement { Ok(()) } - pub fn GetForm(&self) -> Option<JS<HTMLFormElement>> { + pub fn GetForm(&self) -> Option<Unrooted<HTMLFormElement>> { None } @@ -109,15 +109,15 @@ impl HTMLSelectElement { Ok(()) } - pub fn Item(&self, _index: u32) -> Option<JS<Element>> { + pub fn Item(&self, _index: u32) -> Option<Unrooted<Element>> { None } - pub fn NamedItem(&self, _name: DOMString) -> Option<JS<HTMLOptionElement>> { + pub fn NamedItem(&self, _name: DOMString) -> Option<Unrooted<HTMLOptionElement>> { None } - pub fn IndexedGetter(&self, _index: u32, _found: &mut bool) -> Option<JS<Element>> { + pub fn IndexedGetter(&self, _index: u32, _found: &mut bool) -> Option<Unrooted<Element>> { None } @@ -153,12 +153,11 @@ impl HTMLSelectElement { pub fn SetWillValidate(&mut self, _will_validate: bool) { } - pub fn Validity(&self) -> JS<ValidityState> { + pub fn Validity(&self) -> Unrooted<ValidityState> { let roots = RootCollection::new(); - let doc = self.htmlelement.element.node.owner_doc(); - let doc = doc.get(); - let window = doc.window.root(&roots); - ValidityState::new(&window.root_ref()) + let doc = self.htmlelement.element.node.owner_doc().root(&roots); + let window = doc.deref().window.root(&roots); + ValidityState::new(&*window) } pub fn SetValidity(&mut self, _validity: JS<ValidityState>) { diff --git a/src/components/script/dom/htmlserializer.rs b/src/components/script/dom/htmlserializer.rs index e99982822ed..55c1ba03d9e 100644 --- a/src/components/script/dom/htmlserializer.rs +++ b/src/components/script/dom/htmlserializer.rs @@ -4,15 +4,15 @@ use servo_util::namespace; use dom::attr::Attr; -use dom::bindings::codegen::InheritTypes::{ElementCast, TextCast, CommentCast}; +use dom::bindings::codegen::InheritTypes::{ElementCast, TextCast, CommentCast, NodeCast}; use dom::bindings::codegen::InheritTypes::{DocumentTypeCast, CharacterDataCast}; use dom::bindings::codegen::InheritTypes::ProcessingInstructionCast; -use dom::bindings::js::{JS, JSRef, RootCollection}; +use dom::bindings::js::{JSRef, RootCollection}; use dom::characterdata::CharacterData; use dom::comment::Comment; use dom::documenttype::DocumentType; use dom::element::Element; -use dom::node::NodeIterator; +use dom::node::{Node, NodeIterator}; use dom::node::{DoctypeNodeTypeId, DocumentFragmentNodeTypeId, CommentNodeTypeId}; use dom::node::{DocumentNodeTypeId, ElementNodeTypeId, ProcessingInstructionNodeTypeId}; use dom::node::{TextNodeTypeId, NodeHelpers}; @@ -20,7 +20,6 @@ use dom::processinginstruction::ProcessingInstruction; use dom::text::Text; pub fn serialize(iterator: &mut NodeIterator) -> ~str { - let roots = RootCollection::new(); let mut html = ~""; let mut open_elements: Vec<~str> = vec!(); @@ -31,29 +30,25 @@ pub fn serialize(iterator: &mut NodeIterator) -> ~str { html.push_str( match node.type_id() { ElementNodeTypeId(..) => { - let elem: JS<Element> = ElementCast::to(&node).unwrap(); - let elem = elem.root(&roots); - serialize_elem(&elem.root_ref(), &mut open_elements) + let elem: &JSRef<Element> = ElementCast::to_ref(&node).unwrap(); + serialize_elem(elem, &mut open_elements) } CommentNodeTypeId => { - let comment: JS<Comment> = CommentCast::to(&node).unwrap(); - let comment = comment.root(&roots); - serialize_comment(&comment.root_ref()) + let comment: &JSRef<Comment> = CommentCast::to_ref(&node).unwrap(); + serialize_comment(comment) } TextNodeTypeId => { - let text: JS<Text> = TextCast::to(&node).unwrap(); - let text = text.root(&roots); - serialize_text(&text.root_ref()) + let text: &JSRef<Text> = TextCast::to_ref(&node).unwrap(); + serialize_text(text) } DoctypeNodeTypeId => { - let doctype: JS<DocumentType> = DocumentTypeCast::to(&node).unwrap(); - let doctype = doctype.root(&roots); - serialize_doctype(&doctype.root_ref()) + let doctype: &JSRef<DocumentType> = DocumentTypeCast::to_ref(&node).unwrap(); + serialize_doctype(doctype) } ProcessingInstructionNodeTypeId => { - let processing_instruction: JS<ProcessingInstruction> = ProcessingInstructionCast::to(&node).unwrap(); - let processing_instruction = processing_instruction.root(&roots); - serialize_processing_instruction(&processing_instruction.root_ref()) + let processing_instruction: &JSRef<ProcessingInstruction> = + ProcessingInstructionCast::to_ref(&node).unwrap(); + serialize_processing_instruction(processing_instruction) } DocumentFragmentNodeTypeId => { ~"" @@ -75,9 +70,11 @@ fn serialize_comment(comment: &JSRef<Comment>) -> ~str { } fn serialize_text(text: &JSRef<Text>) -> ~str { - match text.get().characterdata.node.parent_node { + let roots = RootCollection::new(); + let text_node: &JSRef<Node> = NodeCast::from_ref(text); + match text_node.parent_node().map(|node| node.root(&roots)) { Some(ref parent) if parent.is_element() => { - let elem: JS<Element> = ElementCast::to(parent).unwrap(); + let elem: &JSRef<Element> = ElementCast::to_ref(&**parent).unwrap(); match elem.get().local_name.as_slice() { "style" | "script" | "xmp" | "iframe" | "noembed" | "noframes" | "plaintext" | @@ -104,14 +101,15 @@ fn serialize_elem(elem: &JSRef<Element>, open_elements: &mut Vec<~str>) -> ~str let mut rv = ~"<" + elem.get().local_name; for attr in elem.get().attrs.iter() { let attr = attr.root(&roots); - rv.push_str(serialize_attr(&attr.root_ref())); + rv.push_str(serialize_attr(&*attr)); }; rv.push_str(">"); match elem.get().local_name.as_slice() { "pre" | "listing" | "textarea" if elem.get().namespace == namespace::HTML => { - match elem.get().node.first_child { + let node: &JSRef<Node> = NodeCast::from_ref(elem); + match node.first_child().map(|child| child.root(&roots)) { Some(ref child) if child.is_text() => { - let text: JS<CharacterData> = CharacterDataCast::to(child).unwrap(); + let text: &JSRef<CharacterData> = CharacterDataCast::to_ref(&**child).unwrap(); if text.get().data.len() > 0 && text.get().data[0] == 0x0A as u8 { rv.push_str("\x0A"); } diff --git a/src/components/script/dom/htmlsourceelement.rs b/src/components/script/dom/htmlsourceelement.rs index 8db513bfbd2..ef7ec5c9108 100644 --- a/src/components/script/dom/htmlsourceelement.rs +++ b/src/components/script/dom/htmlsourceelement.rs @@ -4,7 +4,7 @@ use dom::bindings::codegen::BindingDeclarations::HTMLSourceElementBinding; use dom::bindings::codegen::InheritTypes::HTMLSourceElementDerived; -use dom::bindings::js::{JS, JSRef}; +use dom::bindings::js::{JS, JSRef, Unrooted}; use dom::bindings::error::ErrorResult; use dom::document::Document; use dom::element::HTMLSourceElementTypeId; @@ -34,7 +34,7 @@ impl HTMLSourceElement { } } - pub fn new(localName: DOMString, document: &JSRef<Document>) -> JS<HTMLSourceElement> { + pub fn new(localName: DOMString, document: &JSRef<Document>) -> Unrooted<HTMLSourceElement> { let element = HTMLSourceElement::new_inherited(localName, document.unrooted()); Node::reflect_node(~element, document, HTMLSourceElementBinding::Wrap) } diff --git a/src/components/script/dom/htmlspanelement.rs b/src/components/script/dom/htmlspanelement.rs index 20e95ae4b8d..3867fa591de 100644 --- a/src/components/script/dom/htmlspanelement.rs +++ b/src/components/script/dom/htmlspanelement.rs @@ -4,7 +4,7 @@ use dom::bindings::codegen::BindingDeclarations::HTMLSpanElementBinding; use dom::bindings::codegen::InheritTypes::HTMLSpanElementDerived; -use dom::bindings::js::{JS, JSRef}; +use dom::bindings::js::{JS, JSRef, Unrooted}; use dom::document::Document; use dom::element::HTMLSpanElementTypeId; use dom::eventtarget::{EventTarget, NodeTargetTypeId}; @@ -33,7 +33,7 @@ impl HTMLSpanElement { } } - pub fn new(localName: DOMString, document: &JSRef<Document>) -> JS<HTMLSpanElement> { + pub fn new(localName: DOMString, document: &JSRef<Document>) -> Unrooted<HTMLSpanElement> { let element = HTMLSpanElement::new_inherited(localName, document.unrooted()); Node::reflect_node(~element, document, HTMLSpanElementBinding::Wrap) } diff --git a/src/components/script/dom/htmlstyleelement.rs b/src/components/script/dom/htmlstyleelement.rs index be43a40f27d..ec2a997586b 100644 --- a/src/components/script/dom/htmlstyleelement.rs +++ b/src/components/script/dom/htmlstyleelement.rs @@ -4,7 +4,7 @@ use dom::bindings::codegen::BindingDeclarations::HTMLStyleElementBinding; use dom::bindings::codegen::InheritTypes::{HTMLElementCast, HTMLStyleElementDerived, NodeCast}; -use dom::bindings::js::{JS, JSRef, RootCollection}; +use dom::bindings::js::{JS, JSRef, RootCollection, Unrooted}; use dom::bindings::error::ErrorResult; use dom::document::Document; use dom::element::HTMLStyleElementTypeId; @@ -37,7 +37,7 @@ impl HTMLStyleElement { } } - pub fn new(localName: DOMString, document: &JSRef<Document>) -> JS<HTMLStyleElement> { + pub fn new(localName: DOMString, document: &JSRef<Document>) -> Unrooted<HTMLStyleElement> { let element = HTMLStyleElement::new_inherited(localName, document.unrooted()); Node::reflect_node(~element, document, HTMLStyleElementBinding::Wrap) } @@ -80,28 +80,27 @@ pub trait StyleElementHelpers { fn parse_own_css(&self); } -impl StyleElementHelpers for JS<HTMLStyleElement> { +impl<'a> StyleElementHelpers for JSRef<'a, HTMLStyleElement> { fn parse_own_css(&self) { let roots = RootCollection::new(); - let node: JS<Node> = NodeCast::from(self); - let node_root = node.root(&roots); - let win = window_from_node(&node); + let node: &JSRef<Node> = NodeCast::from_ref(self); + let win = window_from_node(node).root(&roots); let url = win.get().page().get_url(); - let data = node.get().GetTextContent(&node_root.root_ref()).expect("Element.textContent must be a string"); + let data = node.get().GetTextContent(node).expect("Element.textContent must be a string"); let sheet = parse_inline_css(url, data); let LayoutChan(ref layout_chan) = *win.get().page().layout_chan; layout_chan.send(AddStylesheetMsg(sheet)); } } -impl VirtualMethods for JS<HTMLStyleElement> { +impl<'a> VirtualMethods for JSRef<'a, HTMLStyleElement> { fn super_type(&self) -> Option<~VirtualMethods:> { - let htmlelement: JS<HTMLElement> = HTMLElementCast::from(self); - Some(~htmlelement as ~VirtualMethods:) + let htmlelement: &JSRef<HTMLElement> = HTMLElementCast::from_ref(self); + Some(~htmlelement.clone() as ~VirtualMethods:) } - fn child_inserted(&mut self, child: &JS<Node>) { + fn child_inserted(&mut self, child: &JSRef<Node>) { match self.super_type() { Some(ref mut s) => s.child_inserted(child), _ => (), diff --git a/src/components/script/dom/htmltablecaptionelement.rs b/src/components/script/dom/htmltablecaptionelement.rs index 6aa88d6c05a..ba83cd93ae8 100644 --- a/src/components/script/dom/htmltablecaptionelement.rs +++ b/src/components/script/dom/htmltablecaptionelement.rs @@ -4,7 +4,7 @@ use dom::bindings::codegen::BindingDeclarations::HTMLTableCaptionElementBinding; use dom::bindings::codegen::InheritTypes::HTMLTableCaptionElementDerived; -use dom::bindings::js::{JS, JSRef}; +use dom::bindings::js::{JS, JSRef, Unrooted}; use dom::bindings::error::ErrorResult; use dom::document::Document; use dom::element::HTMLTableCaptionElementTypeId; @@ -34,7 +34,7 @@ impl HTMLTableCaptionElement { } } - pub fn new(localName: DOMString, document: &JSRef<Document>) -> JS<HTMLTableCaptionElement> { + pub fn new(localName: DOMString, document: &JSRef<Document>) -> Unrooted<HTMLTableCaptionElement> { let element = HTMLTableCaptionElement::new_inherited(localName, document.unrooted()); Node::reflect_node(~element, document, HTMLTableCaptionElementBinding::Wrap) } diff --git a/src/components/script/dom/htmltablecolelement.rs b/src/components/script/dom/htmltablecolelement.rs index cc967f14c49..c8b8c74ad6b 100644 --- a/src/components/script/dom/htmltablecolelement.rs +++ b/src/components/script/dom/htmltablecolelement.rs @@ -4,7 +4,7 @@ use dom::bindings::codegen::BindingDeclarations::HTMLTableColElementBinding; use dom::bindings::codegen::InheritTypes::HTMLTableColElementDerived; -use dom::bindings::js::{JS, JSRef}; +use dom::bindings::js::{JS, JSRef, Unrooted}; use dom::bindings::error::ErrorResult; use dom::document::Document; use dom::element::HTMLTableColElementTypeId; @@ -34,7 +34,7 @@ impl HTMLTableColElement { } } - pub fn new(localName: DOMString, document: &JSRef<Document>) -> JS<HTMLTableColElement> { + pub fn new(localName: DOMString, document: &JSRef<Document>) -> Unrooted<HTMLTableColElement> { let element = HTMLTableColElement::new_inherited(localName, document.unrooted()); Node::reflect_node(~element, document, HTMLTableColElementBinding::Wrap) } diff --git a/src/components/script/dom/htmltabledatacellelement.rs b/src/components/script/dom/htmltabledatacellelement.rs index 7a6185d6ec2..830740127f0 100644 --- a/src/components/script/dom/htmltabledatacellelement.rs +++ b/src/components/script/dom/htmltabledatacellelement.rs @@ -4,7 +4,7 @@ use dom::bindings::codegen::BindingDeclarations::HTMLTableDataCellElementBinding; use dom::bindings::codegen::InheritTypes::HTMLTableDataCellElementDerived; -use dom::bindings::js::{JS, JSRef}; +use dom::bindings::js::{JS, JSRef, Unrooted}; use dom::document::Document; use dom::element::HTMLTableDataCellElementTypeId; use dom::eventtarget::{EventTarget, NodeTargetTypeId}; @@ -33,7 +33,7 @@ impl HTMLTableDataCellElement { } } - pub fn new(localName: DOMString, document: &JSRef<Document>) -> JS<HTMLTableDataCellElement> { + pub fn new(localName: DOMString, document: &JSRef<Document>) -> Unrooted<HTMLTableDataCellElement> { let element = HTMLTableDataCellElement::new_inherited(localName, document.unrooted()); Node::reflect_node(~element, document, HTMLTableDataCellElementBinding::Wrap) } diff --git a/src/components/script/dom/htmltableelement.rs b/src/components/script/dom/htmltableelement.rs index 20948ff1d67..8150c68d3a6 100644 --- a/src/components/script/dom/htmltableelement.rs +++ b/src/components/script/dom/htmltableelement.rs @@ -4,7 +4,7 @@ use dom::bindings::codegen::BindingDeclarations::HTMLTableElementBinding; use dom::bindings::codegen::InheritTypes::HTMLTableElementDerived; -use dom::bindings::js::{JS, JSRef}; +use dom::bindings::js::{JS, JSRef, Unrooted}; use dom::bindings::error::ErrorResult; use dom::document::Document; use dom::element::HTMLTableElementTypeId; @@ -34,7 +34,7 @@ impl HTMLTableElement { } } - pub fn new(localName: DOMString, document: &JSRef<Document>) -> JS<HTMLTableElement> { + pub fn new(localName: DOMString, document: &JSRef<Document>) -> Unrooted<HTMLTableElement> { let element = HTMLTableElement::new_inherited(localName, document.unrooted()); Node::reflect_node(~element, document, HTMLTableElementBinding::Wrap) } diff --git a/src/components/script/dom/htmltableheadercellelement.rs b/src/components/script/dom/htmltableheadercellelement.rs index 47057fd0fa2..90dba152b44 100644 --- a/src/components/script/dom/htmltableheadercellelement.rs +++ b/src/components/script/dom/htmltableheadercellelement.rs @@ -4,7 +4,7 @@ use dom::bindings::codegen::BindingDeclarations::HTMLTableHeaderCellElementBinding; use dom::bindings::codegen::InheritTypes::HTMLTableHeaderCellElementDerived; -use dom::bindings::js::{JS, JSRef}; +use dom::bindings::js::{JS, JSRef, Unrooted}; use dom::document::Document; use dom::element::HTMLTableHeaderCellElementTypeId; use dom::eventtarget::{EventTarget, NodeTargetTypeId}; @@ -33,7 +33,7 @@ impl HTMLTableHeaderCellElement { } } - pub fn new(localName: DOMString, document: &JSRef<Document>) -> JS<HTMLTableHeaderCellElement> { + pub fn new(localName: DOMString, document: &JSRef<Document>) -> Unrooted<HTMLTableHeaderCellElement> { let element = HTMLTableHeaderCellElement::new_inherited(localName, document.unrooted()); Node::reflect_node(~element, document, HTMLTableHeaderCellElementBinding::Wrap) } diff --git a/src/components/script/dom/htmltablerowelement.rs b/src/components/script/dom/htmltablerowelement.rs index 1256dbfdabc..2b77faeadab 100644 --- a/src/components/script/dom/htmltablerowelement.rs +++ b/src/components/script/dom/htmltablerowelement.rs @@ -4,7 +4,7 @@ use dom::bindings::codegen::BindingDeclarations::HTMLTableRowElementBinding; use dom::bindings::codegen::InheritTypes::HTMLTableRowElementDerived; -use dom::bindings::js::{JS, JSRef}; +use dom::bindings::js::{JS, JSRef, Unrooted}; use dom::bindings::error::ErrorResult; use dom::document::Document; use dom::element::HTMLTableRowElementTypeId; @@ -34,7 +34,7 @@ impl HTMLTableRowElement { } } - pub fn new(localName: DOMString, document: &JSRef<Document>) -> JS<HTMLTableRowElement> { + pub fn new(localName: DOMString, document: &JSRef<Document>) -> Unrooted<HTMLTableRowElement> { let element = HTMLTableRowElement::new_inherited(localName, document.unrooted()); Node::reflect_node(~element, document, HTMLTableRowElementBinding::Wrap) } diff --git a/src/components/script/dom/htmltablesectionelement.rs b/src/components/script/dom/htmltablesectionelement.rs index 3689bba1f48..b44aba6e9dc 100644 --- a/src/components/script/dom/htmltablesectionelement.rs +++ b/src/components/script/dom/htmltablesectionelement.rs @@ -4,7 +4,7 @@ use dom::bindings::codegen::BindingDeclarations::HTMLTableSectionElementBinding; use dom::bindings::codegen::InheritTypes::HTMLTableSectionElementDerived; -use dom::bindings::js::{JS, JSRef}; +use dom::bindings::js::{JS, JSRef, Unrooted}; use dom::bindings::error::ErrorResult; use dom::document::Document; use dom::element::HTMLTableSectionElementTypeId; @@ -34,7 +34,7 @@ impl HTMLTableSectionElement { } } - pub fn new(localName: DOMString, document: &JSRef<Document>) -> JS<HTMLTableSectionElement> { + pub fn new(localName: DOMString, document: &JSRef<Document>) -> Unrooted<HTMLTableSectionElement> { let element = HTMLTableSectionElement::new_inherited(localName, document.unrooted()); Node::reflect_node(~element, document, HTMLTableSectionElementBinding::Wrap) } diff --git a/src/components/script/dom/htmltemplateelement.rs b/src/components/script/dom/htmltemplateelement.rs index 9880dc0b34d..f645e1815d3 100644 --- a/src/components/script/dom/htmltemplateelement.rs +++ b/src/components/script/dom/htmltemplateelement.rs @@ -4,7 +4,7 @@ use dom::bindings::codegen::BindingDeclarations::HTMLTemplateElementBinding; use dom::bindings::codegen::InheritTypes::HTMLTemplateElementDerived; -use dom::bindings::js::{JS, JSRef}; +use dom::bindings::js::{JS, JSRef, Unrooted}; use dom::document::Document; use dom::element::HTMLTemplateElementTypeId; use dom::eventtarget::{EventTarget, NodeTargetTypeId}; @@ -33,7 +33,7 @@ impl HTMLTemplateElement { } } - pub fn new(localName: DOMString, document: &JSRef<Document>) -> JS<HTMLTemplateElement> { + pub fn new(localName: DOMString, document: &JSRef<Document>) -> Unrooted<HTMLTemplateElement> { let element = HTMLTemplateElement::new_inherited(localName, document.unrooted()); Node::reflect_node(~element, document, HTMLTemplateElementBinding::Wrap) } diff --git a/src/components/script/dom/htmltextareaelement.rs b/src/components/script/dom/htmltextareaelement.rs index 4f4c7b55c9d..4955085c751 100644 --- a/src/components/script/dom/htmltextareaelement.rs +++ b/src/components/script/dom/htmltextareaelement.rs @@ -4,7 +4,7 @@ use dom::bindings::codegen::BindingDeclarations::HTMLTextAreaElementBinding; use dom::bindings::codegen::InheritTypes::HTMLTextAreaElementDerived; -use dom::bindings::js::{JS, JSRef}; +use dom::bindings::js::{JS, JSRef, Unrooted}; use dom::bindings::error::{ErrorResult, Fallible}; use dom::document::Document; use dom::element::HTMLTextAreaElementTypeId; @@ -34,7 +34,7 @@ impl HTMLTextAreaElement { } } - pub fn new(localName: DOMString, document: &JSRef<Document>) -> JS<HTMLTextAreaElement> { + pub fn new(localName: DOMString, document: &JSRef<Document>) -> Unrooted<HTMLTextAreaElement> { let element = HTMLTextAreaElement::new_inherited(localName, document.unrooted()); Node::reflect_node(~element, document, HTMLTextAreaElementBinding::Wrap) } diff --git a/src/components/script/dom/htmltimeelement.rs b/src/components/script/dom/htmltimeelement.rs index 938a1013876..df74323fc01 100644 --- a/src/components/script/dom/htmltimeelement.rs +++ b/src/components/script/dom/htmltimeelement.rs @@ -4,7 +4,7 @@ use dom::bindings::codegen::BindingDeclarations::HTMLTimeElementBinding; use dom::bindings::codegen::InheritTypes::HTMLTimeElementDerived; -use dom::bindings::js::{JS, JSRef}; +use dom::bindings::js::{JS, JSRef, Unrooted}; use dom::bindings::error::ErrorResult; use dom::document::Document; use dom::element::HTMLTimeElementTypeId; @@ -34,7 +34,7 @@ impl HTMLTimeElement { } } - pub fn new(localName: DOMString, document: &JSRef<Document>) -> JS<HTMLTimeElement> { + pub fn new(localName: DOMString, document: &JSRef<Document>) -> Unrooted<HTMLTimeElement> { let element = HTMLTimeElement::new_inherited(localName, document.unrooted()); Node::reflect_node(~element, document, HTMLTimeElementBinding::Wrap) } diff --git a/src/components/script/dom/htmltitleelement.rs b/src/components/script/dom/htmltitleelement.rs index 3fe46fe1b81..2c1af9b5291 100644 --- a/src/components/script/dom/htmltitleelement.rs +++ b/src/components/script/dom/htmltitleelement.rs @@ -4,7 +4,7 @@ use dom::bindings::codegen::BindingDeclarations::HTMLTitleElementBinding; use dom::bindings::codegen::InheritTypes::HTMLTitleElementDerived; -use dom::bindings::js::{JS, JSRef}; +use dom::bindings::js::{JS, JSRef, Unrooted}; use dom::bindings::error::ErrorResult; use dom::document::Document; use dom::element::HTMLTitleElementTypeId; @@ -34,7 +34,7 @@ impl HTMLTitleElement { } } - pub fn new(localName: DOMString, document: &JSRef<Document>) -> JS<HTMLTitleElement> { + pub fn new(localName: DOMString, document: &JSRef<Document>) -> Unrooted<HTMLTitleElement> { let element = HTMLTitleElement::new_inherited(localName, document.unrooted()); Node::reflect_node(~element, document, HTMLTitleElementBinding::Wrap) } diff --git a/src/components/script/dom/htmltrackelement.rs b/src/components/script/dom/htmltrackelement.rs index 19a58090dcf..408da82d53b 100644 --- a/src/components/script/dom/htmltrackelement.rs +++ b/src/components/script/dom/htmltrackelement.rs @@ -4,7 +4,7 @@ use dom::bindings::codegen::BindingDeclarations::HTMLTrackElementBinding; use dom::bindings::codegen::InheritTypes::HTMLTrackElementDerived; -use dom::bindings::js::{JS, JSRef}; +use dom::bindings::js::{JS, JSRef, Unrooted}; use dom::bindings::error::ErrorResult; use dom::document::Document; use dom::element::HTMLTrackElementTypeId; @@ -34,7 +34,7 @@ impl HTMLTrackElement { } } - pub fn new(localName: DOMString, document: &JSRef<Document>) -> JS<HTMLTrackElement> { + pub fn new(localName: DOMString, document: &JSRef<Document>) -> Unrooted<HTMLTrackElement> { let element = HTMLTrackElement::new_inherited(localName, document.unrooted()); Node::reflect_node(~element, document, HTMLTrackElementBinding::Wrap) } diff --git a/src/components/script/dom/htmlulistelement.rs b/src/components/script/dom/htmlulistelement.rs index 1fe1be79af1..c2661a5ee46 100644 --- a/src/components/script/dom/htmlulistelement.rs +++ b/src/components/script/dom/htmlulistelement.rs @@ -4,7 +4,7 @@ use dom::bindings::codegen::BindingDeclarations::HTMLUListElementBinding; use dom::bindings::codegen::InheritTypes::HTMLUListElementDerived; -use dom::bindings::js::{JS, JSRef}; +use dom::bindings::js::{JS, JSRef, Unrooted}; use dom::bindings::error::ErrorResult; use dom::document::Document; use dom::element::HTMLUListElementTypeId; @@ -34,7 +34,7 @@ impl HTMLUListElement { } } - pub fn new(localName: DOMString, document: &JSRef<Document>) -> JS<HTMLUListElement> { + pub fn new(localName: DOMString, document: &JSRef<Document>) -> Unrooted<HTMLUListElement> { let element = HTMLUListElement::new_inherited(localName, document.unrooted()); Node::reflect_node(~element, document, HTMLUListElementBinding::Wrap) } diff --git a/src/components/script/dom/htmlunknownelement.rs b/src/components/script/dom/htmlunknownelement.rs index aa472bb04fc..da68e0c51bf 100644 --- a/src/components/script/dom/htmlunknownelement.rs +++ b/src/components/script/dom/htmlunknownelement.rs @@ -4,7 +4,7 @@ use dom::bindings::codegen::BindingDeclarations::HTMLUnknownElementBinding; use dom::bindings::codegen::InheritTypes::HTMLUnknownElementDerived; -use dom::bindings::js::{JS, JSRef}; +use dom::bindings::js::{JS, JSRef, Unrooted}; use dom::document::Document; use dom::element::HTMLUnknownElementTypeId; use dom::eventtarget::{EventTarget, NodeTargetTypeId}; @@ -33,7 +33,7 @@ impl HTMLUnknownElement { } } - pub fn new(localName: DOMString, document: &JSRef<Document>) -> JS<HTMLUnknownElement> { + pub fn new(localName: DOMString, document: &JSRef<Document>) -> Unrooted<HTMLUnknownElement> { let element = HTMLUnknownElement::new_inherited(localName, document.unrooted()); Node::reflect_node(~element, document, HTMLUnknownElementBinding::Wrap) } diff --git a/src/components/script/dom/htmlvideoelement.rs b/src/components/script/dom/htmlvideoelement.rs index 3587ab4931a..aba9c3c3436 100644 --- a/src/components/script/dom/htmlvideoelement.rs +++ b/src/components/script/dom/htmlvideoelement.rs @@ -4,7 +4,7 @@ use dom::bindings::codegen::BindingDeclarations::HTMLVideoElementBinding; use dom::bindings::codegen::InheritTypes::HTMLVideoElementDerived; -use dom::bindings::js::{JS, JSRef}; +use dom::bindings::js::{JS, JSRef, Unrooted}; use dom::bindings::error::ErrorResult; use dom::document::Document; use dom::element::HTMLVideoElementTypeId; @@ -34,7 +34,7 @@ impl HTMLVideoElement { } } - pub fn new(localName: DOMString, document: &JSRef<Document>) -> JS<HTMLVideoElement> { + pub fn new(localName: DOMString, document: &JSRef<Document>) -> Unrooted<HTMLVideoElement> { let element = HTMLVideoElement::new_inherited(localName, document.unrooted()); Node::reflect_node(~element, document, HTMLVideoElementBinding::Wrap) } diff --git a/src/components/script/dom/location.rs b/src/components/script/dom/location.rs index fa0aaf103d7..762da0a383b 100644 --- a/src/components/script/dom/location.rs +++ b/src/components/script/dom/location.rs @@ -3,7 +3,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use dom::bindings::codegen::BindingDeclarations::LocationBinding; -use dom::bindings::js::{JS, JSRef}; +use dom::bindings::js::{JSRef, Unrooted}; use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object}; use dom::bindings::error::Fallible; use dom::window::Window; @@ -29,7 +29,7 @@ impl Location { } } - pub fn new(window: &JSRef<Window>, page: Rc<Page>) -> JS<Location> { + pub fn new(window: &JSRef<Window>, page: Rc<Page>) -> Unrooted<Location> { reflect_dom_object(~Location::new_inherited(page), window, LocationBinding::Wrap) diff --git a/src/components/script/dom/mouseevent.rs b/src/components/script/dom/mouseevent.rs index a1f08aa72e0..b771b1b091c 100644 --- a/src/components/script/dom/mouseevent.rs +++ b/src/components/script/dom/mouseevent.rs @@ -4,7 +4,7 @@ use dom::bindings::codegen::BindingDeclarations::MouseEventBinding; use dom::bindings::codegen::InheritTypes::MouseEventDerived; -use dom::bindings::js::{JS, JSRef, RootCollection, RootedReference}; +use dom::bindings::js::{JS, JSRef, RootCollection, RootedReference, Unrooted}; use dom::bindings::error::Fallible; use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object}; use dom::event::{Event, MouseEventTypeId}; @@ -51,7 +51,7 @@ impl MouseEvent { } } - pub fn new(window: &JSRef<Window>) -> JS<MouseEvent> { + pub fn new(window: &JSRef<Window>) -> Unrooted<MouseEvent> { reflect_dom_object(~MouseEvent::new_inherited(), window, MouseEventBinding::Wrap) @@ -59,9 +59,9 @@ impl MouseEvent { pub fn Constructor(owner: &JSRef<Window>, type_: DOMString, - init: &MouseEventBinding::MouseEventInit) -> Fallible<JS<MouseEvent>> { + init: &MouseEventBinding::MouseEventInit) -> Fallible<Unrooted<MouseEvent>> { let roots = RootCollection::new(); - let mut ev = MouseEvent::new(owner); + let mut ev = MouseEvent::new(owner).root(&roots); let view = init.view.as_ref().map(|view| view.root(&roots)); let related_target = init.relatedTarget.as_ref().map(|relatedTarget| relatedTarget.root(&roots)); ev.get_mut().InitMouseEvent(type_, init.bubbles, init.cancelable, view.root_ref(), @@ -69,7 +69,7 @@ impl MouseEvent { init.clientX, init.clientY, init.ctrlKey, init.altKey, init.shiftKey, init.metaKey, init.button, related_target.root_ref()); - Ok(ev) + Ok(Unrooted::new_rooted(&*ev)) } pub fn ScreenX(&self) -> i32 { @@ -113,8 +113,8 @@ impl MouseEvent { 0 } - pub fn GetRelatedTarget(&self) -> Option<JS<EventTarget>> { - self.related_target.clone() + pub fn GetRelatedTarget(&self) -> Option<Unrooted<EventTarget>> { + self.related_target.clone().map(|target| Unrooted::new(target)) } pub fn GetModifierState(&self, _keyArg: DOMString) -> bool { diff --git a/src/components/script/dom/navigator.rs b/src/components/script/dom/navigator.rs index 63779428d94..494175cb6b8 100644 --- a/src/components/script/dom/navigator.rs +++ b/src/components/script/dom/navigator.rs @@ -3,7 +3,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use dom::bindings::codegen::BindingDeclarations::NavigatorBinding; -use dom::bindings::js::{JS, JSRef}; +use dom::bindings::js::{JSRef, Unrooted}; use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object}; use dom::bindings::error::Fallible; use dom::window::Window; @@ -21,7 +21,7 @@ impl Navigator { } } - pub fn new(window: &JSRef<Window>) -> JS<Navigator> { + pub fn new(window: &JSRef<Window>) -> Unrooted<Navigator> { reflect_dom_object(~Navigator::new_inherited(), window, NavigatorBinding::Wrap) diff --git a/src/components/script/dom/node.rs b/src/components/script/dom/node.rs index 4d40d8daeb7..6758efeb65d 100644 --- a/src/components/script/dom/node.rs +++ b/src/components/script/dom/node.rs @@ -10,7 +10,9 @@ use dom::bindings::codegen::InheritTypes::{ElementCast, TextCast, NodeCast}; use dom::bindings::codegen::InheritTypes::{CharacterDataCast, NodeBase, NodeDerived}; use dom::bindings::codegen::InheritTypes::{ProcessingInstructionCast, EventTargetCast}; use dom::bindings::codegen::BindingDeclarations::NodeBinding::NodeConstants; -use dom::bindings::js::{JS, JSRef, RootCollection, RootedReference}; +use dom::bindings::js::{JS, JSRef, RootCollection, RootedReference, Unrooted, Root}; +use dom::bindings::js::{OptionalAssignable, UnrootedPushable, OptionalRootable}; +use dom::bindings::js::ResultRootable; use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object}; use dom::bindings::error::{ErrorResult, Fallible, NotFound, HierarchyRequest}; use dom::bindings::utils; @@ -222,30 +224,19 @@ pub enum NodeTypeId { ProcessingInstructionNodeTypeId, } -pub trait INode { - fn AppendChild(&mut self, node: &mut JSRef<Node>) -> Fallible<JS<Node>>; - fn ReplaceChild(&mut self, node: &mut JSRef<Node>, child: &mut JSRef<Node>) -> Fallible<JS<Node>>; - fn RemoveChild(&mut self, node: &mut JSRef<Node>) -> Fallible<JS<Node>>; +pub fn AppendChild<'a>(self_: &mut JSRef<'a, Node>, node: &mut JSRef<Node>) -> Fallible<Unrooted<Node>> { + let mut self_alias = self_.clone(); + self_.get_mut().AppendChild(&mut self_alias, node) } -impl INode for JS<Node> { - fn AppendChild(&mut self, node: &mut JSRef<Node>) -> Fallible<JS<Node>> { - let roots = RootCollection::new(); - let self_node = self.root(&roots); - self.get_mut().AppendChild(&mut self_node.root_ref(), node) - } - - fn ReplaceChild(&mut self, node: &mut JSRef<Node>, child: &mut JSRef<Node>) -> Fallible<JS<Node>> { - let roots = RootCollection::new(); - let self_node = self.root(&roots); - self.get_mut().ReplaceChild(&mut self_node.root_ref(), node, child) - } +pub fn ReplaceChild<'a>(self_: &mut JSRef<'a, Node>, node: &mut JSRef<Node>, child: &mut JSRef<Node>) -> Fallible<Unrooted<Node>> { + let mut self_alias = self_.clone(); + self_.get_mut().ReplaceChild(&mut self_alias, node, child) +} - fn RemoveChild(&mut self, node: &mut JSRef<Node>) -> Fallible<JS<Node>> { - let roots = RootCollection::new(); - let self_node = self.root(&roots); - self.get_mut().RemoveChild(&mut self_node.root_ref(), node) - } +pub fn RemoveChild<'a>(self_: &mut JSRef<'a, Node>, node: &mut JSRef<Node>) -> Fallible<Unrooted<Node>> { + let mut self_alias = self_.clone(); + self_.get_mut().RemoveChild(&mut self_alias, node) } pub trait NodeHelpers { @@ -259,11 +250,11 @@ pub trait NodeHelpers { fn type_id(&self) -> NodeTypeId; - fn parent_node(&self) -> Option<JS<Node>>; - fn first_child(&self) -> Option<JS<Node>>; - fn last_child(&self) -> Option<JS<Node>>; - fn prev_sibling(&self) -> Option<JS<Node>>; - fn next_sibling(&self) -> Option<JS<Node>>; + fn parent_node(&self) -> Option<Unrooted<Node>>; + fn first_child(&self) -> Option<Unrooted<Node>>; + fn last_child(&self) -> Option<Unrooted<Node>>; + fn prev_sibling(&self) -> Option<Unrooted<Node>>; + fn next_sibling(&self) -> Option<Unrooted<Node>>; fn is_element(&self) -> bool; fn is_document(&self) -> bool; @@ -283,18 +274,17 @@ pub trait NodeHelpers { fn dump_indent(&self, indent: uint); fn debug_str(&self) -> ~str; - fn traverse_preorder(&self) -> TreeIterator; - fn sequential_traverse_postorder(&self) -> TreeIterator; + fn traverse_preorder<'a>(&self, roots: &'a RootCollection) -> TreeIterator<'a>; + fn sequential_traverse_postorder<'a>(&self, roots: &'a RootCollection) -> TreeIterator<'a>; fn inclusively_following_siblings(&self) -> AbstractNodeChildrenIterator; - fn from_untrusted_node_address(runtime: *JSRuntime, candidate: UntrustedNodeAddress) -> Self; fn to_trusted_node_address(&self) -> TrustedNodeAddress; fn get_bounding_content_box(&self) -> Rect<Au>; fn get_content_boxes(&self) -> Vec<Rect<Au>>; } -impl NodeHelpers for JS<Node> { +impl<'a> NodeHelpers for JSRef<'a, Node> { /// Dumps the subtree rooted at this node, for debugging. fn dump(&self) { self.dump_indent(0); @@ -343,26 +333,26 @@ impl NodeHelpers for JS<Node> { self.get().type_id } - fn parent_node(&self) -> Option<JS<Node>> { - self.get().parent_node.clone() + fn parent_node(&self) -> Option<Unrooted<Node>> { + self.get().parent_node.clone().map(|node| Unrooted::new(node)) } - fn first_child(&self) -> Option<JS<Node>> { - self.get().first_child.clone() + fn first_child(&self) -> Option<Unrooted<Node>> { + self.get().first_child.clone().map(|node| Unrooted::new(node)) } - fn last_child(&self) -> Option<JS<Node>> { - self.get().last_child.clone() + fn last_child(&self) -> Option<Unrooted<Node>> { + self.get().last_child.clone().map(|node| Unrooted::new(node)) } /// Returns the previous sibling of this node. Fails if this node is borrowed mutably. - fn prev_sibling(&self) -> Option<JS<Node>> { - self.get().prev_sibling.clone() + fn prev_sibling(&self) -> Option<Unrooted<Node>> { + self.get().prev_sibling.clone().map(|node| Unrooted::new(node)) } /// Returns the next sibling of this node. Fails if this node is borrowed mutably. - fn next_sibling(&self) -> Option<JS<Node>> { - self.get().next_sibling.clone() + fn next_sibling(&self) -> Option<Unrooted<Node>> { + self.get().next_sibling.clone().map(|node| Unrooted::new(node)) } #[inline] @@ -388,10 +378,7 @@ impl NodeHelpers for JS<Node> { #[inline] fn is_doctype(&self) -> bool { - match self.type_id() { - DoctypeNodeTypeId => true, - _ => false - } + self.get().is_doctype() } #[inline] @@ -406,25 +393,28 @@ impl NodeHelpers for JS<Node> { // http://dom.spec.whatwg.org/#node-is-inserted fn node_inserted(&self) { + let roots = RootCollection::new(); assert!(self.parent_node().is_some()); - let document = document_from_node(self); + let document = document_from_node(self).root(&roots); if self.is_in_doc() { - for node in self.traverse_preorder() { + for node in self.traverse_preorder(&roots) { vtable_for(&node).bind_to_tree(); } } - self.parent_node().map(|parent| vtable_for(&parent).child_inserted(self)); + self.parent_node().root(&roots) + .map(|parent| vtable_for(&*parent).child_inserted(self)); document.get().content_changed(); } // http://dom.spec.whatwg.org/#node-is-removed fn node_removed(&self) { + let roots = RootCollection::new(); assert!(self.parent_node().is_none()); - let document = document_from_node(self); + let document = document_from_node(self).root(&roots); - for node in self.traverse_preorder() { + for node in self.traverse_preorder(&roots) { // XXX how about if the node wasn't in the tree in the first place? vtable_for(&node).unbind_from_tree(); } @@ -439,49 +429,45 @@ impl NodeHelpers for JS<Node> { /// Adds a new child to the end of this node's list of children. /// /// Fails unless `new_child` is disconnected from the tree. - fn add_child(&mut self, new_child_root: &mut JSRef<Node>, before: Option<JSRef<Node>>) { + fn add_child(&mut self, new_child: &mut JSRef<Node>, mut before: Option<JSRef<Node>>) { let roots = RootCollection::new(); - let mut new_child = new_child_root.unrooted(); assert!(new_child.parent_node().is_none()); assert!(new_child.prev_sibling().is_none()); assert!(new_child.next_sibling().is_none()); match before { - Some(before_root) => { - let mut before = before_root.unrooted(); + Some(ref mut before) => { // XXX Should assert that parent is self. assert!(before.parent_node().is_some()); match before.prev_sibling() { None => { // XXX Should assert that before is the first child of // self. - self.get_mut().set_first_child(Some(new_child_root.clone())); + self.get_mut().set_first_child(Some(new_child.clone())); }, - Some(mut prev_sibling) => { - let prev_sibling_root = prev_sibling.root(&roots); - prev_sibling.get_mut().set_next_sibling(Some(new_child_root.clone())); - new_child.get_mut().set_prev_sibling(Some(prev_sibling_root.root_ref())); + Some(prev_sibling) => { + let mut prev_sibling = prev_sibling.root(&roots); + prev_sibling.get_mut().set_next_sibling(Some(new_child.clone())); + new_child.get_mut().set_prev_sibling(Some((*prev_sibling).clone())); }, } - before.get_mut().set_prev_sibling(Some(new_child_root.clone())); - new_child.get_mut().set_next_sibling(Some(before_root.clone())); + before.get_mut().set_prev_sibling(Some(new_child.clone())); + new_child.get_mut().set_next_sibling(Some(before.clone())); }, None => { - match self.last_child() { - None => self.get_mut().set_first_child(Some(new_child_root.clone())), + match self.last_child().map(|child| child.root(&roots)) { + None => self.get_mut().set_first_child(Some(new_child.clone())), Some(mut last_child) => { - let last_child_root = last_child.root(&roots); assert!(last_child.next_sibling().is_none()); - last_child.get_mut().set_next_sibling(Some(new_child_root.clone())); - new_child.get_mut().set_prev_sibling(Some(last_child_root.root_ref())); + last_child.get_mut().set_next_sibling(Some(new_child.clone())); + new_child.get_mut().set_prev_sibling(Some((*last_child).clone())); } } - self.get_mut().set_last_child(Some(new_child_root.clone())); + self.get_mut().set_last_child(Some(new_child.clone())); }, } - let self_root = self.root(&roots); - new_child.get_mut().set_parent_node(Some(self_root.root_ref())); + new_child.get_mut().set_parent_node(Some(self.clone())); } /// Removes the given child from this node's list of children. @@ -531,69 +517,53 @@ impl NodeHelpers for JS<Node> { } /// Iterates over this node and all its descendants, in preorder. - fn traverse_preorder(&self) -> TreeIterator { - let roots = RootCollection::new(); + fn traverse_preorder<'a>(&self, roots: &'a RootCollection) -> TreeIterator<'a> { let mut nodes = vec!(); - let self_root = self.root(&roots); - gather_abstract_nodes(&self_root.root_ref(), &mut nodes, false); + gather_abstract_nodes(self, roots, &mut nodes, false); TreeIterator::new(nodes) } /// Iterates over this node and all its descendants, in postorder. - fn sequential_traverse_postorder(&self) -> TreeIterator { - let roots = RootCollection::new(); + fn sequential_traverse_postorder<'a>(&self, roots: &'a RootCollection) -> TreeIterator<'a> { let mut nodes = vec!(); - let self_root = self.root(&roots); - gather_abstract_nodes(&self_root.root_ref(), &mut nodes, true); + gather_abstract_nodes(self, roots, &mut nodes, true); TreeIterator::new(nodes) } fn inclusively_following_siblings(&self) -> AbstractNodeChildrenIterator { + let roots = RootCollection::new(); AbstractNodeChildrenIterator { - current_node: Some(self.clone()), + current_node: Some((*self.unrooted().root(&roots)).clone()), + roots: roots, } } fn is_inclusive_ancestor_of(&self, parent: &JSRef<Node>) -> bool { - let parent = &parent.unrooted(); - self == parent || parent.ancestors().any(|ancestor| ancestor == *self) + self == parent || parent.ancestors().any(|ancestor| &ancestor == self) } fn following_siblings(&self) -> AbstractNodeChildrenIterator { + let roots = RootCollection::new(); AbstractNodeChildrenIterator { - current_node: self.next_sibling(), + current_node: self.next_sibling().map(|node| (*node.root(&roots)).clone()), + roots: roots, } } fn is_parent_of(&self, child: &JSRef<Node>) -> bool { - match child.unrooted().parent_node() { - Some(ref parent) if parent == self => true, + match child.parent_node() { + Some(ref parent) if *parent == Unrooted::new_rooted(self) => true, _ => false } } - /// If the given untrusted node address represents a valid DOM node in the given runtime, - /// returns it. - fn from_untrusted_node_address(runtime: *JSRuntime, candidate: UntrustedNodeAddress) - -> JS<Node> { - unsafe { - let candidate: uintptr_t = cast::transmute(candidate); - let object: *JSObject = jsfriendapi::bindgen::JS_GetAddressableObject(runtime, - candidate); - if object.is_null() { - fail!("Attempted to create a `JS<Node>` from an invalid pointer!") - } - let boxed_node: *mut Node = utils::unwrap(object); - JS::from_raw(boxed_node) - } - } - fn to_trusted_node_address(&self) -> TrustedNodeAddress { TrustedNodeAddress(self.get() as *Node as *libc::c_void) } fn get_bounding_content_box(&self) -> Rect<Au> { - let window = window_from_node(self); + let roots = RootCollection::new(); + let window = window_from_node(self).root(&roots); let page = window.get().page(); let (chan, port) = channel(); let addr = self.to_trusted_node_address(); @@ -602,7 +572,8 @@ impl NodeHelpers for JS<Node> { } fn get_content_boxes(&self) -> Vec<Rect<Au>> { - let window = window_from_node(self); + let roots = RootCollection::new(); + let window = window_from_node(self).root(&roots); let page = window.get().page(); let (chan, port) = channel(); let addr = self.to_trusted_node_address(); @@ -611,54 +582,86 @@ impl NodeHelpers for JS<Node> { } } +/// If the given untrusted node address represents a valid DOM node in the given runtime, +/// returns it. +pub fn from_untrusted_node_address(runtime: *JSRuntime, candidate: UntrustedNodeAddress) + -> Unrooted<Node> { + unsafe { + let candidate: uintptr_t = cast::transmute(candidate); + let object: *JSObject = jsfriendapi::bindgen::JS_GetAddressableObject(runtime, + candidate); + if object.is_null() { + fail!("Attempted to create a `JS<Node>` from an invalid pointer!") + } + let boxed_node: *mut Node = utils::unwrap(object); + Unrooted::new(JS::from_raw(boxed_node)) + } +} + +pub trait LayoutNodeHelpers { + fn type_id_for_layout(&self) -> NodeTypeId; +} + +impl LayoutNodeHelpers for JS<Node> { + fn type_id_for_layout(&self) -> NodeTypeId { + unsafe { + let node: **Node = cast::transmute::<*JS<Node>, + **Node>(self); + (**node).type_id + } + } +} + // // Iteration and traversal // -pub type ChildElementIterator<'a> = Map<'a, JS<Node>, - JS<Element>, - Filter<'a, JS<Node>, AbstractNodeChildrenIterator>>; +pub type ChildElementIterator<'a, 'b> = Map<'a, JSRef<'b, Node>, + JSRef<'b, Element>, + Filter<'a, JSRef<'b, Node>, AbstractNodeChildrenIterator<'b>>>; -pub struct AbstractNodeChildrenIterator { - current_node: Option<JS<Node>>, +pub struct AbstractNodeChildrenIterator<'a> { + current_node: Option<JSRef<'a, Node>>, + roots: RootCollection, } -impl Iterator<JS<Node>> for AbstractNodeChildrenIterator { - fn next(&mut self) -> Option<JS<Node>> { +impl<'a> Iterator<JSRef<'a, Node>> for AbstractNodeChildrenIterator<'a> { + fn next(&mut self) -> Option<JSRef<'a, Node>> { let node = self.current_node.clone(); self.current_node = node.clone().and_then(|node| { - node.next_sibling() + node.next_sibling().map(|node| (*node.root(&self.roots)).clone()) }); node } } -pub struct AncestorIterator { - current: Option<JS<Node>>, +pub struct AncestorIterator<'a> { + current: Option<JSRef<'a, Node>>, + roots: RootCollection, } -impl Iterator<JS<Node>> for AncestorIterator { - fn next(&mut self) -> Option<JS<Node>> { +impl<'a> Iterator<JSRef<'a, Node>> for AncestorIterator<'a> { + fn next(&mut self) -> Option<JSRef<'a, Node>> { if self.current.is_none() { return None; } // FIXME: Do we need two clones here? let x = self.current.get_ref().clone(); - self.current = x.parent_node(); - Some(x.clone()) + self.current = x.parent_node().map(|node| (*node.root(&self.roots)).clone()); + Some(x) } } // FIXME: Do this without precomputing a vector of refs. // Easy for preorder; harder for postorder. -pub struct TreeIterator { - nodes: Vec<JS<Node>>, +pub struct TreeIterator<'a> { + nodes: Vec<JSRef<'a, Node>>, index: uint, } -impl TreeIterator { - fn new(nodes: Vec<JS<Node>>) -> TreeIterator { +impl<'a> TreeIterator<'a> { + fn new(nodes: Vec<JSRef<'a, Node>>) -> TreeIterator<'a> { TreeIterator { nodes: nodes, index: 0, @@ -666,8 +669,8 @@ impl TreeIterator { } } -impl Iterator<JS<Node>> for TreeIterator { - fn next(&mut self) -> Option<JS<Node>> { +impl<'a> Iterator<JSRef<'a, Node>> for TreeIterator<'a> { + fn next(&mut self) -> Option<JSRef<'a, Node>> { if self.index >= self.nodes.len() { None } else { @@ -678,7 +681,8 @@ impl Iterator<JS<Node>> for TreeIterator { } } -pub struct NodeIterator { +pub struct NodeIterator<'a> { + roots: &'a RootCollection, pub start_node: JS<Node>, pub current_node: Option<JS<Node>>, pub depth: uint, @@ -686,10 +690,14 @@ pub struct NodeIterator { include_descendants_of_void: bool } -impl NodeIterator { - pub fn new(start_node: JS<Node>, include_start: bool, include_descendants_of_void: bool) -> NodeIterator { +impl<'a> NodeIterator<'a> { + pub fn new<'a, 'b>(roots: &'a RootCollection, + start_node: &JSRef<'b, Node>, + include_start: bool, + include_descendants_of_void: bool) -> NodeIterator<'a> { NodeIterator { - start_node: start_node, + roots: roots, + start_node: start_node.unrooted(), current_node: None, depth: 0, include_start: include_start, @@ -697,54 +705,54 @@ impl NodeIterator { } } - fn next_child(&self, node: &JSRef<Node>) -> Option<JS<Node>> { + fn next_child<'b>(&self, node: &JSRef<'b, Node>) -> Option<JSRef<Node>> { if !self.include_descendants_of_void && node.get().is_element() { - let elem: JS<Element> = ElementCast::to(&node.unrooted()).unwrap(); + let elem: &JSRef<Element> = ElementCast::to_ref(node).unwrap(); if elem.get().is_void() { None } else { - node.get().first_child.clone() + node.first_child().map(|child| (*child.root(self.roots)).clone()) } } else { - node.get().first_child.clone() + node.first_child().map(|child| (*child.root(self.roots)).clone()) } } } -impl Iterator<JS<Node>> for NodeIterator { - fn next(&mut self) -> Option<JS<Node>> { - let roots = RootCollection::new(); - self.current_node = match self.current_node { +impl<'a, 'b> Iterator<JSRef<'b, Node>> for NodeIterator<'a> { + fn next(&mut self) -> Option<JSRef<Node>> { + self.current_node = match self.current_node.as_ref().map(|node| node.root(self.roots)) { None => { if self.include_start { Some(self.start_node.clone()) } else { - let start_node = self.start_node.root(&roots); - self.next_child(&start_node.root_ref()) + self.next_child(&*self.start_node.root(self.roots)) + .map(|child| child.unrooted()) } }, - Some(ref node) => { - let node_root = node.root(&roots); - match self.next_child(&node_root.root_ref()) { + Some(node) => { + match self.next_child(&*node) { Some(child) => { self.depth += 1; - Some(child.clone()) + Some(child.unrooted()) }, - None if node == &self.start_node => None, + None if node.deref().unrooted() == self.start_node => None, None => { - match node.next_sibling() { - Some(sibling) => Some(sibling), + match node.deref().next_sibling().root(self.roots) { + Some(sibling) => Some(sibling.deref().unrooted()), None => { - let mut candidate = node.clone(); + let mut candidate = node.deref().clone(); while candidate.next_sibling().is_none() { - candidate = candidate.parent_node().expect("Got to root without reaching start node"); + candidate = (*candidate.parent_node() + .expect("Got to root without reaching start node") + .root(self.roots)).clone(); self.depth -= 1; - if candidate == self.start_node { + if candidate.unrooted() == self.start_node { break; } } - if candidate != self.start_node { - candidate.next_sibling() + if candidate.unrooted() != self.start_node { + candidate.next_sibling().map(|node| node.root(self.roots).unrooted()) } else { None } @@ -754,21 +762,19 @@ impl Iterator<JS<Node>> for NodeIterator { } } }; - self.current_node.clone() + self.current_node.clone().map(|node| (*node.root(self.roots)).clone()) } } -fn gather_abstract_nodes(cur: &JSRef<Node>, refs: &mut Vec<JS<Node>>, postorder: bool) { - let roots = RootCollection::new(); +fn gather_abstract_nodes<'a>(cur: &JSRef<Node>, roots: &'a RootCollection, refs: &mut Vec<JSRef<Node>>, postorder: bool) { if !postorder { - refs.push(cur.unrooted()); + refs.push((*cur.unrooted().root(roots)).clone()); } - for kid in cur.unrooted().children() { - let kid = kid.root(&roots); - gather_abstract_nodes(&kid.root_ref(), refs, postorder) + for kid in cur.children() { + gather_abstract_nodes(&kid, roots, refs, postorder) } if postorder { - refs.push(cur.unrooted()); + refs.push((*cur.unrooted().root(roots)).clone()); } } @@ -783,8 +789,10 @@ fn as_uintptr<T>(t: &T) -> uintptr_t { t as *T as uintptr_t } impl Node { pub fn ancestors(&self) -> AncestorIterator { + let roots = RootCollection::new(); AncestorIterator { - current: self.parent_node.clone(), + current: self.parent_node.clone().map(|node| (*node.root(&roots)).clone()), + roots: roots, } } @@ -795,7 +803,18 @@ impl Node { } } - pub fn owner_doc<'a>(&'a self) -> &'a JS<Document> { + pub fn is_doctype(&self) -> bool { + match self.type_id { + DoctypeNodeTypeId => true, + _ => false + } + } + + pub fn owner_doc(&self) -> Unrooted<Document> { + Unrooted::new(self.owner_doc.get_ref().clone()) + } + + pub fn owner_doc_for_layout<'a>(&'a self) -> &'a JS<Document> { self.owner_doc.get_ref() } @@ -804,17 +823,21 @@ impl Node { } pub fn children(&self) -> AbstractNodeChildrenIterator { + let roots = RootCollection::new(); AbstractNodeChildrenIterator { - current_node: self.first_child.clone(), + current_node: self.first_child.clone().map(|node| (*node.root(&roots)).clone()), + roots: roots, } } pub fn child_elements(&self) -> ChildElementIterator { self.children() - .filter(|node| node.is_element()) + .filter(|node| { + node.is_element() + }) .map(|node| { - let elem: JS<Element> = ElementCast::to(&node).unwrap(); - elem + let elem: &JSRef<Element> = ElementCast::to_ref(&node).unwrap(); + elem.clone() }) } @@ -822,13 +845,13 @@ impl Node { (node: ~N, document: &JSRef<Document>, wrap_fn: extern "Rust" fn(*JSContext, &JSRef<Window>, ~N) -> JS<N>) - -> JS<N> { + -> Unrooted<N> { let roots = RootCollection::new(); assert!(node.reflector().get_jsobject().is_null()); let window = document.get().window.root(&roots); - let node = reflect_dom_object(node, &window.root_ref(), wrap_fn); + let node = reflect_dom_object(node, &window.root_ref(), wrap_fn).root(&roots); assert!(node.reflector().get_jsobject().is_not_null()); - node + Unrooted::new_rooted(&*node) } pub fn new_inherited(type_id: NodeTypeId, doc: JS<Document>) -> Node { @@ -919,26 +942,33 @@ impl Node { } // http://dom.spec.whatwg.org/#dom-node-ownerdocument - pub fn GetOwnerDocument(&self) -> Option<JS<Document>> { + pub fn GetOwnerDocument(&self) -> Option<Unrooted<Document>> { match self.type_id { ElementNodeTypeId(..) | CommentNodeTypeId | TextNodeTypeId | ProcessingInstructionNodeTypeId | DoctypeNodeTypeId | - DocumentFragmentNodeTypeId => Some(self.owner_doc().clone()), + DocumentFragmentNodeTypeId => Some(self.owner_doc()), DocumentNodeTypeId => None } } // http://dom.spec.whatwg.org/#dom-node-parentnode - pub fn GetParentNode(&self) -> Option<JS<Node>> { - self.parent_node.clone() + pub fn GetParentNode(&self) -> Option<Unrooted<Node>> { + self.parent_node.clone().map(|node| Unrooted::new(node)) } // http://dom.spec.whatwg.org/#dom-node-parentelement - pub fn GetParentElement(&self) -> Option<JS<Element>> { - self.parent_node.clone().and_then(|parent| ElementCast::to(&parent)) + pub fn GetParentElement(&self) -> Option<Unrooted<Element>> { + let roots = RootCollection::new(); + self.parent_node.clone() + .and_then(|parent| { + let parent = parent.root(&roots); + ElementCast::to_ref(&*parent).map(|elem| { + Unrooted::new_rooted(elem) + }) + }) } // http://dom.spec.whatwg.org/#dom-node-haschildnodes @@ -947,39 +977,37 @@ impl Node { } // http://dom.spec.whatwg.org/#dom-node-childnodes - pub fn ChildNodes(&mut self, abstract_self: &JSRef<Node>) -> JS<NodeList> { + pub fn ChildNodes(&mut self, abstract_self: &JSRef<Node>) -> Unrooted<NodeList> { let roots = RootCollection::new(); match self.child_list { None => { - let doc = self.owner_doc().clone(); - let doc = doc.get(); - let window = doc.window.root(&roots); - let list = NodeList::new_child_list(&window.root_ref(), abstract_self); - self.child_list = Some(list.clone()); - list + let doc = self.owner_doc().root(&roots); + let window = doc.deref().window.root(&roots); + self.child_list.assign(Some(NodeList::new_child_list(&*window, abstract_self))); + Unrooted::new(self.child_list.get_ref().clone()) } - Some(ref list) => list.clone() + Some(ref list) => Unrooted::new(list.clone()) } } // http://dom.spec.whatwg.org/#dom-node-firstchild - pub fn GetFirstChild(&self) -> Option<JS<Node>> { - self.first_child.clone() + pub fn GetFirstChild(&self) -> Option<Unrooted<Node>> { + self.first_child.clone().map(|node| Unrooted::new(node)) } // http://dom.spec.whatwg.org/#dom-node-lastchild - pub fn GetLastChild(&self) -> Option<JS<Node>> { - self.last_child.clone() + pub fn GetLastChild(&self) -> Option<Unrooted<Node>> { + self.last_child.clone().map(|node| Unrooted::new(node)) } // http://dom.spec.whatwg.org/#dom-node-previoussibling - pub fn GetPreviousSibling(&self) -> Option<JS<Node>> { - self.prev_sibling.clone() + pub fn GetPreviousSibling(&self) -> Option<Unrooted<Node>> { + self.prev_sibling.clone().map(|node| Unrooted::new(node)) } // http://dom.spec.whatwg.org/#dom-node-nextsibling - pub fn GetNextSibling(&self) -> Option<JS<Node>> { - self.next_sibling.clone() + pub fn GetNextSibling(&self) -> Option<Unrooted<Node>> { + self.next_sibling.clone().map(|node| Unrooted::new(node)) } // http://dom.spec.whatwg.org/#dom-node-nodevalue @@ -1012,13 +1040,14 @@ impl Node { // http://dom.spec.whatwg.org/#dom-node-textcontent pub fn GetTextContent(&self, abstract_self: &JSRef<Node>) -> Option<DOMString> { + let roots = RootCollection::new(); match self.type_id { DocumentFragmentNodeTypeId | ElementNodeTypeId(..) => { let mut content = ~""; - for node in abstract_self.unrooted().traverse_preorder() { + for node in abstract_self.traverse_preorder(&roots) { if node.is_text() { - let text: JS<Text> = TextCast::to(&node).unwrap(); + let text: &JSRef<Text> = TextCast::to_ref(&node).unwrap(); content.push_str(text.get().characterdata.data.as_slice()); } } @@ -1027,7 +1056,7 @@ impl Node { CommentNodeTypeId | TextNodeTypeId | ProcessingInstructionNodeTypeId => { - let characterdata: JS<CharacterData> = CharacterDataCast::to(&abstract_self.unrooted()).unwrap(); + let characterdata: &JSRef<CharacterData> = CharacterDataCast::to_ref(abstract_self).unwrap(); Some(characterdata.get().Data()) } DoctypeNodeTypeId | @@ -1051,9 +1080,8 @@ impl Node { } else { let document = self.owner_doc(); let document = document.root(&roots); - Some(NodeCast::from(&document.get().CreateTextNode(&document.root_ref(), value))) - }; - let node = node.map(|node| node.root(&roots)); + Some(NodeCast::from_unrooted(document.deref().CreateTextNode(&*document, value))) + }.root(&roots); // Step 3. Node::replace_all(node.root_ref(), abstract_self); @@ -1067,7 +1095,7 @@ impl Node { characterdata.get_mut().data = value.clone(); // Notify the document that the content of this node is different - let document = self.owner_doc(); + let document = self.owner_doc().root(&roots); document.get().content_changed(); } DoctypeNodeTypeId | @@ -1077,21 +1105,20 @@ impl Node { } // http://dom.spec.whatwg.org/#concept-node-adopt - pub fn adopt(node_root: &mut JSRef<Node>, document: &JSRef<Document>) { + pub fn adopt(node: &mut JSRef<Node>, document: &JSRef<Document>) { let roots = RootCollection::new(); - let node = node_root.unrooted(); // Step 1. - match node.parent_node() { - Some(ref mut parent) => { - let parent = parent.root(&roots); - Node::remove(node_root, &mut parent.root_ref(), Unsuppressed); + match node.parent_node().root(&roots) { + Some(mut parent) => { + Node::remove(node, &mut *parent, Unsuppressed); } None => (), } // Step 2. - if document_from_node(&node) != document.unrooted() { - for mut descendant in node.traverse_preorder() { + let node_doc = document_from_node(node).root(&roots); + if &*node_doc != document { + for mut descendant in node.traverse_preorder(&roots) { descendant.get_mut().set_owner_doc(document); } } @@ -1101,11 +1128,9 @@ impl Node { } // http://dom.spec.whatwg.org/#concept-node-pre-insert - fn pre_insert(node_root: &mut JSRef<Node>, parent_root: &mut JSRef<Node>, child: Option<JSRef<Node>>) - -> Fallible<JS<Node>> { + fn pre_insert(node: &mut JSRef<Node>, parent: &mut JSRef<Node>, child: Option<JSRef<Node>>) + -> Fallible<Unrooted<Node>> { let roots = RootCollection::new(); - let node = node_root.unrooted(); - let parent = parent_root.unrooted(); // Step 1. match parent.type_id() { DocumentNodeTypeId | @@ -1115,7 +1140,7 @@ impl Node { } // Step 2. - if node.is_inclusive_ancestor_of(parent_root) { + if node.is_inclusive_ancestor_of(parent) { return Err(HierarchyRequest); } @@ -1128,13 +1153,13 @@ impl Node { // Step 4-5. match node.type_id() { TextNodeTypeId => { - match node.parent_node() { + match node.parent_node().root(&roots) { Some(ref parent) if parent.is_document() => return Err(HierarchyRequest), _ => () } } DoctypeNodeTypeId => { - match node.parent_node() { + match node.parent_node().root(&roots) { Some(ref parent) if !parent.is_document() => return Err(HierarchyRequest), _ => () } @@ -1147,7 +1172,6 @@ impl Node { } // Step 6. - let child = child.map(|child| child.unrooted()); match parent.type_id() { DocumentNodeTypeId => { match node.type_id() { @@ -1168,7 +1192,7 @@ impl Node { } match child { Some(ref child) if child.inclusively_following_siblings() - .any(|child| child.is_doctype()) => { + .any(|child| child.deref().is_doctype()) => { return Err(HierarchyRequest); } _ => (), @@ -1187,7 +1211,7 @@ impl Node { } match child { Some(ref child) if child.inclusively_following_siblings() - .any(|child| child.is_doctype()) => { + .any(|child| child.deref().is_doctype()) => { return Err(HierarchyRequest); } _ => (), @@ -1195,14 +1219,14 @@ impl Node { }, // Step 6.3 DoctypeNodeTypeId => { - if parent.children().any(|c| c.is_doctype()) { + if parent.children().any(|c| c.deref().is_doctype()) { return Err(HierarchyRequest); } match child { Some(ref child) => { if parent.children() .take_while(|c| c != child) - .any(|c| c.is_element()) { + .any(|c| c.deref().is_element()) { return Err(HierarchyRequest); } }, @@ -1226,31 +1250,26 @@ impl Node { // Step 7-8. let referenceChild = match child { - Some(ref child) if child == &node => node.next_sibling(), + Some(ref child) if child == node => node.next_sibling().map(|node| (*node.root(&roots)).clone()), _ => child }; - let referenceChild = referenceChild.map(|child| child.root(&roots)); // Step 9. - let document = document_from_node(&parent); - let document = document.root(&roots); - Node::adopt(node_root, &document.root_ref()); + let document = document_from_node(parent).root(&roots); + Node::adopt(node, &*document); // Step 10. - Node::insert(node_root, parent_root, referenceChild.root_ref(), Unsuppressed); + Node::insert(node, parent, referenceChild, Unsuppressed); // Step 11. - return Ok(node) + return Ok(Unrooted::new_rooted(node)) } // http://dom.spec.whatwg.org/#concept-node-insert - fn insert(node_root: &mut JSRef<Node>, - parent_root: &mut JSRef<Node>, + fn insert(node: &mut JSRef<Node>, + parent: &mut JSRef<Node>, child: Option<JSRef<Node>>, suppress_observers: SuppressObserver) { - let roots = RootCollection::new(); - let node = node_root.unrooted(); - let mut parent = parent_root.unrooted(); // XXX assert owner_doc // Step 1-3: ranges. // Step 4. @@ -1263,9 +1282,8 @@ impl Node { // Step 6: DocumentFragment. match node.type_id() { DocumentFragmentNodeTypeId => { - for c in node.children() { - let c = c.root(&roots); - Node::remove(&mut c.root_ref(), node_root, Suppressed); + for mut c in node.children() { + Node::remove(&mut c, node, Suppressed); } }, _ => (), @@ -1274,7 +1292,7 @@ impl Node { // Step 7: mutation records. // Step 8. for node in nodes.mut_iter() { - parent.add_child(node_root, child.clone()); + parent.add_child(node, child.clone()); node.get_mut().flags.set_is_in_doc(parent.is_in_doc()); } @@ -1290,23 +1308,20 @@ impl Node { } // http://dom.spec.whatwg.org/#concept-node-replace-all - pub fn replace_all(mut node_root: Option<JSRef<Node>>, parent_root: &mut JSRef<Node>) { + pub fn replace_all(mut node: Option<JSRef<Node>>, parent: &mut JSRef<Node>) { let roots = RootCollection::new(); - let node = node_root.as_ref().map(|node| node.unrooted()); - let parent = parent_root.unrooted(); // Step 1. - match node_root { + match node { Some(ref mut node) => { - let document = document_from_node(&parent); - let document = document.root(&roots); - Node::adopt(node, &document.root_ref()); + let document = document_from_node(parent).root(&roots); + Node::adopt(node, &*document); } None => (), } // Step 2. - let removedNodes: Vec<JS<Node>> = parent.children().collect(); + let removedNodes: Vec<JSRef<Node>> = parent.children().collect(); // Step 3. let addedNodes = match node { @@ -1318,14 +1333,13 @@ impl Node { }; // Step 4. - for child in parent.children() { - let child = child.root(&roots); - Node::remove(&mut child.root_ref(), parent_root, Suppressed); + for mut child in parent.children() { + Node::remove(&mut child, parent, Suppressed); } // Step 5. - match node_root { - Some(ref mut node) => Node::insert(node, parent_root, None, Suppressed), + match node { + Some(ref mut node) => Node::insert(node, parent, None, Suppressed), None => (), } @@ -1341,10 +1355,10 @@ impl Node { } // http://dom.spec.whatwg.org/#concept-node-pre-remove - fn pre_remove(child: &mut JSRef<Node>, parent: &mut JSRef<Node>) -> Fallible<JS<Node>> { + fn pre_remove(child: &mut JSRef<Node>, parent: &mut JSRef<Node>) -> Fallible<Unrooted<Node>> { // Step 1. - match child.unrooted().parent_node() { - Some(ref node) if node != &parent.unrooted() => return Err(NotFound), + match child.parent_node() { + Some(ref node) if *node != Unrooted::new_rooted(parent) => return Err(NotFound), _ => () } @@ -1352,19 +1366,17 @@ impl Node { Node::remove(child, parent, Unsuppressed); // Step 3. - Ok(child.unrooted()) + Ok(Unrooted::new_rooted(child)) } // http://dom.spec.whatwg.org/#concept-node-remove - fn remove(node_root: &mut JSRef<Node>, parent: &mut JSRef<Node>, suppress_observers: SuppressObserver) { - let mut parent = parent.unrooted(); - let mut node = node_root.unrooted(); - assert!(node.parent_node().map_or(false, |ref node_parent| node_parent == &parent)); + fn remove(node: &mut JSRef<Node>, parent: &mut JSRef<Node>, suppress_observers: SuppressObserver) { + assert!(node.parent_node().map_or(false, |node_parent| node_parent == Unrooted::new_rooted(parent))); // Step 1-5: ranges. // Step 6-7: mutation observers. // Step 8. - parent.remove_child(node_root); + parent.remove_child(node); node.get_mut().flags.set_is_in_doc(false); // Step 9. @@ -1376,94 +1388,95 @@ impl Node { // http://dom.spec.whatwg.org/#concept-node-clone pub fn clone(node: &JSRef<Node>, maybe_doc: Option<&JSRef<Document>>, - clone_children: CloneChildrenFlag) -> JS<Node> { + clone_children: CloneChildrenFlag) -> Unrooted<Node> { let roots = RootCollection::new(); // Step 1. let mut document = match maybe_doc { - Some(doc) => doc.unrooted(), - None => node.get().owner_doc().clone() + Some(doc) => doc.unrooted().root(&roots), + None => node.get().owner_doc().root(&roots) }; - let document_root = document.root(&roots); // Step 2. // XXXabinader: clone() for each node as trait? - let copy: JS<Node> = match node.get().type_id { + let mut copy: Root<Node> = match node.type_id() { DoctypeNodeTypeId => { - let doctype: JS<DocumentType> = DocumentTypeCast::to(&node.unrooted()).unwrap(); + let doctype: &JSRef<DocumentType> = DocumentTypeCast::to_ref(node).unwrap(); let doctype = doctype.get(); let doctype = DocumentType::new(doctype.name.clone(), Some(doctype.public_id.clone()), - Some(doctype.system_id.clone()), &document_root.root_ref()); - NodeCast::from(&doctype) + Some(doctype.system_id.clone()), &*document); + NodeCast::from_unrooted(doctype) }, DocumentFragmentNodeTypeId => { - let doc_fragment = DocumentFragment::new(&document_root.root_ref()); - NodeCast::from(&doc_fragment) + let doc_fragment = DocumentFragment::new(&*document); + NodeCast::from_unrooted(doc_fragment) }, CommentNodeTypeId => { - let comment: JS<Comment> = CommentCast::to(&node.unrooted()).unwrap(); + let comment: &JSRef<Comment> = CommentCast::to_ref(node).unwrap(); let comment = comment.get(); - let comment = Comment::new(comment.characterdata.data.clone(), &document_root.root_ref()); - NodeCast::from(&comment) + let comment = Comment::new(comment.characterdata.data.clone(), &*document); + NodeCast::from_unrooted(comment) }, DocumentNodeTypeId => { - let document: JS<Document> = DocumentCast::to(&node.unrooted()).unwrap(); + let document: &JSRef<Document> = DocumentCast::to_ref(node).unwrap(); let document = document.get(); let is_html_doc = match document.is_html_document { true => HTMLDocument, false => NonHTMLDocument }; let window = document.window.root(&roots); - let document = Document::new(&window.root_ref(), Some(document.url().clone()), + let document = Document::new(&*window, Some(document.url().clone()), is_html_doc, None); - NodeCast::from(&document) + NodeCast::from_unrooted(document) }, ElementNodeTypeId(..) => { - let element: JS<Element> = ElementCast::to(&node.unrooted()).unwrap(); + let element: &JSRef<Element> = ElementCast::to_ref(node).unwrap(); let element = element.get(); - let element = build_element_from_tag(element.local_name.clone(), &document_root.root_ref()); - NodeCast::from(&element) + let element = build_element_from_tag(element.local_name.clone(), &*document); + NodeCast::from_unrooted(element) }, TextNodeTypeId => { - let text: JS<Text> = TextCast::to(&node.unrooted()).unwrap(); + let text: &JSRef<Text> = TextCast::to_ref(node).unwrap(); let text = text.get(); - let text = Text::new(text.characterdata.data.clone(), &document_root.root_ref()); - NodeCast::from(&text) + let text = Text::new(text.characterdata.data.clone(), &*document); + NodeCast::from_unrooted(text) }, ProcessingInstructionNodeTypeId => { - let pi: JS<ProcessingInstruction> = ProcessingInstructionCast::to(&node.unrooted()).unwrap(); + let pi: &JSRef<ProcessingInstruction> = ProcessingInstructionCast::to_ref(node).unwrap(); let pi = pi.get(); let pi = ProcessingInstruction::new(pi.target.clone(), - pi.characterdata.data.clone(), &document_root.root_ref()); - NodeCast::from(&pi) + pi.characterdata.data.clone(), &*document); + NodeCast::from_unrooted(pi) }, - }; + }.root(&roots); // Step 3. - if copy.is_document() { - document = DocumentCast::to(©).unwrap(); - } - let document_root = document.root(&roots); - assert!(copy.get().owner_doc() == &document); + let document = if copy.is_document() { + let doc: &JSRef<Document> = DocumentCast::to_ref(&*copy).unwrap(); + doc.unrooted().root(&roots) + } else { + document.unrooted().root(&roots) + }; + assert!(&*copy.get().owner_doc().root(&roots) == &*document); // Step 4 (some data already copied in step 2). match node.get().type_id { DocumentNodeTypeId => { - let node_doc: JS<Document> = DocumentCast::to(&node.unrooted()).unwrap(); + let node_doc: &JSRef<Document> = DocumentCast::to_ref(node).unwrap(); let node_doc = node_doc.get(); - let mut copy_doc: JS<Document> = DocumentCast::to(©).unwrap(); + let copy_doc: &mut JSRef<Document> = DocumentCast::to_mut_ref(&mut *copy).unwrap(); let copy_doc = copy_doc.get_mut(); copy_doc.set_encoding_name(node_doc.encoding_name.clone()); copy_doc.set_quirks_mode(node_doc.quirks_mode()); }, ElementNodeTypeId(..) => { - let node_elem: JS<Element> = ElementCast::to(&node.unrooted()).unwrap(); + let node_elem: &JSRef<Element> = ElementCast::to_ref(node).unwrap(); let node_elem = node_elem.get(); - let mut copy_elem: JS<Element> = ElementCast::to(©).unwrap(); + let copy_elem: &mut JSRef<Element> = ElementCast::to_mut_ref(&mut *copy).unwrap(); // XXX: to avoid double borrowing compile error. we might be able to fix this after #1854 - let copy_elem_alias: JS<Element> = copy_elem.clone(); + let copy_elem_alias = copy_elem.clone(); let copy_elem = copy_elem.get_mut(); // FIXME: https://github.com/mozilla/servo/issues/1737 @@ -1471,10 +1484,11 @@ impl Node { let window = document.get().window.root(&roots); for attr in node_elem.attrs.iter() { let attr = attr.get(); - copy_elem.attrs.push(Attr::new(&window.root_ref(), - attr.local_name.clone(), attr.value.clone(), - attr.name.clone(), attr.namespace.clone(), - attr.prefix.clone(), copy_elem_alias.clone())); + copy_elem.attrs.push_unrooted( + Attr::new(&*window, + attr.local_name.clone(), attr.value.clone(), + attr.name.clone(), attr.namespace.clone(), + attr.prefix.clone(), ©_elem_alias)); } }, _ => () @@ -1485,41 +1499,37 @@ impl Node { // Step 6. if clone_children == CloneChildren { for ref child in node.get().children() { - let child = child.root(&roots); - let child_copy = Node::clone(&child.root_ref(), Some(&document_root.root_ref()), clone_children).root(&roots); - let copy = copy.root(&roots); - let _inserted_node = Node::pre_insert(&mut child_copy.root_ref(), &mut copy.root_ref(), None); + let mut child_copy = Node::clone(&*child, Some(&*document), clone_children).root(&roots); + let _inserted_node = Node::pre_insert(&mut *child_copy, &mut *copy, None); } } // Step 7. - copy + Unrooted::new_rooted(&*copy) } // http://dom.spec.whatwg.org/#dom-node-insertbefore pub fn InsertBefore(&self, abstract_self: &mut JSRef<Node>, node: &mut JSRef<Node>, child: Option<JSRef<Node>>) - -> Fallible<JS<Node>> { + -> Fallible<Unrooted<Node>> { Node::pre_insert(node, abstract_self, child) } pub fn wait_until_safe_to_modify_dom(&self) { - let document = self.owner_doc(); + let roots = RootCollection::new(); + let document = self.owner_doc().root(&roots); document.get().wait_until_safe_to_modify_dom(); } // http://dom.spec.whatwg.org/#dom-node-appendchild pub fn AppendChild(&self, abstract_self: &mut JSRef<Node>, node: &mut JSRef<Node>) - -> Fallible<JS<Node>> { + -> Fallible<Unrooted<Node>> { Node::pre_insert(node, abstract_self, None) } // http://dom.spec.whatwg.org/#concept-node-replace - pub fn ReplaceChild(&self, parent_root: &mut JSRef<Node>, node_root: &mut JSRef<Node>, child_root: &mut JSRef<Node>) - -> Fallible<JS<Node>> { + pub fn ReplaceChild(&self, parent: &mut JSRef<Node>, node: &mut JSRef<Node>, child: &mut JSRef<Node>) + -> Fallible<Unrooted<Node>> { let roots = RootCollection::new(); - let parent = parent_root.unrooted(); - let node = node_root.unrooted(); - let child = child_root.unrooted(); // Step 1. match parent.type_id() { @@ -1530,12 +1540,12 @@ impl Node { } // Step 2. - if node.is_inclusive_ancestor_of(parent_root) { + if node.is_inclusive_ancestor_of(parent) { return Err(HierarchyRequest); } // Step 3. - if !parent.is_parent_of(child_root) { + if !parent.is_parent_of(child) { return Err(NotFound); } @@ -1566,11 +1576,11 @@ impl Node { 0 => (), // Step 6.1.2 1 => { - if parent.child_elements().any(|c| NodeCast::from(&c) != child) { + if parent.child_elements().any(|c| NodeCast::from_ref(&c) != child) { return Err(HierarchyRequest); } if child.following_siblings() - .any(|child| child.is_doctype()) { + .any(|child| child.deref().is_doctype()) { return Err(HierarchyRequest); } }, @@ -1580,22 +1590,22 @@ impl Node { }, // Step 6.2 ElementNodeTypeId(..) => { - if parent.child_elements().any(|c| NodeCast::from(&c) != child) { + if parent.child_elements().any(|c| NodeCast::from_ref(&c) != child) { return Err(HierarchyRequest); } if child.following_siblings() - .any(|child| child.is_doctype()) { + .any(|child| child.deref().is_doctype()) { return Err(HierarchyRequest); } }, // Step 6.3 DoctypeNodeTypeId => { - if parent.children().any(|c| c.is_doctype() && c != child) { + if parent.children().any(|c| c.deref().is_doctype() && &c != child) { return Err(HierarchyRequest); } if parent.children() - .take_while(|c| c != &child) - .any(|c| c.is_element()) { + .take_while(|c| c != child) + .any(|c| c.deref().is_element()) { return Err(HierarchyRequest); } }, @@ -1609,29 +1619,27 @@ impl Node { } // Ok if not caught by previous error checks. - if node == child { - return Ok(child); + if node.unrooted() == child.unrooted() { + return Ok(Unrooted::new_rooted(child)); } // Step 7-8. - let next_sibling = child.next_sibling(); + let next_sibling = child.next_sibling().map(|node| (*node.root(&roots)).clone()); let reference_child = match next_sibling { - Some(ref sibling) if sibling == &node => node.next_sibling(), + Some(ref sibling) if sibling == node => node.next_sibling().map(|node| (*node.root(&roots)).clone()), _ => next_sibling }; - let reference_child = reference_child.map(|child| child.root(&roots)); // Step 9. - let document = document_from_node(&parent); - let document = document.root(&roots); - Node::adopt(node_root, &document.root_ref()); + let document = document_from_node(parent).root(&roots); + Node::adopt(node, &*document); { // Step 10. - Node::remove(child_root, parent_root, Suppressed); + Node::remove(child, parent, Suppressed); // Step 11. - Node::insert(node_root, parent_root, reference_child.root_ref(), Suppressed); + Node::insert(node, parent, reference_child, Suppressed); } // Step 12-14. @@ -1646,40 +1654,38 @@ impl Node { } // Step 15. - Ok(child) + Ok(Unrooted::new_rooted(child)) } // http://dom.spec.whatwg.org/#dom-node-removechild pub fn RemoveChild(&self, abstract_self: &mut JSRef<Node>, node: &mut JSRef<Node>) - -> Fallible<JS<Node>> { + -> Fallible<Unrooted<Node>> { Node::pre_remove(node, abstract_self) } // http://dom.spec.whatwg.org/#dom-node-normalize pub fn Normalize(&mut self, abstract_self: &mut JSRef<Node>) { let roots = RootCollection::new(); - let mut abstract_self = abstract_self.unrooted(); let mut prev_text = None; for mut child in self.children() { if child.is_text() { - let characterdata: JS<CharacterData> = CharacterDataCast::to(&child).unwrap(); + let mut child_alias = child.clone(); + let characterdata: &JSRef<CharacterData> = CharacterDataCast::to_ref(&child).unwrap(); if characterdata.get().Length() == 0 { - let child = child.root(&roots); - abstract_self.remove_child(&mut child.root_ref()); + abstract_self.remove_child(&mut child_alias); } else { match prev_text { - Some(ref text_node) => { - let mut prev_characterdata: JS<CharacterData> = CharacterDataCast::to(text_node).unwrap(); + Some(ref mut text_node) => { + let prev_characterdata: &mut JSRef<CharacterData> = CharacterDataCast::to_mut_ref(text_node).unwrap(); let _ = prev_characterdata.get_mut().AppendData(characterdata.get().Data()); - let child = child.root(&roots); - abstract_self.remove_child(&mut child.root_ref()); + abstract_self.remove_child(&mut child_alias); }, - None => prev_text = Some(child) + None => prev_text = Some(child_alias) } } } else { - let c = child.root(&roots); - child.get_mut().Normalize(&mut c.root_ref()); + let mut c = child.clone(); + child.get_mut().Normalize(&mut c); prev_text = None; } @@ -1687,7 +1693,7 @@ impl Node { } // http://dom.spec.whatwg.org/#dom-node-clonenode - pub fn CloneNode(&self, abstract_self: &mut JSRef<Node>, deep: bool) -> JS<Node> { + pub fn CloneNode(&self, abstract_self: &mut JSRef<Node>, deep: bool) -> Unrooted<Node> { match deep { true => Node::clone(abstract_self, None, CloneChildren), false => Node::clone(abstract_self, None, DoNotCloneChildren) @@ -1735,16 +1741,12 @@ impl Node { }) } fn is_equal_node(this: &JSRef<Node>, node: &JSRef<Node>) -> bool { - let roots = RootCollection::new(); - let this_node = this.unrooted(); - let other = node.unrooted(); - // Step 2. - if this_node.type_id() != other.type_id() { + if this.type_id() != node.type_id() { return false; } - match other.type_id() { + match node.type_id() { // Step 3. DoctypeNodeTypeId if !is_equal_doctype(this, node) => return false, ElementNodeTypeId(..) if !is_equal_element(this, node) => return false, @@ -1757,15 +1759,13 @@ impl Node { } // Step 5. - if this_node.children().len() != other.children().len() { + if this.children().len() != node.children().len() { return false; } // Step 6. - this_node.children().zip(other.children()).all(|(ref child, ref other_child)| { - let child = child.root(&roots); - let other_child = other_child.root(&roots); - is_equal_node(&child.root_ref(), &other_child.root_ref()) + this.children().zip(node.children()).all(|(ref child, ref other_child)| { + is_equal_node(child, other_child) }) } match maybe_node { @@ -1777,9 +1777,8 @@ impl Node { } // http://dom.spec.whatwg.org/#dom-node-comparedocumentposition - pub fn CompareDocumentPosition(&self, abstract_self_root: &JSRef<Node>, other_root: &JSRef<Node>) -> u16 { - let other = other_root.unrooted(); - let abstract_self = abstract_self_root.unrooted(); + pub fn CompareDocumentPosition(&self, abstract_self: &JSRef<Node>, other: &JSRef<Node>) -> u16 { + let roots = RootCollection::new(); if abstract_self == other { // step 2. 0 @@ -1787,25 +1786,25 @@ impl Node { let mut lastself = abstract_self.clone(); let mut lastother = other.clone(); for ancestor in abstract_self.ancestors() { - if ancestor == other { + if &ancestor == other { // step 4. return NodeConstants::DOCUMENT_POSITION_CONTAINS + NodeConstants::DOCUMENT_POSITION_PRECEDING; } - lastself = ancestor; + lastself = ancestor.clone(); } for ancestor in other.ancestors() { - if ancestor == abstract_self { + if &ancestor == abstract_self { // step 5. return NodeConstants::DOCUMENT_POSITION_CONTAINED_BY + NodeConstants::DOCUMENT_POSITION_FOLLOWING; } - lastother = ancestor; + lastother = ancestor.clone(); } if lastself != lastother { - let abstract_uint: uintptr_t = as_uintptr(&abstract_self.get()); - let other_uint: uintptr_t = as_uintptr(&other.get()); + let abstract_uint: uintptr_t = as_uintptr(&*abstract_self); + let other_uint: uintptr_t = as_uintptr(&*other); let random = if abstract_uint < other_uint { NodeConstants::DOCUMENT_POSITION_FOLLOWING @@ -1818,12 +1817,12 @@ impl Node { NodeConstants::DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC; } - for child in lastself.traverse_preorder() { - if child == other { + for child in lastself.traverse_preorder(&roots) { + if &child == other { // step 6. return NodeConstants::DOCUMENT_POSITION_PRECEDING; } - if child == abstract_self { + if &child == abstract_self { // step 7. return NodeConstants::DOCUMENT_POSITION_FOLLOWING; } @@ -1836,7 +1835,7 @@ impl Node { pub fn Contains(&self, abstract_self: &JSRef<Node>, maybe_other: Option<JSRef<Node>>) -> bool { match maybe_other { None => false, - Some(ref other) => abstract_self.unrooted().is_inclusive_ancestor_of(other) + Some(ref other) => abstract_self.is_inclusive_ancestor_of(other) } } @@ -1863,33 +1862,38 @@ impl Node { // pub fn set_parent_node(&mut self, new_parent_node: Option<JSRef<Node>>) { - let doc = self.owner_doc().clone(); + let roots = RootCollection::new(); + let doc = self.owner_doc().root(&roots); doc.get().wait_until_safe_to_modify_dom(); - self.parent_node = new_parent_node.map(|node| node.unrooted()) + self.parent_node.assign(new_parent_node); } pub fn set_first_child(&mut self, new_first_child: Option<JSRef<Node>>) { - let doc = self.owner_doc().clone(); + let roots = RootCollection::new(); + let doc = self.owner_doc().root(&roots); doc.get().wait_until_safe_to_modify_dom(); - self.first_child = new_first_child.map(|node| node.unrooted()) + self.first_child.assign(new_first_child); } pub fn set_last_child(&mut self, new_last_child: Option<JSRef<Node>>) { - let doc = self.owner_doc().clone(); + let roots = RootCollection::new(); + let doc = self.owner_doc().root(&roots); doc.get().wait_until_safe_to_modify_dom(); - self.last_child = new_last_child.map(|node| node.unrooted()) + self.last_child.assign(new_last_child); } pub fn set_prev_sibling(&mut self, new_prev_sibling: Option<JSRef<Node>>) { - let doc = self.owner_doc().clone(); + let roots = RootCollection::new(); + let doc = self.owner_doc().root(&roots); doc.get().wait_until_safe_to_modify_dom(); - self.prev_sibling = new_prev_sibling.map(|node| node.unrooted()) + self.prev_sibling.assign(new_prev_sibling); } pub fn set_next_sibling(&mut self, new_next_sibling: Option<JSRef<Node>>) { - let doc = self.owner_doc().clone(); + let roots = RootCollection::new(); + let doc = self.owner_doc().root(&roots); doc.get().wait_until_safe_to_modify_dom(); - self.next_sibling = new_next_sibling.map(|node| node.unrooted()) + self.next_sibling.assign(new_next_sibling); } pub fn get_hover_state(&self) -> bool { @@ -1940,19 +1944,20 @@ impl Reflectable for Node { } } -pub fn document_from_node<T: NodeBase>(derived: &JS<T>) -> JS<Document> { - let node: JS<Node> = NodeCast::from(derived); - node.get().owner_doc().clone() +pub fn document_from_node<T: NodeBase>(derived: &JSRef<T>) -> Unrooted<Document> { + let node: &JSRef<Node> = NodeCast::from_ref(derived); + node.owner_doc() } -pub fn window_from_node<T: NodeBase>(derived: &JS<T>) -> JS<Window> { - let document: JS<Document> = document_from_node(derived); - document.get().window.clone() +pub fn window_from_node<T: NodeBase>(derived: &JSRef<T>) -> Unrooted<Window> { + let roots = RootCollection::new(); + let document = document_from_node(derived).root(&roots); + Unrooted::new(document.deref().window.clone()) } -impl VirtualMethods for JS<Node> { +impl<'a> VirtualMethods for JSRef<'a, Node> { fn super_type(&self) -> Option<~VirtualMethods:> { - let eventtarget: JS<EventTarget> = EventTargetCast::from(self); - Some(~eventtarget as ~VirtualMethods:) + let eventtarget: &JSRef<EventTarget> = EventTargetCast::from_ref(self); + Some(~eventtarget.clone() as ~VirtualMethods:) } } diff --git a/src/components/script/dom/nodelist.rs b/src/components/script/dom/nodelist.rs index 751c15ab098..219731034f1 100644 --- a/src/components/script/dom/nodelist.rs +++ b/src/components/script/dom/nodelist.rs @@ -3,7 +3,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use dom::bindings::codegen::BindingDeclarations::NodeListBinding; -use dom::bindings::js::{JS, JSRef}; +use dom::bindings::js::{JS, JSRef, Unrooted, RootCollection}; use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object}; use dom::node::{Node, NodeHelpers}; use dom::window::Window; @@ -32,35 +32,44 @@ impl NodeList { } pub fn new(window: &JSRef<Window>, - list_type: NodeListType) -> JS<NodeList> { + list_type: NodeListType) -> Unrooted<NodeList> { reflect_dom_object(~NodeList::new_inherited(window.unrooted(), list_type), window, NodeListBinding::Wrap) } - pub fn new_simple_list(window: &JSRef<Window>, elements: Vec<JS<Node>>) -> JS<NodeList> { - NodeList::new(window, Simple(elements)) + pub fn new_simple_list(window: &JSRef<Window>, elements: Vec<JSRef<Node>>) -> Unrooted<NodeList> { + NodeList::new(window, Simple(elements.iter().map(|element| element.unrooted()).collect())) } - pub fn new_child_list(window: &JSRef<Window>, node: &JSRef<Node>) -> JS<NodeList> { + pub fn new_child_list(window: &JSRef<Window>, node: &JSRef<Node>) -> Unrooted<NodeList> { NodeList::new(window, Children(node.unrooted())) } pub fn Length(&self) -> u32 { + let roots = RootCollection::new(); match self.list_type { Simple(ref elems) => elems.len() as u32, - Children(ref node) => node.children().len() as u32 + Children(ref node) => { + let node = node.root(&roots); + node.deref().children().len() as u32 + } } } - pub fn Item(&self, index: u32) -> Option<JS<Node>> { + pub fn Item(&self, index: u32) -> Option<Unrooted<Node>> { + let roots = RootCollection::new(); match self.list_type { _ if index >= self.Length() => None, - Simple(ref elems) => Some(elems.get(index as uint).clone()), - Children(ref node) => node.children().nth(index as uint) + Simple(ref elems) => Some(Unrooted::new(elems.get(index as uint).clone())), + Children(ref node) => { + let node = node.root(&roots); + node.deref().children().nth(index as uint) + .map(|child| Unrooted::new_rooted(&child)) + } } } - pub fn IndexedGetter(&self, index: u32, found: &mut bool) -> Option<JS<Node>> { + pub fn IndexedGetter(&self, index: u32, found: &mut bool) -> Option<Unrooted<Node>> { let item = self.Item(index); *found = item.is_some(); item diff --git a/src/components/script/dom/processinginstruction.rs b/src/components/script/dom/processinginstruction.rs index 7064f8d3ca7..c094e4ae654 100644 --- a/src/components/script/dom/processinginstruction.rs +++ b/src/components/script/dom/processinginstruction.rs @@ -4,7 +4,7 @@ use dom::bindings::codegen::BindingDeclarations::ProcessingInstructionBinding; use dom::bindings::codegen::InheritTypes::ProcessingInstructionDerived; -use dom::bindings::js::{JS, JSRef}; +use dom::bindings::js::{JS, JSRef, Unrooted}; use dom::characterdata::CharacterData; use dom::document::Document; use dom::eventtarget::{EventTarget, NodeTargetTypeId}; @@ -35,7 +35,7 @@ impl ProcessingInstruction { } } - pub fn new(target: DOMString, data: DOMString, document: &JSRef<Document>) -> JS<ProcessingInstruction> { + pub fn new(target: DOMString, data: DOMString, document: &JSRef<Document>) -> Unrooted<ProcessingInstruction> { let node = ProcessingInstruction::new_inherited(target, data, document.unrooted()); Node::reflect_node(~node, document, ProcessingInstructionBinding::Wrap) } diff --git a/src/components/script/dom/testbinding.rs b/src/components/script/dom/testbinding.rs index e05cec800bb..76bb587b134 100644 --- a/src/components/script/dom/testbinding.rs +++ b/src/components/script/dom/testbinding.rs @@ -2,7 +2,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -use dom::bindings::js::{JS, JSRef, RootCollection}; +use dom::bindings::js::{JS, JSRef, RootCollection, Unrooted}; use dom::bindings::codegen::BindingDeclarations::TestBindingBinding; use dom::bindings::codegen::UnionTypes::HTMLElementOrLong; use self::TestBindingBinding::TestEnum; @@ -51,10 +51,10 @@ impl TestBinding { pub fn SetByteStringAttribute(&self, _: ByteString) {} pub fn EnumAttribute(&self) -> TestEnum { _empty } pub fn SetEnumAttribute(&self, _: TestEnum) {} - pub fn InterfaceAttribute(&self) -> JS<Blob> { + pub fn InterfaceAttribute(&self) -> Unrooted<Blob> { let roots = RootCollection::new(); let window = self.window.root(&roots); - Blob::new(&window.root_ref()) + Blob::new(&*window) } pub fn SetInterfaceAttribute(&self, _: &JSRef<Blob>) {} pub fn AnyAttribute(&self, _: *JSContext) -> JSVal { NullValue() } @@ -87,10 +87,10 @@ impl TestBinding { pub fn GetStringAttributeNullable(&self) -> Option<DOMString> { Some(~"") } pub fn SetStringAttributeNullable(&self, _: Option<DOMString>) {} pub fn GetEnumAttributeNullable(&self) -> Option<TestEnum> { Some(_empty) } - pub fn GetInterfaceAttributeNullable(&self) -> Option<JS<Blob>> { + pub fn GetInterfaceAttributeNullable(&self) -> Option<Unrooted<Blob>> { let roots = RootCollection::new(); let window = self.window.root(&roots); - Some(Blob::new(&window.root_ref())) + Some(Blob::new(&(*window))) } pub fn SetInterfaceAttributeNullable(&self, _: Option<JSRef<Blob>>) {} diff --git a/src/components/script/dom/text.rs b/src/components/script/dom/text.rs index 61c37d2ad52..cdcfdac6af3 100644 --- a/src/components/script/dom/text.rs +++ b/src/components/script/dom/text.rs @@ -4,7 +4,7 @@ use dom::bindings::codegen::BindingDeclarations::TextBinding; use dom::bindings::codegen::InheritTypes::TextDerived; -use dom::bindings::js::{JS, JSRef, RootCollection}; +use dom::bindings::js::{JS, JSRef, RootCollection, Unrooted}; use dom::bindings::error::Fallible; use dom::characterdata::CharacterData; use dom::document::Document; @@ -35,19 +35,19 @@ impl Text { } } - pub fn new(text: DOMString, document: &JSRef<Document>) -> JS<Text> { + pub fn new(text: DOMString, document: &JSRef<Document>) -> Unrooted<Text> { let node = Text::new_inherited(text, document.unrooted()); Node::reflect_node(~node, document, TextBinding::Wrap) } - pub fn Constructor(owner: &JSRef<Window>, text: DOMString) -> Fallible<JS<Text>> { + pub fn Constructor(owner: &JSRef<Window>, text: DOMString) -> Fallible<Unrooted<Text>> { let roots = RootCollection::new(); let document = owner.get().Document(); let document = document.root(&roots); Ok(Text::new(text.clone(), &document.root_ref())) } - pub fn SplitText(&self, _offset: u32) -> Fallible<JS<Text>> { + pub fn SplitText(&self, _offset: u32) -> Fallible<Unrooted<Text>> { fail!("unimplemented") } diff --git a/src/components/script/dom/uievent.rs b/src/components/script/dom/uievent.rs index 50c97ee8373..f42edeb42bf 100644 --- a/src/components/script/dom/uievent.rs +++ b/src/components/script/dom/uievent.rs @@ -4,7 +4,7 @@ use dom::bindings::codegen::BindingDeclarations::UIEventBinding; use dom::bindings::codegen::InheritTypes::UIEventDerived; -use dom::bindings::js::{JS, JSRef, RootCollection, RootedReference}; +use dom::bindings::js::{JS, JSRef, RootCollection, RootedReference, Unrooted}; use dom::bindings::error::Fallible; use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object}; use dom::event::{Event, EventTypeId, UIEventTypeId}; @@ -36,7 +36,7 @@ impl UIEvent { } } - pub fn new(window: &JSRef<Window>) -> JS<UIEvent> { + pub fn new(window: &JSRef<Window>) -> Unrooted<UIEvent> { reflect_dom_object(~UIEvent::new_inherited(UIEventTypeId), window, UIEventBinding::Wrap) @@ -44,17 +44,17 @@ impl UIEvent { pub fn Constructor(owner: &JSRef<Window>, type_: DOMString, - init: &UIEventBinding::UIEventInit) -> Fallible<JS<UIEvent>> { + init: &UIEventBinding::UIEventInit) -> Fallible<Unrooted<UIEvent>> { let roots = RootCollection::new(); - let mut ev = UIEvent::new(owner); + let mut ev = UIEvent::new(owner).root(&roots); let view = init.view.as_ref().map(|view| view.root(&roots)); ev.get_mut().InitUIEvent(type_, init.parent.bubbles, init.parent.cancelable, view.root_ref(), init.detail); - Ok(ev) + Ok(Unrooted::new_rooted(&*ev)) } - pub fn GetView(&self) -> Option<JS<Window>> { - self.view.clone() + pub fn GetView(&self) -> Option<Unrooted<Window>> { + self.view.clone().map(|view| Unrooted::new(view)) } pub fn Detail(&self) -> i32 { @@ -97,7 +97,7 @@ impl UIEvent { 0 } - pub fn GetRangeParent(&self) -> Option<JS<Node>> { + pub fn GetRangeParent(&self) -> Option<Unrooted<Node>> { //TODO None } diff --git a/src/components/script/dom/validitystate.rs b/src/components/script/dom/validitystate.rs index 9a03134169f..02b0b9a7a11 100644 --- a/src/components/script/dom/validitystate.rs +++ b/src/components/script/dom/validitystate.rs @@ -3,7 +3,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use dom::bindings::codegen::BindingDeclarations::ValidityStateBinding; -use dom::bindings::js::{JS, JSRef}; +use dom::bindings::js::{JS, JSRef, Unrooted}; use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object}; use dom::window::Window; @@ -23,7 +23,7 @@ impl ValidityState { } } - pub fn new(window: &JSRef<Window>) -> JS<ValidityState> { + pub fn new(window: &JSRef<Window>) -> Unrooted<ValidityState> { reflect_dom_object(~ValidityState::new_inherited(window.unrooted()), window, ValidityStateBinding::Wrap) diff --git a/src/components/script/dom/virtualmethods.rs b/src/components/script/dom/virtualmethods.rs index 85ae37cb032..bf4681fab3b 100644 --- a/src/components/script/dom/virtualmethods.rs +++ b/src/components/script/dom/virtualmethods.rs @@ -8,7 +8,7 @@ use dom::bindings::codegen::InheritTypes::HTMLIFrameElementCast; use dom::bindings::codegen::InheritTypes::HTMLImageElementCast; use dom::bindings::codegen::InheritTypes::HTMLObjectElementCast; use dom::bindings::codegen::InheritTypes::HTMLStyleElementCast; -use dom::bindings::js::JS; +use dom::bindings::js::JSRef; use dom::element::Element; use dom::element::{ElementTypeId, HTMLImageElementTypeId}; use dom::element::{HTMLIFrameElementTypeId, HTMLObjectElementTypeId, HTMLStyleElementTypeId}; @@ -62,7 +62,7 @@ pub trait VirtualMethods { } /// Called on the parent when a node is added to its child list. - fn child_inserted(&mut self, child: &JS<Node>) { + fn child_inserted(&mut self, child: &JSRef<Node>) { match self.super_type() { Some(ref mut s) => s.child_inserted(child), _ => (), @@ -74,31 +74,31 @@ pub trait VirtualMethods { /// method call on the trait object will invoke the corresponding method on the /// concrete type, propagating up the parent hierarchy unless otherwise /// interrupted. -pub fn vtable_for<'a>(node: &JS<Node>) -> ~VirtualMethods: { +pub fn vtable_for<'a>(node: &JSRef<Node>) -> ~VirtualMethods: { match node.get().type_id { ElementNodeTypeId(HTMLImageElementTypeId) => { - let element: JS<HTMLImageElement> = HTMLImageElementCast::to(node).unwrap(); - ~element as ~VirtualMethods: + let element: &JSRef<HTMLImageElement> = HTMLImageElementCast::to_ref(node).unwrap(); + ~element.clone() as ~VirtualMethods: } ElementNodeTypeId(HTMLIFrameElementTypeId) => { - let element: JS<HTMLIFrameElement> = HTMLIFrameElementCast::to(node).unwrap(); - ~element as ~VirtualMethods: + let element: &JSRef<HTMLIFrameElement> = HTMLIFrameElementCast::to_ref(node).unwrap(); + ~element.clone() as ~VirtualMethods: } ElementNodeTypeId(HTMLObjectElementTypeId) => { - let element: JS<HTMLObjectElement> = HTMLObjectElementCast::to(node).unwrap(); - ~element as ~VirtualMethods: + let element: &JSRef<HTMLObjectElement> = HTMLObjectElementCast::to_ref(node).unwrap(); + ~element.clone() as ~VirtualMethods: } ElementNodeTypeId(HTMLStyleElementTypeId) => { - let element: JS<HTMLStyleElement> = HTMLStyleElementCast::to(node).unwrap(); - ~element as ~VirtualMethods: + let element: &JSRef<HTMLStyleElement> = HTMLStyleElementCast::to_ref(node).unwrap(); + ~element.clone() as ~VirtualMethods: } ElementNodeTypeId(ElementTypeId) => { - let element: JS<Element> = ElementCast::to(node).unwrap(); - ~element as ~VirtualMethods: + let element: &JSRef<Element> = ElementCast::to_ref(node).unwrap(); + ~element.clone() as ~VirtualMethods: } ElementNodeTypeId(_) => { - let element: JS<HTMLElement> = HTMLElementCast::to(node).unwrap(); - ~element as ~VirtualMethods: + let element: &JSRef<HTMLElement> = HTMLElementCast::to_ref(node).unwrap(); + ~element.clone() as ~VirtualMethods: } _ => { ~node.clone() as ~VirtualMethods: diff --git a/src/components/script/dom/window.rs b/src/components/script/dom/window.rs index a1155434d89..ff46c27ed79 100644 --- a/src/components/script/dom/window.rs +++ b/src/components/script/dom/window.rs @@ -3,7 +3,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use dom::bindings::codegen::BindingDeclarations::WindowBinding; -use dom::bindings::js::{JS, JSRef}; +use dom::bindings::js::{JS, JSRef, Unrooted, OptionalAssignable}; use dom::bindings::trace::{Traceable, Untraceable}; use dom::bindings::utils::{Reflectable, Reflector}; use dom::browsercontext::BrowserContext; @@ -116,9 +116,9 @@ impl Window { chan.send(ExitWindowMsg(self.page.id.clone())); } - pub fn Document(&self) -> JS<Document> { + pub fn Document(&self) -> Unrooted<Document> { let frame = self.page().frame(); - frame.get_ref().document.clone() + Unrooted::new(frame.get_ref().document.clone()) } pub fn Name(&self) -> DOMString { @@ -148,29 +148,29 @@ impl Window { pub fn Blur(&self) { } - pub fn GetFrameElement(&self) -> Option<JS<Element>> { + pub fn GetFrameElement(&self) -> Option<Unrooted<Element>> { None } - pub fn Location(&mut self, abstract_self: &JSRef<Window>) -> JS<Location> { + pub fn Location(&mut self, abstract_self: &JSRef<Window>) -> Unrooted<Location> { if self.location.is_none() { - self.location = Some(Location::new(abstract_self, self.page.clone())); + self.location.assign(Some(Location::new(abstract_self, self.page.clone()))); } - self.location.get_ref().clone() + Unrooted::new(self.location.get_ref().clone()) } - pub fn Console(&mut self, abstract_self: &JSRef<Window>) -> JS<Console> { + pub fn Console(&mut self, abstract_self: &JSRef<Window>) -> Unrooted<Console> { if self.console.is_none() { - self.console = Some(Console::new(abstract_self)); + self.console.assign(Some(Console::new(abstract_self))); } - self.console.get_ref().clone() + Unrooted::new(self.console.get_ref().clone()) } - pub fn Navigator(&mut self, abstract_self: &JSRef<Window>) -> JS<Navigator> { + pub fn Navigator(&mut self, abstract_self: &JSRef<Window>) -> Unrooted<Navigator> { if self.navigator.is_none() { - self.navigator = Some(Navigator::new(abstract_self)); + self.navigator.assign(Some(Navigator::new(abstract_self))); } - self.navigator.get_ref().clone() + Unrooted::new(self.navigator.get_ref().clone()) } pub fn Confirm(&self, _message: DOMString) -> bool { @@ -279,11 +279,11 @@ impl Window { self.ClearTimeout(handle); } - pub fn Window(&self, abstract_self: &JSRef<Window>) -> JS<Window> { - abstract_self.unrooted() + pub fn Window(&self, abstract_self: &JSRef<Window>) -> Unrooted<Window> { + Unrooted::new_rooted(abstract_self) } - pub fn Self(&self, abstract_self: &JSRef<Window>) -> JS<Window> { + pub fn Self(&self, abstract_self: &JSRef<Window>) -> Unrooted<Window> { self.Window(abstract_self) } @@ -301,7 +301,7 @@ impl Window { self.page().join_layout(); } - pub fn init_browser_context(&mut self, doc: &JS<Document>) { + pub fn init_browser_context(&mut self, doc: &JSRef<Document>) { self.browser_context = Some(BrowserContext::new(doc)); } @@ -310,7 +310,7 @@ impl Window { script_chan: ScriptChan, compositor: ~ScriptListener, image_cache_task: ImageCacheTask) - -> JS<Window> { + -> Unrooted<Window> { let win = ~Window { eventtarget: EventTarget::new_inherited(WindowTypeId), script_chan: script_chan, @@ -325,6 +325,6 @@ impl Window { browser_context: None, }; - WindowBinding::Wrap(cx, win) + Unrooted::new(WindowBinding::Wrap(cx, win)) } } diff --git a/src/components/script/dom/xmlhttprequest.rs b/src/components/script/dom/xmlhttprequest.rs index 9f2bbf180b5..8327135d566 100644 --- a/src/components/script/dom/xmlhttprequest.rs +++ b/src/components/script/dom/xmlhttprequest.rs @@ -10,7 +10,7 @@ use dom::bindings::codegen::InheritTypes::XMLHttpRequestDerived; use dom::document::Document; use dom::eventtarget::{EventTarget, XMLHttpRequestTargetTypeId}; use dom::bindings::error::Fallible; -use dom::bindings::js::{JS, JSRef}; +use dom::bindings::js::{JS, JSRef, Unrooted, OptionalAssignable}; use js::jsapi::JSContext; use js::jsval::{JSVal, NullValue}; use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object}; @@ -31,7 +31,7 @@ pub struct XMLHttpRequest { ready_state: u16, timeout: u32, with_credentials: bool, - upload: JS<XMLHttpRequestUpload>, + upload: Option<JS<XMLHttpRequestUpload>>, response_url: DOMString, status: u16, status_text: ByteString, @@ -42,26 +42,28 @@ pub struct XMLHttpRequest { impl XMLHttpRequest { pub fn new_inherited(owner: &JSRef<Window>) -> XMLHttpRequest { - XMLHttpRequest { + let mut xhr = XMLHttpRequest { eventtarget: XMLHttpRequestEventTarget::new_inherited(XMLHttpRequestTypeId), ready_state: 0, timeout: 0u32, with_credentials: false, - upload: XMLHttpRequestUpload::new(owner), + upload: None, response_url: ~"", status: 0, status_text: ByteString::new(vec!()), response_type: _empty, response_text: ~"", response_xml: None - } + }; + xhr.upload.assign(Some(XMLHttpRequestUpload::new(owner))); + xhr } - pub fn new(window: &JSRef<Window>) -> JS<XMLHttpRequest> { + pub fn new(window: &JSRef<Window>) -> Unrooted<XMLHttpRequest> { reflect_dom_object(~XMLHttpRequest::new_inherited(window), window, XMLHttpRequestBinding::Wrap) } - pub fn Constructor(owner: &JSRef<Window>) -> Fallible<JS<XMLHttpRequest>> { + pub fn Constructor(owner: &JSRef<Window>) -> Fallible<Unrooted<XMLHttpRequest>> { Ok(XMLHttpRequest::new(owner)) } pub fn ReadyState(&self) -> u16 { @@ -89,8 +91,8 @@ impl XMLHttpRequest { pub fn SetWithCredentials(&mut self, with_credentials: bool) { self.with_credentials = with_credentials } - pub fn Upload(&self) -> JS<XMLHttpRequestUpload> { - self.upload.clone() + pub fn Upload(&self) -> Unrooted<XMLHttpRequestUpload> { + Unrooted::new(self.upload.get_ref().clone()) } pub fn Send(&self, _data: Option<DOMString>) { @@ -128,8 +130,8 @@ impl XMLHttpRequest { pub fn ResponseText(&self) -> DOMString { self.response_text.clone() } - pub fn GetResponseXML(&self) -> Option<JS<Document>> { - self.response_xml.clone() + pub fn GetResponseXML(&self) -> Option<Unrooted<Document>> { + self.response_xml.clone().map(|response| Unrooted::new(response)) } } diff --git a/src/components/script/dom/xmlhttprequestupload.rs b/src/components/script/dom/xmlhttprequestupload.rs index 5e06d51b1d3..8e251dd4e8f 100644 --- a/src/components/script/dom/xmlhttprequestupload.rs +++ b/src/components/script/dom/xmlhttprequestupload.rs @@ -4,7 +4,7 @@ use dom::bindings::codegen::InheritTypes::XMLHttpRequestUploadDerived; use dom::bindings::codegen::BindingDeclarations::XMLHttpRequestUploadBinding; -use dom::bindings::js::{JS, JSRef}; +use dom::bindings::js::{Unrooted, JSRef}; use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object}; use dom::eventtarget::{EventTarget, XMLHttpRequestTargetTypeId}; use dom::window::Window; @@ -22,7 +22,7 @@ impl XMLHttpRequestUpload { eventtarget:XMLHttpRequestEventTarget::new_inherited(XMLHttpRequestUploadTypeId) } } - pub fn new(window: &JSRef<Window>) -> JS<XMLHttpRequestUpload> { + pub fn new(window: &JSRef<Window>) -> Unrooted<XMLHttpRequestUpload> { reflect_dom_object(~XMLHttpRequestUpload::new_inherited(), window, XMLHttpRequestUploadBinding::Wrap) diff --git a/src/components/script/html/hubbub_html_parser.rs b/src/components/script/html/hubbub_html_parser.rs index 771b75f3e9c..a90a696063c 100644 --- a/src/components/script/html/hubbub_html_parser.rs +++ b/src/components/script/html/hubbub_html_parser.rs @@ -4,7 +4,7 @@ use dom::bindings::codegen::InheritTypes::{NodeBase, NodeCast, TextCast, ElementCast}; use dom::bindings::codegen::InheritTypes::HTMLIFrameElementCast; -use dom::bindings::js::{JS, JSRef, RootCollection}; +use dom::bindings::js::{JS, JSRef, RootCollection, Unrooted, OptionalRootable}; use dom::bindings::utils::Reflectable; use dom::document::Document; use dom::element::{AttributeHandlers, HTMLLinkElementTypeId, HTMLIFrameElementTypeId}; @@ -12,7 +12,7 @@ use dom::htmlelement::HTMLElement; use dom::htmlheadingelement::{Heading1, Heading2, Heading3, Heading4, Heading5, Heading6}; use dom::htmliframeelement::IFrameSize; use dom::htmlformelement::HTMLFormElement; -use dom::node::{ElementNodeTypeId, INode, NodeHelpers}; +use dom::node::{ElementNodeTypeId, NodeHelpers, AppendChild}; use dom::types::*; use html::cssparse::{StylesheetProvenance, UrlProvenance, spawn_css_parser}; use script_task::Page; @@ -39,7 +39,7 @@ macro_rules! handle_element( $ctor: ident $(, $arg:expr )*) => ( if $string == $localName { - return ElementCast::from(&$ctor::new($localName, $document $(, $arg)*)); + return ElementCast::from_unrooted($ctor::new($localName, $document $(, $arg)*)); } ) ) @@ -74,21 +74,22 @@ pub struct HtmlParserResult { pub discovery_port: Receiver<HtmlDiscoveryMessage>, } -trait NodeWrapping { +trait NodeWrapping<T> { unsafe fn to_hubbub_node(&self, roots: &RootCollection) -> hubbub::NodeDataPtr; - unsafe fn from_hubbub_node(n: hubbub::NodeDataPtr, roots: Option<&RootCollection>) -> Self; } -impl<T: NodeBase+Reflectable> NodeWrapping for JS<T> { +impl<'a, T: NodeBase+Reflectable> NodeWrapping<T> for JSRef<'a, T> { unsafe fn to_hubbub_node(&self, roots: &RootCollection) -> hubbub::NodeDataPtr { roots.root_raw(self.reflector().get_jsobject()); cast::transmute(self.get()) } - unsafe fn from_hubbub_node(n: hubbub::NodeDataPtr, roots: Option<&RootCollection>) -> JS<T> { - let js = JS::from_raw(cast::transmute(n)); - let _ = roots.map(|roots| roots.unroot_raw(js.reflector().get_jsobject())); - js - } +} + +unsafe fn from_hubbub_node<T: Reflectable>(n: hubbub::NodeDataPtr, + roots: Option<&RootCollection>) -> Unrooted<T> { + let js = JS::from_raw(cast::transmute(n)); + let _ = roots.map(|roots| roots.unroot_raw(js.reflector().get_jsobject())); + Unrooted::new(js) } /** @@ -163,7 +164,7 @@ fn js_script_listener(to_parent: Sender<HtmlDiscoveryMessage>, // Silly macros to handle constructing DOM nodes. This produces bad code and should be optimized // via atomization (issue #85). -pub fn build_element_from_tag(tag: DOMString, document: &JSRef<Document>) -> JS<Element> { +pub fn build_element_from_tag(tag: DOMString, document: &JSRef<Document>) -> Unrooted<Element> { // TODO (Issue #85): use atoms handle_element!(document, tag, "a", HTMLAnchorElement); handle_element!(document, tag, "applet", HTMLAppletElement); @@ -245,7 +246,7 @@ pub fn build_element_from_tag(tag: DOMString, document: &JSRef<Document>) -> JS< handle_element!(document, tag, "ul", HTMLUListElement); handle_element!(document, tag, "video", HTMLVideoElement); - return ElementCast::from(&HTMLUnknownElement::new(tag, document)); + return ElementCast::from_unrooted(HTMLUnknownElement::new(tag, document)); } pub fn parse_html(page: &Page, @@ -297,7 +298,7 @@ pub fn parse_html(page: &Page, let roots = RootCollection::new(); - parser.set_document_node(unsafe { document.unrooted().to_hubbub_node(&roots) }); + parser.set_document_node(unsafe { document.to_hubbub_node(&roots) }); parser.enable_scripting(true); parser.enable_styling(true); @@ -313,7 +314,8 @@ pub fn parse_html(page: &Page, // NOTE: tmp vars are workaround for lifetime issues. Both required. let tmp_borrow = doc_cell.borrow(); let tmp = &*tmp_borrow; - let comment: JS<Node> = NodeCast::from(&Comment::new(data, *tmp)); + let comment = Comment::new(data, *tmp).root(&roots); + let comment: &JSRef<Node> = NodeCast::from_ref(&*comment); unsafe { comment.to_hubbub_node(&roots) } }, create_doctype: |doctype: ~hubbub::Doctype| { @@ -325,9 +327,9 @@ pub fn parse_html(page: &Page, // NOTE: tmp vars are workaround for lifetime issues. Both required. let tmp_borrow = doc_cell.borrow(); let tmp = &*tmp_borrow; - let doctype_node = DocumentType::new(name, public_id, system_id, *tmp); + let doctype_node = DocumentType::new(name, public_id, system_id, *tmp).root(&roots); unsafe { - doctype_node.to_hubbub_node(&roots) + doctype_node.deref().to_hubbub_node(&roots) } }, create_element: |tag: ~hubbub::Tag| { @@ -335,8 +337,7 @@ pub fn parse_html(page: &Page, // NOTE: tmp vars are workaround for lifetime issues. Both required. let tmp_borrow = doc_cell.borrow(); let tmp = &*tmp_borrow; - let mut element = build_element_from_tag(tag.name.clone(), *tmp); - let _element_root = element.root(&roots); + let mut element = build_element_from_tag(tag.name.clone(), *tmp).root(&roots); debug!("-- attach attrs"); for attr in tag.attributes.iter() { @@ -346,21 +347,32 @@ pub fn parse_html(page: &Page, attr.value.clone()).is_ok()); } + //FIXME: workaround for https://github.com/mozilla/rust/issues/13246; + // we get unrooting order failures if these are inside the match. + let rel = { + let rel = element.get_attribute(Null, "rel").root(&roots); + rel.map(|a| a.deref().Value()) + }; + let href = { + let href= element.get_attribute(Null, "href").root(&roots); + href.map(|a| a.deref().Value()) + }; + let src_opt = { + let src_opt = element.get_attribute(Null, "src").root(&roots); + src_opt.map(|a| a.deref().Value()) + }; + // Spawn additional parsing, network loads, etc. from tag and attrs match element.get().node.type_id { // Handle CSS style sheets from <link> elements ElementNodeTypeId(HTMLLinkElementTypeId) => { - match (element.get_attribute(Null, "rel"), - element.get_attribute(Null, "href")) { - (Some(ref rel), Some(ref href)) if rel.get() - .value_ref() - .split(HTML_SPACE_CHARACTERS. - as_slice()) + match (rel, href) { + (Some(ref rel), Some(ref href)) if rel.split(HTML_SPACE_CHARACTERS.as_slice()) .any(|s| { s.eq_ignore_ascii_case("stylesheet") }) => { - debug!("found CSS stylesheet: {:s}", href.get().value_ref()); - let url = parse_url(href.get().value_ref(), Some(url2.clone())); + debug!("found CSS stylesheet: {:s}", *href); + let url = parse_url(href.as_slice(), Some(url2.clone())); css_chan2.send(CSSTaskNewFile(UrlProvenance(url, resource_task.clone()))); } _ => {} @@ -369,11 +381,9 @@ pub fn parse_html(page: &Page, ElementNodeTypeId(HTMLIFrameElementTypeId) => { let iframe_chan = discovery_chan.clone(); - let mut iframe_element: JS<HTMLIFrameElement> = - HTMLIFrameElementCast::to(&element).unwrap(); + let iframe_element: &mut JSRef<HTMLIFrameElement> = + HTMLIFrameElementCast::to_mut_ref(&mut *element).unwrap(); let sandboxed = iframe_element.get().is_sandboxed(); - let elem: JS<Element> = ElementCast::from(&iframe_element); - let src_opt = elem.get_attribute(Null, "src").map(|x| x.get().Value()); for src in src_opt.iter() { let iframe_url = parse_url(*src, Some(url2.clone())); iframe_element.get_mut().set_frame(iframe_url.clone()); @@ -402,18 +412,17 @@ pub fn parse_html(page: &Page, // NOTE: tmp vars are workaround for lifetime issues. Both required. let tmp_borrow = doc_cell.borrow(); let tmp = &*tmp_borrow; - let text = Text::new(data, *tmp); - unsafe { text.to_hubbub_node(&roots) } + let text = Text::new(data, *tmp).root(&roots); + unsafe { text.deref().to_hubbub_node(&roots) } }, ref_node: |_| {}, unref_node: |_| {}, append_child: |parent: hubbub::NodeDataPtr, child: hubbub::NodeDataPtr| { unsafe { debug!("append child {:x} {:x}", parent, child); - let mut parent: JS<Node> = NodeWrapping::from_hubbub_node(parent, None); - let child: JS<Node> = NodeWrapping::from_hubbub_node(child, Some(&roots)); - let child = child.root(&roots); - assert!(parent.AppendChild(&mut child.root_ref()).is_ok()); + let mut child = from_hubbub_node(child, Some(&roots)).root(&roots); + let mut parent = from_hubbub_node(parent, None).root(&roots); + assert!(AppendChild(&mut *parent, &mut *child).is_ok()); } child }, @@ -464,8 +473,8 @@ pub fn parse_html(page: &Page, }, complete_script: |script| { unsafe { - let script: JS<Element> = NodeWrapping::from_hubbub_node(script, None); - match script.get_attribute(Null, "src") { + let script: &JSRef<Element> = &*from_hubbub_node(script, None).root(&roots); + match script.get_attribute(Null, "src").root(&roots) { Some(src) => { debug!("found script: {:s}", src.get().Value()); let new_url = parse_url(src.get().value_ref(), Some(url3.clone())); @@ -473,11 +482,11 @@ pub fn parse_html(page: &Page, } None => { let mut data = vec!(); - let scriptnode: JS<Node> = NodeCast::from(&script); + let scriptnode: &JSRef<Node> = NodeCast::from_ref(script); debug!("iterating over children {:?}", scriptnode.first_child()); for child in scriptnode.children() { debug!("child = {:?}", child); - let text: JS<Text> = TextCast::to(&child).unwrap(); + let text: &JSRef<Text> = TextCast::to_ref(&child).unwrap(); data.push(text.get().characterdata.data.to_str()); // FIXME: Bad copy. } diff --git a/src/components/script/script_task.rs b/src/components/script/script_task.rs index f442ddae7c1..f29a18b850a 100644 --- a/src/components/script/script_task.rs +++ b/src/components/script/script_task.rs @@ -7,7 +7,8 @@ use dom::bindings::codegen::RegisterBindings; use dom::bindings::codegen::InheritTypes::{EventTargetCast, NodeCast, ElementCast, EventCast}; -use dom::bindings::js::{JS, JSRef, RootCollection, RootedReference}; +use dom::bindings::js::{JS, JSRef, RootCollection, Unrooted, OptionalAssignable}; +use dom::bindings::js::OptionalRootable; use dom::bindings::trace::{Traceable, Untraceable}; use dom::bindings::utils::{Reflectable, GlobalStaticData, wrap_for_same_compartment}; use dom::document::{Document, HTMLDocument}; @@ -16,6 +17,7 @@ use dom::event::{Event_, ResizeEvent, ReflowEvent, ClickEvent, MouseDownEvent, M use dom::event::Event; use dom::uievent::UIEvent; use dom::eventtarget::EventTarget; +use dom::node; use dom::node::{Node, NodeHelpers}; use dom::window::{TimerId, Window}; use html::hubbub_html_parser::HtmlParserResult; @@ -272,14 +274,15 @@ impl Page { /// Adds the given damage. pub fn damage(&self, level: DocumentDamageLevel) { + let roots = RootCollection::new(); let root = match *self.frame() { None => return, Some(ref frame) => frame.document.get().GetDocumentElement() }; - match root { + match root.root(&roots) { None => {}, Some(root) => { - let root: JS<Node> = NodeCast::from(&root); + let root: &JSRef<Node> = NodeCast::from_ref(&*root); let mut damage = *self.damage.deref().borrow_mut(); match damage { None => {} @@ -351,6 +354,8 @@ impl Page { goal: ReflowGoal, script_chan: ScriptChan, compositor: &ScriptListener) { + let roots = RootCollection::new(); + let root = match *self.frame() { None => return, Some(ref frame) => { @@ -358,7 +363,7 @@ impl Page { } }; - match root { + match root.root(&roots) { None => {}, Some(root) => { debug!("script: performing reflow for goal {:?}", goal); @@ -377,7 +382,7 @@ impl Page { let mut last_reflow_id = self.last_reflow_id.deref().borrow_mut(); *last_reflow_id += 1; - let root: JS<Node> = NodeCast::from(&root); + let root: &JSRef<Node> = NodeCast::from_ref(&*root); let mut damage = self.damage.deref().borrow_mut(); let window_size = self.window_size.deref().borrow(); @@ -401,19 +406,21 @@ impl Page { } } - fn find_fragment_node(&self, fragid: ~str) -> Option<JS<Element>> { - let document = self.frame().get_ref().document.clone(); + fn find_fragment_node(&self, fragid: ~str) -> Option<Unrooted<Element>> { + let roots = RootCollection::new(); + let document = self.frame().get_ref().document.root(&roots); match document.get().GetElementById(fragid.to_owned()) { Some(node) => Some(node), None => { - let doc_node: JS<Node> = NodeCast::from(&document); - let mut anchors = doc_node.traverse_preorder().filter(|node| node.is_anchor_element()); + let doc_node: &JSRef<Node> = NodeCast::from_ref(&*document); + let mut anchors = doc_node.traverse_preorder(&roots) + .filter(|node| node.is_anchor_element()); anchors.find(|node| { - let elem: JS<Element> = ElementCast::to(node).unwrap(); - elem.get_attribute(Null, "name").map_or(false, |attr| { + let elem: &JSRef<Element> = ElementCast::to_ref(node).unwrap(); + elem.get_attribute(Null, "name").root(&roots).map_or(false, |attr| { attr.get().value_ref() == fragid }) - }).map(|node| ElementCast::to(&node).unwrap()) + }).map(|node| Unrooted::new_rooted(ElementCast::to_ref(&node).unwrap())) } } } @@ -435,13 +442,15 @@ impl Page { } pub fn hit_test(&self, point: &Point2D<f32>) -> Option<UntrustedNodeAddress> { + let roots = RootCollection::new(); let frame = self.frame(); let document = frame.get_ref().document.clone(); - let root = document.get().GetDocumentElement(); + let root = document.get().GetDocumentElement().root(&roots); if root.is_none() { return None; } - let root: JS<Node> = NodeCast::from(&root.unwrap()); + let root = root.unwrap(); + let root: &JSRef<Node> = NodeCast::from_ref(&*root); let (chan, port) = channel(); let address = match self.query_layout(HitTestQuery(root.to_trusted_node_address(), *point, chan), port) { Ok(HitTestResponse(node_address)) => { @@ -456,13 +465,15 @@ impl Page { } pub fn get_nodes_under_mouse(&self, point: &Point2D<f32>) -> Option<Vec<UntrustedNodeAddress>> { + let roots = RootCollection::new(); let frame = self.frame(); let document = frame.get_ref().document.clone(); - let root = document.get().GetDocumentElement(); + let root = document.get().GetDocumentElement().root(&roots); if root.is_none() { return None; } - let root: JS<Node> = NodeCast::from(&root.unwrap()); + let root = root.unwrap(); + let root: &JSRef<Node> = NodeCast::from_ref(&*root); let (chan, port) = channel(); let address = match self.query_layout(MouseOverQuery(root.to_trusted_node_address(), *point, chan), port) { Ok(MouseOverResponse(node_address)) => { @@ -868,16 +879,14 @@ impl ScriptTask { page_tree.page.clone(), self.chan.clone(), self.compositor.dup(), - self.image_cache_task.clone()); - let window_root = window.root(&roots); + self.image_cache_task.clone()).root(&roots); page.initialize_js_info(cx.clone(), window.reflector().get_jsobject()); - let mut document = Document::new(&window_root.root_ref(), Some(url.clone()), HTMLDocument, None); - let doc_root = document.root(&roots); - window.get_mut().init_browser_context(&document); + let mut document = Document::new(&*window, Some(url.clone()), HTMLDocument, None).root(&roots); + window.get_mut().init_browser_context(&*document); { let mut js_info = page.mut_js_info(); - RegisterBindings::Register(&window_root.root_ref(), js_info.get_mut_ref()); + RegisterBindings::Register(&*window, js_info.get_mut_ref()); } self.compositor.set_ready_state(Loading); @@ -885,7 +894,7 @@ impl ScriptTask { // // Note: We can parse the next document in parallel with any previous documents. let html_parsing_result = hubbub_html_parser::parse_html(page, - &mut doc_root.root_ref(), + &mut *document, url.clone(), self.resource_task.clone()); @@ -897,8 +906,8 @@ impl ScriptTask { // Create the root frame. let mut frame = page.mut_frame(); *frame = Some(Frame { - document: document.clone(), - window: window.clone(), + document: document.deref().unrooted(), + window: window.deref().unrooted(), }); } @@ -973,26 +982,24 @@ impl ScriptTask { // We have no concept of a document loader right now, so just dispatch the // "load" event as soon as we've finished executing all scripts parsed during // the initial load. - let mut event = Event::new(&window_root.root_ref()); + let mut event = Event::new(&*window).root(&roots); event.get_mut().InitEvent(~"load", false, false); - let event = event.root(&roots); - let doctarget = EventTargetCast::from(&document); - let doctarget = doctarget.root(&roots); - let mut wintarget: JS<EventTarget> = EventTargetCast::from(&window); - let wintarget_root = wintarget.root(&roots); - let _ = wintarget.get_mut().dispatch_event_with_target(&wintarget_root.root_ref(), - Some(doctarget.root_ref()), - &mut event.root_ref()); + let doctarget: &JSRef<EventTarget> = EventTargetCast::from_ref(&*document); + let wintarget: &mut JSRef<EventTarget> = EventTargetCast::from_mut_ref(&mut *window); + let wintarget_alias = wintarget.clone(); + let _ = wintarget.get_mut().dispatch_event_with_target(&wintarget_alias, + Some((*doctarget).clone()), + &mut *event); let mut fragment_node = page.fragment_node.deref().borrow_mut(); - *fragment_node = fragment.map_or(None, |fragid| page.find_fragment_node(fragid)); + (*fragment_node).assign(fragment.map_or(None, |fragid| page.find_fragment_node(fragid))); let ConstellationChan(ref chan) = self.constellation_chan; chan.send(LoadCompleteMsg(page.id, url)); } - fn scroll_fragment_point(&self, pipeline_id: PipelineId, node: JS<Element>) { - let node: JS<Node> = NodeCast::from(&node); + fn scroll_fragment_point(&self, pipeline_id: PipelineId, node: &JSRef<Element>) { + let node: &JSRef<Node> = NodeCast::from_ref(node); let rect = node.get_bounding_content_box(); let point = Point2D(to_frac_px(rect.origin.x).to_f32().unwrap(), to_frac_px(rect.origin.y).to_f32().unwrap()); @@ -1015,6 +1022,7 @@ impl ScriptTask { match event { ResizeEvent(new_width, new_height) => { + let roots = RootCollection::new(); debug!("script got resize event: {:u}, {:u}", new_width, new_height); let window = { @@ -1032,31 +1040,28 @@ impl ScriptTask { } let mut fragment_node = page.fragment_node.deref().borrow_mut(); - match fragment_node.take() { - Some(node) => self.scroll_fragment_point(pipeline_id, node), + match fragment_node.take().map(|node| node.root(&roots)) { + Some(node) => self.scroll_fragment_point(pipeline_id, &*node), None => {} } - frame.as_ref().map(|frame| frame.window.clone()) + frame.as_ref().map(|frame| Unrooted::new(frame.window.clone())) }; - match window { - Some(ref window) => { + match window.root(&roots) { + Some(mut window) => { // http://dev.w3.org/csswg/cssom-view/#resizing-viewports // https://dvcs.w3.org/hg/dom3events/raw-file/tip/html/DOM3-Events.html#event-type-resize - let roots = RootCollection::new(); - let window_root = window.root(&roots); - - let mut uievent = UIEvent::new(&window_root.root_ref()); - uievent.get_mut().InitUIEvent(~"resize", false, false, Some(window_root).root_ref(), 0i32); - let event: JS<Event> = EventCast::from(&uievent); - let event = event.root(&roots); - - let mut wintarget: JS<EventTarget> = EventTargetCast::from(window); - let targetroot = wintarget.root(&roots); - let _ = wintarget.get_mut().dispatch_event_with_target(&targetroot.root_ref(), + let mut uievent = UIEvent::new(&*window).root(&roots); + uievent.get_mut().InitUIEvent(~"resize", false, false, + Some((*window).clone()), 0i32); + let event: &mut JSRef<Event> = EventCast::from_mut_ref(&mut *uievent); + + let wintarget: &mut JSRef<EventTarget> = EventTargetCast::from_mut_ref(&mut *window); + let wintarget_alias = wintarget.clone(); + let _ = wintarget.get_mut().dispatch_event_with_target(&wintarget_alias, None, - &mut event.root_ref()); + &mut *event); } None => () } @@ -1076,32 +1081,31 @@ impl ScriptTask { } ClickEvent(_button, point) => { + let roots = RootCollection::new(); debug!("ClickEvent: clicked at {:?}", point); let mut page_tree = self.page_tree.borrow_mut(); let page = get_page(&mut *page_tree, pipeline_id); match page.hit_test(&point) { Some(node_address) => { debug!("node address is {:?}", node_address); - let mut node: JS<Node> = - NodeHelpers::from_untrusted_node_address(self.js_runtime.deref().ptr, - node_address); - debug!("clicked on {:s}", node.debug_str()); + let mut node = + node::from_untrusted_node_address(self.js_runtime.deref().ptr, + node_address).root(&roots); + debug!("clicked on {:s}", node.deref().debug_str()); // Traverse node generations until a node that is an element is // found. - while !node.is_element() { - match node.parent_node() { - Some(parent) => node = parent, + while !node.deref().is_element() { + match node.deref().parent_node() { + Some(parent) => node = parent.root(&roots), None => break, } } - if node.is_element() { - let element: JS<Element> = ElementCast::to(&node).unwrap(); + if node.deref().is_element() { + let element: &JSRef<Element> = ElementCast::to_ref(&*node).unwrap(); if "a" == element.get().local_name { - let roots = RootCollection::new(); - let element = element.root(&roots); - self.load_url_from_element(page, &element.root_ref()) + self.load_url_from_element(page, element) } } } @@ -1112,6 +1116,7 @@ impl ScriptTask { MouseDownEvent(..) => {} MouseUpEvent(..) => {} MouseMoveEvent(point) => { + let roots = RootCollection::new(); let mut page_tree = self.page_tree.borrow_mut(); let page = get_page(&mut *page_tree, pipeline_id); match page.get_nodes_under_mouse(&point) { @@ -1124,6 +1129,7 @@ impl ScriptTask { match *mouse_over_targets { Some(ref mut mouse_over_targets) => { for node in mouse_over_targets.mut_iter() { + let mut node = node.root(&roots); node.set_hover_state(false); } } @@ -1131,14 +1137,14 @@ impl ScriptTask { } for node_address in node_address.iter() { - let mut node: JS<Node> = - NodeHelpers::from_untrusted_node_address( - self.js_runtime.deref().ptr, *node_address); + let mut node = + node::from_untrusted_node_address( + self.js_runtime.deref().ptr, *node_address).root(&roots); // Traverse node generations until a node that is an element is // found. while !node.is_element() { match node.parent_node() { - Some(parent) => node = parent, + Some(parent) => node = parent.root(&roots), None => break, } } @@ -1149,12 +1155,12 @@ impl ScriptTask { match *mouse_over_targets { Some(ref mouse_over_targets) => { if !target_compare { - target_compare = !mouse_over_targets.contains(&node); + target_compare = !mouse_over_targets.contains(&node.unrooted()); } } None => {} } - target_list.push(node); + target_list.push(node.unrooted()); } } match *mouse_over_targets { @@ -1182,9 +1188,10 @@ impl ScriptTask { } fn load_url_from_element(&self, page: &Page, element: &JSRef<Element>) { + let roots = RootCollection::new(); // if the node's element is "a," load url from href attr - let attr = element.unrooted().get_attribute(Null, "href"); - for href in attr.iter() { + let attr = element.get_attribute(Null, "href"); + for href in attr.root(&roots).iter() { debug!("ScriptTask: clicked on link to {:s}", href.get().Value()); let click_frag = href.get().value_ref().starts_with("#"); let base_url = Some(page.get_url()); @@ -1192,8 +1199,8 @@ impl ScriptTask { let url = parse_url(href.get().value_ref(), base_url); if click_frag { - match page.find_fragment_node(url.fragment.unwrap()) { - Some(node) => self.scroll_fragment_point(page.id, node), + match page.find_fragment_node(url.fragment.unwrap()).root(&roots) { + Some(node) => self.scroll_fragment_point(page.id, &*node), None => {} } } else { |