Skip to content

Commit

Permalink
Add a window object with an alert method
Browse files Browse the repository at this point in the history
test/test-js-alert.html tests use of the alert method, which currently
just prints to the console.
  • Loading branch information
catamorphism committed Aug 21, 2012
1 parent 82c9f9b commit 5079e10
Show file tree
Hide file tree
Showing 9 changed files with 172 additions and 41 deletions.
2 changes: 1 addition & 1 deletion src/rust-mozjs
Submodule rust-mozjs updated 2 files
+9 −4 global.rs
+10 −3 rust.rs
15 changes: 10 additions & 5 deletions src/servo/content/content_task.rs
Expand Up @@ -13,7 +13,7 @@ import task::{spawn, spawn_listener};
import io::{read_whole_file, println};
import result::{ok, err};

import dom::base::{Document, Node, NodeScope, define_bindings};
import dom::base::{Document, Node, NodeScope, Window, define_bindings};
import dom::event::{Event, ResizeEvent};
import dom::style;
import dom::style::Stylesheet;
Expand Down Expand Up @@ -80,6 +80,7 @@ struct Content<C:Compositor> {
let jsrt: jsrt;

let mut document: option<@Document>;
let mut window: option<@Window>;
let mut doc_url: option<url>;

let resource_task: ResourceTask;
Expand All @@ -95,7 +96,8 @@ struct Content<C:Compositor> {
self.jsrt = jsrt();

self.document = none;
self.doc_url = none;
self.window = none;
self.doc_url = none;

self.compositor.add_event_listener(self.event_port.chan());

Expand Down Expand Up @@ -129,13 +131,15 @@ struct Content<C:Compositor> {
let js_scripts = js_port.recv();

// Apply the css rules to the dom tree:
#debug["%?", css_rules];
#debug["css_rules: %?", css_rules];

#debug["%?", js_scripts];
#debug["js_scripts: %?", js_scripts];

let document = Document(root, css_rules);
let window = Window(root);
self.relayout(document, &url);
self.document = some(@document);
self.window = some(@window);
self.doc_url = some(copy url);

//XXXjdm it was easier to duplicate the relevant ExecuteMsg code;
Expand All @@ -146,7 +150,8 @@ struct Content<C:Compositor> {
cx.set_logging_error_reporter();
cx.new_compartment(global_class).chain(|compartment| {
compartment.define_functions(debug_fns);
define_bindings(*compartment, option::get(self.document));
define_bindings(*compartment, option::get(self.document),
option::get(self.window));
cx.evaluate_script(compartment.global_obj, bytes, ~"???", 1u)
});
}
Expand Down
11 changes: 10 additions & 1 deletion src/servo/dom/base.rs
Expand Up @@ -15,6 +15,13 @@ import bindings;
import std::arc::arc;
import style::Stylesheet;

struct Window {
let root: Node;
new(root: Node) {
self.root = root;
}
}

struct Document {
let root: Node;
let css_rules: arc<Stylesheet>;
Expand Down Expand Up @@ -69,7 +76,9 @@ struct Attr {
}
}

fn define_bindings(compartment: bare_compartment, doc: @Document) {
fn define_bindings(compartment: bare_compartment, doc: @Document,
win: @Window) {
bindings::window::init(compartment, win);
bindings::document::init(compartment, doc);
bindings::node::init(compartment);
}
Expand Down
46 changes: 13 additions & 33 deletions src/servo/dom/bindings/document.rs
@@ -1,4 +1,4 @@
import js::rust::{bare_compartment, methods};
import js::rust::{compartment, bare_compartment, methods, jsobj};
import js::{JS_ARGV, JSCLASS_HAS_RESERVED_SLOTS, JSPROP_ENUMERATE, JSPROP_SHARED, JSVAL_NULL, JS_THIS_OBJECT,
JS_SET_RVAL};
import js::jsapi::{JSContext, jsval, JSObject, JSBool, jsid, JSClass, JSFreeOp};
Expand All @@ -10,9 +10,10 @@ import js::crust::{JS_PropertyStub, JS_StrictPropertyStub, JS_EnumerateStub, JS_
import result::{result, ok, err};
import ptr::null;
import libc::c_uint;
import utils::{DOMString, domstring_to_jsval, rust_box, squirrel_away, str};
import utils::{DOMString, domstring_to_jsval, rust_box, squirrel_away, str,
Document_class};
import bindings::node::create;
import base::Document;
import base::{Document, Node};

enum DOMException {
INVALID_CHARACTER_ERR
Expand Down Expand Up @@ -59,6 +60,8 @@ enum Element = int;
return 1;
}*/

// Unfortunately duplicated in document and window.
// Generalizing it triggers a trans bug
extern fn getDocumentElement(cx: *JSContext, obj: *JSObject, _id: jsid, rval: *mut jsval) -> JSBool unsafe {
let node = (*unwrap(obj)).payload.root;
*rval = RUST_OBJECT_TO_JSVAL(node::create(cx, node).ptr);
Expand All @@ -80,7 +83,7 @@ extern fn finalize(_fop: *JSFreeOp, obj: *JSObject) {
}

fn init(compartment: bare_compartment, doc: @Document) {
fn DocumentProto_class(compartment: bare_compartment) -> JSClass {
fn DocumentProto_class(compartment: bare_compartment) -> JSClass {
{name: compartment.add_name(~"DOMDocumentPrototype"),
flags: 0,
addProperty: JS_PropertyStub,
Expand All @@ -106,39 +109,16 @@ fn init(compartment: bare_compartment, doc: @Document) {
null(), null(), null(), null(), null())} // 40
};

fn Document_class(compartment: bare_compartment) -> JSClass {
{name: compartment.add_name(~"DOMDocument"),
flags: JSCLASS_HAS_RESERVED_SLOTS(1),
addProperty: JS_PropertyStub,
delProperty: JS_PropertyStub,
getProperty: JS_PropertyStub,
setProperty: JS_StrictPropertyStub,
enumerate: JS_EnumerateStub,
resolve: JS_ResolveStub,
convert: JS_ConvertStub,
finalize: finalize,
checkAccess: null(),
call: null(),
construct: null(),
hasInstance: utils::has_instance,
trace: 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
};

compartment.register_class(DocumentProto_class);
compartment.register_class(Document_class);
compartment.register_class(|c| Document_class(c, ~"DOMDocument",
finalize));

//TODO error checking
let obj = result::unwrap(
compartment.new_object(~"DOMDocumentPrototype", null(),
compartment.global_obj.ptr));
compartment.new_object(~"DOMDocumentPrototype",
null(),
compartment.global_obj.ptr));

/*let methods = ~[
{name: compartment.add_name("getDocumentURI"),
call: getDocumentURI,
Expand Down
32 changes: 31 additions & 1 deletion src/servo/dom/bindings/utils.rs
@@ -1,4 +1,4 @@
import js::rust::{compartment, bare_compartment};
import js::rust::{compartment, bare_compartment, methods};
import js::{JS_ARGV, JSCLASS_HAS_RESERVED_SLOTS, JSPROP_ENUMERATE, JSPROP_SHARED, JSVAL_NULL,
JS_THIS_OBJECT, JS_SET_RVAL};
import js::jsapi::{JSContext, jsval, JSObject, JSBool, jsid, JSClass, JSFreeOp};
Expand All @@ -7,7 +7,10 @@ import js::jsapi::bindgen::{JS_ValueToString, JS_GetStringCharsZAndLength, JS_Re
JS_DefineFunctions, JS_DefineProperty, JS_GetContextPrivate,
JS_GetClass, JS_GetPrototype};
import js::glue::bindgen::*;
import ptr::null;
import result::{result, ok, err};
import js::crust::{JS_PropertyStub, JS_StrictPropertyStub, JS_EnumerateStub,
JS_ResolveStub, JS_ConvertStub};

enum DOMString {
str(~str),
Expand Down Expand Up @@ -91,3 +94,30 @@ extern fn has_instance(_cx: *JSContext, obj: *JSObject, v: *jsval, bp: *mut JSBo
}
return 1;
}

fn Document_class(compartment: bare_compartment, name: ~str,
finalize: *u8) -> JSClass {
{name: compartment.add_name(name),
flags: JSCLASS_HAS_RESERVED_SLOTS(1),
addProperty: JS_PropertyStub,
delProperty: JS_PropertyStub,
getProperty: JS_PropertyStub,
setProperty: JS_StrictPropertyStub,
enumerate: JS_EnumerateStub,
resolve: JS_ResolveStub,
convert: JS_ConvertStub,
finalize: finalize,
checkAccess: null(),
call: null(),
construct: null(),
hasInstance: null(),
trace: 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
}
97 changes: 97 additions & 0 deletions src/servo/dom/bindings/window.rs
@@ -0,0 +1,97 @@
import js::rust::{bare_compartment, methods};
import js::{JS_ARGV, JSCLASS_HAS_RESERVED_SLOTS, JSPROP_ENUMERATE, JSPROP_SHARED, JSVAL_NULL, JS_THIS_OBJECT,
JS_SET_RVAL};
import js::jsapi::{JSContext, jsval, JSObject, JSBool, jsid, JSClass, JSFreeOp};
import js::jsapi::bindgen::{JS_ValueToString, JS_GetStringCharsZAndLength, JS_ReportError,
JS_GetReservedSlot, JS_SetReservedSlot, JS_NewStringCopyN,
JS_DefineFunctions, JS_DefineProperty, JS_DefineProperties, JS_EncodeString, JS_free};
import js::glue::bindgen::*;
import js::global::jsval_to_rust_str;
import js::crust::{JS_PropertyStub, JS_StrictPropertyStub, JS_EnumerateStub, JS_ConvertStub, JS_ResolveStub};
import result::{result, ok, err};
import ptr::null;
import libc::c_uint;
import utils::{DOMString, domstring_to_jsval, rust_box, squirrel_away, str,
Document_class};
import bindings::node::create;
import base::{Node, Window};

enum DOMException {
INVALID_CHARACTER_ERR
}

enum Element = int;

extern fn alert(cx: *JSContext, argc: c_uint, vp: *jsval) -> JSBool {
unsafe {
let argv = JS_ARGV(cx, vp);
assert (argc == 1);
// Abstract this pattern and use it in debug, too?
let jsstr = JS_ValueToString(cx, *ptr::offset(argv, 0));
// Right now, just print to the console
io::println(#fmt("ALERT: %s", jsval_to_rust_str(cx, jsstr)));
JS_SET_RVAL(cx, vp, JSVAL_NULL);
}
1_i32
}

// Unfortunately duplicated in document and window.
// Generalizing it triggers a trans bug
extern fn getDocumentElement(cx: *JSContext, obj: *JSObject,
_id: jsid, rval: *mut jsval) -> JSBool unsafe {
let node = (*unwrap(obj)).payload.root;
*rval = RUST_OBJECT_TO_JSVAL(node::create(cx, node).ptr);
return 1;
}

unsafe fn unwrap(obj: *JSObject) -> *rust_box<Window> {
let val = JS_GetReservedSlot(obj, 0);
unsafe::reinterpret_cast(RUST_JSVAL_TO_PRIVATE(val))
}

extern fn finalize(_fop: *JSFreeOp, obj: *JSObject) {
#debug("finalize!");
unsafe {
let val = JS_GetReservedSlot(obj, 0);
let _: @Window = unsafe::reinterpret_cast(RUST_JSVAL_TO_PRIVATE(val));
}
}

fn init(compartment: bare_compartment, win: @Window) {

compartment.register_class(|c| Document_class(c, ~"DOMWindow",
finalize));

let obj = result::unwrap(
compartment.new_object(~"DOMWindow", null(), null()));

/* Define methods on a window */
let methods = ~[{name: compartment.add_name(~"alert"),
call: alert,
nargs: 1,
flags: 0}];

vec::as_buf(methods, |fns, _len| {
JS_DefineFunctions(compartment.cx.ptr, obj.ptr, fns);
});

let attrs = @~[
{name: compartment.add_name(~"DOMWindow"),
tinyid: 0, // ???
flags: 0,
getter: getDocumentElement,
setter: null()}];
vec::push(compartment.global_props, attrs);
vec::as_buf(*attrs, |specs, _len| {
JS_DefineProperties(compartment.cx.ptr, obj.ptr, specs);
});

unsafe {
let raw_ptr: *libc::c_void = unsafe::reinterpret_cast(squirrel_away(win));
JS_SetReservedSlot(obj.ptr, 0, RUST_PRIVATE_TO_JSVAL(raw_ptr));
}

compartment.define_property(~"window", RUST_OBJECT_TO_JSVAL(obj.ptr),
JS_PropertyStub, JS_StrictPropertyStub,
JSPROP_ENUMERATE);
}
1 change: 1 addition & 0 deletions src/servo/servo.rc
Expand Up @@ -28,6 +28,7 @@ mod dom {
mod document;
mod utils;
mod node;
mod window;
}
}

Expand Down
8 changes: 8 additions & 0 deletions src/test/test-alert.js
@@ -0,0 +1,8 @@
function output (text)
{
window.alert(text);
}

output("Opossums have pouches like kangaroos");


1 change: 1 addition & 0 deletions src/test/test-js-alert.html
@@ -0,0 +1 @@
<script src="test-alert.js"></script>

0 comments on commit 5079e10

Please sign in to comment.