Remove all handwritten bindings code.

This commit is contained in:
Josh Matthews 2013-08-30 13:13:46 -04:00
parent 7584aee98e
commit 75f1cbd76f
5 changed files with 7 additions and 514 deletions

View file

@ -4,311 +4,10 @@
use dom::types::*;
use dom::bindings::codegen::*;
use dom::bindings::node::unwrap;
use dom::bindings::utils::jsval_to_str;
use dom::bindings::utils::{domstring_to_jsval, WrapNewBindingObject};
use dom::bindings::utils::{str, CacheableWrapper, DOM_OBJECT_SLOT, DOMString};
use dom::bindings::utils::{BindingObject, WrapperCache};
use dom::element::Element;
use dom::element::{HTMLImageElementTypeId, HTMLHeadElementTypeId, HTMLScriptElementTypeId,
HTMLDivElementTypeId};
use dom::node::{AbstractNode, ScriptView, ElementNodeTypeId};
use layout_interface::{ContentBoxQuery, ContentBoxResponse};
use script_task::page_from_context;
use super::utils;
use dom::bindings::utils::{BindingObject, WrapperCache, CacheableWrapper};
use dom::node::ScriptView;
use std::cast;
use std::i32;
use std::libc;
use std::libc::c_uint;
use std::comm;
use std::ptr;
use std::ptr::null;
use js::glue::*;
use js::jsapi::*;
use js::jsapi::{JSContext, JSVal, JSObject, JSBool, JSFreeOp, JSPropertySpec};
use js::jsapi::{JSNativeWrapper, JSTracer, JSTRACE_OBJECT};
use js::jsapi::{JSPropertyOpWrapper, JSStrictPropertyOpWrapper, JSFunctionSpec};
use js::rust::{Compartment, jsobj};
use js::{JS_ARGV, JSPROP_ENUMERATE, JSPROP_SHARED};
use js::{JS_THIS_OBJECT, JSPROP_NATIVE_ACCESSORS};
extern fn finalize(_fop: *JSFreeOp, obj: *JSObject) {
debug!("element finalize: %x!", obj as uint);
unsafe {
let node: AbstractNode<ScriptView> = unwrap(obj);
//XXXjdm We need separate finalizers for each specialty element type like headings
let _elem: @Element = cast::transmute(node.raw_object());
}
}
pub extern fn trace(tracer: *mut JSTracer, obj: *JSObject) {
let node = unsafe { unwrap(obj) };
fn trace_node(tracer: *mut JSTracer, node: Option<AbstractNode<ScriptView>>, name: &str) {
if node.is_none() {
return;
}
error!("tracing %s", name);
let mut node = node.unwrap();
let cache = node.get_wrappercache();
let wrapper = cache.get_wrapper();
assert!(wrapper.is_not_null());
unsafe {
(*tracer).debugPrinter = ptr::null();
(*tracer).debugPrintIndex = -1;
do name.to_c_str().with_ref |name| {
(*tracer).debugPrintArg = name as *libc::c_void;
JS_CallTracer(cast::transmute(tracer), wrapper, JSTRACE_OBJECT as u32);
}
}
}
error!("tracing %?:", obj as uint);
trace_node(tracer, node.parent_node(), "parent");
trace_node(tracer, node.first_child(), "first child");
trace_node(tracer, node.last_child(), "last child");
trace_node(tracer, node.next_sibling(), "next sibling");
trace_node(tracer, node.prev_sibling(), "prev sibling");
}
pub fn init(compartment: @mut Compartment) {
let obj = utils::define_empty_prototype(~"Element", Some(~"Node"), compartment);
let attrs = @~[
JSPropertySpec {
name: compartment.add_name(~"tagName"),
tinyid: 0,
flags: (JSPROP_ENUMERATE | JSPROP_SHARED | JSPROP_NATIVE_ACCESSORS) as u8,
getter: JSPropertyOpWrapper {op: getTagName, info: null()},
setter: JSStrictPropertyOpWrapper {op: null(), info: null()}},
JSPropertySpec {
name: null(),
tinyid: 0,
flags: (JSPROP_SHARED | JSPROP_ENUMERATE | JSPROP_NATIVE_ACCESSORS) as u8,
getter: JSPropertyOpWrapper {op: null(), info: null()},
setter: JSStrictPropertyOpWrapper {op: null(), info: null()}}];
compartment.global_props.push(attrs);
do attrs.as_imm_buf |specs, _len| {
unsafe {
JS_DefineProperties(compartment.cx.ptr, obj.ptr, specs);
}
}
let methods = @~[JSFunctionSpec {name: compartment.add_name(~"getClientRects"),
call: JSNativeWrapper {op: getClientRects, info: null()},
nargs: 0,
flags: 0,
selfHostedName: null()},
JSFunctionSpec {name: compartment.add_name(~"getBoundingClientRect"),
call: JSNativeWrapper {op: getBoundingClientRect, info: null()},
nargs: 0,
flags: 0,
selfHostedName: null()},
JSFunctionSpec {name: compartment.add_name(~"setAttribute"),
call: JSNativeWrapper {op: setAttribute, info: null()},
nargs: 0,
flags: 0,
selfHostedName: null()},
JSFunctionSpec {name: null(),
call: JSNativeWrapper {op: null(), info: null()},
nargs: 0,
flags: 0,
selfHostedName: null()}];
do methods.as_imm_buf |fns, _len| {
unsafe {
JS_DefineFunctions(compartment.cx.ptr, obj.ptr, fns);
}
}
compartment.register_class(utils::instance_jsclass(~"GenericElementInstance",
finalize, trace));
let _ = utils::define_empty_prototype(~"HTMLElement", Some(~"Element"), compartment);
let _ = utils::define_empty_prototype(~"HTMLDivElement", Some(~"HTMLElement"), compartment);
let _ = utils::define_empty_prototype(~"HTMLScriptElement", Some(~"HTMLElement"), compartment);
let _ = utils::define_empty_prototype(~"HTMLHeadElement", Some(~"HTMLElement"), compartment);
let obj = utils::define_empty_prototype(~"HTMLImageElement", Some(~"HTMLElement"), compartment);
let attrs = @~[
JSPropertySpec {name: compartment.add_name(~"width"),
tinyid: 0,
flags: (JSPROP_SHARED | JSPROP_ENUMERATE | JSPROP_NATIVE_ACCESSORS) as u8,
getter: JSPropertyOpWrapper {op: HTMLImageElement_getWidth, info: null()},
setter: JSStrictPropertyOpWrapper {op: HTMLImageElement_setWidth, info: null()}},
JSPropertySpec {name: null(),
tinyid: 0,
flags: (JSPROP_SHARED | JSPROP_ENUMERATE | JSPROP_NATIVE_ACCESSORS) as u8,
getter: JSPropertyOpWrapper {op: null(), info: null()},
setter: JSStrictPropertyOpWrapper {op: null(), info: null()}}];
compartment.global_props.push(attrs);
do attrs.as_imm_buf |specs, _len| {
unsafe {
JS_DefineProperties(compartment.cx.ptr, obj.ptr, specs);
}
}
}
extern fn getClientRects(cx: *JSContext, _argc: c_uint, vp: *JSVal) -> JSBool {
unsafe {
let obj = JS_THIS_OBJECT(cx, vp);
let mut node = unwrap(obj);
let rval = do node.with_imm_element |elem| {
elem.GetClientRects(node)
};
let cache = node.get_wrappercache();
let rval = rval as @mut CacheableWrapper;
assert!(WrapNewBindingObject(cx, cache.get_wrapper(),
rval,
cast::transmute(vp)));
return 1;
}
}
extern fn getBoundingClientRect(cx: *JSContext, _argc: c_uint, vp: *JSVal) -> JSBool {
unsafe {
let obj = JS_THIS_OBJECT(cx, vp);
let mut node = unwrap(obj);
let rval = do node.with_imm_element |elem| {
elem.GetBoundingClientRect(node)
};
let cache = node.get_wrappercache();
let rval = rval as @mut CacheableWrapper;
assert!(WrapNewBindingObject(cx, cache.get_wrapper(),
rval,
cast::transmute(vp)));
return 1;
}
}
extern fn setAttribute(cx: *JSContext, argc: c_uint, vp: *JSVal) -> JSBool {
unsafe {
let obj = JS_THIS_OBJECT(cx, vp);
let node = unwrap(obj);
if (argc < 2) {
return 0; //XXXjdm throw exception
}
let argv = JS_ARGV(cx, cast::transmute(vp));
let arg0: DOMString;
let strval = jsval_to_str(cx, (*argv.offset(0)));
if strval.is_err() {
return 0;
}
arg0 = str(strval.unwrap());
let arg1: DOMString;
let strval = jsval_to_str(cx, (*argv.offset(1)));
if strval.is_err() {
return 0;
}
arg1 = str(strval.unwrap());
do node.as_mut_element |elem| {
elem.set_attr(&arg0, &arg1);
};
return 1;
}
}
extern fn HTMLImageElement_getWidth(cx: *JSContext, _argc: c_uint, vp: *mut JSVal) -> JSBool {
unsafe {
let obj = JS_THIS_OBJECT(cx, cast::transmute(vp));
if obj.is_null() {
return 0;
}
let node = unwrap(obj);
let width = match node.type_id() {
ElementNodeTypeId(HTMLImageElementTypeId) => {
let page = page_from_context(cx);
let (port, chan) = comm::stream();
// TODO(tkuehn): currently this just queries top-level page's layout. Need to handle subframes.
match (*page).query_layout(ContentBoxQuery(node, chan), port) {
Ok(ContentBoxResponse(rect)) => rect.size.width.to_nearest_px(),
Err(()) => 0
}
// TODO: if nothing is being rendered(?), return zero dimensions
}
ElementNodeTypeId(_) => fail!(~"why is this not an image element?"),
_ => fail!(~"why is this not an element?")
};
*vp = RUST_INT_TO_JSVAL(
(width & (i32::max_value as int)) as libc::c_int);
return 1;
}
}
extern fn HTMLImageElement_setWidth(cx: *JSContext, _argc: c_uint, vp: *mut JSVal) -> JSBool {
unsafe {
let obj = JS_THIS_OBJECT(cx, cast::transmute(vp));
if obj.is_null() {
return 0;
}
let node = unwrap(obj);
match node.type_id() {
ElementNodeTypeId(HTMLImageElementTypeId) => {
do node.as_mut_element |elem| {
let arg = ptr::offset(JS_ARGV(cx, cast::transmute(vp)), 0);
elem.set_attr(&str(~"width"),
&str((RUST_JSVAL_TO_INT(*arg) as int).to_str()))
}
}
ElementNodeTypeId(_) => fail!(~"why is this not an image element?"),
_ => fail!(~"why is this not an element?")
};
return 1;
}
}
extern fn getTagName(cx: *JSContext, _argc: c_uint, vp: *mut JSVal) -> JSBool {
unsafe {
let obj = JS_THIS_OBJECT(cx, cast::transmute(vp));
if obj.is_null() {
return 0;
}
let node = unwrap(obj);
do node.with_imm_element |elem| {
let s = str(elem.tag_name.clone());
*vp = domstring_to_jsval(cx, &s);
}
}
return 1;
}
pub fn create(cx: *JSContext, node: &mut AbstractNode<ScriptView>) -> jsobj {
let proto = match node.type_id() {
ElementNodeTypeId(HTMLDivElementTypeId) => ~"HTMLDivElement",
ElementNodeTypeId(HTMLHeadElementTypeId) => ~"HTMLHeadElement",
ElementNodeTypeId(HTMLImageElementTypeId) => ~"HTMLImageElement",
ElementNodeTypeId(HTMLScriptElementTypeId) => ~"HTMLScriptElement",
ElementNodeTypeId(_) => ~"HTMLElement",
_ => fail!(~"element::create only handles elements")
};
//XXXjdm the parent should probably be the node parent instead of the global
//TODO error checking
let compartment = utils::get_compartment(cx);
let obj = compartment.new_object_with_proto(~"GenericElementInstance",
proto,
compartment.global_obj.ptr).unwrap();
let cache = node.get_wrappercache();
assert!(cache.get_wrapper().is_null());
cache.set_wrapper(obj.ptr);
unsafe {
let raw_ptr = node.raw_object() as *libc::c_void;
JS_SetReservedSlot(obj.ptr, DOM_OBJECT_SLOT as u32, RUST_PRIVATE_TO_JSVAL(raw_ptr));
}
return obj;
}
use js::jsapi::{JSContext, JSObject};
pub macro_rules! generate_cacheable_wrapper(
($name: path, $wrap: path) => (

View file

@ -2,66 +2,17 @@
* 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::element;
use dom::bindings::utils;
use dom::bindings::utils::{CacheableWrapper, WrapperCache, DerivedWrapper};
use dom::bindings::utils::{CacheableWrapper, WrapperCache};
use dom::element::*;
use dom::types::*;
use dom::node::{AbstractNode, Node, ElementNodeTypeId, TextNodeTypeId, CommentNodeTypeId};
use dom::node::{AbstractNode, ElementNodeTypeId, TextNodeTypeId, CommentNodeTypeId};
use dom::node::{DoctypeNodeTypeId, ScriptView};
use std::cast;
use std::libc::c_uint;
use std::ptr;
use std::ptr::null;
use js::jsapi::*;
use js::jsapi::{JSContext, JSVal, JSObject, JSBool, JSPropertySpec};
use js::jsapi::{JSPropertyOpWrapper, JSStrictPropertyOpWrapper};
use js::jsval::{INT_TO_JSVAL};
use js::rust::{Compartment};
use js::{JSPROP_ENUMERATE, JSPROP_SHARED, JSVAL_NULL};
use js::{JS_THIS_OBJECT, JSPROP_NATIVE_ACCESSORS};
use js::jsapi::{JSContext, JSObject};
use servo_util::tree::TreeNodeRef;
pub fn init(compartment: @mut Compartment) {
let obj = utils::define_empty_prototype(~"Node", None, compartment);
let attrs = @~[
JSPropertySpec {
name: compartment.add_name(~"firstChild"),
tinyid: 0,
flags: (JSPROP_SHARED | JSPROP_ENUMERATE | JSPROP_NATIVE_ACCESSORS) as u8,
getter: JSPropertyOpWrapper {op: getFirstChild, info: null()},
setter: JSStrictPropertyOpWrapper {op: null(), info: null()}},
JSPropertySpec {
name: compartment.add_name(~"nextSibling"),
tinyid: 0,
flags: (JSPROP_SHARED | JSPROP_ENUMERATE | JSPROP_NATIVE_ACCESSORS) as u8,
getter: JSPropertyOpWrapper {op: getNextSibling, info: null()},
setter: JSStrictPropertyOpWrapper {op: null(), info: null()}},
JSPropertySpec {
name: compartment.add_name(~"nodeType"),
tinyid: 0,
flags: (JSPROP_SHARED | JSPROP_ENUMERATE | JSPROP_NATIVE_ACCESSORS) as u8,
getter: JSPropertyOpWrapper {op: getNodeType, info: null()},
setter: JSStrictPropertyOpWrapper {op: null(), info: null()}},
JSPropertySpec {
name: null(),
tinyid: 0,
flags: (JSPROP_SHARED | JSPROP_ENUMERATE | JSPROP_NATIVE_ACCESSORS) as u8,
getter: JSPropertyOpWrapper {op: null(), info: null()},
setter: JSStrictPropertyOpWrapper {op: null(), info: null()}}];
compartment.global_props.push(attrs);
do attrs.as_imm_buf |specs, _len| {
unsafe {
JS_DefineProperties(compartment.cx.ptr, obj.ptr, specs);
}
}
}
macro_rules! generate_element(
($name: path) => ({
let node: @mut $name = unsafe { cast::transmute(node.raw_object()) };
@ -135,69 +86,6 @@ pub fn create(cx: *JSContext, node: &mut AbstractNode<ScriptView>) -> *JSObject
}
}
pub unsafe fn unwrap(obj: *JSObject) -> AbstractNode<ScriptView> {
let raw = utils::unwrap::<*mut Node<ScriptView>>(obj);
AbstractNode::from_raw(raw)
}
extern fn getFirstChild(cx: *JSContext, _argc: c_uint, vp: *mut JSVal) -> JSBool {
unsafe {
let obj = JS_THIS_OBJECT(cx, cast::transmute(vp));
if obj.is_null() {
return 0;
}
let node = unwrap(obj);
let rval = do node.with_mut_base |base| {
base.getFirstChild()
};
match rval {
Some(n) => {
n.wrap(cx, ptr::null(), vp); //XXXjdm pass a real scope
}
None => *vp = JSVAL_NULL
};
}
return 1;
}
extern fn getNextSibling(cx: *JSContext, _argc: c_uint, vp: *mut JSVal) -> JSBool {
unsafe {
let obj = JS_THIS_OBJECT(cx, cast::transmute(vp));
if obj.is_null() {
return 0;
}
let node = unwrap(obj);
let rval = do node.with_mut_base |base| {
base.getNextSibling()
};
match rval {
Some(n) => {
n.wrap(cx, ptr::null(), vp); //XXXjdm pass a real scope
}
None => *vp = JSVAL_NULL
};
}
return 1;
}
extern fn getNodeType(cx: *JSContext, _argc: c_uint, vp: *mut JSVal) -> JSBool {
unsafe {
let obj = JS_THIS_OBJECT(cx, cast::transmute(vp));
if obj.is_null() {
return 0;
}
let node = unwrap(obj);
let rval = do node.with_base |base| {
base.getNodeType()
};
*vp = INT_TO_JSVAL(rval);
}
return 1;
}
impl CacheableWrapper for AbstractNode<ScriptView> {
fn get_wrappercache(&mut self) -> &mut WrapperCache {
do self.with_mut_base |base| {

View file

@ -18,7 +18,6 @@ use std::unstable::intrinsics;
use js::glue::*;
use js::glue::{DefineFunctionWithReserved, GetObjectJSClass, RUST_OBJECT_TO_JSVAL};
use js::glue::{js_IsObjectProxyClass, js_IsFunctionProxyClass, IsProxyHandlerFamily};
use js::glue::{PROPERTY_STUB, STRICT_PROPERTY_STUB, ENUMERATE_STUB, CONVERT_STUB, RESOLVE_STUB};
use js::jsapi::{JS_AlreadyHasOwnProperty, JS_NewObject, JS_NewFunction, JS_GetGlobalObject};
use js::jsapi::{JS_DefineProperties, JS_WrapValue, JS_ForwardGetPropertyTo};
use js::jsapi::{JS_EncodeString, JS_free, JS_GetStringCharsAndLength};
@ -31,7 +30,7 @@ use js::jsapi::{JSContext, JSObject, JSBool, jsid, JSClass, JSNative};
use js::jsapi::{JSFunctionSpec, JSPropertySpec, JSVal, JSPropertyDescriptor};
use js::jsfriendapi::bindgen::JS_NewObjectWithUniqueType;
use js::rust::Compartment;
use js::{JSCLASS_HAS_RESERVED_SLOTS, JSPROP_ENUMERATE, JSVAL_NULL};
use js::{JSPROP_ENUMERATE, JSVAL_NULL};
use js::{JSPROP_PERMANENT, JSID_VOID, JSPROP_NATIVE_ACCESSORS, JSPROP_GETTER};
use js::{JSPROP_SETTER, JSVAL_VOID, JSVAL_TRUE, JSVAL_FALSE};
use js::{JS_THIS_OBJECT, JSFUN_CONSTRUCTOR, JS_CALLEE, JSPROP_READONLY};
@ -248,96 +247,6 @@ extern fn has_instance(_cx: *JSContext, obj: **JSObject, v: *JSVal, bp: *mut JSB
}
}
pub fn prototype_jsclass(name: ~str) -> @fn(compartment: @mut Compartment) -> JSClass {
let f: @fn(@mut Compartment) -> JSClass = |compartment: @mut Compartment| {
unsafe {
JSClass {
name: compartment.add_name(name.to_owned()),
flags: 0,
addProperty: GetJSClassHookStubPointer(PROPERTY_STUB) as *u8,
delProperty: GetJSClassHookStubPointer(PROPERTY_STUB) as *u8,
getProperty: GetJSClassHookStubPointer(PROPERTY_STUB) as *u8,
setProperty: GetJSClassHookStubPointer(STRICT_PROPERTY_STUB) as *u8,
enumerate: GetJSClassHookStubPointer(ENUMERATE_STUB) as *u8,
resolve: GetJSClassHookStubPointer(RESOLVE_STUB) as *u8,
convert: GetJSClassHookStubPointer(CONVERT_STUB) as *u8,
finalize: null(),
checkAccess: null(),
call: null(),
hasInstance: has_instance,
construct: null(),
trace: null(),
reserved: (null(), null(), null(), null(), null(), // 05
null(), null(), null(), null(), null(), // 10
null(), null(), null(), null(), null(), // 15
null(), null(), null(), null(), null(), // 20
null(), null(), null(), null(), null(), // 25
null(), null(), null(), null(), null(), // 30
null(), null(), null(), null(), null(), // 35
null(), null(), null(), null(), null()) // 40
}
}
};
return f;
}
pub fn instance_jsclass(name: ~str, finalize: *u8, trace: *u8)
-> @fn(compartment: @mut Compartment) -> JSClass {
let f: @fn(@mut Compartment) -> JSClass = |compartment: @mut Compartment| {
unsafe {
JSClass {
name: compartment.add_name(name.to_owned()),
flags: JSCLASS_HAS_RESERVED_SLOTS(1) | js::JSCLASS_IS_DOMJSCLASS,
addProperty: GetJSClassHookStubPointer(PROPERTY_STUB) as *u8,
delProperty: GetJSClassHookStubPointer(PROPERTY_STUB) as *u8,
getProperty: GetJSClassHookStubPointer(PROPERTY_STUB) as *u8,
setProperty: GetJSClassHookStubPointer(STRICT_PROPERTY_STUB) as *u8,
enumerate: GetJSClassHookStubPointer(ENUMERATE_STUB) as *u8,
resolve: GetJSClassHookStubPointer(RESOLVE_STUB) as *u8,
convert: GetJSClassHookStubPointer(CONVERT_STUB) as *u8,
finalize: finalize,
checkAccess: null(),
call: null(),
hasInstance: has_instance,
construct: null(),
trace: trace,
reserved: (null(), null(), null(), null(), null(), // 05
null(), null(), null(), null(), null(), // 10
null(), null(), null(), null(), null(), // 15
null(), null(), null(), null(), null(), // 20
null(), null(), null(), null(), null(), // 25
null(), null(), null(), null(), null(), // 30
null(), null(), null(), null(), null(), // 35
null(), null(), null(), null(), null()) // 40
}
}
};
return f;
}
pub fn define_empty_prototype(name: ~str, proto: Option<~str>, compartment: @mut Compartment)
-> js::rust::jsobj {
compartment.register_class(prototype_jsclass(name.to_owned()));
//TODO error checking
let obj = (
match proto {
Some(s) => compartment.new_object_with_proto(name.to_owned(),
s,
compartment.global_obj.ptr),
None => compartment.new_object(name.to_owned(), null(), compartment.global_obj.ptr)
}).unwrap();
unsafe {
compartment.define_property(name.to_owned(), RUST_OBJECT_TO_JSVAL(obj.ptr),
GetJSClassHookStubPointer(PROPERTY_STUB) as *u8,
GetJSClassHookStubPointer(STRICT_PROPERTY_STUB) as *u8,
JSPROP_ENUMERATE);
compartment.stash_global_proto(name, obj);
return obj;
}
}
// We use slot 0 for holding the raw object. This is safe for both
// globals and non-globals.
pub static DOM_OBJECT_SLOT: uint = 0;

View file

@ -6,7 +6,6 @@
use dom::bindings::utils::{null_string, str};
use dom::bindings::utils::{BindingObject, CacheableWrapper, DOMString, ErrorResult, WrapperCache};
use dom::htmlelement::HTMLElement;
use dom::htmlcollection::HTMLCollection;
use dom::clientrect::ClientRect;
use dom::clientrectlist::ClientRectList;

View file

@ -608,8 +608,6 @@ impl VoidPtrLike for AbstractNode<LayoutView> {
}
pub fn define_bindings(compartment: @mut Compartment) {
bindings::node::init(compartment);
bindings::element::init(compartment);
bindings::utils::initialize_global(compartment.global_obj.ptr);
bindings::codegen::RegisterBindings::Register(compartment);
}