Add prototypes to DOMDocument and Node.

This commit is contained in:
Josh Matthews 2012-08-20 18:12:31 -07:00
parent 517504e4fc
commit daf95fb41b
6 changed files with 132 additions and 26 deletions

@ -1 +1 @@
Subproject commit 8fa47b7a1dcc4e13f0f5a1e978cf332a4e3d0189 Subproject commit fc904d3a7c36934ad0b2a4f83ad99f3862febada

View file

@ -70,8 +70,8 @@ struct Attr {
} }
fn define_bindings(compartment: bare_compartment, doc: @Document) { fn define_bindings(compartment: bare_compartment, doc: @Document) {
//bindings::window::init(compartment);
bindings::document::init(compartment, doc); bindings::document::init(compartment, doc);
bindings::node::init(compartment);
} }
enum ElementKind { enum ElementKind {

View file

@ -66,6 +66,7 @@ extern fn getDocumentElement(cx: *JSContext, obj: *JSObject, _id: jsid, rval: *m
} }
unsafe fn unwrap(obj: *JSObject) -> *rust_box<Document> { unsafe fn unwrap(obj: *JSObject) -> *rust_box<Document> {
//TODO: some kind of check if this is a Document object
let val = JS_GetReservedSlot(obj, 0); let val = JS_GetReservedSlot(obj, 0);
unsafe::reinterpret_cast(RUST_JSVAL_TO_PRIVATE(val)) unsafe::reinterpret_cast(RUST_JSVAL_TO_PRIVATE(val))
} }
@ -79,6 +80,32 @@ extern fn finalize(_fop: *JSFreeOp, obj: *JSObject) {
} }
fn init(compartment: bare_compartment, doc: @Document) { fn init(compartment: bare_compartment, doc: @Document) {
fn DocumentProto_class(compartment: bare_compartment) -> JSClass {
{name: compartment.add_name(~"DOMDocumentPrototype"),
flags: 0,
addProperty: JS_PropertyStub,
delProperty: JS_PropertyStub,
getProperty: JS_PropertyStub,
setProperty: JS_StrictPropertyStub,
enumerate: JS_EnumerateStub,
resolve: JS_ResolveStub,
convert: JS_ConvertStub,
finalize: null(),
checkAccess: null(),
call: null(),
construct: null(),
hasInstance: utils::has_instance,
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
};
fn Document_class(compartment: bare_compartment) -> JSClass { fn Document_class(compartment: bare_compartment) -> JSClass {
{name: compartment.add_name(~"DOMDocument"), {name: compartment.add_name(~"DOMDocument"),
flags: JSCLASS_HAS_RESERVED_SLOTS(1), flags: JSCLASS_HAS_RESERVED_SLOTS(1),
@ -93,7 +120,7 @@ fn init(compartment: bare_compartment, doc: @Document) {
checkAccess: null(), checkAccess: null(),
call: null(), call: null(),
construct: null(), construct: null(),
hasInstance: null(), hasInstance: utils::has_instance,
trace: null(), trace: null(),
reserved: (null(), null(), null(), null(), null(), // 05 reserved: (null(), null(), null(), null(), null(), // 05
null(), null(), null(), null(), null(), // 10 null(), null(), null(), null(), null(), // 10
@ -105,8 +132,13 @@ fn init(compartment: bare_compartment, doc: @Document) {
null(), null(), null(), null(), null())} // 40 null(), null(), null(), null(), null())} // 40
}; };
compartment.register_class(DocumentProto_class);
compartment.register_class(Document_class);
//TODO error checking
let obj = result::unwrap( let obj = result::unwrap(
compartment.new_object(Document_class, null(), null())); compartment.new_object(~"DOMDocumentPrototype", null(),
compartment.global_obj.ptr));
/*let methods = ~[ /*let methods = ~[
{name: compartment.add_name("getDocumentURI"), {name: compartment.add_name("getDocumentURI"),
call: getDocumentURI, call: getDocumentURI,
@ -123,16 +155,25 @@ fn init(compartment: bare_compartment, doc: @Document) {
getter: getDocumentElement, getter: getDocumentElement,
setter: null()}]; setter: null()}];
vec::push(compartment.global_props, attrs); vec::push(compartment.global_props, attrs);
vec::as_buf(*attrs, |specs, _len| { vec::as_buf(*attrs, |specs, _len| {
JS_DefineProperties(compartment.cx.ptr, obj.ptr, specs); JS_DefineProperties(compartment.cx.ptr, obj.ptr, specs);
}); });
compartment.define_property(~"Document", RUST_OBJECT_TO_JSVAL(obj.ptr),
JS_PropertyStub, JS_StrictPropertyStub,
JSPROP_ENUMERATE);
let instance = result::unwrap(
//compartment.new_object(Document_class, null(), compartment.global_obj.ptr));
compartment.new_object_with_proto(~"DOMDocument", ~"DOMDocumentPrototype",
compartment.global_obj.ptr));
unsafe { unsafe {
let raw_ptr: *libc::c_void = unsafe::reinterpret_cast(squirrel_away(doc)); let raw_ptr: *libc::c_void = unsafe::reinterpret_cast(squirrel_away(doc));
JS_SetReservedSlot(obj.ptr, 0, RUST_PRIVATE_TO_JSVAL(raw_ptr)); JS_SetReservedSlot(instance.ptr, 0, RUST_PRIVATE_TO_JSVAL(raw_ptr));
} }
compartment.define_property(~"document", RUST_OBJECT_TO_JSVAL(obj.ptr), compartment.define_property(~"document", RUST_OBJECT_TO_JSVAL(instance.ptr),
JS_PropertyStub, JS_StrictPropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
JSPROP_ENUMERATE); JSPROP_ENUMERATE);
} }

View file

@ -22,8 +22,33 @@ extern fn finalize(_fop: *JSFreeOp, obj: *JSObject) {
} }
} }
fn create(cx: *JSContext, node: Node) -> jsobj unsafe { fn init(compartment: bare_compartment) {
let compartment = get_compartment(cx); fn NodeProto_class(compartment: bare_compartment) -> JSClass {
{name: compartment.add_name(~"NodePrototype"),
flags: 0,
addProperty: JS_PropertyStub,
delProperty: JS_PropertyStub,
getProperty: JS_PropertyStub,
setProperty: JS_StrictPropertyStub,
enumerate: JS_EnumerateStub,
resolve: JS_PropertyStub,
convert: JS_ConvertStub,
finalize: null(),
checkAccess: null(),
call: null(),
construct: null(),
hasInstance: utils::has_instance,
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
};
fn Node_class(compartment: bare_compartment) -> JSClass { fn Node_class(compartment: bare_compartment) -> JSClass {
{name: compartment.add_name(~"Node"), {name: compartment.add_name(~"Node"),
flags: JSCLASS_HAS_RESERVED_SLOTS(1), flags: JSCLASS_HAS_RESERVED_SLOTS(1),
@ -38,7 +63,7 @@ fn create(cx: *JSContext, node: Node) -> jsobj unsafe {
checkAccess: null(), checkAccess: null(),
call: null(), call: null(),
construct: null(), construct: null(),
hasInstance: null(), hasInstance: utils::has_instance,
trace: null(), trace: null(),
reserved: (null(), null(), null(), null(), null(), // 05 reserved: (null(), null(), null(), null(), null(), // 05
null(), null(), null(), null(), null(), // 10 null(), null(), null(), null(), null(), // 10
@ -50,32 +75,49 @@ fn create(cx: *JSContext, node: Node) -> jsobj unsafe {
null(), null(), null(), null(), null())} // 40 null(), null(), null(), null(), null())} // 40
}; };
compartment.register_class(NodeProto_class);
compartment.register_class(Node_class);
let obj = result::unwrap( let obj = result::unwrap(
(*compartment).new_object(Node_class, null(), compartment.new_object(~"NodePrototype", null(),
(*compartment).global_obj.ptr)); compartment.global_obj.ptr));
let attrs = @~[ let attrs = @~[
{name: (*compartment).add_name(~"firstChild"), {name: compartment.add_name(~"firstChild"),
tinyid: 0, tinyid: 0,
flags: 0, flags: 0,
getter: getFirstChild, getter: getFirstChild,
setter: null()}, setter: null()},
{name: (*compartment).add_name(~"nextSibling"), {name: compartment.add_name(~"nextSibling"),
tinyid: 0, tinyid: 0,
flags: 0, flags: 0,
getter: getNextSibling, getter: getNextSibling,
setter: null()}, setter: null()},
{name: (*compartment).add_name(~"tagName"), {name: compartment.add_name(~"tagName"),
tinyid: 0, tinyid: 0,
flags: 0, flags: 0,
getter: getTagName, getter: getTagName,
setter: null()}]; setter: null()}];
vec::push((*compartment).global_props, attrs); vec::push(compartment.global_props, attrs);
vec::as_buf(*attrs, |specs, _len| { vec::as_buf(*attrs, |specs, _len| {
JS_DefineProperties((*compartment).cx.ptr, obj.ptr, specs); JS_DefineProperties(compartment.cx.ptr, obj.ptr, specs);
}); });
compartment.define_property(~"Node", RUST_OBJECT_TO_JSVAL(obj.ptr),
JS_PropertyStub, JS_StrictPropertyStub,
JSPROP_ENUMERATE);
}
fn create(cx: *JSContext, node: Node) -> jsobj unsafe {
let compartment = get_compartment(cx);
//XXXjdm the parent should probably be the node parent instead of the global
//TODO error checking
let obj = result::unwrap(
(*compartment).new_object_with_proto(~"Node", ~"NodePrototype",
(*compartment).global_obj.ptr));
unsafe { unsafe {
let raw_ptr: *libc::c_void = unsafe::reinterpret_cast(squirrel_away_unique(~node)); let raw_ptr: *libc::c_void = unsafe::reinterpret_cast(squirrel_away_unique(~node));
JS_SetReservedSlot(obj.ptr, 0, RUST_PRIVATE_TO_JSVAL(raw_ptr)); JS_SetReservedSlot(obj.ptr, 0, RUST_PRIVATE_TO_JSVAL(raw_ptr));

View file

@ -4,7 +4,8 @@ import js::{JS_ARGV, JSCLASS_HAS_RESERVED_SLOTS, JSPROP_ENUMERATE, JSPROP_SHARED
import js::jsapi::{JSContext, jsval, JSObject, JSBool, jsid, JSClass, JSFreeOp}; import js::jsapi::{JSContext, jsval, JSObject, JSBool, jsid, JSClass, JSFreeOp};
import js::jsapi::bindgen::{JS_ValueToString, JS_GetStringCharsZAndLength, JS_ReportError, import js::jsapi::bindgen::{JS_ValueToString, JS_GetStringCharsZAndLength, JS_ReportError,
JS_GetReservedSlot, JS_SetReservedSlot, JS_NewStringCopyN, JS_GetReservedSlot, JS_SetReservedSlot, JS_NewStringCopyN,
JS_DefineFunctions, JS_DefineProperty, JS_GetContextPrivate}; JS_DefineFunctions, JS_DefineProperty, JS_GetContextPrivate,
JS_GetClass, JS_GetPrototype};
import js::glue::bindgen::*; import js::glue::bindgen::*;
import result::{result, ok, err}; import result::{result, ok, err};
@ -75,3 +76,18 @@ fn get_compartment(cx: *JSContext) -> *bare_compartment {
compartment compartment
} }
} }
extern fn has_instance(_cx: *JSContext, obj: *JSObject, v: *jsval, bp: *mut JSBool) -> JSBool {
//XXXjdm this is totally broken for non-object values
let mut o = RUST_JSVAL_TO_OBJECT(unsafe {*v});
let clasp = JS_GetClass(obj);
unsafe { *bp = 0; }
while o.is_not_null() {
if JS_GetClass(o) == clasp {
unsafe { *bp = 1; }
break;
}
o = JS_GetPrototype(o);
}
return 1;
}

View file

@ -1,10 +1,17 @@
debug("hi"); debug("hi");
var elem = document.documentElement; var elem = document.documentElement;
debug(elem); debug("document.documentElement: " + elem);
debug(elem.tagName); debug("Document: " + Document);
debug(elem.firstChild); debug("Node: " + Node);
debug(elem.firstChild.tagName); debug("Document instanceof Node: " + (Document instanceof Node));
debug(elem.firstChild.nextSibling); debug("elem instanceof Node: " + (elem instanceof Node));
debug(elem.firstChild.nextSibling.tagName); debug("elem instanceof Document: " + (elem instanceof Document));
debug(elem.nextSibling); debug("document instanceof Document: " + (document instanceof Document));
debug(elem.nextSibling.tagName); debug("document instanceof Node: " + (document instanceof Node));
debug("elem.tagName: " + elem.tagName);
debug("elem.firstChild: " + elem.firstChild);
debug("elem.firstChild.tagName: " + elem.firstChild.tagName);
debug("elem.firstChild.nextSibling: " + elem.firstChild.nextSibling);
debug("elem.firstChild.nextSibling.tagName: " + elem.firstChild.nextSibling.tagName);
debug("elem.nextSibling: " + elem.nextSibling);
debug("elem.nextSibling.tagName: " + elem.nextSibling.tagName);