From 5c31f3d45e0e671e5ccd87683bba8e0b91d537ca Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Thu, 24 May 2012 14:15:59 -0700 Subject: [PATCH] initial integration of spidermonkey into servo --- src/servo/content/js.rs | 75 ++++++++++++++++++++++++++++------- src/servo/content/jsglobal.rs | 31 +++++++-------- src/servo/servo.rc | 4 +- 3 files changed, 75 insertions(+), 35 deletions(-) diff --git a/src/servo/content/js.rs b/src/servo/content/js.rs index 55702c5769d..fc5486835c1 100644 --- a/src/servo/content/js.rs +++ b/src/servo/content/js.rs @@ -1,9 +1,12 @@ -import jsapi::*; -import jsapi::bindgen::*; +import spidermonkey::*; +import spidermonkey::jsapi::*; +import spidermonkey::jsapi::bindgen::*; import ptr::{null, addr_of}; import result::{result, ok, err, extensions}; import libc::c_char; import name_pool::{name_pool, methods}; +import str::unsafe::from_c_str; +import io::writer_util; export rt; export methods; @@ -58,6 +61,23 @@ impl methods for cx { jsobj } + fn set_default_options_and_version() { + self.set_options(JSOPTION_VAROBJFIX | JSOPTION_METHODJIT); + self.set_version(JSVERSION_LATEST); + } + + fn set_options(v: jsuint) { + JS_SetOptions(self.ptr, v); + } + + fn set_version(v: i32) { + JS_SetVersion(self.ptr, v); + } + + fn set_error_reporter(reportfn: *u8) { + JS_SetErrorReporter(self.ptr, reportfn); + } + fn new_compartment(globclsfn: fn(name_pool) -> JSClass) -> result { let np = name_pool(); let globcls = @globclsfn(np); @@ -67,9 +87,11 @@ impl methods for cx { &*globcls as *JSClass, null()); result(JS_InitStandardClasses(self.ptr, globobj)).chain { |_ok| - ok({name_pool: np, - global_class: globcls, - global_obj: self.rooted_obj(globobj)}) + ok(@{cx: self, + name_pool: np, + global_class: globcls, + mut global_funcs: [], + global_obj: self.rooted_obj(globobj)}) } } @@ -79,7 +101,7 @@ impl methods for cx { str::as_c_str(filename) { |filename_cstr| let bytes_ptr = bytes_ptr as *c_char; let v: jsval = 0_u64; - #debug["Evaluating script from %s", filename]; + #debug["Evaluating script from %s with bytes %?", filename, bytes]; if JS_EvaluateScript(self.ptr, glob.ptr, bytes_ptr, bytes.len() as uintN, filename_cstr, line_num as uintN, @@ -100,12 +122,24 @@ impl methods for cx { // ___________________________________________________________________________ // compartment -type compartment = { +type compartment = @{ + cx: cx, name_pool: name_pool, global_class: @JSClass, + mut global_funcs: [@[JSFunctionSpec]], global_obj: jsobj }; +impl methods for compartment { + fn define_functions(specfn: fn(name_pool) -> [JSFunctionSpec]) -> result<(),()> { + let specvec = @specfn(self.name_pool); + self.global_funcs += [specvec]; + vec::as_buf(*specvec) { |specs| + result(JS_DefineFunctions(self.cx.ptr, self.global_obj.ptr, specs)) + } + } +} + // ___________________________________________________________________________ // objects @@ -118,18 +152,29 @@ resource jsobj_rsrc(self: {cx: cx, cxptr: *JSContext, ptr: *JSObject}) { #[cfg(test)] mod test { + crust fn reportError(_cx: *JSContext, + msg: *c_char, + report: *JSErrorReport) { + unsafe { + let fnptr = (*report).filename; + let fname = if fnptr.is_not_null() {from_c_str(fnptr)} else {"none"}; + let lineno = (*report).lineno; + let msg = from_c_str(msg); + #error["Error at %s:%?: %s\n", fname, lineno, msg]; + } + } + #[test] fn dummy() { let rt = rt(); let cx = rt.cx(); - let gc = jsglobal::global_class(); - cx.new_global(gc).chain { - |glob| - str::as_bytes("print(\"1\");") { - |bytes| - cx.evaluate_script(glob, bytes, "test", 1u) - }; - ok(()) + cx.set_default_options_and_version(); + cx.set_error_reporter(reportError); + cx.new_compartment(jsglobal::global_class).chain { |comp| + comp.define_functions(jsglobal::global_fns); + + let bytes = str::bytes("debug(22);"); + cx.evaluate_script(comp.global_obj, bytes, "test", 1u) }; } diff --git a/src/servo/content/jsglobal.rs b/src/servo/content/jsglobal.rs index 04de837b7b2..29995fe4af4 100644 --- a/src/servo/content/jsglobal.rs +++ b/src/servo/content/jsglobal.rs @@ -1,23 +1,19 @@ // Definition for the global object that we use: -import jsapi::*; -import jsapi::bindgen::*; +import spidermonkey::*; +import spidermonkey::jsapi::*; +import spidermonkey::jsapi::bindgen::*; import ptr::null; import jsutil::*; import name_pool::{name_pool, methods}; -crust fn PropertyStub(++arg0: *JSContext, - ++arg1: *JSObject, - ++arg2: jsid, - ++arg3: *jsval) -> JSBool { +// Can't use spidermonkey::crust::* versions due to Rust #2440 + +crust fn PropertyStub(++arg0: *JSContext, ++arg1: *JSObject, ++arg2: jsid, ++arg3: *jsval) -> JSBool { JS_PropertyStub(arg0, arg1, arg2, arg3) } -crust fn StrictPropertyStub(++arg0: *JSContext, - ++arg1: *JSObject, - ++arg2: jsid, - ++arg3: JSBool, - ++arg4: *jsval) -> JSBool { +crust fn StrictPropertyStub(++arg0: *JSContext, ++arg1: *JSObject, ++arg2: jsid, ++arg3: JSBool, ++arg4: *jsval) -> JSBool { JS_StrictPropertyStub(arg0, arg1, arg2, arg3, arg4) } @@ -67,9 +63,11 @@ fn global_class(np: name_pool) -> JSClass { null(), null(), null(), null(), null())} // 40 } -crust fn print(cx: *JSContext, argc: uintN, vp: *jsval) { +crust fn debug(cx: *JSContext, argc: uintN, vp: *jsval) { import io::writer_util; + #debug["debug() called with %? arguments", argc]; + unsafe { let argv = JS_ARGV(cx, vp); uint::range(0u, argc as uint) { |i| @@ -77,16 +75,15 @@ crust fn print(cx: *JSContext, argc: uintN, vp: *jsval) { let bytes = JS_EncodeString(cx, jsstr); let str = str::unsafe::from_c_str(bytes); JS_free(cx, unsafe::reinterpret_cast(bytes)); - io::stdout().write_str(str); - io::stdout().write_str("\n"); + #debug["%s", str]; } JS_SET_RVAL(cx, vp, JSVAL_NULL); } } fn global_fns(np: name_pool) -> [JSFunctionSpec] { - [{name: np.add("print"), - call: print, + [{name: np.add("debug"), + call: debug, nargs: 0_u16, flags: 0_u16}] -} \ No newline at end of file +} diff --git a/src/servo/servo.rc b/src/servo/servo.rc index c5ab1d2f590..309dd818b9e 100755 --- a/src/servo/servo.rc +++ b/src/servo/servo.rc @@ -9,11 +9,9 @@ use std; use sdl; use azure; -use js; +use spidermonkey (name = "js"); use harfbuzz; -import js::jsapi; - mod dom { mod base; mod rcu;