diff --git a/components/script/devtools.rs b/components/script/devtools.rs index 271cc39ab35..cdc0537fa15 100644 --- a/components/script/devtools.rs +++ b/components/script/devtools.rs @@ -5,7 +5,7 @@ use devtools_traits::{EvaluateJSReply, NodeInfo, Modification, TimelineMarker, TimelineMarkerType}; use dom::bindings::conversions::FromJSValConvertible; use dom::bindings::conversions::StringificationBehavior; -use dom::bindings::js::{JSRef, Temporary, OptionalRootable}; +use dom::bindings::js::{JSRef, OptionalRootable, Rootable, Temporary}; use dom::bindings::codegen::InheritTypes::{NodeCast, ElementCast}; use dom::bindings::codegen::Bindings::DocumentBinding::DocumentMethods; use dom::bindings::codegen::Bindings::DOMRectBinding::{DOMRectMethods}; diff --git a/components/script/dom/activation.rs b/components/script/dom/activation.rs index 34bd440527c..047d3a5c4df 100644 --- a/components/script/dom/activation.rs +++ b/components/script/dom/activation.rs @@ -4,7 +4,7 @@ use dom::bindings::codegen::Bindings::EventBinding::EventMethods; use dom::bindings::codegen::InheritTypes::{EventCast, EventTargetCast}; -use dom::bindings::js::{JSRef, Temporary, OptionalRootable}; +use dom::bindings::js::{JSRef, Temporary, OptionalRootable, Rootable}; use dom::element::{Element, ActivationElementHelpers}; use dom::event::{Event, EventHelpers, EventBubbles, EventCancelable}; use dom::eventtarget::EventTarget; diff --git a/components/script/dom/attr.rs b/components/script/dom/attr.rs index d9fba643985..88384aabe5f 100644 --- a/components/script/dom/attr.rs +++ b/components/script/dom/attr.rs @@ -7,8 +7,7 @@ use dom::bindings::codegen::Bindings::AttrBinding::{self, AttrMethods}; use dom::bindings::codegen::InheritTypes::NodeCast; use dom::bindings::global::GlobalRef; use dom::bindings::js::{JS, JSRef, MutNullableHeap, Temporary}; -use dom::bindings::js::{OptionalRootable, OptionalRootedRootable}; -use dom::bindings::js::RootedReference; +use dom::bindings::js::{OptionalRootable, Rootable, RootedReference}; use dom::bindings::utils::{Reflector, reflect_dom_object}; use dom::element::{Element, AttributeHandlers}; use dom::node::Node; @@ -275,7 +274,7 @@ impl<'a> AttrHelpers<'a> for JSRef<'a, Attr> { } fn owner(self) -> Option> { - self.owner.get().map(Temporary::new) + self.owner.get().map(Temporary::from_rooted) } fn summarize(self) -> AttrInfo { diff --git a/components/script/dom/bindings/codegen/CodegenRust.py b/components/script/dom/bindings/codegen/CodegenRust.py index 6c0bef73c02..6b4acd64bd4 100644 --- a/components/script/dom/bindings/codegen/CodegenRust.py +++ b/components/script/dom/bindings/codegen/CodegenRust.py @@ -4733,8 +4733,8 @@ class CGBindingRoot(CGThing): 'dom::bindings::global::GlobalRef', 'dom::bindings::global::global_object_for_js_object', 'dom::bindings::js::{JS, JSRef, Root, RootedReference, Temporary, Unrooted}', - 'dom::bindings::js::{OptionalRootable, OptionalRootedRootable, ResultRootable}', - 'dom::bindings::js::{OptionalRootedReference, OptionalOptionalRootedRootable}', + 'dom::bindings::js::{OptionalOptionalRootable, OptionalRootable}', + 'dom::bindings::js::{OptionalRootedReference, ResultRootable, Rootable}', 'dom::bindings::utils::{create_dom_global, do_create_interface_objects}', 'dom::bindings::utils::ConstantSpec', 'dom::bindings::utils::{DOMClass}', @@ -5415,7 +5415,7 @@ class GlobalGenRoots(): descriptors = config.getDescriptors(register=True, isCallback=False) allprotos = [CGGeneric("#![allow(unused_imports)]\n"), CGGeneric("use dom::types::*;\n"), - CGGeneric("use dom::bindings::js::{JS, JSRef, LayoutJS, Temporary};\n"), + CGGeneric("use dom::bindings::js::{JS, JSRef, LayoutJS, Rootable, Temporary};\n"), CGGeneric("use dom::bindings::trace::JSTraceable;\n"), CGGeneric("use dom::bindings::utils::Reflectable;\n"), CGGeneric("use js::jsapi::JSTracer;\n\n"), diff --git a/components/script/dom/bindings/error.rs b/components/script/dom/bindings/error.rs index 181d02f0353..3fe23eaca2a 100644 --- a/components/script/dom/bindings/error.rs +++ b/components/script/dom/bindings/error.rs @@ -6,6 +6,7 @@ use dom::bindings::conversions::ToJSValConvertible; use dom::bindings::global::GlobalRef; +use dom::bindings::js::Rootable; use dom::domexception::{DOMException, DOMErrorName}; use util::str::DOMString; diff --git a/components/script/dom/bindings/global.rs b/components/script/dom/bindings/global.rs index 41fb88adf56..8297c2244a9 100644 --- a/components/script/dom/bindings/global.rs +++ b/components/script/dom/bindings/global.rs @@ -8,7 +8,7 @@ //! code that works in workers as well as window scopes. use dom::bindings::conversions::native_from_reflector_jsmanaged; -use dom::bindings::js::{JS, JSRef, Root, Unrooted}; +use dom::bindings::js::{JS, JSRef, Rootable, Root, Unrooted}; use dom::bindings::utils::{Reflectable, Reflector}; use dom::workerglobalscope::{WorkerGlobalScope, WorkerGlobalScopeHelpers}; use dom::window::{self, WindowHelpers}; diff --git a/components/script/dom/bindings/js.rs b/components/script/dom/bindings/js.rs index a6dc495fc04..115fcdbbe97 100644 --- a/components/script/dom/bindings/js.rs +++ b/components/script/dom/bindings/js.rs @@ -31,17 +31,18 @@ //! the self value will not be collected for the duration of the method call. //! //! Both `Temporary` and `JS` do not allow access to their inner value -//! without explicitly creating a stack-based root via the `root` method. This -//! returns a `Root`, which causes the JS-owned value to be uncollectable -//! for the duration of the `Root` object's lifetime. A `JSRef` can be -//! obtained from a `Root` by calling the `r` method. These `JSRef` -//! values are not allowed to outlive their originating `Root`, to ensure -//! that all interactions with the enclosed value only occur when said value is -//! uncollectable, and will cause static lifetime errors if misused. +//! without explicitly creating a stack-based root via the `root` method +//! through the `Rootable` trait. This returns a `Root`, which causes the +//! JS-owned value to be uncollectable for the duration of the `Root` object's +//! lifetime. A `JSRef` can be obtained from a `Root` by calling the `r` +//! method. These `JSRef` values are not allowed to outlive their +//! originating `Root`, to ensure that all interactions with the enclosed +//! value only occur when said value is uncollectable, and will cause static +//! lifetime errors if misused. //! //! Other miscellaneous helper traits: //! -//! - `OptionalRootable` and `OptionalRootedRootable`: make rooting `Option` +//! - `OptionalRootable` and `OptionalOptionalRootable`: make rooting `Option` //! values easy via a `root` method //! - `ResultRootable`: make rooting successful `Result` values easy //! - `TemporaryPushable`: allows mutating vectors of `JS` with new elements @@ -108,9 +109,11 @@ impl Unrooted { pub unsafe fn unsafe_get(&self) -> *const T { *self.ptr } +} +impl Rootable for Unrooted { /// Create a stack-bounded root for this value. - pub fn root(self) -> Root { + fn root(&self) -> Root { STACK_ROOTS.with(|ref collection| { let RootCollectionPtr(collection) = collection.get().unwrap(); unsafe { @@ -150,14 +153,6 @@ impl PartialEq for Temporary { } impl Temporary { - /// Create a new `Temporary` value from a JS-owned value. - pub fn new(inner: JS) -> Temporary { - Temporary { - inner: inner, - _js_ptr: inner.reflector().get_jsobject(), - } - } - /// Create a new `Temporary` value from an unrooted value. #[allow(unrooted_must_root)] pub fn from_unrooted(unrooted: Unrooted) -> Temporary { @@ -168,22 +163,20 @@ impl Temporary { } /// Create a new `Temporary` value from a rooted value. - pub fn from_rooted<'a>(root: JSRef<'a, T>) -> Temporary { - Temporary::new(JS::from_rooted(root)) + #[allow(unrooted_must_root)] + pub fn from_rooted>(root: U) -> Temporary { + let inner = JS::from_rooted(root); + Temporary { + inner: inner, + _js_ptr: inner.reflector().get_jsobject(), + } } +} +impl Rootable for Temporary { /// Create a stack-bounded root for this value. - pub fn root(&self) -> Root { - STACK_ROOTS.with(|ref collection| { - let RootCollectionPtr(collection) = collection.get().unwrap(); - unsafe { - Root::new(&*collection, self.inner.ptr) - } - }) - } - - unsafe fn inner(&self) -> JS { - self.inner.clone() + fn root(&self) -> Root { + self.inner.root() } } @@ -264,9 +257,9 @@ impl LayoutJS { } } -impl JS { +impl Rootable for JS { /// Root this JS-owned value to prevent its collection as garbage. - pub fn root(&self) -> Root { + fn root(&self) -> Root { STACK_ROOTS.with(|ref collection| { let RootCollectionPtr(collection) = collection.get().unwrap(); unsafe { @@ -376,7 +369,7 @@ impl MutNullableHeap> { where F: FnOnce() -> Temporary { match self.get() { - Some(inner) => Temporary::new(inner), + Some(inner) => Temporary::from_rooted(inner), None => { let inner = cb(); self.set(Some(JS::from_rooted(inner.clone()))); @@ -406,7 +399,7 @@ impl JS { /// 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: Temporary) { - *self = unsafe { val.inner() }; + *self = val.inner.clone(); } } @@ -461,96 +454,62 @@ impl Assignable for JS { impl<'a, T: Reflectable> Assignable for JSRef<'a, T> { unsafe fn get_js(&self) -> JS { - self.unrooted() + JS { + ptr: self.ptr + } } } impl Assignable for Temporary { unsafe fn get_js(&self) -> JS { - self.inner() + self.inner.clone() } } /// Root a rootable `Option` type (used for `Option>`) pub trait OptionalRootable { - /// Root the inner value, if it exists. - fn root(self) -> Option>; -} - -impl OptionalRootable for Option> { - fn root(self) -> Option> { - self.map(|inner| inner.root()) - } -} - -/// Return an unrooted type for storing in optional DOM fields -pub trait OptionalUnrootable { - /// Returns a `JS` for the inner value, if it exists. - fn unrooted(&self) -> Option>; -} - -impl<'a, T: Reflectable> OptionalUnrootable for Option> { - fn unrooted(&self) -> Option> { - self.as_ref().map(|inner| JS::from_rooted(*inner)) - } -} - -/// Root a rootable `Option` type (used for `Option>`) -pub trait OptionalRootedRootable { /// Root the inner value, if it exists. fn root(&self) -> Option>; } -impl OptionalRootedRootable for Option> { - fn root(&self) -> Option> { - self.as_ref().map(|inner| inner.root()) - } -} - -impl OptionalRootedRootable for Option> { +impl> OptionalRootable for Option { fn root(&self) -> Option> { self.as_ref().map(|inner| inner.root()) } } /// Root a rootable `Option