mirror of
https://github.com/servo/servo.git
synced 2025-08-04 13:10:20 +01:00
Auto merge of #15072 - nox:load-fixes, r=jdm
Refactor some things related to script loading <!-- Reviewable:start --> This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/15072) <!-- Reviewable:end -->
This commit is contained in:
commit
80c6383140
4 changed files with 69 additions and 108 deletions
|
@ -1450,29 +1450,6 @@ impl Document {
|
||||||
changed
|
changed
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_pending_parsing_blocking_script(&self,
|
|
||||||
script: &HTMLScriptElement,
|
|
||||||
load: Option<ScriptResult>) {
|
|
||||||
assert!(!self.has_pending_parsing_blocking_script());
|
|
||||||
*self.pending_parsing_blocking_script.borrow_mut() = Some(PendingScript::new_with_load(script, load));
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn has_pending_parsing_blocking_script(&self) -> bool {
|
|
||||||
self.pending_parsing_blocking_script.borrow().is_some()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn add_deferred_script(&self, script: &HTMLScriptElement) {
|
|
||||||
self.deferred_scripts.push(script);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn add_asap_script(&self, script: &HTMLScriptElement) {
|
|
||||||
self.asap_scripts_set.borrow_mut().push_back(PendingScript::new(script));
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn push_asap_in_order_script(&self, script: &HTMLScriptElement) {
|
|
||||||
self.asap_in_order_scripts_list.push(script);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn trigger_mozbrowser_event(&self, event: MozBrowserEvent) {
|
pub fn trigger_mozbrowser_event(&self, event: MozBrowserEvent) {
|
||||||
if PREFS.is_mozbrowser_enabled() {
|
if PREFS.is_mozbrowser_enabled() {
|
||||||
if let Some((parent_pipeline_id, _)) = self.window.parent_info() {
|
if let Some((parent_pipeline_id, _)) = self.window.parent_info() {
|
||||||
|
@ -1592,14 +1569,6 @@ impl Document {
|
||||||
*self.pending_parsing_blocking_script.borrow_mut() = None;
|
*self.pending_parsing_blocking_script.borrow_mut() = None;
|
||||||
parser.resume_with_pending_parsing_blocking_script(&element, result);
|
parser.resume_with_pending_parsing_blocking_script(&element, result);
|
||||||
}
|
}
|
||||||
} else if self.reflow_timeout.get().is_none() {
|
|
||||||
// If we don't have a parser, and the reflow timer has been reset, explicitly
|
|
||||||
// trigger a reflow.
|
|
||||||
if let LoadType::Stylesheet(_) = load {
|
|
||||||
self.window.reflow(ReflowGoal::ForDisplay,
|
|
||||||
ReflowQueryType::NoQuery,
|
|
||||||
ReflowReason::StylesheetLoaded);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if !self.loader.borrow().is_blocked() && !self.loader.borrow().events_inhibited() {
|
if !self.loader.borrow().is_blocked() && !self.loader.borrow().events_inhibited() {
|
||||||
|
@ -1613,6 +1582,17 @@ impl Document {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_pending_parsing_blocking_script(&self,
|
||||||
|
script: &HTMLScriptElement,
|
||||||
|
load: Option<ScriptResult>) {
|
||||||
|
assert!(!self.has_pending_parsing_blocking_script());
|
||||||
|
*self.pending_parsing_blocking_script.borrow_mut() = Some(PendingScript::new_with_load(script, load));
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn has_pending_parsing_blocking_script(&self) -> bool {
|
||||||
|
self.pending_parsing_blocking_script.borrow().is_some()
|
||||||
|
}
|
||||||
|
|
||||||
/// https://html.spec.whatwg.org/multipage/#prepare-a-script step 22.d.
|
/// https://html.spec.whatwg.org/multipage/#prepare-a-script step 22.d.
|
||||||
pub fn pending_parsing_blocking_script_loaded(&self, element: &HTMLScriptElement, result: ScriptResult) {
|
pub fn pending_parsing_blocking_script_loaded(&self, element: &HTMLScriptElement, result: ScriptResult) {
|
||||||
let mut blocking_script = self.pending_parsing_blocking_script.borrow_mut();
|
let mut blocking_script = self.pending_parsing_blocking_script.borrow_mut();
|
||||||
|
@ -1621,6 +1601,46 @@ impl Document {
|
||||||
entry.loaded(result);
|
entry.loaded(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn add_asap_script(&self, script: &HTMLScriptElement) {
|
||||||
|
self.asap_scripts_set.borrow_mut().push_back(PendingScript::new(script));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// https://html.spec.whatwg.org/multipage/#the-end step 3.
|
||||||
|
/// https://html.spec.whatwg.org/multipage/#prepare-a-script step 22.d.
|
||||||
|
pub fn asap_script_loaded(&self, element: &HTMLScriptElement, result: ScriptResult) {
|
||||||
|
let mut scripts = self.asap_scripts_set.borrow_mut();
|
||||||
|
let idx = scripts.iter().position(|entry| &*entry.element == element).unwrap();
|
||||||
|
scripts.swap(0, idx);
|
||||||
|
scripts[0].loaded(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn push_asap_in_order_script(&self, script: &HTMLScriptElement) {
|
||||||
|
self.asap_in_order_scripts_list.push(script);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// https://html.spec.whatwg.org/multipage/#the-end step 3.
|
||||||
|
/// https://html.spec.whatwg.org/multipage/#prepare-a-script step 22.c.
|
||||||
|
pub fn asap_in_order_script_loaded(&self,
|
||||||
|
element: &HTMLScriptElement,
|
||||||
|
result: ScriptResult) {
|
||||||
|
self.asap_in_order_scripts_list.loaded(element, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn process_asap_scripts(&self) {
|
||||||
|
let pair = self.asap_scripts_set.borrow_mut().front_mut().and_then(PendingScript::take_result);
|
||||||
|
if let Some((element, result)) = pair {
|
||||||
|
self.asap_scripts_set.borrow_mut().pop_front();
|
||||||
|
element.execute(result);
|
||||||
|
}
|
||||||
|
while let Some((element, result)) = self.asap_in_order_scripts_list.take_next_ready_to_be_executed() {
|
||||||
|
element.execute(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn add_deferred_script(&self, script: &HTMLScriptElement) {
|
||||||
|
self.deferred_scripts.push(script);
|
||||||
|
}
|
||||||
|
|
||||||
/// https://html.spec.whatwg.org/multipage/#prepare-a-script step 22.d.
|
/// https://html.spec.whatwg.org/multipage/#prepare-a-script step 22.d.
|
||||||
pub fn deferred_script_loaded(&self, element: &HTMLScriptElement, result: ScriptResult) {
|
pub fn deferred_script_loaded(&self, element: &HTMLScriptElement, result: ScriptResult) {
|
||||||
self.deferred_scripts.loaded(element, result);
|
self.deferred_scripts.loaded(element, result);
|
||||||
|
@ -1648,34 +1668,6 @@ impl Document {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// https://html.spec.whatwg.org/multipage/#the-end step 3.
|
|
||||||
/// https://html.spec.whatwg.org/multipage/#prepare-a-script step 22.d.
|
|
||||||
pub fn asap_script_loaded(&self, element: &HTMLScriptElement, result: ScriptResult) {
|
|
||||||
let mut scripts = self.asap_scripts_set.borrow_mut();
|
|
||||||
let idx = scripts.iter().position(|entry| &*entry.element == element).unwrap();
|
|
||||||
scripts.swap(0, idx);
|
|
||||||
scripts[0].loaded(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// https://html.spec.whatwg.org/multipage/#the-end step 3.
|
|
||||||
/// https://html.spec.whatwg.org/multipage/#prepare-a-script step 22.c.
|
|
||||||
pub fn asap_in_order_script_loaded(&self,
|
|
||||||
element: &HTMLScriptElement,
|
|
||||||
result: ScriptResult) {
|
|
||||||
self.asap_in_order_scripts_list.loaded(element, result);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn process_asap_scripts(&self) {
|
|
||||||
let pair = self.asap_scripts_set.borrow_mut().front_mut().and_then(PendingScript::take_result);
|
|
||||||
if let Some((element, result)) = pair {
|
|
||||||
self.asap_scripts_set.borrow_mut().pop_front();
|
|
||||||
element.execute(result);
|
|
||||||
}
|
|
||||||
while let Some((element, result)) = self.asap_in_order_scripts_list.take_next_ready_to_be_executed() {
|
|
||||||
element.execute(result);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn maybe_dispatch_dom_content_loaded(&self) {
|
pub fn maybe_dispatch_dom_content_loaded(&self) {
|
||||||
if self.domcontentloaded_dispatched.get() {
|
if self.domcontentloaded_dispatched.get() {
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -55,9 +55,6 @@ pub struct HTMLScriptElement {
|
||||||
/// (currently unused)
|
/// (currently unused)
|
||||||
non_blocking: Cell<bool>,
|
non_blocking: Cell<bool>,
|
||||||
|
|
||||||
/// https://html.spec.whatwg.org/multipage/#ready-to-be-parser-executed
|
|
||||||
ready_to_be_parser_executed: Cell<bool>,
|
|
||||||
|
|
||||||
/// Document of the parser that created this element
|
/// Document of the parser that created this element
|
||||||
parser_document: JS<Document>,
|
parser_document: JS<Document>,
|
||||||
|
|
||||||
|
@ -74,7 +71,6 @@ impl HTMLScriptElement {
|
||||||
already_started: Cell::new(false),
|
already_started: Cell::new(false),
|
||||||
parser_inserted: Cell::new(creator.is_parser_created()),
|
parser_inserted: Cell::new(creator.is_parser_created()),
|
||||||
non_blocking: Cell::new(!creator.is_parser_created()),
|
non_blocking: Cell::new(!creator.is_parser_created()),
|
||||||
ready_to_be_parser_executed: Cell::new(false),
|
|
||||||
parser_document: JS::from_ref(document),
|
parser_document: JS::from_ref(document),
|
||||||
line_number: creator.return_line_number(),
|
line_number: creator.return_line_number(),
|
||||||
}
|
}
|
||||||
|
@ -210,7 +206,6 @@ impl FetchResponseListener for ScriptContext {
|
||||||
// https://html.spec.whatwg.org/multipage/#prepare-a-script
|
// https://html.spec.whatwg.org/multipage/#prepare-a-script
|
||||||
// Step 18.6 (When the chosen algorithm asynchronously completes).
|
// Step 18.6 (When the chosen algorithm asynchronously completes).
|
||||||
let elem = self.elem.root();
|
let elem = self.elem.root();
|
||||||
elem.ready_to_be_parser_executed.set(true);
|
|
||||||
let document = document_from_node(&*elem);
|
let document = document_from_node(&*elem);
|
||||||
|
|
||||||
match self.kind {
|
match self.kind {
|
||||||
|
@ -441,7 +436,6 @@ impl HTMLScriptElement {
|
||||||
// Step 21.
|
// Step 21.
|
||||||
assert!(!text.is_empty());
|
assert!(!text.is_empty());
|
||||||
let result = Ok(ClassicScript::internal(text, base_url));
|
let result = Ok(ClassicScript::internal(text, base_url));
|
||||||
self.ready_to_be_parser_executed.set(true);
|
|
||||||
|
|
||||||
// Step 22.
|
// Step 22.
|
||||||
if was_parser_inserted &&
|
if was_parser_inserted &&
|
||||||
|
@ -456,14 +450,8 @@ impl HTMLScriptElement {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_ready_to_be_executed(&self) -> bool {
|
|
||||||
self.ready_to_be_parser_executed.get()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// https://html.spec.whatwg.org/multipage/#execute-the-script-block
|
/// https://html.spec.whatwg.org/multipage/#execute-the-script-block
|
||||||
pub fn execute(&self, result: Result<ClassicScript, NetworkError>) {
|
pub fn execute(&self, result: Result<ClassicScript, NetworkError>) {
|
||||||
assert!(self.ready_to_be_parser_executed.get());
|
|
||||||
|
|
||||||
// Step 1.
|
// Step 1.
|
||||||
let doc = document_from_node(self);
|
let doc = document_from_node(self);
|
||||||
if self.parser_inserted.get() && &*doc != &*self.parser_document {
|
if self.parser_inserted.get() && &*doc != &*self.parser_document {
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
use document_loader::{DocumentLoader, LoadType};
|
use document_loader::{DocumentLoader, LoadType};
|
||||||
use dom::bindings::cell::DOMRefCell;
|
use dom::bindings::cell::DOMRefCell;
|
||||||
use dom::bindings::codegen::Bindings::DocumentBinding::DocumentMethods;
|
use dom::bindings::codegen::Bindings::DocumentBinding::{DocumentMethods, DocumentReadyState};
|
||||||
use dom::bindings::codegen::Bindings::HTMLImageElementBinding::HTMLImageElementMethods;
|
use dom::bindings::codegen::Bindings::HTMLImageElementBinding::HTMLImageElementMethods;
|
||||||
use dom::bindings::codegen::Bindings::NodeBinding::NodeMethods;
|
use dom::bindings::codegen::Bindings::NodeBinding::NodeMethods;
|
||||||
use dom::bindings::codegen::Bindings::ServoParserBinding;
|
use dom::bindings::codegen::Bindings::ServoParserBinding;
|
||||||
|
@ -20,8 +20,9 @@ use dom::globalscope::GlobalScope;
|
||||||
use dom::htmlformelement::HTMLFormElement;
|
use dom::htmlformelement::HTMLFormElement;
|
||||||
use dom::htmlimageelement::HTMLImageElement;
|
use dom::htmlimageelement::HTMLImageElement;
|
||||||
use dom::htmlscriptelement::{HTMLScriptElement, ScriptResult};
|
use dom::htmlscriptelement::{HTMLScriptElement, ScriptResult};
|
||||||
use dom::node::{Node, NodeSiblingIterator};
|
use dom::node::{Node, NodeDamage, NodeSiblingIterator};
|
||||||
use dom::text::Text;
|
use dom::text::Text;
|
||||||
|
use dom::window::ReflowReason;
|
||||||
use encoding::all::UTF_8;
|
use encoding::all::UTF_8;
|
||||||
use encoding::types::{DecoderTrap, Encoding};
|
use encoding::types::{DecoderTrap, Encoding};
|
||||||
use html5ever::tokenizer::buffer_queue::BufferQueue;
|
use html5ever::tokenizer::buffer_queue::BufferQueue;
|
||||||
|
@ -34,11 +35,13 @@ use net_traits::{FetchMetadata, FetchResponseListener, Metadata, NetworkError};
|
||||||
use network_listener::PreInvoke;
|
use network_listener::PreInvoke;
|
||||||
use profile_traits::time::{TimerMetadata, TimerMetadataFrameType};
|
use profile_traits::time::{TimerMetadata, TimerMetadataFrameType};
|
||||||
use profile_traits::time::{TimerMetadataReflowType, ProfilerCategory, profile};
|
use profile_traits::time::{TimerMetadataReflowType, ProfilerCategory, profile};
|
||||||
|
use script_layout_interface::message::ReflowQueryType;
|
||||||
use script_thread::ScriptThread;
|
use script_thread::ScriptThread;
|
||||||
use servo_config::resource_files::read_resource_file;
|
use servo_config::resource_files::read_resource_file;
|
||||||
use servo_url::ServoUrl;
|
use servo_url::ServoUrl;
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
use style::context::ReflowGoal;
|
||||||
|
|
||||||
mod html;
|
mod html;
|
||||||
mod xml;
|
mod xml;
|
||||||
|
@ -333,20 +336,29 @@ impl ServoParser {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://html.spec.whatwg.org/multipage/#the-end
|
||||||
fn finish(&self) {
|
fn finish(&self) {
|
||||||
assert!(!self.suspended.get());
|
assert!(!self.suspended.get());
|
||||||
assert!(self.last_chunk_received.get());
|
assert!(self.last_chunk_received.get());
|
||||||
assert!(self.script_input.borrow().is_empty());
|
assert!(self.script_input.borrow().is_empty());
|
||||||
assert!(self.network_input.borrow().is_empty());
|
assert!(self.network_input.borrow().is_empty());
|
||||||
|
|
||||||
self.tokenizer.borrow_mut().end();
|
// Step 1.
|
||||||
debug!("finished parsing");
|
self.document.set_ready_state(DocumentReadyState::Interactive);
|
||||||
|
|
||||||
|
// Step 2.
|
||||||
|
self.tokenizer.borrow_mut().end();
|
||||||
self.document.set_current_parser(None);
|
self.document.set_current_parser(None);
|
||||||
|
|
||||||
if let Some(pipeline) = self.pipeline {
|
if self.pipeline.is_some() {
|
||||||
ScriptThread::parsing_complete(pipeline);
|
self.document.disarm_reflow_timeout();
|
||||||
|
self.document.upcast::<Node>().dirty(NodeDamage::OtherNodeDamage);
|
||||||
|
let window = self.document.window();
|
||||||
|
window.reflow(ReflowGoal::ForDisplay, ReflowQueryType::NoQuery, ReflowReason::FirstLoad);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Step 3.
|
||||||
|
self.document.process_deferred_scripts();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -583,13 +583,6 @@ impl ScriptThread {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parsing_complete(id: PipelineId) {
|
|
||||||
SCRIPT_THREAD_ROOT.with(|root| {
|
|
||||||
let script_thread = unsafe { &*root.get().unwrap() };
|
|
||||||
script_thread.handle_parsing_complete(id);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn process_event(msg: CommonScriptMsg) {
|
pub fn process_event(msg: CommonScriptMsg) {
|
||||||
SCRIPT_THREAD_ROOT.with(|root| {
|
SCRIPT_THREAD_ROOT.with(|root| {
|
||||||
if let Some(script_thread) = root.get() {
|
if let Some(script_thread) = root.get() {
|
||||||
|
@ -2163,30 +2156,6 @@ impl ScriptThread {
|
||||||
context.process_response_eof(Ok(()));
|
context.process_response_eof(Ok(()));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_parsing_complete(&self, id: PipelineId) {
|
|
||||||
let document = match { self.documents.borrow().find_document(id) } {
|
|
||||||
Some(document) => document,
|
|
||||||
None => return,
|
|
||||||
};
|
|
||||||
|
|
||||||
let final_url = document.url();
|
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/#the-end step 1
|
|
||||||
document.set_ready_state(DocumentReadyState::Interactive);
|
|
||||||
|
|
||||||
// TODO: Execute step 2 here.
|
|
||||||
|
|
||||||
// Kick off the initial reflow of the page.
|
|
||||||
debug!("kicking off initial reflow of {:?}", final_url);
|
|
||||||
document.disarm_reflow_timeout();
|
|
||||||
document.upcast::<Node>().dirty(NodeDamage::OtherNodeDamage);
|
|
||||||
let window = window_from_node(&*document);
|
|
||||||
window.reflow(ReflowGoal::ForDisplay, ReflowQueryType::NoQuery, ReflowReason::FirstLoad);
|
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/#the-end steps 3-4.
|
|
||||||
document.process_deferred_scripts();
|
|
||||||
}
|
|
||||||
|
|
||||||
fn handle_css_error_reporting(&self, pipeline_id: PipelineId, filename: String,
|
fn handle_css_error_reporting(&self, pipeline_id: PipelineId, filename: String,
|
||||||
line: usize, column: usize, msg: String) {
|
line: usize, column: usize, msg: String) {
|
||||||
let sender = match self.devtools_chan {
|
let sender = match self.devtools_chan {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue