Skip to content

Commit

Permalink
initial integration of spidermonkey into servo
Browse files Browse the repository at this point in the history
  • Loading branch information
nikomatsakis committed May 24, 2012
1 parent adc6d37 commit 5c31f3d
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 35 deletions.
75 changes: 60 additions & 15 deletions 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;
Expand Down Expand Up @@ -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<compartment,()> {
let np = name_pool();
let globcls = @globclsfn(np);
Expand All @@ -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)})
}
}

Expand All @@ -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,
Expand All @@ -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

Expand All @@ -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)
};
}

Expand Down
31 changes: 14 additions & 17 deletions 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)
}

Expand Down Expand Up @@ -67,26 +63,27 @@ 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|
let jsstr = JS_ValueToString(cx, argv[i]);
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}]
}
}
4 changes: 1 addition & 3 deletions src/servo/servo.rc
Expand Up @@ -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;
Expand Down

0 comments on commit 5c31f3d

Please sign in to comment.