servo: integrate spidermonkey (it doesn't do anything yet)
authorNiko Matsakis <niko@alum.mit.edu>
Thu, 10 May 2012 16:23:13 -0700
changeset 361579 282e4a04ba9ac003cdff27f3b9a3a57214d16c05
parent 361578 9b97bbe736d4b743b100cdcb09fd353e0cbb56d6
child 361580 e09852ff661940ac1707c089bd43633ee11d2acd
push id10863
push userjlorenzo@mozilla.com
push dateMon, 06 Mar 2017 23:02:23 +0000
treeherdermozilla-aurora@0931190cd725 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
servo: integrate spidermonkey (it doesn't do anything yet) Source-Repo: https://github.com/servo/servo Source-Revision: 6d27ee5e0e4d1f3d7e02a1700df1ef3cb0731221
servo/src/etc/jsdefine
servo/src/servo/content.rs
servo/src/servo/content/js.rs
servo/src/servo/content/jsglobal.rs
servo/src/servo/engine.rs
servo/src/servo/servo.rc
new file mode 100755
--- /dev/null
+++ b/servo/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
--- a/servo/src/servo/content.rs
+++ b/servo/src/servo/content.rs
@@ -1,17 +1,19 @@
 export msg, ping;
 export content;
 
 import dom::rcu::writer_methods;
 import dom=dom::base;
 import layout::layout;
+import js::methods;
 
 enum msg {
     parse(str),
+    execute(str),
     exit
 }
 
 enum ping {
     pong
 }
 
 // sends a ping to layout and awaits the response.
@@ -24,20 +26,21 @@ fn join_layout(scope: dom::node_scope,
         }
         scope.reader_joined();
     }
 }
 
 fn content(to_layout: chan<layout::msg>) -> chan<msg> {
     task::spawn_listener::<msg> {|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.
                 let stream = html::spawn_parser_task(filename);
                 let root = parser::html_builder::build_dom(scope, stream);
 
                 // Now, join the layout so that they will see the latest
                 // changes we have made.
@@ -45,16 +48,22 @@ fn content(to_layout: chan<layout::msg>)
 
                 // Send new document to layout.
                 to_layout.send(layout::build(root));
 
                 // Indicate that reader was forked so any further
                 // 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;
               }
             }
         }
     }
 }
new file mode 100644
--- /dev/null
+++ b/servo/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<jsobj,()> {
+        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));
+}
+
new file mode 100644
--- /dev/null
+++ b/servo/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
--- a/servo/src/servo/engine.rs
+++ b/servo/src/servo/engine.rs
@@ -14,17 +14,23 @@ fn engine<S: renderer::sink send>(sink: 
         // The layout task
         let layout = layout::layout::layout(renderer);
 
         // The content task
         let content = content::content(layout);
 
         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);
                 listen {|resp_ch|
                     renderer.send(renderer::exit(resp_ch));
                     resp_ch.recv();
                 }
                 sender.send(());
--- a/servo/src/servo/servo.rc
+++ b/servo/src/servo/servo.rc
@@ -7,16 +7,18 @@
 #[license = "MPL"];
 
 use std;
 use sdl;
 use azure;
 use js;
 use harfbuzz;
 
+import js::jsapi;
+
 mod dom {
     mod base;
     mod rcu;
 }
 
 mod gfx {
     mod geom;
     mod surface;
@@ -52,11 +54,15 @@ mod platform {
     mod base;
     mod osmain;
 }
 
 mod util {
     mod tree;
 }
 
-mod content;
+mod content {
+    mod js;
+    mod jsglobal;
+}
+
 mod opts;
 mod engine;