From 6d27ee5e0e4d1f3d7e02a1700df1ef3cb0731221 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Thu, 10 May 2012 16:23:13 -0700 Subject: [PATCH] integrate spidermonkey (it doesn't do anything yet) --- src/etc/jsdefine | 21 ++++++++++ src/mozjs | 2 +- src/servo/content.rs | 11 ++++- src/servo/content/js.rs | 79 +++++++++++++++++++++++++++++++++++ src/servo/content/jsglobal.rs | 69 ++++++++++++++++++++++++++++++ src/servo/engine.rs | 8 +++- src/servo/servo.rc | 8 +++- 7 files changed, 194 insertions(+), 4 deletions(-) create mode 100755 src/etc/jsdefine create mode 100644 src/servo/content/js.rs create mode 100644 src/servo/content/jsglobal.rs diff --git a/src/etc/jsdefine b/src/etc/jsdefine new file mode 100755 index 00000000000..c16febf9706 --- /dev/null +++ b/src/etc/jsdefine @@ -0,0 +1,21 @@ +#!/bin/bash +# +# Handy tool for extracting #defines from jsapi.h. For example: +# ./jsdefine %x JSCLASS_GLOBAL_FLAGS +# outputs +# 48000 + +ETCDIR=$(dirname $0) +INCDIR=${ETCDIR}/../mozjs/dist/include + +echo > jsdefine.c +echo '#include "jsapi.h"' >> jsdefine.c +echo '' >> jsdefine.c +echo 'int main() {' >> jsdefine.c +echo ' printf(' >> jsdefine.c +echo ' "'"$1"'\n"', >> jsdefine.c +echo " $2);" >> jsdefine.c +echo '}' >> jsdefine.c + +gcc -I ${INCDIR} jsdefine.c -o jsdefine.exe +./jsdefine.exe diff --git a/src/mozjs b/src/mozjs index e8ffa4638b1..a971b9dd539 160000 --- a/src/mozjs +++ b/src/mozjs @@ -1 +1 @@ -Subproject commit e8ffa4638b185dc2a7303fadcd253599684f0028 +Subproject commit a971b9dd53975db0225bb900c216f2a1f4cd1de9 diff --git a/src/servo/content.rs b/src/servo/content.rs index 3e9264dfb1c..5197dc6d3f5 100644 --- a/src/servo/content.rs +++ b/src/servo/content.rs @@ -4,9 +4,11 @@ export content; import dom::rcu::writer_methods; import dom=dom::base; import layout::layout; +import js::methods; enum msg { parse(str), + execute(str), exit } @@ -29,10 +31,11 @@ fn join_layout(scope: dom::node_scope, fn content(to_layout: chan) -> chan { task::spawn_listener:: {|from_master| let scope = dom::node_scope(); + let rt = js::rt(); loop { alt from_master.recv() { parse(filename) { - #debug["content: Received filename `%s`", filename]; + #debug["content: Received filename `%s` to parse", filename]; // Note: we can parse the next document in parallel // with any previous documents. @@ -50,6 +53,12 @@ fn content(to_layout: chan) -> chan { // changes will be isolated. scope.reader_forked(); } + execute(filename) { + #debug["content: Received filename `%s` to execute", filename]; + + let cx = rt.cx(); + let _glob = cx.new_global(jsglobal::global_class()); + } exit { to_layout.send(layout::exit); break; diff --git a/src/servo/content/js.rs b/src/servo/content/js.rs new file mode 100644 index 00000000000..b76fd92683a --- /dev/null +++ b/src/servo/content/js.rs @@ -0,0 +1,79 @@ +import jsapi::*; +import jsapi::bindgen::*; +import ptr::{null, addr_of}; +import result::{result, ok, err, extensions}; + +export rt; +export methods; +export cx; +export named_class; +export jsobj; + +const default_heapsize: u32 = 8_u32 * 1024_u32 * 1024_u32; +const default_stacksize: uint = 8192u; +const ERR: JSBool = 0_i32; + +fn result(n: JSBool) -> result<(),()> { + if n != ERR {ok(())} else {err(())} +} + +type named_class = @{ + name: str, + jsclass: JSClass +}; + +// ___________________________________________________________________________ +// runtimes + +type rt = @rt_rsrc; + +resource rt_rsrc(self: {ptr: *JSRuntime}) { + JS_Finish(self.ptr) +} + +fn rt() -> rt { + @rt_rsrc({ptr: JS_Init(default_heapsize)}) +} + +impl methods for rt { + fn cx() -> cx { + @cx_rsrc({ptr: JS_NewContext(self.ptr, default_stacksize)}) + } +} + +// ___________________________________________________________________________ +// contexts + +type cx = @cx_rsrc; +resource cx_rsrc(self: {ptr: *JSContext}) { + JS_DestroyContext(self.ptr); +} + +impl methods for cx { + fn rooted_obj(obj: *JSObject) -> jsobj { + let jsobj = @jsobj_rsrc({cx: self.ptr, obj: obj}); + JS_AddObjectRoot(self.ptr, ptr::addr_of(jsobj.obj)); + jsobj + } + + fn new_global(globcls: named_class) -> result { + let globobj = + JS_NewCompartmentAndGlobalObject( + self.ptr, + addr_of(globcls.jsclass), + null()); + result(JS_InitStandardClasses(self.ptr, globobj)).chain { |_ok| + ok(self.rooted_obj(globobj)) + } + } +} + +// ___________________________________________________________________________ +// objects + +type jsobj = @jsobj_rsrc; + +resource jsobj_rsrc(self: {cx: *JSContext, obj: *JSObject}) { + JS_RemoveObjectRoot(self.cx, ptr::addr_of(self.obj)); +} + diff --git a/src/servo/content/jsglobal.rs b/src/servo/content/jsglobal.rs new file mode 100644 index 00000000000..ac48e9bc513 --- /dev/null +++ b/src/servo/content/jsglobal.rs @@ -0,0 +1,69 @@ +// Definition for the global object that we use: + +import jsapi::*; +import jsapi::bindgen::*; +import ptr::null; + +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 { + JS_StrictPropertyStub(arg0, arg1, arg2, arg3, arg4) +} + +crust fn EnumerateStub(++arg0: *JSContext, ++arg1: *JSObject) -> JSBool { + JS_EnumerateStub(arg0, arg1) +} + +crust fn ResolveStub(++arg0: *JSContext, + ++arg1: *JSObject, + ++arg2: jsid) -> JSBool { + JS_ResolveStub(arg0, arg1, arg2) +} + +crust fn ConvertStub(++arg0: *JSContext, + ++arg1: *JSObject, + ++arg2: JSType, + ++arg3: *jsval) -> JSBool { + JS_ConvertStub(arg0, arg1, arg2, arg3) +} + +fn global_class() -> js::named_class { + let name = "global"; + let c_str = str::as_c_str(name) { |bytes| bytes }; + @{name: name, // in theory, this should *move* the str in here.. + jsclass: {name: c_str, // ...and so this ptr ought to be valid. + flags: 0x48000_u32, + addProperty: PropertyStub, + delProperty: PropertyStub, + getProperty: PropertyStub, + setProperty: StrictPropertyStub, + enumerate: EnumerateStub, + resolve: ResolveStub, + convert: ConvertStub, + finalize: null(), + reserved0: null(), + checkAccess: null(), + call: null(), + construct: null(), + xdrObject: null(), + hasInstance: null(), + trace: null(), + reserved1: 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 +} \ No newline at end of file diff --git a/src/servo/engine.rs b/src/servo/engine.rs index c20131797f4..ff6a2846825 100644 --- a/src/servo/engine.rs +++ b/src/servo/engine.rs @@ -19,7 +19,13 @@ fn engine(sink: S) -> comm::chan { loop { alt self_ch.recv() { - load_url(url) { content.send(content::parse(url)) } + load_url(url) { + if url.ends_with(".js") { + content.send(content::execute(url)) + } else { + content.send(content::parse(url)) + } + } exit(sender) { content.send(content::exit); layout.send(layout::layout::exit); diff --git a/src/servo/servo.rc b/src/servo/servo.rc index d11ec3989ca..3f41a5ce0df 100755 --- a/src/servo/servo.rc +++ b/src/servo/servo.rc @@ -12,6 +12,8 @@ use azure; use js; use harfbuzz; +import js::jsapi; + mod dom { mod base; mod rcu; @@ -57,6 +59,10 @@ mod util { mod tree; } -mod content; +mod content { + mod js; + mod jsglobal; +} + mod opts; mod engine;