Implement JSManaged for DOM objects.

This commit is contained in:
Josh Matthews 2013-11-30 21:04:49 +01:00
parent 061269f963
commit 625325434b
137 changed files with 3644 additions and 2778 deletions

View file

@ -4,11 +4,13 @@
use dom::bindings::codegen::PrototypeList;
use dom::bindings::codegen::PrototypeList::MAX_PROTO_CHAIN_LENGTH;
use dom::bindings::js::JS;
use dom::window;
use servo_util::str::DOMString;
use std::libc::c_uint;
use std::cast;
use std::cmp::Eq;
use std::hashmap::HashMap;
use std::libc;
use std::ptr;
@ -32,7 +34,7 @@ use js::jsapi::{JSContext, JSObject, JSBool, jsid, JSClass, JSNative, JSTracer};
use js::jsapi::{JSFunctionSpec, JSPropertySpec, JSVal, JSPropertyDescriptor};
use js::jsapi::{JS_NewGlobalObject, JS_InitStandardClasses};
use js::jsapi::{JSString, JS_CallTracer, JSTRACE_OBJECT};
use js::jsapi::{JS_IsExceptionPending};
use js::jsapi::{JS_IsExceptionPending, JS_AllowGC, JS_InhibitGC};
use js::jsfriendapi::bindgen::JS_NewObjectWithUniqueType;
use js::{JSPROP_ENUMERATE, JSVAL_NULL, JSCLASS_IS_GLOBAL, JSCLASS_IS_DOMJSCLASS};
use js::{JSPROP_PERMANENT, JSID_VOID, JSPROP_NATIVE_ACCESSORS, JSPROP_GETTER};
@ -174,6 +176,17 @@ pub fn unwrap_object<T>(obj: *JSObject, proto_id: PrototypeList::id::ID, proto_d
}
}
pub fn unwrap_jsmanaged<T: Reflectable>(obj: *JSObject,
proto_id: PrototypeList::id::ID,
proto_depth: uint) -> Result<JS<T>, ()> {
let result: Result<*mut Box<T>, ()> = unwrap_object(obj, proto_id, proto_depth);
result.map(|unwrapped| {
unsafe {
JS::from_box(unwrapped)
}
})
}
pub fn unwrap_value<T>(val: *JSVal, proto_id: PrototypeList::id::ID, proto_depth: uint) -> Result<T, ()> {
unsafe {
let obj = RUST_JSVAL_TO_OBJECT(*val);
@ -182,8 +195,11 @@ pub fn unwrap_value<T>(val: *JSVal, proto_id: PrototypeList::id::ID, proto_depth
}
pub unsafe fn squirrel_away<T>(x: @mut T) -> *Box<T> {
let y: *Box<T> = cast::transmute(x);
y
cast::transmute(x)
}
pub unsafe fn squirrel_away_unique<T>(x: ~T) -> *Box<T> {
cast::transmute(x)
}
pub fn jsstring_to_str(cx: *JSContext, s: *JSString) -> DOMString {
@ -557,10 +573,6 @@ pub fn trace_reflector(tracer: *mut JSTracer, description: &str, reflector: &Ref
}
}
pub fn trace_option<T: Reflectable>(tracer: *mut JSTracer, description: &str, option: Option<@mut T>) {
option.map(|some| trace_reflector(tracer, description, some.reflector()));
}
pub fn initialize_global(global: *JSObject) {
let protoArray = @mut ([0 as *JSObject, ..PrototypeList::id::_ID_Count as uint]);
unsafe {
@ -579,21 +591,17 @@ pub trait Reflectable {
}
pub fn reflect_dom_object<T: Reflectable>
(obj: @mut T,
(obj: ~T,
window: &window::Window,
wrap_fn: extern "Rust" fn(*JSContext, *JSObject, @mut T) -> *JSObject)
-> @mut T {
let cx = window.get_cx();
let scope = window.reflector().get_jsobject();
if wrap_fn(cx, scope, obj).is_null() {
fail!("Could not eagerly wrap object");
}
assert!(obj.reflector().get_jsobject().is_not_null());
obj
wrap_fn: extern "Rust" fn(*JSContext, *JSObject, ~T) -> *JSObject)
-> JS<T> {
JS::new(obj, window, wrap_fn)
}
#[deriving(Eq)]
pub struct Reflector {
object: *JSObject
object: *JSObject,
force_box_layout: @int,
}
impl Reflector {
@ -610,7 +618,8 @@ impl Reflector {
pub fn new() -> Reflector {
Reflector {
object: ptr::null()
object: ptr::null(),
force_box_layout: @1,
}
}
}
@ -849,11 +858,11 @@ fn cx_for_dom_reflector(obj: *JSObject) -> *JSContext {
}
/// Returns the global object of the realm that the given DOM object was created in.
pub fn global_object_for_dom_object<T: Reflectable>(obj: &mut T) -> *Box<window::Window> {
pub fn global_object_for_dom_object<T: Reflectable>(obj: &T) -> *Box<window::Window> {
global_object_for_js_object(obj.reflector().get_jsobject())
}
pub fn cx_for_dom_object<T: Reflectable>(obj: &mut T) -> *JSContext {
pub fn cx_for_dom_object<T: Reflectable>(obj: &T) -> *JSContext {
cx_for_dom_reflector(obj.reflector().get_jsobject())
}
@ -870,6 +879,26 @@ pub fn throw_method_failed_with_details<T>(cx: *JSContext,
return 0;
}
/// Execute arbitrary code with the JS GC enabled, then disable it afterwards.
pub fn with_gc_enabled<R>(cx: *JSContext, f: || -> R) -> R {
unsafe {
JS_AllowGC(cx);
let rv = f();
JS_InhibitGC(cx);
rv
}
}
/// Execute arbitrary code with the JS GC disabled, then enable it afterwards.
pub fn with_gc_disabled<R>(cx: *JSContext, f: || -> R) -> R {
unsafe {
JS_InhibitGC(cx);
let rv = f();
JS_AllowGC(cx);
rv
}
}
/// Check if an element name is valid. See http://www.w3.org/TR/xml/#NT-Name
/// for details.
#[deriving(Eq)]