From a09a4bd297d48c2702e1e15a901b1fdec32dda83 Mon Sep 17 00:00:00 2001 From: Josh Matthews Date: Thu, 17 Apr 2014 20:28:01 -0400 Subject: Root Temporary values for the duration of their lifetime. --- src/components/script/dom/bindings/js.rs | 30 ++++++++++++++++++++--------- src/components/script/dom/bindings/utils.rs | 11 +++++++---- src/components/script/dom/window.rs | 4 ++-- 3 files changed, 30 insertions(+), 15 deletions(-) (limited to 'src') 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 types) safely via the /// `JS::assign` method or `OptionalAssignable::assign` (for Option> fields). pub struct Temporary { - inner: JS + inner: JS, } impl Eq for Temporary { @@ -24,19 +24,31 @@ impl Eq for Temporary { } } +#[unsafe_destructor] +impl Drop for Temporary { + fn drop(&mut self) { + let cx = cx_for_dom_object(&self.inner); + unsafe { + JS_RemoveObjectRoot(cx, self.inner.reflector().rootable()); + } + } +} + impl Temporary { /// Create a new Temporary value from a JS-owned value. pub fn new(inner: JS) -> Temporary { + 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 { - 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 { +pub fn global_object_for_js_object(obj: *JSObject) -> JS { 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 { + -> JS { 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) } } -- cgit v1.2.3