diff options
author | Josh Matthews <josh@joshmatthews.net> | 2014-04-17 20:28:01 -0400 |
---|---|---|
committer | Josh Matthews <josh@joshmatthews.net> | 2014-05-03 14:18:31 -0400 |
commit | a09a4bd297d48c2702e1e15a901b1fdec32dda83 (patch) | |
tree | 4de4af60eea5d6a0947ff1be6d384709c8b2a066 | |
parent | 522d3f167b12fa79401eea5525c7b6133cae0f06 (diff) | |
download | servo-a09a4bd297d48c2702e1e15a901b1fdec32dda83.tar.gz servo-a09a4bd297d48c2702e1e15a901b1fdec32dda83.zip |
Root Temporary values for the duration of their lifetime.
-rw-r--r-- | src/components/script/dom/bindings/js.rs | 30 | ||||
-rw-r--r-- | src/components/script/dom/bindings/utils.rs | 11 | ||||
-rw-r--r-- | src/components/script/dom/window.rs | 4 |
3 files changed, 30 insertions, 15 deletions
diff --git a/src/components/script/dom/bindings/js.rs b/src/components/script/dom/bindings/js.rs index 031987181c2..9b61482e41a 100644 --- a/src/components/script/dom/bindings/js.rs +++ b/src/components/script/dom/bindings/js.rs @@ -2,20 +2,20 @@ * 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::utils::{Reflector, Reflectable}; +use dom::bindings::utils::{Reflector, Reflectable, cx_for_dom_object}; use dom::window::Window; -use js::jsapi::{JSObject, JSContext}; +use js::jsapi::{JSObject, JSContext, JS_AddObjectRoot, JS_RemoveObjectRoot}; use layout_interface::TrustedNodeAddress; use std::cast; use std::cell::RefCell; -/// 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. +/// A type that represents a JS-owned value that is rooted for the lifetime of this value. +/// Importantly, it requires explicit rooting in order to interact with the inner value. /// 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 Temporary<T> { - inner: JS<T> + inner: JS<T>, } impl<T> Eq for Temporary<T> { @@ -24,19 +24,31 @@ impl<T> Eq for Temporary<T> { } } +#[unsafe_destructor] +impl<T: Reflectable> Drop for Temporary<T> { + fn drop(&mut self) { + let cx = cx_for_dom_object(&self.inner); + unsafe { + JS_RemoveObjectRoot(cx, self.inner.reflector().rootable()); + } + } +} + impl<T: Reflectable> Temporary<T> { /// Create a new Temporary value from a JS-owned value. pub fn new(inner: JS<T>) -> Temporary<T> { + let cx = cx_for_dom_object(&inner); + unsafe { + JS_AddObjectRoot(cx, inner.reflector().rootable()); + } Temporary { - inner: inner + inner: inner, } } /// Create a new Temporary value from a rooted value. pub fn new_rooted<'a>(root: &JSRef<'a, T>) -> Temporary<T> { - Temporary { - inner: root.unrooted() - } + Temporary::new(root.unrooted()) } /// Root this unrooted value. diff --git a/src/components/script/dom/bindings/utils.rs b/src/components/script/dom/bindings/utils.rs index cbccb90197a..96982ebb6e2 100644 --- a/src/components/script/dom/bindings/utils.rs +++ b/src/components/script/dom/bindings/utils.rs @@ -412,6 +412,10 @@ impl Reflector { self.object = object; } + pub fn rootable(&self) -> **JSObject { + &self.object as **JSObject + } + pub fn new() -> Reflector { Reflector { object: ptr::null(), @@ -616,14 +620,13 @@ 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) -> Temporary<window::Window> { +pub fn global_object_for_js_object(obj: *JSObject) -> JS<window::Window> { unsafe { let global = GetGlobalForObjectCrossCompartment(obj); let clasp = JS_GetClass(global); assert!(((*clasp).flags & (JSCLASS_IS_DOMJSCLASS | JSCLASS_IS_GLOBAL)) != 0); - Temporary::new( - FromJSValConvertible::from_jsval(ptr::null(), ObjectOrNullValue(global), ()) - .ok().expect("found DOM global that doesn't unwrap to Window")) + FromJSValConvertible::from_jsval(ptr::null(), ObjectOrNullValue(global), ()) + .ok().expect("found DOM global that doesn't unwrap to Window") } } diff --git a/src/components/script/dom/window.rs b/src/components/script/dom/window.rs index d3ef0769431..3908db73326 100644 --- a/src/components/script/dom/window.rs +++ b/src/components/script/dom/window.rs @@ -342,7 +342,7 @@ impl Window { script_chan: ScriptChan, compositor: ~ScriptListener, image_cache_task: ImageCacheTask) - -> Temporary<Window> { + -> JS<Window> { let win = ~Window { eventtarget: EventTarget::new_inherited(WindowTypeId), script_chan: script_chan, @@ -357,6 +357,6 @@ impl Window { browser_context: None, }; - Temporary::new(WindowBinding::Wrap(cx, win)) + WindowBinding::Wrap(cx, win) } } |