Upgrade to latest Rust.

This commit is contained in:
Jack Moffitt 2013-12-20 22:04:46 -07:00
parent 728fb9a7de
commit a7ef1cd35e
127 changed files with 1892 additions and 2501 deletions

View file

@ -14,15 +14,15 @@ use dom::event::Event;
use dom::eventtarget::AbstractEventTarget;
use dom::htmldocument::HTMLDocument;
use dom::namespace::Null;
use dom::node::{AbstractNode, LayoutDataRef};
use dom::window::{TimerData, Window};
use dom::node::AbstractNode;
use dom::window::{TimerData, TimerHandle, Window};
use html::hubbub_html_parser::HtmlParserResult;
use html::hubbub_html_parser::{HtmlDiscoveredStyle, HtmlDiscoveredIFrame, HtmlDiscoveredScript};
use html::hubbub_html_parser;
use layout_interface::{AddStylesheetMsg, DocumentDamage};
use layout_interface::{ContentBoxQuery, ContentBoxResponse};
use layout_interface::{DocumentDamageLevel, HitTestQuery, HitTestResponse, LayoutQuery};
use layout_interface::{LayoutChan, MatchSelectorsDocumentDamage, QueryMsg, ReapLayoutDataMsg};
use layout_interface::{LayoutChan, MatchSelectorsDocumentDamage, QueryMsg};
use layout_interface::{Reflow, ReflowDocumentDamage, ReflowForDisplay, ReflowGoal, ReflowMsg};
use layout_interface::ContentChangedDocumentDamage;
use layout_interface;
@ -46,12 +46,9 @@ use servo_net::image_cache_task::ImageCacheTask;
use servo_net::resource_task::ResourceTask;
use servo_util::geometry::to_frac_px;
use servo_util::url::make_url;
use std::cell::Cell;
use std::comm::{Port, SharedChan};
use std::comm;
use std::ptr;
use std::str::eq_slice;
use std::task::{spawn_sched, SingleThreaded};
use std::util::replace;
/// Messages used to control the script task.
@ -90,8 +87,9 @@ pub struct ScriptChan(SharedChan<ScriptMsg>);
impl ScriptChan {
/// Creates a new script chan.
pub fn new(chan: Chan<ScriptMsg>) -> ScriptChan {
ScriptChan(SharedChan::new(chan))
pub fn new() -> (Port<ScriptMsg>, ScriptChan) {
let (port, chan) = SharedChan::new();
(port, ScriptChan(chan))
}
}
@ -140,8 +138,8 @@ pub struct PageTree {
inner: ~[PageTree],
}
pub struct PageTreeIterator<'self> {
priv stack: ~[&'self mut PageTree],
pub struct PageTreeIterator<'a> {
priv stack: ~[&'a mut PageTree],
}
impl PageTree {
@ -203,7 +201,7 @@ impl PageTree {
}
}
impl<'self> Iterator<@mut Page> for PageTreeIterator<'self> {
impl<'a> Iterator<@mut Page> for PageTreeIterator<'a> {
fn next(&mut self) -> Option<@mut Page> {
if !self.stack.is_empty() {
let next = self.stack.pop();
@ -254,12 +252,14 @@ impl Page {
let join_port = replace(&mut self.layout_join_port, None);
match join_port {
Some(ref join_port) => {
if !join_port.peek() {
info!("script: waiting on layout");
match join_port.try_recv() {
None => {
info!("script: waiting on layout");
join_port.recv();
}
Some(_) => {}
}
join_port.recv();
debug!("script: layout joined")
}
None => fail!(~"reader forked but no join port?"),
@ -307,7 +307,7 @@ impl Page {
compositor.set_ready_state(PerformingLayout);
// Layout will let us know when it's done.
let (join_port, join_chan) = comm::stream();
let (join_port, join_chan) = Chan::new();
self.layout_join_port = Some(join_port);
self.last_reflow_id += 1;
@ -359,11 +359,6 @@ impl Page {
js_context: js_context,
});
}
/// Sends the given layout data back to the layout task to be destroyed.
pub unsafe fn reap_dead_layout_data(&self, layout_data: LayoutDataRef) {
self.layout_chan.send(ReapLayoutDataMsg(layout_data))
}
}
/// Information for one frame in the browsing context.
@ -412,7 +407,6 @@ pub struct ScriptTask {
}
/// Returns the relevant page from the associated JS Context.
#[fixed_stack_segment]
pub fn page_from_context(js_context: *JSContext) -> *mut Page {
unsafe {
JS_GetContextPrivate(js_context) as *mut Page
@ -468,24 +462,7 @@ impl ScriptTask {
resource_task: ResourceTask,
image_cache_task: ImageCacheTask,
window_size: Size2D<uint>) {
let parms = Cell::new((compositor,
layout_chan,
port,
chan,
constellation_chan,
resource_task,
image_cache_task));
// Since SpiderMonkey is blocking it needs to run in its own thread.
// If we don't do this then we'll just end up with a bunch of SpiderMonkeys
// starving all the other tasks.
do spawn_sched(SingleThreaded) {
let (compositor,
layout_chan,
port,
chan,
constellation_chan,
resource_task,
image_cache_task) = parms.take();
spawn(proc() {
let script_task = ScriptTask::new(id,
@compositor as @ScriptListener,
layout_chan,
@ -496,7 +473,7 @@ impl ScriptTask {
image_cache_task,
window_size);
script_task.start();
}
});
}
/// Handle incoming control messages.
@ -520,12 +497,13 @@ impl ScriptTask {
// Store new resizes, and gather all other events.
let mut sequential = ~[];
// Receive at least one message so we don't spinloop.
let mut event = self.port.recv();
loop {
// Receive at least one message so we don't spinloop.
let event = self.port.recv();
match event {
ResizeMsg(id, size) => {
debug!("script got resize message");
let page = self.page_tree.find(id).expect("resize sent to nonexistent pipeline").page;
page.resize_event = Some(size);
}
@ -534,9 +512,9 @@ impl ScriptTask {
}
}
// Break if there are no more messages.
if !self.port.peek() {
break;
match self.port.try_recv() {
None => break,
Some(ev) => event = ev,
}
}
@ -556,7 +534,7 @@ impl ScriptTask {
self.handle_exit_window_msg(id);
return false
},
ResizeMsg(*) => fail!("should have handled ResizeMsg already"),
ResizeMsg(..) => fail!("should have handled ResizeMsg already"),
}
}
@ -579,14 +557,14 @@ impl ScriptTask {
}
/// Handles a timer that fired.
#[fixed_stack_segment]
fn handle_fire_timer_msg(&mut self, id: PipelineId, timer_data: ~TimerData) {
let page = self.page_tree.find(id).expect("ScriptTask: received fire timer msg for a
pipeline ID not associated with this script task. This is a bug.").page;
let window = page.frame.expect("ScriptTask: Expect a timeout to have a document").window;
if !window.active_timers.contains(&timer_data.handle) {
if !window.active_timers.contains(&TimerHandle { handle: timer_data.handle, cancel_chan: None }) {
return;
}
window.active_timers.remove(&TimerHandle { handle: timer_data.handle, cancel_chan: None });
unsafe {
let this_value = if timer_data.args.len() > 0 {
RUST_JSVAL_TO_OBJECT(timer_data.args[0])
@ -711,7 +689,6 @@ impl ScriptTask {
//
// Note: We can parse the next document in parallel with any previous documents.
let document = HTMLDocument::new(window);
let html_parsing_result = hubbub_html_parser::parse_html(cx.ptr,
document,
url.clone(),
@ -736,7 +713,7 @@ impl ScriptTask {
let mut js_scripts = None;
loop {
match discovery_port.try_recv() {
match discovery_port.recv_opt() {
Some(HtmlDiscoveredScript(scripts)) => {
assert!(js_scripts.is_none());
js_scripts = Some(scripts);
@ -805,20 +782,20 @@ impl ScriptTask {
None => {
let doc_node = AbstractNode::from_document(document);
let mut anchors = doc_node.traverse_preorder().filter(|node| node.is_anchor_element());
do anchors.find |node| {
do node.with_imm_element |elem| {
anchors.find(|node| {
node.with_imm_element(|elem| {
match elem.get_attr(Null, "name") {
Some(name) => eq_slice(name, fragid),
None => false
}
}
}
})
})
}
}
}
fn scroll_fragment_point(&self, pipeline_id: PipelineId, page: &mut Page, node: AbstractNode) {
let (port, chan) = comm::stream();
let (port, chan) = Chan::new();
match page.query_layout(ContentBoxQuery(node, chan), port) {
ContentBoxResponse(rect) => {
let point = Point2D(to_frac_px(rect.origin.x).to_f32().unwrap(),
@ -870,7 +847,7 @@ impl ScriptTask {
if root.is_none() {
return;
}
let (port, chan) = comm::stream();
let (port, chan) = Chan::new();
match page.query_layout(HitTestQuery(root.unwrap(), point, chan), port) {
Ok(node) => match node {
HitTestResponse(node) => {
@ -886,11 +863,11 @@ impl ScriptTask {
}
}
if node.is_element() {
do node.with_imm_element |element| {
node.with_imm_element(|element| {
if "a" == element.tag_name {
self.load_url_from_element(page, element)
}
}
})
}
}
},
@ -899,8 +876,8 @@ impl ScriptTask {
}
}
}
MouseDownEvent(*) => {}
MouseUpEvent(*) => {}
MouseDownEvent(..) => {}
MouseUpEvent(..) => {}
}
}
@ -910,9 +887,9 @@ impl ScriptTask {
for href in attr.iter() {
debug!("ScriptTask: clicked on link to {:s}", *href);
let click_frag = href.starts_with("#");
let current_url = do page.url.as_ref().map |&(ref url, _)| {
let current_url = page.url.as_ref().map(|&(ref url, _)| {
url.clone()
};
});
debug!("ScriptTask: current url is {:?}", current_url);
let url = make_url(href.to_owned(), current_url);
@ -933,29 +910,15 @@ fn shut_down_layout(page: @mut Page) {
page.join_layout();
// Tell the layout task to begin shutting down.
let (response_port, response_chan) = comm::stream();
let (response_port, response_chan) = Chan::new();
page.layout_chan.send(layout_interface::PrepareToExitMsg(response_chan));
response_port.recv();
// Destroy all nodes.
//
// If there was a leak, the layout task will soon crash safely when it detects that local data
// is missing from its heap.
//
// FIXME(pcwalton): *But*, for now, because we use `@mut` boxes to hold onto Nodes, if this
// didn't destroy all the nodes there will be an *exploitable* security vulnerability as the
// nodes try to access the destroyed JS context. We need to change this so that the only actor
// who can judge a JS object dead (and thus run its drop glue) is the JS engine itself; thus it
// will be impossible (absent a serious flaw in the JS engine) for the JS context to be dead
// before nodes are.
unsafe {
let document_node = AbstractNode::from_document(page.frame.as_ref().unwrap().document);
for node in document_node.traverse_preorder() {
node.mut_node().reap_layout_data()
}
}
// Destroy all nodes. Setting frame and js_info to None will trigger our
// compartment to shutdown, run GC, etc.
page.frame = None;
page.js_info = None;
// Destroy the layout task. If there were node leaks, layout will now crash safely.
page.layout_chan.send(layout_interface::ExitNowMsg);
}