From 006f5be58f2b422080397c6fe1a5c9b90ed9c7d8 Mon Sep 17 00:00:00 2001 From: Josh Matthews Date: Sat, 29 Sep 2012 17:09:24 -0400 Subject: [PATCH 1/3] Move Window method implementations into actual impl to better reflect proposed bindings. --- src/servo/content/content_task.rs | 2 +- src/servo/dom/bindings/window.rs | 38 +++++----------------------- src/servo/dom/node.rs | 3 +-- src/servo/dom/window.rs | 42 ++++++++++++++++++++++++++++++- 4 files changed, 49 insertions(+), 36 deletions(-) diff --git a/src/servo/content/content_task.rs b/src/servo/content/content_task.rs index b96f6c52ad7..67019edc29b 100644 --- a/src/servo/content/content_task.rs +++ b/src/servo/content/content_task.rs @@ -51,7 +51,7 @@ use ptr::null; enum ControlMsg { ParseMsg(Url), ExecuteMsg(Url), - Timer(~dom::bindings::window::TimerData), + Timer(~dom::base::TimerData), ExitMsg } diff --git a/src/servo/dom/bindings/window.rs b/src/servo/dom/bindings/window.rs index aeec2b670a9..edb81aa418a 100644 --- a/src/servo/dom/bindings/window.rs +++ b/src/servo/dom/bindings/window.rs @@ -23,49 +23,23 @@ extern fn alert(cx: *JSContext, argc: c_uint, vp: *jsval) -> JSBool { 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))); + + (*unwrap(JS_THIS_OBJECT(cx, vp))).payload.alert(jsval_to_rust_str(cx, jsstr)); + JS_SET_RVAL(cx, vp, JSVAL_NULL); } 1_i32 } -// Holder for the various JS values associated with setTimeout -// (ie. function value to invoke and all arguments to pass -// to the function when calling it) -struct TimerData { - funval: jsval, - args: DVec, -} - -fn TimerData(argc: c_uint, argv: *jsval) -> TimerData unsafe { - let data = TimerData { - funval : *argv, - args : DVec(), - }; - - let mut i = 2; - while i < argc as uint { - data.args.push(*ptr::offset(argv, i)); - i += 1; - }; - - data -} - - extern fn setTimeout(cx: *JSContext, argc: c_uint, vp: *jsval) -> JSBool unsafe { let argv = JS_ARGV(cx, vp); assert (argc >= 2); //TODO: don't crash when passed a non-integer value for the timeout - // Post a delayed message to the per-window timer task; it will dispatch it - // to the relevant content handler that will deal with it. - std::timer::delayed_send(std::uv_global_loop::get(), - RUST_JSVAL_TO_INT(*ptr::offset(argv, 1)) as uint, - (*unwrap(JS_THIS_OBJECT(cx, vp))).payload.timer_chan, - TimerMessage_Fire(~TimerData(argc, argv))); + (*unwrap(JS_THIS_OBJECT(cx, vp))).payload.setTimeout( + RUST_JSVAL_TO_INT(*ptr::offset(argv, 1)) as int, + argc, argv); JS_SET_RVAL(cx, vp, JSVAL_NULL); return 1; diff --git a/src/servo/dom/node.rs b/src/servo/dom/node.rs index b538b99edbe..0569213a611 100644 --- a/src/servo/dom/node.rs +++ b/src/servo/dom/node.rs @@ -23,7 +23,6 @@ enum NodeData = { kind: ~NodeKind, }; - /* The tree holding Nodes (read-only) */ enum NodeTree { NodeTree } @@ -176,4 +175,4 @@ impl NodeScope : tree::WriteMethods { fn with_tree_fields(node: Node, f: fn(tree::Tree) -> R) -> R { self.write(node, |n| f(n.tree)) } -} \ No newline at end of file +} diff --git a/src/servo/dom/window.rs b/src/servo/dom/window.rs index b98f1b5dff8..ac37628af9b 100644 --- a/src/servo/dom/window.rs +++ b/src/servo/dom/window.rs @@ -2,7 +2,7 @@ use comm::{Port, Chan}; use content::content_task::{ControlMsg, Timer}; enum TimerControlMsg { - TimerMessage_Fire(~dom::bindings::window::TimerData), + TimerMessage_Fire(~TimerData), TimerMessage_Close } @@ -14,6 +14,46 @@ struct Window { } } +// Holder for the various JS values associated with setTimeout +// (ie. function value to invoke and all arguments to pass +// to the function when calling it) +struct TimerData { + funval: jsval, + args: DVec, +} + +fn TimerData(argc: libc::c_uint, argv: *jsval) -> TimerData unsafe { + let data = TimerData { + funval : *argv, + args : DVec(), + }; + + let mut i = 2; + while i < argc as uint { + data.args.push(*ptr::offset(argv, i)); + i += 1; + }; + + data +} + +impl Window { + fn alert(s: &str) { + // Right now, just print to the console + io::println(#fmt("ALERT: %s", s)); + } + + fn setTimeout(&self, timeout: int, argc: libc::c_uint, argv: *jsval) { + let timeout = int::max(0, timeout) as uint; + + // Post a delayed message to the per-window timer task; it will dispatch it + // to the relevant content handler that will deal with it. + std::timer::delayed_send(std::uv_global_loop::get(), + timeout, self.timer_chan, + TimerMessage_Fire(~TimerData(argc, argv))); + } +} + fn Window(content_port: Port) -> Window { let content_chan = Chan(content_port); From 27ccaa80beeaef949aec50c4902cdb5a0ae567ac Mon Sep 17 00:00:00 2001 From: Josh Matthews Date: Sat, 29 Sep 2012 17:49:43 -0400 Subject: [PATCH 2/3] Add basic content test framework. --- mk/check.mk | 9 +++- src/contenttest/contenttest.rs | 73 +++++++++++++++++++++++++++ src/servo/content/content_task.rs | 2 +- src/servo/dom/bindings/window.rs | 11 ++++ src/servo/dom/window.rs | 12 ++++- src/test/content/harness.js | 16 ++++++ src/test/content/test_prototypes.html | 8 +++ src/test/content/test_prototypes.js | 7 +++ src/test/test_close.html | 3 ++ src/test/test_close.js | 1 + 10 files changed, 137 insertions(+), 5 deletions(-) create mode 100644 src/contenttest/contenttest.rs create mode 100644 src/test/content/harness.js create mode 100644 src/test/content/test_prototypes.html create mode 100644 src/test/content/test_prototypes.js create mode 100644 src/test/test_close.html create mode 100644 src/test/test_close.js diff --git a/mk/check.mk b/mk/check.mk index 8c348d02b32..5ee706d38db 100644 --- a/mk/check.mk +++ b/mk/check.mk @@ -20,7 +20,10 @@ $(eval $(call DEF_SUBMODULE_TEST_RULES,$(submodule)))) servo-test: $(DEPS_servo) $(CFG_RUSTC) $(RFLAGS_servo) --test -o $@ $< -reftest: src/reftest/reftest.rs servo +reftest: $(S)src/reftest/reftest.rs servo + $(CFG_RUSTC) $(RFLAGS_servo) -o $@ $< -L . + +contenttest: $(S)src/contenttest/contenttest.rs servo $(CFG_RUSTC) $(RFLAGS_servo) -o $@ $< -L . .PHONY: check $(DEPS_CHECK) @@ -31,5 +34,7 @@ check-servo: servo-test ./servo-test $(TESTNAME) check-ref: reftest - ./reftest --source-dir=$(VPATH)/src/test/ref --work-dir=src/test/ref $(TESTNAME) + ./reftest --source-dir=$(VPATH)/test/ref --work-dir=src/test/ref $(TESTNAME) +check-content: contenttest + ./contenttest --source-dir=$(VPATH)/test/content $(TESTNAME) diff --git a/src/contenttest/contenttest.rs b/src/contenttest/contenttest.rs new file mode 100644 index 00000000000..6ffc18a8a05 --- /dev/null +++ b/src/contenttest/contenttest.rs @@ -0,0 +1,73 @@ +extern mod std; + +use std::test::{TestOpts, run_tests_console, TestDesc}; +use std::getopts::{getopts, reqopt, opt_str, fail_str}; +use os::list_dir_path; + +struct Config { + source_dir: ~str, + filter: Option<~str> +} + +fn main(args: ~[~str]) { + let config = parse_config(args); + let opts = test_options(config); + let tests = find_tests(config); + run_tests_console(&opts, tests); +} + +fn parse_config(args: ~[~str]) -> Config { + let args = args.tail(); + let opts = ~[reqopt(~"source-dir")]; + let matches = match getopts(args, opts) { + Ok(m) => m, + Err(f) => fail fail_str(f) + }; + + Config { + source_dir: opt_str(matches, ~"source-dir"), + filter: if matches.free.is_empty() { + None + } else { + Some(matches.free.head()) + } + } +} + +fn test_options(config: Config) -> TestOpts { + { + filter: config.filter, + run_ignored: false, + logfile: None + } +} + +fn find_tests(config: Config) -> ~[TestDesc] { + let all_files = list_dir_path(&Path(config.source_dir)); + let html_files = all_files.filter( |file| file.to_str().ends_with(".html") ); + return html_files.map(|file| make_test(config, (*file).to_str()) ); +} + +fn make_test(config: Config, file: ~str) -> TestDesc { + { + name: file, + testfn: fn~() { run_test(config, file) }, + ignore: false, + should_fail: false + } +} + +fn run_test(config: Config, file: ~str) { + let infile = ~"file://" + os::make_absolute(&Path(file)).to_str(); + let res = run::program_output("./servo", ~[infile]); + io::print(res.out); + do str::split_char_each(res.out, '\n') |line| { + if line.contains("TEST-UNEXPECTED-FAIL") { + fail str::from_slice(line); + } + true + } +} + +fn render_servo(config: Config, file: ~str) { +} diff --git a/src/servo/content/content_task.rs b/src/servo/content/content_task.rs index 67019edc29b..d55e1f082e1 100644 --- a/src/servo/content/content_task.rs +++ b/src/servo/content/content_task.rs @@ -51,7 +51,7 @@ use ptr::null; enum ControlMsg { ParseMsg(Url), ExecuteMsg(Url), - Timer(~dom::base::TimerData), + Timer(~dom::window::TimerData), ExitMsg } diff --git a/src/servo/dom/bindings/window.rs b/src/servo/dom/bindings/window.rs index edb81aa418a..6effce5dd60 100644 --- a/src/servo/dom/bindings/window.rs +++ b/src/servo/dom/bindings/window.rs @@ -45,6 +45,12 @@ extern fn setTimeout(cx: *JSContext, argc: c_uint, vp: *jsval) -> JSBool unsafe return 1; } +extern fn close(cx: *JSContext, argc: c_uint, vp: *jsval) -> JSBool unsafe { + (*unwrap(JS_THIS_OBJECT(cx, vp))).payload.close(); + JS_SET_RVAL(cx, vp, JSVAL_NULL); + return 1; +} + unsafe fn unwrap(obj: *JSObject) -> *rust_box { let val = JS_GetReservedSlot(obj, 0); cast::reinterpret_cast(&RUST_JSVAL_TO_PRIVATE(val)) @@ -76,6 +82,11 @@ fn init(compartment: bare_compartment, win: @Window) { call: {op: setTimeout, info: null()}, nargs: 2, flags: 0, + selfHostedName: null()}, + {name: compartment.add_name(~"close"), + call: {op: close, info: null()}, + nargs: 2, + flags: 0, selfHostedName: null()}]; vec::as_imm_buf(methods, |fns, _len| { diff --git a/src/servo/dom/window.rs b/src/servo/dom/window.rs index ac37628af9b..6bc74913ad8 100644 --- a/src/servo/dom/window.rs +++ b/src/servo/dom/window.rs @@ -1,9 +1,12 @@ use comm::{Port, Chan}; -use content::content_task::{ControlMsg, Timer}; +use content::content_task::{ControlMsg, Timer, ExitMsg}; +use js::jsapi::jsval; +use dvec::DVec; enum TimerControlMsg { TimerMessage_Fire(~TimerData), - TimerMessage_Close + TimerMessage_Close, + TimerMessage_TriggerExit //XXXjdm this is just a quick hack to talk to the content task } struct Window { @@ -43,6 +46,10 @@ impl Window { io::println(#fmt("ALERT: %s", s)); } + fn close() { + self.timer_chan.send(TimerMessage_TriggerExit); + } + fn setTimeout(&self, timeout: int, argc: libc::c_uint, argv: *jsval) { let timeout = int::max(0, timeout) as uint; @@ -65,6 +72,7 @@ fn Window(content_port: Port) -> Window { TimerMessage_Fire(td) => { content_chan.send(Timer(copy td)); } + TimerMessage_TriggerExit => content_chan.send(ExitMsg) } } } diff --git a/src/test/content/harness.js b/src/test/content/harness.js new file mode 100644 index 00000000000..de2eec8bcf9 --- /dev/null +++ b/src/test/content/harness.js @@ -0,0 +1,16 @@ +function _fail(s) { + window.alert("TEST-UNEXPECTED-FAIL | " + s); +} + +function _pass(s) { + window.alert("TEST-PASS | " + s); +} + +function is(a, b) { + let f = a != b ? _fail : _pass; + f(a + " == " + b); +} + +function finish() { + window.close(); +} \ No newline at end of file diff --git a/src/test/content/test_prototypes.html b/src/test/content/test_prototypes.html new file mode 100644 index 00000000000..95d33713711 --- /dev/null +++ b/src/test/content/test_prototypes.html @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/src/test/content/test_prototypes.js b/src/test/content/test_prototypes.js new file mode 100644 index 00000000000..327843439f5 --- /dev/null +++ b/src/test/content/test_prototypes.js @@ -0,0 +1,7 @@ +is(HTMLImageElement instanceof HTMLElement, true); +is(HTMLElement instanceof Element, true); +is(Element instanceof Node, true); +is(document instanceof Document, true); +is(document.documentElement instanceof HTMLElement, true); +is(document.documentElement instanceof Element, true); +finish(); \ No newline at end of file diff --git a/src/test/test_close.html b/src/test/test_close.html new file mode 100644 index 00000000000..f4c8b185d0d --- /dev/null +++ b/src/test/test_close.html @@ -0,0 +1,3 @@ + + + diff --git a/src/test/test_close.js b/src/test/test_close.js new file mode 100644 index 00000000000..0f1640bab56 --- /dev/null +++ b/src/test/test_close.js @@ -0,0 +1 @@ +window.setTimeout(function() { window.close(); }, 3000); \ No newline at end of file From 8fb858b2694f5bc1a1330666de693f091e7b0671 Mon Sep 17 00:00:00 2001 From: Josh Matthews Date: Tue, 2 Oct 2012 00:25:25 -0400 Subject: [PATCH 3/3] Fix linux build. --- src/rust-azure | 2 +- src/sharegl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rust-azure b/src/rust-azure index 0b520a6caf1..9e8b2d1e8b3 160000 --- a/src/rust-azure +++ b/src/rust-azure @@ -1 +1 @@ -Subproject commit 0b520a6caf17b05d25db0026431873ae3f86a456 +Subproject commit 9e8b2d1e8b327bb49c514c2688265ec6dba9b627 diff --git a/src/sharegl b/src/sharegl index 809ba9338f4..c94fb282867 160000 --- a/src/sharegl +++ b/src/sharegl @@ -1 +1 @@ -Subproject commit 809ba9338f4ab67655786f6f05a60485c9cf56ef +Subproject commit c94fb282867c83783227bbd0dca1edac5c81b097