servo: move JS stuff out of servo into mozjs; redefine geom types to

make use of inherited mutability

Source-Repo: https://github.com/servo/servo
Source-Revision: 902f81ca3fd37d0e739c79a55cfe21746f9e3178
This commit is contained in:
Niko Matsakis 2012-05-31 12:40:49 -07:00
Родитель 11bc38de9a
Коммит 4b39cef9ee
16 изменённых файлов: 54 добавлений и 368 удалений

Просмотреть файл

@ -5,7 +5,7 @@ import result::extensions;
import dom::rcu::writer_methods;
import dom=dom::base;
import layout::layout;
import js::methods;
import js::rust::methods;
enum msg {
parse(str),
@ -32,7 +32,7 @@ fn join_layout(scope: dom::node_scope,
fn content(to_layout: chan<layout::msg>) -> chan<msg> {
task::spawn_listener::<msg> {|from_master|
let scope = dom::node_scope();
let rt = js::rt();
let rt = js::rust::rt();
loop {
alt from_master.recv() {
parse(filename) {
@ -65,8 +65,8 @@ fn content(to_layout: chan<layout::msg>) -> chan<msg> {
let cx = rt.cx();
cx.set_default_options_and_version();
cx.set_logging_error_reporter();
cx.new_compartment(jsglobal::global_class).chain { |comp|
comp.define_functions(jsglobal::global_fns);
cx.new_compartment(js::global::global_class).chain { |comp|
comp.define_functions(js::global::debug_fns);
cx.evaluate_script(comp.global_obj, bytes, filename, 1u)
};
}

Просмотреть файл

@ -1,185 +0,0 @@
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;
export cx;
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_functions = @{
names: [str],
funcs: [JSFunctionSpec]
};
// ___________________________________________________________________________
// 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),
rt: self})
}
}
// ___________________________________________________________________________
// contexts
type cx = @cx_rsrc;
resource cx_rsrc(self: {ptr: *JSContext, rt: rt}) {
JS_DestroyContext(self.ptr);
}
impl methods for cx {
fn rooted_obj(obj: *JSObject) -> jsobj {
let jsobj = @jsobj_rsrc({cx: self, cxptr: self.ptr, ptr: obj});
JS_AddObjectRoot(self.ptr, ptr::addr_of(jsobj.ptr));
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_logging_error_reporter() {
JS_SetErrorReporter(self.ptr, reportError);
}
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);
let globobj =
JS_NewCompartmentAndGlobalObject(
self.ptr,
&*globcls as *JSClass,
null());
result(JS_InitStandardClasses(self.ptr, globobj)).chain { |_ok|
ok(@{cx: self,
name_pool: np,
global_class: globcls,
mut global_funcs: [],
global_obj: self.rooted_obj(globobj)})
}
}
fn evaluate_script(glob: jsobj, bytes: [u8], filename: str,
line_num: uint) -> result<(),()> {
vec::as_buf(bytes) { |bytes_ptr|
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 with bytes %?", filename, bytes];
if JS_EvaluateScript(self.ptr, glob.ptr,
bytes_ptr, bytes.len() as uintN,
filename_cstr, line_num as uintN,
ptr::addr_of(v)) == ERR {
#debug["...err!"];
err(())
} else {
// we could return the script result but then we'd have
// to root it and so forth and, really, who cares?
#debug["...ok!"];
ok(())
}
}
}
}
}
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];
}
}
// ___________________________________________________________________________
// 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
type jsobj = @jsobj_rsrc;
resource jsobj_rsrc(self: {cx: cx, cxptr: *JSContext, ptr: *JSObject}) {
JS_RemoveObjectRoot(self.cxptr, ptr::addr_of(self.ptr));
}
#[cfg(test)]
mod test {
#[test]
fn dummy() {
let rt = rt();
let cx = rt.cx();
cx.set_default_options_and_version();
cx.set_logging_error_reporter();
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)
};
}
}

Просмотреть файл

@ -1,90 +0,0 @@
// Definition for the global object that we use:
import spidermonkey::*;
import spidermonkey::jsapi::*;
import spidermonkey::jsapi::bindgen::*;
import ptr::null;
import jsutil::*;
import name_pool::{name_pool, methods};
// 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 {
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(np: name_pool) -> JSClass {
{name: np.add("global"),
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
}
crust fn debug(cx: *JSContext, argc: uintN, vp: *jsval) -> JSBool {
import io::writer_util;
#debug["debug() called with %? arguments", argc];
unsafe {
let argv = JS_ARGV(cx, vp);
for 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));
#debug["%s", str];
}
JS_SET_RVAL(cx, vp, JSVAL_NULL);
ret 1_i32;
}
}
fn global_fns(np: name_pool) -> [JSFunctionSpec] {
[{name: np.add("debug"),
call: debug,
nargs: 0_u16,
flags: 0_u16}]
}

Просмотреть файл

@ -1,27 +0,0 @@
import spidermonkey::jsapi::{JSContext, jsval};
impl methods<T: copy> for *T {
unsafe fn +(idx: uint) -> *T {
ptr::offset(self, idx)
}
unsafe fn [](idx: uint) -> T {
*(self + idx)
}
}
const JSVAL_VOID: u64 = 0x0001fff2_00000000_u64;
const JSVAL_NULL: u64 = 0x0001fff6_00000000_u64;
const JSVAL_ZERO: u64 = 0x0001fff1_00000000_u64;
const JSVAL_ONE: u64 = 0x0001fff1_00000001_u64;
const JSVAL_FALSE: u64 = 0x0001fff3_00000000_u64;
const JSVAL_TRUE: u64 = 0x0001fff3_00000001_u64;
unsafe fn JS_ARGV(_cx: *JSContext, vp: *jsval) -> *jsval {
vp + 2u
}
unsafe fn JS_SET_RVAL(_cx: *JSContext, vp: *jsval, v: jsval) {
let vp: *mut jsval = unsafe::reinterpret_cast(vp);
*vp = v;
}

Просмотреть файл

@ -1,17 +0,0 @@
import libc::c_char;
type name_pool = @{
mut strbufs: [str]
};
fn name_pool() -> name_pool {
@{mut strbufs: []}
}
impl methods for name_pool {
fn add(-s: str) -> *c_char {
let c_str = str::as_c_str(s) { |bytes| bytes };
self.strbufs += [s]; // in theory, this should *move* the str in here..
ret c_str; // ...and so this ptr ought to be valid.
}
}

Просмотреть файл

@ -50,7 +50,7 @@ class attr {
enum element_subclass {
es_unknown,
es_div,
es_img(size<au>),
es_img({mut size: size<au>}),
es_head
}

Просмотреть файл

@ -1,7 +1,6 @@
// FIXME--mut should be inherited
type point<A> = { mut x: A, mut y: A };
type size<A> = { mut width: A, mut height: A };
type rect<A> = { mut origin: point<A>, mut size: size<A> };
type point<A> = { x: A, y: A };
type size<A> = { width: A, height: A };
type rect<A> = { origin: point<A>, size: size<A> };
enum au = int;
@ -12,25 +11,25 @@ impl size for size<int> {
}
fn point<A:copy>(x: A, y: A) -> point<A> {
{mut x: x, mut y: y}
{x: x, y: y}
}
fn size<A:copy>(w: A, h: A) -> size<A> {
{mut width: w, mut height: h}
{width: w, height: h}
}
fn box<A:copy>(x: A, y: A, w: A, h: A) -> rect<A> {
{mut origin: point(x, y),
mut size: size(w, h)}
{origin: point(x, y),
size: size(w, h)}
}
fn zero_rect_au() -> rect<au> {
let z = au(0);
{mut origin: point(z, z), mut size: zero_size_au()}
{origin: point(z, z), size: zero_size_au()}
}
fn zero_size_au() -> size<au> {
{mut width: au(0), mut height: au(0)}
{width: au(0), height: au(0)}
}
fn px_to_au(i: int) -> au {

Просмотреть файл

@ -173,12 +173,13 @@ mod test {
fn do_layout() {
let s = scope();
let n0 = s.new_node(nk_element(element("img",
~es_img(size(au(10),au(10))))));
let n1 = s.new_node(nk_element(element("img",
~es_img(size(au(10),au(15))))));
let n2 = s.new_node(nk_element(element("img",
~es_img(size(au(10),au(20))))));
fn mk_img(size: size<au>) -> ~dom::base::element_subclass {
~es_img({mut size: size})
}
let n0 = s.new_node(nk_element(element("img", mk_img(size(au(10),au(10))))));
let n1 = s.new_node(nk_element(element("img", mk_img(size(au(10),au(10))))));
let n2 = s.new_node(nk_element(element("img", mk_img(size(au(10),au(20))))));
let n3 = s.new_node(nk_element(element("div", ~es_div)));
tree::add_child(s, n3, n0);

Просмотреть файл

@ -22,13 +22,13 @@ impl block_layout_methods for @box {
for tree::each_child(btree, self) {|c|
let mut blk_available_width = available_width;
// FIXME subtract borders, margins, etc
c.bounds.origin = {mut x: au(0), mut y: au(current_height)};
c.bounds.origin = {x: au(0), y: au(current_height)};
c.reflow(blk_available_width);
current_height += *c.bounds.size.height;
}
self.bounds.size = {mut width: available_width, // FIXME
mut height: au(current_height)};
self.bounds.size = {width: available_width, // FIXME
height: au(current_height)};
#debug["reflow_block size=%?", self.bounds];
}

Просмотреть файл

@ -153,9 +153,9 @@ impl box_builder_priv for node {
~nk_text(string) { bk_text(@text_box(string)) }
~nk_element(element) {
alt *element.subclass {
es_div { bk_block }
es_img(size) { bk_intrinsic(@copy size) }
es_unknown { bk_inline }
es_div { bk_block }
es_img({size}) { bk_intrinsic(@size) }
es_unknown { bk_inline }
}
}
}

Просмотреть файл

@ -19,15 +19,15 @@ impl inline_layout_methods for @box {
let mut current_height = 0;
for tree::each_child(btree, self) {
|kid|
kid.bounds.origin = { mut x: au(x), mut y: y };
kid.bounds.origin = { x: au(x), y: y };
kid.reflow(au(inline_available_width));
inline_available_width -= *kid.bounds.size.width;
x += *kid.bounds.size.width;
current_height = int::max(current_height, *kid.bounds.size.height);
}
self.bounds.size = { mut width: available_width,
mut height: au(current_height) };
self.bounds.size = { width: available_width,
height: au(current_height) };
#debug["reflow_inline size=%?", self.bounds];
}

Просмотреть файл

@ -27,14 +27,14 @@ impl text_layout_methods for @box {
run.shape();
self.bounds.size = {
mut width:
width:
alt vec::last_opt(run.glyphs.get()) {
some(glyph) {
au(*glyph.pos.offset.x + *glyph.pos.advance.x)
}
none { au(0) }
},
mut height: au(60 * 14)
height: au(60 * 14)
};
}
}

Просмотреть файл

@ -20,16 +20,16 @@ fn link_up_attribute(scope: dom::node_scope, node: dom::node, key: str,
dom::nk_element(element) {
element.attrs.push(~attr(key, value));
alt *element.subclass {
es_img(dimensions) if key == "width" {
es_img(img) if key == "width" {
alt int::from_str(value) {
none { /* drop on the floor */ }
some(s) { dimensions.width = geom::px_to_au(s); }
some(s) { img.size.width = geom::px_to_au(s); }
}
}
es_img(dimensions) if key == "height" {
es_img(img) if key == "height" {
alt int::from_str(value) {
none { /* drop on the floor */ }
some(s) { dimensions.height = geom::px_to_au(s); }
some(s) { img.size.height = geom::px_to_au(s); }
}
}
es_div | es_img(*) | es_head | es_unknown {
@ -48,10 +48,10 @@ fn build_element_subclass(tag_name: str) -> ~element_subclass {
alt tag_name {
"div" { ret ~es_div; }
"img" {
ret ~es_img({
mut width: geom::px_to_au(100),
mut height: geom::px_to_au(100)
});
ret ~es_img({mut size: {
width: geom::px_to_au(100),
height: geom::px_to_au(100)
}});
}
"head" { ret ~es_head; }
_ { ret ~es_unknown; }

Просмотреть файл

@ -9,7 +9,7 @@
use std;
use sdl;
use azure;
use spidermonkey (name = "js");
use js;
use harfbuzz;
use stb_image;
@ -65,13 +65,10 @@ mod text {
mod util {
mod tree;
mod unsafe;
}
mod content {
mod js;
mod jsglobal;
mod jsutil;
mod name_pool;
}
mod net {

Просмотреть файл

@ -7,12 +7,12 @@ class glyph_pos {
new(hb_pos: harfbuzz::hb_glyph_position_t) {
self.advance = {
mut x: px_to_au(hb_pos.x_advance as int),
mut y: px_to_au(hb_pos.y_advance as int)
x: px_to_au(hb_pos.x_advance as int),
y: px_to_au(hb_pos.y_advance as int)
};
self.offset = {
mut x: px_to_au(hb_pos.x_offset as int),
mut y: px_to_au(hb_pos.y_offset as int)
x: px_to_au(hb_pos.x_offset as int),
y: px_to_au(hb_pos.y_offset as int)
};
}
}

Просмотреть файл

@ -0,0 +1,8 @@
impl methods<T: copy> for *T {
unsafe fn +(idx: uint) -> *T {
ptr::offset(self, idx)
}
unsafe fn [](idx: uint) -> T {
*(self + idx)
}
}