mirror of
https://github.com/servo/servo.git
synced 2025-06-08 00:23:30 +00:00
Root Temporary values for the duration of their lifetime.
This commit is contained in:
parent
522d3f167b
commit
a09a4bd297
3 changed files with 30 additions and 15 deletions
|
@ -2,20 +2,20 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* 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/. */
|
* 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 dom::window::Window;
|
||||||
use js::jsapi::{JSObject, JSContext};
|
use js::jsapi::{JSObject, JSContext, JS_AddObjectRoot, JS_RemoveObjectRoot};
|
||||||
use layout_interface::TrustedNodeAddress;
|
use layout_interface::TrustedNodeAddress;
|
||||||
|
|
||||||
use std::cast;
|
use std::cast;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
|
|
||||||
/// A type that represents a JS-owned value that may or may not be rooted.
|
/// A type that represents a JS-owned value that is rooted for the lifetime of this value.
|
||||||
/// Importantly, it requires rooting in order to interact with the value in any way.
|
/// 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
|
/// 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).
|
/// `JS<T>::assign` method or `OptionalAssignable::assign` (for Option<JS<T>> fields).
|
||||||
pub struct Temporary<T> {
|
pub struct Temporary<T> {
|
||||||
inner: JS<T>
|
inner: JS<T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> Eq for Temporary<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> {
|
impl<T: Reflectable> Temporary<T> {
|
||||||
/// Create a new Temporary value from a JS-owned value.
|
/// Create a new Temporary value from a JS-owned value.
|
||||||
pub fn new(inner: JS<T>) -> Temporary<T> {
|
pub fn new(inner: JS<T>) -> Temporary<T> {
|
||||||
|
let cx = cx_for_dom_object(&inner);
|
||||||
|
unsafe {
|
||||||
|
JS_AddObjectRoot(cx, inner.reflector().rootable());
|
||||||
|
}
|
||||||
Temporary {
|
Temporary {
|
||||||
inner: inner
|
inner: inner,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new Temporary value from a rooted value.
|
/// Create a new Temporary value from a rooted value.
|
||||||
pub fn new_rooted<'a>(root: &JSRef<'a, T>) -> Temporary<T> {
|
pub fn new_rooted<'a>(root: &JSRef<'a, T>) -> Temporary<T> {
|
||||||
Temporary {
|
Temporary::new(root.unrooted())
|
||||||
inner: root.unrooted()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Root this unrooted value.
|
/// Root this unrooted value.
|
||||||
|
|
|
@ -412,6 +412,10 @@ impl Reflector {
|
||||||
self.object = object;
|
self.object = object;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn rootable(&self) -> **JSObject {
|
||||||
|
&self.object as **JSObject
|
||||||
|
}
|
||||||
|
|
||||||
pub fn new() -> Reflector {
|
pub fn new() -> Reflector {
|
||||||
Reflector {
|
Reflector {
|
||||||
object: ptr::null(),
|
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.
|
/// 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 {
|
unsafe {
|
||||||
let global = GetGlobalForObjectCrossCompartment(obj);
|
let global = GetGlobalForObjectCrossCompartment(obj);
|
||||||
let clasp = JS_GetClass(global);
|
let clasp = JS_GetClass(global);
|
||||||
assert!(((*clasp).flags & (JSCLASS_IS_DOMJSCLASS | JSCLASS_IS_GLOBAL)) != 0);
|
assert!(((*clasp).flags & (JSCLASS_IS_DOMJSCLASS | JSCLASS_IS_GLOBAL)) != 0);
|
||||||
Temporary::new(
|
FromJSValConvertible::from_jsval(ptr::null(), ObjectOrNullValue(global), ())
|
||||||
FromJSValConvertible::from_jsval(ptr::null(), ObjectOrNullValue(global), ())
|
.ok().expect("found DOM global that doesn't unwrap to Window")
|
||||||
.ok().expect("found DOM global that doesn't unwrap to Window"))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -342,7 +342,7 @@ impl Window {
|
||||||
script_chan: ScriptChan,
|
script_chan: ScriptChan,
|
||||||
compositor: ~ScriptListener,
|
compositor: ~ScriptListener,
|
||||||
image_cache_task: ImageCacheTask)
|
image_cache_task: ImageCacheTask)
|
||||||
-> Temporary<Window> {
|
-> JS<Window> {
|
||||||
let win = ~Window {
|
let win = ~Window {
|
||||||
eventtarget: EventTarget::new_inherited(WindowTypeId),
|
eventtarget: EventTarget::new_inherited(WindowTypeId),
|
||||||
script_chan: script_chan,
|
script_chan: script_chan,
|
||||||
|
@ -357,6 +357,6 @@ impl Window {
|
||||||
browser_context: None,
|
browser_context: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
Temporary::new(WindowBinding::Wrap(cx, win))
|
WindowBinding::Wrap(cx, win)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue