initial integration of spidermonkey into servo

This commit is contained in:
Niko Matsakis 2012-05-24 14:15:59 -07:00
parent adc6d3701d
commit 5c31f3d45e
3 changed files with 75 additions and 35 deletions

View file

@ -1,9 +1,12 @@
import jsapi::*; import spidermonkey::*;
import jsapi::bindgen::*; import spidermonkey::jsapi::*;
import spidermonkey::jsapi::bindgen::*;
import ptr::{null, addr_of}; import ptr::{null, addr_of};
import result::{result, ok, err, extensions}; import result::{result, ok, err, extensions};
import libc::c_char; import libc::c_char;
import name_pool::{name_pool, methods}; import name_pool::{name_pool, methods};
import str::unsafe::from_c_str;
import io::writer_util;
export rt; export rt;
export methods; export methods;
@ -58,6 +61,23 @@ impl methods for cx {
jsobj 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<compartment,()> { fn new_compartment(globclsfn: fn(name_pool) -> JSClass) -> result<compartment,()> {
let np = name_pool(); let np = name_pool();
let globcls = @globclsfn(np); let globcls = @globclsfn(np);
@ -67,9 +87,11 @@ impl methods for cx {
&*globcls as *JSClass, &*globcls as *JSClass,
null()); null());
result(JS_InitStandardClasses(self.ptr, globobj)).chain { |_ok| result(JS_InitStandardClasses(self.ptr, globobj)).chain { |_ok|
ok({name_pool: np, ok(@{cx: self,
global_class: globcls, name_pool: np,
global_obj: self.rooted_obj(globobj)}) 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| str::as_c_str(filename) { |filename_cstr|
let bytes_ptr = bytes_ptr as *c_char; let bytes_ptr = bytes_ptr as *c_char;
let v: jsval = 0_u64; 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, if JS_EvaluateScript(self.ptr, glob.ptr,
bytes_ptr, bytes.len() as uintN, bytes_ptr, bytes.len() as uintN,
filename_cstr, line_num as uintN, filename_cstr, line_num as uintN,
@ -100,12 +122,24 @@ impl methods for cx {
// ___________________________________________________________________________ // ___________________________________________________________________________
// compartment // compartment
type compartment = { type compartment = @{
cx: cx,
name_pool: name_pool, name_pool: name_pool,
global_class: @JSClass, global_class: @JSClass,
mut global_funcs: [@[JSFunctionSpec]],
global_obj: jsobj 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 // objects
@ -118,18 +152,29 @@ resource jsobj_rsrc(self: {cx: cx, cxptr: *JSContext, ptr: *JSObject}) {
#[cfg(test)] #[cfg(test)]
mod 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] #[test]
fn dummy() { fn dummy() {
let rt = rt(); let rt = rt();
let cx = rt.cx(); let cx = rt.cx();
let gc = jsglobal::global_class(); cx.set_default_options_and_version();
cx.new_global(gc).chain { cx.set_error_reporter(reportError);
|glob| cx.new_compartment(jsglobal::global_class).chain { |comp|
str::as_bytes("print(\"1\");") { comp.define_functions(jsglobal::global_fns);
|bytes|
cx.evaluate_script(glob, bytes, "test", 1u) let bytes = str::bytes("debug(22);");
}; cx.evaluate_script(comp.global_obj, bytes, "test", 1u)
ok(())
}; };
} }

View file

@ -1,23 +1,19 @@
// Definition for the global object that we use: // Definition for the global object that we use:
import jsapi::*; import spidermonkey::*;
import jsapi::bindgen::*; import spidermonkey::jsapi::*;
import spidermonkey::jsapi::bindgen::*;
import ptr::null; import ptr::null;
import jsutil::*; import jsutil::*;
import name_pool::{name_pool, methods}; import name_pool::{name_pool, methods};
crust fn PropertyStub(++arg0: *JSContext, // Can't use spidermonkey::crust::* versions due to Rust #2440
++arg1: *JSObject,
++arg2: jsid, crust fn PropertyStub(++arg0: *JSContext, ++arg1: *JSObject, ++arg2: jsid, ++arg3: *jsval) -> JSBool {
++arg3: *jsval) -> JSBool {
JS_PropertyStub(arg0, arg1, arg2, arg3) JS_PropertyStub(arg0, arg1, arg2, arg3)
} }
crust fn StrictPropertyStub(++arg0: *JSContext, crust fn StrictPropertyStub(++arg0: *JSContext, ++arg1: *JSObject, ++arg2: jsid, ++arg3: JSBool, ++arg4: *jsval) -> JSBool {
++arg1: *JSObject,
++arg2: jsid,
++arg3: JSBool,
++arg4: *jsval) -> JSBool {
JS_StrictPropertyStub(arg0, arg1, arg2, arg3, arg4) JS_StrictPropertyStub(arg0, arg1, arg2, arg3, arg4)
} }
@ -67,9 +63,11 @@ fn global_class(np: name_pool) -> JSClass {
null(), null(), null(), null(), null())} // 40 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; import io::writer_util;
#debug["debug() called with %? arguments", argc];
unsafe { unsafe {
let argv = JS_ARGV(cx, vp); let argv = JS_ARGV(cx, vp);
uint::range(0u, argc as uint) { |i| 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 bytes = JS_EncodeString(cx, jsstr);
let str = str::unsafe::from_c_str(bytes); let str = str::unsafe::from_c_str(bytes);
JS_free(cx, unsafe::reinterpret_cast(bytes)); JS_free(cx, unsafe::reinterpret_cast(bytes));
io::stdout().write_str(str); #debug["%s", str];
io::stdout().write_str("\n");
} }
JS_SET_RVAL(cx, vp, JSVAL_NULL); JS_SET_RVAL(cx, vp, JSVAL_NULL);
} }
} }
fn global_fns(np: name_pool) -> [JSFunctionSpec] { fn global_fns(np: name_pool) -> [JSFunctionSpec] {
[{name: np.add("print"), [{name: np.add("debug"),
call: print, call: debug,
nargs: 0_u16, nargs: 0_u16,
flags: 0_u16}] flags: 0_u16}]
} }

View file

@ -9,11 +9,9 @@
use std; use std;
use sdl; use sdl;
use azure; use azure;
use js; use spidermonkey (name = "js");
use harfbuzz; use harfbuzz;
import js::jsapi;
mod dom { mod dom {
mod base; mod base;
mod rcu; mod rcu;