From a13b47dbcd243285b28eb7e08af216eaba3b282e Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Thu, 19 Jan 2017 07:32:45 -0800 Subject: [PATCH] servo: Merge #15098 - Mark the page source as loaded only after parsing is done (from nox:load-fixes); r=jdm Source-Repo: https://github.com/servo/servo Source-Revision: 6272cb5a519d2b5e92ac7112c177043970feedaa --- servo/components/script/dom/document.rs | 18 ++++++----- .../components/script/dom/servoparser/html.rs | 4 +++ .../components/script/dom/servoparser/mod.rs | 18 ++++++++--- .../components/script/dom/servoparser/xml.rs | 4 +++ servo/components/script/script_thread.rs | 31 ++----------------- 5 files changed, 34 insertions(+), 41 deletions(-) diff --git a/servo/components/script/dom/document.rs b/servo/components/script/dom/document.rs index d99a90588d78..65f106192bda 100644 --- a/servo/components/script/dom/document.rs +++ b/servo/components/script/dom/document.rs @@ -132,6 +132,7 @@ use style::restyle_hints::RestyleHint; use style::selector_parser::{RestyleDamage, Snapshot}; use style::str::{split_html_space_chars, str_join}; use style::stylesheets::Stylesheet; +use task_source::TaskSource; use time; use url::percent_encoding::percent_decode; @@ -1572,13 +1573,11 @@ impl Document { } if !self.loader.borrow().is_blocked() && !self.loader.borrow().events_inhibited() { - // Schedule a task to fire a "load" event (if no blocking loads have arrived in the mean time) - // NOTE: we can end up executing this code more than once, in case more blocking loads arrive. + self.loader.borrow_mut().inhibit_events(); + // Schedule a task to fire a "load" event. debug!("Document loads are complete."); - let win = self.window(); - let msg = MainThreadScriptMsg::DocumentLoadsComplete( - win.upcast::().pipeline_id()); - win.main_thread_script_chan().send(msg).unwrap(); + let handler = box DocumentProgressHandler::new(Trusted::new(self)); + self.window.dom_manipulation_task_source().queue(handler, self.window.upcast()).unwrap(); } } @@ -3314,6 +3313,9 @@ impl DocumentProgressHandler { fn dispatch_load(&self) { let document = self.addr.root(); + if document.browsing_context().is_none() { + return; + } let window = document.window(); let event = Event::new(window.upcast(), atom!("load"), @@ -3331,7 +3333,6 @@ impl DocumentProgressHandler { // http://w3c.github.io/navigation-timing/#widl-PerformanceNavigationTiming-loadEventEnd update_with_current_time_ms(&document.load_event_end); - window.reflow(ReflowGoal::ForDisplay, ReflowQueryType::NoQuery, ReflowReason::DocumentLoaded); @@ -3349,6 +3350,9 @@ impl Runnable for DocumentProgressHandler { if window.is_alive() { self.set_ready_state_complete(); self.dispatch_load(); + if let Some(fragment) = document.url().fragment() { + document.check_and_scroll_fragment(fragment); + } } } } diff --git a/servo/components/script/dom/servoparser/html.rs b/servo/components/script/dom/servoparser/html.rs index 1e53cea83411..a6270eaaf262 100644 --- a/servo/components/script/dom/servoparser/html.rs +++ b/servo/components/script/dom/servoparser/html.rs @@ -93,6 +93,10 @@ impl Tokenizer { self.inner.end(); } + pub fn url(&self) -> &ServoUrl { + &self.inner.sink().sink().base_url + } + pub fn set_plaintext_state(&mut self) { self.inner.set_plaintext_state(); } diff --git a/servo/components/script/dom/servoparser/mod.rs b/servo/components/script/dom/servoparser/mod.rs index f71205efe380..30a5c5948a24 100644 --- a/servo/components/script/dom/servoparser/mod.rs +++ b/servo/components/script/dom/servoparser/mod.rs @@ -110,7 +110,8 @@ impl ServoParser { let url = context_document.url(); // Step 1. - let loader = DocumentLoader::new(&*context_document.loader()); + let loader = DocumentLoader::new_with_threads(context_document.loader().resource_threads().clone(), + Some(url.clone())); let document = Document::new(window, None, Some(url.clone()), context_document.origin().alias(), IsHTMLDocument::HTMLDocument, @@ -351,14 +352,17 @@ impl ServoParser { self.document.set_current_parser(None); if self.pipeline.is_some() { + // Initial reflow. self.document.disarm_reflow_timeout(); self.document.upcast::().dirty(NodeDamage::OtherNodeDamage); let window = self.document.window(); window.reflow(ReflowGoal::ForDisplay, ReflowQueryType::NoQuery, ReflowReason::FirstLoad); } - // Step 3. + // Steps 3-12 are in other castles, namely process_deferred_scripts and finish_load. + let url = self.tokenizer.borrow().url().clone(); self.document.process_deferred_scripts(); + self.document.finish_load(LoadType::PageSource(url)); } } @@ -401,6 +405,13 @@ impl Tokenizer { } } + fn url(&self) -> &ServoUrl { + match *self { + Tokenizer::Html(ref tokenizer) => tokenizer.url(), + Tokenizer::Xml(ref tokenizer) => tokenizer.url(), + } + } + fn set_plaintext_state(&mut self) { match *self { Tokenizer::Html(ref mut tokenizer) => tokenizer.set_plaintext_state(), @@ -558,9 +569,6 @@ impl FetchResponseListener for ParserContext { debug!("Failed to load page URL {}, error: {:?}", self.url, err); } - parser.document - .finish_load(LoadType::PageSource(self.url.clone())); - parser.last_chunk_received.set(true); if !parser.suspended.get() { parser.parse_sync(); diff --git a/servo/components/script/dom/servoparser/xml.rs b/servo/components/script/dom/servoparser/xml.rs index 96de50f293d5..1ef5f882db0c 100644 --- a/servo/components/script/dom/servoparser/xml.rs +++ b/servo/components/script/dom/servoparser/xml.rs @@ -71,6 +71,10 @@ impl Tokenizer { pub fn end(&mut self) { self.inner.end() } + + pub fn url(&self) -> &ServoUrl { + &self.inner.sink().sink().base_url + } } #[allow(unsafe_code)] diff --git a/servo/components/script/script_thread.rs b/servo/components/script/script_thread.rs index 58a59e2fd91d..ce02d763699d 100644 --- a/servo/components/script/script_thread.rs +++ b/servo/components/script/script_thread.rs @@ -41,7 +41,7 @@ use dom::bindings::str::DOMString; use dom::bindings::trace::JSTraceable; use dom::bindings::utils::WRAP_CALLBACKS; use dom::browsingcontext::BrowsingContext; -use dom::document::{Document, DocumentProgressHandler, DocumentSource, FocusType, IsHTMLDocument, TouchEventResult}; +use dom::document::{Document, DocumentSource, FocusType, IsHTMLDocument, TouchEventResult}; use dom::element::Element; use dom::event::{Event, EventBubbles, EventCancelable}; use dom::globalscope::GlobalScope; @@ -239,8 +239,6 @@ enum MixedMessage { pub enum MainThreadScriptMsg { /// Common variants associated with the script messages Common(CommonScriptMsg), - /// Notify a document that all pending loads are complete. - DocumentLoadsComplete(PipelineId), /// Notifies the script that a window associated with a particular pipeline /// should be closed (only dispatched to ScriptThread). ExitWindow(PipelineId), @@ -1027,8 +1025,6 @@ impl ScriptThread { self.handle_navigate(parent_pipeline_id, None, load_data, replace), MainThreadScriptMsg::ExitWindow(id) => self.handle_exit_window_msg(id), - MainThreadScriptMsg::DocumentLoadsComplete(id) => - self.handle_loads_complete(id), MainThreadScriptMsg::Common(CommonScriptMsg::RunnableMsg(_, runnable)) => { // The category of the runnable is ignored by the pattern, however // it is still respected by profiling (see categorize_msg). @@ -1248,29 +1244,6 @@ impl ScriptThread { } } - fn handle_loads_complete(&self, pipeline: PipelineId) { - let doc = match { self.documents.borrow().find_document(pipeline) } { - Some(doc) => doc, - None => return warn!("Message sent to closed pipeline {}.", pipeline), - }; - if doc.loader().is_blocked() { - debug!("Script thread got loads complete while loader is blocked."); - return; - } - - doc.mut_loader().inhibit_events(); - - // https://html.spec.whatwg.org/multipage/#the-end step 7 - // Schedule a task to fire a "load" event (if no blocking loads have arrived in the mean time) - // NOTE: we can end up executing this code more than once, in case more blocking loads arrive. - let handler = box DocumentProgressHandler::new(Trusted::new(&doc)); - self.dom_manipulation_task_source.queue(handler, doc.window().upcast()).unwrap(); - - if let Some(fragment) = doc.url().fragment() { - doc.check_and_scroll_fragment(fragment); - }; - } - fn collect_reports(&self, reports_chan: ReportsChan) { let mut path_seg = String::from("url("); let mut dom_tree_size = 0; @@ -1771,7 +1744,7 @@ impl ScriptThread { }); let loader = DocumentLoader::new_with_threads(self.resource_threads.clone(), - Some(incomplete.url.clone())); + Some(final_url.clone())); let is_html_document = match metadata.content_type { Some(Serde(ContentType(Mime(TopLevel::Application, SubLevel::Ext(ref sub_level), _))))