From 5079e1088217eb23a82487d3a352de4f7c3659a2 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Mon, 20 Aug 2012 18:49:13 -0700 Subject: [PATCH] Add a window object with an alert method test/test-js-alert.html tests use of the alert method, which currently just prints to the console. --- src/rust-mozjs | 2 +- src/servo/content/content_task.rs | 15 +++-- src/servo/dom/base.rs | 11 +++- src/servo/dom/bindings/document.rs | 46 ++++---------- src/servo/dom/bindings/utils.rs | 32 +++++++++- src/servo/dom/bindings/window.rs | 97 ++++++++++++++++++++++++++++++ src/servo/servo.rc | 1 + src/test/test-alert.js | 8 +++ src/test/test-js-alert.html | 1 + 9 files changed, 172 insertions(+), 41 deletions(-) create mode 100644 src/servo/dom/bindings/window.rs create mode 100644 src/test/test-alert.js create mode 100644 src/test/test-js-alert.html diff --git a/src/rust-mozjs b/src/rust-mozjs index fc904d3a7c3..1a01c0063a4 160000 --- a/src/rust-mozjs +++ b/src/rust-mozjs @@ -1 +1 @@ -Subproject commit fc904d3a7c36934ad0b2a4f83ad99f3862febada +Subproject commit 1a01c0063a4f0cd5ceaf04fbd84a59699f668a02 diff --git a/src/servo/content/content_task.rs b/src/servo/content/content_task.rs index 945d43fd8b9..e48b4cc944e 100644 --- a/src/servo/content/content_task.rs +++ b/src/servo/content/content_task.rs @@ -13,7 +13,7 @@ import task::{spawn, spawn_listener}; import io::{read_whole_file, println}; import result::{ok, err}; -import dom::base::{Document, Node, NodeScope, define_bindings}; +import dom::base::{Document, Node, NodeScope, Window, define_bindings}; import dom::event::{Event, ResizeEvent}; import dom::style; import dom::style::Stylesheet; @@ -80,6 +80,7 @@ struct Content { let jsrt: jsrt; let mut document: option<@Document>; + let mut window: option<@Window>; let mut doc_url: option; let resource_task: ResourceTask; @@ -95,7 +96,8 @@ struct Content { self.jsrt = jsrt(); self.document = none; - self.doc_url = none; + self.window = none; + self.doc_url = none; self.compositor.add_event_listener(self.event_port.chan()); @@ -129,13 +131,15 @@ struct Content { let js_scripts = js_port.recv(); // Apply the css rules to the dom tree: - #debug["%?", css_rules]; + #debug["css_rules: %?", css_rules]; - #debug["%?", js_scripts]; + #debug["js_scripts: %?", js_scripts]; let document = Document(root, css_rules); + let window = Window(root); self.relayout(document, &url); self.document = some(@document); + self.window = some(@window); self.doc_url = some(copy url); //XXXjdm it was easier to duplicate the relevant ExecuteMsg code; @@ -146,7 +150,8 @@ struct Content { cx.set_logging_error_reporter(); cx.new_compartment(global_class).chain(|compartment| { compartment.define_functions(debug_fns); - define_bindings(*compartment, option::get(self.document)); + define_bindings(*compartment, option::get(self.document), + option::get(self.window)); cx.evaluate_script(compartment.global_obj, bytes, ~"???", 1u) }); } diff --git a/src/servo/dom/base.rs b/src/servo/dom/base.rs index 9ca7aa27252..9a4fafc80da 100644 --- a/src/servo/dom/base.rs +++ b/src/servo/dom/base.rs @@ -15,6 +15,13 @@ import bindings; import std::arc::arc; import style::Stylesheet; +struct Window { + let root: Node; + new(root: Node) { + self.root = root; + } +} + struct Document { let root: Node; let css_rules: arc; @@ -69,7 +76,9 @@ struct Attr { } } -fn define_bindings(compartment: bare_compartment, doc: @Document) { +fn define_bindings(compartment: bare_compartment, doc: @Document, + win: @Window) { + bindings::window::init(compartment, win); bindings::document::init(compartment, doc); bindings::node::init(compartment); } diff --git a/src/servo/dom/bindings/document.rs b/src/servo/dom/bindings/document.rs index 1151974856d..b4a72d96224 100644 --- a/src/servo/dom/bindings/document.rs +++ b/src/servo/dom/bindings/document.rs @@ -1,4 +1,4 @@ -import js::rust::{bare_compartment, methods}; +import js::rust::{compartment, bare_compartment, methods, jsobj}; import js::{JS_ARGV, JSCLASS_HAS_RESERVED_SLOTS, JSPROP_ENUMERATE, JSPROP_SHARED, JSVAL_NULL, JS_THIS_OBJECT, JS_SET_RVAL}; import js::jsapi::{JSContext, jsval, JSObject, JSBool, jsid, JSClass, JSFreeOp}; @@ -10,9 +10,10 @@ import js::crust::{JS_PropertyStub, JS_StrictPropertyStub, JS_EnumerateStub, JS_ import result::{result, ok, err}; import ptr::null; import libc::c_uint; -import utils::{DOMString, domstring_to_jsval, rust_box, squirrel_away, str}; +import utils::{DOMString, domstring_to_jsval, rust_box, squirrel_away, str, + Document_class}; import bindings::node::create; -import base::Document; +import base::{Document, Node}; enum DOMException { INVALID_CHARACTER_ERR @@ -59,6 +60,8 @@ enum Element = int; return 1; }*/ +// Unfortunately duplicated in document and window. +// Generalizing it triggers a trans bug extern fn getDocumentElement(cx: *JSContext, obj: *JSObject, _id: jsid, rval: *mut jsval) -> JSBool unsafe { let node = (*unwrap(obj)).payload.root; *rval = RUST_OBJECT_TO_JSVAL(node::create(cx, node).ptr); @@ -80,7 +83,7 @@ extern fn finalize(_fop: *JSFreeOp, obj: *JSObject) { } fn init(compartment: bare_compartment, doc: @Document) { - fn DocumentProto_class(compartment: bare_compartment) -> JSClass { + fn DocumentProto_class(compartment: bare_compartment) -> JSClass { {name: compartment.add_name(~"DOMDocumentPrototype"), flags: 0, addProperty: JS_PropertyStub, @@ -106,39 +109,16 @@ fn init(compartment: bare_compartment, doc: @Document) { null(), null(), null(), null(), null())} // 40 }; - fn Document_class(compartment: bare_compartment) -> JSClass { - {name: compartment.add_name(~"DOMDocument"), - flags: JSCLASS_HAS_RESERVED_SLOTS(1), - addProperty: JS_PropertyStub, - delProperty: JS_PropertyStub, - getProperty: JS_PropertyStub, - setProperty: JS_StrictPropertyStub, - enumerate: JS_EnumerateStub, - resolve: JS_ResolveStub, - convert: JS_ConvertStub, - finalize: finalize, - 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 - }; - compartment.register_class(DocumentProto_class); - compartment.register_class(Document_class); + compartment.register_class(|c| Document_class(c, ~"DOMDocument", + finalize)); //TODO error checking let obj = result::unwrap( - compartment.new_object(~"DOMDocumentPrototype", null(), - compartment.global_obj.ptr)); + compartment.new_object(~"DOMDocumentPrototype", + null(), + compartment.global_obj.ptr)); + /*let methods = ~[ {name: compartment.add_name("getDocumentURI"), call: getDocumentURI, diff --git a/src/servo/dom/bindings/utils.rs b/src/servo/dom/bindings/utils.rs index d7aceb337d8..ad37135ea63 100644 --- a/src/servo/dom/bindings/utils.rs +++ b/src/servo/dom/bindings/utils.rs @@ -1,4 +1,4 @@ -import js::rust::{compartment, bare_compartment}; +import js::rust::{compartment, bare_compartment, methods}; import js::{JS_ARGV, JSCLASS_HAS_RESERVED_SLOTS, JSPROP_ENUMERATE, JSPROP_SHARED, JSVAL_NULL, JS_THIS_OBJECT, JS_SET_RVAL}; import js::jsapi::{JSContext, jsval, JSObject, JSBool, jsid, JSClass, JSFreeOp}; @@ -7,7 +7,10 @@ import js::jsapi::bindgen::{JS_ValueToString, JS_GetStringCharsZAndLength, JS_Re JS_DefineFunctions, JS_DefineProperty, JS_GetContextPrivate, JS_GetClass, JS_GetPrototype}; import js::glue::bindgen::*; +import ptr::null; import result::{result, ok, err}; +import js::crust::{JS_PropertyStub, JS_StrictPropertyStub, JS_EnumerateStub, + JS_ResolveStub, JS_ConvertStub}; enum DOMString { str(~str), @@ -91,3 +94,30 @@ extern fn has_instance(_cx: *JSContext, obj: *JSObject, v: *jsval, bp: *mut JSBo } return 1; } + +fn Document_class(compartment: bare_compartment, name: ~str, + finalize: *u8) -> JSClass { + {name: compartment.add_name(name), + flags: JSCLASS_HAS_RESERVED_SLOTS(1), + addProperty: JS_PropertyStub, + delProperty: JS_PropertyStub, + getProperty: JS_PropertyStub, + setProperty: JS_StrictPropertyStub, + enumerate: JS_EnumerateStub, + resolve: JS_ResolveStub, + convert: JS_ConvertStub, + finalize: finalize, + checkAccess: null(), + call: null(), + construct: null(), + hasInstance: 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 +} diff --git a/src/servo/dom/bindings/window.rs b/src/servo/dom/bindings/window.rs new file mode 100644 index 00000000000..646d872b623 --- /dev/null +++ b/src/servo/dom/bindings/window.rs @@ -0,0 +1,97 @@ +import js::rust::{bare_compartment, methods}; +import js::{JS_ARGV, JSCLASS_HAS_RESERVED_SLOTS, JSPROP_ENUMERATE, JSPROP_SHARED, JSVAL_NULL, JS_THIS_OBJECT, + JS_SET_RVAL}; +import js::jsapi::{JSContext, jsval, JSObject, JSBool, jsid, JSClass, JSFreeOp}; +import js::jsapi::bindgen::{JS_ValueToString, JS_GetStringCharsZAndLength, JS_ReportError, + JS_GetReservedSlot, JS_SetReservedSlot, JS_NewStringCopyN, + JS_DefineFunctions, JS_DefineProperty, JS_DefineProperties, JS_EncodeString, JS_free}; +import js::glue::bindgen::*; +import js::global::jsval_to_rust_str; +import js::crust::{JS_PropertyStub, JS_StrictPropertyStub, JS_EnumerateStub, JS_ConvertStub, JS_ResolveStub}; +import result::{result, ok, err}; +import ptr::null; +import libc::c_uint; +import utils::{DOMString, domstring_to_jsval, rust_box, squirrel_away, str, + Document_class}; +import bindings::node::create; +import base::{Node, Window}; + +enum DOMException { + INVALID_CHARACTER_ERR +} + +enum Element = int; + +extern fn alert(cx: *JSContext, argc: c_uint, vp: *jsval) -> JSBool { + unsafe { + let argv = JS_ARGV(cx, vp); + assert (argc == 1); + // Abstract this pattern and use it in debug, too? + let jsstr = JS_ValueToString(cx, *ptr::offset(argv, 0)); + // Right now, just print to the console + io::println(#fmt("ALERT: %s", jsval_to_rust_str(cx, jsstr))); + JS_SET_RVAL(cx, vp, JSVAL_NULL); + } + 1_i32 +} + +// Unfortunately duplicated in document and window. +// Generalizing it triggers a trans bug +extern fn getDocumentElement(cx: *JSContext, obj: *JSObject, + _id: jsid, rval: *mut jsval) -> JSBool unsafe { + let node = (*unwrap(obj)).payload.root; + *rval = RUST_OBJECT_TO_JSVAL(node::create(cx, node).ptr); + return 1; +} + +unsafe fn unwrap(obj: *JSObject) -> *rust_box { + let val = JS_GetReservedSlot(obj, 0); + unsafe::reinterpret_cast(RUST_JSVAL_TO_PRIVATE(val)) +} + +extern fn finalize(_fop: *JSFreeOp, obj: *JSObject) { + #debug("finalize!"); + unsafe { + let val = JS_GetReservedSlot(obj, 0); + let _: @Window = unsafe::reinterpret_cast(RUST_JSVAL_TO_PRIVATE(val)); + } +} + +fn init(compartment: bare_compartment, win: @Window) { + + compartment.register_class(|c| Document_class(c, ~"DOMWindow", + finalize)); + + let obj = result::unwrap( + compartment.new_object(~"DOMWindow", null(), null())); + + /* Define methods on a window */ + let methods = ~[{name: compartment.add_name(~"alert"), + call: alert, + nargs: 1, + flags: 0}]; + + vec::as_buf(methods, |fns, _len| { + JS_DefineFunctions(compartment.cx.ptr, obj.ptr, fns); + }); + + let attrs = @~[ + {name: compartment.add_name(~"DOMWindow"), + tinyid: 0, // ??? + flags: 0, + getter: getDocumentElement, + setter: null()}]; + vec::push(compartment.global_props, attrs); + vec::as_buf(*attrs, |specs, _len| { + JS_DefineProperties(compartment.cx.ptr, obj.ptr, specs); + }); + + unsafe { + let raw_ptr: *libc::c_void = unsafe::reinterpret_cast(squirrel_away(win)); + JS_SetReservedSlot(obj.ptr, 0, RUST_PRIVATE_TO_JSVAL(raw_ptr)); + } + + compartment.define_property(~"window", RUST_OBJECT_TO_JSVAL(obj.ptr), + JS_PropertyStub, JS_StrictPropertyStub, + JSPROP_ENUMERATE); +} diff --git a/src/servo/servo.rc b/src/servo/servo.rc index cb0f4421bb7..4b11b2d472e 100755 --- a/src/servo/servo.rc +++ b/src/servo/servo.rc @@ -28,6 +28,7 @@ mod dom { mod document; mod utils; mod node; + mod window; } } diff --git a/src/test/test-alert.js b/src/test/test-alert.js new file mode 100644 index 00000000000..a8ea7ab24b9 --- /dev/null +++ b/src/test/test-alert.js @@ -0,0 +1,8 @@ +function output (text) +{ + window.alert(text); +} + +output("Opossums have pouches like kangaroos"); + + diff --git a/src/test/test-js-alert.html b/src/test/test-js-alert.html new file mode 100644 index 00000000000..9d875b04249 --- /dev/null +++ b/src/test/test-js-alert.html @@ -0,0 +1 @@ +