mirror of
https://github.com/servo/servo.git
synced 2025-08-05 21:50:18 +01:00
Auto merge of #5804 - jdm:docloader, r=Ms2ger
This implements a simple load-tracking system and tracks stylesheet loads as an example of how it fits together. This is a simplified and rebased version of #3714; I do not believe that the main thrust of hsivonen's comments (related to tracking navigation in browsing contexts) affect this part of the work. r? @Ms2ger <!-- Reviewable:start --> [<img src="https://reviewable.io/review_button.png" height=40 alt="Review on Reviewable"/>](https://reviewable.io/reviews/servo/servo/5804) <!-- Reviewable:end -->
This commit is contained in:
commit
2baa69595e
22 changed files with 459 additions and 144 deletions
|
@ -108,7 +108,7 @@ impl Pipeline {
|
||||||
script_port,
|
script_port,
|
||||||
constellation_chan.clone(),
|
constellation_chan.clone(),
|
||||||
failure.clone(),
|
failure.clone(),
|
||||||
resource_task.clone(),
|
resource_task,
|
||||||
storage_task.clone(),
|
storage_task.clone(),
|
||||||
image_cache_task.clone(),
|
image_cache_task.clone(),
|
||||||
devtools_chan,
|
devtools_chan,
|
||||||
|
@ -153,7 +153,6 @@ impl Pipeline {
|
||||||
failure,
|
failure,
|
||||||
script_chan.clone(),
|
script_chan.clone(),
|
||||||
paint_chan.clone(),
|
paint_chan.clone(),
|
||||||
resource_task,
|
|
||||||
image_cache_task,
|
image_cache_task,
|
||||||
font_cache_task,
|
font_cache_task,
|
||||||
time_profiler_chan,
|
time_profiler_chan,
|
||||||
|
|
|
@ -45,7 +45,7 @@ use msg::constellation_msg::{ConstellationChan, Failure, PipelineExitType, Pipel
|
||||||
use profile_traits::mem::{self, Report, ReportsChan};
|
use profile_traits::mem::{self, Report, ReportsChan};
|
||||||
use profile_traits::time::{self, ProfilerMetadata, profile};
|
use profile_traits::time::{self, ProfilerMetadata, profile};
|
||||||
use profile_traits::time::{TimerMetadataFrameType, TimerMetadataReflowType};
|
use profile_traits::time::{TimerMetadataFrameType, TimerMetadataReflowType};
|
||||||
use net_traits::{load_bytes_iter, ResourceTask};
|
use net_traits::{load_bytes_iter, PendingAsyncLoad};
|
||||||
use net_traits::image_cache_task::{ImageCacheTask, ImageCacheResult, ImageCacheChan};
|
use net_traits::image_cache_task::{ImageCacheTask, ImageCacheResult, ImageCacheChan};
|
||||||
use script::dom::bindings::js::LayoutJS;
|
use script::dom::bindings::js::LayoutJS;
|
||||||
use script::dom::node::{LayoutData, Node};
|
use script::dom::node::{LayoutData, Node};
|
||||||
|
@ -54,7 +54,7 @@ use script::layout_interface::{HitTestResponse, LayoutChan, LayoutRPC};
|
||||||
use script::layout_interface::{MouseOverResponse, Msg, Reflow, ReflowGoal, ReflowQueryType};
|
use script::layout_interface::{MouseOverResponse, Msg, Reflow, ReflowGoal, ReflowQueryType};
|
||||||
use script::layout_interface::{ScriptLayoutChan, ScriptReflow, TrustedNodeAddress};
|
use script::layout_interface::{ScriptLayoutChan, ScriptReflow, TrustedNodeAddress};
|
||||||
use script_traits::{ConstellationControlMsg, OpaqueScriptLayoutChannel};
|
use script_traits::{ConstellationControlMsg, OpaqueScriptLayoutChannel};
|
||||||
use script_traits::ScriptControlChan;
|
use script_traits::{ScriptControlChan, StylesheetLoadResponder};
|
||||||
use std::borrow::ToOwned;
|
use std::borrow::ToOwned;
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
use std::mem::transmute;
|
use std::mem::transmute;
|
||||||
|
@ -170,8 +170,8 @@ pub struct LayoutTask {
|
||||||
/// The name used for the task's memory reporter.
|
/// The name used for the task's memory reporter.
|
||||||
pub reporter_name: String,
|
pub reporter_name: String,
|
||||||
|
|
||||||
/// The channel on which messages can be sent to the resource task.
|
/// The channel on which messages can be sent to the image cache.
|
||||||
pub resource_task: ResourceTask,
|
pub image_cache_task: ImageCacheTask,
|
||||||
|
|
||||||
/// Public interface to the font cache task.
|
/// Public interface to the font cache task.
|
||||||
pub font_cache_task: FontCacheTask,
|
pub font_cache_task: FontCacheTask,
|
||||||
|
@ -198,7 +198,6 @@ impl LayoutTaskFactory for LayoutTask {
|
||||||
failure_msg: Failure,
|
failure_msg: Failure,
|
||||||
script_chan: ScriptControlChan,
|
script_chan: ScriptControlChan,
|
||||||
paint_chan: PaintChan,
|
paint_chan: PaintChan,
|
||||||
resource_task: ResourceTask,
|
|
||||||
image_cache_task: ImageCacheTask,
|
image_cache_task: ImageCacheTask,
|
||||||
font_cache_task: FontCacheTask,
|
font_cache_task: FontCacheTask,
|
||||||
time_profiler_chan: time::ProfilerChan,
|
time_profiler_chan: time::ProfilerChan,
|
||||||
|
@ -217,7 +216,6 @@ impl LayoutTaskFactory for LayoutTask {
|
||||||
constellation_chan,
|
constellation_chan,
|
||||||
script_chan,
|
script_chan,
|
||||||
paint_chan,
|
paint_chan,
|
||||||
resource_task,
|
|
||||||
image_cache_task,
|
image_cache_task,
|
||||||
font_cache_task,
|
font_cache_task,
|
||||||
time_profiler_chan,
|
time_profiler_chan,
|
||||||
|
@ -270,7 +268,6 @@ impl LayoutTask {
|
||||||
constellation_chan: ConstellationChan,
|
constellation_chan: ConstellationChan,
|
||||||
script_chan: ScriptControlChan,
|
script_chan: ScriptControlChan,
|
||||||
paint_chan: PaintChan,
|
paint_chan: PaintChan,
|
||||||
resource_task: ResourceTask,
|
|
||||||
image_cache_task: ImageCacheTask,
|
image_cache_task: ImageCacheTask,
|
||||||
font_cache_task: FontCacheTask,
|
font_cache_task: FontCacheTask,
|
||||||
time_profiler_chan: time::ProfilerChan,
|
time_profiler_chan: time::ProfilerChan,
|
||||||
|
@ -311,7 +308,7 @@ impl LayoutTask {
|
||||||
time_profiler_chan: time_profiler_chan,
|
time_profiler_chan: time_profiler_chan,
|
||||||
mem_profiler_chan: mem_profiler_chan,
|
mem_profiler_chan: mem_profiler_chan,
|
||||||
reporter_name: reporter_name,
|
reporter_name: reporter_name,
|
||||||
resource_task: resource_task,
|
image_cache_task: image_cache_task.clone(),
|
||||||
font_cache_task: font_cache_task,
|
font_cache_task: font_cache_task,
|
||||||
first_reflow: Cell::new(true),
|
first_reflow: Cell::new(true),
|
||||||
image_cache_receiver: image_cache_receiver,
|
image_cache_receiver: image_cache_receiver,
|
||||||
|
@ -489,8 +486,8 @@ impl LayoutTask {
|
||||||
Msg::AddStylesheet(sheet, mq) => {
|
Msg::AddStylesheet(sheet, mq) => {
|
||||||
self.handle_add_stylesheet(sheet, mq, possibly_locked_rw_data)
|
self.handle_add_stylesheet(sheet, mq, possibly_locked_rw_data)
|
||||||
}
|
}
|
||||||
Msg::LoadStylesheet(url, mq) => {
|
Msg::LoadStylesheet(url, mq, pending, link_element) => {
|
||||||
self.handle_load_stylesheet(url, mq, possibly_locked_rw_data)
|
self.handle_load_stylesheet(url, mq, pending, link_element, possibly_locked_rw_data)
|
||||||
}
|
}
|
||||||
Msg::SetQuirksMode => self.handle_set_quirks_mode(possibly_locked_rw_data),
|
Msg::SetQuirksMode => self.handle_set_quirks_mode(possibly_locked_rw_data),
|
||||||
Msg::GetRPC(response_chan) => {
|
Msg::GetRPC(response_chan) => {
|
||||||
|
@ -595,13 +592,15 @@ impl LayoutTask {
|
||||||
fn handle_load_stylesheet<'a>(&'a self,
|
fn handle_load_stylesheet<'a>(&'a self,
|
||||||
url: Url,
|
url: Url,
|
||||||
mq: MediaQueryList,
|
mq: MediaQueryList,
|
||||||
|
pending: PendingAsyncLoad,
|
||||||
|
responder: Box<StylesheetLoadResponder+Send>,
|
||||||
possibly_locked_rw_data:
|
possibly_locked_rw_data:
|
||||||
&mut Option<MutexGuard<'a, LayoutTaskData>>) {
|
&mut Option<MutexGuard<'a, LayoutTaskData>>) {
|
||||||
// TODO: Get the actual value. http://dev.w3.org/csswg/css-syntax/#environment-encoding
|
// TODO: Get the actual value. http://dev.w3.org/csswg/css-syntax/#environment-encoding
|
||||||
let environment_encoding = UTF_8 as EncodingRef;
|
let environment_encoding = UTF_8 as EncodingRef;
|
||||||
|
|
||||||
// TODO we don't really even need to load this if mq does not match
|
// TODO we don't really even need to load this if mq does not match
|
||||||
let (metadata, iter) = load_bytes_iter(&self.resource_task, url);
|
let (metadata, iter) = load_bytes_iter(pending);
|
||||||
let protocol_encoding_label = metadata.charset.as_ref().map(|s| &**s);
|
let protocol_encoding_label = metadata.charset.as_ref().map(|s| &**s);
|
||||||
let final_url = metadata.final_url;
|
let final_url = metadata.final_url;
|
||||||
|
|
||||||
|
@ -610,6 +609,11 @@ impl LayoutTask {
|
||||||
protocol_encoding_label,
|
protocol_encoding_label,
|
||||||
Some(environment_encoding),
|
Some(environment_encoding),
|
||||||
Origin::Author);
|
Origin::Author);
|
||||||
|
|
||||||
|
//TODO: mark critical subresources as blocking load as well (#5974)
|
||||||
|
let ScriptControlChan(ref chan) = self.script_chan;
|
||||||
|
chan.send(ConstellationControlMsg::StylesheetLoadComplete(self.id, url, responder)).unwrap();
|
||||||
|
|
||||||
self.handle_add_stylesheet(sheet, mq, possibly_locked_rw_data);
|
self.handle_add_stylesheet(sheet, mq, possibly_locked_rw_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,6 @@ use gfx::paint_task::PaintChan;
|
||||||
use msg::constellation_msg::{ConstellationChan, Failure, PipelineId, PipelineExitType};
|
use msg::constellation_msg::{ConstellationChan, Failure, PipelineId, PipelineExitType};
|
||||||
use profile_traits::mem;
|
use profile_traits::mem;
|
||||||
use profile_traits::time;
|
use profile_traits::time;
|
||||||
use net_traits::ResourceTask;
|
|
||||||
use net_traits::image_cache_task::ImageCacheTask;
|
use net_traits::image_cache_task::ImageCacheTask;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
use script_traits::{ScriptControlChan, OpaqueScriptLayoutChannel};
|
use script_traits::{ScriptControlChan, OpaqueScriptLayoutChannel};
|
||||||
|
@ -49,7 +48,6 @@ pub trait LayoutTaskFactory {
|
||||||
failure_msg: Failure,
|
failure_msg: Failure,
|
||||||
script_chan: ScriptControlChan,
|
script_chan: ScriptControlChan,
|
||||||
paint_chan: PaintChan,
|
paint_chan: PaintChan,
|
||||||
resource_task: ResourceTask,
|
|
||||||
image_cache_task: ImageCacheTask,
|
image_cache_task: ImageCacheTask,
|
||||||
font_cache_task: FontCacheTask,
|
font_cache_task: FontCacheTask,
|
||||||
time_profiler_chan: time::ProfilerChan,
|
time_profiler_chan: time::ProfilerChan,
|
||||||
|
|
|
@ -125,6 +125,58 @@ pub enum ControlMsg {
|
||||||
Exit
|
Exit
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Initialized but unsent request. Encapsulates everything necessary to instruct
|
||||||
|
/// the resource task to make a new request. The `load` method *must* be called before
|
||||||
|
/// destruction or the task will panic.
|
||||||
|
pub struct PendingAsyncLoad {
|
||||||
|
resource_task: ResourceTask,
|
||||||
|
url: Url,
|
||||||
|
pipeline: Option<PipelineId>,
|
||||||
|
input_sender: Sender<LoadResponse>,
|
||||||
|
input_receiver: Receiver<LoadResponse>,
|
||||||
|
guard: PendingLoadGuard,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct PendingLoadGuard {
|
||||||
|
loaded: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PendingLoadGuard {
|
||||||
|
fn neuter(&mut self) {
|
||||||
|
self.loaded = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for PendingLoadGuard {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
assert!(self.loaded)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PendingAsyncLoad {
|
||||||
|
pub fn new(resource_task: ResourceTask, url: Url, pipeline: Option<PipelineId>)
|
||||||
|
-> PendingAsyncLoad {
|
||||||
|
let (sender, receiver) = channel();
|
||||||
|
PendingAsyncLoad {
|
||||||
|
resource_task: resource_task,
|
||||||
|
url: url,
|
||||||
|
pipeline: pipeline,
|
||||||
|
input_sender: sender,
|
||||||
|
input_receiver: receiver,
|
||||||
|
guard: PendingLoadGuard { loaded: false, },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Initiate the network request associated with this pending load.
|
||||||
|
pub fn load(mut self) -> Receiver<LoadResponse> {
|
||||||
|
self.guard.neuter();
|
||||||
|
let load_data = LoadData::new(self.url, self.pipeline);
|
||||||
|
let consumer = LoadConsumer::Channel(self.input_sender);
|
||||||
|
self.resource_task.send(ControlMsg::Load(load_data, consumer)).unwrap();
|
||||||
|
self.input_receiver
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Message sent in response to `Load`. Contains metadata, and a port
|
/// Message sent in response to `Load`. Contains metadata, and a port
|
||||||
/// for receiving the data.
|
/// for receiving the data.
|
||||||
///
|
///
|
||||||
|
@ -230,10 +282,8 @@ pub fn load_whole_resource(resource_task: &ResourceTask, url: Url)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Load a URL asynchronously and iterate over chunks of bytes from the response.
|
/// Load a URL asynchronously and iterate over chunks of bytes from the response.
|
||||||
pub fn load_bytes_iter(resource_task: &ResourceTask, url: Url) -> (Metadata, ProgressMsgPortIterator) {
|
pub fn load_bytes_iter(pending: PendingAsyncLoad) -> (Metadata, ProgressMsgPortIterator) {
|
||||||
let (input_chan, input_port) = channel();
|
let input_port = pending.load();
|
||||||
resource_task.send(ControlMsg::Load(LoadData::new(url, None), LoadConsumer::Channel(input_chan))).unwrap();
|
|
||||||
|
|
||||||
let response = input_port.recv().unwrap();
|
let response = input_port.recv().unwrap();
|
||||||
let iter = ProgressMsgPortIterator { progress_port: response.progress_port };
|
let iter = ProgressMsgPortIterator { progress_port: response.progress_port };
|
||||||
(response.metadata, iter)
|
(response.metadata, iter)
|
||||||
|
|
110
components/script/document_loader.rs
Normal file
110
components/script/document_loader.rs
Normal file
|
@ -0,0 +1,110 @@
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
//! Tracking of pending loads in a document.
|
||||||
|
//! https://html.spec.whatwg.org/multipage/#the-end
|
||||||
|
|
||||||
|
use script_task::{ScriptMsg, ScriptChan};
|
||||||
|
use msg::constellation_msg::{PipelineId};
|
||||||
|
use net_traits::{LoadResponse, Metadata, load_whole_resource, ResourceTask, PendingAsyncLoad};
|
||||||
|
use url::Url;
|
||||||
|
|
||||||
|
use std::sync::mpsc::Receiver;
|
||||||
|
|
||||||
|
#[jstraceable]
|
||||||
|
#[derive(PartialEq, Clone)]
|
||||||
|
pub enum LoadType {
|
||||||
|
Image(Url),
|
||||||
|
Script(Url),
|
||||||
|
Subframe(Url),
|
||||||
|
Stylesheet(Url),
|
||||||
|
PageSource(Url),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LoadType {
|
||||||
|
fn url(&self) -> &Url {
|
||||||
|
match *self {
|
||||||
|
LoadType::Image(ref url) |
|
||||||
|
LoadType::Script(ref url) |
|
||||||
|
LoadType::Subframe(ref url) |
|
||||||
|
LoadType::Stylesheet(ref url) |
|
||||||
|
LoadType::PageSource(ref url) => url,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[jstraceable]
|
||||||
|
pub struct DocumentLoader {
|
||||||
|
pub resource_task: ResourceTask,
|
||||||
|
notifier_data: Option<NotifierData>,
|
||||||
|
blocking_loads: Vec<LoadType>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[jstraceable]
|
||||||
|
pub struct NotifierData {
|
||||||
|
pub script_chan: Box<ScriptChan + Send>,
|
||||||
|
pub pipeline: PipelineId,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DocumentLoader {
|
||||||
|
pub fn new(existing: &DocumentLoader) -> DocumentLoader {
|
||||||
|
DocumentLoader::new_with_task(existing.resource_task.clone(), None, None)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new_with_task(resource_task: ResourceTask,
|
||||||
|
data: Option<NotifierData>,
|
||||||
|
initial_load: Option<Url>,)
|
||||||
|
-> DocumentLoader {
|
||||||
|
let initial_loads = initial_load.into_iter().map(LoadType::PageSource).collect();
|
||||||
|
|
||||||
|
DocumentLoader {
|
||||||
|
resource_task: resource_task,
|
||||||
|
notifier_data: data,
|
||||||
|
blocking_loads: initial_loads,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create a new pending network request, which can be initiated at some point in
|
||||||
|
/// the future.
|
||||||
|
pub fn prepare_async_load(&mut self, load: LoadType) -> PendingAsyncLoad {
|
||||||
|
let url = load.url().clone();
|
||||||
|
self.blocking_loads.push(load);
|
||||||
|
let pipeline = self.notifier_data.as_ref().map(|data| data.pipeline);
|
||||||
|
PendingAsyncLoad::new(self.resource_task.clone(), url, pipeline)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create and initiate a new network request.
|
||||||
|
pub fn load_async(&mut self, load: LoadType) -> Receiver<LoadResponse> {
|
||||||
|
let pending = self.prepare_async_load(load);
|
||||||
|
pending.load()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create, initiate, and await the response for a new network request.
|
||||||
|
pub fn load_sync(&mut self, load: LoadType) -> Result<(Metadata, Vec<u8>), String> {
|
||||||
|
self.blocking_loads.push(load.clone());
|
||||||
|
let result = load_whole_resource(&self.resource_task, load.url().clone());
|
||||||
|
self.finish_load(load);
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Mark an in-progress network request complete.
|
||||||
|
pub fn finish_load(&mut self, load: LoadType) {
|
||||||
|
let idx = self.blocking_loads.iter().position(|unfinished| *unfinished == load);
|
||||||
|
self.blocking_loads.remove(idx.expect("unknown completed load"));
|
||||||
|
|
||||||
|
if let Some(NotifierData { ref script_chan, pipeline }) = self.notifier_data {
|
||||||
|
if !self.is_blocked() {
|
||||||
|
script_chan.send(ScriptMsg::DocumentLoadsComplete(pipeline)).unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_blocked(&self) -> bool {
|
||||||
|
!self.blocking_loads.is_empty()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn inhibit_events(&mut self) {
|
||||||
|
self.notifier_data = None;
|
||||||
|
}
|
||||||
|
}
|
|
@ -7,9 +7,11 @@
|
||||||
//! This module contains smart pointers to global scopes, to simplify writing
|
//! This module contains smart pointers to global scopes, to simplify writing
|
||||||
//! code that works in workers as well as window scopes.
|
//! code that works in workers as well as window scopes.
|
||||||
|
|
||||||
|
use dom::bindings::codegen::Bindings::WindowBinding::WindowMethods;
|
||||||
use dom::bindings::conversions::native_from_reflector_jsmanaged;
|
use dom::bindings::conversions::native_from_reflector_jsmanaged;
|
||||||
use dom::bindings::js::{JS, JSRef, Rootable, Root, Unrooted};
|
use dom::bindings::js::{JS, JSRef, Rootable, Root, Unrooted};
|
||||||
use dom::bindings::utils::{Reflectable, Reflector};
|
use dom::bindings::utils::{Reflectable, Reflector};
|
||||||
|
use dom::document::DocumentHelpers;
|
||||||
use dom::workerglobalscope::{WorkerGlobalScope, WorkerGlobalScopeHelpers};
|
use dom::workerglobalscope::{WorkerGlobalScope, WorkerGlobalScopeHelpers};
|
||||||
use dom::window::{self, WindowHelpers};
|
use dom::window::{self, WindowHelpers};
|
||||||
use devtools_traits::DevtoolsControlChan;
|
use devtools_traits::DevtoolsControlChan;
|
||||||
|
@ -101,7 +103,12 @@ impl<'a> GlobalRef<'a> {
|
||||||
/// Get the `ResourceTask` for this global scope.
|
/// Get the `ResourceTask` for this global scope.
|
||||||
pub fn resource_task(&self) -> ResourceTask {
|
pub fn resource_task(&self) -> ResourceTask {
|
||||||
match *self {
|
match *self {
|
||||||
GlobalRef::Window(ref window) => window.resource_task().clone(),
|
GlobalRef::Window(ref window) => {
|
||||||
|
let doc = window.Document().root();
|
||||||
|
let doc = doc.r();
|
||||||
|
let loader = doc.loader();
|
||||||
|
loader.resource_task.clone()
|
||||||
|
}
|
||||||
GlobalRef::Worker(ref worker) => worker.resource_task().clone(),
|
GlobalRef::Worker(ref worker) => worker.resource_task().clone(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
use document_loader::{DocumentLoader, LoadType};
|
||||||
use dom::attr::{Attr, AttrHelpers, AttrValue};
|
use dom::attr::{Attr, AttrHelpers, AttrValue};
|
||||||
use dom::bindings::cell::DOMRefCell;
|
use dom::bindings::cell::DOMRefCell;
|
||||||
use dom::bindings::codegen::Bindings::DocumentBinding;
|
use dom::bindings::codegen::Bindings::DocumentBinding;
|
||||||
|
@ -71,6 +72,7 @@ use msg::constellation_msg::{ConstellationChan, FocusType, Key, KeyState, KeyMod
|
||||||
use msg::constellation_msg::{SUPER, ALT, SHIFT, CONTROL};
|
use msg::constellation_msg::{SUPER, ALT, SHIFT, CONTROL};
|
||||||
use net_traits::CookieSource::NonHTTP;
|
use net_traits::CookieSource::NonHTTP;
|
||||||
use net_traits::ControlMsg::{SetCookiesForUrl, GetCookiesForUrl};
|
use net_traits::ControlMsg::{SetCookiesForUrl, GetCookiesForUrl};
|
||||||
|
use net_traits::{Metadata, LoadResponse, PendingAsyncLoad};
|
||||||
use script_task::Runnable;
|
use script_task::Runnable;
|
||||||
use script_traits::{MouseButton, UntrustedNodeAddress};
|
use script_traits::{MouseButton, UntrustedNodeAddress};
|
||||||
use util::opts;
|
use util::opts;
|
||||||
|
@ -90,9 +92,9 @@ use std::borrow::ToOwned;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::collections::hash_map::Entry::{Occupied, Vacant};
|
use std::collections::hash_map::Entry::{Occupied, Vacant};
|
||||||
use std::ascii::AsciiExt;
|
use std::ascii::AsciiExt;
|
||||||
use std::cell::{Cell, Ref, RefCell};
|
use std::cell::{Cell, Ref, RefMut, RefCell};
|
||||||
use std::default::Default;
|
use std::default::Default;
|
||||||
use std::sync::mpsc::channel;
|
use std::sync::mpsc::{Receiver, channel};
|
||||||
use time;
|
use time;
|
||||||
|
|
||||||
#[derive(PartialEq)]
|
#[derive(PartialEq)]
|
||||||
|
@ -139,6 +141,8 @@ pub struct Document {
|
||||||
/// https://html.spec.whatwg.org/multipage/#list-of-animation-frame-callbacks
|
/// https://html.spec.whatwg.org/multipage/#list-of-animation-frame-callbacks
|
||||||
/// List of animation frame callbacks
|
/// List of animation frame callbacks
|
||||||
animation_frame_list: RefCell<HashMap<i32, Box<Fn(f64)>>>,
|
animation_frame_list: RefCell<HashMap<i32, Box<Fn(f64)>>>,
|
||||||
|
/// Tracks all outstanding loads related to this document.
|
||||||
|
loader: DOMRefCell<DocumentLoader>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DocumentDerived for EventTarget {
|
impl DocumentDerived for EventTarget {
|
||||||
|
@ -205,6 +209,8 @@ impl CollectionFilter for AppletsFilter {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait DocumentHelpers<'a> {
|
pub trait DocumentHelpers<'a> {
|
||||||
|
fn loader(&self) -> Ref<DocumentLoader>;
|
||||||
|
fn mut_loader(&self) -> RefMut<DocumentLoader>;
|
||||||
fn window(self) -> Temporary<Window>;
|
fn window(self) -> Temporary<Window>;
|
||||||
fn encoding_name(self) -> Ref<'a, DOMString>;
|
fn encoding_name(self) -> Ref<'a, DOMString>;
|
||||||
fn is_html_document(self) -> bool;
|
fn is_html_document(self) -> bool;
|
||||||
|
@ -254,9 +260,23 @@ pub trait DocumentHelpers<'a> {
|
||||||
fn cancel_animation_frame(self, ident: i32);
|
fn cancel_animation_frame(self, ident: i32);
|
||||||
/// http://w3c.github.io/animation-timing/#dfn-invoke-callbacks-algorithm
|
/// http://w3c.github.io/animation-timing/#dfn-invoke-callbacks-algorithm
|
||||||
fn invoke_animation_callbacks(self);
|
fn invoke_animation_callbacks(self);
|
||||||
|
fn prepare_async_load(self, load: LoadType) -> PendingAsyncLoad;
|
||||||
|
fn load_async(self, load: LoadType) -> Receiver<LoadResponse>;
|
||||||
|
fn load_sync(self, load: LoadType) -> Result<(Metadata, Vec<u8>), String>;
|
||||||
|
fn finish_load(self, load: LoadType);
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> DocumentHelpers<'a> for JSRef<'a, Document> {
|
impl<'a> DocumentHelpers<'a> for JSRef<'a, Document> {
|
||||||
|
#[inline]
|
||||||
|
fn loader(&self) -> Ref<DocumentLoader> {
|
||||||
|
self.loader.borrow()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn mut_loader(&self) -> RefMut<DocumentLoader> {
|
||||||
|
self.loader.borrow_mut()
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn window(self) -> Temporary<Window> {
|
fn window(self) -> Temporary<Window> {
|
||||||
Temporary::from_rooted(self.window)
|
Temporary::from_rooted(self.window)
|
||||||
|
@ -864,6 +884,26 @@ impl<'a> DocumentHelpers<'a> for JSRef<'a, Document> {
|
||||||
callback(*performance.Now());
|
callback(*performance.Now());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn prepare_async_load(self, load: LoadType) -> PendingAsyncLoad {
|
||||||
|
let mut loader = self.loader.borrow_mut();
|
||||||
|
loader.prepare_async_load(load)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn load_async(self, load: LoadType) -> Receiver<LoadResponse> {
|
||||||
|
let mut loader = self.loader.borrow_mut();
|
||||||
|
loader.load_async(load)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn load_sync(self, load: LoadType) -> Result<(Metadata, Vec<u8>), String> {
|
||||||
|
let mut loader = self.loader.borrow_mut();
|
||||||
|
loader.load_sync(load)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn finish_load(self, load: LoadType) {
|
||||||
|
let mut loader = self.loader.borrow_mut();
|
||||||
|
loader.finish_load(load);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum MouseEventType {
|
pub enum MouseEventType {
|
||||||
|
@ -898,7 +938,8 @@ impl Document {
|
||||||
is_html_document: IsHTMLDocument,
|
is_html_document: IsHTMLDocument,
|
||||||
content_type: Option<DOMString>,
|
content_type: Option<DOMString>,
|
||||||
last_modified: Option<DOMString>,
|
last_modified: Option<DOMString>,
|
||||||
source: DocumentSource) -> Document {
|
source: DocumentSource,
|
||||||
|
doc_loader: DocumentLoader) -> Document {
|
||||||
let url = url.unwrap_or_else(|| Url::parse("about:blank").unwrap());
|
let url = url.unwrap_or_else(|| Url::parse("about:blank").unwrap());
|
||||||
|
|
||||||
let ready_state = if source == DocumentSource::FromParser {
|
let ready_state = if source == DocumentSource::FromParser {
|
||||||
|
@ -943,14 +984,19 @@ impl Document {
|
||||||
scripting_enabled: Cell::new(true),
|
scripting_enabled: Cell::new(true),
|
||||||
animation_frame_ident: Cell::new(0),
|
animation_frame_ident: Cell::new(0),
|
||||||
animation_frame_list: RefCell::new(HashMap::new()),
|
animation_frame_list: RefCell::new(HashMap::new()),
|
||||||
|
loader: DOMRefCell::new(doc_loader),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://dom.spec.whatwg.org/#dom-document
|
// https://dom.spec.whatwg.org/#dom-document
|
||||||
pub fn Constructor(global: GlobalRef) -> Fallible<Temporary<Document>> {
|
pub fn Constructor(global: GlobalRef) -> Fallible<Temporary<Document>> {
|
||||||
Ok(Document::new(global.as_window(), None,
|
let win = global.as_window();
|
||||||
|
let doc = win.Document().root();
|
||||||
|
let doc = doc.r();
|
||||||
|
let docloader = DocumentLoader::new(&*doc.loader());
|
||||||
|
Ok(Document::new(win, None,
|
||||||
IsHTMLDocument::NonHTMLDocument, None,
|
IsHTMLDocument::NonHTMLDocument, None,
|
||||||
None, DocumentSource::NotFromParser))
|
None, DocumentSource::NotFromParser, docloader))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new(window: JSRef<Window>,
|
pub fn new(window: JSRef<Window>,
|
||||||
|
@ -958,10 +1004,11 @@ impl Document {
|
||||||
doctype: IsHTMLDocument,
|
doctype: IsHTMLDocument,
|
||||||
content_type: Option<DOMString>,
|
content_type: Option<DOMString>,
|
||||||
last_modified: Option<DOMString>,
|
last_modified: Option<DOMString>,
|
||||||
source: DocumentSource) -> Temporary<Document> {
|
source: DocumentSource,
|
||||||
|
doc_loader: DocumentLoader) -> Temporary<Document> {
|
||||||
let document = reflect_dom_object(box Document::new_inherited(window, url, doctype,
|
let document = reflect_dom_object(box Document::new_inherited(window, url, doctype,
|
||||||
content_type, last_modified,
|
content_type, last_modified,
|
||||||
source),
|
source, doc_loader),
|
||||||
GlobalRef::Window(window),
|
GlobalRef::Window(window),
|
||||||
DocumentBinding::Wrap).root();
|
DocumentBinding::Wrap).root();
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
use document_loader::DocumentLoader;
|
||||||
use dom::bindings::codegen::Bindings::DocumentBinding::DocumentMethods;
|
use dom::bindings::codegen::Bindings::DocumentBinding::DocumentMethods;
|
||||||
use dom::bindings::codegen::Bindings::DOMImplementationBinding;
|
use dom::bindings::codegen::Bindings::DOMImplementationBinding;
|
||||||
use dom::bindings::codegen::Bindings::DOMImplementationBinding::DOMImplementationMethods;
|
use dom::bindings::codegen::Bindings::DOMImplementationBinding::DOMImplementationMethods;
|
||||||
|
@ -63,11 +64,13 @@ impl<'a> DOMImplementationMethods for JSRef<'a, DOMImplementation> {
|
||||||
fn CreateDocument(self, namespace: Option<DOMString>, qname: DOMString,
|
fn CreateDocument(self, namespace: Option<DOMString>, qname: DOMString,
|
||||||
maybe_doctype: Option<JSRef<DocumentType>>) -> Fallible<Temporary<Document>> {
|
maybe_doctype: Option<JSRef<DocumentType>>) -> Fallible<Temporary<Document>> {
|
||||||
let doc = self.document.root();
|
let doc = self.document.root();
|
||||||
let win = doc.r().window().root();
|
let doc = doc.r();
|
||||||
|
let win = doc.window().root();
|
||||||
|
let loader = DocumentLoader::new(&*doc.loader());
|
||||||
|
|
||||||
// Step 1.
|
// Step 1.
|
||||||
let doc = Document::new(win.r(), None, IsHTMLDocument::NonHTMLDocument,
|
let doc = Document::new(win.r(), None, IsHTMLDocument::NonHTMLDocument,
|
||||||
None, None, DocumentSource::NotFromParser).root();
|
None, None, DocumentSource::NotFromParser, loader).root();
|
||||||
// Step 2-3.
|
// Step 2-3.
|
||||||
let maybe_elem = if qname.is_empty() {
|
let maybe_elem = if qname.is_empty() {
|
||||||
None
|
None
|
||||||
|
@ -109,11 +112,13 @@ impl<'a> DOMImplementationMethods for JSRef<'a, DOMImplementation> {
|
||||||
// https://dom.spec.whatwg.org/#dom-domimplementation-createhtmldocument
|
// https://dom.spec.whatwg.org/#dom-domimplementation-createhtmldocument
|
||||||
fn CreateHTMLDocument(self, title: Option<DOMString>) -> Temporary<Document> {
|
fn CreateHTMLDocument(self, title: Option<DOMString>) -> Temporary<Document> {
|
||||||
let document = self.document.root();
|
let document = self.document.root();
|
||||||
let win = document.r().window().root();
|
let document = document.r();
|
||||||
|
let win = document.window().root();
|
||||||
|
let loader = DocumentLoader::new(&*document.loader());
|
||||||
|
|
||||||
// Step 1-2.
|
// Step 1-2.
|
||||||
let doc = Document::new(win.r(), None, IsHTMLDocument::HTMLDocument, None, None,
|
let doc = Document::new(win.r(), None, IsHTMLDocument::HTMLDocument, None, None,
|
||||||
DocumentSource::NotFromParser).root();
|
DocumentSource::NotFromParser, loader).root();
|
||||||
let doc_node: JSRef<Node> = NodeCast::from_ref(doc.r());
|
let doc_node: JSRef<Node> = NodeCast::from_ref(doc.r());
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
|
@ -2,10 +2,12 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
use document_loader::DocumentLoader;
|
||||||
use dom::bindings::codegen::Bindings::DocumentBinding::DocumentReadyState;
|
use dom::bindings::codegen::Bindings::DocumentBinding::DocumentReadyState;
|
||||||
use dom::bindings::codegen::Bindings::DOMParserBinding;
|
use dom::bindings::codegen::Bindings::DOMParserBinding;
|
||||||
use dom::bindings::codegen::Bindings::DOMParserBinding::DOMParserMethods;
|
use dom::bindings::codegen::Bindings::DOMParserBinding::DOMParserMethods;
|
||||||
use dom::bindings::codegen::Bindings::DOMParserBinding::SupportedType::{Text_html, Text_xml};
|
use dom::bindings::codegen::Bindings::DOMParserBinding::SupportedType::{Text_html, Text_xml};
|
||||||
|
use dom::bindings::codegen::Bindings::WindowBinding::WindowMethods;
|
||||||
use dom::bindings::error::Fallible;
|
use dom::bindings::error::Fallible;
|
||||||
use dom::bindings::global::GlobalRef;
|
use dom::bindings::global::GlobalRef;
|
||||||
use dom::bindings::js::{JS, JSRef, Rootable, Temporary};
|
use dom::bindings::js::{JS, JSRef, Rootable, Temporary};
|
||||||
|
@ -51,13 +53,17 @@ impl<'a> DOMParserMethods for JSRef<'a, DOMParser> {
|
||||||
let window = self.window.root();
|
let window = self.window.root();
|
||||||
let url = window.r().get_url();
|
let url = window.r().get_url();
|
||||||
let content_type = DOMParserBinding::SupportedTypeValues::strings[ty as usize].to_owned();
|
let content_type = DOMParserBinding::SupportedTypeValues::strings[ty as usize].to_owned();
|
||||||
|
let doc = window.r().Document().root();
|
||||||
|
let doc = doc.r();
|
||||||
|
let loader = DocumentLoader::new(&*doc.loader());
|
||||||
match ty {
|
match ty {
|
||||||
Text_html => {
|
Text_html => {
|
||||||
let document = Document::new(window.r(), Some(url.clone()),
|
let document = Document::new(window.r(), Some(url.clone()),
|
||||||
IsHTMLDocument::HTMLDocument,
|
IsHTMLDocument::HTMLDocument,
|
||||||
Some(content_type),
|
Some(content_type),
|
||||||
None,
|
None,
|
||||||
DocumentSource::FromParser).root();
|
DocumentSource::FromParser,
|
||||||
|
loader).root();
|
||||||
parse_html(document.r(), HTMLInput::InputString(s), &url, None);
|
parse_html(document.r(), HTMLInput::InputString(s), &url, None);
|
||||||
document.r().set_ready_state(DocumentReadyState::Complete);
|
document.r().set_ready_state(DocumentReadyState::Complete);
|
||||||
Ok(Temporary::from_rooted(document.r()))
|
Ok(Temporary::from_rooted(document.r()))
|
||||||
|
@ -68,7 +74,8 @@ impl<'a> DOMParserMethods for JSRef<'a, DOMParser> {
|
||||||
IsHTMLDocument::NonHTMLDocument,
|
IsHTMLDocument::NonHTMLDocument,
|
||||||
Some(content_type),
|
Some(content_type),
|
||||||
None,
|
None,
|
||||||
DocumentSource::NotFromParser))
|
DocumentSource::NotFromParser,
|
||||||
|
loader))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,17 +2,22 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
use document_loader::LoadType;
|
||||||
use dom::attr::{Attr, AttrValue};
|
use dom::attr::{Attr, AttrValue};
|
||||||
use dom::attr::AttrHelpers;
|
use dom::attr::AttrHelpers;
|
||||||
use dom::bindings::codegen::Bindings::HTMLLinkElementBinding;
|
use dom::bindings::codegen::Bindings::HTMLLinkElementBinding;
|
||||||
use dom::bindings::codegen::Bindings::HTMLLinkElementBinding::HTMLLinkElementMethods;
|
use dom::bindings::codegen::Bindings::HTMLLinkElementBinding::HTMLLinkElementMethods;
|
||||||
use dom::bindings::codegen::InheritTypes::HTMLLinkElementDerived;
|
use dom::bindings::codegen::Bindings::WindowBinding::WindowMethods;
|
||||||
|
use dom::bindings::codegen::InheritTypes::{EventTargetCast, HTMLLinkElementDerived};
|
||||||
use dom::bindings::codegen::InheritTypes::{ElementCast, HTMLElementCast, NodeCast};
|
use dom::bindings::codegen::InheritTypes::{ElementCast, HTMLElementCast, NodeCast};
|
||||||
|
use dom::bindings::global::GlobalRef;
|
||||||
use dom::bindings::js::{JS, JSRef, MutNullableHeap, Rootable, Temporary};
|
use dom::bindings::js::{JS, JSRef, MutNullableHeap, Rootable, Temporary};
|
||||||
use dom::bindings::js::{OptionalRootable, RootedReference};
|
use dom::bindings::js::{OptionalRootable, RootedReference};
|
||||||
use dom::document::Document;
|
use dom::bindings::refcounted::Trusted;
|
||||||
|
use dom::document::{Document, DocumentHelpers};
|
||||||
use dom::domtokenlist::DOMTokenList;
|
use dom::domtokenlist::DOMTokenList;
|
||||||
use dom::element::{AttributeHandlers, Element};
|
use dom::element::{AttributeHandlers, Element};
|
||||||
|
use dom::event::{EventBubbles, EventCancelable, Event, EventHelpers};
|
||||||
use dom::eventtarget::{EventTarget, EventTargetTypeId};
|
use dom::eventtarget::{EventTarget, EventTargetTypeId};
|
||||||
use dom::element::ElementTypeId;
|
use dom::element::ElementTypeId;
|
||||||
use dom::htmlelement::{HTMLElement, HTMLElementTypeId};
|
use dom::htmlelement::{HTMLElement, HTMLElementTypeId};
|
||||||
|
@ -20,6 +25,7 @@ use dom::node::{Node, NodeHelpers, NodeTypeId, window_from_node};
|
||||||
use dom::virtualmethods::VirtualMethods;
|
use dom::virtualmethods::VirtualMethods;
|
||||||
use dom::window::WindowHelpers;
|
use dom::window::WindowHelpers;
|
||||||
use layout_interface::{LayoutChan, Msg};
|
use layout_interface::{LayoutChan, Msg};
|
||||||
|
use script_traits::StylesheetLoadResponder;
|
||||||
use util::str::{DOMString, HTML_SPACE_CHARACTERS};
|
use util::str::{DOMString, HTML_SPACE_CHARACTERS};
|
||||||
use style::media_queries::parse_media_query_list;
|
use style::media_queries::parse_media_query_list;
|
||||||
use cssparser::Parser as CssParser;
|
use cssparser::Parser as CssParser;
|
||||||
|
@ -153,8 +159,13 @@ impl<'a> PrivateHTMLLinkElementHelpers for JSRef<'a, HTMLLinkElement> {
|
||||||
let mut css_parser = CssParser::new(&mq_str);
|
let mut css_parser = CssParser::new(&mq_str);
|
||||||
let media = parse_media_query_list(&mut css_parser);
|
let media = parse_media_query_list(&mut css_parser);
|
||||||
|
|
||||||
|
let doc = window.Document().root();
|
||||||
|
let link_element = Trusted::new(window.get_cx(), self, window.script_chan().clone());
|
||||||
|
let load_dispatcher = StylesheetLoadDispatcher::new(link_element);
|
||||||
|
|
||||||
|
let pending = doc.r().prepare_async_load(LoadType::Stylesheet(url.clone()));
|
||||||
let LayoutChan(ref layout_chan) = window.layout_chan();
|
let LayoutChan(ref layout_chan) = window.layout_chan();
|
||||||
layout_chan.send(Msg::LoadStylesheet(url, media)).unwrap();
|
layout_chan.send(Msg::LoadStylesheet(url, media, pending, box load_dispatcher)).unwrap();
|
||||||
}
|
}
|
||||||
Err(e) => debug!("Parsing url {} failed: {}", href, e)
|
Err(e) => debug!("Parsing url {} failed: {}", href, e)
|
||||||
}
|
}
|
||||||
|
@ -183,3 +194,27 @@ impl<'a> HTMLLinkElementMethods for JSRef<'a, HTMLLinkElement> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct StylesheetLoadDispatcher {
|
||||||
|
elem: Trusted<HTMLLinkElement>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl StylesheetLoadDispatcher {
|
||||||
|
pub fn new(elem: Trusted<HTMLLinkElement>) -> StylesheetLoadDispatcher {
|
||||||
|
StylesheetLoadDispatcher {
|
||||||
|
elem: elem,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl StylesheetLoadResponder for StylesheetLoadDispatcher {
|
||||||
|
fn respond(self: Box<StylesheetLoadDispatcher>) {
|
||||||
|
let elem = self.elem.to_temporary().root();
|
||||||
|
let window = window_from_node(elem.r()).root();
|
||||||
|
let event = Event::new(GlobalRef::Window(window.r()), "load".to_owned(),
|
||||||
|
EventBubbles::DoesNotBubble,
|
||||||
|
EventCancelable::NotCancelable).root();
|
||||||
|
let target = EventTargetCast::from_ref(elem.r());
|
||||||
|
event.r().fire(target);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
use std::ascii::AsciiExt;
|
use std::ascii::AsciiExt;
|
||||||
|
|
||||||
|
use document_loader::LoadType;
|
||||||
use dom::attr::Attr;
|
use dom::attr::Attr;
|
||||||
use dom::attr::AttrHelpers;
|
use dom::attr::AttrHelpers;
|
||||||
use dom::bindings::cell::DOMRefCell;
|
use dom::bindings::cell::DOMRefCell;
|
||||||
|
@ -34,7 +35,7 @@ use script_task::{ScriptMsg, Runnable};
|
||||||
use encoding::all::UTF_8;
|
use encoding::all::UTF_8;
|
||||||
use encoding::label::encoding_from_whatwg_label;
|
use encoding::label::encoding_from_whatwg_label;
|
||||||
use encoding::types::{Encoding, EncodingRef, DecoderTrap};
|
use encoding::types::{Encoding, EncodingRef, DecoderTrap};
|
||||||
use net_traits::{load_whole_resource, Metadata};
|
use net_traits::Metadata;
|
||||||
use util::str::{DOMString, HTML_SPACE_CHARACTERS, StaticStringVec};
|
use util::str::{DOMString, HTML_SPACE_CHARACTERS, StaticStringVec};
|
||||||
use std::borrow::ToOwned;
|
use std::borrow::ToOwned;
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
|
@ -261,7 +262,9 @@ impl<'a> HTMLScriptElementHelpers for JSRef<'a, HTMLScriptElement> {
|
||||||
// state of the element's `crossorigin` content attribute, the origin being
|
// state of the element's `crossorigin` content attribute, the origin being
|
||||||
// the origin of the script element's node document, and the default origin
|
// the origin of the script element's node document, and the default origin
|
||||||
// behaviour set to taint.
|
// behaviour set to taint.
|
||||||
ScriptOrigin::External(load_whole_resource(&window.resource_task(), url))
|
let doc = document_from_node(self).root();
|
||||||
|
let contents = doc.r().load_sync(LoadType::Script(url));
|
||||||
|
ScriptOrigin::External(contents)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
//! The core DOM types. Defines the basic DOM hierarchy as well as all the HTML elements.
|
//! The core DOM types. Defines the basic DOM hierarchy as well as all the HTML elements.
|
||||||
|
|
||||||
|
use document_loader::DocumentLoader;
|
||||||
use dom::attr::{Attr, AttrHelpers};
|
use dom::attr::{Attr, AttrHelpers};
|
||||||
use dom::bindings::cell::DOMRefCell;
|
use dom::bindings::cell::DOMRefCell;
|
||||||
use dom::bindings::codegen::Bindings::AttrBinding::AttrMethods;
|
use dom::bindings::codegen::Bindings::AttrBinding::AttrMethods;
|
||||||
|
@ -1708,9 +1709,10 @@ impl Node {
|
||||||
false => IsHTMLDocument::NonHTMLDocument,
|
false => IsHTMLDocument::NonHTMLDocument,
|
||||||
};
|
};
|
||||||
let window = document.window().root();
|
let window = document.window().root();
|
||||||
|
let loader = DocumentLoader::new(&*document.loader());
|
||||||
let document = Document::new(window.r(), Some(document.url()),
|
let document = Document::new(window.r(), Some(document.url()),
|
||||||
is_html_doc, None,
|
is_html_doc, None,
|
||||||
None, DocumentSource::NotFromParser);
|
None, DocumentSource::NotFromParser, loader);
|
||||||
NodeCast::from_temporary(document)
|
NodeCast::from_temporary(document)
|
||||||
},
|
},
|
||||||
NodeTypeId::Element(..) => {
|
NodeTypeId::Element(..) => {
|
||||||
|
|
|
@ -12,8 +12,10 @@ use geom::point::Point2D;
|
||||||
use geom::rect::Rect;
|
use geom::rect::Rect;
|
||||||
use libc::uintptr_t;
|
use libc::uintptr_t;
|
||||||
use msg::constellation_msg::{PipelineExitType, WindowSizeData};
|
use msg::constellation_msg::{PipelineExitType, WindowSizeData};
|
||||||
|
use net_traits::PendingAsyncLoad;
|
||||||
use profile_traits::mem::{Reporter, ReportsChan};
|
use profile_traits::mem::{Reporter, ReportsChan};
|
||||||
use script_traits::{ScriptControlChan, OpaqueScriptLayoutChannel, UntrustedNodeAddress};
|
use script_traits::{ScriptControlChan, OpaqueScriptLayoutChannel, UntrustedNodeAddress};
|
||||||
|
use script_traits::StylesheetLoadResponder;
|
||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
use std::sync::mpsc::{channel, Receiver, Sender};
|
use std::sync::mpsc::{channel, Receiver, Sender};
|
||||||
use style::animation::PropertyAnimation;
|
use style::animation::PropertyAnimation;
|
||||||
|
@ -30,7 +32,7 @@ pub enum Msg {
|
||||||
AddStylesheet(Stylesheet, MediaQueryList),
|
AddStylesheet(Stylesheet, MediaQueryList),
|
||||||
|
|
||||||
/// Adds the given stylesheet to the document.
|
/// Adds the given stylesheet to the document.
|
||||||
LoadStylesheet(Url, MediaQueryList),
|
LoadStylesheet(Url, MediaQueryList, PendingAsyncLoad, Box<StylesheetLoadResponder+Send>),
|
||||||
|
|
||||||
/// Puts a document into quirks mode, causing the quirks mode stylesheet to be loaded.
|
/// Puts a document into quirks mode, causing the quirks mode stylesheet to be loaded.
|
||||||
SetQuirksMode,
|
SetQuirksMode,
|
||||||
|
|
|
@ -54,6 +54,7 @@ extern crate string_cache;
|
||||||
extern crate webdriver_traits;
|
extern crate webdriver_traits;
|
||||||
|
|
||||||
pub mod cors;
|
pub mod cors;
|
||||||
|
pub mod document_loader;
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
pub mod dom;
|
pub mod dom;
|
||||||
|
|
|
@ -71,6 +71,10 @@ impl Page {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn pipeline(&self) -> PipelineId {
|
||||||
|
self.id
|
||||||
|
}
|
||||||
|
|
||||||
pub fn window(&self) -> Temporary<Window> {
|
pub fn window(&self) -> Temporary<Window> {
|
||||||
Temporary::from_rooted(self.frame.borrow().as_ref().unwrap().window.clone())
|
Temporary::from_rooted(self.frame.borrow().as_ref().unwrap().window.clone())
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
#![allow(unsafe_code, unrooted_must_root)]
|
#![allow(unsafe_code, unrooted_must_root)]
|
||||||
|
|
||||||
|
use document_loader::{DocumentLoader, LoadType};
|
||||||
use dom::attr::AttrHelpers;
|
use dom::attr::AttrHelpers;
|
||||||
use dom::bindings::codegen::Bindings::DocumentBinding::DocumentMethods;
|
use dom::bindings::codegen::Bindings::DocumentBinding::DocumentMethods;
|
||||||
use dom::bindings::codegen::Bindings::NodeBinding::NodeMethods;
|
use dom::bindings::codegen::Bindings::NodeBinding::NodeMethods;
|
||||||
|
@ -286,7 +287,7 @@ pub fn parse_html(document: JSRef<Document>,
|
||||||
task_state::enter(IN_HTML_PARSER);
|
task_state::enter(IN_HTML_PARSER);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_progress(parser: JSRef<ServoHTMLParser>, url: &Url, load_response: &LoadResponse) {
|
fn parse_progress(document: JSRef<Document>, parser: JSRef<ServoHTMLParser>, url: &Url, load_response: &LoadResponse) {
|
||||||
for msg in load_response.progress_port.iter() {
|
for msg in load_response.progress_port.iter() {
|
||||||
match msg {
|
match msg {
|
||||||
ProgressMsg::Payload(data) => {
|
ProgressMsg::Payload(data) => {
|
||||||
|
@ -299,7 +300,10 @@ pub fn parse_html(document: JSRef<Document>,
|
||||||
// TODO(Savago): we should send a notification to callers #5463.
|
// TODO(Savago): we should send a notification to callers #5463.
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
ProgressMsg::Done(Ok(())) => break,
|
ProgressMsg::Done(Ok(())) => {
|
||||||
|
document.finish_load(LoadType::PageSource(url.clone()));
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -313,6 +317,7 @@ pub fn parse_html(document: JSRef<Document>,
|
||||||
Some(ContentType(Mime(TopLevel::Image, _, _))) => {
|
Some(ContentType(Mime(TopLevel::Image, _, _))) => {
|
||||||
let page = format!("<html><body><img src='{}' /></body></html>", url.serialize());
|
let page = format!("<html><body><img src='{}' /></body></html>", url.serialize());
|
||||||
parser.parse_chunk(page);
|
parser.parse_chunk(page);
|
||||||
|
document.finish_load(LoadType::PageSource(url.clone()));
|
||||||
},
|
},
|
||||||
Some(ContentType(Mime(TopLevel::Text, SubLevel::Plain, _))) => {
|
Some(ContentType(Mime(TopLevel::Text, SubLevel::Plain, _))) => {
|
||||||
// FIXME: When servo/html5ever#109 is fixed remove <plaintext> usage and
|
// FIXME: When servo/html5ever#109 is fixed remove <plaintext> usage and
|
||||||
|
@ -325,10 +330,10 @@ pub fn parse_html(document: JSRef<Document>,
|
||||||
// https://html.spec.whatwg.org/multipage/#read-text
|
// https://html.spec.whatwg.org/multipage/#read-text
|
||||||
let page = format!("<pre>\u{000A}<plaintext>");
|
let page = format!("<pre>\u{000A}<plaintext>");
|
||||||
parser.parse_chunk(page);
|
parser.parse_chunk(page);
|
||||||
parse_progress(parser, url, &load_response);
|
parse_progress(document, parser, url, &load_response);
|
||||||
},
|
},
|
||||||
_ => {
|
_ => {
|
||||||
parse_progress(parser, url, &load_response);
|
parse_progress(document, parser, url, &load_response);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -349,16 +354,19 @@ pub fn parse_html_fragment(context_node: JSRef<Node>,
|
||||||
output: &mut RootedVec<JS<Node>>) {
|
output: &mut RootedVec<JS<Node>>) {
|
||||||
let window = window_from_node(context_node).root();
|
let window = window_from_node(context_node).root();
|
||||||
let context_document = document_from_node(context_node).root();
|
let context_document = document_from_node(context_node).root();
|
||||||
let url = context_document.r().url();
|
let context_document = context_document.r();
|
||||||
|
let url = context_document.url();
|
||||||
|
|
||||||
// Step 1.
|
// Step 1.
|
||||||
|
let loader = DocumentLoader::new(&*context_document.loader());
|
||||||
let document = Document::new(window.r(), Some(url.clone()),
|
let document = Document::new(window.r(), Some(url.clone()),
|
||||||
IsHTMLDocument::HTMLDocument,
|
IsHTMLDocument::HTMLDocument,
|
||||||
None, None,
|
None, None,
|
||||||
DocumentSource::FromParser).root();
|
DocumentSource::FromParser,
|
||||||
|
loader).root();
|
||||||
|
|
||||||
// Step 2.
|
// Step 2.
|
||||||
document.r().set_quirks_mode(context_document.r().quirks_mode());
|
document.r().set_quirks_mode(context_document.quirks_mode());
|
||||||
|
|
||||||
// Step 11.
|
// Step 11.
|
||||||
let form = context_node.inclusive_ancestors()
|
let form = context_node.inclusive_ancestors()
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
|
|
||||||
#![allow(unsafe_code)]
|
#![allow(unsafe_code)]
|
||||||
|
|
||||||
|
use document_loader::{LoadType, DocumentLoader, NotifierData};
|
||||||
use dom::bindings::cell::DOMRefCell;
|
use dom::bindings::cell::DOMRefCell;
|
||||||
use dom::bindings::codegen::Bindings::DocumentBinding::{DocumentMethods, DocumentReadyState};
|
use dom::bindings::codegen::Bindings::DocumentBinding::{DocumentMethods, DocumentReadyState};
|
||||||
use dom::bindings::codegen::InheritTypes::{ElementCast, EventTargetCast, HTMLIFrameElementCast, NodeCast, EventCast};
|
use dom::bindings::codegen::InheritTypes::{ElementCast, EventTargetCast, HTMLIFrameElementCast, NodeCast, EventCast};
|
||||||
|
@ -65,7 +66,7 @@ use msg::constellation_msg::{ConstellationChan, FocusType};
|
||||||
use msg::constellation_msg::{LoadData, PipelineId, SubpageId, MozBrowserEvent, WorkerId};
|
use msg::constellation_msg::{LoadData, PipelineId, SubpageId, MozBrowserEvent, WorkerId};
|
||||||
use msg::constellation_msg::{Failure, WindowSizeData, PipelineExitType};
|
use msg::constellation_msg::{Failure, WindowSizeData, PipelineExitType};
|
||||||
use msg::constellation_msg::Msg as ConstellationMsg;
|
use msg::constellation_msg::Msg as ConstellationMsg;
|
||||||
use net_traits::{ResourceTask, ControlMsg, LoadResponse, LoadConsumer};
|
use net_traits::{ResourceTask, LoadResponse, LoadConsumer, ControlMsg};
|
||||||
use net_traits::LoadData as NetLoadData;
|
use net_traits::LoadData as NetLoadData;
|
||||||
use net_traits::image_cache_task::{ImageCacheChan, ImageCacheTask, ImageCacheResult};
|
use net_traits::image_cache_task::{ImageCacheChan, ImageCacheTask, ImageCacheResult};
|
||||||
use net_traits::storage_task::StorageTask;
|
use net_traits::storage_task::StorageTask;
|
||||||
|
@ -190,6 +191,8 @@ pub enum ScriptMsg {
|
||||||
RefcountCleanup(TrustedReference),
|
RefcountCleanup(TrustedReference),
|
||||||
/// The final network response for a page has arrived.
|
/// The final network response for a page has arrived.
|
||||||
PageFetchComplete(PipelineId, Option<SubpageId>, LoadResponse),
|
PageFetchComplete(PipelineId, Option<SubpageId>, LoadResponse),
|
||||||
|
/// Notify a document that all pending loads are complete.
|
||||||
|
DocumentLoadsComplete(PipelineId),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A cloneable interface for communicating with an event loop.
|
/// A cloneable interface for communicating with an event loop.
|
||||||
|
@ -728,6 +731,10 @@ impl ScriptTask {
|
||||||
self.handle_webdriver_msg(pipeline_id, msg),
|
self.handle_webdriver_msg(pipeline_id, msg),
|
||||||
ConstellationControlMsg::TickAllAnimations(pipeline_id) =>
|
ConstellationControlMsg::TickAllAnimations(pipeline_id) =>
|
||||||
self.handle_tick_all_animations(pipeline_id),
|
self.handle_tick_all_animations(pipeline_id),
|
||||||
|
ConstellationControlMsg::StylesheetLoadComplete(id, url, responder) => {
|
||||||
|
responder.respond();
|
||||||
|
self.handle_resource_loaded(id, LoadType::Stylesheet(url));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -753,6 +760,8 @@ impl ScriptTask {
|
||||||
LiveDOMReferences::cleanup(self.get_cx(), addr),
|
LiveDOMReferences::cleanup(self.get_cx(), addr),
|
||||||
ScriptMsg::PageFetchComplete(id, subpage, response) =>
|
ScriptMsg::PageFetchComplete(id, subpage, response) =>
|
||||||
self.handle_page_fetch_complete(id, subpage, response),
|
self.handle_page_fetch_complete(id, subpage, response),
|
||||||
|
ScriptMsg::DocumentLoadsComplete(id) =>
|
||||||
|
self.handle_loads_complete(id),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -844,6 +853,12 @@ impl ScriptTask {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Handle a request to load a page in a new child frame of an existing page.
|
/// Handle a request to load a page in a new child frame of an existing page.
|
||||||
|
fn handle_resource_loaded(&self, pipeline: PipelineId, load: LoadType) {
|
||||||
|
let page = get_page(&self.root_page(), pipeline);
|
||||||
|
let doc = page.document().root();
|
||||||
|
doc.r().finish_load(load);
|
||||||
|
}
|
||||||
|
|
||||||
fn handle_new_layout(&self, new_layout_info: NewLayoutInfo) {
|
fn handle_new_layout(&self, new_layout_info: NewLayoutInfo) {
|
||||||
let NewLayoutInfo {
|
let NewLayoutInfo {
|
||||||
containing_pipeline_id,
|
containing_pipeline_id,
|
||||||
|
@ -868,6 +883,25 @@ impl ScriptTask {
|
||||||
self.start_page_load(new_load, load_data);
|
self.start_page_load(new_load, load_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn handle_loads_complete(&self, pipeline: PipelineId) {
|
||||||
|
let page = get_page(&self.root_page(), pipeline);
|
||||||
|
let doc = page.document().root();
|
||||||
|
let doc = doc.r();
|
||||||
|
if doc.loader().is_blocked() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
doc.mut_loader().inhibit_events();
|
||||||
|
|
||||||
|
// https://html.spec.whatwg.org/multipage/#the-end step 7
|
||||||
|
let addr: Trusted<Document> = Trusted::new(self.get_cx(), doc, self.chan.clone());
|
||||||
|
let handler = box DocumentProgressHandler::new(addr.clone(), DocumentProgressTask::Load);
|
||||||
|
self.chan.send(ScriptMsg::RunnableMsg(handler)).unwrap();
|
||||||
|
|
||||||
|
let ConstellationChan(ref chan) = self.constellation_chan;
|
||||||
|
chan.send(ConstellationMsg::LoadComplete).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
/// Handles a timer that fired.
|
/// Handles a timer that fired.
|
||||||
fn handle_fire_timer_msg(&self, id: PipelineId, timer_id: TimerId) {
|
fn handle_fire_timer_msg(&self, id: PipelineId, timer_id: TimerId) {
|
||||||
let page = self.root_page();
|
let page = self.root_page();
|
||||||
|
@ -1152,12 +1186,20 @@ impl ScriptTask {
|
||||||
_ => None
|
_ => None
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let notifier_data = NotifierData {
|
||||||
|
script_chan: self.chan.clone(),
|
||||||
|
pipeline: page.pipeline(),
|
||||||
|
};
|
||||||
|
let loader = DocumentLoader::new_with_task(self.resource_task.clone(),
|
||||||
|
Some(notifier_data),
|
||||||
|
Some(final_url.clone()));
|
||||||
let document = Document::new(window.r(),
|
let document = Document::new(window.r(),
|
||||||
Some(final_url.clone()),
|
Some(final_url.clone()),
|
||||||
IsHTMLDocument::HTMLDocument,
|
IsHTMLDocument::HTMLDocument,
|
||||||
content_type,
|
content_type,
|
||||||
last_modified,
|
last_modified,
|
||||||
DocumentSource::FromParser).root();
|
DocumentSource::FromParser,
|
||||||
|
loader).root();
|
||||||
|
|
||||||
let frame_element = frame_element.r().map(|elem| ElementCast::from_ref(elem));
|
let frame_element = frame_element.r().map(|elem| ElementCast::from_ref(elem));
|
||||||
window.r().init_browser_context(document.r(), frame_element);
|
window.r().init_browser_context(document.r(), frame_element);
|
||||||
|
@ -1434,22 +1476,11 @@ impl ScriptTask {
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/#the-end step 4
|
// https://html.spec.whatwg.org/multipage/#the-end step 4
|
||||||
let addr: Trusted<Document> = Trusted::new(self.get_cx(), document.r(), self.chan.clone());
|
let addr: Trusted<Document> = Trusted::new(self.get_cx(), document.r(), self.chan.clone());
|
||||||
let handler = box DocumentProgressHandler::new(addr.clone(), DocumentProgressTask::DOMContentLoaded);
|
let handler = box DocumentProgressHandler::new(addr, DocumentProgressTask::DOMContentLoaded);
|
||||||
self.chan.send(ScriptMsg::RunnableMsg(handler)).unwrap();
|
|
||||||
|
|
||||||
// We have no concept of a document loader right now, so just dispatch the
|
|
||||||
// "load" event as soon as we've finished executing all scripts parsed during
|
|
||||||
// the initial load.
|
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/#the-end step 7
|
|
||||||
let handler = box DocumentProgressHandler::new(addr, DocumentProgressTask::Load);
|
|
||||||
self.chan.send(ScriptMsg::RunnableMsg(handler)).unwrap();
|
self.chan.send(ScriptMsg::RunnableMsg(handler)).unwrap();
|
||||||
|
|
||||||
window.r().set_fragment_name(final_url.fragment.clone());
|
window.r().set_fragment_name(final_url.fragment.clone());
|
||||||
|
|
||||||
let ConstellationChan(ref chan) = self.constellation_chan;
|
|
||||||
chan.send(ConstellationMsg::LoadComplete).unwrap();
|
|
||||||
|
|
||||||
// Notify devtools that a new script global exists.
|
// Notify devtools that a new script global exists.
|
||||||
self.notify_devtools(document.r().Title(), final_url, (id, None));
|
self.notify_devtools(document.r().Title(), final_url, (id, None));
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,7 @@ use net_traits::storage_task::StorageTask;
|
||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
use std::sync::mpsc::{Sender, Receiver};
|
use std::sync::mpsc::{Sender, Receiver};
|
||||||
use webdriver_traits::WebDriverScriptCommand;
|
use webdriver_traits::WebDriverScriptCommand;
|
||||||
|
use url::Url;
|
||||||
|
|
||||||
use geom::point::Point2D;
|
use geom::point::Point2D;
|
||||||
use geom::rect::Rect;
|
use geom::rect::Rect;
|
||||||
|
@ -55,6 +56,10 @@ pub struct NewLayoutInfo {
|
||||||
pub load_data: LoadData,
|
pub load_data: LoadData,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait StylesheetLoadResponder {
|
||||||
|
fn respond(self: Box<Self>);
|
||||||
|
}
|
||||||
|
|
||||||
/// Messages sent from the constellation to the script task
|
/// Messages sent from the constellation to the script task
|
||||||
pub enum ConstellationControlMsg {
|
pub enum ConstellationControlMsg {
|
||||||
/// Gives a channel and ID to a layout task, as well as the ID of that layout's parent
|
/// Gives a channel and ID to a layout task, as well as the ID of that layout's parent
|
||||||
|
@ -89,6 +94,8 @@ pub enum ConstellationControlMsg {
|
||||||
WebDriverCommand(PipelineId, WebDriverScriptCommand),
|
WebDriverCommand(PipelineId, WebDriverScriptCommand),
|
||||||
/// Notifies script task that all animations are done
|
/// Notifies script task that all animations are done
|
||||||
TickAllAnimations(PipelineId),
|
TickAllAnimations(PipelineId),
|
||||||
|
/// Notifies script that a stylesheet has finished loading.
|
||||||
|
StylesheetLoadComplete(PipelineId, Url, Box<StylesheetLoadResponder+Send>),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The mouse button involved in the event.
|
/// The mouse button involved in the event.
|
||||||
|
|
|
@ -12553,6 +12553,10 @@
|
||||||
"path": "html/semantics/document-metadata/the-base-element/base_multiple.html",
|
"path": "html/semantics/document-metadata/the-base-element/base_multiple.html",
|
||||||
"url": "/html/semantics/document-metadata/the-base-element/base_multiple.html"
|
"url": "/html/semantics/document-metadata/the-base-element/base_multiple.html"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"path": "html/semantics/document-metadata/the-link-element/link-load-event.html",
|
||||||
|
"url": "/html/semantics/document-metadata/the-link-element/link-load-event.html"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"path": "html/semantics/document-metadata/the-link-element/link-rellist.html",
|
"path": "html/semantics/document-metadata/the-link-element/link-rellist.html",
|
||||||
"url": "/html/semantics/document-metadata/the-link-element/link-rellist.html"
|
"url": "/html/semantics/document-metadata/the-link-element/link-rellist.html"
|
||||||
|
|
|
@ -2,7 +2,55 @@
|
||||||
type: testharness
|
type: testharness
|
||||||
expected: TIMEOUT
|
expected: TIMEOUT
|
||||||
[src removed]
|
[src removed]
|
||||||
expected: FAIL
|
expected: TIMEOUT
|
||||||
|
|
||||||
|
[inserted into picture]
|
||||||
|
expected: TIMEOUT
|
||||||
|
|
||||||
|
[removed from picture]
|
||||||
|
expected: TIMEOUT
|
||||||
|
|
||||||
|
[parent is picture, previous source inserted]
|
||||||
|
expected: TIMEOUT
|
||||||
|
|
||||||
|
[parent is picture, previous source removed]
|
||||||
|
expected: TIMEOUT
|
||||||
|
|
||||||
|
[parent is picture, previous source has srcset set]
|
||||||
|
expected: TIMEOUT
|
||||||
|
|
||||||
|
[parent is picture, previous source has srcset changed]
|
||||||
|
expected: TIMEOUT
|
||||||
|
|
||||||
|
[parent is picture, previous source has srcset removed]
|
||||||
|
expected: TIMEOUT
|
||||||
|
|
||||||
|
[parent is picture, previous source has sizes set]
|
||||||
|
expected: TIMEOUT
|
||||||
|
|
||||||
|
[parent is picture, previous source has sizes changed]
|
||||||
|
expected: TIMEOUT
|
||||||
|
|
||||||
|
[parent is picture, previous source has sizes removed]
|
||||||
|
expected: TIMEOUT
|
||||||
|
|
||||||
|
[parent is picture, previous source has media set]
|
||||||
|
expected: TIMEOUT
|
||||||
|
|
||||||
|
[parent is picture, previous source has media changed]
|
||||||
|
expected: TIMEOUT
|
||||||
|
|
||||||
|
[parent is picture, previous source has media removed]
|
||||||
|
expected: TIMEOUT
|
||||||
|
|
||||||
|
[parent is picture, previous source has type set]
|
||||||
|
expected: TIMEOUT
|
||||||
|
|
||||||
|
[parent is picture, previous source has type changed]
|
||||||
|
expected: TIMEOUT
|
||||||
|
|
||||||
|
[parent is picture, previous source has type removed]
|
||||||
|
expected: TIMEOUT
|
||||||
|
|
||||||
[srcset set]
|
[srcset set]
|
||||||
expected: TIMEOUT
|
expected: TIMEOUT
|
||||||
|
@ -52,84 +100,3 @@
|
||||||
[crossorigin use-credentials to anonymous]
|
[crossorigin use-credentials to anonymous]
|
||||||
expected: TIMEOUT
|
expected: TIMEOUT
|
||||||
|
|
||||||
[crossorigin state not changed: absent, removeAttribute]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[crossorigin state not changed: empty to anonymous]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[crossorigin state not changed: anonymous to foobar]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[crossorigin state not changed: use-credentials to USE-CREDENTIALS]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[inserted into picture ancestor]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[removed from picture ancestor]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[ancestor picture has a source inserted]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[ancestor picture has a source removed]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[ancestor picture; previous sibling source inserted]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[ancestor picture; previous sibling source removed]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[parent is picture, following sibling source inserted]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[parent is picture, following sibling source removed]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[parent is picture, following sibling source has srcset set]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[media on img set]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[type on img set]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[class on img set]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[alt on img set]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[src on previous sibling source set]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[class on previous sibling source set]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[inserted/removed children of img]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[picture is inserted]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[picture is removed]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[parent is picture, following img inserted]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[parent is picture, following img removed]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[parent is picture, following img has src set]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[parent is picture, following img has srcset set]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[parent is picture, following img has sizes set]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<link rel="author" title="Josh Matthews" href="mailto:josh@joshmatthews.net">
|
||||||
|
<link rel="help" href="https://html.spec.whatwg.org/multipage/#the-link-element">
|
||||||
|
<script src="/resources/testharness.js"></script>
|
||||||
|
<script src="/resources/testharnessreport.js"></script>
|
||||||
|
<link href="style.css?pipe=trickle(d3)" rel="stylesheet" id="style_test"></link>
|
||||||
|
<script>
|
||||||
|
var saw_link_onload = false;
|
||||||
|
var t = async_test("Check if the stylesheet's load event blocks the document load event");
|
||||||
|
document.getElementById('style_test').onload = t.step_func(function() {
|
||||||
|
saw_link_onload = true;
|
||||||
|
});
|
||||||
|
window.addEventListener('load', function() {
|
||||||
|
t.step_func(function() {
|
||||||
|
assert_true(saw_link_onload);
|
||||||
|
});
|
||||||
|
t.done();
|
||||||
|
}, false);
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
</html>
|
|
@ -0,0 +1,3 @@
|
||||||
|
body {
|
||||||
|
background-color: white;
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue