mirror of
https://github.com/servo/servo.git
synced 2025-08-03 04:30:10 +01:00
Auto merge of #18533 - servo:TASKS, r=SimonSapin
Rename Runnable to Task and other improvements <!-- 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/18533) <!-- Reviewable:end -->
This commit is contained in:
commit
23701f8659
43 changed files with 916 additions and 1090 deletions
|
@ -32,8 +32,6 @@ use dom::promise::Promise;
|
|||
use js::jsapi::JSAutoCompartment;
|
||||
use js::jsapi::JSTracer;
|
||||
use libc;
|
||||
use script_thread::Runnable;
|
||||
use script_thread::ScriptThread;
|
||||
use std::cell::RefCell;
|
||||
use std::collections::hash_map::Entry::{Occupied, Vacant};
|
||||
use std::collections::hash_map::HashMap;
|
||||
|
@ -42,6 +40,7 @@ use std::marker::PhantomData;
|
|||
use std::os;
|
||||
use std::rc::Rc;
|
||||
use std::sync::{Arc, Weak};
|
||||
use task::Task;
|
||||
|
||||
|
||||
#[allow(missing_docs)] // FIXME
|
||||
|
@ -121,40 +120,33 @@ impl TrustedPromise {
|
|||
})
|
||||
}
|
||||
|
||||
/// A runnable which will reject the promise.
|
||||
/// A task which will reject the promise.
|
||||
#[allow(unrooted_must_root)]
|
||||
pub fn reject_runnable(self, error: Error) -> impl Runnable + Send {
|
||||
struct RejectPromise(TrustedPromise, Error);
|
||||
impl Runnable for RejectPromise {
|
||||
fn main_thread_handler(self: Box<Self>, script_thread: &ScriptThread) {
|
||||
debug!("Rejecting promise.");
|
||||
let this = *self;
|
||||
let cx = script_thread.get_cx();
|
||||
let promise = this.0.root();
|
||||
let _ac = JSAutoCompartment::new(cx, promise.reflector().get_jsobject().get());
|
||||
promise.reject_error(cx, this.1);
|
||||
}
|
||||
}
|
||||
RejectPromise(self, error)
|
||||
pub fn reject_task(self, error: Error) -> impl Send + Task {
|
||||
let this = self;
|
||||
task!(reject_promise: move || {
|
||||
debug!("Rejecting promise.");
|
||||
let this = this.root();
|
||||
let cx = this.global().get_cx();
|
||||
let _ac = JSAutoCompartment::new(cx, this.reflector().get_jsobject().get());
|
||||
this.reject_error(cx, error);
|
||||
})
|
||||
}
|
||||
|
||||
/// A runnable which will resolve the promise.
|
||||
/// A task which will resolve the promise.
|
||||
#[allow(unrooted_must_root)]
|
||||
pub fn resolve_runnable<T>(self, value: T) -> impl Runnable + Send where
|
||||
T: ToJSValConvertible + Send
|
||||
pub fn resolve_task<T>(self, value: T) -> impl Send + Task
|
||||
where
|
||||
T: ToJSValConvertible + Send,
|
||||
{
|
||||
struct ResolvePromise<T>(TrustedPromise, T);
|
||||
impl<T: ToJSValConvertible> Runnable for ResolvePromise<T> {
|
||||
fn main_thread_handler(self: Box<Self>, script_thread: &ScriptThread) {
|
||||
debug!("Resolving promise.");
|
||||
let this = *self;
|
||||
let cx = script_thread.get_cx();
|
||||
let promise = this.0.root();
|
||||
let _ac = JSAutoCompartment::new(cx, promise.reflector().get_jsobject().get());
|
||||
promise.resolve_native(cx, &this.1);
|
||||
}
|
||||
}
|
||||
ResolvePromise(self, value)
|
||||
let this = self;
|
||||
task!(resolve_promise: move || {
|
||||
debug!("Resolving promise.");
|
||||
let this = this.root();
|
||||
let cx = this.global().get_cx();
|
||||
let _ac = JSAutoCompartment::new(cx, this.reflector().get_jsobject().get());
|
||||
this.resolve_native(cx, &value);
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -35,12 +35,12 @@ use ipc_channel::router::ROUTER;
|
|||
use js::conversions::ConversionResult;
|
||||
use js::jsapi::{JSAutoCompartment, JSContext, JSObject};
|
||||
use js::jsval::{ObjectValue, UndefinedValue};
|
||||
use script_thread::Runnable;
|
||||
use std::cell::Ref;
|
||||
use std::collections::HashMap;
|
||||
use std::rc::Rc;
|
||||
use std::str::FromStr;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use task::Task;
|
||||
|
||||
const KEY_CONVERSION_ERROR: &'static str = "This `manufacturerData` key can not be parsed as unsigned short:";
|
||||
const FILTER_EMPTY_ERROR: &'static str = "'filters' member, if present, must be nonempty to find any devices.";
|
||||
|
@ -224,25 +224,28 @@ pub fn response_async<T: AsyncBluetoothListener + DomObject + 'static>(
|
|||
receiver: Trusted::new(receiver),
|
||||
}));
|
||||
ROUTER.add_route(action_receiver.to_opaque(), box move |message| {
|
||||
struct ListenerRunnable<T: AsyncBluetoothListener + DomObject> {
|
||||
struct ListenerTask<T: AsyncBluetoothListener + DomObject> {
|
||||
context: Arc<Mutex<BluetoothContext<T>>>,
|
||||
action: BluetoothResponseResult,
|
||||
}
|
||||
|
||||
impl<T: AsyncBluetoothListener + DomObject> Runnable for ListenerRunnable<T> {
|
||||
fn handler(self: Box<Self>) {
|
||||
impl<T> Task for ListenerTask<T>
|
||||
where
|
||||
T: AsyncBluetoothListener + DomObject,
|
||||
{
|
||||
fn run(self: Box<Self>) {
|
||||
let this = *self;
|
||||
let mut context = this.context.lock().unwrap();
|
||||
context.response(this.action);
|
||||
}
|
||||
}
|
||||
|
||||
let runnable = box ListenerRunnable {
|
||||
let task = box ListenerTask {
|
||||
context: context.clone(),
|
||||
action: message.to().unwrap(),
|
||||
};
|
||||
|
||||
let result = task_source.queue_wrapperless(runnable);
|
||||
let result = task_source.queue_unconditionally(task);
|
||||
if let Err(err) = result {
|
||||
warn!("failed to deliver network data: {:?}", err);
|
||||
}
|
||||
|
|
|
@ -15,15 +15,18 @@ use dom::bindings::js::{Root, RootCollection};
|
|||
use dom::bindings::reflector::DomObject;
|
||||
use dom::bindings::str::DOMString;
|
||||
use dom::bindings::structuredclone::StructuredCloneData;
|
||||
use dom::errorevent::ErrorEvent;
|
||||
use dom::event::{Event, EventBubbles, EventCancelable, EventStatus};
|
||||
use dom::eventtarget::EventTarget;
|
||||
use dom::globalscope::GlobalScope;
|
||||
use dom::messageevent::MessageEvent;
|
||||
use dom::worker::{TrustedWorkerAddress, WorkerErrorHandler, WorkerMessageHandler};
|
||||
use dom::worker::{TrustedWorkerAddress, Worker};
|
||||
use dom::workerglobalscope::WorkerGlobalScope;
|
||||
use dom_struct::dom_struct;
|
||||
use ipc_channel::ipc::{self, IpcReceiver, IpcSender};
|
||||
use ipc_channel::router::ROUTER;
|
||||
use js::jsapi::{HandleValue, JS_SetInterruptCallback};
|
||||
use js::jsapi::{JSAutoCompartment, JSContext};
|
||||
use js::jsapi::{JSAutoCompartment, JSContext, NullHandleValue};
|
||||
use js::jsval::UndefinedValue;
|
||||
use js::rust::Runtime;
|
||||
use msg::constellation_msg::TopLevelBrowsingContextId;
|
||||
|
@ -190,7 +193,7 @@ impl DedicatedWorkerGlobalScope {
|
|||
&init.resource_threads.sender()) {
|
||||
Err(_) => {
|
||||
println!("error loading script {}", serialized_worker_url);
|
||||
parent_sender.send(CommonScriptMsg::RunnableMsg(WorkerEvent,
|
||||
parent_sender.send(CommonScriptMsg::Task(WorkerEvent,
|
||||
box SimpleWorkerErrorHandler::new(worker))).unwrap();
|
||||
return;
|
||||
}
|
||||
|
@ -348,13 +351,36 @@ impl DedicatedWorkerGlobalScope {
|
|||
}
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#runtime-script-errors-2
|
||||
#[allow(unsafe_code)]
|
||||
pub fn forward_error_to_worker_object(&self, error_info: ErrorInfo) {
|
||||
let worker = self.worker.borrow().as_ref().unwrap().clone();
|
||||
let task = box task!(forward_error_to_worker_object: move || {
|
||||
let worker = worker.root();
|
||||
let global = worker.global();
|
||||
|
||||
// Step 1.
|
||||
let event = ErrorEvent::new(
|
||||
&global,
|
||||
atom!("error"),
|
||||
EventBubbles::DoesNotBubble,
|
||||
EventCancelable::Cancelable,
|
||||
error_info.message.as_str().into(),
|
||||
error_info.filename.as_str().into(),
|
||||
error_info.lineno,
|
||||
error_info.column,
|
||||
unsafe { NullHandleValue },
|
||||
);
|
||||
let event_status =
|
||||
event.upcast::<Event>().fire(worker.upcast::<EventTarget>());
|
||||
|
||||
// Step 2.
|
||||
if event_status == EventStatus::NotCanceled {
|
||||
global.report_an_error(error_info, unsafe { NullHandleValue });
|
||||
}
|
||||
});
|
||||
// TODO: Should use the DOM manipulation task source.
|
||||
self.parent_sender
|
||||
.send(CommonScriptMsg::RunnableMsg(WorkerEvent,
|
||||
box WorkerErrorHandler::new(worker, error_info)))
|
||||
.unwrap();
|
||||
self.parent_sender.send(CommonScriptMsg::Task(WorkerEvent, task)).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -375,10 +401,10 @@ impl DedicatedWorkerGlobalScopeMethods for DedicatedWorkerGlobalScope {
|
|||
unsafe fn PostMessage(&self, cx: *mut JSContext, message: HandleValue) -> ErrorResult {
|
||||
let data = StructuredCloneData::write(cx, message)?;
|
||||
let worker = self.worker.borrow().as_ref().unwrap().clone();
|
||||
self.parent_sender
|
||||
.send(CommonScriptMsg::RunnableMsg(WorkerEvent,
|
||||
box WorkerMessageHandler::new(worker, data)))
|
||||
.unwrap();
|
||||
let task = box task!(post_worker_message: move || {
|
||||
Worker::handle_message(worker, data);
|
||||
});
|
||||
self.parent_sender.send(CommonScriptMsg::Task(WorkerEvent, task)).unwrap();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
|
@ -113,7 +113,7 @@ use net_traits::response::HttpsState;
|
|||
use num_traits::ToPrimitive;
|
||||
use script_layout_interface::message::{Msg, ReflowQueryType};
|
||||
use script_runtime::{CommonScriptMsg, ScriptThreadEventCategory};
|
||||
use script_thread::{MainThreadScriptMsg, Runnable, ScriptThread};
|
||||
use script_thread::{MainThreadScriptMsg, ScriptThread};
|
||||
use script_traits::{AnimationState, CompositorEvent, DocumentActivity};
|
||||
use script_traits::{MouseButton, MouseEventType, MozBrowserEvent};
|
||||
use script_traits::{MsDuration, ScriptMsg, TouchpadPressurePhase};
|
||||
|
@ -1714,8 +1714,57 @@ impl Document {
|
|||
// The rest will ever run only once per document.
|
||||
// Step 7.
|
||||
debug!("Document loads are complete.");
|
||||
let handler = box DocumentProgressHandler::new(Trusted::new(self));
|
||||
self.window.dom_manipulation_task_source().queue(handler, self.window.upcast()).unwrap();
|
||||
let document = Trusted::new(self);
|
||||
self.window.dom_manipulation_task_source().queue(
|
||||
box task!(fire_load_event: move || {
|
||||
let document = document.root();
|
||||
let window = document.window();
|
||||
if !window.is_alive() {
|
||||
return;
|
||||
}
|
||||
|
||||
// Step 7.1.
|
||||
document.set_ready_state(DocumentReadyState::Complete);
|
||||
|
||||
// Step 7.2.
|
||||
if document.browsing_context().is_none() {
|
||||
return;
|
||||
}
|
||||
let event = Event::new(
|
||||
window.upcast(),
|
||||
atom!("load"),
|
||||
EventBubbles::DoesNotBubble,
|
||||
EventCancelable::NotCancelable,
|
||||
);
|
||||
event.set_trusted(true);
|
||||
|
||||
// http://w3c.github.io/navigation-timing/#widl-PerformanceNavigationTiming-loadEventStart
|
||||
update_with_current_time_ms(&document.load_event_start);
|
||||
|
||||
debug!("About to dispatch load for {:?}", document.url());
|
||||
// FIXME(nox): Why are errors silenced here?
|
||||
let _ = window.upcast::<EventTarget>().dispatch_event_with_target(
|
||||
document.upcast(),
|
||||
&event,
|
||||
);
|
||||
|
||||
// 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,
|
||||
);
|
||||
|
||||
document.notify_constellation_load();
|
||||
|
||||
if let Some(fragment) = document.url().fragment() {
|
||||
document.check_and_scroll_fragment(fragment);
|
||||
}
|
||||
}),
|
||||
self.window.upcast(),
|
||||
).unwrap();
|
||||
|
||||
// Step 8.
|
||||
// TODO: pageshow event.
|
||||
|
@ -2609,7 +2658,7 @@ impl Document {
|
|||
let trusted_pending = Trusted::new(pending);
|
||||
let trusted_promise = TrustedPromise::new(promise.clone());
|
||||
let handler = ElementPerformFullscreenEnter::new(trusted_pending, trusted_promise, error);
|
||||
let script_msg = CommonScriptMsg::RunnableMsg(ScriptThreadEventCategory::EnterFullscreen, handler);
|
||||
let script_msg = CommonScriptMsg::Task(ScriptThreadEventCategory::EnterFullscreen, handler);
|
||||
let msg = MainThreadScriptMsg::Common(script_msg);
|
||||
window.main_thread_script_chan().send(msg).unwrap();
|
||||
|
||||
|
@ -2641,7 +2690,7 @@ impl Document {
|
|||
let trusted_element = Trusted::new(element.r());
|
||||
let trusted_promise = TrustedPromise::new(promise.clone());
|
||||
let handler = ElementPerformFullscreenExit::new(trusted_element, trusted_promise);
|
||||
let script_msg = CommonScriptMsg::RunnableMsg(ScriptThreadEventCategory::ExitFullscreen, handler);
|
||||
let script_msg = CommonScriptMsg::Task(ScriptThreadEventCategory::ExitFullscreen, handler);
|
||||
let msg = MainThreadScriptMsg::Common(script_msg);
|
||||
window.main_thread_script_chan().send(msg).unwrap();
|
||||
|
||||
|
@ -3970,66 +4019,6 @@ pub fn determine_policy_for_token(token: &str) -> Option<ReferrerPolicy> {
|
|||
}
|
||||
}
|
||||
|
||||
pub struct DocumentProgressHandler {
|
||||
addr: Trusted<Document>
|
||||
}
|
||||
|
||||
impl DocumentProgressHandler {
|
||||
pub fn new(addr: Trusted<Document>) -> DocumentProgressHandler {
|
||||
DocumentProgressHandler {
|
||||
addr: addr
|
||||
}
|
||||
}
|
||||
|
||||
fn set_ready_state_complete(&self) {
|
||||
let document = self.addr.root();
|
||||
document.set_ready_state(DocumentReadyState::Complete);
|
||||
}
|
||||
|
||||
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"),
|
||||
EventBubbles::DoesNotBubble,
|
||||
EventCancelable::NotCancelable);
|
||||
let wintarget = window.upcast::<EventTarget>();
|
||||
event.set_trusted(true);
|
||||
|
||||
// http://w3c.github.io/navigation-timing/#widl-PerformanceNavigationTiming-loadEventStart
|
||||
update_with_current_time_ms(&document.load_event_start);
|
||||
|
||||
debug!("About to dispatch load for {:?}", document.url());
|
||||
let _ = wintarget.dispatch_event_with_target(document.upcast(), &event);
|
||||
|
||||
// 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);
|
||||
|
||||
document.notify_constellation_load();
|
||||
}
|
||||
}
|
||||
|
||||
impl Runnable for DocumentProgressHandler {
|
||||
fn handler(self: Box<DocumentProgressHandler>) {
|
||||
let document = self.addr.root();
|
||||
let window = document.window();
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Specifies the type of focus event that is sent to a pipeline
|
||||
#[derive(Clone, Copy, PartialEq)]
|
||||
pub enum FocusType {
|
||||
|
|
|
@ -87,7 +87,7 @@ use js::jsval::JSVal;
|
|||
use net_traits::request::CorsSettings;
|
||||
use ref_filter_map::ref_filter_map;
|
||||
use script_layout_interface::message::ReflowQueryType;
|
||||
use script_thread::{Runnable, ScriptThread};
|
||||
use script_thread::ScriptThread;
|
||||
use selectors::attr::{AttrSelectorOperation, NamespaceConstraint, CaseSensitivity};
|
||||
use selectors::matching::{ElementSelectorFlags, LocalMatchingContext, MatchingContext, MatchingMode};
|
||||
use selectors::matching::{HAS_EDGE_CHILD_SELECTOR, HAS_SLOW_SELECTOR, HAS_SLOW_SELECTOR_LATER_SIBLINGS};
|
||||
|
@ -119,6 +119,7 @@ use style::thread_state;
|
|||
use style::values::{CSSFloat, Either};
|
||||
use style::values::{specified, computed};
|
||||
use stylesheet_loader::StylesheetOwner;
|
||||
use task::Task;
|
||||
|
||||
// TODO: Update focus state when the top-level browsing context gains or loses system focus,
|
||||
// and when the element enters or leaves a browsing context container.
|
||||
|
@ -3046,9 +3047,9 @@ impl ElementPerformFullscreenEnter {
|
|||
}
|
||||
}
|
||||
|
||||
impl Runnable for ElementPerformFullscreenEnter {
|
||||
impl Task for ElementPerformFullscreenEnter {
|
||||
#[allow(unrooted_must_root)]
|
||||
fn handler(self: Box<ElementPerformFullscreenEnter>) {
|
||||
fn run(self: Box<Self>) {
|
||||
let element = self.element.root();
|
||||
let document = document_from_node(element.r());
|
||||
|
||||
|
@ -3099,9 +3100,9 @@ impl ElementPerformFullscreenExit {
|
|||
}
|
||||
}
|
||||
|
||||
impl Runnable for ElementPerformFullscreenExit {
|
||||
impl Task for ElementPerformFullscreenExit {
|
||||
#[allow(unrooted_must_root)]
|
||||
fn handler(self: Box<ElementPerformFullscreenExit>) {
|
||||
fn run(self: Box<Self>) {
|
||||
let element = self.element.root();
|
||||
let document = document_from_node(element.r());
|
||||
// TODO Step 9.1-5
|
||||
|
|
|
@ -20,10 +20,10 @@ use dom::node::Node;
|
|||
use dom::virtualmethods::vtable_for;
|
||||
use dom::window::Window;
|
||||
use dom_struct::dom_struct;
|
||||
use script_thread::Runnable;
|
||||
use servo_atoms::Atom;
|
||||
use std::cell::Cell;
|
||||
use std::default::Default;
|
||||
use task::Task;
|
||||
use time;
|
||||
|
||||
#[dom_struct]
|
||||
|
@ -381,15 +381,15 @@ pub enum EventStatus {
|
|||
}
|
||||
|
||||
// https://dom.spec.whatwg.org/#concept-event-fire
|
||||
pub struct EventRunnable {
|
||||
pub struct EventTask {
|
||||
pub target: Trusted<EventTarget>,
|
||||
pub name: Atom,
|
||||
pub bubbles: EventBubbles,
|
||||
pub cancelable: EventCancelable,
|
||||
}
|
||||
|
||||
impl Runnable for EventRunnable {
|
||||
fn handler(self: Box<EventRunnable>) {
|
||||
impl Task for EventTask {
|
||||
fn run(self: Box<Self>) {
|
||||
let target = self.target.root();
|
||||
let bubbles = self.bubbles;
|
||||
let cancelable = self.cancelable;
|
||||
|
@ -398,13 +398,13 @@ impl Runnable for EventRunnable {
|
|||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#fire-a-simple-event
|
||||
pub struct SimpleEventRunnable {
|
||||
pub struct SimpleEventTask {
|
||||
pub target: Trusted<EventTarget>,
|
||||
pub name: Atom,
|
||||
}
|
||||
|
||||
impl Runnable for SimpleEventRunnable {
|
||||
fn handler(self: Box<SimpleEventRunnable>) {
|
||||
impl Task for SimpleEventTask {
|
||||
fn run(self: Box<Self>) {
|
||||
let target = self.target.root();
|
||||
target.fire_event(self.name);
|
||||
}
|
||||
|
|
|
@ -27,7 +27,6 @@ use net_traits::{CoreResourceMsg, FetchMetadata, FetchResponseMsg, FetchResponse
|
|||
use net_traits::request::{CacheMode, CorsSettings, CredentialsMode};
|
||||
use net_traits::request::{RequestInit, RequestMode};
|
||||
use network_listener::{NetworkListener, PreInvoke};
|
||||
use script_thread::Runnable;
|
||||
use servo_atoms::Atom;
|
||||
use servo_url::ServoUrl;
|
||||
use std::cell::Cell;
|
||||
|
@ -91,26 +90,46 @@ struct EventSourceContext {
|
|||
}
|
||||
|
||||
impl EventSourceContext {
|
||||
/// https://html.spec.whatwg.org/multipage/#announce-the-connection
|
||||
fn announce_the_connection(&self) {
|
||||
let event_source = self.event_source.root();
|
||||
if self.gen_id != event_source.generation_id.get() {
|
||||
return;
|
||||
}
|
||||
let runnable = box AnnounceConnectionRunnable {
|
||||
event_source: self.event_source.clone()
|
||||
};
|
||||
let _ = event_source.global().networking_task_source().queue(runnable, &*event_source.global());
|
||||
let global = event_source.global();
|
||||
let event_source = self.event_source.clone();
|
||||
// FIXME(nox): Why are errors silenced here?
|
||||
let _ = global.networking_task_source().queue(
|
||||
box task!(announce_the_event_source_connection: move || {
|
||||
let event_source = event_source.root();
|
||||
if event_source.ready_state.get() != ReadyState::Closed {
|
||||
event_source.ready_state.set(ReadyState::Open);
|
||||
event_source.upcast::<EventTarget>().fire_event(atom!("open"));
|
||||
}
|
||||
}),
|
||||
&global,
|
||||
);
|
||||
}
|
||||
|
||||
/// https://html.spec.whatwg.org/multipage/#fail-the-connection
|
||||
fn fail_the_connection(&self) {
|
||||
let event_source = self.event_source.root();
|
||||
if self.gen_id != event_source.generation_id.get() {
|
||||
return;
|
||||
}
|
||||
let runnable = box FailConnectionRunnable {
|
||||
event_source: self.event_source.clone()
|
||||
};
|
||||
let _ = event_source.global().networking_task_source().queue(runnable, &*event_source.global());
|
||||
let global = event_source.global();
|
||||
let event_source = self.event_source.clone();
|
||||
// FIXME(nox): Why are errors silenced here?
|
||||
let _ = global.networking_task_source().queue(
|
||||
box task!(fail_the_event_source_connection: move || {
|
||||
let event_source = event_source.root();
|
||||
if event_source.ready_state.get() != ReadyState::Closed {
|
||||
event_source.ready_state.set(ReadyState::Closed);
|
||||
event_source.upcast::<EventTarget>().fire_event(atom!("error"));
|
||||
}
|
||||
}),
|
||||
&global,
|
||||
);
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#reestablish-the-connection
|
||||
|
@ -121,12 +140,43 @@ impl EventSourceContext {
|
|||
return;
|
||||
}
|
||||
|
||||
// Step 1
|
||||
let runnable = box ReestablishConnectionRunnable {
|
||||
event_source: self.event_source.clone(),
|
||||
action_sender: self.action_sender.clone()
|
||||
};
|
||||
let _ = event_source.global().networking_task_source().queue(runnable, &*event_source.global());
|
||||
let trusted_event_source = self.event_source.clone();
|
||||
let action_sender = self.action_sender.clone();
|
||||
let global = event_source.global();
|
||||
// FIXME(nox): Why are errors silenced here?
|
||||
let _ = global.networking_task_source().queue(
|
||||
box task!(reestablish_the_event_source_onnection: move || {
|
||||
let event_source = trusted_event_source.root();
|
||||
|
||||
// Step 1.1.
|
||||
if event_source.ready_state.get() == ReadyState::Closed {
|
||||
return;
|
||||
}
|
||||
|
||||
// Step 1.2.
|
||||
event_source.ready_state.set(ReadyState::Connecting);
|
||||
|
||||
// Step 1.3.
|
||||
event_source.upcast::<EventTarget>().fire_event(atom!("error"));
|
||||
|
||||
// Step 2.
|
||||
let duration = Length::new(event_source.reconnection_time.get());
|
||||
|
||||
// Step 3.
|
||||
// TODO: Optionally wait some more.
|
||||
|
||||
// Steps 4-5.
|
||||
let callback = OneshotTimerCallback::EventSourceTimeout(
|
||||
EventSourceTimeoutCallback {
|
||||
event_source: trusted_event_source,
|
||||
action_sender,
|
||||
}
|
||||
);
|
||||
// FIXME(nox): Why are errors silenced here?
|
||||
let _ = event_source.global().schedule_callback(callback, duration);
|
||||
}),
|
||||
&global,
|
||||
);
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#processField
|
||||
|
@ -185,12 +235,21 @@ impl EventSourceContext {
|
|||
// Step 7
|
||||
self.event_type.clear();
|
||||
self.data.clear();
|
||||
// Step 8
|
||||
let runnable = box DispatchEventRunnable {
|
||||
event_source: self.event_source.clone(),
|
||||
event: Trusted::new(&event)
|
||||
};
|
||||
let _ = event_source.global().networking_task_source().queue(runnable, &*event_source.global());
|
||||
|
||||
// Step 8.
|
||||
let global = event_source.global();
|
||||
let event_source = self.event_source.clone();
|
||||
let event = Trusted::new(&*event);
|
||||
// FIXME(nox): Why are errors silenced here?
|
||||
let _ = global.networking_task_source().queue(
|
||||
box task!(dispatch_the_event_source_event: move || {
|
||||
let event_source = event_source.root();
|
||||
if event_source.ready_state.get() != ReadyState::Closed {
|
||||
event.root().upcast::<Event>().fire(&event_source.upcast());
|
||||
}
|
||||
}),
|
||||
&global,
|
||||
);
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#event-stream-interpretation
|
||||
|
@ -425,7 +484,7 @@ impl EventSource {
|
|||
let listener = NetworkListener {
|
||||
context: Arc::new(Mutex::new(context)),
|
||||
task_source: global.networking_task_source(),
|
||||
wrapper: Some(global.get_runnable_wrapper())
|
||||
canceller: Some(global.task_canceller())
|
||||
};
|
||||
ROUTER.add_route(action_receiver.to_opaque(), box move |message| {
|
||||
listener.notify_fetch(message.to().unwrap());
|
||||
|
@ -469,65 +528,6 @@ impl EventSourceMethods for EventSource {
|
|||
}
|
||||
}
|
||||
|
||||
pub struct AnnounceConnectionRunnable {
|
||||
event_source: Trusted<EventSource>,
|
||||
}
|
||||
|
||||
impl Runnable for AnnounceConnectionRunnable {
|
||||
// https://html.spec.whatwg.org/multipage/#announce-the-connection
|
||||
fn handler(self: Box<AnnounceConnectionRunnable>) {
|
||||
let event_source = self.event_source.root();
|
||||
if event_source.ready_state.get() != ReadyState::Closed {
|
||||
event_source.ready_state.set(ReadyState::Open);
|
||||
event_source.upcast::<EventTarget>().fire_event(atom!("open"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct FailConnectionRunnable {
|
||||
event_source: Trusted<EventSource>,
|
||||
}
|
||||
|
||||
impl Runnable for FailConnectionRunnable {
|
||||
// https://html.spec.whatwg.org/multipage/#fail-the-connection
|
||||
fn handler(self: Box<FailConnectionRunnable>) {
|
||||
let event_source = self.event_source.root();
|
||||
if event_source.ready_state.get() != ReadyState::Closed {
|
||||
event_source.ready_state.set(ReadyState::Closed);
|
||||
event_source.upcast::<EventTarget>().fire_event(atom!("error"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ReestablishConnectionRunnable {
|
||||
event_source: Trusted<EventSource>,
|
||||
action_sender: ipc::IpcSender<FetchResponseMsg>,
|
||||
}
|
||||
|
||||
impl Runnable for ReestablishConnectionRunnable {
|
||||
// https://html.spec.whatwg.org/multipage/#reestablish-the-connection
|
||||
fn handler(self: Box<ReestablishConnectionRunnable>) {
|
||||
let event_source = self.event_source.root();
|
||||
// Step 1.1
|
||||
if event_source.ready_state.get() == ReadyState::Closed {
|
||||
return;
|
||||
}
|
||||
// Step 1.2
|
||||
event_source.ready_state.set(ReadyState::Connecting);
|
||||
// Step 1.3
|
||||
event_source.upcast::<EventTarget>().fire_event(atom!("error"));
|
||||
// Step 2
|
||||
let duration = Length::new(event_source.reconnection_time.get());
|
||||
// TODO Step 3: Optionally wait some more
|
||||
// Steps 4-5
|
||||
let callback = OneshotTimerCallback::EventSourceTimeout(EventSourceTimeoutCallback {
|
||||
event_source: self.event_source.clone(),
|
||||
action_sender: self.action_sender.clone()
|
||||
});
|
||||
let _ = event_source.global().schedule_callback(callback, duration);
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(HeapSizeOf, JSTraceable)]
|
||||
pub struct EventSourceTimeoutCallback {
|
||||
#[ignore_heap_size_of = "Because it is non-owning"]
|
||||
|
@ -555,19 +555,3 @@ impl EventSourceTimeoutCallback {
|
|||
global.core_resource_thread().send(CoreResourceMsg::Fetch(request, self.action_sender)).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
pub struct DispatchEventRunnable {
|
||||
event_source: Trusted<EventSource>,
|
||||
event: Trusted<MessageEvent>,
|
||||
}
|
||||
|
||||
impl Runnable for DispatchEventRunnable {
|
||||
// https://html.spec.whatwg.org/multipage/#dispatchMessage
|
||||
fn handler(self: Box<DispatchEventRunnable>) {
|
||||
let event_source = self.event_source.root();
|
||||
// Step 8
|
||||
if event_source.ready_state.get() != ReadyState::Closed {
|
||||
self.event.root().upcast::<Event>().fire(&event_source.upcast());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,14 +29,14 @@ use js::jsapi::JSAutoCompartment;
|
|||
use js::jsapi::JSContext;
|
||||
use js::jsval::{self, JSVal};
|
||||
use js::typedarray::{ArrayBuffer, CreateWith};
|
||||
use script_thread::RunnableWrapper;
|
||||
use servo_atoms::Atom;
|
||||
use std::cell::Cell;
|
||||
use std::ptr;
|
||||
use std::sync::Arc;
|
||||
use std::thread;
|
||||
use task::TaskCanceller;
|
||||
use task_source::TaskSource;
|
||||
use task_source::file_reading::{FileReadingTaskSource, FileReadingRunnable, FileReadingTask};
|
||||
use task_source::file_reading::{FileReadingTask, FileReadingTaskSource};
|
||||
|
||||
#[derive(Clone, Copy, HeapSizeOf, JSTraceable, PartialEq)]
|
||||
pub enum FileReaderFunction {
|
||||
|
@ -383,11 +383,18 @@ impl FileReader {
|
|||
let gen_id = self.generation_id.get();
|
||||
|
||||
let global = self.global();
|
||||
let wrapper = global.get_runnable_wrapper();
|
||||
let canceller = global.task_canceller();
|
||||
let task_source = global.file_reading_task_source();
|
||||
|
||||
thread::Builder::new().name("file reader async operation".to_owned()).spawn(move || {
|
||||
perform_annotated_read_operation(gen_id, load_data, blob_contents, fr, task_source, wrapper)
|
||||
perform_annotated_read_operation(
|
||||
gen_id,
|
||||
load_data,
|
||||
blob_contents,
|
||||
fr,
|
||||
task_source,
|
||||
canceller,
|
||||
)
|
||||
}).expect("Thread spawning failed");
|
||||
|
||||
Ok(())
|
||||
|
@ -399,19 +406,21 @@ impl FileReader {
|
|||
}
|
||||
|
||||
// https://w3c.github.io/FileAPI/#thread-read-operation
|
||||
fn perform_annotated_read_operation(gen_id: GenerationId,
|
||||
data: ReadMetaData,
|
||||
blob_contents: Arc<Vec<u8>>,
|
||||
filereader: TrustedFileReader,
|
||||
task_source: FileReadingTaskSource,
|
||||
wrapper: RunnableWrapper) {
|
||||
fn perform_annotated_read_operation(
|
||||
gen_id: GenerationId,
|
||||
data: ReadMetaData,
|
||||
blob_contents: Arc<Vec<u8>>,
|
||||
filereader: TrustedFileReader,
|
||||
task_source: FileReadingTaskSource,
|
||||
canceller: TaskCanceller,
|
||||
) {
|
||||
// Step 4
|
||||
let task = FileReadingRunnable::new(FileReadingTask::ProcessRead(filereader.clone(), gen_id));
|
||||
task_source.queue_with_wrapper(task, &wrapper).unwrap();
|
||||
let task = FileReadingTask::ProcessRead(filereader.clone(), gen_id);
|
||||
task_source.queue_with_canceller(box task, &canceller).unwrap();
|
||||
|
||||
let task = FileReadingRunnable::new(FileReadingTask::ProcessReadData(filereader.clone(), gen_id));
|
||||
task_source.queue_with_wrapper(task, &wrapper).unwrap();
|
||||
let task = FileReadingTask::ProcessReadData(filereader.clone(), gen_id);
|
||||
task_source.queue_with_canceller(box task, &canceller).unwrap();
|
||||
|
||||
let task = FileReadingRunnable::new(FileReadingTask::ProcessReadEOF(filereader, gen_id, data, blob_contents));
|
||||
task_source.queue_with_wrapper(task, &wrapper).unwrap();
|
||||
let task = FileReadingTask::ProcessReadEOF(filereader, gen_id, data, blob_contents);
|
||||
task_source.queue_with_canceller(box task, &canceller).unwrap();
|
||||
}
|
||||
|
|
|
@ -38,7 +38,7 @@ use msg::constellation_msg::PipelineId;
|
|||
use net_traits::{CoreResourceThread, ResourceThreads, IpcSend};
|
||||
use profile_traits::{mem, time};
|
||||
use script_runtime::{CommonScriptMsg, ScriptChan, ScriptPort};
|
||||
use script_thread::{MainThreadScriptChan, RunnableWrapper, ScriptThread};
|
||||
use script_thread::{MainThreadScriptChan, ScriptThread};
|
||||
use script_traits::{MsDuration, ScriptToConstellationChan, TimerEvent};
|
||||
use script_traits::{TimerEventId, TimerSchedulerMsg, TimerSource};
|
||||
use servo_url::{MutableOrigin, ServoUrl};
|
||||
|
@ -47,6 +47,7 @@ use std::collections::HashMap;
|
|||
use std::collections::hash_map::Entry;
|
||||
use std::ffi::CString;
|
||||
use std::rc::Rc;
|
||||
use task::TaskCanceller;
|
||||
use task_source::file_reading::FileReadingTaskSource;
|
||||
use task_source::networking::NetworkingTaskSource;
|
||||
use task_source::performance_timeline::PerformanceTimelineTaskSource;
|
||||
|
@ -312,30 +313,34 @@ impl GlobalScope {
|
|||
// Step 2.
|
||||
self.in_error_reporting_mode.set(true);
|
||||
|
||||
// Steps 3-12.
|
||||
// Steps 3-6.
|
||||
// FIXME(#13195): muted errors.
|
||||
let event = ErrorEvent::new(self,
|
||||
atom!("error"),
|
||||
EventBubbles::DoesNotBubble,
|
||||
EventCancelable::Cancelable,
|
||||
error_info.message.as_str().into(),
|
||||
error_info.filename.as_str().into(),
|
||||
error_info.lineno,
|
||||
error_info.column,
|
||||
value);
|
||||
let event = ErrorEvent::new(
|
||||
self,
|
||||
atom!("error"),
|
||||
EventBubbles::DoesNotBubble,
|
||||
EventCancelable::Cancelable,
|
||||
error_info.message.as_str().into(),
|
||||
error_info.filename.as_str().into(),
|
||||
error_info.lineno,
|
||||
error_info.column,
|
||||
value,
|
||||
);
|
||||
|
||||
// Step 13.
|
||||
// Step 7.
|
||||
let event_status = event.upcast::<Event>().fire(self.upcast::<EventTarget>());
|
||||
|
||||
// Step 15
|
||||
// Step 8.
|
||||
self.in_error_reporting_mode.set(false);
|
||||
|
||||
// Step 9.
|
||||
if event_status == EventStatus::NotCanceled {
|
||||
// https://html.spec.whatwg.org/multipage/#runtime-script-errors-2
|
||||
if let Some(dedicated) = self.downcast::<DedicatedWorkerGlobalScope>() {
|
||||
dedicated.forward_error_to_worker_object(error_info);
|
||||
}
|
||||
}
|
||||
|
||||
// Step 14
|
||||
self.in_error_reporting_mode.set(false);
|
||||
}
|
||||
|
||||
/// Get the `&ResourceThreads` for this global scope.
|
||||
|
@ -477,14 +482,14 @@ impl GlobalScope {
|
|||
unreachable!();
|
||||
}
|
||||
|
||||
/// Returns a wrapper for runnables to ensure they are cancelled if
|
||||
/// the global scope is being destroyed.
|
||||
pub fn get_runnable_wrapper(&self) -> RunnableWrapper {
|
||||
/// Returns the task canceller of this global to ensure that everything is
|
||||
/// properly cancelled when the global scope is destroyed.
|
||||
pub fn task_canceller(&self) -> TaskCanceller {
|
||||
if let Some(window) = self.downcast::<Window>() {
|
||||
return window.get_runnable_wrapper();
|
||||
return window.task_canceller();
|
||||
}
|
||||
if let Some(worker) = self.downcast::<WorkerGlobalScope>() {
|
||||
return worker.get_runnable_wrapper();
|
||||
return worker.task_canceller();
|
||||
}
|
||||
unreachable!();
|
||||
}
|
||||
|
|
|
@ -16,7 +16,6 @@ use dom::node::{Node, window_from_node};
|
|||
use dom::virtualmethods::VirtualMethods;
|
||||
use dom_struct::dom_struct;
|
||||
use html5ever::{LocalName, Prefix};
|
||||
use script_thread::Runnable;
|
||||
use std::cell::Cell;
|
||||
use task_source::TaskSource;
|
||||
|
||||
|
@ -45,10 +44,6 @@ impl HTMLDetailsElement {
|
|||
document,
|
||||
HTMLDetailsElementBinding::Wrap)
|
||||
}
|
||||
|
||||
pub fn check_toggle_count(&self, number: u32) -> bool {
|
||||
number == self.toggle_counter.get()
|
||||
}
|
||||
}
|
||||
|
||||
impl HTMLDetailsElementMethods for HTMLDetailsElement {
|
||||
|
@ -72,27 +67,17 @@ impl VirtualMethods for HTMLDetailsElement {
|
|||
self.toggle_counter.set(counter);
|
||||
|
||||
let window = window_from_node(self);
|
||||
let task_source = window.dom_manipulation_task_source();
|
||||
let details = Trusted::new(self);
|
||||
let runnable = box DetailsNotificationRunnable {
|
||||
element: details,
|
||||
toggle_number: counter
|
||||
};
|
||||
let _ = task_source.queue(runnable, window.upcast());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct DetailsNotificationRunnable {
|
||||
element: Trusted<HTMLDetailsElement>,
|
||||
toggle_number: u32
|
||||
}
|
||||
|
||||
impl Runnable for DetailsNotificationRunnable {
|
||||
fn handler(self: Box<DetailsNotificationRunnable>) {
|
||||
let target = self.element.root();
|
||||
if target.check_toggle_count(self.toggle_number) {
|
||||
target.upcast::<EventTarget>().fire_event(atom!("toggle"));
|
||||
let this = Trusted::new(self);
|
||||
// FIXME(nox): Why are errors silenced here?
|
||||
let _ = window.dom_manipulation_task_source().queue(
|
||||
box task!(details_notification_task_steps: move || {
|
||||
let this = this.root();
|
||||
if counter == this.toggle_counter.get() {
|
||||
this.upcast::<EventTarget>().fire_event(atom!("toggle"));
|
||||
}
|
||||
}),
|
||||
window.upcast(),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -48,13 +48,11 @@ use encoding::label::encoding_from_whatwg_label;
|
|||
use html5ever::{LocalName, Prefix};
|
||||
use hyper::header::{Charset, ContentDisposition, ContentType, DispositionParam, DispositionType};
|
||||
use hyper::method::Method;
|
||||
use msg::constellation_msg::PipelineId;
|
||||
use script_thread::{MainThreadScriptMsg, Runnable};
|
||||
use script_thread::MainThreadScriptMsg;
|
||||
use script_traits::LoadData;
|
||||
use servo_rand::random;
|
||||
use std::borrow::ToOwned;
|
||||
use std::cell::Cell;
|
||||
use std::sync::mpsc::Sender;
|
||||
use style::attr::AttrValue;
|
||||
use style::str::split_html_space_chars;
|
||||
use task_source::TaskSource;
|
||||
|
@ -432,23 +430,29 @@ impl HTMLFormElement {
|
|||
let window = window_from_node(self);
|
||||
|
||||
// Step 1
|
||||
// Each planned navigation runnable is tagged with a generation ID, and
|
||||
// before the runnable is handled, it first checks whether the HTMLFormElement's
|
||||
// Each planned navigation task is tagged with a generation ID, and
|
||||
// before the task is handled, it first checks whether the HTMLFormElement's
|
||||
// generation ID is the same as its own generation ID.
|
||||
let GenerationId(prev_id) = self.generation_id.get();
|
||||
self.generation_id.set(GenerationId(prev_id + 1));
|
||||
let generation_id = GenerationId(self.generation_id.get().0 + 1);
|
||||
self.generation_id.set(generation_id);
|
||||
|
||||
// Step 2
|
||||
let nav = box PlannedNavigation {
|
||||
load_data: load_data,
|
||||
pipeline_id: window.upcast::<GlobalScope>().pipeline_id(),
|
||||
script_chan: window.main_thread_script_chan().clone(),
|
||||
generation_id: self.generation_id.get(),
|
||||
form: Trusted::new(self)
|
||||
};
|
||||
// Step 2.
|
||||
let pipeline_id = window.upcast::<GlobalScope>().pipeline_id();
|
||||
let script_chan = window.main_thread_script_chan().clone();
|
||||
let this = Trusted::new(self);
|
||||
let task = box task!(navigate_to_form_planned_navigation: move || {
|
||||
if generation_id != this.root().generation_id.get() {
|
||||
return;
|
||||
}
|
||||
script_chan.send(MainThreadScriptMsg::Navigate(
|
||||
pipeline_id,
|
||||
load_data,
|
||||
false,
|
||||
)).unwrap();
|
||||
});
|
||||
|
||||
// Step 3
|
||||
window.dom_manipulation_task_source().queue(nav, window.upcast()).unwrap();
|
||||
// Step 3.
|
||||
window.dom_manipulation_task_source().queue(task, window.upcast()).unwrap();
|
||||
}
|
||||
|
||||
/// Interactively validate the constraints of form elements
|
||||
|
@ -1107,24 +1111,6 @@ impl FormControlElementHelpers for Element {
|
|||
}
|
||||
}
|
||||
|
||||
struct PlannedNavigation {
|
||||
load_data: LoadData,
|
||||
pipeline_id: PipelineId,
|
||||
script_chan: Sender<MainThreadScriptMsg>,
|
||||
generation_id: GenerationId,
|
||||
form: Trusted<HTMLFormElement>
|
||||
}
|
||||
|
||||
impl Runnable for PlannedNavigation {
|
||||
fn handler(self: Box<PlannedNavigation>) {
|
||||
if self.generation_id == self.form.root().generation_id.get() {
|
||||
let script_chan = self.script_chan.clone();
|
||||
script_chan.send(MainThreadScriptMsg::Navigate(self.pipeline_id, self.load_data, false)).unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#multipart/form-data-encoding-algorithm
|
||||
pub fn encode_multipart_form_data(form_data: &mut Vec<FormDatum>,
|
||||
boundary: String, encoding: EncodingRef) -> Vec<u8> {
|
||||
|
|
|
@ -43,7 +43,7 @@ use js::jsval::{NullValue, UndefinedValue};
|
|||
use msg::constellation_msg::{FrameType, BrowsingContextId, PipelineId, TopLevelBrowsingContextId, TraversalDirection};
|
||||
use net_traits::response::HttpsState;
|
||||
use script_layout_interface::message::ReflowQueryType;
|
||||
use script_thread::{ScriptThread, Runnable};
|
||||
use script_thread::ScriptThread;
|
||||
use script_traits::{IFrameLoadInfo, IFrameLoadInfoWithData, JsEvalResult, LoadData, UpdatePipelineIdReason};
|
||||
use script_traits::{MozBrowserEvent, NewLayoutInfo, ScriptMsg};
|
||||
use script_traits::IFrameSandboxState::{IFrameSandboxed, IFrameUnsandboxed};
|
||||
|
@ -232,9 +232,15 @@ impl HTMLIFrameElement {
|
|||
|
||||
// https://github.com/whatwg/html/issues/490
|
||||
if mode == ProcessingMode::FirstTime && !self.upcast::<Element>().has_attribute(&local_name!("src")) {
|
||||
let event_loop = window.dom_manipulation_task_source();
|
||||
let _ = event_loop.queue(box IFrameLoadEventSteps::new(self),
|
||||
window.upcast());
|
||||
let this = Trusted::new(self);
|
||||
let pipeline_id = self.pipeline_id().unwrap();
|
||||
// FIXME(nox): Why are errors silenced here?
|
||||
let _ = window.dom_manipulation_task_source().queue(
|
||||
box task!(iframe_load_event_steps: move || {
|
||||
this.root().iframe_load_event_steps(pipeline_id);
|
||||
}),
|
||||
window.upcast(),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -834,24 +840,3 @@ impl VirtualMethods for HTMLIFrameElement {
|
|||
self.destroy_nested_browsing_context();
|
||||
}
|
||||
}
|
||||
|
||||
struct IFrameLoadEventSteps {
|
||||
frame_element: Trusted<HTMLIFrameElement>,
|
||||
pipeline_id: PipelineId,
|
||||
}
|
||||
|
||||
impl IFrameLoadEventSteps {
|
||||
fn new(frame_element: &HTMLIFrameElement) -> IFrameLoadEventSteps {
|
||||
IFrameLoadEventSteps {
|
||||
frame_element: Trusted::new(frame_element),
|
||||
pipeline_id: frame_element.pipeline_id().unwrap(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Runnable for IFrameLoadEventSteps {
|
||||
fn handler(self: Box<IFrameLoadEventSteps>) {
|
||||
let this = self.frame_element.root();
|
||||
this.iframe_load_event_steps(self.pipeline_id);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -48,7 +48,7 @@ use net_traits::image_cache::UsePlaceholder;
|
|||
use net_traits::request::{RequestInit, Type as RequestType};
|
||||
use network_listener::{NetworkListener, PreInvoke};
|
||||
use num_traits::ToPrimitive;
|
||||
use script_thread::{Runnable, ScriptThread};
|
||||
use script_thread::ScriptThread;
|
||||
use servo_url::ServoUrl;
|
||||
use servo_url::origin::ImmutableOrigin;
|
||||
use std::cell::{Cell, RefMut};
|
||||
|
@ -99,33 +99,6 @@ impl HTMLImageElement {
|
|||
}
|
||||
}
|
||||
|
||||
struct ImageResponseHandlerRunnable {
|
||||
element: Trusted<HTMLImageElement>,
|
||||
image: ImageResponse,
|
||||
generation: u32,
|
||||
}
|
||||
|
||||
impl ImageResponseHandlerRunnable {
|
||||
fn new(element: Trusted<HTMLImageElement>, image: ImageResponse, generation: u32)
|
||||
-> ImageResponseHandlerRunnable {
|
||||
ImageResponseHandlerRunnable {
|
||||
element: element,
|
||||
image: image,
|
||||
generation: generation,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Runnable for ImageResponseHandlerRunnable {
|
||||
fn handler(self: Box<Self>) {
|
||||
let element = self.element.root();
|
||||
// Ignore any image response for a previous request that has been discarded.
|
||||
if element.generation.get() == self.generation {
|
||||
element.process_image_response(self.image);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The context required for asynchronously loading an external image.
|
||||
struct ImageContext {
|
||||
/// Reference to the script thread image cache.
|
||||
|
@ -191,15 +164,25 @@ impl HTMLImageElement {
|
|||
|
||||
let window = window_from_node(elem);
|
||||
let task_source = window.networking_task_source();
|
||||
let wrapper = window.get_runnable_wrapper();
|
||||
let task_canceller = window.task_canceller();
|
||||
let generation = elem.generation.get();
|
||||
ROUTER.add_route(responder_receiver.to_opaque(), box move |message| {
|
||||
debug!("Got image {:?}", message);
|
||||
// Return the image via a message to the script thread, which marks
|
||||
// the element as dirty and triggers a reflow.
|
||||
let runnable = ImageResponseHandlerRunnable::new(
|
||||
trusted_node.clone(), message.to().unwrap(), generation);
|
||||
let _ = task_source.queue_with_wrapper(box runnable, &wrapper);
|
||||
let element = trusted_node.clone();
|
||||
let image = message.to().unwrap();
|
||||
// FIXME(nox): Why are errors silenced here?
|
||||
let _ = task_source.queue_with_canceller(
|
||||
box task!(process_image_response: move || {
|
||||
let element = element.root();
|
||||
// Ignore any image response for a previous request that has been discarded.
|
||||
if generation == element.generation.get() {
|
||||
element.process_image_response(image);
|
||||
}
|
||||
}),
|
||||
&task_canceller,
|
||||
);
|
||||
});
|
||||
|
||||
image_cache.add_listener(id, ImageResponder::new(responder_sender, id));
|
||||
|
@ -249,7 +232,7 @@ impl HTMLImageElement {
|
|||
let listener = NetworkListener {
|
||||
context: context,
|
||||
task_source: window.networking_task_source(),
|
||||
wrapper: Some(window.get_runnable_wrapper()),
|
||||
canceller: Some(window.task_canceller()),
|
||||
};
|
||||
ROUTER.add_route(action_receiver.to_opaque(), box move |message| {
|
||||
listener.notify_fetch(message.to().unwrap());
|
||||
|
@ -352,58 +335,6 @@ impl HTMLImageElement {
|
|||
request.metadata = None;
|
||||
}
|
||||
|
||||
/// Step 11.4 of https://html.spec.whatwg.org/multipage/#update-the-image-data
|
||||
fn set_current_request_url_to_selected_fire_error_and_loadend(&self, src: DOMString) {
|
||||
struct Task {
|
||||
img: Trusted<HTMLImageElement>,
|
||||
src: String,
|
||||
}
|
||||
impl Runnable for Task {
|
||||
fn handler(self: Box<Self>) {
|
||||
let img = self.img.root();
|
||||
{
|
||||
let mut current_request = img.current_request.borrow_mut();
|
||||
current_request.source_url = Some(DOMString::from_string(self.src));
|
||||
}
|
||||
img.upcast::<EventTarget>().fire_event(atom!("error"));
|
||||
img.upcast::<EventTarget>().fire_event(atom!("loadend"));
|
||||
img.abort_request(State::Broken, ImageRequestPhase::Current);
|
||||
img.abort_request(State::Broken, ImageRequestPhase::Pending);
|
||||
}
|
||||
}
|
||||
|
||||
let task = box Task {
|
||||
img: Trusted::new(self),
|
||||
src: src.into()
|
||||
};
|
||||
let document = document_from_node(self);
|
||||
let window = document.window();
|
||||
let task_source = window.dom_manipulation_task_source();
|
||||
let _ = task_source.queue(task, window.upcast());
|
||||
}
|
||||
|
||||
/// Step 10 of html.spec.whatwg.org/multipage/#update-the-image-data
|
||||
fn dispatch_loadstart_progress_event(&self) {
|
||||
struct FireprogressEventTask {
|
||||
img: Trusted<HTMLImageElement>,
|
||||
}
|
||||
impl Runnable for FireprogressEventTask {
|
||||
fn handler(self: Box<Self>) {
|
||||
let progressevent = ProgressEvent::new(&self.img.root().global(),
|
||||
atom!("loadstart"), EventBubbles::DoesNotBubble, EventCancelable::NotCancelable,
|
||||
false, 0, 0);
|
||||
progressevent.upcast::<Event>().fire(self.img.root().upcast());
|
||||
}
|
||||
}
|
||||
let runnable = box FireprogressEventTask {
|
||||
img: Trusted::new(self),
|
||||
};
|
||||
let document = document_from_node(self);
|
||||
let window = document.window();
|
||||
let task = window.dom_manipulation_task_source();
|
||||
let _ = task.queue(runnable, window.upcast());
|
||||
}
|
||||
|
||||
/// https://html.spec.whatwg.org/multipage/#update-the-source-set
|
||||
fn update_source_set(&self) -> Vec<DOMString> {
|
||||
let elem = self.upcast::<Element>();
|
||||
|
@ -421,67 +352,6 @@ impl HTMLImageElement {
|
|||
self.update_source_set().first().cloned()
|
||||
}
|
||||
|
||||
/// Step 9.2 of https://html.spec.whatwg.org/multipage/#update-the-image-data
|
||||
fn set_current_request_url_to_none_fire_error(&self) {
|
||||
struct SetUrlToNoneTask {
|
||||
img: Trusted<HTMLImageElement>,
|
||||
}
|
||||
impl Runnable for SetUrlToNoneTask {
|
||||
fn handler(self: Box<Self>) {
|
||||
let img = self.img.root();
|
||||
{
|
||||
let mut current_request = img.current_request.borrow_mut();
|
||||
current_request.source_url = None;
|
||||
current_request.parsed_url = None;
|
||||
}
|
||||
let elem = img.upcast::<Element>();
|
||||
if elem.has_attribute(&local_name!("src")) {
|
||||
img.upcast::<EventTarget>().fire_event(atom!("error"));
|
||||
}
|
||||
img.abort_request(State::Broken, ImageRequestPhase::Current);
|
||||
img.abort_request(State::Broken, ImageRequestPhase::Pending);
|
||||
}
|
||||
}
|
||||
|
||||
let task = box SetUrlToNoneTask {
|
||||
img: Trusted::new(self),
|
||||
};
|
||||
let document = document_from_node(self);
|
||||
let window = document.window();
|
||||
let task_source = window.dom_manipulation_task_source();
|
||||
let _ = task_source.queue(task, window.upcast());
|
||||
}
|
||||
|
||||
/// Step 5.3.7 of https://html.spec.whatwg.org/multipage/#update-the-image-data
|
||||
fn set_current_request_url_to_string_and_fire_load(&self, src: DOMString, url: ServoUrl) {
|
||||
struct SetUrlToStringTask {
|
||||
img: Trusted<HTMLImageElement>,
|
||||
src: String,
|
||||
url: ServoUrl
|
||||
}
|
||||
impl Runnable for SetUrlToStringTask {
|
||||
fn handler(self: Box<Self>) {
|
||||
let img = self.img.root();
|
||||
{
|
||||
let mut current_request = img.current_request.borrow_mut();
|
||||
current_request.parsed_url = Some(self.url.clone());
|
||||
current_request.source_url = Some(self.src.into());
|
||||
}
|
||||
// TODO: restart animation, if set
|
||||
img.upcast::<EventTarget>().fire_event(atom!("load"));
|
||||
}
|
||||
}
|
||||
let runnable = box SetUrlToStringTask {
|
||||
img: Trusted::new(self),
|
||||
src: src.into(),
|
||||
url: url
|
||||
};
|
||||
let document = document_from_node(self);
|
||||
let window = document.window();
|
||||
let task = window.dom_manipulation_task_source();
|
||||
let _ = task.queue(runnable, window.upcast());
|
||||
}
|
||||
|
||||
fn init_image_request(&self,
|
||||
request: &mut RefMut<ImageRequest>,
|
||||
url: &ServoUrl,
|
||||
|
@ -542,30 +412,93 @@ impl HTMLImageElement {
|
|||
/// Step 8-12 of html.spec.whatwg.org/multipage/#update-the-image-data
|
||||
fn update_the_image_data_sync_steps(&self) {
|
||||
let document = document_from_node(self);
|
||||
// Step 8
|
||||
// TODO: take pixel density into account
|
||||
match self.select_image_source() {
|
||||
let window = document.window();
|
||||
let task_source = window.dom_manipulation_task_source();
|
||||
let this = Trusted::new(self);
|
||||
let src = match self.select_image_source() {
|
||||
Some(src) => {
|
||||
// Step 10
|
||||
self.dispatch_loadstart_progress_event();
|
||||
// Step 11
|
||||
let base_url = document.base_url();
|
||||
let parsed_url = base_url.join(&src);
|
||||
match parsed_url {
|
||||
Ok(url) => {
|
||||
// Step 12
|
||||
self.prepare_image_request(&url, &src);
|
||||
},
|
||||
Err(_) => {
|
||||
// Step 11.1-11.5
|
||||
self.set_current_request_url_to_selected_fire_error_and_loadend(src);
|
||||
}
|
||||
}
|
||||
// Step 8.
|
||||
// TODO: Handle pixel density.
|
||||
src
|
||||
},
|
||||
None => {
|
||||
// Step 9
|
||||
self.set_current_request_url_to_none_fire_error();
|
||||
// Step 9.
|
||||
// FIXME(nox): Why are errors silenced here?
|
||||
let _ = task_source.queue(
|
||||
box task!(image_null_source_error: move || {
|
||||
let this = this.root();
|
||||
{
|
||||
let mut current_request =
|
||||
this.current_request.borrow_mut();
|
||||
current_request.source_url = None;
|
||||
current_request.parsed_url = None;
|
||||
}
|
||||
if this.upcast::<Element>().has_attribute(&local_name!("src")) {
|
||||
this.upcast::<EventTarget>().fire_event(atom!("error"));
|
||||
}
|
||||
// FIXME(nox): According to the spec, setting the current
|
||||
// request to the broken state is done prior to queuing a
|
||||
// task, why is this here?
|
||||
this.abort_request(State::Broken, ImageRequestPhase::Current);
|
||||
this.abort_request(State::Broken, ImageRequestPhase::Pending);
|
||||
}),
|
||||
window.upcast(),
|
||||
);
|
||||
return;
|
||||
},
|
||||
};
|
||||
// Step 10.
|
||||
let target = Trusted::new(self.upcast::<EventTarget>());
|
||||
// FIXME(nox): Why are errors silenced here?
|
||||
let _ = task_source.queue(
|
||||
box task!(fire_progress_event: move || {
|
||||
let target = target.root();
|
||||
|
||||
let event = ProgressEvent::new(
|
||||
&target.global(),
|
||||
atom!("loadstart"),
|
||||
EventBubbles::DoesNotBubble,
|
||||
EventCancelable::NotCancelable,
|
||||
false,
|
||||
0,
|
||||
0,
|
||||
);
|
||||
event.upcast::<Event>().fire(&target);
|
||||
}),
|
||||
window.upcast(),
|
||||
);
|
||||
// Step 11
|
||||
let base_url = document.base_url();
|
||||
let parsed_url = base_url.join(&src);
|
||||
match parsed_url {
|
||||
Ok(url) => {
|
||||
// Step 12
|
||||
self.prepare_image_request(&url, &src);
|
||||
},
|
||||
Err(_) => {
|
||||
// Step 11.1-11.5.
|
||||
let src = String::from(src);
|
||||
// FIXME(nox): Why are errors silenced here?
|
||||
let _ = task_source.queue(
|
||||
box task!(image_selected_source_error: move || {
|
||||
let this = this.root();
|
||||
{
|
||||
let mut current_request =
|
||||
this.current_request.borrow_mut();
|
||||
current_request.source_url = Some(src.into());
|
||||
}
|
||||
this.upcast::<EventTarget>().fire_event(atom!("error"));
|
||||
this.upcast::<EventTarget>().fire_event(atom!("loadend"));
|
||||
|
||||
// FIXME(nox): According to the spec, setting the current
|
||||
// request to the broken state is done prior to queuing a
|
||||
// task, why is this here?
|
||||
this.abort_request(State::Broken, ImageRequestPhase::Current);
|
||||
this.abort_request(State::Broken, ImageRequestPhase::Pending);
|
||||
}),
|
||||
window.upcast(),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -613,8 +546,23 @@ impl HTMLImageElement {
|
|||
current_request.final_url = Some(url);
|
||||
current_request.image = Some(image.clone());
|
||||
current_request.metadata = Some(metadata);
|
||||
self.set_current_request_url_to_string_and_fire_load(src, img_url);
|
||||
return
|
||||
let this = Trusted::new(self);
|
||||
let src = String::from(src);
|
||||
let _ = window.dom_manipulation_task_source().queue(
|
||||
box task!(image_load_event: move || {
|
||||
let this = this.root();
|
||||
{
|
||||
let mut current_request =
|
||||
this.current_request.borrow_mut();
|
||||
current_request.parsed_url = Some(img_url);
|
||||
current_request.source_url = Some(src.into());
|
||||
}
|
||||
// TODO: restart animation, if set.
|
||||
this.upcast::<EventTarget>().fire_event(atom!("load"));
|
||||
}),
|
||||
window.upcast(),
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,7 +35,7 @@ use microtask::{Microtask, MicrotaskRunnable};
|
|||
use net_traits::{FetchResponseListener, FetchMetadata, Metadata, NetworkError};
|
||||
use net_traits::request::{CredentialsMode, Destination, RequestInit, Type as RequestType};
|
||||
use network_listener::{NetworkListener, PreInvoke};
|
||||
use script_thread::{Runnable, ScriptThread};
|
||||
use script_thread::ScriptThread;
|
||||
use servo_url::ServoUrl;
|
||||
use std::cell::Cell;
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
@ -139,15 +139,11 @@ impl HTMLMediaElement {
|
|||
|
||||
// Step 2.3.
|
||||
let window = window_from_node(self);
|
||||
let target = Trusted::new(self.upcast::<EventTarget>());
|
||||
// FIXME(nox): Why are errors silenced here?
|
||||
let _ = window.dom_manipulation_task_source().queue(
|
||||
box InternalPauseStepsTask(Trusted::new(self.upcast())),
|
||||
window.upcast(),
|
||||
);
|
||||
struct InternalPauseStepsTask(Trusted<EventTarget>);
|
||||
impl Runnable for InternalPauseStepsTask {
|
||||
fn handler(self: Box<Self>) {
|
||||
let target = self.0.root();
|
||||
box task!(internal_pause_steps: move || {
|
||||
let target = target.root();
|
||||
|
||||
// Step 2.3.1.
|
||||
target.fire_event(atom!("timeupdate"));
|
||||
|
@ -158,8 +154,9 @@ impl HTMLMediaElement {
|
|||
// Step 2.3.3.
|
||||
// FIXME(nox): Reject pending play promises with promises
|
||||
// and an "AbortError" DOMException.
|
||||
}
|
||||
}
|
||||
}),
|
||||
window.upcast(),
|
||||
);
|
||||
|
||||
// Step 2.4.
|
||||
// FIXME(nox): Set the official playback position to the current
|
||||
|
@ -173,24 +170,21 @@ impl HTMLMediaElement {
|
|||
// TODO(nox): Take pending play promises and let promises be the result.
|
||||
|
||||
// Step 2.
|
||||
let target = Trusted::new(self.upcast::<EventTarget>());
|
||||
let window = window_from_node(self);
|
||||
// FIXME(nox): Why are errors silenced here?
|
||||
let _ = window.dom_manipulation_task_source().queue(
|
||||
box NotifyAboutPlayingTask(Trusted::new(self.upcast())),
|
||||
window.upcast(),
|
||||
);
|
||||
struct NotifyAboutPlayingTask(Trusted<EventTarget>);
|
||||
impl Runnable for NotifyAboutPlayingTask {
|
||||
fn handler(self: Box<Self>) {
|
||||
let target = self.0.root();
|
||||
box task!(notify_about_playing: move || {
|
||||
let target = target.root();
|
||||
|
||||
// Step 2.1.
|
||||
target.fire_event(atom!("playing"));
|
||||
|
||||
// Step 2.2.
|
||||
// FIXME(nox): Resolve pending play promises with promises.
|
||||
}
|
||||
}
|
||||
}),
|
||||
window.upcast(),
|
||||
);
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#ready-states
|
||||
|
@ -428,7 +422,7 @@ impl HTMLMediaElement {
|
|||
let listener = NetworkListener {
|
||||
context: context,
|
||||
task_source: window.networking_task_source(),
|
||||
wrapper: Some(window.get_runnable_wrapper())
|
||||
canceller: Some(window.task_canceller())
|
||||
};
|
||||
|
||||
ROUTER.add_route(action_receiver.to_opaque(), box move |message| {
|
||||
|
@ -466,30 +460,43 @@ impl HTMLMediaElement {
|
|||
}
|
||||
}
|
||||
|
||||
/// Queues the [dedicated media source failure steps][steps].
|
||||
///
|
||||
/// [steps]: https://html.spec.whatwg.org/multipage/#dedicated-media-source-failure-steps
|
||||
fn queue_dedicated_media_source_failure_steps(&self) {
|
||||
let this = Trusted::new(self);
|
||||
let window = window_from_node(self);
|
||||
// FIXME(nox): Why are errors silenced here?
|
||||
let _ = window.dom_manipulation_task_source().queue(
|
||||
box DedicatedMediaSourceFailureTask::new(self), window.upcast());
|
||||
}
|
||||
box task!(dedicated_media_source_failure_steps: move || {
|
||||
let this = this.root();
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dedicated-media-source-failure-steps
|
||||
fn dedicated_media_source_failure(&self) {
|
||||
// Step 1
|
||||
self.error.set(Some(&*MediaError::new(&*window_from_node(self),
|
||||
MEDIA_ERR_SRC_NOT_SUPPORTED)));
|
||||
// Step 1.
|
||||
this.error.set(Some(&*MediaError::new(
|
||||
&window_from_node(&*this),
|
||||
MEDIA_ERR_SRC_NOT_SUPPORTED,
|
||||
)));
|
||||
|
||||
// TODO step 2 (forget resource tracks)
|
||||
// Step 2.
|
||||
// FIXME(nox): Forget the media-resource-specific tracks.
|
||||
|
||||
// Step 3
|
||||
self.network_state.set(NetworkState::NoSource);
|
||||
// Step 3.
|
||||
this.network_state.set(NetworkState::NoSource);
|
||||
|
||||
// TODO step 4 (show poster)
|
||||
// Step 4.
|
||||
// FIXME(nox): Set show poster flag to true.
|
||||
|
||||
// Step 5
|
||||
self.upcast::<EventTarget>().fire_event(atom!("error"));
|
||||
// Step 5.
|
||||
this.upcast::<EventTarget>().fire_event(atom!("error"));
|
||||
|
||||
// TODO step 6 (resolve pending play promises)
|
||||
// TODO step 7 (delay load event)
|
||||
// Step 6.
|
||||
// FIXME(nox): Reject pending play promises.
|
||||
|
||||
// Step 7.
|
||||
// FIXME(nox): Set the delaying-the-load-event flag to false.
|
||||
}),
|
||||
window.upcast(),
|
||||
);
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#media-element-load-algorithm
|
||||
|
@ -738,24 +745,6 @@ impl MicrotaskRunnable for MediaElementMicrotask {
|
|||
}
|
||||
}
|
||||
|
||||
struct DedicatedMediaSourceFailureTask {
|
||||
elem: Trusted<HTMLMediaElement>,
|
||||
}
|
||||
|
||||
impl DedicatedMediaSourceFailureTask {
|
||||
fn new(elem: &HTMLMediaElement) -> DedicatedMediaSourceFailureTask {
|
||||
DedicatedMediaSourceFailureTask {
|
||||
elem: Trusted::new(elem),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Runnable for DedicatedMediaSourceFailureTask {
|
||||
fn handler(self: Box<DedicatedMediaSourceFailureTask>) {
|
||||
self.elem.root().dedicated_media_source_failure();
|
||||
}
|
||||
}
|
||||
|
||||
enum ResourceSelectionMode {
|
||||
Object,
|
||||
Attribute(String),
|
||||
|
|
|
@ -277,7 +277,7 @@ fn fetch_a_classic_script(script: &HTMLScriptElement,
|
|||
let listener = NetworkListener {
|
||||
context: context,
|
||||
task_source: doc.window().networking_task_source(),
|
||||
wrapper: Some(doc.window().get_runnable_wrapper())
|
||||
canceller: Some(doc.window().task_canceller())
|
||||
};
|
||||
|
||||
ROUTER.add_route(action_receiver.to_opaque(), box move |message| {
|
||||
|
|
|
@ -46,7 +46,6 @@ use js::rust::Runtime;
|
|||
use msg::constellation_msg::PipelineId;
|
||||
use net_traits::image::base::PixelFormat;
|
||||
use net_traits::image_cache::ImageCache;
|
||||
use script_layout_interface::message::Msg;
|
||||
use script_traits::DrawAPaintImageResult;
|
||||
use script_traits::Painter;
|
||||
use servo_atoms::Atom;
|
||||
|
@ -443,8 +442,7 @@ impl PaintWorkletGlobalScopeMethods for PaintWorkletGlobalScope {
|
|||
// Inform layout that there is a registered paint worklet.
|
||||
// TODO: layout will end up getting this message multiple times.
|
||||
let painter = self.painter(name.clone());
|
||||
let msg = Msg::RegisterPaint(name, properties, painter);
|
||||
self.worklet_global.send_to_layout(msg);
|
||||
self.worklet_global.register_paint_worklet(name, properties, painter);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -16,10 +16,10 @@ use dom::eventtarget::EventTarget;
|
|||
use dom::globalscope::GlobalScope;
|
||||
use dom_struct::dom_struct;
|
||||
use js::jsapi::{HandleValue, JSContext};
|
||||
use script_thread::Runnable;
|
||||
use script_traits::{ScriptMsg, DOMMessage};
|
||||
use servo_url::ServoUrl;
|
||||
use std::cell::Cell;
|
||||
use task::Task;
|
||||
|
||||
pub type TrustedServiceWorkerAddress = Trusted<ServiceWorker>;
|
||||
|
||||
|
@ -104,9 +104,9 @@ impl ServiceWorkerMethods for ServiceWorker {
|
|||
event_handler!(statechange, GetOnstatechange, SetOnstatechange);
|
||||
}
|
||||
|
||||
impl Runnable for SimpleWorkerErrorHandler<ServiceWorker> {
|
||||
impl Task for SimpleWorkerErrorHandler<ServiceWorker> {
|
||||
#[allow(unrooted_must_root)]
|
||||
fn handler(self: Box<SimpleWorkerErrorHandler<ServiceWorker>>) {
|
||||
fn run(self: Box<Self>) {
|
||||
let this = *self;
|
||||
ServiceWorker::dispatch_simple_error(this.addr);
|
||||
}
|
||||
|
|
|
@ -114,7 +114,7 @@ impl ServiceWorkerContainerMethods for ServiceWorkerContainer {
|
|||
|
||||
// B: Step 8
|
||||
let job = Job::create_job(JobType::Register, scope, script_url, promise.clone(), &*self.client);
|
||||
ScriptThread::schedule_job(job, &*self.global());
|
||||
ScriptThread::schedule_job(job);
|
||||
promise
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,7 +17,6 @@ use dom_struct::dom_struct;
|
|||
use ipc_channel::ipc::{self, IpcSender};
|
||||
use net_traits::IpcSend;
|
||||
use net_traits::storage_thread::{StorageThreadMsg, StorageType};
|
||||
use script_thread::{Runnable, ScriptThread};
|
||||
use script_traits::ScriptMsg;
|
||||
use servo_url::ServoUrl;
|
||||
use task_source::TaskSource;
|
||||
|
@ -158,50 +157,33 @@ impl Storage {
|
|||
}
|
||||
|
||||
/// https://html.spec.whatwg.org/multipage/#send-a-storage-notification
|
||||
pub fn queue_storage_event(&self, url: ServoUrl,
|
||||
key: Option<String>, old_value: Option<String>, new_value: Option<String>) {
|
||||
pub fn queue_storage_event(
|
||||
&self,
|
||||
url: ServoUrl,
|
||||
key: Option<String>,
|
||||
old_value: Option<String>,
|
||||
new_value: Option<String>,
|
||||
) {
|
||||
let global = self.global();
|
||||
let window = global.as_window();
|
||||
let task_source = window.dom_manipulation_task_source();
|
||||
let trusted_storage = Trusted::new(self);
|
||||
task_source
|
||||
.queue(
|
||||
box StorageEventRunnable::new(trusted_storage, url, key, old_value, new_value), &global)
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
pub struct StorageEventRunnable {
|
||||
element: Trusted<Storage>,
|
||||
url: ServoUrl,
|
||||
key: Option<String>,
|
||||
old_value: Option<String>,
|
||||
new_value: Option<String>
|
||||
}
|
||||
|
||||
impl StorageEventRunnable {
|
||||
fn new(storage: Trusted<Storage>, url: ServoUrl,
|
||||
key: Option<String>, old_value: Option<String>, new_value: Option<String>) -> StorageEventRunnable {
|
||||
StorageEventRunnable { element: storage, url: url, key: key, old_value: old_value, new_value: new_value }
|
||||
}
|
||||
}
|
||||
|
||||
impl Runnable for StorageEventRunnable {
|
||||
fn main_thread_handler(self: Box<StorageEventRunnable>, _: &ScriptThread) {
|
||||
let this = *self;
|
||||
let storage = this.element.root();
|
||||
let global = storage.global();
|
||||
let window = global.as_window();
|
||||
|
||||
let storage_event = StorageEvent::new(
|
||||
&window,
|
||||
atom!("storage"),
|
||||
EventBubbles::DoesNotBubble, EventCancelable::NotCancelable,
|
||||
this.key.map(DOMString::from), this.old_value.map(DOMString::from), this.new_value.map(DOMString::from),
|
||||
DOMString::from(this.url.into_string()),
|
||||
Some(&storage)
|
||||
);
|
||||
|
||||
storage_event.upcast::<Event>().fire(window.upcast());
|
||||
let this = Trusted::new(self);
|
||||
global.as_window().dom_manipulation_task_source().queue(
|
||||
box task!(send_storage_notification: move || {
|
||||
let this = this.root();
|
||||
let global = this.global();
|
||||
let event = StorageEvent::new(
|
||||
global.as_window(),
|
||||
atom!("storage"),
|
||||
EventBubbles::DoesNotBubble,
|
||||
EventCancelable::NotCancelable,
|
||||
key.map(DOMString::from),
|
||||
old_value.map(DOMString::from),
|
||||
new_value.map(DOMString::from),
|
||||
DOMString::from(url.into_string()),
|
||||
Some(&this),
|
||||
);
|
||||
event.upcast::<Event>().fire(global.upcast());
|
||||
}),
|
||||
global.upcast(),
|
||||
).unwrap();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,7 +36,6 @@ use ipc_channel::ipc::{self, IpcSender};
|
|||
use js::jsapi::JSContext;
|
||||
use script_runtime::CommonScriptMsg;
|
||||
use script_runtime::ScriptThreadEventCategory::WebVREvent;
|
||||
use script_thread::Runnable;
|
||||
use std::cell::Cell;
|
||||
use std::mem;
|
||||
use std::rc::Rc;
|
||||
|
@ -511,11 +510,12 @@ impl VRDisplay {
|
|||
api_sender.send_vr(WebVRCommand::Create(display_id)).unwrap();
|
||||
loop {
|
||||
// Run RAF callbacks on JavaScript thread
|
||||
let msg = box NotifyDisplayRAF {
|
||||
address: address.clone(),
|
||||
sender: raf_sender.clone()
|
||||
};
|
||||
js_sender.send(CommonScriptMsg::RunnableMsg(WebVREvent, msg)).unwrap();
|
||||
let this = address.clone();
|
||||
let sender = raf_sender.clone();
|
||||
let task = box task!(handle_vrdisplay_raf: move || {
|
||||
this.root().handle_raf(&sender);
|
||||
});
|
||||
js_sender.send(CommonScriptMsg::Task(WebVREvent, task)).unwrap();
|
||||
|
||||
// Run Sync Poses in parallell on Render thread
|
||||
let msg = WebVRCommand::SyncPoses(display_id, near, far, sync_sender.clone());
|
||||
|
@ -608,19 +608,6 @@ impl VRDisplay {
|
|||
}
|
||||
}
|
||||
|
||||
struct NotifyDisplayRAF {
|
||||
address: Trusted<VRDisplay>,
|
||||
sender: mpsc::Sender<Result<(f64, f64), ()>>
|
||||
}
|
||||
|
||||
impl Runnable for NotifyDisplayRAF {
|
||||
fn handler(self: Box<Self>) {
|
||||
let display = self.address.root();
|
||||
display.handle_raf(&self.sender);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// WebVR Spec: If the number of values in the leftBounds/rightBounds arrays
|
||||
// is not 0 or 4 for any of the passed layers the promise is rejected
|
||||
fn parse_bounds(src: &Option<Vec<Finite<f32>>>, dst: &mut [f32; 4]) -> Result<(), &'static str> {
|
||||
|
|
|
@ -31,13 +31,13 @@ use net_traits::CoreResourceMsg::WebsocketConnect;
|
|||
use net_traits::MessageData;
|
||||
use script_runtime::CommonScriptMsg;
|
||||
use script_runtime::ScriptThreadEventCategory::WebSocketEvent;
|
||||
use script_thread::{Runnable, RunnableWrapper};
|
||||
use servo_url::ServoUrl;
|
||||
use std::ascii::AsciiExt;
|
||||
use std::borrow::ToOwned;
|
||||
use std::cell::Cell;
|
||||
use std::ptr;
|
||||
use std::thread;
|
||||
use task::{Task, TaskCanceller};
|
||||
use task_source::TaskSource;
|
||||
use task_source::networking::NetworkingTaskSource;
|
||||
|
||||
|
@ -67,30 +67,34 @@ mod close_code {
|
|||
pub const TLS_FAILED: u16 = 1015;
|
||||
}
|
||||
|
||||
pub fn close_the_websocket_connection(address: Trusted<WebSocket>,
|
||||
task_source: &NetworkingTaskSource,
|
||||
wrapper: &RunnableWrapper,
|
||||
code: Option<u16>,
|
||||
reason: String) {
|
||||
pub fn close_the_websocket_connection(
|
||||
address: Trusted<WebSocket>,
|
||||
task_source: &NetworkingTaskSource,
|
||||
canceller: &TaskCanceller,
|
||||
code: Option<u16>,
|
||||
reason: String,
|
||||
) {
|
||||
let close_task = box CloseTask {
|
||||
address: address,
|
||||
failed: false,
|
||||
code: code,
|
||||
reason: Some(reason),
|
||||
};
|
||||
task_source.queue_with_wrapper(close_task, &wrapper).unwrap();
|
||||
task_source.queue_with_canceller(close_task, &canceller).unwrap();
|
||||
}
|
||||
|
||||
pub fn fail_the_websocket_connection(address: Trusted<WebSocket>,
|
||||
task_source: &NetworkingTaskSource,
|
||||
wrapper: &RunnableWrapper) {
|
||||
pub fn fail_the_websocket_connection(
|
||||
address: Trusted<WebSocket>,
|
||||
task_source: &NetworkingTaskSource,
|
||||
canceller: &TaskCanceller,
|
||||
) {
|
||||
let close_task = box CloseTask {
|
||||
address: address,
|
||||
failed: true,
|
||||
code: Some(close_code::ABNORMAL),
|
||||
reason: None,
|
||||
};
|
||||
task_source.queue_with_wrapper(close_task, &wrapper).unwrap();
|
||||
task_source.queue_with_canceller(close_task, &canceller).unwrap();
|
||||
}
|
||||
|
||||
#[dom_struct]
|
||||
|
@ -197,7 +201,7 @@ impl WebSocket {
|
|||
*ws.sender.borrow_mut() = Some(dom_action_sender);
|
||||
|
||||
let task_source = global.networking_task_source();
|
||||
let wrapper = global.get_runnable_wrapper();
|
||||
let canceller = global.task_canceller();
|
||||
thread::spawn(move || {
|
||||
while let Ok(event) = dom_event_receiver.recv() {
|
||||
match event {
|
||||
|
@ -206,22 +210,22 @@ impl WebSocket {
|
|||
address: address.clone(),
|
||||
protocol_in_use,
|
||||
};
|
||||
task_source.queue_with_wrapper(open_thread, &wrapper).unwrap();
|
||||
task_source.queue_with_canceller(open_thread, &canceller).unwrap();
|
||||
},
|
||||
WebSocketNetworkEvent::MessageReceived(message) => {
|
||||
let message_thread = box MessageReceivedTask {
|
||||
address: address.clone(),
|
||||
message: message,
|
||||
};
|
||||
task_source.queue_with_wrapper(message_thread, &wrapper).unwrap();
|
||||
task_source.queue_with_canceller(message_thread, &canceller).unwrap();
|
||||
},
|
||||
WebSocketNetworkEvent::Fail => {
|
||||
fail_the_websocket_connection(address.clone(),
|
||||
&task_source, &wrapper);
|
||||
&task_source, &canceller);
|
||||
},
|
||||
WebSocketNetworkEvent::Close(code, reason) => {
|
||||
close_the_websocket_connection(address.clone(),
|
||||
&task_source, &wrapper, code, reason);
|
||||
&task_source, &canceller, code, reason);
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -261,7 +265,7 @@ impl WebSocket {
|
|||
|
||||
self.global()
|
||||
.script_chan()
|
||||
.send(CommonScriptMsg::RunnableMsg(WebSocketEvent, task))
|
||||
.send(CommonScriptMsg::Task(WebSocketEvent, task))
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
|
@ -368,7 +372,7 @@ impl WebSocketMethods for WebSocket {
|
|||
|
||||
let address = Trusted::new(self);
|
||||
let task_source = self.global().networking_task_source();
|
||||
fail_the_websocket_connection(address, &task_source, &self.global().get_runnable_wrapper());
|
||||
fail_the_websocket_connection(address, &task_source, &self.global().task_canceller());
|
||||
}
|
||||
WebSocketRequestState::Open => {
|
||||
self.ready_state.set(WebSocketRequestState::Closing);
|
||||
|
@ -393,9 +397,9 @@ struct ConnectionEstablishedTask {
|
|||
protocol_in_use: Option<String>,
|
||||
}
|
||||
|
||||
impl Runnable for ConnectionEstablishedTask {
|
||||
impl Task for ConnectionEstablishedTask {
|
||||
/// https://html.spec.whatwg.org/multipage/#feedback-from-the-protocol:concept-websocket-established
|
||||
fn handler(self: Box<Self>) {
|
||||
fn run(self: Box<Self>) {
|
||||
let ws = self.address.root();
|
||||
|
||||
// Step 1.
|
||||
|
@ -418,13 +422,13 @@ struct BufferedAmountTask {
|
|||
address: Trusted<WebSocket>,
|
||||
}
|
||||
|
||||
impl Runnable for BufferedAmountTask {
|
||||
impl Task for BufferedAmountTask {
|
||||
// See https://html.spec.whatwg.org/multipage/#dom-websocket-bufferedamount
|
||||
//
|
||||
// To be compliant with standards, we need to reset bufferedAmount only when the event loop
|
||||
// reaches step 1. In our implementation, the bytes will already have been sent on a background
|
||||
// thread.
|
||||
fn handler(self: Box<Self>) {
|
||||
fn run(self: Box<Self>) {
|
||||
let ws = self.address.root();
|
||||
|
||||
ws.buffered_amount.set(0);
|
||||
|
@ -439,8 +443,8 @@ struct CloseTask {
|
|||
reason: Option<String>,
|
||||
}
|
||||
|
||||
impl Runnable for CloseTask {
|
||||
fn handler(self: Box<Self>) {
|
||||
impl Task for CloseTask {
|
||||
fn run(self: Box<Self>) {
|
||||
let ws = self.address.root();
|
||||
|
||||
if ws.ready_state.get() == WebSocketRequestState::Closed {
|
||||
|
@ -479,9 +483,9 @@ struct MessageReceivedTask {
|
|||
message: MessageData,
|
||||
}
|
||||
|
||||
impl Runnable for MessageReceivedTask {
|
||||
impl Task for MessageReceivedTask {
|
||||
#[allow(unsafe_code)]
|
||||
fn handler(self: Box<Self>) {
|
||||
fn run(self: Box<Self>) {
|
||||
let ws = self.address.root();
|
||||
debug!("MessageReceivedTask::handler({:p}): readyState={:?}", &*ws,
|
||||
ws.ready_state.get());
|
||||
|
|
|
@ -76,8 +76,8 @@ use script_layout_interface::rpc::{ContentBoxResponse, ContentBoxesResponse, Lay
|
|||
use script_layout_interface::rpc::{MarginStyleResponse, NodeScrollRootIdResponse};
|
||||
use script_layout_interface::rpc::{ResolvedStyleResponse, TextIndexResponse};
|
||||
use script_runtime::{CommonScriptMsg, ScriptChan, ScriptPort, ScriptThreadEventCategory};
|
||||
use script_thread::{ImageCacheMsg, MainThreadScriptChan, MainThreadScriptMsg, Runnable};
|
||||
use script_thread::{RunnableWrapper, ScriptThread, SendableMainThreadScriptChan};
|
||||
use script_thread::{ImageCacheMsg, MainThreadScriptChan, MainThreadScriptMsg};
|
||||
use script_thread::{ScriptThread, SendableMainThreadScriptChan};
|
||||
use script_traits::{ConstellationControlMsg, DocumentState, LoadData, MozBrowserEvent};
|
||||
use script_traits::{ScriptToConstellationChan, ScriptMsg, ScrollState, TimerEvent, TimerEventId};
|
||||
use script_traits::{TimerSchedulerMsg, UntrustedNodeAddress, WindowSizeData, WindowSizeType};
|
||||
|
@ -111,6 +111,7 @@ use style::selector_parser::PseudoElement;
|
|||
use style::str::HTML_SPACE_CHARACTERS;
|
||||
use style::stylesheets::CssRuleType;
|
||||
use style_traits::PARSING_MODE_DEFAULT;
|
||||
use task::TaskCanceller;
|
||||
use task_source::dom_manipulation::DOMManipulationTaskSource;
|
||||
use task_source::file_reading::FileReadingTaskSource;
|
||||
use task_source::history_traversal::HistoryTraversalTaskSource;
|
||||
|
@ -1038,8 +1039,8 @@ impl WindowMethods for Window {
|
|||
}
|
||||
|
||||
impl Window {
|
||||
pub fn get_runnable_wrapper(&self) -> RunnableWrapper {
|
||||
RunnableWrapper {
|
||||
pub fn task_canceller(&self) -> TaskCanceller {
|
||||
TaskCanceller {
|
||||
cancelled: Some(self.ignore_further_async_events.borrow().clone()),
|
||||
}
|
||||
}
|
||||
|
@ -1968,59 +1969,50 @@ fn debug_reflow_events(id: PipelineId, goal: &ReflowGoal, query_type: &ReflowQue
|
|||
println!("{}", debug_msg);
|
||||
}
|
||||
|
||||
struct PostMessageHandler {
|
||||
destination: Trusted<Window>,
|
||||
origin: Option<ImmutableOrigin>,
|
||||
message: StructuredCloneData,
|
||||
}
|
||||
|
||||
impl PostMessageHandler {
|
||||
fn new(window: &Window,
|
||||
origin: Option<ImmutableOrigin>,
|
||||
message: StructuredCloneData) -> PostMessageHandler {
|
||||
PostMessageHandler {
|
||||
destination: Trusted::new(window),
|
||||
origin: origin,
|
||||
message: message,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Runnable for PostMessageHandler {
|
||||
// https://html.spec.whatwg.org/multipage/#dom-window-postmessage steps 10-12.
|
||||
fn handler(self: Box<PostMessageHandler>) {
|
||||
let this = *self;
|
||||
let window = this.destination.root();
|
||||
|
||||
// Step 10.
|
||||
let doc = window.Document();
|
||||
if let Some(source) = this.origin {
|
||||
if !source.same_origin(doc.origin()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
let cx = window.get_cx();
|
||||
let globalhandle = window.reflector().get_jsobject();
|
||||
let _ac = JSAutoCompartment::new(cx, globalhandle.get());
|
||||
|
||||
rooted!(in(cx) let mut message = UndefinedValue());
|
||||
this.message.read(window.upcast(), message.handle_mut());
|
||||
|
||||
// Step 11-12.
|
||||
// TODO(#12719): set the other attributes.
|
||||
MessageEvent::dispatch_jsval(window.upcast(),
|
||||
window.upcast(),
|
||||
message.handle());
|
||||
}
|
||||
}
|
||||
|
||||
impl Window {
|
||||
pub fn post_message(&self, origin: Option<ImmutableOrigin>, data: StructuredCloneData) {
|
||||
let runnable = PostMessageHandler::new(self, origin, data);
|
||||
let runnable = self.get_runnable_wrapper().wrap_runnable(box runnable);
|
||||
let msg = CommonScriptMsg::RunnableMsg(ScriptThreadEventCategory::DomEvent, runnable);
|
||||
// https://html.spec.whatwg.org/multipage/#dom-window-postmessage step 7.
|
||||
pub fn post_message(
|
||||
&self,
|
||||
target_origin: Option<ImmutableOrigin>,
|
||||
serialize_with_transfer_result: StructuredCloneData,
|
||||
) {
|
||||
let this = Trusted::new(self);
|
||||
let task = box task!(post_serialised_message: move || {
|
||||
let this = this.root();
|
||||
|
||||
// Step 7.1.
|
||||
if let Some(target_origin) = target_origin {
|
||||
if !target_origin.same_origin(this.Document().origin()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Steps 7.2.-7.5.
|
||||
let cx = this.get_cx();
|
||||
let obj = this.reflector().get_jsobject();
|
||||
let _ac = JSAutoCompartment::new(cx, obj.get());
|
||||
rooted!(in(cx) let mut message_clone = UndefinedValue());
|
||||
serialize_with_transfer_result.read(
|
||||
this.upcast(),
|
||||
message_clone.handle_mut(),
|
||||
);
|
||||
|
||||
// Step 7.6.
|
||||
// TODO: MessagePort array.
|
||||
|
||||
// Step 7.7.
|
||||
// TODO(#12719): Set the other attributes.
|
||||
MessageEvent::dispatch_jsval(
|
||||
this.upcast(),
|
||||
this.upcast(),
|
||||
message_clone.handle(),
|
||||
);
|
||||
});
|
||||
// FIXME(nox): Why are errors silenced here?
|
||||
// TODO(#12718): Use the "posted message task source".
|
||||
let _ = self.script_chan.send(msg);
|
||||
let _ = self.script_chan.send(CommonScriptMsg::Task(
|
||||
ScriptThreadEventCategory::DomEvent,
|
||||
self.task_canceller().wrap_task(task),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ use dom::abstractworker::{SharedRt, SimpleWorkerErrorHandler};
|
|||
use dom::abstractworker::WorkerScriptMsg;
|
||||
use dom::bindings::codegen::Bindings::WorkerBinding;
|
||||
use dom::bindings::codegen::Bindings::WorkerBinding::WorkerMethods;
|
||||
use dom::bindings::error::{Error, ErrorResult, Fallible, ErrorInfo};
|
||||
use dom::bindings::error::{Error, ErrorResult, Fallible};
|
||||
use dom::bindings::inheritance::Castable;
|
||||
use dom::bindings::js::Root;
|
||||
use dom::bindings::refcounted::Trusted;
|
||||
|
@ -15,22 +15,20 @@ use dom::bindings::reflector::{DomObject, reflect_dom_object};
|
|||
use dom::bindings::str::DOMString;
|
||||
use dom::bindings::structuredclone::StructuredCloneData;
|
||||
use dom::dedicatedworkerglobalscope::DedicatedWorkerGlobalScope;
|
||||
use dom::errorevent::ErrorEvent;
|
||||
use dom::event::{Event, EventBubbles, EventCancelable, EventStatus};
|
||||
use dom::eventtarget::EventTarget;
|
||||
use dom::globalscope::GlobalScope;
|
||||
use dom::messageevent::MessageEvent;
|
||||
use dom::workerglobalscope::prepare_workerscope_init;
|
||||
use dom_struct::dom_struct;
|
||||
use ipc_channel::ipc;
|
||||
use js::jsapi::{HandleValue, JSAutoCompartment, JSContext, NullHandleValue};
|
||||
use js::jsapi::{HandleValue, JSAutoCompartment, JSContext};
|
||||
use js::jsval::UndefinedValue;
|
||||
use script_thread::Runnable;
|
||||
use script_traits::WorkerScriptLoadOrigin;
|
||||
use std::cell::Cell;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::sync::mpsc::{Sender, channel};
|
||||
use task::Task;
|
||||
|
||||
pub type TrustedWorkerAddress = Trusted<Worker>;
|
||||
|
||||
|
@ -139,27 +137,6 @@ impl Worker {
|
|||
let worker = address.root();
|
||||
worker.upcast().fire_event(atom!("error"));
|
||||
}
|
||||
|
||||
#[allow(unsafe_code)]
|
||||
fn dispatch_error(&self, error_info: ErrorInfo) {
|
||||
let global = self.global();
|
||||
let event = ErrorEvent::new(&global,
|
||||
atom!("error"),
|
||||
EventBubbles::DoesNotBubble,
|
||||
EventCancelable::Cancelable,
|
||||
error_info.message.as_str().into(),
|
||||
error_info.filename.as_str().into(),
|
||||
error_info.lineno,
|
||||
error_info.column,
|
||||
unsafe { NullHandleValue });
|
||||
|
||||
let event_status = event.upcast::<Event>().fire(self.upcast::<EventTarget>());
|
||||
if event_status == EventStatus::Canceled {
|
||||
return;
|
||||
}
|
||||
|
||||
global.report_an_error(error_info, unsafe { NullHandleValue });
|
||||
}
|
||||
}
|
||||
|
||||
impl WorkerMethods for Worker {
|
||||
|
@ -198,52 +175,10 @@ impl WorkerMethods for Worker {
|
|||
event_handler!(error, GetOnerror, SetOnerror);
|
||||
}
|
||||
|
||||
pub struct WorkerMessageHandler {
|
||||
addr: TrustedWorkerAddress,
|
||||
data: StructuredCloneData,
|
||||
}
|
||||
|
||||
impl WorkerMessageHandler {
|
||||
pub fn new(addr: TrustedWorkerAddress, data: StructuredCloneData) -> WorkerMessageHandler {
|
||||
WorkerMessageHandler {
|
||||
addr: addr,
|
||||
data: data,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Runnable for WorkerMessageHandler {
|
||||
fn handler(self: Box<WorkerMessageHandler>) {
|
||||
let this = *self;
|
||||
Worker::handle_message(this.addr, this.data);
|
||||
}
|
||||
}
|
||||
|
||||
impl Runnable for SimpleWorkerErrorHandler<Worker> {
|
||||
impl Task for SimpleWorkerErrorHandler<Worker> {
|
||||
#[allow(unrooted_must_root)]
|
||||
fn handler(self: Box<SimpleWorkerErrorHandler<Worker>>) {
|
||||
fn run(self: Box<Self>) {
|
||||
let this = *self;
|
||||
Worker::dispatch_simple_error(this.addr);
|
||||
}
|
||||
}
|
||||
|
||||
pub struct WorkerErrorHandler {
|
||||
address: Trusted<Worker>,
|
||||
error_info: ErrorInfo,
|
||||
}
|
||||
|
||||
impl WorkerErrorHandler {
|
||||
pub fn new(address: Trusted<Worker>, error_info: ErrorInfo) -> WorkerErrorHandler {
|
||||
WorkerErrorHandler {
|
||||
address: address,
|
||||
error_info: error_info,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Runnable for WorkerErrorHandler {
|
||||
fn handler(self: Box<Self>) {
|
||||
let this = *self;
|
||||
this.address.root().dispatch_error(this.error_info);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,7 +33,6 @@ use js::rust::Runtime;
|
|||
use net_traits::{IpcSend, load_whole_resource};
|
||||
use net_traits::request::{CredentialsMode, Destination, RequestInit as NetRequestInit, Type as RequestType};
|
||||
use script_runtime::{CommonScriptMsg, ScriptChan, ScriptPort, get_reports};
|
||||
use script_thread::RunnableWrapper;
|
||||
use script_traits::{TimerEvent, TimerEventId};
|
||||
use script_traits::WorkerGlobalScopeInit;
|
||||
use servo_url::{MutableOrigin, ServoUrl};
|
||||
|
@ -42,6 +41,7 @@ use std::rc::Rc;
|
|||
use std::sync::Arc;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::sync::mpsc::Receiver;
|
||||
use task::TaskCanceller;
|
||||
use task_source::file_reading::FileReadingTaskSource;
|
||||
use task_source::networking::NetworkingTaskSource;
|
||||
use task_source::performance_timeline::PerformanceTimelineTaskSource;
|
||||
|
@ -161,8 +161,8 @@ impl WorkerGlobalScope {
|
|||
self.worker_id.clone()
|
||||
}
|
||||
|
||||
pub fn get_runnable_wrapper(&self) -> RunnableWrapper {
|
||||
RunnableWrapper {
|
||||
pub fn task_canceller(&self) -> TaskCanceller {
|
||||
TaskCanceller {
|
||||
cancelled: self.closing.clone(),
|
||||
}
|
||||
}
|
||||
|
@ -387,8 +387,8 @@ impl WorkerGlobalScope {
|
|||
|
||||
pub fn process_event(&self, msg: CommonScriptMsg) {
|
||||
match msg {
|
||||
CommonScriptMsg::RunnableMsg(_, runnable) => {
|
||||
runnable.handler()
|
||||
CommonScriptMsg::Task(_, task) => {
|
||||
task.run()
|
||||
},
|
||||
CommonScriptMsg::CollectReports(reports_chan) => {
|
||||
let cx = self.get_cx();
|
||||
|
|
|
@ -51,9 +51,7 @@ use script_runtime::CommonScriptMsg;
|
|||
use script_runtime::ScriptThreadEventCategory;
|
||||
use script_runtime::StackRootTLS;
|
||||
use script_runtime::new_rt_and_cx;
|
||||
use script_thread::MainThreadScriptMsg;
|
||||
use script_thread::Runnable;
|
||||
use script_thread::ScriptThread;
|
||||
use script_thread::{MainThreadScriptMsg, ScriptThread};
|
||||
use servo_rand;
|
||||
use servo_url::ImmutableOrigin;
|
||||
use servo_url::ServoUrl;
|
||||
|
@ -71,6 +69,7 @@ use std::thread;
|
|||
use style::thread_state;
|
||||
use swapper::Swapper;
|
||||
use swapper::swapper;
|
||||
use task::Task;
|
||||
use uuid::Uuid;
|
||||
|
||||
// Magic numbers
|
||||
|
@ -600,7 +599,7 @@ impl WorkletThread {
|
|||
debug!("Failed to load script.");
|
||||
let old_counter = pending_tasks_struct.set_counter_to(-1);
|
||||
if old_counter > 0 {
|
||||
self.run_in_script_thread(promise.reject_runnable(Error::Abort));
|
||||
self.run_in_script_thread(promise.reject_task(Error::Abort));
|
||||
}
|
||||
} else {
|
||||
// Step 5.
|
||||
|
@ -610,7 +609,7 @@ impl WorkletThread {
|
|||
debug!("Resolving promise.");
|
||||
let msg = MainThreadScriptMsg::WorkletLoaded(pipeline_id);
|
||||
self.global_init.to_script_thread_sender.send(msg).expect("Worklet thread outlived script thread.");
|
||||
self.run_in_script_thread(promise.resolve_runnable(()));
|
||||
self.run_in_script_thread(promise.resolve_task(()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -645,11 +644,11 @@ impl WorkletThread {
|
|||
}
|
||||
}
|
||||
|
||||
/// Run a runnable in the main script thread.
|
||||
fn run_in_script_thread<R>(&self, runnable: R) where
|
||||
R: 'static + Send + Runnable,
|
||||
/// Run a task in the main script thread.
|
||||
fn run_in_script_thread<T>(&self, task: T) where
|
||||
T: 'static + Send + Task,
|
||||
{
|
||||
let msg = CommonScriptMsg::RunnableMsg(ScriptThreadEventCategory::WorkletEvent, box runnable);
|
||||
let msg = CommonScriptMsg::Task(ScriptThreadEventCategory::WorkletEvent, box task);
|
||||
let msg = MainThreadScriptMsg::Common(msg);
|
||||
self.global_init.to_script_thread_sender.send(msg).expect("Worklet thread outlived script thread.");
|
||||
}
|
||||
|
|
|
@ -22,15 +22,10 @@ use net_traits::ResourceThreads;
|
|||
use net_traits::image_cache::ImageCache;
|
||||
use profile_traits::mem;
|
||||
use profile_traits::time;
|
||||
use script_layout_interface::message::Msg;
|
||||
use script_runtime::CommonScriptMsg;
|
||||
use script_runtime::ScriptThreadEventCategory;
|
||||
use script_thread::MainThreadScriptMsg;
|
||||
use script_thread::Runnable;
|
||||
use script_thread::ScriptThread;
|
||||
use script_traits::ScriptMsg;
|
||||
use script_traits::ScriptToConstellationChan;
|
||||
use script_traits::TimerSchedulerMsg;
|
||||
use script_traits::{Painter, ScriptMsg};
|
||||
use script_traits::{ScriptToConstellationChan, TimerSchedulerMsg};
|
||||
use servo_atoms::Atom;
|
||||
use servo_url::ImmutableOrigin;
|
||||
use servo_url::MutableOrigin;
|
||||
use servo_url::ServoUrl;
|
||||
|
@ -96,25 +91,21 @@ impl WorkletGlobalScope {
|
|||
self.globalscope.evaluate_js_on_global_with_result(&*script, rval.handle_mut())
|
||||
}
|
||||
|
||||
/// Run a runnable in the main script thread.
|
||||
pub fn run_in_script_thread<R>(&self, runnable: R) where
|
||||
R: 'static + Send + Runnable,
|
||||
{
|
||||
let msg = CommonScriptMsg::RunnableMsg(ScriptThreadEventCategory::WorkletEvent, box runnable);
|
||||
let msg = MainThreadScriptMsg::Common(msg);
|
||||
self.to_script_thread_sender.send(msg).expect("Worklet thread outlived script thread.");
|
||||
}
|
||||
|
||||
/// Send a message to layout.
|
||||
pub fn send_to_layout(&self, msg: Msg) {
|
||||
struct RunnableMsg(PipelineId, Msg);
|
||||
impl Runnable for RunnableMsg {
|
||||
fn main_thread_handler(self: Box<Self>, script_thread: &ScriptThread) {
|
||||
script_thread.send_to_layout(self.0, self.1);
|
||||
}
|
||||
}
|
||||
let pipeline_id = self.globalscope.pipeline_id();
|
||||
self.run_in_script_thread(RunnableMsg(pipeline_id, msg));
|
||||
/// Register a paint worklet to the script thread.
|
||||
pub fn register_paint_worklet(
|
||||
&self,
|
||||
name: Atom,
|
||||
properties: Vec<Atom>,
|
||||
painter: Box<Painter>,
|
||||
) {
|
||||
self.to_script_thread_sender
|
||||
.send(MainThreadScriptMsg::RegisterPaintWorklet {
|
||||
pipeline_id: self.globalscope.pipeline_id(),
|
||||
name,
|
||||
properties,
|
||||
painter,
|
||||
})
|
||||
.expect("Worklet thread outlived script thread.");
|
||||
}
|
||||
|
||||
/// The base URL of this global.
|
||||
|
|
|
@ -261,7 +261,7 @@ impl XMLHttpRequest {
|
|||
let listener = NetworkListener {
|
||||
context: context,
|
||||
task_source: task_source,
|
||||
wrapper: Some(global.get_runnable_wrapper())
|
||||
canceller: Some(global.task_canceller())
|
||||
};
|
||||
ROUTER.add_route(action_receiver.to_opaque(), box move |message| {
|
||||
listener.notify_fetch(message.to().unwrap());
|
||||
|
|
|
@ -102,7 +102,7 @@ pub fn Fetch(global: &GlobalScope, input: RequestInfo, init: RootedTraceableBox<
|
|||
let listener = NetworkListener {
|
||||
context: fetch_context,
|
||||
task_source: global.networking_task_source(),
|
||||
wrapper: Some(global.get_runnable_wrapper())
|
||||
canceller: Some(global.task_canceller())
|
||||
};
|
||||
|
||||
ROUTER.add_route(action_receiver.to_opaque(), box move |message| {
|
||||
|
|
|
@ -62,7 +62,7 @@ pub fn fetch_image_for_layout(url: ServoUrl,
|
|||
let listener = NetworkListener {
|
||||
context: context,
|
||||
task_source: window.networking_task_source(),
|
||||
wrapper: Some(window.get_runnable_wrapper()),
|
||||
canceller: Some(window.task_canceller()),
|
||||
};
|
||||
ROUTER.add_route(action_receiver.to_opaque(), box move |message| {
|
||||
listener.notify_fetch(message.to().unwrap());
|
||||
|
|
|
@ -108,6 +108,9 @@ extern crate webrender_api;
|
|||
extern crate webvr_traits;
|
||||
extern crate xml5ever;
|
||||
|
||||
#[macro_use]
|
||||
mod task;
|
||||
|
||||
mod body;
|
||||
pub mod clipboard_provider;
|
||||
mod devtools;
|
||||
|
|
|
@ -3,29 +3,29 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use net_traits::{Action, FetchResponseListener, FetchResponseMsg};
|
||||
use script_thread::{Runnable, RunnableWrapper};
|
||||
use std::sync::{Arc, Mutex};
|
||||
use task::{Task, TaskCanceller};
|
||||
use task_source::TaskSource;
|
||||
use task_source::networking::NetworkingTaskSource;
|
||||
|
||||
/// An off-thread sink for async network event runnables. All such events are forwarded to
|
||||
/// An off-thread sink for async network event tasks. All such events are forwarded to
|
||||
/// a target thread, where they are invoked on the provided context object.
|
||||
pub struct NetworkListener<Listener: PreInvoke + Send + 'static> {
|
||||
pub context: Arc<Mutex<Listener>>,
|
||||
pub task_source: NetworkingTaskSource,
|
||||
pub wrapper: Option<RunnableWrapper>,
|
||||
pub canceller: Option<TaskCanceller>,
|
||||
}
|
||||
|
||||
impl<Listener: PreInvoke + Send + 'static> NetworkListener<Listener> {
|
||||
pub fn notify<A: Action<Listener> + Send + 'static>(&self, action: A) {
|
||||
let runnable = box ListenerRunnable {
|
||||
let task = box ListenerTask {
|
||||
context: self.context.clone(),
|
||||
action: action,
|
||||
};
|
||||
let result = if let Some(ref wrapper) = self.wrapper {
|
||||
self.task_source.queue_with_wrapper(runnable, wrapper)
|
||||
let result = if let Some(ref canceller) = self.canceller {
|
||||
self.task_source.queue_with_canceller(task, canceller)
|
||||
} else {
|
||||
self.task_source.queue_wrapperless(runnable)
|
||||
self.task_source.queue_unconditionally(task)
|
||||
};
|
||||
if let Err(err) = result {
|
||||
warn!("failed to deliver network data: {:?}", err);
|
||||
|
@ -40,8 +40,8 @@ impl<Listener: FetchResponseListener + PreInvoke + Send + 'static> NetworkListen
|
|||
}
|
||||
}
|
||||
|
||||
/// A gating mechanism that runs before invoking the runnable on the target thread.
|
||||
/// If the `should_invoke` method returns false, the runnable is discarded without
|
||||
/// A gating mechanism that runs before invoking the task on the target thread.
|
||||
/// If the `should_invoke` method returns false, the task is discarded without
|
||||
/// being invoked.
|
||||
pub trait PreInvoke {
|
||||
fn should_invoke(&self) -> bool {
|
||||
|
@ -49,14 +49,18 @@ pub trait PreInvoke {
|
|||
}
|
||||
}
|
||||
|
||||
/// A runnable for moving the async network events between threads.
|
||||
struct ListenerRunnable<A: Action<Listener> + Send + 'static, Listener: PreInvoke + Send> {
|
||||
/// A task for moving the async network events between threads.
|
||||
struct ListenerTask<A: Action<Listener> + Send + 'static, Listener: PreInvoke + Send> {
|
||||
context: Arc<Mutex<Listener>>,
|
||||
action: A,
|
||||
}
|
||||
|
||||
impl<A: Action<Listener> + Send + 'static, Listener: PreInvoke + Send> Runnable for ListenerRunnable<A, Listener> {
|
||||
fn handler(self: Box<ListenerRunnable<A, Listener>>) {
|
||||
impl<A, Listener> Task for ListenerTask<A, Listener>
|
||||
where
|
||||
A: Action<Listener> + Send + 'static,
|
||||
Listener: PreInvoke + Send,
|
||||
{
|
||||
fn run(self: Box<Self>) {
|
||||
let this = *self;
|
||||
let mut context = this.context.lock().unwrap();
|
||||
if context.should_invoke() {
|
||||
|
|
|
@ -23,7 +23,7 @@ use js::panic::wrap_panic;
|
|||
use js::rust::Runtime;
|
||||
use microtask::{EnqueuedPromiseCallback, Microtask};
|
||||
use profile_traits::mem::{Report, ReportKind, ReportsChan};
|
||||
use script_thread::{Runnable, STACK_ROOTS, trace_thread};
|
||||
use script_thread::{STACK_ROOTS, trace_thread};
|
||||
use servo_config::opts;
|
||||
use servo_config::prefs::PREFS;
|
||||
use std::cell::Cell;
|
||||
|
@ -35,6 +35,7 @@ use std::os::raw::c_void;
|
|||
use std::panic::AssertUnwindSafe;
|
||||
use std::ptr;
|
||||
use style::thread_state;
|
||||
use task::Task;
|
||||
use time::{Tm, now};
|
||||
|
||||
/// Common messages used to control the event loops in both the script and the worker
|
||||
|
@ -43,14 +44,16 @@ pub enum CommonScriptMsg {
|
|||
/// supplied channel.
|
||||
CollectReports(ReportsChan),
|
||||
/// Generic message that encapsulates event handling.
|
||||
RunnableMsg(ScriptThreadEventCategory, Box<Runnable + Send>),
|
||||
Task(ScriptThreadEventCategory, Box<Task + Send>),
|
||||
}
|
||||
|
||||
impl fmt::Debug for CommonScriptMsg {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match *self {
|
||||
CommonScriptMsg::CollectReports(_) => write!(f, "CollectReports(...)"),
|
||||
CommonScriptMsg::RunnableMsg(category, _) => write!(f, "RunnableMsg({:?}, ...)", category),
|
||||
CommonScriptMsg::Task(ref category, ref task) => {
|
||||
f.debug_tuple("Task").field(category).field(task).finish()
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -87,29 +87,30 @@ use profile_traits::time::{self, ProfilerCategory, profile};
|
|||
use script_layout_interface::message::{self, Msg, NewLayoutThreadInfo, ReflowQueryType};
|
||||
use script_runtime::{CommonScriptMsg, ScriptChan, ScriptThreadEventCategory};
|
||||
use script_runtime::{ScriptPort, StackRootTLS, get_reports, new_rt_and_cx};
|
||||
use script_traits::{CompositorEvent, ConstellationControlMsg, PaintMetricType};
|
||||
use script_traits::{DocumentActivity, DiscardBrowsingContext, EventResult};
|
||||
use script_traits::{InitialScriptState, JsEvalResult, LayoutMsg, LoadData, MouseButton, MouseEventType};
|
||||
use script_traits::{MozBrowserEvent, NewLayoutInfo, ScriptToConstellationChan, ScriptMsg, UpdatePipelineIdReason};
|
||||
use script_traits::{ScriptThreadFactory, TimerEvent, TimerSchedulerMsg, TimerSource};
|
||||
use script_traits::{TouchEventType, TouchId, UntrustedNodeAddress, WindowSizeData, WindowSizeType};
|
||||
use script_traits::{CompositorEvent, ConstellationControlMsg};
|
||||
use script_traits::{DiscardBrowsingContext, DocumentActivity, EventResult};
|
||||
use script_traits::{InitialScriptState, JsEvalResult, LayoutMsg, LoadData};
|
||||
use script_traits::{MouseButton, MouseEventType, MozBrowserEvent, NewLayoutInfo};
|
||||
use script_traits::{PaintMetricType, Painter, ScriptMsg, ScriptThreadFactory};
|
||||
use script_traits::{ScriptToConstellationChan, TimerEvent, TimerSchedulerMsg};
|
||||
use script_traits::{TimerSource, TouchEventType, TouchId, UntrustedNodeAddress};
|
||||
use script_traits::{UpdatePipelineIdReason, WindowSizeData, WindowSizeType};
|
||||
use script_traits::CompositorEvent::{KeyEvent, MouseButtonEvent, MouseMoveEvent, ResizeEvent};
|
||||
use script_traits::CompositorEvent::{TouchEvent, TouchpadPressureEvent};
|
||||
use script_traits::webdriver_msg::WebDriverScriptCommand;
|
||||
use serviceworkerjob::{Job, JobQueue, AsyncJobHandler};
|
||||
use serviceworkerjob::{Job, JobQueue};
|
||||
use servo_atoms::Atom;
|
||||
use servo_config::opts;
|
||||
use servo_url::{ImmutableOrigin, MutableOrigin, ServoUrl};
|
||||
use std::cell::Cell;
|
||||
use std::collections::{hash_map, HashMap, HashSet};
|
||||
use std::default::Default;
|
||||
use std::intrinsics;
|
||||
use std::ops::Deref;
|
||||
use std::option::Option;
|
||||
use std::ptr;
|
||||
use std::rc::Rc;
|
||||
use std::result::Result;
|
||||
use std::sync::Arc;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::sync::mpsc::{Receiver, Select, Sender, channel};
|
||||
use std::thread;
|
||||
use style::context::ReflowGoal;
|
||||
|
@ -202,62 +203,6 @@ impl InProgressLoad {
|
|||
}
|
||||
}
|
||||
|
||||
/// Encapsulated state required to create cancellable runnables from non-script threads.
|
||||
pub struct RunnableWrapper {
|
||||
pub cancelled: Option<Arc<AtomicBool>>,
|
||||
}
|
||||
|
||||
impl RunnableWrapper {
|
||||
pub fn wrap_runnable<T: Runnable + Send + 'static>(&self, runnable: Box<T>) -> Box<Runnable + Send> {
|
||||
box CancellableRunnable {
|
||||
cancelled: self.cancelled.clone(),
|
||||
inner: runnable,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A runnable that can be discarded by toggling a shared flag.
|
||||
pub struct CancellableRunnable<T: Runnable + Send> {
|
||||
cancelled: Option<Arc<AtomicBool>>,
|
||||
inner: Box<T>,
|
||||
}
|
||||
|
||||
impl<T> CancellableRunnable<T>
|
||||
where
|
||||
T: Runnable + Send,
|
||||
{
|
||||
fn is_cancelled(&self) -> bool {
|
||||
self.cancelled.as_ref().map_or(false, |cancelled| {
|
||||
cancelled.load(Ordering::SeqCst)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Runnable for CancellableRunnable<T>
|
||||
where
|
||||
T: Runnable + Send,
|
||||
{
|
||||
fn main_thread_handler(self: Box<CancellableRunnable<T>>, script_thread: &ScriptThread) {
|
||||
if !self.is_cancelled() {
|
||||
self.inner.main_thread_handler(script_thread);
|
||||
}
|
||||
}
|
||||
|
||||
fn handler(self: Box<CancellableRunnable<T>>) {
|
||||
if !self.is_cancelled() {
|
||||
self.inner.handler()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait Runnable {
|
||||
fn name(&self) -> &'static str { unsafe { intrinsics::type_name::<Self>() } }
|
||||
fn handler(self: Box<Self>) {
|
||||
panic!("This should probably be redefined.")
|
||||
}
|
||||
fn main_thread_handler(self: Box<Self>, _script_thread: &ScriptThread) { self.handler(); }
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
enum MixedMessage {
|
||||
FromConstellation(ConstellationControlMsg),
|
||||
|
@ -267,7 +212,7 @@ enum MixedMessage {
|
|||
FromScheduler(TimerEvent),
|
||||
}
|
||||
|
||||
/// Messages used to control the script event loop
|
||||
/// Messages used to control the script event loop.
|
||||
#[derive(Debug)]
|
||||
pub enum MainThreadScriptMsg {
|
||||
/// Common variants associated with the script messages
|
||||
|
@ -282,6 +227,15 @@ pub enum MainThreadScriptMsg {
|
|||
/// Notifies the script thread that a new worklet has been loaded, and thus the page should be
|
||||
/// reflowed.
|
||||
WorkletLoaded(PipelineId),
|
||||
/// Notifies the script thread that a new paint worklet has been registered.
|
||||
RegisterPaintWorklet {
|
||||
pipeline_id: PipelineId,
|
||||
name: Atom,
|
||||
properties: Vec<Atom>,
|
||||
painter: Box<Painter>
|
||||
},
|
||||
/// Dispatches a job queue.
|
||||
DispatchJobQueue { scope_url: ServoUrl },
|
||||
}
|
||||
|
||||
impl OpaqueSender<CommonScriptMsg> for Box<ScriptChan + Send> {
|
||||
|
@ -694,11 +648,11 @@ impl ScriptThread {
|
|||
}
|
||||
|
||||
#[allow(unrooted_must_root)]
|
||||
pub fn schedule_job(job: Job, global: &GlobalScope) {
|
||||
pub fn schedule_job(job: Job) {
|
||||
SCRIPT_THREAD_ROOT.with(|root| {
|
||||
let script_thread = unsafe { &*root.get().unwrap() };
|
||||
let job_queue = &*script_thread.job_queue_map;
|
||||
job_queue.schedule_job(job, global, &script_thread);
|
||||
job_queue.schedule_job(job, &script_thread);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -766,13 +720,21 @@ impl ScriptThread {
|
|||
})
|
||||
}
|
||||
|
||||
pub fn send_to_layout(&self, pipeline_id: PipelineId, msg: Msg) {
|
||||
fn handle_register_paint_worklet(
|
||||
&self,
|
||||
pipeline_id: PipelineId,
|
||||
name: Atom,
|
||||
properties: Vec<Atom>,
|
||||
painter: Box<Painter>,
|
||||
) {
|
||||
let window = self.documents.borrow().find_window(pipeline_id);
|
||||
let window = match window {
|
||||
Some(window) => window,
|
||||
None => return warn!("Message sent to layout after pipeline {} closed.", pipeline_id),
|
||||
None => return warn!("Paint worklet registered after pipeline {} closed.", pipeline_id),
|
||||
};
|
||||
let _ = window.layout_chan().send(msg);
|
||||
let _ = window.layout_chan().send(
|
||||
Msg::RegisterPaint(name, properties, painter),
|
||||
);
|
||||
}
|
||||
|
||||
pub fn push_new_element_queue() {
|
||||
|
@ -1160,9 +1122,13 @@ impl ScriptThread {
|
|||
MixedMessage::FromImageCache(_) => ScriptThreadEventCategory::ImageCacheMsg,
|
||||
MixedMessage::FromScript(ref inner_msg) => {
|
||||
match *inner_msg {
|
||||
MainThreadScriptMsg::Common(CommonScriptMsg::RunnableMsg(ref category, _)) =>
|
||||
*category,
|
||||
_ => ScriptThreadEventCategory::ScriptEvent
|
||||
MainThreadScriptMsg::Common(CommonScriptMsg::Task(category, _)) => {
|
||||
category
|
||||
},
|
||||
MainThreadScriptMsg::RegisterPaintWorklet { .. } => {
|
||||
ScriptThreadEventCategory::WorkletEvent
|
||||
},
|
||||
_ => ScriptThreadEventCategory::ScriptEvent,
|
||||
}
|
||||
},
|
||||
MixedMessage::FromScheduler(_) => ScriptThreadEventCategory::TimerEvent
|
||||
|
@ -1291,8 +1257,8 @@ impl ScriptThread {
|
|||
MainThreadScriptMsg::ExitWindow(id) => {
|
||||
self.handle_exit_window_msg(id)
|
||||
},
|
||||
MainThreadScriptMsg::Common(CommonScriptMsg::RunnableMsg(_, runnable)) => {
|
||||
runnable.main_thread_handler(self)
|
||||
MainThreadScriptMsg::Common(CommonScriptMsg::Task(_, task)) => {
|
||||
task.run()
|
||||
}
|
||||
MainThreadScriptMsg::Common(CommonScriptMsg::CollectReports(chan)) => {
|
||||
self.collect_reports(chan)
|
||||
|
@ -1300,6 +1266,22 @@ impl ScriptThread {
|
|||
MainThreadScriptMsg::WorkletLoaded(pipeline_id) => {
|
||||
self.handle_worklet_loaded(pipeline_id)
|
||||
},
|
||||
MainThreadScriptMsg::RegisterPaintWorklet {
|
||||
pipeline_id,
|
||||
name,
|
||||
properties,
|
||||
painter,
|
||||
} => {
|
||||
self.handle_register_paint_worklet(
|
||||
pipeline_id,
|
||||
name,
|
||||
properties,
|
||||
painter,
|
||||
)
|
||||
},
|
||||
MainThreadScriptMsg::DispatchJobQueue { scope_url } => {
|
||||
self.job_queue_map.run_job(scope_url, self)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1736,8 +1718,8 @@ impl ScriptThread {
|
|||
let _ = self.script_sender.send((pipeline_id, ScriptMsg::RegisterServiceWorker(scope_things, scope.clone())));
|
||||
}
|
||||
|
||||
pub fn dispatch_job_queue(&self, job_handler: Box<AsyncJobHandler>) {
|
||||
self.job_queue_map.run_job(job_handler, self);
|
||||
pub fn schedule_job_queue(&self, scope_url: ServoUrl) {
|
||||
let _ = self.chan.0.send(MainThreadScriptMsg::DispatchJobQueue { scope_url });
|
||||
}
|
||||
|
||||
pub fn dom_manipulation_task_source(&self) -> &DOMManipulationTaskSource {
|
||||
|
|
|
@ -18,7 +18,7 @@ use dom::promise::Promise;
|
|||
use dom::serviceworkerregistration::ServiceWorkerRegistration;
|
||||
use dom::urlhelper::UrlHelper;
|
||||
use js::jsapi::JSAutoCompartment;
|
||||
use script_thread::{ScriptThread, Runnable};
|
||||
use script_thread::ScriptThread;
|
||||
use servo_url::ServoUrl;
|
||||
use std::cmp::PartialEq;
|
||||
use std::collections::HashMap;
|
||||
|
@ -93,25 +93,6 @@ impl PartialEq for Job {
|
|||
}
|
||||
}
|
||||
|
||||
pub struct AsyncJobHandler {
|
||||
pub scope_url: ServoUrl,
|
||||
}
|
||||
|
||||
impl AsyncJobHandler {
|
||||
fn new(scope_url: ServoUrl) -> AsyncJobHandler {
|
||||
AsyncJobHandler {
|
||||
scope_url: scope_url,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Runnable for AsyncJobHandler {
|
||||
#[allow(unrooted_must_root)]
|
||||
fn main_thread_handler(self: Box<AsyncJobHandler>, script_thread: &ScriptThread) {
|
||||
script_thread.dispatch_job_queue(self);
|
||||
}
|
||||
}
|
||||
|
||||
#[must_root]
|
||||
#[derive(JSTraceable)]
|
||||
pub struct JobQueue(pub DOMRefCell<HashMap<ServoUrl, Vec<Job>>>);
|
||||
|
@ -122,10 +103,7 @@ impl JobQueue {
|
|||
}
|
||||
#[allow(unrooted_must_root)]
|
||||
// https://w3c.github.io/ServiceWorker/#schedule-job-algorithm
|
||||
pub fn schedule_job(&self,
|
||||
job: Job,
|
||||
global: &GlobalScope,
|
||||
script_thread: &ScriptThread) {
|
||||
pub fn schedule_job(&self, job: Job, script_thread: &ScriptThread) {
|
||||
debug!("scheduling {:?} job", job.job_type);
|
||||
let mut queue_ref = self.0.borrow_mut();
|
||||
let job_queue = queue_ref.entry(job.scope_url.clone()).or_insert(vec![]);
|
||||
|
@ -133,8 +111,7 @@ impl JobQueue {
|
|||
if job_queue.is_empty() {
|
||||
let scope_url = job.scope_url.clone();
|
||||
job_queue.push(job);
|
||||
let run_job_handler = box AsyncJobHandler::new(scope_url);
|
||||
let _ = script_thread.dom_manipulation_task_source().queue(run_job_handler, global);
|
||||
let _ = script_thread.schedule_job_queue(scope_url);
|
||||
debug!("queued task to run newly-queued job");
|
||||
} else {
|
||||
// Step 2
|
||||
|
@ -155,30 +132,29 @@ impl JobQueue {
|
|||
|
||||
#[allow(unrooted_must_root)]
|
||||
// https://w3c.github.io/ServiceWorker/#run-job-algorithm
|
||||
pub fn run_job(&self, run_job_handler: Box<AsyncJobHandler>, script_thread: &ScriptThread) {
|
||||
pub fn run_job(&self, scope_url: ServoUrl, script_thread: &ScriptThread) {
|
||||
debug!("running a job");
|
||||
let url = {
|
||||
let queue_ref = self.0.borrow();
|
||||
let front_job = {
|
||||
let job_vec = queue_ref.get(&run_job_handler.scope_url);
|
||||
let job_vec = queue_ref.get(&scope_url);
|
||||
job_vec.unwrap().first().unwrap()
|
||||
};
|
||||
let scope_url = front_job.scope_url.clone();
|
||||
let front_scope_url = front_job.scope_url.clone();
|
||||
match front_job.job_type {
|
||||
JobType::Register => self.run_register(front_job, run_job_handler, script_thread),
|
||||
JobType::Register => self.run_register(front_job, scope_url, script_thread),
|
||||
JobType::Update => self.update(front_job, script_thread),
|
||||
JobType::Unregister => unreachable!(),
|
||||
};
|
||||
scope_url
|
||||
front_scope_url
|
||||
};
|
||||
self.finish_job(url, script_thread);
|
||||
}
|
||||
|
||||
#[allow(unrooted_must_root)]
|
||||
// https://w3c.github.io/ServiceWorker/#register-algorithm
|
||||
fn run_register(&self, job: &Job, register_job_handler: Box<AsyncJobHandler>, script_thread: &ScriptThread) {
|
||||
fn run_register(&self, job: &Job, scope_url: ServoUrl, script_thread: &ScriptThread) {
|
||||
debug!("running register job");
|
||||
let AsyncJobHandler { scope_url, .. } = *register_job_handler;
|
||||
// Step 1-3
|
||||
if !UrlHelper::is_origin_trustworthy(&job.script_url) {
|
||||
// Step 1.1
|
||||
|
@ -237,8 +213,7 @@ impl JobQueue {
|
|||
|
||||
if run_job {
|
||||
debug!("further jobs in queue after finishing");
|
||||
let handler = box AsyncJobHandler::new(scope_url);
|
||||
self.run_job(handler, script_thread);
|
||||
self.run_job(scope_url, script_thread);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -286,33 +261,6 @@ impl JobQueue {
|
|||
}
|
||||
}
|
||||
|
||||
struct AsyncPromiseSettle {
|
||||
global: Trusted<GlobalScope>,
|
||||
promise: TrustedPromise,
|
||||
settle_type: SettleType,
|
||||
}
|
||||
|
||||
impl Runnable for AsyncPromiseSettle {
|
||||
#[allow(unrooted_must_root)]
|
||||
fn handler(self: Box<AsyncPromiseSettle>) {
|
||||
let global = self.global.root();
|
||||
let settle_type = self.settle_type.clone();
|
||||
let promise = self.promise.root();
|
||||
settle_job_promise(&*global, &*promise, settle_type)
|
||||
}
|
||||
}
|
||||
|
||||
impl AsyncPromiseSettle {
|
||||
#[allow(unrooted_must_root)]
|
||||
fn new(promise: Rc<Promise>, settle_type: SettleType) -> AsyncPromiseSettle {
|
||||
AsyncPromiseSettle {
|
||||
global: Trusted::new(&*promise.global()),
|
||||
promise: TrustedPromise::new(promise),
|
||||
settle_type: settle_type,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn settle_job_promise(global: &GlobalScope, promise: &Promise, settle: SettleType) {
|
||||
let _ac = JSAutoCompartment::new(global.get_cx(), promise.reflector().get_jsobject().get());
|
||||
match settle {
|
||||
|
@ -321,11 +269,18 @@ fn settle_job_promise(global: &GlobalScope, promise: &Promise, settle: SettleTyp
|
|||
};
|
||||
}
|
||||
|
||||
#[allow(unrooted_must_root)]
|
||||
fn queue_settle_promise_for_job(job: &Job, settle: SettleType, task_source: &DOMManipulationTaskSource) {
|
||||
let task = box AsyncPromiseSettle::new(job.promise.clone(), settle);
|
||||
let global = job.client.global();
|
||||
let _ = task_source.queue(task, &*global);
|
||||
|
||||
let promise = TrustedPromise::new(job.promise.clone());
|
||||
// FIXME(nox): Why are errors silenced here?
|
||||
let _ = task_source.queue(
|
||||
box task!(settle_promise_for_job: move || {
|
||||
let promise = promise.root();
|
||||
settle_job_promise(&promise.global(), &promise, settle)
|
||||
}),
|
||||
&*global,
|
||||
);
|
||||
}
|
||||
|
||||
// https://w3c.github.io/ServiceWorker/#reject-job-promise-algorithm
|
||||
|
|
|
@ -229,7 +229,7 @@ impl<'a> StylesheetLoader<'a> {
|
|||
let listener = NetworkListener {
|
||||
context: context,
|
||||
task_source: document.window().networking_task_source(),
|
||||
wrapper: Some(document.window().get_runnable_wrapper())
|
||||
canceller: Some(document.window().task_canceller())
|
||||
};
|
||||
ROUTER.add_route(action_receiver.to_opaque(), box move |message| {
|
||||
listener.notify_fetch(message.to().unwrap());
|
||||
|
|
94
components/script/task.rs
Normal file
94
components/script/task.rs
Normal file
|
@ -0,0 +1,94 @@
|
|||
/* 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/. */
|
||||
|
||||
//! Machinery for [tasks](https://html.spec.whatwg.org/multipage/#concept-task).
|
||||
|
||||
use std::fmt;
|
||||
use std::intrinsics;
|
||||
use std::sync::Arc;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
|
||||
macro_rules! task {
|
||||
($name:ident: move || $body:tt) => {{
|
||||
#[allow(non_camel_case_types)]
|
||||
struct $name<F>(F);
|
||||
impl<F> ::task::Task for $name<F>
|
||||
where
|
||||
F: ::std::ops::FnOnce(),
|
||||
{
|
||||
fn name(&self) -> &'static str {
|
||||
stringify!($name)
|
||||
}
|
||||
|
||||
fn run(self: Box<Self>) {
|
||||
(self.0)();
|
||||
}
|
||||
}
|
||||
$name(move || $body)
|
||||
}};
|
||||
}
|
||||
|
||||
/// A task that can be run. The name method is for profiling purposes.
|
||||
pub trait Task {
|
||||
#[allow(unsafe_code)]
|
||||
fn name(&self) -> &'static str { unsafe { intrinsics::type_name::<Self>() } }
|
||||
fn run(self: Box<Self>);
|
||||
}
|
||||
|
||||
impl fmt::Debug for Task + Send {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||
fmt.debug_tuple(self.name()).field(&format_args!("...")).finish()
|
||||
}
|
||||
}
|
||||
|
||||
/// Encapsulated state required to create cancellable tasks from non-script threads.
|
||||
pub struct TaskCanceller {
|
||||
pub cancelled: Option<Arc<AtomicBool>>,
|
||||
}
|
||||
|
||||
impl TaskCanceller {
|
||||
/// Returns a wrapped `task` that will be cancelled if the `TaskCanceller`
|
||||
/// says so.
|
||||
pub fn wrap_task<T>(&self, task: Box<T>) -> Box<Task + Send>
|
||||
where
|
||||
T: Send + Task + 'static,
|
||||
{
|
||||
box CancellableTask {
|
||||
cancelled: self.cancelled.clone(),
|
||||
inner: task,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A task that can be cancelled by toggling a shared flag.
|
||||
pub struct CancellableTask<T: Send + Task> {
|
||||
cancelled: Option<Arc<AtomicBool>>,
|
||||
inner: Box<T>,
|
||||
}
|
||||
|
||||
impl<T> CancellableTask<T>
|
||||
where
|
||||
T: Send + Task,
|
||||
{
|
||||
fn is_cancelled(&self) -> bool {
|
||||
self.cancelled.as_ref().map_or(false, |cancelled| {
|
||||
cancelled.load(Ordering::SeqCst)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Task for CancellableTask<T>
|
||||
where
|
||||
T: Send + Task,
|
||||
{
|
||||
fn name(&self) -> &'static str {
|
||||
self.inner.name()
|
||||
}
|
||||
|
||||
fn run(self: Box<Self>) {
|
||||
if !self.is_cancelled() {
|
||||
self.inner.run()
|
||||
}
|
||||
}
|
||||
}
|
|
@ -4,15 +4,16 @@
|
|||
|
||||
use dom::bindings::inheritance::Castable;
|
||||
use dom::bindings::refcounted::Trusted;
|
||||
use dom::event::{EventBubbles, EventCancelable, EventRunnable, SimpleEventRunnable};
|
||||
use dom::event::{EventBubbles, EventCancelable, EventTask, SimpleEventTask};
|
||||
use dom::eventtarget::EventTarget;
|
||||
use dom::window::Window;
|
||||
use script_runtime::{CommonScriptMsg, ScriptThreadEventCategory};
|
||||
use script_thread::{MainThreadScriptMsg, Runnable, RunnableWrapper};
|
||||
use script_thread::MainThreadScriptMsg;
|
||||
use servo_atoms::Atom;
|
||||
use std::fmt;
|
||||
use std::result::Result;
|
||||
use std::sync::mpsc::Sender;
|
||||
use task::{Task, TaskCanceller};
|
||||
use task_source::TaskSource;
|
||||
|
||||
#[derive(Clone, JSTraceable)]
|
||||
|
@ -25,17 +26,17 @@ impl fmt::Debug for DOMManipulationTaskSource {
|
|||
}
|
||||
|
||||
impl TaskSource for DOMManipulationTaskSource {
|
||||
fn queue_with_wrapper<T>(
|
||||
fn queue_with_canceller<T>(
|
||||
&self,
|
||||
msg: Box<T>,
|
||||
wrapper: &RunnableWrapper,
|
||||
canceller: &TaskCanceller,
|
||||
) -> Result<(), ()>
|
||||
where
|
||||
T: Runnable + Send + 'static,
|
||||
T: Task + Send + 'static,
|
||||
{
|
||||
let msg = MainThreadScriptMsg::Common(CommonScriptMsg::RunnableMsg(
|
||||
let msg = MainThreadScriptMsg::Common(CommonScriptMsg::Task(
|
||||
ScriptThreadEventCategory::ScriptEvent,
|
||||
wrapper.wrap_runnable(msg),
|
||||
canceller.wrap_task(msg),
|
||||
));
|
||||
self.0.send(msg).map_err(|_| ())
|
||||
}
|
||||
|
@ -49,21 +50,17 @@ impl DOMManipulationTaskSource {
|
|||
cancelable: EventCancelable,
|
||||
window: &Window) {
|
||||
let target = Trusted::new(target);
|
||||
let runnable = box EventRunnable {
|
||||
let task = box EventTask {
|
||||
target: target,
|
||||
name: name,
|
||||
bubbles: bubbles,
|
||||
cancelable: cancelable,
|
||||
};
|
||||
let _ = self.queue(runnable, window.upcast());
|
||||
let _ = self.queue(task, window.upcast());
|
||||
}
|
||||
|
||||
pub fn queue_simple_event(&self, target: &EventTarget, name: Atom, window: &Window) {
|
||||
let target = Trusted::new(target);
|
||||
let runnable = box SimpleEventRunnable {
|
||||
target: target,
|
||||
name: name,
|
||||
};
|
||||
let _ = self.queue(runnable, window.upcast());
|
||||
let _ = self.queue(box SimpleEventTask { target, name }, window.upcast());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,8 +5,8 @@
|
|||
use dom::domexception::DOMErrorName;
|
||||
use dom::filereader::{FileReader, TrustedFileReader, GenerationId, ReadMetaData};
|
||||
use script_runtime::{CommonScriptMsg, ScriptThreadEventCategory, ScriptChan};
|
||||
use script_thread::{Runnable, RunnableWrapper};
|
||||
use std::sync::Arc;
|
||||
use task::{Task, TaskCanceller};
|
||||
use task_source::TaskSource;
|
||||
|
||||
#[derive(JSTraceable)]
|
||||
|
@ -19,31 +19,24 @@ impl Clone for FileReadingTaskSource {
|
|||
}
|
||||
|
||||
impl TaskSource for FileReadingTaskSource {
|
||||
fn queue_with_wrapper<T>(&self,
|
||||
msg: Box<T>,
|
||||
wrapper: &RunnableWrapper)
|
||||
-> Result<(), ()>
|
||||
where T: Runnable + Send + 'static {
|
||||
self.0.send(CommonScriptMsg::RunnableMsg(ScriptThreadEventCategory::FileRead,
|
||||
wrapper.wrap_runnable(msg)))
|
||||
fn queue_with_canceller<T>(
|
||||
&self,
|
||||
msg: Box<T>,
|
||||
canceller: &TaskCanceller,
|
||||
) -> Result<(), ()>
|
||||
where
|
||||
T: Send + Task + 'static,
|
||||
{
|
||||
self.0.send(CommonScriptMsg::Task(
|
||||
ScriptThreadEventCategory::FileRead,
|
||||
canceller.wrap_task(msg),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
pub struct FileReadingRunnable {
|
||||
task: FileReadingTask,
|
||||
}
|
||||
|
||||
impl FileReadingRunnable {
|
||||
pub fn new(task: FileReadingTask) -> Box<FileReadingRunnable> {
|
||||
box FileReadingRunnable {
|
||||
task: task
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Runnable for FileReadingRunnable {
|
||||
fn handler(self: Box<FileReadingRunnable>) {
|
||||
self.task.handle_task();
|
||||
impl Task for FileReadingTask {
|
||||
fn run(self: Box<Self>) {
|
||||
self.handle_task();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -10,16 +10,19 @@ pub mod performance_timeline;
|
|||
pub mod user_interaction;
|
||||
|
||||
use dom::globalscope::GlobalScope;
|
||||
use script_thread::{Runnable, RunnableWrapper};
|
||||
use std::result::Result;
|
||||
use task::{Task, TaskCanceller};
|
||||
|
||||
pub trait TaskSource {
|
||||
fn queue_with_wrapper<T>(&self,
|
||||
msg: Box<T>,
|
||||
wrapper: &RunnableWrapper)
|
||||
-> Result<(), ()>
|
||||
where T: Runnable + Send + 'static;
|
||||
fn queue<T: Runnable + Send + 'static>(&self, msg: Box<T>, global: &GlobalScope) -> Result<(), ()> {
|
||||
self.queue_with_wrapper(msg, &global.get_runnable_wrapper())
|
||||
fn queue_with_canceller<T>(
|
||||
&self,
|
||||
msg: Box<T>,
|
||||
canceller: &TaskCanceller,
|
||||
) -> Result<(), ()>
|
||||
where
|
||||
T: Send + Task + 'static;
|
||||
|
||||
fn queue<T: Task + Send + 'static>(&self, msg: Box<T>, global: &GlobalScope) -> Result<(), ()> {
|
||||
self.queue_with_canceller(msg, &global.task_canceller())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use script_runtime::{CommonScriptMsg, ScriptChan, ScriptThreadEventCategory};
|
||||
use script_thread::{Runnable, RunnableWrapper};
|
||||
use task::{Task, TaskCanceller};
|
||||
use task_source::TaskSource;
|
||||
|
||||
#[derive(JSTraceable)]
|
||||
|
@ -16,18 +16,28 @@ impl Clone for NetworkingTaskSource {
|
|||
}
|
||||
|
||||
impl TaskSource for NetworkingTaskSource {
|
||||
fn queue_with_wrapper<T>(&self,
|
||||
msg: Box<T>,
|
||||
wrapper: &RunnableWrapper)
|
||||
-> Result<(), ()>
|
||||
where T: Runnable + Send + 'static {
|
||||
self.0.send(CommonScriptMsg::RunnableMsg(ScriptThreadEventCategory::NetworkEvent,
|
||||
wrapper.wrap_runnable(msg)))
|
||||
fn queue_with_canceller<T>(
|
||||
&self,
|
||||
msg: Box<T>,
|
||||
canceller: &TaskCanceller,
|
||||
) -> Result<(), ()>
|
||||
where
|
||||
T: Send + Task + 'static,
|
||||
{
|
||||
self.0.send(CommonScriptMsg::Task(
|
||||
ScriptThreadEventCategory::NetworkEvent,
|
||||
canceller.wrap_task(msg),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
impl NetworkingTaskSource {
|
||||
pub fn queue_wrapperless<T: Runnable + Send + 'static>(&self, msg: Box<T>) -> Result<(), ()> {
|
||||
self.0.send(CommonScriptMsg::RunnableMsg(ScriptThreadEventCategory::NetworkEvent, msg))
|
||||
/// This queues a task that will not be cancelled when its associated
|
||||
/// global scope gets destroyed.
|
||||
pub fn queue_unconditionally<T>(&self, msg: Box<T>) -> Result<(), ()>
|
||||
where
|
||||
T: Task + Send + 'static,
|
||||
{
|
||||
self.0.send(CommonScriptMsg::Task(ScriptThreadEventCategory::NetworkEvent, msg))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,31 +8,12 @@
|
|||
|
||||
use dom::bindings::refcounted::Trusted;
|
||||
use dom::globalscope::GlobalScope;
|
||||
use dom::performance::Performance;
|
||||
use script_runtime::{CommonScriptMsg, ScriptChan, ScriptThreadEventCategory};
|
||||
use script_thread::{Runnable, RunnableWrapper};
|
||||
use std::fmt;
|
||||
use std::result::Result;
|
||||
use task::{Task, TaskCanceller};
|
||||
use task_source::TaskSource;
|
||||
|
||||
pub struct NotifyPerformanceObserverRunnable {
|
||||
owner: Trusted<Performance>,
|
||||
}
|
||||
|
||||
impl NotifyPerformanceObserverRunnable {
|
||||
pub fn new(owner: Trusted<Performance>) -> Self {
|
||||
NotifyPerformanceObserverRunnable {
|
||||
owner,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Runnable for NotifyPerformanceObserverRunnable {
|
||||
fn handler(self: Box<NotifyPerformanceObserverRunnable>) {
|
||||
self.owner.root().notify_observers();
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(JSTraceable)]
|
||||
pub struct PerformanceTimelineTaskSource(pub Box<ScriptChan + Send + 'static>);
|
||||
|
||||
|
@ -49,13 +30,17 @@ impl fmt::Debug for PerformanceTimelineTaskSource {
|
|||
}
|
||||
|
||||
impl TaskSource for PerformanceTimelineTaskSource {
|
||||
fn queue_with_wrapper<T>(&self,
|
||||
msg: Box<T>,
|
||||
wrapper: &RunnableWrapper) -> Result<(), ()>
|
||||
where T: Runnable + Send + 'static {
|
||||
let msg = CommonScriptMsg::RunnableMsg(
|
||||
fn queue_with_canceller<T>(
|
||||
&self,
|
||||
msg: Box<T>,
|
||||
canceller: &TaskCanceller,
|
||||
) -> Result<(), ()>
|
||||
where
|
||||
T: Send + Task + 'static,
|
||||
{
|
||||
let msg = CommonScriptMsg::Task(
|
||||
ScriptThreadEventCategory::PerformanceTimelineTask,
|
||||
wrapper.wrap_runnable(msg)
|
||||
canceller.wrap_task(msg)
|
||||
);
|
||||
self.0.send(msg).map_err(|_| ())
|
||||
}
|
||||
|
@ -64,7 +49,12 @@ impl TaskSource for PerformanceTimelineTaskSource {
|
|||
impl PerformanceTimelineTaskSource {
|
||||
pub fn queue_notification(&self, global: &GlobalScope) {
|
||||
let owner = Trusted::new(&*global.performance());
|
||||
let runnable = box NotifyPerformanceObserverRunnable::new(owner);
|
||||
let _ = self.queue(runnable, global);
|
||||
// FIXME(nox): Why are errors silenced here?
|
||||
let _ = self.queue(
|
||||
box task!(notify_performance_observers: move || {
|
||||
owner.root().notify_observers();
|
||||
}),
|
||||
global,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,15 +4,16 @@
|
|||
|
||||
use dom::bindings::inheritance::Castable;
|
||||
use dom::bindings::refcounted::Trusted;
|
||||
use dom::event::{EventBubbles, EventCancelable, EventRunnable};
|
||||
use dom::event::{EventBubbles, EventCancelable, EventTask};
|
||||
use dom::eventtarget::EventTarget;
|
||||
use dom::window::Window;
|
||||
use script_runtime::{CommonScriptMsg, ScriptThreadEventCategory};
|
||||
use script_thread::{MainThreadScriptMsg, Runnable, RunnableWrapper};
|
||||
use script_thread::MainThreadScriptMsg;
|
||||
use servo_atoms::Atom;
|
||||
use std::fmt;
|
||||
use std::result::Result;
|
||||
use std::sync::mpsc::Sender;
|
||||
use task::{Task, TaskCanceller};
|
||||
use task_source::TaskSource;
|
||||
|
||||
#[derive(Clone, JSTraceable)]
|
||||
|
@ -25,17 +26,17 @@ impl fmt::Debug for UserInteractionTaskSource {
|
|||
}
|
||||
|
||||
impl TaskSource for UserInteractionTaskSource {
|
||||
fn queue_with_wrapper<T>(
|
||||
fn queue_with_canceller<T>(
|
||||
&self,
|
||||
msg: Box<T>,
|
||||
wrapper: &RunnableWrapper,
|
||||
canceller: &TaskCanceller,
|
||||
) -> Result<(), ()>
|
||||
where
|
||||
T: Runnable + Send + 'static,
|
||||
T: Task + Send + 'static,
|
||||
{
|
||||
let msg = MainThreadScriptMsg::Common(CommonScriptMsg::RunnableMsg(
|
||||
let msg = MainThreadScriptMsg::Common(CommonScriptMsg::Task(
|
||||
ScriptThreadEventCategory::InputEvent,
|
||||
wrapper.wrap_runnable(msg),
|
||||
canceller.wrap_task(msg),
|
||||
));
|
||||
self.0.send(msg).map_err(|_| ())
|
||||
}
|
||||
|
@ -49,12 +50,7 @@ impl UserInteractionTaskSource {
|
|||
cancelable: EventCancelable,
|
||||
window: &Window) {
|
||||
let target = Trusted::new(target);
|
||||
let runnable = box EventRunnable {
|
||||
target: target,
|
||||
name: name,
|
||||
bubbles: bubbles,
|
||||
cancelable: cancelable,
|
||||
};
|
||||
let _ = self.queue(runnable, window.upcast());
|
||||
let task = box EventTask { target, name, bubbles, cancelable };
|
||||
let _ = self.queue(task, window.upcast());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -860,6 +860,12 @@ pub trait Painter: SpeculativePainter {
|
|||
-> DrawAPaintImageResult;
|
||||
}
|
||||
|
||||
impl fmt::Debug for Painter {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||
fmt.debug_tuple("Painter").field(&format_args!("..")).finish()
|
||||
}
|
||||
}
|
||||
|
||||
/// The result of executing paint code: the image together with any image URLs that need to be loaded.
|
||||
/// TODO: this should return a WR display list. https://github.com/servo/servo/issues/17497
|
||||
#[derive(Clone, Debug, Deserialize, HeapSizeOf, Serialize)]
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue