Source-Repo: https://github.com/servo/servo
Source-Revision: 9b599e4e5ab4829d12d21e799b62f8a0962b8bf7
This commit is contained in:
Patrick Walton 2012-07-12 16:32:27 -07:00
Родитель 173ae430f3
Коммит acac40ea41
2 изменённых файлов: 107 добавлений и 63 удалений

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

@ -6,6 +6,7 @@
export Content;
export ControlMsg, ExecuteMsg, ParseMsg, ExitMsg;
export PingMsg, PongMsg;
export create_content;
import comm::{port, chan, listen, select2};
import task::{spawn, spawn_listener};
@ -13,7 +14,7 @@ import io::{read_whole_file, println};
import result::{ok, err};
import dom::base::NodeScope;
import dom::event::ResizeEvent;
import dom::event::{Event, ResizeEvent};
import dom::rcu::WriterMethods;
import dom::style;
import gfx::renderer::Sink;
@ -27,7 +28,7 @@ import jsrt = js::rust::rt;
import js::rust::methods;
import js::global::{global_class, debug_fns};
import either::{left, right};
import either::{either, left, right};
import result::extensions;
type Content = chan<ControlMsg>;
@ -55,70 +56,113 @@ fn join_layout(scope: NodeScope, layout: Layout) {
}
}
#[warn(no_non_implicitly_copyable_typarams)]
fn Content<S:Sink send copy>(layout: Layout, sink: S) -> Content {
spawn_listener::<ControlMsg>(|from_master| {
let event_port = port();
sink.add_event_listener(event_port.chan());
class Content<S:Sink send copy> {
let sink: S;
let layout: Layout;
let from_master: port<ControlMsg>;
let event_port: port<Event>;
let scope = NodeScope();
let rt = jsrt();
loop {
alt select2(from_master, event_port) {
left(ParseMsg(filename)) {
#debug["content: Received filename `%s` to parse", *filename];
let scope: NodeScope;
let jsrt: jsrt;
// Note: we can parse the next document in parallel
// with any previous documents.
let stream = spawn_html_lexer_task(copy filename);
let (root, style_port) = build_dom(scope, stream);
// Collect the css stylesheet
let css_rules = style_port.recv();
// Apply the css rules to the dom tree:
#debug["%?", css_rules];
new(layout: Layout, sink: S, from_master: port<ControlMsg>) {
self.layout = layout;
self.sink = sink;
self.from_master = from_master;
self.event_port = port();
// Now, join the layout so that they will see the latest
// changes we have made.
join_layout(scope, layout);
self.scope = NodeScope();
self.jsrt = jsrt();
// Send new document and relevant styles to layout
layout.send(BuildMsg(root, css_rules));
self.sink.add_event_listener(self.event_port.chan());
}
// Indicate that reader was forked so any further
// changes will be isolated.
scope.reader_forked();
}
fn start() {
while self.handle_msg(select2(self.from_master, self.event_port)) {
// Go on...
}
}
left(ExecuteMsg(filename)) {
#debug["content: Received filename `%s` to execute", *filename];
alt read_whole_file(*filename) {
err(msg) {
println(#fmt["Error opening %s: %s", *filename, msg]);
}
ok(bytes) {
let cx = rt.cx();
cx.set_default_options_and_version();
cx.set_logging_error_reporter();
cx.new_compartment(global_class).chain(|compartment| {
compartment.define_functions(debug_fns);
cx.evaluate_script(compartment.global_obj, bytes, *filename, 1u)
});
}
}
}
left(ExitMsg) {
layout.send(layout_task::ExitMsg);
break;
}
right(ResizeEvent(new_width, new_height)) {
#debug("content got resize event: %d, %d", new_width, new_height);
}
fn handle_msg(msg: either<ControlMsg,Event>) -> bool {
alt msg {
left(control_msg) {
ret self.handle_control_msg(control_msg);
}
right(event) {
ret self.handle_event(event);
}
}
})
}
fn handle_control_msg(control_msg: ControlMsg) -> bool {
alt control_msg {
ParseMsg(filename) {
#debug["content: Received filename `%s` to parse", *filename];
// Note: we can parse the next document in parallel
// with any previous documents.
let stream = spawn_html_lexer_task(copy filename);
let (root, style_port) = build_dom(self.scope, stream);
// Collect the css stylesheet
let css_rules = style_port.recv();
// Apply the css rules to the dom tree:
#debug["%?", css_rules];
// Now, join the layout so that they will see the latest
// changes we have made.
join_layout(self.scope, self.layout);
// Send new document and relevant styles to layout
self.layout.send(BuildMsg(root, css_rules));
// Indicate that reader was forked so any further
// changes will be isolated.
self.scope.reader_forked();
ret true;
}
ExecuteMsg(filename) {
#debug["content: Received filename `%s` to execute", *filename];
alt read_whole_file(*filename) {
err(msg) {
println(#fmt["Error opening %s: %s", *filename, msg]);
}
ok(bytes) {
let cx = self.jsrt.cx();
cx.set_default_options_and_version();
cx.set_logging_error_reporter();
cx.new_compartment(global_class).chain(|compartment| {
compartment.define_functions(debug_fns);
cx.evaluate_script(compartment.global_obj, bytes, *filename, 1u)
});
}
}
ret true;
}
ExitMsg {
self.layout.send(layout_task::ExitMsg);
ret false;
}
}
}
fn handle_event(event: Event) -> bool {
alt event {
ResizeEvent(new_width, new_height) {
#debug("content got resize event: %d, %d", new_width, new_height);
ret true;
}
}
}
}
fn create_content<S: Sink send copy>(layout: Layout, sink: S) -> chan<ControlMsg> {
do spawn_listener::<ControlMsg> |from_master| {
Content(layout, sink, from_master).start();
}
}

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

@ -3,21 +3,21 @@ import task::spawn_listener;
import comm::chan;
import layout::layout_task;
import layout_task::Layout;
import content::{Content, ExecuteMsg, ParseMsg, ExitMsg};
import content::{Content, ExecuteMsg, ParseMsg, ExitMsg, create_content};
class Engine<S:Sink send copy> {
let sink: S;
let renderer: Renderer;
let layout: Layout;
let content: Content;
let content: chan<content::ControlMsg>;
new(sink: S) {
self.sink = sink;
let renderer = Renderer(sink);
let layout = Layout(renderer);
let content = Content(layout, sink);
let content = create_content(layout, sink);
self.renderer = renderer;
self.layout = layout;