mirror of
https://github.com/servo/servo.git
synced 2025-06-25 01:24:37 +01:00
Return a JS<T> from *Binding::Wrap rather than a JSObject.
This lets us avoid the sketchy tricks in JS::new and Window::new, where we kept an unsafe pointer to the native object across the Wrap call that consumed the owned pointer.
This commit is contained in:
parent
71f4fd0478
commit
4ad3b6ccd1
6 changed files with 30 additions and 43 deletions
|
@ -2058,7 +2058,7 @@ def DOMObjectPointerArg(descriptor):
|
||||||
return DOMObjectPointerType(descriptor) + descriptor.concreteType
|
return DOMObjectPointerType(descriptor) + descriptor.concreteType
|
||||||
|
|
||||||
def CreateBindingJSObject(descriptor, parent=None):
|
def CreateBindingJSObject(descriptor, parent=None):
|
||||||
create = " let raw: *mut %s = &mut *aObject;\n" % descriptor.concreteType;
|
create = " let mut raw: JS<%s> = JS::from_raw(&mut *aObject);\n" % descriptor.concreteType
|
||||||
if descriptor.proxy:
|
if descriptor.proxy:
|
||||||
assert not descriptor.createGlobal
|
assert not descriptor.createGlobal
|
||||||
handler = """
|
handler = """
|
||||||
|
@ -2069,9 +2069,7 @@ def CreateBindingJSObject(descriptor, parent=None):
|
||||||
ptr::to_unsafe_ptr(&PrivateValue(squirrel_away_unique(aObject) as *libc::c_void)),
|
ptr::to_unsafe_ptr(&PrivateValue(squirrel_away_unique(aObject) as *libc::c_void)),
|
||||||
proto, %s,
|
proto, %s,
|
||||||
ptr::null(), ptr::null());
|
ptr::null(), ptr::null());
|
||||||
if obj.is_null() {
|
assert!(obj.is_not_null());
|
||||||
return ptr::null();
|
|
||||||
}
|
|
||||||
|
|
||||||
""" % (parent)
|
""" % (parent)
|
||||||
else:
|
else:
|
||||||
|
@ -2079,9 +2077,7 @@ def CreateBindingJSObject(descriptor, parent=None):
|
||||||
create += " let obj = CreateDOMGlobal(aCx, &Class.base);\n"
|
create += " let obj = CreateDOMGlobal(aCx, &Class.base);\n"
|
||||||
else:
|
else:
|
||||||
create += " let obj = JS_NewObject(aCx, &Class.base, proto, %s);\n" % parent
|
create += " let obj = JS_NewObject(aCx, &Class.base, proto, %s);\n" % parent
|
||||||
create += """ if obj.is_null() {
|
create += """ assert!(obj.is_not_null());
|
||||||
return ptr::null();
|
|
||||||
}
|
|
||||||
|
|
||||||
JS_SetReservedSlot(obj, DOM_OBJECT_SLOT as u32,
|
JS_SetReservedSlot(obj, DOM_OBJECT_SLOT as u32,
|
||||||
PrivateValue(squirrel_away_unique(aObject) as *libc::c_void));
|
PrivateValue(squirrel_away_unique(aObject) as *libc::c_void));
|
||||||
|
@ -2097,7 +2093,8 @@ class CGWrapMethod(CGAbstractMethod):
|
||||||
else:
|
else:
|
||||||
args = [Argument('*JSContext', 'aCx'),
|
args = [Argument('*JSContext', 'aCx'),
|
||||||
Argument(DOMObjectPointerArg(descriptor), 'aObject', mutable=True)]
|
Argument(DOMObjectPointerArg(descriptor), 'aObject', mutable=True)]
|
||||||
CGAbstractMethod.__init__(self, descriptor, 'Wrap', '*JSObject', args, pub=True)
|
retval = 'JS<%s>' % descriptor.concreteType
|
||||||
|
CGAbstractMethod.__init__(self, descriptor, 'Wrap', retval, args, pub=True)
|
||||||
|
|
||||||
def definition_body(self):
|
def definition_body(self):
|
||||||
if not self.descriptor.createGlobal:
|
if not self.descriptor.createGlobal:
|
||||||
|
@ -2108,22 +2105,20 @@ class CGWrapMethod(CGAbstractMethod):
|
||||||
|
|
||||||
//JSAutoCompartment ac(aCx, scope);
|
//JSAutoCompartment ac(aCx, scope);
|
||||||
let proto = GetProtoObject(aCx, scope, scope);
|
let proto = GetProtoObject(aCx, scope, scope);
|
||||||
if proto.is_null() {
|
assert!(proto.is_not_null());
|
||||||
return ptr::null();
|
|
||||||
}
|
|
||||||
|
|
||||||
%s
|
%s
|
||||||
|
|
||||||
(*raw).mut_reflector().set_jsobject(obj);
|
raw.mut_reflector().set_jsobject(obj);
|
||||||
|
|
||||||
return obj;""" % CreateBindingJSObject(self.descriptor, "scope")
|
return raw;""" % CreateBindingJSObject(self.descriptor, "scope")
|
||||||
else:
|
else:
|
||||||
return """
|
return """
|
||||||
%s
|
%s
|
||||||
let proto = GetProtoObject(aCx, obj, obj);
|
let proto = GetProtoObject(aCx, obj, obj);
|
||||||
JS_SetPrototype(aCx, obj, proto);
|
JS_SetPrototype(aCx, obj, proto);
|
||||||
(*raw).mut_reflector().set_jsobject(obj);
|
raw.mut_reflector().set_jsobject(obj);
|
||||||
return obj;""" % CreateBindingJSObject(self.descriptor)
|
return raw;""" % CreateBindingJSObject(self.descriptor)
|
||||||
|
|
||||||
class CGAbstractExternMethod(CGAbstractMethod):
|
class CGAbstractExternMethod(CGAbstractMethod):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
use dom::bindings::utils::{Reflector, Reflectable};
|
use dom::bindings::utils::{Reflector, Reflectable};
|
||||||
use dom::window::Window;
|
use dom::window::Window;
|
||||||
use js::jsapi::{JSContext, JSObject};
|
use js::jsapi::JSContext;
|
||||||
use layout_interface::TrustedNodeAddress;
|
use layout_interface::TrustedNodeAddress;
|
||||||
|
|
||||||
use std::cast;
|
use std::cast;
|
||||||
|
@ -30,17 +30,10 @@ impl <T> Clone for JS<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Reflectable> JS<T> {
|
impl<T: Reflectable> JS<T> {
|
||||||
pub fn new(mut obj: ~T,
|
pub fn new(obj: ~T,
|
||||||
window: &JS<Window>,
|
window: &JS<Window>,
|
||||||
wrap_fn: extern "Rust" fn(*JSContext, &JS<Window>, ~T) -> *JSObject) -> JS<T> {
|
wrap_fn: extern "Rust" fn(*JSContext, &JS<Window>, ~T) -> JS<T>) -> JS<T> {
|
||||||
let cx = window.get().get_cx();
|
wrap_fn(window.get().get_cx(), window, obj)
|
||||||
let raw: *mut T = &mut *obj;
|
|
||||||
if wrap_fn(cx, window, obj).is_null() {
|
|
||||||
fail!("Could not eagerly wrap object");
|
|
||||||
}
|
|
||||||
JS {
|
|
||||||
ptr: RefCell::new(raw)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn from_raw(raw: *mut T) -> JS<T> {
|
pub unsafe fn from_raw(raw: *mut T) -> JS<T> {
|
||||||
|
|
|
@ -429,7 +429,7 @@ pub trait Reflectable {
|
||||||
pub fn reflect_dom_object<T: Reflectable>
|
pub fn reflect_dom_object<T: Reflectable>
|
||||||
(obj: ~T,
|
(obj: ~T,
|
||||||
window: &JS<window::Window>,
|
window: &JS<window::Window>,
|
||||||
wrap_fn: extern "Rust" fn(*JSContext, &JS<window::Window>, ~T) -> *JSObject)
|
wrap_fn: extern "Rust" fn(*JSContext, &JS<window::Window>, ~T) -> JS<T>)
|
||||||
-> JS<T> {
|
-> JS<T> {
|
||||||
JS::new(obj, window, wrap_fn)
|
JS::new(obj, window, wrap_fn)
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,7 +39,7 @@ use servo_util::namespace::{Namespace, Null};
|
||||||
use servo_util::str::DOMString;
|
use servo_util::str::DOMString;
|
||||||
|
|
||||||
use extra::url::{Url, from_str};
|
use extra::url::{Url, from_str};
|
||||||
use js::jsapi::{JSObject, JSContext};
|
use js::jsapi::JSContext;
|
||||||
use std::ascii::StrAsciiExt;
|
use std::ascii::StrAsciiExt;
|
||||||
use std::hashmap::HashMap;
|
use std::hashmap::HashMap;
|
||||||
|
|
||||||
|
@ -87,7 +87,7 @@ impl Document {
|
||||||
pub fn reflect_document<D: Reflectable+DocumentBase>
|
pub fn reflect_document<D: Reflectable+DocumentBase>
|
||||||
(document: ~D,
|
(document: ~D,
|
||||||
window: &JS<Window>,
|
window: &JS<Window>,
|
||||||
wrap_fn: extern "Rust" fn(*JSContext, &JS<Window>, ~D) -> *JSObject)
|
wrap_fn: extern "Rust" fn(*JSContext, &JS<Window>, ~D) -> JS<D>)
|
||||||
-> JS<D> {
|
-> JS<D> {
|
||||||
assert!(document.reflector().get_jsobject().is_null());
|
assert!(document.reflector().get_jsobject().is_null());
|
||||||
let raw_doc = reflect_dom_object(document, window, wrap_fn);
|
let raw_doc = reflect_dom_object(document, window, wrap_fn);
|
||||||
|
|
|
@ -766,7 +766,7 @@ impl Node {
|
||||||
pub fn reflect_node<N: Reflectable+NodeBase>
|
pub fn reflect_node<N: Reflectable+NodeBase>
|
||||||
(node: ~N,
|
(node: ~N,
|
||||||
document: &JS<Document>,
|
document: &JS<Document>,
|
||||||
wrap_fn: extern "Rust" fn(*JSContext, &JS<Window>, ~N) -> *JSObject)
|
wrap_fn: extern "Rust" fn(*JSContext, &JS<Window>, ~N) -> JS<N>)
|
||||||
-> JS<N> {
|
-> JS<N> {
|
||||||
assert!(node.reflector().get_jsobject().is_null());
|
assert!(node.reflector().get_jsobject().is_null());
|
||||||
let node = reflect_dom_object(node, &document.get().window, wrap_fn);
|
let node = reflect_dom_object(node, &document.get().window, wrap_fn);
|
||||||
|
|
|
@ -282,7 +282,7 @@ impl Window {
|
||||||
compositor: ~ScriptListener,
|
compositor: ~ScriptListener,
|
||||||
image_cache_task: ImageCacheTask)
|
image_cache_task: ImageCacheTask)
|
||||||
-> JS<Window> {
|
-> JS<Window> {
|
||||||
let mut win = ~Window {
|
let win = ~Window {
|
||||||
eventtarget: EventTarget::new_inherited(WindowTypeId),
|
eventtarget: EventTarget::new_inherited(WindowTypeId),
|
||||||
script_chan: script_chan.clone(),
|
script_chan: script_chan.clone(),
|
||||||
console: None,
|
console: None,
|
||||||
|
@ -311,23 +311,22 @@ impl Window {
|
||||||
next_timer_handle: 0
|
next_timer_handle: 0
|
||||||
};
|
};
|
||||||
|
|
||||||
let raw: *mut Window = &mut *win;
|
|
||||||
let global = WindowBinding::Wrap(cx, win);
|
let global = WindowBinding::Wrap(cx, win);
|
||||||
assert!(global.is_not_null());
|
let fn_names = ["window", "self"];
|
||||||
unsafe {
|
|
||||||
let fn_names = ["window","self"];
|
|
||||||
for str in fn_names.iter() {
|
for str in fn_names.iter() {
|
||||||
(*str).to_c_str().with_ref(|name| {
|
(*str).to_c_str().with_ref(|name| {
|
||||||
JS_DefineProperty(cx, global, name,
|
let object = global.reflector().get_jsobject();
|
||||||
ObjectValue(&*global),
|
assert!(object.is_not_null());
|
||||||
|
unsafe {
|
||||||
|
JS_DefineProperty(cx, object, name,
|
||||||
|
ObjectValue(&*object),
|
||||||
Some(cast::transmute(GetJSClassHookStubPointer(PROPERTY_STUB))),
|
Some(cast::transmute(GetJSClassHookStubPointer(PROPERTY_STUB))),
|
||||||
Some(cast::transmute(GetJSClassHookStubPointer(STRICT_PROPERTY_STUB))),
|
Some(cast::transmute(GetJSClassHookStubPointer(STRICT_PROPERTY_STUB))),
|
||||||
JSPROP_ENUMERATE);
|
JSPROP_ENUMERATE);
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
|
global
|
||||||
JS::from_raw(raw)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue