mirror of
https://github.com/servo/servo.git
synced 2025-06-06 16:45:39 +00:00
script: Move TaskManager
to GlobalScope
(#34827)
This is a simplification of the internal `TaskQueue` API that moves the `TaskManager` to the `GlobalScope` itself. In addition, the handling of cancellers is moved to the `TaskManager` as well. This means that no arguments other than the `task` are necessary for queueing tasks, which makes the API a lot easier to use and cleaner. `TaskSource` now also keeps a copy of the canceller with it, so that they always know the proper way to cancel any tasks queued on them. There is one complication here. The event loop `sender` for dedicated workers is constantly changing as it is set to `None` when not handling messages. This is because this sender keeps a handle to the main thread's `Worker` object, preventing garbage collection while any messages are still in flight or being handled. This change allows setting the `sender` on the `TaskManager` to `None` to allow proper garbabge collection. Signed-off-by: Martin Robinson <mrobinson@igalia.com>
This commit is contained in:
parent
75a22cfe2e
commit
b2eda71952
54 changed files with 1060 additions and 1516 deletions
|
@ -40,8 +40,7 @@ use crate::dom::readablestream::{get_read_promise_bytes, get_read_promise_done,
|
|||
use crate::dom::urlsearchparams::URLSearchParams;
|
||||
use crate::realms::{enter_realm, AlreadyInRealm, InRealm};
|
||||
use crate::script_runtime::{CanGc, JSContext};
|
||||
use crate::task::TaskCanceller;
|
||||
use crate::task_source::{TaskSource, TaskSourceName};
|
||||
use crate::task_source::TaskSource;
|
||||
|
||||
/// The Dom object, or ReadableStream, that is the source of a body.
|
||||
/// <https://fetch.spec.whatwg.org/#concept-body-source>
|
||||
|
@ -72,7 +71,6 @@ enum StopReading {
|
|||
struct TransmitBodyConnectHandler {
|
||||
stream: Trusted<ReadableStream>,
|
||||
task_source: TaskSource,
|
||||
canceller: TaskCanceller,
|
||||
bytes_sender: Option<IpcSender<BodyChunkResponse>>,
|
||||
control_sender: IpcSender<BodyChunkRequest>,
|
||||
in_memory: Option<Vec<u8>>,
|
||||
|
@ -84,7 +82,6 @@ impl TransmitBodyConnectHandler {
|
|||
pub fn new(
|
||||
stream: Trusted<ReadableStream>,
|
||||
task_source: TaskSource,
|
||||
canceller: TaskCanceller,
|
||||
control_sender: IpcSender<BodyChunkRequest>,
|
||||
in_memory: Option<Vec<u8>>,
|
||||
source: BodySource,
|
||||
|
@ -92,7 +89,6 @@ impl TransmitBodyConnectHandler {
|
|||
TransmitBodyConnectHandler {
|
||||
stream,
|
||||
task_source,
|
||||
canceller,
|
||||
bytes_sender: None,
|
||||
control_sender,
|
||||
in_memory,
|
||||
|
@ -178,8 +174,9 @@ impl TransmitBodyConnectHandler {
|
|||
// If we're using an actual ReadableStream, acquire a reader for it.
|
||||
if self.source == BodySource::Null {
|
||||
let stream = self.stream.clone();
|
||||
let _ = self.task_source.queue_with_canceller(
|
||||
task!(start_reading_request_body_stream: move || {
|
||||
let _ = self
|
||||
.task_source
|
||||
.queue(task!(start_reading_request_body_stream: move || {
|
||||
// Step 1, Let body be request’s body.
|
||||
let rooted_stream = stream.root();
|
||||
|
||||
|
@ -190,9 +187,7 @@ impl TransmitBodyConnectHandler {
|
|||
.expect("Couldn't acquire a reader for the body stream.");
|
||||
|
||||
// Note: this algorithm continues when the first chunk is requested by `net`.
|
||||
}),
|
||||
&self.canceller,
|
||||
);
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -236,7 +231,7 @@ impl TransmitBodyConnectHandler {
|
|||
return;
|
||||
}
|
||||
|
||||
let _ = self.task_source.queue_with_canceller(
|
||||
let _ = self.task_source.queue(
|
||||
task!(setup_native_body_promise_handler: move || {
|
||||
let rooted_stream = stream.root();
|
||||
let global = rooted_stream.global();
|
||||
|
@ -265,8 +260,7 @@ impl TransmitBodyConnectHandler {
|
|||
let realm = enter_realm(&*global);
|
||||
let comp = InRealm::Entered(&realm);
|
||||
promise.append_native_handler(&handler, comp, CanGc::note());
|
||||
}),
|
||||
&self.canceller,
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -379,7 +373,6 @@ impl ExtractedBody {
|
|||
|
||||
let global = stream.global();
|
||||
let task_source = global.task_manager().networking_task_source();
|
||||
let canceller = global.task_canceller(TaskSourceName::Networking);
|
||||
|
||||
// In case of the data being in-memory, send everything in one chunk, by-passing SM.
|
||||
let in_memory = stream.get_in_memory_bytes();
|
||||
|
@ -392,7 +385,6 @@ impl ExtractedBody {
|
|||
let mut body_handler = TransmitBodyConnectHandler::new(
|
||||
trusted_stream,
|
||||
task_source,
|
||||
canceller,
|
||||
chunk_request_sender.clone(),
|
||||
in_memory,
|
||||
source,
|
||||
|
|
|
@ -110,22 +110,17 @@ impl AnalyserNode {
|
|||
) -> Fallible<DomRoot<AnalyserNode>> {
|
||||
let (node, recv) = AnalyserNode::new_inherited(window, context, options)?;
|
||||
let object = reflect_dom_object_with_proto(Box::new(node), window, proto, can_gc);
|
||||
let (source, canceller) = window
|
||||
.task_manager()
|
||||
.dom_manipulation_task_source_with_canceller();
|
||||
let task_source = window.task_manager().dom_manipulation_task_source();
|
||||
let this = Trusted::new(&*object);
|
||||
|
||||
ROUTER.add_typed_route(
|
||||
recv,
|
||||
Box::new(move |block| {
|
||||
let this = this.clone();
|
||||
let _ = source.queue_with_canceller(
|
||||
task!(append_analysis_block: move || {
|
||||
let this = this.root();
|
||||
this.push_block(block.unwrap())
|
||||
}),
|
||||
&canceller,
|
||||
);
|
||||
let _ = task_source.queue(task!(append_analysis_block: move || {
|
||||
let this = this.root();
|
||||
this.push_block(block.unwrap())
|
||||
}));
|
||||
}),
|
||||
);
|
||||
Ok(object)
|
||||
|
|
|
@ -157,8 +157,7 @@ impl AudioContextMethods<crate::DomTypeHolder> for AudioContext {
|
|||
}
|
||||
|
||||
// Steps 4 and 5.
|
||||
let window = DomRoot::downcast::<Window>(self.global()).unwrap();
|
||||
let task_source = window.task_manager().dom_manipulation_task_source();
|
||||
let task_source = self.global().task_manager().dom_manipulation_task_source();
|
||||
let trusted_promise = TrustedPromise::new(promise.clone());
|
||||
match self.context.audio_context_impl().lock().unwrap().suspend() {
|
||||
Ok(_) => {
|
||||
|
@ -172,27 +171,21 @@ impl AudioContextMethods<crate::DomTypeHolder> for AudioContext {
|
|||
promise.resolve_native(&());
|
||||
if base_context.State() != AudioContextState::Suspended {
|
||||
base_context.set_state_attribute(AudioContextState::Suspended);
|
||||
let window = DomRoot::downcast::<Window>(context.global()).unwrap();
|
||||
window.task_manager().dom_manipulation_task_source().queue_simple_event(
|
||||
context.global().task_manager().dom_manipulation_task_source().queue_simple_event(
|
||||
context.upcast(),
|
||||
atom!("statechange"),
|
||||
&window
|
||||
);
|
||||
);
|
||||
}
|
||||
}),
|
||||
window.upcast(),
|
||||
})
|
||||
);
|
||||
},
|
||||
Err(_) => {
|
||||
// The spec does not define the error case and `suspend` should
|
||||
// never fail, but we handle the case here for completion.
|
||||
let _ = task_source.queue(
|
||||
task!(suspend_error: move || {
|
||||
let promise = trusted_promise.root();
|
||||
promise.reject_error(Error::Type("Something went wrong".to_owned()));
|
||||
}),
|
||||
window.upcast(),
|
||||
);
|
||||
let _ = task_source.queue(task!(suspend_error: move || {
|
||||
let promise = trusted_promise.root();
|
||||
promise.reject_error(Error::Type("Something went wrong".to_owned()));
|
||||
}));
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -218,8 +211,7 @@ impl AudioContextMethods<crate::DomTypeHolder> for AudioContext {
|
|||
}
|
||||
|
||||
// Steps 4 and 5.
|
||||
let window = DomRoot::downcast::<Window>(self.global()).unwrap();
|
||||
let task_source = window.task_manager().dom_manipulation_task_source();
|
||||
let task_source = self.global().task_manager().dom_manipulation_task_source();
|
||||
let trusted_promise = TrustedPromise::new(promise.clone());
|
||||
match self.context.audio_context_impl().lock().unwrap().close() {
|
||||
Ok(_) => {
|
||||
|
@ -233,27 +225,21 @@ impl AudioContextMethods<crate::DomTypeHolder> for AudioContext {
|
|||
promise.resolve_native(&());
|
||||
if base_context.State() != AudioContextState::Closed {
|
||||
base_context.set_state_attribute(AudioContextState::Closed);
|
||||
let window = DomRoot::downcast::<Window>(context.global()).unwrap();
|
||||
window.task_manager().dom_manipulation_task_source().queue_simple_event(
|
||||
context.global().task_manager().dom_manipulation_task_source().queue_simple_event(
|
||||
context.upcast(),
|
||||
atom!("statechange"),
|
||||
&window
|
||||
);
|
||||
);
|
||||
}
|
||||
}),
|
||||
window.upcast(),
|
||||
})
|
||||
);
|
||||
},
|
||||
Err(_) => {
|
||||
// The spec does not define the error case and `suspend` should
|
||||
// never fail, but we handle the case here for completion.
|
||||
let _ = task_source.queue(
|
||||
task!(suspend_error: move || {
|
||||
let promise = trusted_promise.root();
|
||||
promise.reject_error(Error::Type("Something went wrong".to_owned()));
|
||||
}),
|
||||
window.upcast(),
|
||||
);
|
||||
let _ = task_source.queue(task!(suspend_error: move || {
|
||||
let promise = trusted_promise.root();
|
||||
promise.reject_error(Error::Type("Something went wrong".to_owned()));
|
||||
}));
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -71,25 +71,15 @@ impl AudioScheduledSourceNodeMethods<crate::DomTypeHolder> for AudioScheduledSou
|
|||
}
|
||||
|
||||
let this = Trusted::new(self);
|
||||
let global = self.global();
|
||||
let window = global.as_window();
|
||||
let (task_source, canceller) = window
|
||||
.task_manager()
|
||||
.dom_manipulation_task_source_with_canceller();
|
||||
let task_source = self.global().task_manager().dom_manipulation_task_source();
|
||||
let callback = OnEndedCallback::new(move || {
|
||||
let _ = task_source.queue_with_canceller(
|
||||
task!(ended: move || {
|
||||
let this = this.root();
|
||||
let global = this.global();
|
||||
let window = global.as_window();
|
||||
window.task_manager().dom_manipulation_task_source().queue_simple_event(
|
||||
this.upcast(),
|
||||
atom!("ended"),
|
||||
window
|
||||
);
|
||||
}),
|
||||
&canceller,
|
||||
);
|
||||
let _ = task_source.queue(task!(ended: move || {
|
||||
let this = this.root();
|
||||
this.global().task_manager().dom_manipulation_task_source().queue_simple_event(
|
||||
this.upcast(),
|
||||
atom!("ended"),
|
||||
);
|
||||
}));
|
||||
});
|
||||
|
||||
self.node()
|
||||
|
|
|
@ -89,18 +89,11 @@ impl AudioTrackList {
|
|||
// Queue a task to fire an event named change.
|
||||
let global = &self.global();
|
||||
let this = Trusted::new(self);
|
||||
let (source, canceller) = global
|
||||
.as_window()
|
||||
.task_manager()
|
||||
.media_element_task_source_with_canceller();
|
||||
|
||||
let _ = source.queue_with_canceller(
|
||||
task!(media_track_change: move || {
|
||||
let this = this.root();
|
||||
this.upcast::<EventTarget>().fire_event(atom!("change"), CanGc::note());
|
||||
}),
|
||||
&canceller,
|
||||
);
|
||||
let task_source = global.task_manager().media_element_task_source();
|
||||
let _ = task_source.queue(task!(media_track_change: move || {
|
||||
let this = this.root();
|
||||
this.upcast::<EventTarget>().fire_event(atom!("change"), CanGc::note());
|
||||
}));
|
||||
}
|
||||
|
||||
pub fn add(&self, track: &AudioTrack) {
|
||||
|
|
|
@ -65,7 +65,6 @@ use crate::dom::oscillatornode::OscillatorNode;
|
|||
use crate::dom::pannernode::PannerNode;
|
||||
use crate::dom::promise::Promise;
|
||||
use crate::dom::stereopannernode::StereoPannerNode;
|
||||
use crate::dom::window::Window;
|
||||
use crate::realms::InRealm;
|
||||
use crate::script_runtime::CanGc;
|
||||
|
||||
|
@ -230,9 +229,7 @@ impl BaseAudioContext {
|
|||
}
|
||||
|
||||
pub fn resume(&self) {
|
||||
let global = self.global();
|
||||
let window = global.as_window();
|
||||
let task_source = window.task_manager().dom_manipulation_task_source();
|
||||
let task_source = self.global().task_manager().dom_manipulation_task_source();
|
||||
let this = Trusted::new(self);
|
||||
// Set the rendering thread state to 'running' and start
|
||||
// rendering the audio graph.
|
||||
|
@ -245,28 +242,22 @@ impl BaseAudioContext {
|
|||
this.fulfill_in_flight_resume_promises(|| {
|
||||
if this.state.get() != AudioContextState::Running {
|
||||
this.state.set(AudioContextState::Running);
|
||||
let window = DomRoot::downcast::<Window>(this.global()).unwrap();
|
||||
window.task_manager().dom_manipulation_task_source().queue_simple_event(
|
||||
this.global().task_manager().dom_manipulation_task_source().queue_simple_event(
|
||||
this.upcast(),
|
||||
atom!("statechange"),
|
||||
&window
|
||||
);
|
||||
}
|
||||
});
|
||||
}),
|
||||
window.upcast(),
|
||||
})
|
||||
);
|
||||
},
|
||||
Err(()) => {
|
||||
self.take_pending_resume_promises(Err(Error::Type(
|
||||
"Something went wrong".to_owned(),
|
||||
)));
|
||||
let _ = task_source.queue(
|
||||
task!(resume_error: move || {
|
||||
this.root().fulfill_in_flight_resume_promises(|| {})
|
||||
}),
|
||||
window.upcast(),
|
||||
);
|
||||
let _ = task_source.queue(task!(resume_error: move || {
|
||||
this.root().fulfill_in_flight_resume_promises(|| {})
|
||||
}));
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -485,8 +476,6 @@ impl BaseAudioContextMethods<crate::DomTypeHolder> for BaseAudioContext {
|
|||
) -> Rc<Promise> {
|
||||
// Step 1.
|
||||
let promise = Promise::new_in_current_realm(comp, can_gc);
|
||||
let global = self.global();
|
||||
let window = global.as_window();
|
||||
|
||||
if audio_data.len() > 0 {
|
||||
// Step 2.
|
||||
|
@ -512,12 +501,8 @@ impl BaseAudioContextMethods<crate::DomTypeHolder> for BaseAudioContext {
|
|||
let channels = Arc::new(Mutex::new(HashMap::new()));
|
||||
let this = Trusted::new(self);
|
||||
let this_ = this.clone();
|
||||
let (task_source, canceller) = window
|
||||
.task_manager()
|
||||
.dom_manipulation_task_source_with_canceller();
|
||||
let (task_source_, canceller_) = window
|
||||
.task_manager()
|
||||
.dom_manipulation_task_source_with_canceller();
|
||||
let task_source = self.global().task_manager().dom_manipulation_task_source();
|
||||
let task_source_clone = task_source.clone();
|
||||
let callbacks = AudioDecoderCallbacks::new()
|
||||
.ready(move |channel_count| {
|
||||
decoded_audio
|
||||
|
@ -538,36 +523,32 @@ impl BaseAudioContextMethods<crate::DomTypeHolder> for BaseAudioContext {
|
|||
decoded_audio[channel].extend_from_slice((*buffer).as_ref());
|
||||
})
|
||||
.eos(move || {
|
||||
let _ = task_source.queue_with_canceller(
|
||||
task!(audio_decode_eos: move || {
|
||||
let this = this.root();
|
||||
let decoded_audio = decoded_audio__.lock().unwrap();
|
||||
let length = if decoded_audio.len() >= 1 {
|
||||
decoded_audio[0].len()
|
||||
} else {
|
||||
0
|
||||
};
|
||||
let buffer = AudioBuffer::new(
|
||||
this.global().as_window(),
|
||||
decoded_audio.len() as u32 /* number of channels */,
|
||||
length as u32,
|
||||
this.sample_rate,
|
||||
Some(decoded_audio.as_slice()),
|
||||
CanGc::note());
|
||||
let mut resolvers = this.decode_resolvers.borrow_mut();
|
||||
assert!(resolvers.contains_key(&uuid_));
|
||||
let resolver = resolvers.remove(&uuid_).unwrap();
|
||||
if let Some(callback) = resolver.success_callback {
|
||||
let _ = callback.Call__(&buffer, ExceptionHandling::Report);
|
||||
}
|
||||
resolver.promise.resolve_native(&buffer);
|
||||
}),
|
||||
&canceller,
|
||||
);
|
||||
let _ = task_source.queue(task!(audio_decode_eos: move || {
|
||||
let this = this.root();
|
||||
let decoded_audio = decoded_audio__.lock().unwrap();
|
||||
let length = if decoded_audio.len() >= 1 {
|
||||
decoded_audio[0].len()
|
||||
} else {
|
||||
0
|
||||
};
|
||||
let buffer = AudioBuffer::new(
|
||||
this.global().as_window(),
|
||||
decoded_audio.len() as u32 /* number of channels */,
|
||||
length as u32,
|
||||
this.sample_rate,
|
||||
Some(decoded_audio.as_slice()),
|
||||
CanGc::note());
|
||||
let mut resolvers = this.decode_resolvers.borrow_mut();
|
||||
assert!(resolvers.contains_key(&uuid_));
|
||||
let resolver = resolvers.remove(&uuid_).unwrap();
|
||||
if let Some(callback) = resolver.success_callback {
|
||||
let _ = callback.Call__(&buffer, ExceptionHandling::Report);
|
||||
}
|
||||
resolver.promise.resolve_native(&buffer);
|
||||
}));
|
||||
})
|
||||
.error(move |error| {
|
||||
let _ = task_source_.queue_with_canceller(
|
||||
task!(audio_decode_eos: move || {
|
||||
let _ = task_source_clone.queue(task!(audio_decode_eos: move || {
|
||||
let this = this_.root();
|
||||
let mut resolvers = this.decode_resolvers.borrow_mut();
|
||||
assert!(resolvers.contains_key(&uuid));
|
||||
|
@ -579,9 +560,7 @@ impl BaseAudioContextMethods<crate::DomTypeHolder> for BaseAudioContext {
|
|||
}
|
||||
let error = format!("Audio decode error {:?}", error);
|
||||
resolver.promise.reject_error(Error::Type(error));
|
||||
}),
|
||||
&canceller_,
|
||||
);
|
||||
}));
|
||||
})
|
||||
.build();
|
||||
self.audio_context_impl
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use std::mem::replace;
|
||||
use std::sync::atomic::AtomicBool;
|
||||
use std::sync::Arc;
|
||||
use std::thread::{self, JoinHandle};
|
||||
|
@ -76,9 +75,10 @@ impl<'a> AutoWorkerReset<'a> {
|
|||
workerscope: &'a DedicatedWorkerGlobalScope,
|
||||
worker: TrustedWorkerAddress,
|
||||
) -> AutoWorkerReset<'a> {
|
||||
let old_worker = workerscope.replace_worker(Some(worker));
|
||||
AutoWorkerReset {
|
||||
workerscope,
|
||||
old_worker: replace(&mut *workerscope.worker.borrow_mut(), Some(worker)),
|
||||
old_worker,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -86,9 +86,7 @@ impl<'a> AutoWorkerReset<'a> {
|
|||
impl Drop for AutoWorkerReset<'_> {
|
||||
fn drop(&mut self) {
|
||||
self.workerscope
|
||||
.worker
|
||||
.borrow_mut()
|
||||
.clone_from(&self.old_worker)
|
||||
.replace_worker(std::mem::take(&mut self.old_worker));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -387,6 +385,7 @@ impl DedicatedWorkerGlobalScope {
|
|||
}),
|
||||
pipeline_id,
|
||||
name: TaskSourceName::Networking,
|
||||
canceller: Default::default(),
|
||||
};
|
||||
Runtime::new_with_parent(Some(parent), Some(task_source))
|
||||
};
|
||||
|
@ -501,15 +500,38 @@ impl DedicatedWorkerGlobalScope {
|
|||
.expect("Thread spawning failed")
|
||||
}
|
||||
|
||||
/// The non-None value of the `worker` field can contain a rooted [`TrustedWorkerAddress`]
|
||||
/// version of the main thread's worker object. This is set while handling messages and then
|
||||
/// unset otherwise, ensuring that the main thread object can be garbage collected. See
|
||||
/// [`AutoWorkerReset`].
|
||||
fn replace_worker(
|
||||
&self,
|
||||
new_worker: Option<TrustedWorkerAddress>,
|
||||
) -> Option<TrustedWorkerAddress> {
|
||||
let old_worker = std::mem::replace(&mut *self.worker.borrow_mut(), new_worker);
|
||||
|
||||
// The `TaskManager` maintains a handle to this `DedicatedWorkerGlobalScope`'s
|
||||
// event_loop_sender, which might in turn have a `TrustedWorkerAddress` rooting of the main
|
||||
// thread's worker, which prevents garbage collection. Resetting it here ensures that
|
||||
// garbage collection of the main thread object can happen again (assuming the new `worker`
|
||||
// is `None`).
|
||||
self.upcast::<GlobalScope>()
|
||||
.task_manager()
|
||||
.set_sender(self.event_loop_sender());
|
||||
|
||||
old_worker
|
||||
}
|
||||
|
||||
pub fn image_cache(&self) -> Arc<dyn ImageCache> {
|
||||
self.image_cache.clone()
|
||||
}
|
||||
|
||||
pub fn script_chan(&self) -> Box<dyn ScriptChan + Send> {
|
||||
Box::new(WorkerThreadWorkerChan {
|
||||
pub(crate) fn event_loop_sender(&self) -> Option<Box<dyn ScriptChan + Send>> {
|
||||
let worker = self.worker.borrow().clone()?;
|
||||
Some(Box::new(WorkerThreadWorkerChan {
|
||||
sender: self.own_sender.clone(),
|
||||
worker: self.worker.borrow().as_ref().unwrap().clone(),
|
||||
})
|
||||
worker,
|
||||
}))
|
||||
}
|
||||
|
||||
pub fn new_script_pair(&self) -> (Box<dyn ScriptChan + Send>, Box<dyn ScriptPort + Send>) {
|
||||
|
|
|
@ -696,37 +696,34 @@ impl Document {
|
|||
// But it's now Step 4 in https://html.spec.whatwg.org/multipage/#reactivate-a-document
|
||||
// TODO: See #32687 for more information.
|
||||
let document = Trusted::new(self);
|
||||
self.window
|
||||
self.window()
|
||||
.task_manager()
|
||||
.dom_manipulation_task_source()
|
||||
.queue(
|
||||
task!(fire_pageshow_event: move || {
|
||||
let document = document.root();
|
||||
let window = document.window();
|
||||
// Step 4.6.1
|
||||
if document.page_showing.get() {
|
||||
return;
|
||||
}
|
||||
// Step 4.6.2 Set document's page showing flag to true.
|
||||
document.page_showing.set(true);
|
||||
// Step 4.6.3 Update the visibility state of document to "visible".
|
||||
document.update_visibility_state(DocumentVisibilityState::Visible, CanGc::note());
|
||||
// Step 4.6.4 Fire a page transition event named pageshow at document's relevant
|
||||
// global object with true.
|
||||
let event = PageTransitionEvent::new(
|
||||
window,
|
||||
atom!("pageshow"),
|
||||
false, // bubbles
|
||||
false, // cancelable
|
||||
true, // persisted
|
||||
CanGc::note(),
|
||||
);
|
||||
let event = event.upcast::<Event>();
|
||||
event.set_trusted(true);
|
||||
window.dispatch_event_with_target_override(event, CanGc::note());
|
||||
}),
|
||||
self.window.upcast(),
|
||||
)
|
||||
.queue(task!(fire_pageshow_event: move || {
|
||||
let document = document.root();
|
||||
let window = document.window();
|
||||
// Step 4.6.1
|
||||
if document.page_showing.get() {
|
||||
return;
|
||||
}
|
||||
// Step 4.6.2 Set document's page showing flag to true.
|
||||
document.page_showing.set(true);
|
||||
// Step 4.6.3 Update the visibility state of document to "visible".
|
||||
document.update_visibility_state(DocumentVisibilityState::Visible, CanGc::note());
|
||||
// Step 4.6.4 Fire a page transition event named pageshow at document's relevant
|
||||
// global object with true.
|
||||
let event = PageTransitionEvent::new(
|
||||
window,
|
||||
atom!("pageshow"),
|
||||
false, // bubbles
|
||||
false, // cancelable
|
||||
true, // persisted
|
||||
CanGc::note(),
|
||||
);
|
||||
let event = event.upcast::<Event>();
|
||||
event.set_trusted(true);
|
||||
window.dispatch_event_with_target_override(event, CanGc::note());
|
||||
}))
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
|
@ -2129,14 +2126,9 @@ impl Document {
|
|||
request: RequestBuilder,
|
||||
listener: Listener,
|
||||
) {
|
||||
let (task_source, canceller) = self
|
||||
.window()
|
||||
.task_manager()
|
||||
.networking_task_source_with_canceller();
|
||||
let callback = NetworkListener {
|
||||
context: std::sync::Arc::new(Mutex::new(listener)),
|
||||
task_source,
|
||||
canceller: Some(canceller),
|
||||
task_source: self.window().task_manager().networking_task_source(),
|
||||
}
|
||||
.into_callback();
|
||||
self.loader_mut()
|
||||
|
@ -2149,14 +2141,9 @@ impl Document {
|
|||
listener: Listener,
|
||||
cancel_override: Option<ipc::IpcReceiver<()>>,
|
||||
) {
|
||||
let (task_source, canceller) = self
|
||||
.window()
|
||||
.task_manager()
|
||||
.networking_task_source_with_canceller();
|
||||
let callback = NetworkListener {
|
||||
context: std::sync::Arc::new(Mutex::new(listener)),
|
||||
task_source,
|
||||
canceller: Some(canceller),
|
||||
task_source: self.window().task_manager().networking_task_source(),
|
||||
}
|
||||
.into_callback();
|
||||
self.loader_mut()
|
||||
|
@ -2384,81 +2371,75 @@ impl Document {
|
|||
// Step 7.
|
||||
debug!("Document loads are complete.");
|
||||
let document = Trusted::new(self);
|
||||
self.window
|
||||
self.window()
|
||||
.task_manager()
|
||||
.dom_manipulation_task_source()
|
||||
.queue(
|
||||
task!(fire_load_event: move || {
|
||||
let document = document.root();
|
||||
let window = document.window();
|
||||
if !window.is_alive() {
|
||||
return;
|
||||
}
|
||||
.queue(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, CanGc::note());
|
||||
// Step 7.1.
|
||||
document.set_ready_state(DocumentReadyState::Complete, CanGc::note());
|
||||
|
||||
// Step 7.2.
|
||||
if document.browsing_context().is_none() {
|
||||
return;
|
||||
}
|
||||
let event = Event::new(
|
||||
window.upcast(),
|
||||
atom!("load"),
|
||||
EventBubbles::DoesNotBubble,
|
||||
EventCancelable::NotCancelable,
|
||||
CanGc::note(),
|
||||
);
|
||||
event.set_trusted(true);
|
||||
// Step 7.2.
|
||||
if document.browsing_context().is_none() {
|
||||
return;
|
||||
}
|
||||
let event = Event::new(
|
||||
window.upcast(),
|
||||
atom!("load"),
|
||||
EventBubbles::DoesNotBubble,
|
||||
EventCancelable::NotCancelable,
|
||||
CanGc::note(),
|
||||
);
|
||||
event.set_trusted(true);
|
||||
|
||||
// http://w3c.github.io/navigation-timing/#widl-PerformanceNavigationTiming-loadEventStart
|
||||
update_with_current_instant(&document.load_event_start);
|
||||
// http://w3c.github.io/navigation-timing/#widl-PerformanceNavigationTiming-loadEventStart
|
||||
update_with_current_instant(&document.load_event_start);
|
||||
|
||||
debug!("About to dispatch load for {:?}", document.url());
|
||||
window.dispatch_event_with_target_override(&event, CanGc::note());
|
||||
debug!("About to dispatch load for {:?}", document.url());
|
||||
window.dispatch_event_with_target_override(&event, CanGc::note());
|
||||
|
||||
// http://w3c.github.io/navigation-timing/#widl-PerformanceNavigationTiming-loadEventEnd
|
||||
update_with_current_instant(&document.load_event_end);
|
||||
// http://w3c.github.io/navigation-timing/#widl-PerformanceNavigationTiming-loadEventEnd
|
||||
update_with_current_instant(&document.load_event_end);
|
||||
|
||||
if let Some(fragment) = document.url().fragment() {
|
||||
document.check_and_scroll_fragment(fragment, CanGc::note());
|
||||
}
|
||||
}),
|
||||
self.window.upcast(),
|
||||
)
|
||||
if let Some(fragment) = document.url().fragment() {
|
||||
document.check_and_scroll_fragment(fragment, CanGc::note());
|
||||
}
|
||||
}))
|
||||
.unwrap();
|
||||
|
||||
// Step 8.
|
||||
let document = Trusted::new(self);
|
||||
if document.root().browsing_context().is_some() {
|
||||
self.window
|
||||
self.window()
|
||||
.task_manager()
|
||||
.dom_manipulation_task_source()
|
||||
.queue(
|
||||
task!(fire_pageshow_event: move || {
|
||||
let document = document.root();
|
||||
let window = document.window();
|
||||
if document.page_showing.get() || !window.is_alive() {
|
||||
return;
|
||||
}
|
||||
.queue(task!(fire_pageshow_event: move || {
|
||||
let document = document.root();
|
||||
let window = document.window();
|
||||
if document.page_showing.get() || !window.is_alive() {
|
||||
return;
|
||||
}
|
||||
|
||||
document.page_showing.set(true);
|
||||
document.page_showing.set(true);
|
||||
|
||||
let event = PageTransitionEvent::new(
|
||||
window,
|
||||
atom!("pageshow"),
|
||||
false, // bubbles
|
||||
false, // cancelable
|
||||
false, // persisted
|
||||
CanGc::note(),
|
||||
);
|
||||
let event = event.upcast::<Event>();
|
||||
event.set_trusted(true);
|
||||
let event = PageTransitionEvent::new(
|
||||
window,
|
||||
atom!("pageshow"),
|
||||
false, // bubbles
|
||||
false, // cancelable
|
||||
false, // persisted
|
||||
CanGc::note(),
|
||||
);
|
||||
let event = event.upcast::<Event>();
|
||||
event.set_trusted(true);
|
||||
|
||||
window.dispatch_event_with_target_override(event, CanGc::note());
|
||||
}),
|
||||
self.window.upcast(),
|
||||
)
|
||||
window.dispatch_event_with_target_override(event, CanGc::note());
|
||||
}))
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
|
@ -2486,32 +2467,29 @@ impl Document {
|
|||
// TODO: fully implement "completely loaded".
|
||||
let document = Trusted::new(self);
|
||||
if document.root().browsing_context().is_some() {
|
||||
self.window
|
||||
self.window()
|
||||
.task_manager()
|
||||
.dom_manipulation_task_source()
|
||||
.queue(
|
||||
task!(completely_loaded: move || {
|
||||
let document = document.root();
|
||||
document.completely_loaded.set(true);
|
||||
if let Some(DeclarativeRefresh::PendingLoad {
|
||||
url,
|
||||
time
|
||||
}) = &*document.declarative_refresh.borrow() {
|
||||
// https://html.spec.whatwg.org/multipage/#shared-declarative-refresh-steps
|
||||
document.window.upcast::<GlobalScope>().schedule_callback(
|
||||
OneshotTimerCallback::RefreshRedirectDue(RefreshRedirectDue {
|
||||
window: DomRoot::from_ref(document.window()),
|
||||
url: url.clone(),
|
||||
}),
|
||||
Duration::from_secs(*time),
|
||||
);
|
||||
}
|
||||
// Note: this will, among others, result in the "iframe-load-event-steps" being run.
|
||||
// https://html.spec.whatwg.org/multipage/#iframe-load-event-steps
|
||||
document.notify_constellation_load();
|
||||
}),
|
||||
self.window.upcast(),
|
||||
)
|
||||
.queue(task!(completely_loaded: move || {
|
||||
let document = document.root();
|
||||
document.completely_loaded.set(true);
|
||||
if let Some(DeclarativeRefresh::PendingLoad {
|
||||
url,
|
||||
time
|
||||
}) = &*document.declarative_refresh.borrow() {
|
||||
// https://html.spec.whatwg.org/multipage/#shared-declarative-refresh-steps
|
||||
document.window.upcast::<GlobalScope>().schedule_callback(
|
||||
OneshotTimerCallback::RefreshRedirectDue(RefreshRedirectDue {
|
||||
window: DomRoot::from_ref(document.window()),
|
||||
url: url.clone(),
|
||||
}),
|
||||
Duration::from_secs(*time),
|
||||
);
|
||||
}
|
||||
// Note: this will, among others, result in the "iframe-load-event-steps" being run.
|
||||
// https://html.spec.whatwg.org/multipage/#iframe-load-event-steps
|
||||
document.notify_constellation_load();
|
||||
}))
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
@ -2657,9 +2635,8 @@ impl Document {
|
|||
update_with_current_instant(&self.dom_content_loaded_event_start);
|
||||
|
||||
// Step 4.1.
|
||||
let window = self.window();
|
||||
let document = Trusted::new(self);
|
||||
window
|
||||
self.window()
|
||||
.task_manager()
|
||||
.dom_manipulation_task_source()
|
||||
.queue(
|
||||
|
@ -2667,8 +2644,7 @@ impl Document {
|
|||
let document = document.root();
|
||||
document.upcast::<EventTarget>().fire_bubbling_event(atom!("DOMContentLoaded"), CanGc::note());
|
||||
update_with_current_instant(&document.dom_content_loaded_event_end);
|
||||
}),
|
||||
window.upcast(),
|
||||
})
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
|
@ -2713,8 +2689,9 @@ impl Document {
|
|||
// Note: the spec says to discard any tasks queued for fetch.
|
||||
// This cancels all tasks on the networking task source, which might be too broad.
|
||||
// See https://github.com/whatwg/html/issues/3837
|
||||
self.window
|
||||
.cancel_all_tasks_from_source(TaskSourceName::Networking);
|
||||
self.window()
|
||||
.task_manager()
|
||||
.cancel_pending_tasks_for_source(TaskSourceName::Networking);
|
||||
|
||||
// Step 3.
|
||||
if let Some(parser) = self.get_current_parser() {
|
||||
|
|
|
@ -45,7 +45,6 @@ use crate::fetch::{create_a_potential_cors_request, FetchCanceller};
|
|||
use crate::network_listener::{self, NetworkListener, PreInvoke, ResourceTimingListener};
|
||||
use crate::realms::enter_realm;
|
||||
use crate::script_runtime::CanGc;
|
||||
use crate::task_source::TaskSourceName;
|
||||
use crate::timers::OneshotTimerCallback;
|
||||
|
||||
const DEFAULT_RECONNECTION_TIME: Duration = Duration::from_millis(5000);
|
||||
|
@ -121,7 +120,6 @@ impl EventSourceContext {
|
|||
event_source.upcast::<EventTarget>().fire_event(atom!("open"), CanGc::note());
|
||||
}
|
||||
}),
|
||||
&global,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -177,7 +175,6 @@ impl EventSourceContext {
|
|||
// FIXME(nox): Why are errors silenced here?
|
||||
let _ = event_source.global().schedule_callback(callback, duration);
|
||||
}),
|
||||
&global,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -266,7 +263,6 @@ impl EventSourceContext {
|
|||
event.root().upcast::<Event>().fire(event_source.upcast(), CanGc::note());
|
||||
}
|
||||
}),
|
||||
&global,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -508,7 +504,6 @@ impl EventSource {
|
|||
event_source.upcast::<EventTarget>().fire_event(atom!("error"), CanGc::note());
|
||||
}
|
||||
}),
|
||||
&global,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -606,7 +601,6 @@ impl EventSourceMethods<crate::DomTypeHolder> for EventSource {
|
|||
let listener = NetworkListener {
|
||||
context: Arc::new(Mutex::new(context)),
|
||||
task_source: global.task_manager().networking_task_source(),
|
||||
canceller: Some(global.task_canceller(TaskSourceName::Networking)),
|
||||
};
|
||||
ROUTER.add_typed_route(
|
||||
action_receiver,
|
||||
|
|
|
@ -37,7 +37,6 @@ use crate::dom::progressevent::ProgressEvent;
|
|||
use crate::realms::enter_realm;
|
||||
use crate::script_runtime::{CanGc, JSContext};
|
||||
use crate::task::TaskOnce;
|
||||
use crate::task_source::TaskSourceName;
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub enum FileReadingTask {
|
||||
|
@ -503,20 +502,27 @@ impl FileReader {
|
|||
|
||||
let filereader = Trusted::new(self);
|
||||
let global = self.global();
|
||||
let canceller = global.task_canceller(TaskSourceName::FileReading);
|
||||
let task_source = global.task_manager().file_reading_task_source();
|
||||
|
||||
// Queue tasks as appropriate.
|
||||
let task = FileReadingTask::ProcessRead(filereader.clone(), gen_id);
|
||||
task_source.queue_with_canceller(task, &canceller).unwrap();
|
||||
task_source
|
||||
.queue(FileReadingTask::ProcessRead(filereader.clone(), gen_id))
|
||||
.unwrap();
|
||||
|
||||
if !blob_contents.is_empty() {
|
||||
let task = FileReadingTask::ProcessReadData(filereader.clone(), gen_id);
|
||||
task_source.queue_with_canceller(task, &canceller).unwrap();
|
||||
task_source
|
||||
.queue(FileReadingTask::ProcessReadData(filereader.clone(), gen_id))
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
let task = FileReadingTask::ProcessReadEOF(filereader, gen_id, load_data, blob_contents);
|
||||
task_source.queue_with_canceller(task, &canceller).unwrap();
|
||||
task_source
|
||||
.queue(FileReadingTask::ProcessReadEOF(
|
||||
filereader,
|
||||
gen_id,
|
||||
load_data,
|
||||
blob_contents,
|
||||
))
|
||||
.unwrap();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -27,11 +27,9 @@ use crate::dom::globalscope::GlobalScope;
|
|||
use crate::dom::promise::Promise;
|
||||
use crate::realms::InRealm;
|
||||
use crate::script_runtime::{CanGc, JSContext};
|
||||
use crate::task::TaskCanceller;
|
||||
use crate::task_source::{TaskSource, TaskSourceName};
|
||||
use crate::task_source::TaskSource;
|
||||
|
||||
struct HapticEffectListener {
|
||||
canceller: TaskCanceller,
|
||||
task_source: TaskSource,
|
||||
context: Trusted<GamepadHapticActuator>,
|
||||
}
|
||||
|
@ -39,24 +37,22 @@ struct HapticEffectListener {
|
|||
impl HapticEffectListener {
|
||||
fn handle_stopped(&self, stopped_successfully: bool) {
|
||||
let context = self.context.clone();
|
||||
let _ = self.task_source.queue_with_canceller(
|
||||
task!(handle_haptic_effect_stopped: move || {
|
||||
let _ = self
|
||||
.task_source
|
||||
.queue(task!(handle_haptic_effect_stopped: move || {
|
||||
let actuator = context.root();
|
||||
actuator.handle_haptic_effect_stopped(stopped_successfully);
|
||||
}),
|
||||
&self.canceller,
|
||||
);
|
||||
}));
|
||||
}
|
||||
|
||||
fn handle_completed(&self, completed_successfully: bool) {
|
||||
let context = self.context.clone();
|
||||
let _ = self.task_source.queue_with_canceller(
|
||||
task!(handle_haptic_effect_completed: move || {
|
||||
let _ = self
|
||||
.task_source
|
||||
.queue(task!(handle_haptic_effect_completed: move || {
|
||||
let actuator = context.root();
|
||||
actuator.handle_haptic_effect_completed(completed_successfully);
|
||||
}),
|
||||
&self.canceller,
|
||||
);
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -204,7 +200,6 @@ impl GamepadHapticActuatorMethods<crate::DomTypeHolder> for GamepadHapticActuato
|
|||
let message = DOMString::from("preempted");
|
||||
promise.resolve_native(&message);
|
||||
}),
|
||||
&self.global(),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -219,13 +214,8 @@ impl GamepadHapticActuatorMethods<crate::DomTypeHolder> for GamepadHapticActuato
|
|||
let context = Trusted::new(self);
|
||||
let (effect_complete_sender, effect_complete_receiver) =
|
||||
ipc::channel().expect("ipc channel failure");
|
||||
let (task_source, canceller) = (
|
||||
self.global().task_manager().gamepad_task_source(),
|
||||
self.global().task_canceller(TaskSourceName::Gamepad),
|
||||
);
|
||||
let listener = HapticEffectListener {
|
||||
canceller,
|
||||
task_source,
|
||||
task_source: self.global().task_manager().gamepad_task_source(),
|
||||
context,
|
||||
};
|
||||
|
||||
|
@ -277,7 +267,6 @@ impl GamepadHapticActuatorMethods<crate::DomTypeHolder> for GamepadHapticActuato
|
|||
let message = DOMString::from("preempted");
|
||||
promise.resolve_native(&message);
|
||||
}),
|
||||
&self.global(),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -288,13 +277,8 @@ impl GamepadHapticActuatorMethods<crate::DomTypeHolder> for GamepadHapticActuato
|
|||
let context = Trusted::new(self);
|
||||
let (effect_stop_sender, effect_stop_receiver) =
|
||||
ipc::channel().expect("ipc channel failure");
|
||||
let (task_source, canceller) = (
|
||||
self.global().task_manager().gamepad_task_source(),
|
||||
self.global().task_canceller(TaskSourceName::Gamepad),
|
||||
);
|
||||
let listener = HapticEffectListener {
|
||||
canceller,
|
||||
task_source,
|
||||
task_source: self.global().task_manager().gamepad_task_source(),
|
||||
context,
|
||||
};
|
||||
|
||||
|
@ -350,8 +334,7 @@ impl GamepadHapticActuator {
|
|||
let promise = trusted_promise.root();
|
||||
let message = DOMString::from("complete");
|
||||
promise.resolve_native(&message);
|
||||
}),
|
||||
&self.global(),
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -372,7 +355,6 @@ impl GamepadHapticActuator {
|
|||
let message = DOMString::from("preempted");
|
||||
promise.resolve_native(&message);
|
||||
}),
|
||||
&self.global(),
|
||||
);
|
||||
|
||||
let (send, _rcv) = ipc::channel().expect("ipc channel failure");
|
||||
|
|
|
@ -70,6 +70,7 @@ use super::bindings::codegen::Bindings::MessagePortBinding::StructuredSerializeO
|
|||
use super::bindings::codegen::Bindings::WebGPUBinding::GPUDeviceLostReason;
|
||||
use super::bindings::error::Fallible;
|
||||
use super::bindings::trace::{HashMapTracedValues, RootedTraceableBox};
|
||||
use super::serviceworkerglobalscope::ServiceWorkerGlobalScope;
|
||||
use crate::dom::bindings::cell::{DomRefCell, RefMut};
|
||||
use crate::dom::bindings::codegen::Bindings::BroadcastChannelBinding::BroadcastChannelMethods;
|
||||
use crate::dom::bindings::codegen::Bindings::EventSourceBinding::EventSource_Binding::EventSourceMethods;
|
||||
|
@ -127,7 +128,6 @@ use crate::dom::webgpu::identityhub::IdentityHub;
|
|||
use crate::dom::window::Window;
|
||||
use crate::dom::workerglobalscope::WorkerGlobalScope;
|
||||
use crate::dom::workletglobalscope::WorkletGlobalScope;
|
||||
use crate::messaging::MainThreadScriptChan;
|
||||
use crate::microtask::{Microtask, MicrotaskQueue, UserMicrotask};
|
||||
use crate::network_listener::{NetworkListener, PreInvoke};
|
||||
use crate::realms::{enter_realm, AlreadyInRealm, InRealm};
|
||||
|
@ -137,9 +137,8 @@ use crate::script_runtime::{
|
|||
};
|
||||
use crate::script_thread::{with_script_thread, ScriptThread};
|
||||
use crate::security_manager::CSPViolationReporter;
|
||||
use crate::task::TaskCanceller;
|
||||
use crate::task_manager::TaskManager;
|
||||
use crate::task_source::{TaskSource, TaskSourceName};
|
||||
use crate::task_source::TaskSource;
|
||||
use crate::timers::{
|
||||
IsInterval, OneshotTimerCallback, OneshotTimerHandle, OneshotTimers, TimerCallback,
|
||||
};
|
||||
|
@ -195,6 +194,9 @@ pub struct GlobalScope {
|
|||
eventtarget: EventTarget,
|
||||
crypto: MutNullableDom<Crypto>,
|
||||
|
||||
/// A [`TaskManager`] for this [`GlobalScope`].
|
||||
task_manager: OnceCell<TaskManager>,
|
||||
|
||||
/// The message-port router id for this global, if it is managing ports.
|
||||
message_port_state: DomRefCell<MessagePortState>,
|
||||
|
||||
|
@ -374,14 +376,12 @@ pub struct GlobalScope {
|
|||
|
||||
/// A wrapper for glue-code between the ipc router and the event-loop.
|
||||
struct MessageListener {
|
||||
canceller: TaskCanceller,
|
||||
task_source: TaskSource,
|
||||
context: Trusted<GlobalScope>,
|
||||
}
|
||||
|
||||
/// A wrapper for broadcasts coming in over IPC, and the event-loop.
|
||||
struct BroadcastListener {
|
||||
canceller: TaskCanceller,
|
||||
task_source: TaskSource,
|
||||
context: Trusted<GlobalScope>,
|
||||
}
|
||||
|
@ -389,7 +389,6 @@ struct BroadcastListener {
|
|||
/// A wrapper between timer events coming in over IPC, and the event-loop.
|
||||
#[derive(Clone)]
|
||||
pub(crate) struct TimerListener {
|
||||
canceller: TaskCanceller,
|
||||
task_source: TaskSource,
|
||||
context: Trusted<GlobalScope>,
|
||||
}
|
||||
|
@ -403,7 +402,6 @@ struct FileListener {
|
|||
/// - Some(Empty) => None
|
||||
state: Option<FileListenerState>,
|
||||
task_source: TaskSource,
|
||||
task_canceller: TaskCanceller,
|
||||
}
|
||||
|
||||
enum FileListenerTarget {
|
||||
|
@ -516,15 +514,14 @@ impl BroadcastListener {
|
|||
// This however seems to be hard to avoid in the light of the IPC.
|
||||
// One can imagine queueing tasks directly,
|
||||
// for channels that would be in the same script-thread.
|
||||
let _ = self.task_source.queue_with_canceller(
|
||||
task!(broadcast_message_event: move || {
|
||||
let _ = self
|
||||
.task_source
|
||||
.queue(task!(broadcast_message_event: move || {
|
||||
let global = context.root();
|
||||
// Step 10 of https://html.spec.whatwg.org/multipage/#dom-broadcastchannel-postmessage,
|
||||
// For each BroadcastChannel object destination in destinations, queue a task.
|
||||
global.broadcast_message_event(event, None);
|
||||
}),
|
||||
&self.canceller,
|
||||
);
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -535,7 +532,7 @@ impl TimerListener {
|
|||
let context = self.context.clone();
|
||||
// Step 18, queue a task,
|
||||
// https://html.spec.whatwg.org/multipage/#timer-initialisation-steps
|
||||
let _ = self.task_source.queue_with_canceller(
|
||||
let _ = self.task_source.queue(
|
||||
task!(timer_event: move || {
|
||||
let global = context.root();
|
||||
let TimerEvent(source, id) = event;
|
||||
|
@ -550,8 +547,7 @@ impl TimerListener {
|
|||
};
|
||||
// Step 7, substeps run in a task.
|
||||
global.fire_timer(id, CanGc::note());
|
||||
}),
|
||||
&self.canceller,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -568,7 +564,7 @@ impl MessageListener {
|
|||
match msg {
|
||||
MessagePortMsg::CompleteTransfer(ports) => {
|
||||
let context = self.context.clone();
|
||||
let _ = self.task_source.queue_with_canceller(
|
||||
let _ = self.task_source.queue(
|
||||
task!(process_complete_transfer: move || {
|
||||
let global = context.root();
|
||||
|
||||
|
@ -598,39 +594,31 @@ impl MessageListener {
|
|||
let _ = global.script_to_constellation_chan().send(
|
||||
ScriptMsg::MessagePortTransferResult(Some(router_id), succeeded, failed),
|
||||
);
|
||||
}),
|
||||
&self.canceller,
|
||||
})
|
||||
);
|
||||
},
|
||||
MessagePortMsg::CompletePendingTransfer(port_id, buffer) => {
|
||||
let context = self.context.clone();
|
||||
let _ = self.task_source.queue_with_canceller(
|
||||
task!(complete_pending: move || {
|
||||
let global = context.root();
|
||||
global.complete_port_transfer(port_id, buffer);
|
||||
}),
|
||||
&self.canceller,
|
||||
);
|
||||
let _ = self.task_source.queue(task!(complete_pending: move || {
|
||||
let global = context.root();
|
||||
global.complete_port_transfer(port_id, buffer);
|
||||
}));
|
||||
},
|
||||
MessagePortMsg::NewTask(port_id, task) => {
|
||||
let context = self.context.clone();
|
||||
let _ = self.task_source.queue_with_canceller(
|
||||
task!(process_new_task: move || {
|
||||
let global = context.root();
|
||||
global.route_task_to_port(port_id, task, CanGc::note());
|
||||
}),
|
||||
&self.canceller,
|
||||
);
|
||||
let _ = self.task_source.queue(task!(process_new_task: move || {
|
||||
let global = context.root();
|
||||
global.route_task_to_port(port_id, task, CanGc::note());
|
||||
}));
|
||||
},
|
||||
MessagePortMsg::RemoveMessagePort(port_id) => {
|
||||
let context = self.context.clone();
|
||||
let _ = self.task_source.queue_with_canceller(
|
||||
task!(process_remove_message_port: move || {
|
||||
let _ = self
|
||||
.task_source
|
||||
.queue(task!(process_remove_message_port: move || {
|
||||
let global = context.root();
|
||||
global.note_entangled_port_removed(&port_id);
|
||||
}),
|
||||
&self.canceller,
|
||||
);
|
||||
}));
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -665,10 +653,8 @@ impl FileListener {
|
|||
let stream = trusted.root();
|
||||
stream_handle_incoming(&stream, Ok(blob_buf.bytes));
|
||||
});
|
||||
let _ = self.task_source.queue(task);
|
||||
|
||||
let _ = self
|
||||
.task_source
|
||||
.queue_with_canceller(task, &self.task_canceller);
|
||||
Vec::with_capacity(0)
|
||||
} else {
|
||||
blob_buf.bytes
|
||||
|
@ -690,9 +676,7 @@ impl FileListener {
|
|||
stream_handle_incoming(&stream, Ok(bytes_in));
|
||||
});
|
||||
|
||||
let _ = self
|
||||
.task_source
|
||||
.queue_with_canceller(task, &self.task_canceller);
|
||||
let _ = self.task_source.queue(task);
|
||||
} else {
|
||||
bytes.append(&mut bytes_in);
|
||||
};
|
||||
|
@ -712,9 +696,7 @@ impl FileListener {
|
|||
callback(promise, Ok(bytes));
|
||||
});
|
||||
|
||||
let _ = self
|
||||
.task_source
|
||||
.queue_with_canceller(task, &self.task_canceller);
|
||||
let _ = self.task_source.queue(task);
|
||||
},
|
||||
FileListenerTarget::Stream(trusted_stream) => {
|
||||
let trusted = trusted_stream.clone();
|
||||
|
@ -724,9 +706,7 @@ impl FileListener {
|
|||
stream_handle_eof(&stream);
|
||||
});
|
||||
|
||||
let _ = self
|
||||
.task_source
|
||||
.queue_with_canceller(task, &self.task_canceller);
|
||||
let _ = self.task_source.queue(task);
|
||||
},
|
||||
},
|
||||
_ => {
|
||||
|
@ -740,23 +720,17 @@ impl FileListener {
|
|||
|
||||
match target {
|
||||
FileListenerTarget::Promise(trusted_promise, callback) => {
|
||||
let _ = self.task_source.queue_with_canceller(
|
||||
task!(reject_promise: move || {
|
||||
let promise = trusted_promise.root();
|
||||
let _ac = enter_realm(&*promise.global());
|
||||
callback(promise, error);
|
||||
}),
|
||||
&self.task_canceller,
|
||||
);
|
||||
let _ = self.task_source.queue(task!(reject_promise: move || {
|
||||
let promise = trusted_promise.root();
|
||||
let _ac = enter_realm(&*promise.global());
|
||||
callback(promise, error);
|
||||
}));
|
||||
},
|
||||
FileListenerTarget::Stream(trusted_stream) => {
|
||||
let _ = self.task_source.queue_with_canceller(
|
||||
task!(error_stream: move || {
|
||||
let stream = trusted_stream.root();
|
||||
stream_handle_incoming(&stream, error);
|
||||
}),
|
||||
&self.task_canceller,
|
||||
);
|
||||
let _ = self.task_source.queue(task!(error_stream: move || {
|
||||
let stream = trusted_stream.root();
|
||||
stream_handle_incoming(&stream, error);
|
||||
}));
|
||||
},
|
||||
}
|
||||
},
|
||||
|
@ -785,6 +759,7 @@ impl GlobalScope {
|
|||
unminify_js: bool,
|
||||
) -> Self {
|
||||
Self {
|
||||
task_manager: Default::default(),
|
||||
message_port_state: DomRefCell::new(MessagePortState::UnManaged),
|
||||
broadcast_channel_state: DomRefCell::new(BroadcastChannelState::UnManaged),
|
||||
blob_state: DomRefCell::new(BlobState::UnManaged),
|
||||
|
@ -851,16 +826,11 @@ impl GlobalScope {
|
|||
|
||||
fn timers(&self) -> &OneshotTimers {
|
||||
self.timers.get_or_init(|| {
|
||||
let (task_source, canceller) = (
|
||||
self.task_manager().timer_task_source(),
|
||||
self.task_canceller(TaskSourceName::Timer),
|
||||
);
|
||||
OneshotTimers::new(
|
||||
self,
|
||||
TimerListener {
|
||||
context: Trusted::new(self),
|
||||
task_source,
|
||||
canceller,
|
||||
task_source: self.task_manager().timer_task_source(),
|
||||
},
|
||||
)
|
||||
})
|
||||
|
@ -1099,7 +1069,6 @@ impl GlobalScope {
|
|||
let target_global = this.root();
|
||||
target_global.route_task_to_port(port_id, task, CanGc::note());
|
||||
}),
|
||||
self,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1148,15 +1117,15 @@ impl GlobalScope {
|
|||
if let Some(entangled_id) = entangled_port {
|
||||
// Step 7
|
||||
let this = Trusted::new(self);
|
||||
let _ = self.task_manager().port_message_queue().queue(
|
||||
task!(post_message: move || {
|
||||
let global = this.root();
|
||||
// Note: we do this in a task, as this will ensure the global and constellation
|
||||
// are aware of any transfer that might still take place in the current task.
|
||||
global.route_task_to_port(entangled_id, task, CanGc::note());
|
||||
}),
|
||||
self,
|
||||
);
|
||||
let _ =
|
||||
self.task_manager()
|
||||
.port_message_queue()
|
||||
.queue(task!(post_message: move || {
|
||||
let global = this.root();
|
||||
// Note: we do this in a task, as this will ensure the global and constellation
|
||||
// are aware of any transfer that might still take place in the current task.
|
||||
global.route_task_to_port(entangled_id, task, CanGc::note());
|
||||
}));
|
||||
}
|
||||
} else {
|
||||
warn!("post_messageport_msg called on a global not managing any ports.");
|
||||
|
@ -1273,8 +1242,7 @@ impl GlobalScope {
|
|||
// Step 10.3, fire an event named messageerror at destination.
|
||||
MessageEvent::dispatch_error(destination.upcast(), &global, CanGc::note());
|
||||
}
|
||||
}),
|
||||
self,
|
||||
})
|
||||
);
|
||||
});
|
||||
}
|
||||
|
@ -1438,13 +1406,8 @@ impl GlobalScope {
|
|||
let (broadcast_control_sender, broadcast_control_receiver) =
|
||||
ipc::channel().expect("ipc channel failure");
|
||||
let context = Trusted::new(self);
|
||||
let (task_source, canceller) = (
|
||||
self.task_manager().dom_manipulation_task_source(),
|
||||
self.task_canceller(TaskSourceName::DOMManipulation),
|
||||
);
|
||||
let listener = BroadcastListener {
|
||||
canceller,
|
||||
task_source,
|
||||
task_source: self.task_manager().dom_manipulation_task_source(),
|
||||
context,
|
||||
};
|
||||
ROUTER.add_typed_route(
|
||||
|
@ -1491,13 +1454,8 @@ impl GlobalScope {
|
|||
let (port_control_sender, port_control_receiver) =
|
||||
ipc::channel().expect("ipc channel failure");
|
||||
let context = Trusted::new(self);
|
||||
let (task_source, canceller) = (
|
||||
self.task_manager().port_message_queue(),
|
||||
self.task_canceller(TaskSourceName::PortMessage),
|
||||
);
|
||||
let listener = MessageListener {
|
||||
canceller,
|
||||
task_source,
|
||||
task_source: self.task_manager().port_message_queue(),
|
||||
context,
|
||||
};
|
||||
ROUTER.add_typed_route(
|
||||
|
@ -1540,7 +1498,6 @@ impl GlobalScope {
|
|||
let target_global = this.root();
|
||||
target_global.maybe_add_pending_ports();
|
||||
}),
|
||||
self,
|
||||
);
|
||||
} else {
|
||||
// If this is a newly-created port, let the constellation immediately know.
|
||||
|
@ -2017,15 +1974,11 @@ impl GlobalScope {
|
|||
let recv = self.send_msg(file_id);
|
||||
|
||||
let trusted_stream = Trusted::new(&*stream.clone());
|
||||
let task_canceller = self.task_canceller(TaskSourceName::FileReading);
|
||||
let task_source = self.task_manager().file_reading_task_source();
|
||||
|
||||
let mut file_listener = FileListener {
|
||||
state: Some(FileListenerState::Empty(FileListenerTarget::Stream(
|
||||
trusted_stream,
|
||||
))),
|
||||
task_source,
|
||||
task_canceller,
|
||||
task_source: self.task_manager().file_reading_task_source(),
|
||||
};
|
||||
|
||||
ROUTER.add_typed_route(
|
||||
|
@ -2042,16 +1995,12 @@ impl GlobalScope {
|
|||
let recv = self.send_msg(id);
|
||||
|
||||
let trusted_promise = TrustedPromise::new(promise);
|
||||
let task_canceller = self.task_canceller(TaskSourceName::FileReading);
|
||||
let task_source = self.task_manager().file_reading_task_source();
|
||||
|
||||
let mut file_listener = FileListener {
|
||||
state: Some(FileListenerState::Empty(FileListenerTarget::Promise(
|
||||
trusted_promise,
|
||||
callback,
|
||||
))),
|
||||
task_source,
|
||||
task_canceller,
|
||||
task_source: self.task_manager().file_reading_task_source(),
|
||||
};
|
||||
|
||||
ROUTER.add_typed_route(
|
||||
|
@ -2574,28 +2523,36 @@ impl GlobalScope {
|
|||
self.resource_threads().sender()
|
||||
}
|
||||
|
||||
/// `ScriptChan` to send messages to the event loop of this global scope.
|
||||
pub fn script_chan(&self) -> Box<dyn ScriptChan + Send> {
|
||||
/// A sender to the event loop of this global scope. This either sends to the Worker event loop
|
||||
/// or the ScriptThread event loop in the case of a `Window`. This can be `None` for dedicated
|
||||
/// workers that are not currently handling a message.
|
||||
pub(crate) fn event_loop_sender(&self) -> Option<Box<dyn ScriptChan + Send>> {
|
||||
if let Some(window) = self.downcast::<Window>() {
|
||||
return Box::new(
|
||||
MainThreadScriptChan(window.main_thread_script_chan().clone()).clone(),
|
||||
Some(window.event_loop_sender())
|
||||
} else if let Some(dedicated) = self.downcast::<DedicatedWorkerGlobalScope>() {
|
||||
dedicated.event_loop_sender()
|
||||
} else if let Some(service_worker) = self.downcast::<ServiceWorkerGlobalScope>() {
|
||||
Some(service_worker.event_loop_sender())
|
||||
} else {
|
||||
unreachable!(
|
||||
"Tried to access event loop sender for incompatible \
|
||||
GlobalScope (PaintWorklet or DissimilarOriginWindow)"
|
||||
);
|
||||
}
|
||||
if let Some(worker) = self.downcast::<WorkerGlobalScope>() {
|
||||
return worker.script_chan();
|
||||
}
|
||||
unreachable!();
|
||||
}
|
||||
|
||||
/// The [`TaskManager`] used to schedule tasks for this [`GlobalScope`].
|
||||
pub fn task_manager(&self) -> &TaskManager {
|
||||
if let Some(window) = self.downcast::<Window>() {
|
||||
return window.task_manager();
|
||||
}
|
||||
if let Some(worker) = self.downcast::<WorkerGlobalScope>() {
|
||||
return worker.task_manager();
|
||||
}
|
||||
unreachable!();
|
||||
/// A reference to the [`TaskManager`] used to schedule tasks for this [`GlobalScope`].
|
||||
pub(crate) fn task_manager(&self) -> &TaskManager {
|
||||
let shared_canceller = self
|
||||
.downcast::<WorkerGlobalScope>()
|
||||
.map(WorkerGlobalScope::shared_task_canceller);
|
||||
self.task_manager.get_or_init(|| {
|
||||
TaskManager::new(
|
||||
self.event_loop_sender(),
|
||||
self.pipeline_id(),
|
||||
shared_canceller,
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
/// Evaluate JS code on this global scope.
|
||||
|
@ -2777,7 +2734,7 @@ impl GlobalScope {
|
|||
);
|
||||
self.task_manager()
|
||||
.dom_manipulation_task_source()
|
||||
.queue(task, self)
|
||||
.queue(task)
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
@ -2894,21 +2851,6 @@ impl GlobalScope {
|
|||
true
|
||||
}
|
||||
|
||||
/// 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, name: TaskSourceName) -> TaskCanceller {
|
||||
if let Some(window) = self.downcast::<Window>() {
|
||||
return window.task_manager().task_canceller(name);
|
||||
}
|
||||
if let Some(worker) = self.downcast::<WorkerGlobalScope>() {
|
||||
// Note: the "name" is not passed to the worker,
|
||||
// because 'closing' it only requires one task canceller for all task sources.
|
||||
// https://html.spec.whatwg.org/multipage/#dom-workerglobalscope-closing
|
||||
return worker.task_canceller();
|
||||
}
|
||||
unreachable!();
|
||||
}
|
||||
|
||||
/// Perform a microtask checkpoint.
|
||||
pub fn perform_a_microtask_checkpoint(&self, can_gc: CanGc) {
|
||||
// Only perform the checkpoint if we're not shutting down.
|
||||
|
@ -3163,29 +3105,26 @@ impl GlobalScope {
|
|||
let this = Trusted::new(self);
|
||||
self.task_manager()
|
||||
.gamepad_task_source()
|
||||
.queue_with_canceller(
|
||||
task!(gamepad_connected: move || {
|
||||
let global = this.root();
|
||||
.queue(task!(gamepad_connected: move || {
|
||||
let global = this.root();
|
||||
|
||||
if let Some(window) = global.downcast::<Window>() {
|
||||
let navigator = window.Navigator();
|
||||
let selected_index = navigator.select_gamepad_index();
|
||||
let gamepad = Gamepad::new(
|
||||
&global,
|
||||
selected_index,
|
||||
name,
|
||||
"standard".into(),
|
||||
axis_bounds,
|
||||
button_bounds,
|
||||
supported_haptic_effects,
|
||||
false,
|
||||
CanGc::note(),
|
||||
);
|
||||
navigator.set_gamepad(selected_index as usize, &gamepad, CanGc::note());
|
||||
}
|
||||
}),
|
||||
&self.task_canceller(TaskSourceName::Gamepad),
|
||||
)
|
||||
if let Some(window) = global.downcast::<Window>() {
|
||||
let navigator = window.Navigator();
|
||||
let selected_index = navigator.select_gamepad_index();
|
||||
let gamepad = Gamepad::new(
|
||||
&global,
|
||||
selected_index,
|
||||
name,
|
||||
"standard".into(),
|
||||
axis_bounds,
|
||||
button_bounds,
|
||||
supported_haptic_effects,
|
||||
false,
|
||||
CanGc::note(),
|
||||
);
|
||||
navigator.set_gamepad(selected_index as usize, &gamepad, CanGc::note());
|
||||
}
|
||||
}))
|
||||
.expect("Failed to queue gamepad connected task.");
|
||||
}
|
||||
|
||||
|
@ -3194,21 +3133,18 @@ impl GlobalScope {
|
|||
let this = Trusted::new(self);
|
||||
self.task_manager()
|
||||
.gamepad_task_source()
|
||||
.queue_with_canceller(
|
||||
task!(gamepad_disconnected: move || {
|
||||
let global = this.root();
|
||||
if let Some(window) = global.downcast::<Window>() {
|
||||
let navigator = window.Navigator();
|
||||
if let Some(gamepad) = navigator.get_gamepad(index) {
|
||||
if window.Document().is_fully_active() {
|
||||
gamepad.update_connected(false, gamepad.exposed(), CanGc::note());
|
||||
navigator.remove_gamepad(index);
|
||||
}
|
||||
.queue(task!(gamepad_disconnected: move || {
|
||||
let global = this.root();
|
||||
if let Some(window) = global.downcast::<Window>() {
|
||||
let navigator = window.Navigator();
|
||||
if let Some(gamepad) = navigator.get_gamepad(index) {
|
||||
if window.Document().is_fully_active() {
|
||||
gamepad.update_connected(false, gamepad.exposed(), CanGc::note());
|
||||
navigator.remove_gamepad(index);
|
||||
}
|
||||
}
|
||||
}),
|
||||
&self.task_canceller(TaskSourceName::Gamepad),
|
||||
)
|
||||
}
|
||||
}))
|
||||
.expect("Failed to queue gamepad disconnected task.");
|
||||
}
|
||||
|
||||
|
@ -3217,9 +3153,7 @@ impl GlobalScope {
|
|||
let this = Trusted::new(self);
|
||||
|
||||
// <https://w3c.github.io/gamepad/#dfn-update-gamepad-state>
|
||||
self.task_manager()
|
||||
.gamepad_task_source()
|
||||
.queue_with_canceller(
|
||||
self.task_manager().gamepad_task_source().queue(
|
||||
task!(update_gamepad_state: move || {
|
||||
let global = this.root();
|
||||
if let Some(window) = global.downcast::<Window>() {
|
||||
|
@ -3245,13 +3179,11 @@ impl GlobalScope {
|
|||
gamepad.update_timestamp(*current_time);
|
||||
let new_gamepad = Trusted::new(&**gamepad);
|
||||
if window.Document().is_fully_active() {
|
||||
window.task_manager().gamepad_task_source().queue_with_canceller(
|
||||
global.task_manager().gamepad_task_source().queue(
|
||||
task!(update_gamepad_connect: move || {
|
||||
let gamepad = new_gamepad.root();
|
||||
gamepad.notify_event(GamepadEventType::Connected, CanGc::note());
|
||||
}),
|
||||
&window.upcast::<GlobalScope>()
|
||||
.task_canceller(TaskSourceName::Gamepad),
|
||||
})
|
||||
)
|
||||
.expect("Failed to queue update gamepad connect task.");
|
||||
}
|
||||
|
@ -3259,8 +3191,7 @@ impl GlobalScope {
|
|||
}
|
||||
}
|
||||
}
|
||||
}),
|
||||
&self.task_canceller(TaskSourceName::Gamepad),
|
||||
})
|
||||
)
|
||||
.expect("Failed to queue update gamepad state task.");
|
||||
}
|
||||
|
@ -3333,11 +3264,9 @@ impl GlobalScope {
|
|||
task_source: TaskSource,
|
||||
cancellation_sender: Option<ipc::IpcReceiver<()>>,
|
||||
) {
|
||||
let canceller = Some(self.task_canceller(TaskSourceName::Networking));
|
||||
let network_listener = NetworkListener {
|
||||
context,
|
||||
task_source,
|
||||
canceller,
|
||||
};
|
||||
self.fetch_with_network_listener(request_builder, network_listener, cancellation_sender);
|
||||
}
|
||||
|
|
|
@ -92,7 +92,6 @@ impl VirtualMethods for HTMLDetailsElement {
|
|||
this.upcast::<EventTarget>().fire_event(atom!("toggle"), CanGc::note());
|
||||
}
|
||||
}),
|
||||
window.upcast(),
|
||||
);
|
||||
self.upcast::<Node>().dirty(NodeDamage::OtherNodeDamage)
|
||||
}
|
||||
|
|
|
@ -122,6 +122,6 @@ impl HTMLDialogElementMethods<crate::DomTypeHolder> for HTMLDialogElement {
|
|||
// Step 5
|
||||
win.task_manager()
|
||||
.dom_manipulation_task_source()
|
||||
.queue_simple_event(target, atom!("close"), &win);
|
||||
.queue_simple_event(target, atom!("close"));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1039,7 +1039,7 @@ impl HTMLFormElement {
|
|||
target
|
||||
.task_manager()
|
||||
.dom_manipulation_task_source()
|
||||
.queue(task, target.upcast())
|
||||
.queue(task)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
|
|
|
@ -892,24 +892,21 @@ impl HTMLImageElement {
|
|||
self.abort_request(State::Broken, ImageRequestPhase::Pending, can_gc);
|
||||
// Step 9.
|
||||
// FIXME(nox): Why are errors silenced here?
|
||||
let _ = task_source.queue(
|
||||
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;
|
||||
}
|
||||
let elem = this.upcast::<Element>();
|
||||
let src_present = elem.has_attribute(&local_name!("src"));
|
||||
let _ = task_source.queue(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;
|
||||
}
|
||||
let elem = this.upcast::<Element>();
|
||||
let src_present = elem.has_attribute(&local_name!("src"));
|
||||
|
||||
if src_present || Self::uses_srcset_or_picture(elem) {
|
||||
this.upcast::<EventTarget>().fire_event(atom!("error"), CanGc::note());
|
||||
}
|
||||
}),
|
||||
window.upcast(),
|
||||
);
|
||||
if src_present || Self::uses_srcset_or_picture(elem) {
|
||||
this.upcast::<EventTarget>().fire_event(atom!("error"), CanGc::note());
|
||||
}
|
||||
}));
|
||||
return;
|
||||
},
|
||||
};
|
||||
|
@ -928,19 +925,16 @@ impl HTMLImageElement {
|
|||
// Step 12.1-12.5.
|
||||
let src = src.0;
|
||||
// FIXME(nox): Why are errors silenced here?
|
||||
let _ = task_source.queue(
|
||||
task!(image_selected_source_error: move || {
|
||||
let this = this.root();
|
||||
{
|
||||
let mut current_request =
|
||||
this.current_request.borrow_mut();
|
||||
current_request.source_url = Some(USVString(src))
|
||||
}
|
||||
this.upcast::<EventTarget>().fire_event(atom!("error"), CanGc::note());
|
||||
let _ = task_source.queue(task!(image_selected_source_error: move || {
|
||||
let this = this.root();
|
||||
{
|
||||
let mut current_request =
|
||||
this.current_request.borrow_mut();
|
||||
current_request.source_url = Some(USVString(src))
|
||||
}
|
||||
this.upcast::<EventTarget>().fire_event(atom!("error"), CanGc::note());
|
||||
|
||||
}),
|
||||
window.upcast(),
|
||||
);
|
||||
}));
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -1021,6 +1015,7 @@ impl HTMLImageElement {
|
|||
current_request.current_pixel_density = pixel_density;
|
||||
let this = Trusted::new(self);
|
||||
let src = src.0;
|
||||
|
||||
let _ = window.task_manager().dom_manipulation_task_source().queue(
|
||||
task!(image_load_event: move || {
|
||||
let this = this.root();
|
||||
|
@ -1033,7 +1028,6 @@ impl HTMLImageElement {
|
|||
// TODO: restart animation, if set.
|
||||
this.upcast::<EventTarget>().fire_event(atom!("load"), CanGc::note());
|
||||
}),
|
||||
window.upcast(),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
@ -1069,11 +1063,7 @@ impl HTMLImageElement {
|
|||
) -> IpcSender<PendingImageResponse> {
|
||||
let trusted_node = Trusted::new(elem);
|
||||
let (responder_sender, responder_receiver) = ipc::channel().unwrap();
|
||||
|
||||
let window = elem.owner_window();
|
||||
let (task_source, canceller) = window
|
||||
.task_manager()
|
||||
.networking_task_source_with_canceller();
|
||||
let task_source = elem.owner_window().task_manager().networking_task_source();
|
||||
let generation = elem.generation.get();
|
||||
|
||||
ROUTER.add_typed_route(
|
||||
|
@ -1085,7 +1075,7 @@ impl HTMLImageElement {
|
|||
let element = trusted_node.clone();
|
||||
let image: PendingImageResponse = message.unwrap();
|
||||
let selected_source_clone = selected_source.clone();
|
||||
let _ = task_source.queue_with_canceller(
|
||||
let _ = task_source.queue(
|
||||
task!(process_image_response_for_environment_change: move || {
|
||||
let element = element.root();
|
||||
// Ignore any image response for a previous request that has been discarded.
|
||||
|
@ -1094,8 +1084,7 @@ impl HTMLImageElement {
|
|||
USVString::from(selected_source_clone), generation,
|
||||
selected_pixel_density, CanGc::note());
|
||||
}
|
||||
}),
|
||||
&canceller,
|
||||
})
|
||||
);
|
||||
}),
|
||||
);
|
||||
|
@ -1283,8 +1272,7 @@ impl HTMLImageElement {
|
|||
|
||||
// Step 15.7
|
||||
this.upcast::<EventTarget>().fire_event(atom!("load"), CanGc::note());
|
||||
}),
|
||||
window.upcast(),
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -2576,8 +2576,7 @@ impl VirtualMethods for HTMLInputElement {
|
|||
self.input_type().is_textual_or_password()
|
||||
{
|
||||
if event.IsTrusted() {
|
||||
let window = self.owner_window();
|
||||
window
|
||||
self.owner_window()
|
||||
.task_manager()
|
||||
.user_interaction_task_source()
|
||||
.queue_event(
|
||||
|
@ -2585,7 +2584,6 @@ impl VirtualMethods for HTMLInputElement {
|
|||
atom!("input"),
|
||||
EventBubbles::Bubbles,
|
||||
EventCancelable::NotCancelable,
|
||||
&window,
|
||||
);
|
||||
}
|
||||
} else if (event.type_() == atom!("compositionstart") ||
|
||||
|
|
|
@ -523,11 +523,10 @@ impl HTMLMediaElement {
|
|||
fn time_marches_on(&self) {
|
||||
// Step 6.
|
||||
if Instant::now() > self.next_timeupdate_event.get() {
|
||||
let window = self.owner_window();
|
||||
window
|
||||
self.owner_window()
|
||||
.task_manager()
|
||||
.media_element_task_source()
|
||||
.queue_simple_event(self.upcast(), atom!("timeupdate"), &window);
|
||||
.queue_simple_event(self.upcast(), atom!("timeupdate"));
|
||||
self.next_timeupdate_event
|
||||
.set(Instant::now() + Duration::from_millis(350));
|
||||
}
|
||||
|
@ -547,11 +546,13 @@ impl HTMLMediaElement {
|
|||
self.take_pending_play_promises(Err(Error::Abort));
|
||||
|
||||
// Step 2.3.
|
||||
let window = self.owner_window();
|
||||
let this = Trusted::new(self);
|
||||
let generation_id = self.generation_id.get();
|
||||
let _ = window.task_manager().media_element_task_source().queue(
|
||||
task!(internal_pause_steps: move || {
|
||||
let _ = self
|
||||
.owner_window()
|
||||
.task_manager()
|
||||
.media_element_task_source()
|
||||
.queue(task!(internal_pause_steps: move || {
|
||||
let this = this.root();
|
||||
if generation_id != this.generation_id.get() {
|
||||
return;
|
||||
|
@ -574,9 +575,7 @@ impl HTMLMediaElement {
|
|||
// Done after running this closure in
|
||||
// `fulfill_in_flight_play_promises`.
|
||||
});
|
||||
}),
|
||||
window.upcast(),
|
||||
);
|
||||
}));
|
||||
|
||||
// Step 2.4.
|
||||
// FIXME(nox): Set the official playback position to the current
|
||||
|
@ -594,12 +593,14 @@ impl HTMLMediaElement {
|
|||
self.take_pending_play_promises(Ok(()));
|
||||
|
||||
// Step 2.
|
||||
let window = self.owner_window();
|
||||
let this = Trusted::new(self);
|
||||
let generation_id = self.generation_id.get();
|
||||
// FIXME(nox): Why are errors silenced here?
|
||||
let _ = window.task_manager().media_element_task_source().queue(
|
||||
task!(notify_about_playing: move || {
|
||||
let _ = self
|
||||
.owner_window()
|
||||
.task_manager()
|
||||
.media_element_task_source()
|
||||
.queue(task!(notify_about_playing: move || {
|
||||
let this = this.root();
|
||||
if generation_id != this.generation_id.get() {
|
||||
return;
|
||||
|
@ -615,9 +616,7 @@ impl HTMLMediaElement {
|
|||
// `fulfill_in_flight_play_promises`.
|
||||
});
|
||||
|
||||
}),
|
||||
window.upcast(),
|
||||
);
|
||||
}));
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#ready-states
|
||||
|
@ -633,13 +632,15 @@ impl HTMLMediaElement {
|
|||
return;
|
||||
}
|
||||
|
||||
let window = self.owner_window();
|
||||
let task_source = window.task_manager().media_element_task_source();
|
||||
let task_source = self
|
||||
.owner_window()
|
||||
.task_manager()
|
||||
.media_element_task_source();
|
||||
|
||||
// Step 1.
|
||||
match (old_ready_state, ready_state) {
|
||||
(ReadyState::HaveNothing, ReadyState::HaveMetadata) => {
|
||||
task_source.queue_simple_event(self.upcast(), atom!("loadedmetadata"), &window);
|
||||
task_source.queue_simple_event(self.upcast(), atom!("loadedmetadata"));
|
||||
// No other steps are applicable in this case.
|
||||
return;
|
||||
},
|
||||
|
@ -648,14 +649,11 @@ impl HTMLMediaElement {
|
|||
self.fired_loadeddata_event.set(true);
|
||||
let this = Trusted::new(self);
|
||||
// FIXME(nox): Why are errors silenced here?
|
||||
let _ = task_source.queue(
|
||||
task!(media_reached_current_data: move || {
|
||||
let this = this.root();
|
||||
this.upcast::<EventTarget>().fire_event(atom!("loadeddata"), CanGc::note());
|
||||
this.delay_load_event(false, CanGc::note());
|
||||
}),
|
||||
window.upcast(),
|
||||
);
|
||||
let _ = task_source.queue(task!(media_reached_current_data: move || {
|
||||
let this = this.root();
|
||||
this.upcast::<EventTarget>().fire_event(atom!("loadeddata"), CanGc::note());
|
||||
this.delay_load_event(false, CanGc::note());
|
||||
}));
|
||||
}
|
||||
|
||||
// Steps for the transition from HaveMetadata to HaveCurrentData
|
||||
|
@ -676,7 +674,7 @@ impl HTMLMediaElement {
|
|||
if old_ready_state <= ReadyState::HaveCurrentData &&
|
||||
ready_state >= ReadyState::HaveFutureData
|
||||
{
|
||||
task_source.queue_simple_event(self.upcast(), atom!("canplay"), &window);
|
||||
task_source.queue_simple_event(self.upcast(), atom!("canplay"));
|
||||
|
||||
if !self.Paused() {
|
||||
self.notify_about_playing();
|
||||
|
@ -697,7 +695,7 @@ impl HTMLMediaElement {
|
|||
self.time_marches_on();
|
||||
}
|
||||
// Step 3
|
||||
task_source.queue_simple_event(self.upcast(), atom!("play"), &window);
|
||||
task_source.queue_simple_event(self.upcast(), atom!("play"));
|
||||
// Step 4
|
||||
self.notify_about_playing();
|
||||
// Step 5
|
||||
|
@ -706,7 +704,7 @@ impl HTMLMediaElement {
|
|||
|
||||
// FIXME(nox): According to the spec, this should come *before* the
|
||||
// "play" event.
|
||||
task_source.queue_simple_event(self.upcast(), atom!("canplaythrough"), &window);
|
||||
task_source.queue_simple_event(self.upcast(), atom!("canplaythrough"));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -787,11 +785,10 @@ impl HTMLMediaElement {
|
|||
self.network_state.set(NetworkState::Loading);
|
||||
|
||||
// Step 8.
|
||||
let window = self.owner_window();
|
||||
window
|
||||
self.owner_window()
|
||||
.task_manager()
|
||||
.media_element_task_source()
|
||||
.queue_simple_event(self.upcast(), atom!("loadstart"), &window);
|
||||
.queue_simple_event(self.upcast(), atom!("loadstart"));
|
||||
|
||||
// Step 9.
|
||||
match mode {
|
||||
|
@ -941,19 +938,16 @@ impl HTMLMediaElement {
|
|||
window
|
||||
.task_manager()
|
||||
.media_element_task_source()
|
||||
.queue_simple_event(self.upcast(), atom!("suspend"), &window);
|
||||
.queue_simple_event(self.upcast(), atom!("suspend"));
|
||||
|
||||
// Step 4.remote.1.3.
|
||||
let this = Trusted::new(self);
|
||||
window
|
||||
.task_manager()
|
||||
.media_element_task_source()
|
||||
.queue(
|
||||
task!(set_media_delay_load_event_flag_to_false: move || {
|
||||
this.root().delay_load_event(false, CanGc::note());
|
||||
}),
|
||||
window.upcast(),
|
||||
)
|
||||
.queue(task!(set_media_delay_load_event_flag_to_false: move || {
|
||||
this.root().delay_load_event(false, CanGc::note());
|
||||
}))
|
||||
.unwrap();
|
||||
|
||||
// Steps 4.remote.1.4.
|
||||
|
@ -1007,13 +1001,15 @@ impl HTMLMediaElement {
|
|||
///
|
||||
/// [steps]: https://html.spec.whatwg.org/multipage/#dedicated-media-source-failure-steps
|
||||
fn queue_dedicated_media_source_failure_steps(&self) {
|
||||
let window = self.owner_window();
|
||||
let this = Trusted::new(self);
|
||||
let generation_id = self.generation_id.get();
|
||||
self.take_pending_play_promises(Err(Error::NotSupported));
|
||||
// FIXME(nox): Why are errors silenced here?
|
||||
let _ = window.task_manager().media_element_task_source().queue(
|
||||
task!(dedicated_media_source_failure_steps: move || {
|
||||
let _ = self
|
||||
.owner_window()
|
||||
.task_manager()
|
||||
.media_element_task_source()
|
||||
.queue(task!(dedicated_media_source_failure_steps: move || {
|
||||
let this = this.root();
|
||||
if generation_id != this.generation_id.get() {
|
||||
return;
|
||||
|
@ -1052,15 +1048,14 @@ impl HTMLMediaElement {
|
|||
|
||||
// Step 7.
|
||||
this.delay_load_event(false, CanGc::note());
|
||||
}),
|
||||
window.upcast(),
|
||||
);
|
||||
}));
|
||||
}
|
||||
|
||||
fn queue_ratechange_event(&self) {
|
||||
let window = self.owner_window();
|
||||
let task_source = window.task_manager().media_element_task_source();
|
||||
task_source.queue_simple_event(self.upcast(), atom!("ratechange"), &window);
|
||||
self.owner_window()
|
||||
.task_manager()
|
||||
.media_element_task_source()
|
||||
.queue_simple_event(self.upcast(), atom!("ratechange"));
|
||||
}
|
||||
|
||||
fn in_error_state(&self) -> bool {
|
||||
|
@ -1110,19 +1105,21 @@ impl HTMLMediaElement {
|
|||
self.fulfill_in_flight_play_promises(|| ());
|
||||
}
|
||||
|
||||
let window = self.owner_window();
|
||||
let task_source = window.task_manager().media_element_task_source();
|
||||
let task_source = self
|
||||
.owner_window()
|
||||
.task_manager()
|
||||
.media_element_task_source();
|
||||
|
||||
// Step 5.
|
||||
let network_state = self.network_state.get();
|
||||
if network_state == NetworkState::Loading || network_state == NetworkState::Idle {
|
||||
task_source.queue_simple_event(self.upcast(), atom!("abort"), &window);
|
||||
task_source.queue_simple_event(self.upcast(), atom!("abort"));
|
||||
}
|
||||
|
||||
// Step 6.
|
||||
if network_state != NetworkState::Empty {
|
||||
// Step 6.1.
|
||||
task_source.queue_simple_event(self.upcast(), atom!("emptied"), &window);
|
||||
task_source.queue_simple_event(self.upcast(), atom!("emptied"));
|
||||
|
||||
// Step 6.2.
|
||||
if let Some(ref mut current_fetch_context) = *self.current_fetch_context.borrow_mut() {
|
||||
|
@ -1160,7 +1157,7 @@ impl HTMLMediaElement {
|
|||
let queue_timeupdate_event = self.playback_position.get() != 0.;
|
||||
self.playback_position.set(0.);
|
||||
if queue_timeupdate_event {
|
||||
task_source.queue_simple_event(self.upcast(), atom!("timeupdate"), &window);
|
||||
task_source.queue_simple_event(self.upcast(), atom!("timeupdate"));
|
||||
}
|
||||
|
||||
// Step 6.9.
|
||||
|
@ -1291,9 +1288,10 @@ impl HTMLMediaElement {
|
|||
// servo-media with gstreamer does not support inaccurate seeking for now.
|
||||
|
||||
// Step 10.
|
||||
let window = self.owner_window();
|
||||
let task_source = window.task_manager().media_element_task_source();
|
||||
task_source.queue_simple_event(self.upcast(), atom!("seeking"), &window);
|
||||
self.owner_window()
|
||||
.task_manager()
|
||||
.media_element_task_source()
|
||||
.queue_simple_event(self.upcast(), atom!("seeking"));
|
||||
|
||||
// Step 11.
|
||||
if let Some(ref player) = *self.player.borrow() {
|
||||
|
@ -1316,12 +1314,14 @@ impl HTMLMediaElement {
|
|||
self.time_marches_on();
|
||||
|
||||
// Step 16.
|
||||
let window = self.owner_window();
|
||||
let task_source = window.task_manager().media_element_task_source();
|
||||
task_source.queue_simple_event(self.upcast(), atom!("timeupdate"), &window);
|
||||
let task_source = self
|
||||
.owner_window()
|
||||
.task_manager()
|
||||
.media_element_task_source();
|
||||
task_source.queue_simple_event(self.upcast(), atom!("timeupdate"));
|
||||
|
||||
// Step 17.
|
||||
task_source.queue_simple_event(self.upcast(), atom!("seeked"), &window);
|
||||
task_source.queue_simple_event(self.upcast(), atom!("seeked"));
|
||||
}
|
||||
|
||||
/// <https://html.spec.whatwg.org/multipage/#poster-frame>
|
||||
|
@ -1339,9 +1339,10 @@ impl HTMLMediaElement {
|
|||
self.upcast::<Node>().dirty(NodeDamage::OtherNodeDamage);
|
||||
|
||||
if pref!(media.testing.enabled) {
|
||||
let window = self.owner_window();
|
||||
let task_source = window.task_manager().media_element_task_source();
|
||||
task_source.queue_simple_event(self.upcast(), atom!("postershown"), &window);
|
||||
self.owner_window()
|
||||
.task_manager()
|
||||
.media_element_task_source()
|
||||
.queue_simple_event(self.upcast(), atom!("postershown"));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1385,21 +1386,16 @@ impl HTMLMediaElement {
|
|||
*self.player.borrow_mut() = Some(player);
|
||||
|
||||
let trusted_node = Trusted::new(self);
|
||||
let (task_source, canceller) = window
|
||||
.task_manager()
|
||||
.media_element_task_source_with_canceller();
|
||||
let task_source = window.task_manager().media_element_task_source();
|
||||
ROUTER.add_typed_route(
|
||||
action_receiver,
|
||||
Box::new(move |message| {
|
||||
let event = message.unwrap();
|
||||
trace!("Player event {:?}", event);
|
||||
let this = trusted_node.clone();
|
||||
if let Err(err) = task_source.queue_with_canceller(
|
||||
task!(handle_player_event: move || {
|
||||
this.root().handle_player_event(&event, CanGc::note());
|
||||
}),
|
||||
&canceller,
|
||||
) {
|
||||
if let Err(err) = task_source.queue(task!(handle_player_event: move || {
|
||||
this.root().handle_player_event(&event, CanGc::note());
|
||||
})) {
|
||||
warn!("Could not queue player event handler task {:?}", err);
|
||||
}
|
||||
}),
|
||||
|
@ -1428,42 +1424,37 @@ impl HTMLMediaElement {
|
|||
|
||||
if let Some(image_receiver) = image_receiver {
|
||||
let trusted_node = Trusted::new(self);
|
||||
let (task_source, canceller) = window
|
||||
.task_manager()
|
||||
.media_element_task_source_with_canceller();
|
||||
let task_source = window.task_manager().media_element_task_source();
|
||||
ROUTER.add_typed_route(
|
||||
image_receiver.to_ipc_receiver(),
|
||||
Box::new(move |message| {
|
||||
let msg = message.unwrap();
|
||||
let this = trusted_node.clone();
|
||||
if let Err(err) = task_source.queue_with_canceller(
|
||||
task!(handle_glplayer_message: move || {
|
||||
trace!("GLPlayer message {:?}", msg);
|
||||
let video_renderer = this.root().video_renderer.clone();
|
||||
if let Err(err) = task_source.queue(task!(handle_glplayer_message: move || {
|
||||
trace!("GLPlayer message {:?}", msg);
|
||||
let video_renderer = this.root().video_renderer.clone();
|
||||
|
||||
match msg {
|
||||
GLPlayerMsgForward::Lock(sender) => {
|
||||
if let Some(holder) = video_renderer
|
||||
.lock()
|
||||
.unwrap()
|
||||
.current_frame_holder
|
||||
.as_mut() {
|
||||
holder.lock();
|
||||
sender.send(holder.get()).unwrap();
|
||||
};
|
||||
},
|
||||
GLPlayerMsgForward::Unlock() => {
|
||||
if let Some(holder) = video_renderer
|
||||
.lock()
|
||||
.unwrap()
|
||||
.current_frame_holder
|
||||
.as_mut() { holder.unlock() }
|
||||
},
|
||||
_ => (),
|
||||
}
|
||||
}),
|
||||
&canceller,
|
||||
) {
|
||||
match msg {
|
||||
GLPlayerMsgForward::Lock(sender) => {
|
||||
if let Some(holder) = video_renderer
|
||||
.lock()
|
||||
.unwrap()
|
||||
.current_frame_holder
|
||||
.as_mut() {
|
||||
holder.lock();
|
||||
sender.send(holder.get()).unwrap();
|
||||
};
|
||||
},
|
||||
GLPlayerMsgForward::Unlock() => {
|
||||
if let Some(holder) = video_renderer
|
||||
.lock()
|
||||
.unwrap()
|
||||
.current_frame_holder
|
||||
.as_mut() { holder.unlock() }
|
||||
},
|
||||
_ => (),
|
||||
}
|
||||
})) {
|
||||
warn!("Could not queue GL player message handler task {:?}", err);
|
||||
}
|
||||
}),
|
||||
|
@ -1513,10 +1504,9 @@ impl HTMLMediaElement {
|
|||
// the HTMLMediaElementMethods::Ended method
|
||||
|
||||
// Step 3.
|
||||
let window = self.owner_window();
|
||||
let this = Trusted::new(self);
|
||||
|
||||
let _ = window.task_manager().media_element_task_source().queue(
|
||||
let _ = self.owner_window().task_manager().media_element_task_source().queue(
|
||||
task!(reaches_the_end_steps: move || {
|
||||
let this = this.root();
|
||||
// Step 3.1.
|
||||
|
@ -1537,8 +1527,7 @@ impl HTMLMediaElement {
|
|||
|
||||
// Step 3.3.
|
||||
this.upcast::<EventTarget>().fire_event(atom!("ended"), CanGc::note());
|
||||
}),
|
||||
window.upcast(),
|
||||
})
|
||||
);
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-media-have_current_data
|
||||
|
@ -1548,12 +1537,10 @@ impl HTMLMediaElement {
|
|||
|
||||
PlaybackDirection::Backwards => {
|
||||
if self.playback_position.get() <= self.earliest_possible_position() {
|
||||
let window = self.owner_window();
|
||||
|
||||
window
|
||||
self.owner_window()
|
||||
.task_manager()
|
||||
.media_element_task_source()
|
||||
.queue_simple_event(self.upcast(), atom!("ended"), &window);
|
||||
.queue_simple_event(self.upcast(), atom!("ended"));
|
||||
}
|
||||
},
|
||||
}
|
||||
|
@ -1737,9 +1724,10 @@ impl HTMLMediaElement {
|
|||
self.duration.set(f64::INFINITY);
|
||||
}
|
||||
if previous_duration != self.duration.get() {
|
||||
let window = self.owner_window();
|
||||
let task_source = window.task_manager().media_element_task_source();
|
||||
task_source.queue_simple_event(self.upcast(), atom!("durationchange"), &window);
|
||||
self.owner_window()
|
||||
.task_manager()
|
||||
.media_element_task_source()
|
||||
.queue_simple_event(self.upcast(), atom!("durationchange"));
|
||||
}
|
||||
|
||||
// Step 5.
|
||||
|
@ -2130,11 +2118,10 @@ impl HTMLMediaElementMethods<crate::DomTypeHolder> for HTMLMediaElement {
|
|||
}
|
||||
|
||||
self.muted.set(value);
|
||||
let window = self.owner_window();
|
||||
window
|
||||
self.owner_window()
|
||||
.task_manager()
|
||||
.media_element_task_source()
|
||||
.queue_simple_event(self.upcast(), atom!("volumechange"), &window);
|
||||
.queue_simple_event(self.upcast(), atom!("volumechange"));
|
||||
if !self.is_allowed_to_play() {
|
||||
self.internal_pause_steps();
|
||||
}
|
||||
|
@ -2229,9 +2216,10 @@ impl HTMLMediaElementMethods<crate::DomTypeHolder> for HTMLMediaElement {
|
|||
|
||||
let state = self.ready_state.get();
|
||||
|
||||
let window = self.owner_window();
|
||||
// FIXME(nox): Why are errors silenced here?
|
||||
let task_source = window.task_manager().media_element_task_source();
|
||||
let task_source = self
|
||||
.owner_window()
|
||||
.task_manager()
|
||||
.media_element_task_source();
|
||||
if self.Paused() {
|
||||
// Step 6.1.
|
||||
self.paused.set(false);
|
||||
|
@ -2243,14 +2231,14 @@ impl HTMLMediaElementMethods<crate::DomTypeHolder> for HTMLMediaElement {
|
|||
}
|
||||
|
||||
// Step 6.3.
|
||||
task_source.queue_simple_event(self.upcast(), atom!("play"), &window);
|
||||
task_source.queue_simple_event(self.upcast(), atom!("play"));
|
||||
|
||||
// Step 6.4.
|
||||
match state {
|
||||
ReadyState::HaveNothing |
|
||||
ReadyState::HaveMetadata |
|
||||
ReadyState::HaveCurrentData => {
|
||||
task_source.queue_simple_event(self.upcast(), atom!("waiting"), &window);
|
||||
task_source.queue_simple_event(self.upcast(), atom!("waiting"));
|
||||
},
|
||||
ReadyState::HaveFutureData | ReadyState::HaveEnoughData => {
|
||||
self.notify_about_playing();
|
||||
|
@ -2262,19 +2250,16 @@ impl HTMLMediaElementMethods<crate::DomTypeHolder> for HTMLMediaElement {
|
|||
let this = Trusted::new(self);
|
||||
let generation_id = self.generation_id.get();
|
||||
task_source
|
||||
.queue(
|
||||
task!(resolve_pending_play_promises: move || {
|
||||
let this = this.root();
|
||||
if generation_id != this.generation_id.get() {
|
||||
return;
|
||||
}
|
||||
.queue(task!(resolve_pending_play_promises: move || {
|
||||
let this = this.root();
|
||||
if generation_id != this.generation_id.get() {
|
||||
return;
|
||||
}
|
||||
|
||||
this.fulfill_in_flight_play_promises(|| {
|
||||
this.play_media();
|
||||
});
|
||||
}),
|
||||
window.upcast(),
|
||||
)
|
||||
this.fulfill_in_flight_play_promises(|| {
|
||||
this.play_media();
|
||||
});
|
||||
}))
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
|
@ -2478,11 +2463,10 @@ impl HTMLMediaElementMethods<crate::DomTypeHolder> for HTMLMediaElement {
|
|||
if *value != self.volume.get() {
|
||||
self.volume.set(*value);
|
||||
|
||||
let window = self.owner_window();
|
||||
window
|
||||
self.owner_window()
|
||||
.task_manager()
|
||||
.media_element_task_source()
|
||||
.queue_simple_event(self.upcast(), atom!("volumechange"), &window);
|
||||
.queue_simple_event(self.upcast(), atom!("volumechange"));
|
||||
if !self.is_allowed_to_play() {
|
||||
self.internal_pause_steps();
|
||||
}
|
||||
|
@ -2809,11 +2793,10 @@ impl FetchResponseListener for HTMLMediaElementFetchListener {
|
|||
// https://html.spec.whatwg.org/multipage/#concept-media-load-resource step 4,
|
||||
// => "If mode is remote" step 2
|
||||
if Instant::now() > self.next_progress_event {
|
||||
let window = elem.owner_window();
|
||||
window
|
||||
elem.owner_window()
|
||||
.task_manager()
|
||||
.media_element_task_source()
|
||||
.queue_simple_event(elem.upcast(), atom!("progress"), &window);
|
||||
.queue_simple_event(elem.upcast(), atom!("progress"));
|
||||
self.next_progress_event = Instant::now() + Duration::from_millis(350);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -64,7 +64,6 @@ use crate::script_module::{
|
|||
fetch_external_module_script, fetch_inline_module_script, ModuleOwner, ScriptFetchOptions,
|
||||
};
|
||||
use crate::script_runtime::CanGc;
|
||||
use crate::task::TaskCanceller;
|
||||
use crate::task_source::{TaskSource, TaskSourceName};
|
||||
use crate::unminify::{unminify_js, ScriptSource};
|
||||
|
||||
|
@ -102,7 +101,6 @@ impl ScriptSource for ScriptOrigin {
|
|||
final_url: ServoUrl,
|
||||
url: ServoUrl,
|
||||
task_source: TaskSource,
|
||||
canceller: TaskCanceller,
|
||||
script_text: String,
|
||||
fetch_options: ScriptFetchOptions,
|
||||
}
|
||||
|
@ -123,7 +121,7 @@ unsafe extern "C" fn off_thread_compilation_callback(
|
|||
let fetch_options = context.fetch_options.clone();
|
||||
|
||||
// Continue with <https://html.spec.whatwg.org/multipage/#fetch-a-classic-script>
|
||||
let _ = context.task_source.queue_with_canceller(
|
||||
let _ = context.task_source.queue(
|
||||
task!(off_thread_compile_continue: move || {
|
||||
let elem = script_element.root();
|
||||
let global = elem.global();
|
||||
|
@ -157,8 +155,7 @@ unsafe extern "C" fn off_thread_compilation_callback(
|
|||
};
|
||||
|
||||
finish_fetching_a_classic_script(&elem, script_kind, url, load);
|
||||
}),
|
||||
&context.canceller,
|
||||
})
|
||||
);
|
||||
}*/
|
||||
|
||||
|
@ -476,7 +473,6 @@ impl FetchResponseListener for ClassicContext {
|
|||
final_url,
|
||||
url: self.url.clone(),
|
||||
task_source: global.task_manager().dom_manipulation_task_source(),
|
||||
canceller: global.task_canceller(TaskSourceName::DOMManipulation),
|
||||
script_text: source_string,
|
||||
fetch_options: self.fetch_options.clone(),
|
||||
});
|
||||
|
@ -1061,11 +1057,10 @@ impl HTMLScriptElement {
|
|||
}
|
||||
|
||||
pub fn queue_error_event(&self) {
|
||||
let window = self.owner_window();
|
||||
window
|
||||
self.owner_window()
|
||||
.task_manager()
|
||||
.dom_manipulation_task_source()
|
||||
.queue_simple_event(self.upcast(), atom!("error"), &window);
|
||||
.queue_simple_event(self.upcast(), atom!("error"));
|
||||
}
|
||||
|
||||
pub fn dispatch_load_event(&self, can_gc: CanGc) {
|
||||
|
|
|
@ -133,11 +133,10 @@ impl HTMLStyleElement {
|
|||
|
||||
// No subresource loads were triggered, queue load event
|
||||
if self.pending_loads.get() == 0 {
|
||||
let window = self.owner_window();
|
||||
window
|
||||
self.owner_window()
|
||||
.task_manager()
|
||||
.dom_manipulation_task_source()
|
||||
.queue_simple_event(self.upcast(), atom!("load"), &window);
|
||||
.queue_simple_event(self.upcast(), atom!("load"));
|
||||
}
|
||||
|
||||
self.set_stylesheet(sheet);
|
||||
|
|
|
@ -650,8 +650,7 @@ impl VirtualMethods for HTMLTextAreaElement {
|
|||
}
|
||||
} else if event.type_() == atom!("keypress") && !event.DefaultPrevented() {
|
||||
if event.IsTrusted() {
|
||||
let window = self.owner_window();
|
||||
window
|
||||
self.owner_window()
|
||||
.task_manager()
|
||||
.user_interaction_task_source()
|
||||
.queue_event(
|
||||
|
@ -659,7 +658,6 @@ impl VirtualMethods for HTMLTextAreaElement {
|
|||
atom!("input"),
|
||||
EventBubbles::Bubbles,
|
||||
EventCancelable::NotCancelable,
|
||||
&window,
|
||||
);
|
||||
}
|
||||
} else if event.type_() == atom!("compositionstart") ||
|
||||
|
|
|
@ -125,9 +125,10 @@ impl HTMLVideoElement {
|
|||
let sent_resize = if self.htmlmediaelement.get_ready_state() == ReadyState::HaveNothing {
|
||||
None
|
||||
} else {
|
||||
let window = self.owner_window();
|
||||
let task_source = window.task_manager().media_element_task_source();
|
||||
task_source.queue_simple_event(self.upcast(), atom!("resize"), &window);
|
||||
self.owner_window()
|
||||
.task_manager()
|
||||
.media_element_task_source()
|
||||
.queue_simple_event(self.upcast(), atom!("resize"));
|
||||
Some((width, height))
|
||||
};
|
||||
|
||||
|
|
|
@ -170,16 +170,12 @@ impl OfflineAudioContextMethods<crate::DomTypeHolder> for OfflineAudioContext {
|
|||
}));
|
||||
|
||||
let this = Trusted::new(self);
|
||||
let global = self.global();
|
||||
let window = global.as_window();
|
||||
let (task_source, canceller) = window
|
||||
.task_manager()
|
||||
.dom_manipulation_task_source_with_canceller();
|
||||
let task_source = self.global().task_manager().dom_manipulation_task_source();
|
||||
Builder::new()
|
||||
.name("OfflineACResolver".to_owned())
|
||||
.spawn(move || {
|
||||
let _ = receiver.recv();
|
||||
let _ = task_source.queue_with_canceller(
|
||||
let _ = task_source.queue(
|
||||
task!(resolve: move || {
|
||||
let this = this.root();
|
||||
let processed_audio = processed_audio.lock().unwrap();
|
||||
|
@ -207,8 +203,7 @@ impl OfflineAudioContextMethods<crate::DomTypeHolder> for OfflineAudioContext {
|
|||
EventCancelable::NotCancelable,
|
||||
&buffer, CanGc::note());
|
||||
event.upcast::<Event>().fire(this.upcast(), CanGc::note());
|
||||
}),
|
||||
&canceller,
|
||||
})
|
||||
);
|
||||
})
|
||||
.unwrap();
|
||||
|
|
|
@ -247,7 +247,7 @@ impl Performance {
|
|||
let task = task!(notify_performance_observers: move || {
|
||||
owner.root().notify_observers();
|
||||
});
|
||||
let _ = task_source.queue(task, global);
|
||||
let _ = task_source.queue(task);
|
||||
}
|
||||
}
|
||||
let mut observers = self.observers.borrow_mut();
|
||||
|
@ -334,7 +334,7 @@ impl Performance {
|
|||
let task = task!(notify_performance_observers: move || {
|
||||
owner.root().notify_observers();
|
||||
});
|
||||
let _ = task_source.queue(task, global);
|
||||
let _ = task_source.queue(task);
|
||||
|
||||
Some(entry_last_index)
|
||||
}
|
||||
|
|
|
@ -52,7 +52,6 @@ use crate::dom::rtctrackevent::RTCTrackEvent;
|
|||
use crate::dom::window::Window;
|
||||
use crate::realms::{enter_realm, InRealm};
|
||||
use crate::script_runtime::CanGc;
|
||||
use crate::task::TaskCanceller;
|
||||
use crate::task_source::TaskSource;
|
||||
|
||||
#[dom_struct]
|
||||
|
@ -81,75 +80,64 @@ pub struct RTCPeerConnection {
|
|||
struct RTCSignaller {
|
||||
trusted: Trusted<RTCPeerConnection>,
|
||||
task_source: TaskSource,
|
||||
canceller: TaskCanceller,
|
||||
}
|
||||
|
||||
impl WebRtcSignaller for RTCSignaller {
|
||||
fn on_ice_candidate(&self, _: &WebRtcController, candidate: IceCandidate) {
|
||||
let this = self.trusted.clone();
|
||||
let _ = self.task_source.queue_with_canceller(
|
||||
task!(on_ice_candidate: move || {
|
||||
let this = this.root();
|
||||
this.on_ice_candidate(candidate, CanGc::note());
|
||||
}),
|
||||
&self.canceller,
|
||||
);
|
||||
let _ = self.task_source.queue(task!(on_ice_candidate: move || {
|
||||
let this = this.root();
|
||||
this.on_ice_candidate(candidate, CanGc::note());
|
||||
}));
|
||||
}
|
||||
|
||||
fn on_negotiation_needed(&self, _: &WebRtcController) {
|
||||
let this = self.trusted.clone();
|
||||
let _ = self.task_source.queue_with_canceller(
|
||||
task!(on_negotiation_needed: move || {
|
||||
let _ = self
|
||||
.task_source
|
||||
.queue(task!(on_negotiation_needed: move || {
|
||||
let this = this.root();
|
||||
this.on_negotiation_needed(CanGc::note());
|
||||
}),
|
||||
&self.canceller,
|
||||
);
|
||||
}));
|
||||
}
|
||||
|
||||
fn update_gathering_state(&self, state: GatheringState) {
|
||||
let this = self.trusted.clone();
|
||||
let _ = self.task_source.queue_with_canceller(
|
||||
task!(update_gathering_state: move || {
|
||||
let _ = self
|
||||
.task_source
|
||||
.queue(task!(update_gathering_state: move || {
|
||||
let this = this.root();
|
||||
this.update_gathering_state(state, CanGc::note());
|
||||
}),
|
||||
&self.canceller,
|
||||
);
|
||||
}));
|
||||
}
|
||||
|
||||
fn update_ice_connection_state(&self, state: IceConnectionState) {
|
||||
let this = self.trusted.clone();
|
||||
let _ = self.task_source.queue_with_canceller(
|
||||
task!(update_ice_connection_state: move || {
|
||||
let _ = self
|
||||
.task_source
|
||||
.queue(task!(update_ice_connection_state: move || {
|
||||
let this = this.root();
|
||||
this.update_ice_connection_state(state, CanGc::note());
|
||||
}),
|
||||
&self.canceller,
|
||||
);
|
||||
}));
|
||||
}
|
||||
|
||||
fn update_signaling_state(&self, state: SignalingState) {
|
||||
let this = self.trusted.clone();
|
||||
let _ = self.task_source.queue_with_canceller(
|
||||
task!(update_signaling_state: move || {
|
||||
let _ = self
|
||||
.task_source
|
||||
.queue(task!(update_signaling_state: move || {
|
||||
let this = this.root();
|
||||
this.update_signaling_state(state, CanGc::note());
|
||||
}),
|
||||
&self.canceller,
|
||||
);
|
||||
}));
|
||||
}
|
||||
|
||||
fn on_add_stream(&self, id: &MediaStreamId, ty: MediaStreamType) {
|
||||
let this = self.trusted.clone();
|
||||
let id = *id;
|
||||
let _ = self.task_source.queue_with_canceller(
|
||||
task!(on_add_stream: move || {
|
||||
let this = this.root();
|
||||
this.on_add_stream(id, ty, CanGc::note());
|
||||
}),
|
||||
&self.canceller,
|
||||
);
|
||||
let _ = self.task_source.queue(task!(on_add_stream: move || {
|
||||
let this = this.root();
|
||||
this.on_add_stream(id, ty, CanGc::note());
|
||||
}));
|
||||
}
|
||||
|
||||
fn on_data_channel_event(
|
||||
|
@ -160,15 +148,14 @@ impl WebRtcSignaller for RTCSignaller {
|
|||
) {
|
||||
// XXX(ferjm) get label and options from channel properties.
|
||||
let this = self.trusted.clone();
|
||||
let _ = self.task_source.queue_with_canceller(
|
||||
task!(on_data_channel_event: move || {
|
||||
let _ = self
|
||||
.task_source
|
||||
.queue(task!(on_data_channel_event: move || {
|
||||
let this = this.root();
|
||||
let global = this.global();
|
||||
let _ac = enter_realm(&*global);
|
||||
this.on_data_channel_event(channel, event, CanGc::note());
|
||||
}),
|
||||
&self.canceller,
|
||||
);
|
||||
}));
|
||||
}
|
||||
|
||||
fn close(&self) {
|
||||
|
@ -237,15 +224,10 @@ impl RTCPeerConnection {
|
|||
|
||||
fn make_signaller(&self) -> Box<dyn WebRtcSignaller> {
|
||||
let trusted = Trusted::new(self);
|
||||
let (task_source, canceller) = self
|
||||
.global()
|
||||
.as_window()
|
||||
.task_manager()
|
||||
.networking_task_source_with_canceller();
|
||||
let task_source = self.global().task_manager().networking_task_source();
|
||||
Box::new(RTCSignaller {
|
||||
trusted,
|
||||
task_source,
|
||||
canceller,
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -460,65 +442,51 @@ impl RTCPeerConnection {
|
|||
|
||||
fn create_offer(&self) {
|
||||
let generation = self.offer_answer_generation.get();
|
||||
let (task_source, canceller) = self
|
||||
.global()
|
||||
.as_window()
|
||||
.task_manager()
|
||||
.networking_task_source_with_canceller();
|
||||
let task_source = self.global().task_manager().networking_task_source();
|
||||
let this = Trusted::new(self);
|
||||
self.controller
|
||||
.borrow_mut()
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.create_offer(Box::new(move |desc: SessionDescription| {
|
||||
let _ = task_source.queue_with_canceller(
|
||||
task!(offer_created: move || {
|
||||
let this = this.root();
|
||||
if this.offer_answer_generation.get() != generation {
|
||||
// the state has changed since we last created the offer,
|
||||
// create a fresh one
|
||||
this.create_offer();
|
||||
} else {
|
||||
let init: RTCSessionDescriptionInit = desc.convert();
|
||||
for promise in this.offer_promises.borrow_mut().drain(..) {
|
||||
promise.resolve_native(&init);
|
||||
}
|
||||
let _ = task_source.queue(task!(offer_created: move || {
|
||||
let this = this.root();
|
||||
if this.offer_answer_generation.get() != generation {
|
||||
// the state has changed since we last created the offer,
|
||||
// create a fresh one
|
||||
this.create_offer();
|
||||
} else {
|
||||
let init: RTCSessionDescriptionInit = desc.convert();
|
||||
for promise in this.offer_promises.borrow_mut().drain(..) {
|
||||
promise.resolve_native(&init);
|
||||
}
|
||||
}),
|
||||
&canceller,
|
||||
);
|
||||
}
|
||||
}));
|
||||
}));
|
||||
}
|
||||
|
||||
fn create_answer(&self) {
|
||||
let generation = self.offer_answer_generation.get();
|
||||
let (task_source, canceller) = self
|
||||
.global()
|
||||
.as_window()
|
||||
.task_manager()
|
||||
.networking_task_source_with_canceller();
|
||||
let task_source = self.global().task_manager().networking_task_source();
|
||||
let this = Trusted::new(self);
|
||||
self.controller
|
||||
.borrow_mut()
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.create_answer(Box::new(move |desc: SessionDescription| {
|
||||
let _ = task_source.queue_with_canceller(
|
||||
task!(answer_created: move || {
|
||||
let this = this.root();
|
||||
if this.offer_answer_generation.get() != generation {
|
||||
// the state has changed since we last created the offer,
|
||||
// create a fresh one
|
||||
this.create_answer();
|
||||
} else {
|
||||
let init: RTCSessionDescriptionInit = desc.convert();
|
||||
for promise in this.answer_promises.borrow_mut().drain(..) {
|
||||
promise.resolve_native(&init);
|
||||
}
|
||||
let _ = task_source.queue(task!(answer_created: move || {
|
||||
let this = this.root();
|
||||
if this.offer_answer_generation.get() != generation {
|
||||
// the state has changed since we last created the offer,
|
||||
// create a fresh one
|
||||
this.create_answer();
|
||||
} else {
|
||||
let init: RTCSessionDescriptionInit = desc.convert();
|
||||
for promise in this.answer_promises.borrow_mut().drain(..) {
|
||||
promise.resolve_native(&init);
|
||||
}
|
||||
}),
|
||||
&canceller,
|
||||
);
|
||||
}
|
||||
}));
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
@ -667,11 +635,7 @@ impl RTCPeerConnectionMethods<crate::DomTypeHolder> for RTCPeerConnection {
|
|||
let this = Trusted::new(self);
|
||||
let desc: SessionDescription = desc.convert();
|
||||
let trusted_promise = TrustedPromise::new(p.clone());
|
||||
let (task_source, canceller) = self
|
||||
.global()
|
||||
.as_window()
|
||||
.task_manager()
|
||||
.networking_task_source_with_canceller();
|
||||
let task_source = self.global().task_manager().networking_task_source();
|
||||
self.controller
|
||||
.borrow_mut()
|
||||
.as_ref()
|
||||
|
@ -679,23 +643,20 @@ impl RTCPeerConnectionMethods<crate::DomTypeHolder> for RTCPeerConnection {
|
|||
.set_local_description(
|
||||
desc.clone(),
|
||||
Box::new(move || {
|
||||
let _ = task_source.queue_with_canceller(
|
||||
task!(local_description_set: move || {
|
||||
// XXXManishearth spec actually asks for an intricate
|
||||
// dance between pending/current local/remote descriptions
|
||||
let this = this.root();
|
||||
let desc = desc.convert();
|
||||
let desc = RTCSessionDescription::Constructor(
|
||||
this.global().as_window(),
|
||||
None,
|
||||
CanGc::note(),
|
||||
&desc,
|
||||
).unwrap();
|
||||
this.local_description.set(Some(&desc));
|
||||
trusted_promise.root().resolve_native(&())
|
||||
}),
|
||||
&canceller,
|
||||
);
|
||||
let _ = task_source.queue(task!(local_description_set: move || {
|
||||
// XXXManishearth spec actually asks for an intricate
|
||||
// dance between pending/current local/remote descriptions
|
||||
let this = this.root();
|
||||
let desc = desc.convert();
|
||||
let desc = RTCSessionDescription::Constructor(
|
||||
this.global().as_window(),
|
||||
None,
|
||||
CanGc::note(),
|
||||
&desc,
|
||||
).unwrap();
|
||||
this.local_description.set(Some(&desc));
|
||||
trusted_promise.root().resolve_native(&())
|
||||
}));
|
||||
}),
|
||||
);
|
||||
p
|
||||
|
@ -713,11 +674,7 @@ impl RTCPeerConnectionMethods<crate::DomTypeHolder> for RTCPeerConnection {
|
|||
let this = Trusted::new(self);
|
||||
let desc: SessionDescription = desc.convert();
|
||||
let trusted_promise = TrustedPromise::new(p.clone());
|
||||
let (task_source, canceller) = self
|
||||
.global()
|
||||
.as_window()
|
||||
.task_manager()
|
||||
.networking_task_source_with_canceller();
|
||||
let task_source = self.global().task_manager().networking_task_source();
|
||||
self.controller
|
||||
.borrow_mut()
|
||||
.as_ref()
|
||||
|
@ -725,23 +682,20 @@ impl RTCPeerConnectionMethods<crate::DomTypeHolder> for RTCPeerConnection {
|
|||
.set_remote_description(
|
||||
desc.clone(),
|
||||
Box::new(move || {
|
||||
let _ = task_source.queue_with_canceller(
|
||||
task!(remote_description_set: move || {
|
||||
// XXXManishearth spec actually asks for an intricate
|
||||
// dance between pending/current local/remote descriptions
|
||||
let this = this.root();
|
||||
let desc = desc.convert();
|
||||
let desc = RTCSessionDescription::Constructor(
|
||||
this.global().as_window(),
|
||||
None,
|
||||
CanGc::note(),
|
||||
&desc,
|
||||
).unwrap();
|
||||
this.remote_description.set(Some(&desc));
|
||||
trusted_promise.root().resolve_native(&())
|
||||
}),
|
||||
&canceller,
|
||||
);
|
||||
let _ = task_source.queue(task!(remote_description_set: move || {
|
||||
// XXXManishearth spec actually asks for an intricate
|
||||
// dance between pending/current local/remote descriptions
|
||||
let this = this.root();
|
||||
let desc = desc.convert();
|
||||
let desc = RTCSessionDescription::Constructor(
|
||||
this.global().as_window(),
|
||||
None,
|
||||
CanGc::note(),
|
||||
&desc,
|
||||
).unwrap();
|
||||
this.remote_description.set(Some(&desc));
|
||||
trusted_promise.root().resolve_native(&())
|
||||
}));
|
||||
}),
|
||||
);
|
||||
p
|
||||
|
|
|
@ -88,8 +88,8 @@ impl Selection {
|
|||
return;
|
||||
}
|
||||
let this = Trusted::new(self);
|
||||
let window = self.document.window();
|
||||
window
|
||||
self.document
|
||||
.window()
|
||||
.task_manager()
|
||||
.user_interaction_task_source() // w3c/selection-api#117
|
||||
.queue(
|
||||
|
@ -97,8 +97,7 @@ impl Selection {
|
|||
let this = this.root();
|
||||
this.task_queued.set(false);
|
||||
this.document.upcast::<EventTarget>().fire_event(atom!("selectionchange"), CanGc::note());
|
||||
}),
|
||||
window.upcast(),
|
||||
})
|
||||
)
|
||||
.expect("Couldn't queue selectionchange task!");
|
||||
self.task_queued.set(true);
|
||||
|
|
|
@ -26,8 +26,7 @@ use crate::dom::serviceworker::ServiceWorker;
|
|||
use crate::dom::serviceworkerregistration::ServiceWorkerRegistration;
|
||||
use crate::realms::{enter_realm, InRealm};
|
||||
use crate::script_runtime::CanGc;
|
||||
use crate::task::TaskCanceller;
|
||||
use crate::task_source::{TaskSource, TaskSourceName};
|
||||
use crate::task_source::TaskSource;
|
||||
|
||||
#[dom_struct]
|
||||
pub struct ServiceWorkerContainer {
|
||||
|
@ -141,15 +140,10 @@ impl ServiceWorkerContainerMethods<crate::DomTypeHolder> for ServiceWorkerContai
|
|||
|
||||
// Setup the callback for reject/resolve of the promise,
|
||||
// from steps running "in-parallel" from here in the serviceworker manager.
|
||||
let (task_source, task_canceller) = (
|
||||
global.task_manager().dom_manipulation_task_source(),
|
||||
global.task_canceller(TaskSourceName::DOMManipulation),
|
||||
);
|
||||
|
||||
let task_source = global.task_manager().dom_manipulation_task_source();
|
||||
let mut handler = RegisterJobResultHandler {
|
||||
trusted_promise: Some(TrustedPromise::new(promise.clone())),
|
||||
task_source,
|
||||
task_canceller,
|
||||
};
|
||||
|
||||
let (job_result_sender, job_result_receiver) = ipc::channel().expect("ipc channel failure");
|
||||
|
@ -190,7 +184,6 @@ impl ServiceWorkerContainerMethods<crate::DomTypeHolder> for ServiceWorkerContai
|
|||
struct RegisterJobResultHandler {
|
||||
trusted_promise: Option<TrustedPromise>,
|
||||
task_source: TaskSource,
|
||||
task_canceller: TaskCanceller,
|
||||
}
|
||||
|
||||
impl RegisterJobResultHandler {
|
||||
|
@ -206,7 +199,7 @@ impl RegisterJobResultHandler {
|
|||
.expect("No promise to resolve for SW Register job.");
|
||||
|
||||
// Step 1
|
||||
let _ = self.task_source.queue_with_canceller(
|
||||
let _ = self.task_source.queue(
|
||||
task!(reject_promise_with_security_error: move || {
|
||||
let promise = promise.root();
|
||||
let _ac = enter_realm(&*promise.global());
|
||||
|
@ -219,8 +212,7 @@ impl RegisterJobResultHandler {
|
|||
},
|
||||
}
|
||||
|
||||
}),
|
||||
&self.task_canceller,
|
||||
})
|
||||
);
|
||||
|
||||
// TODO: step 2, handle equivalent jobs.
|
||||
|
@ -232,35 +224,32 @@ impl RegisterJobResultHandler {
|
|||
.expect("No promise to resolve for SW Register job.");
|
||||
|
||||
// Step 1
|
||||
let _ = self.task_source.queue_with_canceller(
|
||||
task!(resolve_promise: move || {
|
||||
let promise = promise.root();
|
||||
let global = promise.global();
|
||||
let _ac = enter_realm(&*global);
|
||||
let _ = self.task_source.queue(task!(resolve_promise: move || {
|
||||
let promise = promise.root();
|
||||
let global = promise.global();
|
||||
let _ac = enter_realm(&*global);
|
||||
|
||||
// Step 1.1
|
||||
let JobResultValue::Registration {
|
||||
id,
|
||||
installing_worker,
|
||||
waiting_worker,
|
||||
active_worker,
|
||||
} = value;
|
||||
// Step 1.1
|
||||
let JobResultValue::Registration {
|
||||
id,
|
||||
installing_worker,
|
||||
waiting_worker,
|
||||
active_worker,
|
||||
} = value;
|
||||
|
||||
// Step 1.2 (Job type is "register").
|
||||
let registration = global.get_serviceworker_registration(
|
||||
&job.script_url,
|
||||
&job.scope_url,
|
||||
id,
|
||||
installing_worker,
|
||||
waiting_worker,
|
||||
active_worker,
|
||||
);
|
||||
// Step 1.2 (Job type is "register").
|
||||
let registration = global.get_serviceworker_registration(
|
||||
&job.script_url,
|
||||
&job.scope_url,
|
||||
id,
|
||||
installing_worker,
|
||||
waiting_worker,
|
||||
active_worker,
|
||||
);
|
||||
|
||||
// Step 1.4
|
||||
promise.resolve_native(&*registration);
|
||||
}),
|
||||
&self.task_canceller,
|
||||
);
|
||||
// Step 1.4
|
||||
promise.resolve_native(&*registration);
|
||||
}));
|
||||
|
||||
// TODO: step 2, handle equivalent jobs.
|
||||
},
|
||||
|
|
|
@ -412,7 +412,7 @@ impl ServiceWorkerGlobalScope {
|
|||
}
|
||||
},
|
||||
reporter_name,
|
||||
scope.script_chan(),
|
||||
global.event_loop_sender(),
|
||||
CommonScriptMsg::CollectReports,
|
||||
);
|
||||
|
||||
|
@ -485,7 +485,7 @@ impl ServiceWorkerGlobalScope {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn script_chan(&self) -> Box<dyn ScriptChan + Send> {
|
||||
pub(crate) fn event_loop_sender(&self) -> Box<dyn ScriptChan + Send> {
|
||||
Box::new(ServiceWorkerChan {
|
||||
sender: self.own_sender.clone(),
|
||||
})
|
||||
|
|
|
@ -209,29 +209,25 @@ impl Storage {
|
|||
let global = self.global();
|
||||
let this = Trusted::new(self);
|
||||
global
|
||||
.as_window()
|
||||
.task_manager()
|
||||
.dom_manipulation_task_source()
|
||||
.queue(
|
||||
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),
|
||||
CanGc::note()
|
||||
);
|
||||
event.upcast::<Event>().fire(global.upcast(), CanGc::note());
|
||||
}),
|
||||
global.upcast(),
|
||||
)
|
||||
.queue(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),
|
||||
CanGc::note()
|
||||
);
|
||||
event.upcast::<Event>().fire(global.upcast(), CanGc::note());
|
||||
}))
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,7 +40,6 @@ use crate::dom::bindings::codegen::UnionTypes::{
|
|||
};
|
||||
use crate::dom::bindings::error::{Error, Fallible};
|
||||
use crate::dom::bindings::import::module::SafeJSContext;
|
||||
use crate::dom::bindings::inheritance::Castable;
|
||||
use crate::dom::bindings::refcounted::{Trusted, TrustedPromise};
|
||||
use crate::dom::bindings::reflector::{reflect_dom_object, DomObject, Reflector};
|
||||
use crate::dom::bindings::root::DomRoot;
|
||||
|
@ -49,12 +48,8 @@ use crate::dom::bindings::trace::RootedTraceableBox;
|
|||
use crate::dom::cryptokey::{CryptoKey, Handle};
|
||||
use crate::dom::globalscope::GlobalScope;
|
||||
use crate::dom::promise::Promise;
|
||||
use crate::dom::window::Window;
|
||||
use crate::dom::workerglobalscope::WorkerGlobalScope;
|
||||
use crate::realms::InRealm;
|
||||
use crate::script_runtime::{CanGc, JSContext};
|
||||
use crate::task::TaskCanceller;
|
||||
use crate::task_source::TaskSource;
|
||||
|
||||
// String constants for algorithms/curves
|
||||
const ALG_AES_CBC: &str = "AES-CBC";
|
||||
|
@ -140,20 +135,6 @@ impl SubtleCrypto {
|
|||
CanGc::note(),
|
||||
)
|
||||
}
|
||||
|
||||
fn task_source_with_canceller(&self) -> (TaskSource, TaskCanceller) {
|
||||
if let Some(window) = self.global().downcast::<Window>() {
|
||||
window
|
||||
.task_manager()
|
||||
.dom_manipulation_task_source_with_canceller()
|
||||
} else if let Some(worker_global) = self.global().downcast::<WorkerGlobalScope>() {
|
||||
let task_source = worker_global.task_manager().dom_manipulation_task_source();
|
||||
let canceller = worker_global.task_canceller();
|
||||
(task_source, canceller)
|
||||
} else {
|
||||
unreachable!("Couldn't downcast to Window or WorkerGlobalScope!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl SubtleCryptoMethods<crate::DomTypeHolder> for SubtleCrypto {
|
||||
|
@ -181,13 +162,13 @@ impl SubtleCryptoMethods<crate::DomTypeHolder> for SubtleCrypto {
|
|||
ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
|
||||
};
|
||||
|
||||
let (task_source, canceller) = self.task_source_with_canceller();
|
||||
let task_source = self.global().task_manager().dom_manipulation_task_source();
|
||||
let this = Trusted::new(self);
|
||||
let trusted_promise = TrustedPromise::new(promise.clone());
|
||||
let trusted_key = Trusted::new(key);
|
||||
let key_alg = key.algorithm();
|
||||
let valid_usage = key.usages().contains(&KeyUsage::Encrypt);
|
||||
let _ = task_source.queue_with_canceller(
|
||||
let _ = task_source.queue(
|
||||
task!(encrypt: move || {
|
||||
let subtle = this.root();
|
||||
let promise = trusted_promise.root();
|
||||
|
@ -206,8 +187,7 @@ impl SubtleCryptoMethods<crate::DomTypeHolder> for SubtleCrypto {
|
|||
return;
|
||||
}
|
||||
promise.resolve_native(&*array_buffer_ptr.handle());
|
||||
}),
|
||||
&canceller,
|
||||
})
|
||||
);
|
||||
|
||||
promise
|
||||
|
@ -237,13 +217,13 @@ impl SubtleCryptoMethods<crate::DomTypeHolder> for SubtleCrypto {
|
|||
ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
|
||||
};
|
||||
|
||||
let (task_source, canceller) = self.task_source_with_canceller();
|
||||
let task_source = self.global().task_manager().dom_manipulation_task_source();
|
||||
let this = Trusted::new(self);
|
||||
let trusted_promise = TrustedPromise::new(promise.clone());
|
||||
let trusted_key = Trusted::new(key);
|
||||
let key_alg = key.algorithm();
|
||||
let valid_usage = key.usages().contains(&KeyUsage::Decrypt);
|
||||
let _ = task_source.queue_with_canceller(
|
||||
let _ = task_source.queue(
|
||||
task!(decrypt: move || {
|
||||
let subtle = this.root();
|
||||
let promise = trusted_promise.root();
|
||||
|
@ -262,8 +242,7 @@ impl SubtleCryptoMethods<crate::DomTypeHolder> for SubtleCrypto {
|
|||
}
|
||||
|
||||
promise.resolve_native(&*array_buffer_ptr.handle());
|
||||
}),
|
||||
&canceller,
|
||||
})
|
||||
);
|
||||
|
||||
promise
|
||||
|
@ -304,51 +283,48 @@ impl SubtleCryptoMethods<crate::DomTypeHolder> for SubtleCrypto {
|
|||
// NOTE: We did that in preparation of Step 4.
|
||||
|
||||
// Step 6. Return promise and perform the remaining steps in parallel.
|
||||
let (task_source, canceller) = self.task_source_with_canceller();
|
||||
let task_source = self.global().task_manager().dom_manipulation_task_source();
|
||||
let trusted_promise = TrustedPromise::new(promise.clone());
|
||||
let trusted_key = Trusted::new(key);
|
||||
|
||||
let _ = task_source.queue_with_canceller(
|
||||
task!(sign: move || {
|
||||
// Step 7. If the following steps or referenced procedures say to throw an error, reject promise
|
||||
// with the returned error and then terminate the algorithm.
|
||||
let promise = trusted_promise.root();
|
||||
let key = trusted_key.root();
|
||||
let _ = task_source.queue(task!(sign: move || {
|
||||
// Step 7. If the following steps or referenced procedures say to throw an error, reject promise
|
||||
// with the returned error and then terminate the algorithm.
|
||||
let promise = trusted_promise.root();
|
||||
let key = trusted_key.root();
|
||||
|
||||
// Step 8. If the name member of normalizedAlgorithm is not equal to the name attribute of the
|
||||
// [[algorithm]] internal slot of key then throw an InvalidAccessError.
|
||||
if normalized_algorithm.name() != key.algorithm() {
|
||||
promise.reject_error(Error::InvalidAccess);
|
||||
// Step 8. If the name member of normalizedAlgorithm is not equal to the name attribute of the
|
||||
// [[algorithm]] internal slot of key then throw an InvalidAccessError.
|
||||
if normalized_algorithm.name() != key.algorithm() {
|
||||
promise.reject_error(Error::InvalidAccess);
|
||||
return;
|
||||
}
|
||||
|
||||
// Step 9. If the [[usages]] internal slot of key does not contain an entry that is "sign",
|
||||
// then throw an InvalidAccessError.
|
||||
if !key.usages().contains(&KeyUsage::Sign) {
|
||||
promise.reject_error(Error::InvalidAccess);
|
||||
return;
|
||||
}
|
||||
|
||||
// Step 10. Let result be the result of performing the sign operation specified by normalizedAlgorithm
|
||||
// using key and algorithm and with data as message.
|
||||
let cx = GlobalScope::get_cx();
|
||||
let result = match normalized_algorithm.sign(cx, &key, &data) {
|
||||
Ok(signature) => signature,
|
||||
Err(e) => {
|
||||
promise.reject_error(e);
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
// Step 9. If the [[usages]] internal slot of key does not contain an entry that is "sign",
|
||||
// then throw an InvalidAccessError.
|
||||
if !key.usages().contains(&KeyUsage::Sign) {
|
||||
promise.reject_error(Error::InvalidAccess);
|
||||
return;
|
||||
}
|
||||
rooted!(in(*cx) let mut array_buffer_ptr = ptr::null_mut::<JSObject>());
|
||||
create_buffer_source::<ArrayBufferU8>(cx, &result, array_buffer_ptr.handle_mut())
|
||||
.expect("failed to create buffer source for exported key.");
|
||||
|
||||
// Step 10. Let result be the result of performing the sign operation specified by normalizedAlgorithm
|
||||
// using key and algorithm and with data as message.
|
||||
let cx = GlobalScope::get_cx();
|
||||
let result = match normalized_algorithm.sign(cx, &key, &data) {
|
||||
Ok(signature) => signature,
|
||||
Err(e) => {
|
||||
promise.reject_error(e);
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
rooted!(in(*cx) let mut array_buffer_ptr = ptr::null_mut::<JSObject>());
|
||||
create_buffer_source::<ArrayBufferU8>(cx, &result, array_buffer_ptr.handle_mut())
|
||||
.expect("failed to create buffer source for exported key.");
|
||||
|
||||
// Step 9. Resolve promise with result.
|
||||
promise.resolve_native(&*array_buffer_ptr);
|
||||
}),
|
||||
&canceller,
|
||||
);
|
||||
// Step 9. Resolve promise with result.
|
||||
promise.resolve_native(&*array_buffer_ptr);
|
||||
}));
|
||||
|
||||
promise
|
||||
}
|
||||
|
@ -397,47 +373,44 @@ impl SubtleCryptoMethods<crate::DomTypeHolder> for SubtleCrypto {
|
|||
// NOTE: We did that in preparation of Step 6.
|
||||
|
||||
// Step 7. Return promise and perform the remaining steps in parallel.
|
||||
let (task_source, canceller) = self.task_source_with_canceller();
|
||||
let task_source = self.global().task_manager().dom_manipulation_task_source();
|
||||
let trusted_promise = TrustedPromise::new(promise.clone());
|
||||
let trusted_key = Trusted::new(key);
|
||||
|
||||
let _ = task_source.queue_with_canceller(
|
||||
task!(sign: move || {
|
||||
// Step 8. If the following steps or referenced procedures say to throw an error, reject promise
|
||||
// with the returned error and then terminate the algorithm.
|
||||
let promise = trusted_promise.root();
|
||||
let key = trusted_key.root();
|
||||
let _ = task_source.queue(task!(sign: move || {
|
||||
// Step 8. If the following steps or referenced procedures say to throw an error, reject promise
|
||||
// with the returned error and then terminate the algorithm.
|
||||
let promise = trusted_promise.root();
|
||||
let key = trusted_key.root();
|
||||
|
||||
// Step 9. If the name member of normalizedAlgorithm is not equal to the name attribute of the
|
||||
// [[algorithm]] internal slot of key then throw an InvalidAccessError.
|
||||
if normalized_algorithm.name() != key.algorithm() {
|
||||
promise.reject_error(Error::InvalidAccess);
|
||||
// Step 9. If the name member of normalizedAlgorithm is not equal to the name attribute of the
|
||||
// [[algorithm]] internal slot of key then throw an InvalidAccessError.
|
||||
if normalized_algorithm.name() != key.algorithm() {
|
||||
promise.reject_error(Error::InvalidAccess);
|
||||
return;
|
||||
}
|
||||
|
||||
// Step 10. If the [[usages]] internal slot of key does not contain an entry that is "verify",
|
||||
// then throw an InvalidAccessError.
|
||||
if !key.usages().contains(&KeyUsage::Verify) {
|
||||
promise.reject_error(Error::InvalidAccess);
|
||||
return;
|
||||
}
|
||||
|
||||
// Step 1. Let result be the result of performing the verify operation specified by normalizedAlgorithm
|
||||
// using key, algorithm and signature and with data as message.
|
||||
let cx = GlobalScope::get_cx();
|
||||
let result = match normalized_algorithm.verify(cx, &key, &data, &signature) {
|
||||
Ok(result) => result,
|
||||
Err(e) => {
|
||||
promise.reject_error(e);
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
// Step 10. If the [[usages]] internal slot of key does not contain an entry that is "verify",
|
||||
// then throw an InvalidAccessError.
|
||||
if !key.usages().contains(&KeyUsage::Verify) {
|
||||
promise.reject_error(Error::InvalidAccess);
|
||||
return;
|
||||
}
|
||||
|
||||
// Step 1. Let result be the result of performing the verify operation specified by normalizedAlgorithm
|
||||
// using key, algorithm and signature and with data as message.
|
||||
let cx = GlobalScope::get_cx();
|
||||
let result = match normalized_algorithm.verify(cx, &key, &data, &signature) {
|
||||
Ok(result) => result,
|
||||
Err(e) => {
|
||||
promise.reject_error(e);
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
// Step 9. Resolve promise with result.
|
||||
promise.resolve_native(&result);
|
||||
}),
|
||||
&canceller,
|
||||
);
|
||||
// Step 9. Resolve promise with result.
|
||||
promise.resolve_native(&result);
|
||||
}));
|
||||
|
||||
promise
|
||||
}
|
||||
|
@ -476,10 +449,10 @@ impl SubtleCryptoMethods<crate::DomTypeHolder> for SubtleCrypto {
|
|||
// NOTE: We did that in preparation of Step 4.
|
||||
|
||||
// Step 6. Return promise and perform the remaining steps in parallel.
|
||||
let (task_source, canceller) = self.task_source_with_canceller();
|
||||
let task_source = self.global().task_manager().dom_manipulation_task_source();
|
||||
let trusted_promise = TrustedPromise::new(promise.clone());
|
||||
|
||||
let _ = task_source.queue_with_canceller(
|
||||
let _ = task_source.queue(
|
||||
task!(generate_key: move || {
|
||||
// Step 7. If the following steps or referenced procedures say to throw an error, reject promise
|
||||
// with the returned error and then terminate the algorithm.
|
||||
|
@ -503,8 +476,7 @@ impl SubtleCryptoMethods<crate::DomTypeHolder> for SubtleCrypto {
|
|||
|
||||
// Step 9. Resolve promise with result.
|
||||
promise.resolve_native(&*array_buffer_ptr);
|
||||
}),
|
||||
&canceller,
|
||||
})
|
||||
);
|
||||
|
||||
promise
|
||||
|
@ -529,22 +501,19 @@ impl SubtleCryptoMethods<crate::DomTypeHolder> for SubtleCrypto {
|
|||
},
|
||||
};
|
||||
|
||||
let (task_source, canceller) = self.task_source_with_canceller();
|
||||
let task_source = self.global().task_manager().dom_manipulation_task_source();
|
||||
let this = Trusted::new(self);
|
||||
let trusted_promise = TrustedPromise::new(promise.clone());
|
||||
let _ = task_source.queue_with_canceller(
|
||||
task!(generate_key: move || {
|
||||
let subtle = this.root();
|
||||
let promise = trusted_promise.root();
|
||||
let key = normalized_algorithm.generate_key(&subtle, key_usages, extractable);
|
||||
let _ = task_source.queue(task!(generate_key: move || {
|
||||
let subtle = this.root();
|
||||
let promise = trusted_promise.root();
|
||||
let key = normalized_algorithm.generate_key(&subtle, key_usages, extractable);
|
||||
|
||||
match key {
|
||||
Ok(key) => promise.resolve_native(&key),
|
||||
Err(e) => promise.reject_error(e),
|
||||
}
|
||||
}),
|
||||
&canceller,
|
||||
);
|
||||
match key {
|
||||
Ok(key) => promise.resolve_native(&key),
|
||||
Err(e) => promise.reject_error(e),
|
||||
}
|
||||
}));
|
||||
|
||||
promise
|
||||
}
|
||||
|
@ -604,11 +573,11 @@ impl SubtleCryptoMethods<crate::DomTypeHolder> for SubtleCrypto {
|
|||
// NOTE: We created the promise earlier, after Step 1.
|
||||
|
||||
// Step 9. Return promise and perform the remaining steps in parallel.
|
||||
let (task_source, canceller) = self.task_source_with_canceller();
|
||||
let task_source = self.global().task_manager().dom_manipulation_task_source();
|
||||
let trusted_promise = TrustedPromise::new(promise.clone());
|
||||
let trusted_base_key = Trusted::new(base_key);
|
||||
let this = Trusted::new(self);
|
||||
let _ = task_source.queue_with_canceller(
|
||||
let _ = task_source.queue(
|
||||
task!(derive_key: move || {
|
||||
// Step 10. If the following steps or referenced procedures say to throw an error, reject promise
|
||||
// with the returned error and then terminate the algorithm.
|
||||
|
@ -674,7 +643,6 @@ impl SubtleCryptoMethods<crate::DomTypeHolder> for SubtleCrypto {
|
|||
// Step 17. Resolve promise with result.
|
||||
promise.resolve_native(&*result);
|
||||
}),
|
||||
&canceller,
|
||||
);
|
||||
|
||||
promise
|
||||
|
@ -709,47 +677,44 @@ impl SubtleCryptoMethods<crate::DomTypeHolder> for SubtleCrypto {
|
|||
// NOTE: We did that in preparation of Step 3.
|
||||
|
||||
// Step 5. Return promise and perform the remaining steps in parallel.
|
||||
let (task_source, canceller) = self.task_source_with_canceller();
|
||||
let task_source = self.global().task_manager().dom_manipulation_task_source();
|
||||
let trusted_promise = TrustedPromise::new(promise.clone());
|
||||
let trusted_base_key = Trusted::new(base_key);
|
||||
|
||||
let _ = task_source.queue_with_canceller(
|
||||
task!(import_key: move || {
|
||||
// Step 6. If the following steps or referenced procedures say to throw an error,
|
||||
// reject promise with the returned error and then terminate the algorithm.
|
||||
let _ = task_source.queue(task!(import_key: move || {
|
||||
// Step 6. If the following steps or referenced procedures say to throw an error,
|
||||
// reject promise with the returned error and then terminate the algorithm.
|
||||
|
||||
// TODO Step 7. If the name member of normalizedAlgorithm is not equal to the name attribute
|
||||
// of the [[algorithm]] internal slot of baseKey then throw an InvalidAccessError.
|
||||
let promise = trusted_promise.root();
|
||||
let base_key = trusted_base_key.root();
|
||||
// TODO Step 7. If the name member of normalizedAlgorithm is not equal to the name attribute
|
||||
// of the [[algorithm]] internal slot of baseKey then throw an InvalidAccessError.
|
||||
let promise = trusted_promise.root();
|
||||
let base_key = trusted_base_key.root();
|
||||
|
||||
// Step 8. If the [[usages]] internal slot of baseKey does not contain an entry that
|
||||
// is "deriveBits", then throw an InvalidAccessError.
|
||||
if !base_key.usages().contains(&KeyUsage::DeriveBits) {
|
||||
promise.reject_error(Error::InvalidAccess);
|
||||
// Step 8. If the [[usages]] internal slot of baseKey does not contain an entry that
|
||||
// is "deriveBits", then throw an InvalidAccessError.
|
||||
if !base_key.usages().contains(&KeyUsage::DeriveBits) {
|
||||
promise.reject_error(Error::InvalidAccess);
|
||||
return;
|
||||
}
|
||||
|
||||
// Step 9. Let result be the result of creating an ArrayBuffer containing the result of performing the
|
||||
// derive bits operation specified by normalizedAlgorithm using baseKey, algorithm and length.
|
||||
let cx = GlobalScope::get_cx();
|
||||
rooted!(in(*cx) let mut array_buffer_ptr = ptr::null_mut::<JSObject>());
|
||||
let result = match normalized_algorithm.derive_bits(&base_key, length) {
|
||||
Ok(derived_bits) => derived_bits,
|
||||
Err(e) => {
|
||||
promise.reject_error(e);
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
// Step 9. Let result be the result of creating an ArrayBuffer containing the result of performing the
|
||||
// derive bits operation specified by normalizedAlgorithm using baseKey, algorithm and length.
|
||||
let cx = GlobalScope::get_cx();
|
||||
rooted!(in(*cx) let mut array_buffer_ptr = ptr::null_mut::<JSObject>());
|
||||
let result = match normalized_algorithm.derive_bits(&base_key, length) {
|
||||
Ok(derived_bits) => derived_bits,
|
||||
Err(e) => {
|
||||
promise.reject_error(e);
|
||||
return;
|
||||
}
|
||||
};
|
||||
create_buffer_source::<ArrayBufferU8>(cx, &result, array_buffer_ptr.handle_mut())
|
||||
.expect("failed to create buffer source for derived bits.");
|
||||
|
||||
create_buffer_source::<ArrayBufferU8>(cx, &result, array_buffer_ptr.handle_mut())
|
||||
.expect("failed to create buffer source for derived bits.");
|
||||
|
||||
// Step 10. Resolve promise with result.
|
||||
promise.resolve_native(&*array_buffer_ptr);
|
||||
}),
|
||||
&canceller,
|
||||
);
|
||||
// Step 10. Resolve promise with result.
|
||||
promise.resolve_native(&*array_buffer_ptr);
|
||||
}));
|
||||
|
||||
promise
|
||||
}
|
||||
|
@ -801,10 +766,10 @@ impl SubtleCryptoMethods<crate::DomTypeHolder> for SubtleCrypto {
|
|||
},
|
||||
};
|
||||
|
||||
let (task_source, canceller) = self.task_source_with_canceller();
|
||||
let task_source = self.global().task_manager().dom_manipulation_task_source();
|
||||
let this = Trusted::new(self);
|
||||
let trusted_promise = TrustedPromise::new(promise.clone());
|
||||
let _ = task_source.queue_with_canceller(
|
||||
let _ = task_source.queue(
|
||||
task!(import_key: move || {
|
||||
let subtle = this.root();
|
||||
let promise = trusted_promise.root();
|
||||
|
@ -814,7 +779,6 @@ impl SubtleCryptoMethods<crate::DomTypeHolder> for SubtleCrypto {
|
|||
Err(e) => promise.reject_error(e),
|
||||
};
|
||||
}),
|
||||
&canceller,
|
||||
);
|
||||
|
||||
promise
|
||||
|
@ -830,11 +794,11 @@ impl SubtleCryptoMethods<crate::DomTypeHolder> for SubtleCrypto {
|
|||
) -> Rc<Promise> {
|
||||
let promise = Promise::new_in_current_realm(comp, can_gc);
|
||||
|
||||
let (task_source, canceller) = self.task_source_with_canceller();
|
||||
let task_source = self.global().task_manager().dom_manipulation_task_source();
|
||||
let this = Trusted::new(self);
|
||||
let trusted_key = Trusted::new(key);
|
||||
let trusted_promise = TrustedPromise::new(promise.clone());
|
||||
let _ = task_source.queue_with_canceller(
|
||||
let _ = task_source.queue(
|
||||
task!(export_key: move || {
|
||||
let subtle = this.root();
|
||||
let promise = trusted_promise.root();
|
||||
|
@ -872,7 +836,6 @@ impl SubtleCryptoMethods<crate::DomTypeHolder> for SubtleCrypto {
|
|||
Err(e) => promise.reject_error(e),
|
||||
}
|
||||
}),
|
||||
&canceller,
|
||||
);
|
||||
|
||||
promise
|
||||
|
@ -898,12 +861,12 @@ impl SubtleCryptoMethods<crate::DomTypeHolder> for SubtleCrypto {
|
|||
},
|
||||
};
|
||||
|
||||
let (task_source, canceller) = self.task_source_with_canceller();
|
||||
let task_source = self.global().task_manager().dom_manipulation_task_source();
|
||||
let this = Trusted::new(self);
|
||||
let trusted_key = Trusted::new(key);
|
||||
let trusted_wrapping_key = Trusted::new(wrapping_key);
|
||||
let trusted_promise = TrustedPromise::new(promise.clone());
|
||||
let _ = task_source.queue_with_canceller(
|
||||
let _ = task_source.queue(
|
||||
task!(wrap_key: move || {
|
||||
let subtle = this.root();
|
||||
let promise = trusted_promise.root();
|
||||
|
@ -996,7 +959,6 @@ impl SubtleCryptoMethods<crate::DomTypeHolder> for SubtleCrypto {
|
|||
Err(e) => promise.reject_error(e),
|
||||
}
|
||||
}),
|
||||
&canceller
|
||||
);
|
||||
|
||||
promise
|
||||
|
@ -1037,11 +999,11 @@ impl SubtleCryptoMethods<crate::DomTypeHolder> for SubtleCrypto {
|
|||
},
|
||||
};
|
||||
|
||||
let (task_source, canceller) = self.task_source_with_canceller();
|
||||
let task_source = self.global().task_manager().dom_manipulation_task_source();
|
||||
let this = Trusted::new(self);
|
||||
let trusted_key = Trusted::new(unwrapping_key);
|
||||
let trusted_promise = TrustedPromise::new(promise.clone());
|
||||
let _ = task_source.queue_with_canceller(
|
||||
let _ = task_source.queue(
|
||||
task!(unwrap_key: move || {
|
||||
let subtle = this.root();
|
||||
let promise = trusted_promise.root();
|
||||
|
@ -1103,7 +1065,6 @@ impl SubtleCryptoMethods<crate::DomTypeHolder> for SubtleCrypto {
|
|||
Err(e) => promise.reject_error(e),
|
||||
}
|
||||
}),
|
||||
&canceller
|
||||
);
|
||||
|
||||
promise
|
||||
|
|
|
@ -300,8 +300,8 @@ impl<'a, E: TextControlElement> TextControlSelection<'a, E> {
|
|||
|
||||
// Step 6
|
||||
if textinput.selection_state() != original_selection_state {
|
||||
let window = self.element.owner_window();
|
||||
window
|
||||
self.element
|
||||
.owner_window()
|
||||
.task_manager()
|
||||
.user_interaction_task_source()
|
||||
.queue_event(
|
||||
|
@ -309,7 +309,6 @@ impl<'a, E: TextControlElement> TextControlSelection<'a, E> {
|
|||
atom!("select"),
|
||||
EventBubbles::Bubbles,
|
||||
EventCancelable::NotCancelable,
|
||||
&window,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -63,38 +63,30 @@ impl TextTrackList {
|
|||
self.dom_tracks.borrow_mut().push(Dom::from_ref(track));
|
||||
|
||||
let this = Trusted::new(self);
|
||||
let (source, canceller) = &self
|
||||
.global()
|
||||
.as_window()
|
||||
.task_manager()
|
||||
.media_element_task_source_with_canceller();
|
||||
let task_source = self.global().task_manager().media_element_task_source();
|
||||
|
||||
let idx = match self.find(track) {
|
||||
Some(t) => t,
|
||||
None => return,
|
||||
let Some(idx) = self.find(track) else {
|
||||
return;
|
||||
};
|
||||
|
||||
let _ = source.queue_with_canceller(
|
||||
task!(track_event_queue: move || {
|
||||
let this = this.root();
|
||||
let _ = task_source.queue(task!(track_event_queue: move || {
|
||||
let this = this.root();
|
||||
|
||||
if let Some(track) = this.item(idx) {
|
||||
let event = TrackEvent::new(
|
||||
&this.global(),
|
||||
atom!("addtrack"),
|
||||
false,
|
||||
false,
|
||||
&Some(VideoTrackOrAudioTrackOrTextTrack::TextTrack(
|
||||
DomRoot::from_ref(&track)
|
||||
)),
|
||||
CanGc::note()
|
||||
);
|
||||
if let Some(track) = this.item(idx) {
|
||||
let event = TrackEvent::new(
|
||||
&this.global(),
|
||||
atom!("addtrack"),
|
||||
false,
|
||||
false,
|
||||
&Some(VideoTrackOrAudioTrackOrTextTrack::TextTrack(
|
||||
DomRoot::from_ref(&track)
|
||||
)),
|
||||
CanGc::note()
|
||||
);
|
||||
|
||||
event.upcast::<Event>().fire(this.upcast::<EventTarget>(), CanGc::note());
|
||||
}
|
||||
}),
|
||||
canceller,
|
||||
);
|
||||
event.upcast::<Event>().fire(this.upcast::<EventTarget>(), CanGc::note());
|
||||
}
|
||||
}));
|
||||
track.add_track_list(self);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -81,12 +81,8 @@ impl VideoTrackList {
|
|||
return;
|
||||
}
|
||||
|
||||
let global = &self.global();
|
||||
let this = Trusted::new(self);
|
||||
let (source, canceller) = global
|
||||
.as_window()
|
||||
.task_manager()
|
||||
.media_element_task_source_with_canceller();
|
||||
let task_source = self.global().task_manager().media_element_task_source();
|
||||
|
||||
if let Some(current) = self.selected_index() {
|
||||
self.tracks.borrow()[current].set_selected(false);
|
||||
|
@ -97,13 +93,10 @@ impl VideoTrackList {
|
|||
media_element.set_video_track(idx, value);
|
||||
}
|
||||
|
||||
let _ = source.queue_with_canceller(
|
||||
task!(media_track_change: move || {
|
||||
let this = this.root();
|
||||
this.upcast::<EventTarget>().fire_event(atom!("change"), CanGc::note());
|
||||
}),
|
||||
&canceller,
|
||||
);
|
||||
let _ = task_source.queue(task!(media_track_change: move || {
|
||||
let this = this.root();
|
||||
this.upcast::<EventTarget>().fire_event(atom!("change"), CanGc::note());
|
||||
}));
|
||||
}
|
||||
|
||||
pub fn add(&self, track: &VideoTrack) {
|
||||
|
|
|
@ -171,12 +171,10 @@ impl WebGLQuery {
|
|||
this.update_results(&context);
|
||||
});
|
||||
|
||||
let global = self.global();
|
||||
global
|
||||
.as_window()
|
||||
self.global()
|
||||
.task_manager()
|
||||
.dom_manipulation_task_source()
|
||||
.queue(task, global.upcast())
|
||||
.queue(task)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
|
|
|
@ -59,7 +59,6 @@ impl WebGLSync {
|
|||
) -> Option<u32> {
|
||||
match self.client_wait_status.get() {
|
||||
Some(constants::TIMEOUT_EXPIRED) | Some(constants::WAIT_FAILED) | None => {
|
||||
let global = self.global();
|
||||
let this = Trusted::new(self);
|
||||
let context = Trusted::new(context);
|
||||
let task = task!(request_client_wait_status: move || {
|
||||
|
@ -74,11 +73,10 @@ impl WebGLSync {
|
|||
));
|
||||
this.client_wait_status.set(Some(receiver.recv().unwrap()));
|
||||
});
|
||||
global
|
||||
.as_window()
|
||||
self.global()
|
||||
.task_manager()
|
||||
.dom_manipulation_task_source()
|
||||
.queue(task, global.upcast())
|
||||
.queue(task)
|
||||
.unwrap();
|
||||
},
|
||||
_ => {},
|
||||
|
@ -101,7 +99,6 @@ impl WebGLSync {
|
|||
pub fn get_sync_status(&self, pname: u32, context: &WebGLRenderingContext) -> Option<u32> {
|
||||
match self.sync_status.get() {
|
||||
Some(constants::UNSIGNALED) | None => {
|
||||
let global = self.global();
|
||||
let this = Trusted::new(self);
|
||||
let context = Trusted::new(context);
|
||||
let task = task!(request_sync_status: move || {
|
||||
|
@ -111,11 +108,10 @@ impl WebGLSync {
|
|||
context.send_command(WebGLCommand::GetSyncParameter(this.sync_id, pname, sender));
|
||||
this.sync_status.set(Some(receiver.recv().unwrap()));
|
||||
});
|
||||
global
|
||||
.as_window()
|
||||
self.global()
|
||||
.task_manager()
|
||||
.dom_manipulation_task_source()
|
||||
.queue(task, global.upcast())
|
||||
.queue(task)
|
||||
.unwrap();
|
||||
},
|
||||
_ => {},
|
||||
|
|
|
@ -25,7 +25,6 @@ use crate::dom::promise::Promise;
|
|||
use crate::dom::webgpu::gpuadapter::GPUAdapter;
|
||||
use crate::realms::InRealm;
|
||||
use crate::script_runtime::CanGc;
|
||||
use crate::task_source::TaskSourceName;
|
||||
|
||||
#[dom_struct]
|
||||
#[allow(clippy::upper_case_acronyms)]
|
||||
|
@ -73,9 +72,6 @@ pub fn response_async<T: AsyncWGPUListener + DomObject + 'static>(
|
|||
.global()
|
||||
.task_manager()
|
||||
.dom_manipulation_task_source();
|
||||
let canceller = receiver
|
||||
.global()
|
||||
.task_canceller(TaskSourceName::DOMManipulation);
|
||||
let mut trusted: Option<TrustedPromise> = Some(TrustedPromise::new(promise.clone()));
|
||||
let trusted_receiver = Trusted::new(receiver);
|
||||
ROUTER.add_typed_route(
|
||||
|
@ -92,12 +88,9 @@ pub fn response_async<T: AsyncWGPUListener + DomObject + 'static>(
|
|||
trusted,
|
||||
receiver: trusted_receiver.clone(),
|
||||
};
|
||||
let result = task_source.queue_with_canceller(
|
||||
task!(process_webgpu_task: move|| {
|
||||
context.response(message.unwrap(), CanGc::note());
|
||||
}),
|
||||
&canceller,
|
||||
);
|
||||
let result = task_source.queue(task!(process_webgpu_task: move|| {
|
||||
context.response(message.unwrap(), CanGc::note());
|
||||
}));
|
||||
if let Err(err) = result {
|
||||
error!("Failed to queue GPU listener-task: {:?}", err);
|
||||
}
|
||||
|
|
|
@ -39,8 +39,8 @@ use crate::dom::eventtarget::EventTarget;
|
|||
use crate::dom::globalscope::GlobalScope;
|
||||
use crate::dom::messageevent::MessageEvent;
|
||||
use crate::script_runtime::CanGc;
|
||||
use crate::task::{TaskCanceller, TaskOnce};
|
||||
use crate::task_source::{TaskSource, TaskSourceName};
|
||||
use crate::task::TaskOnce;
|
||||
use crate::task_source::TaskSource;
|
||||
|
||||
#[derive(Clone, Copy, Debug, JSTraceable, MallocSizeOf, PartialEq)]
|
||||
enum WebSocketRequestState {
|
||||
|
@ -71,7 +71,6 @@ mod close_code {
|
|||
fn close_the_websocket_connection(
|
||||
address: Trusted<WebSocket>,
|
||||
task_source: &TaskSource,
|
||||
canceller: &TaskCanceller,
|
||||
code: Option<u16>,
|
||||
reason: String,
|
||||
) {
|
||||
|
@ -81,21 +80,17 @@ fn close_the_websocket_connection(
|
|||
code,
|
||||
reason: Some(reason),
|
||||
};
|
||||
let _ = task_source.queue_with_canceller(close_task, canceller);
|
||||
let _ = task_source.queue(close_task);
|
||||
}
|
||||
|
||||
fn fail_the_websocket_connection(
|
||||
address: Trusted<WebSocket>,
|
||||
task_source: &TaskSource,
|
||||
canceller: &TaskCanceller,
|
||||
) {
|
||||
fn fail_the_websocket_connection(address: Trusted<WebSocket>, task_source: &TaskSource) {
|
||||
let close_task = CloseTask {
|
||||
address,
|
||||
failed: true,
|
||||
code: Some(close_code::ABNORMAL),
|
||||
reason: None,
|
||||
};
|
||||
let _ = task_source.queue_with_canceller(close_task, canceller);
|
||||
let _ = task_source.queue(close_task);
|
||||
}
|
||||
|
||||
#[dom_struct]
|
||||
|
@ -276,7 +271,6 @@ impl WebSocketMethods<crate::DomTypeHolder> for WebSocket {
|
|||
.send(CoreResourceMsg::Fetch(request, channels));
|
||||
|
||||
let task_source = global.task_manager().websocket_task_source();
|
||||
let canceller = global.task_canceller(TaskSourceName::WebSocket);
|
||||
ROUTER.add_typed_route(
|
||||
dom_event_receiver.to_ipc_receiver(),
|
||||
Box::new(move |message| match message.unwrap() {
|
||||
|
@ -285,26 +279,20 @@ impl WebSocketMethods<crate::DomTypeHolder> for WebSocket {
|
|||
address: address.clone(),
|
||||
protocol_in_use,
|
||||
};
|
||||
let _ = task_source.queue_with_canceller(open_thread, &canceller);
|
||||
let _ = task_source.queue(open_thread);
|
||||
},
|
||||
WebSocketNetworkEvent::MessageReceived(message) => {
|
||||
let message_thread = MessageReceivedTask {
|
||||
address: address.clone(),
|
||||
message,
|
||||
};
|
||||
let _ = task_source.queue_with_canceller(message_thread, &canceller);
|
||||
let _ = task_source.queue(message_thread);
|
||||
},
|
||||
WebSocketNetworkEvent::Fail => {
|
||||
fail_the_websocket_connection(address.clone(), &task_source, &canceller);
|
||||
fail_the_websocket_connection(address.clone(), &task_source);
|
||||
},
|
||||
WebSocketNetworkEvent::Close(code, reason) => {
|
||||
close_the_websocket_connection(
|
||||
address.clone(),
|
||||
&task_source,
|
||||
&canceller,
|
||||
code,
|
||||
reason,
|
||||
);
|
||||
close_the_websocket_connection(address.clone(), &task_source, code, reason);
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
@ -439,15 +427,8 @@ impl WebSocketMethods<crate::DomTypeHolder> for WebSocket {
|
|||
self.ready_state.set(WebSocketRequestState::Closing);
|
||||
|
||||
let address = Trusted::new(self);
|
||||
// TODO: use a dedicated task source,
|
||||
// https://html.spec.whatwg.org/multipage/#websocket-task-source
|
||||
// When making the switch, also update the task_canceller call.
|
||||
let task_source = self.global().task_manager().websocket_task_source();
|
||||
fail_the_websocket_connection(
|
||||
address,
|
||||
&task_source,
|
||||
&self.global().task_canceller(TaskSourceName::WebSocket),
|
||||
);
|
||||
fail_the_websocket_connection(address, &task_source);
|
||||
},
|
||||
WebSocketRequestState::Open => {
|
||||
self.ready_state.set(WebSocketRequestState::Closing);
|
||||
|
|
|
@ -306,10 +306,7 @@ impl FakeXRDeviceMethods<crate::DomTypeHolder> for FakeXRDevice {
|
|||
let global = self.global();
|
||||
let p = Promise::new(&global, can_gc);
|
||||
let mut trusted = Some(TrustedPromise::new(p.clone()));
|
||||
let (task_source, canceller) = global
|
||||
.as_window()
|
||||
.task_manager()
|
||||
.dom_manipulation_task_source_with_canceller();
|
||||
let task_source = global.task_manager().dom_manipulation_task_source();
|
||||
let (sender, receiver) = ipc::channel(global.time_profiler_chan().clone()).unwrap();
|
||||
|
||||
ROUTER.add_typed_route(
|
||||
|
@ -318,7 +315,7 @@ impl FakeXRDeviceMethods<crate::DomTypeHolder> for FakeXRDevice {
|
|||
let trusted = trusted
|
||||
.take()
|
||||
.expect("disconnect callback called multiple times");
|
||||
let _ = task_source.queue_with_canceller(trusted.resolve_task(()), &canceller);
|
||||
let _ = task_source.queue(trusted.resolve_task(()));
|
||||
}),
|
||||
);
|
||||
self.disconnect(sender);
|
||||
|
|
|
@ -201,22 +201,16 @@ impl XRSession {
|
|||
fn setup_raf_loop(&self, frame_receiver: IpcReceiver<Frame>) {
|
||||
let this = Trusted::new(self);
|
||||
let global = self.global();
|
||||
let window = global.as_window();
|
||||
let (task_source, canceller) = window
|
||||
.task_manager()
|
||||
.dom_manipulation_task_source_with_canceller();
|
||||
let task_source = global.task_manager().dom_manipulation_task_source();
|
||||
ROUTER.add_typed_route(
|
||||
frame_receiver,
|
||||
Box::new(move |message| {
|
||||
let frame: Frame = message.unwrap();
|
||||
let time = CrossProcessInstant::now();
|
||||
let this = this.clone();
|
||||
let _ = task_source.queue_with_canceller(
|
||||
task!(xr_raf_callback: move || {
|
||||
this.root().raf_callback(frame, time);
|
||||
}),
|
||||
&canceller,
|
||||
);
|
||||
let _ = task_source.queue(task!(xr_raf_callback: move || {
|
||||
this.root().raf_callback(frame, time);
|
||||
}));
|
||||
}),
|
||||
);
|
||||
|
||||
|
@ -230,22 +224,16 @@ impl XRSession {
|
|||
fn attach_event_handler(&self) {
|
||||
let this = Trusted::new(self);
|
||||
let global = self.global();
|
||||
let window = global.as_window();
|
||||
let (task_source, canceller) = window
|
||||
.task_manager()
|
||||
.dom_manipulation_task_source_with_canceller();
|
||||
let task_source = global.task_manager().dom_manipulation_task_source();
|
||||
let (sender, receiver) = ipc::channel(global.time_profiler_chan().clone()).unwrap();
|
||||
|
||||
ROUTER.add_typed_route(
|
||||
receiver.to_ipc_receiver(),
|
||||
Box::new(move |message| {
|
||||
let this = this.clone();
|
||||
let _ = task_source.queue_with_canceller(
|
||||
task!(xr_event_callback: move || {
|
||||
this.root().event_callback(message.unwrap(), CanGc::note());
|
||||
}),
|
||||
&canceller,
|
||||
);
|
||||
let _ = task_source.queue(task!(xr_event_callback: move || {
|
||||
this.root().event_callback(message.unwrap(), CanGc::note());
|
||||
}));
|
||||
}),
|
||||
);
|
||||
|
||||
|
@ -266,21 +254,14 @@ impl XRSession {
|
|||
return;
|
||||
}
|
||||
|
||||
let global = self.global();
|
||||
let window = global.as_window();
|
||||
let (task_source, canceller) = window
|
||||
.task_manager()
|
||||
.dom_manipulation_task_source_with_canceller();
|
||||
let task_source = self.global().task_manager().dom_manipulation_task_source();
|
||||
let this = Trusted::new(self);
|
||||
// Queue a task so that it runs after resolve()'s microtasks complete
|
||||
// so that content has a chance to attach a listener for inputsourceschange
|
||||
let _ = task_source.queue_with_canceller(
|
||||
task!(session_initial_inputs: move || {
|
||||
let this = this.root();
|
||||
this.input_sources.add_input_sources(&this, &initial_inputs, CanGc::note());
|
||||
}),
|
||||
&canceller,
|
||||
);
|
||||
let _ = task_source.queue(task!(session_initial_inputs: move || {
|
||||
let this = this.root();
|
||||
this.input_sources.add_input_sources(&this, &initial_inputs, CanGc::note());
|
||||
}));
|
||||
}
|
||||
|
||||
fn event_callback(&self, event: XREvent, can_gc: CanGc) {
|
||||
|
@ -1055,26 +1036,20 @@ impl XRSessionMethods<crate::DomTypeHolder> for XRSession {
|
|||
|
||||
let this = Trusted::new(self);
|
||||
let global = self.global();
|
||||
let window = global.as_window();
|
||||
let (task_source, canceller) = window
|
||||
.task_manager()
|
||||
.dom_manipulation_task_source_with_canceller();
|
||||
let task_source = global.task_manager().dom_manipulation_task_source();
|
||||
let (sender, receiver) = ipc::channel(global.time_profiler_chan().clone()).unwrap();
|
||||
|
||||
ROUTER.add_typed_route(
|
||||
receiver.to_ipc_receiver(),
|
||||
Box::new(move |message| {
|
||||
let this = this.clone();
|
||||
let _ = task_source.queue_with_canceller(
|
||||
task!(update_session_framerate: move || {
|
||||
let session = this.root();
|
||||
session.apply_nominal_framerate(message.unwrap(), CanGc::note());
|
||||
if let Some(promise) = session.update_framerate_promise.borrow_mut().take() {
|
||||
promise.resolve_native(&());
|
||||
};
|
||||
}),
|
||||
&canceller,
|
||||
);
|
||||
let _ = task_source.queue(task!(update_session_framerate: move || {
|
||||
let session = this.root();
|
||||
session.apply_nominal_framerate(message.unwrap(), CanGc::note());
|
||||
if let Some(promise) = session.update_framerate_promise.borrow_mut().take() {
|
||||
promise.resolve_native(&());
|
||||
};
|
||||
}));
|
||||
}),
|
||||
);
|
||||
|
||||
|
|
|
@ -118,10 +118,7 @@ impl XRSystemMethods<crate::DomTypeHolder> for XRSystem {
|
|||
let promise = Promise::new(&self.global(), can_gc);
|
||||
let mut trusted = Some(TrustedPromise::new(promise.clone()));
|
||||
let global = self.global();
|
||||
let window = global.as_window();
|
||||
let (task_source, canceller) = window
|
||||
.task_manager()
|
||||
.dom_manipulation_task_source_with_canceller();
|
||||
let task_source = global.task_manager().dom_manipulation_task_source();
|
||||
let (sender, receiver) = ipc::channel(global.time_profiler_chan().clone()).unwrap();
|
||||
ROUTER.add_typed_route(
|
||||
receiver.to_ipc_receiver(),
|
||||
|
@ -140,15 +137,13 @@ impl XRSystemMethods<crate::DomTypeHolder> for XRSystem {
|
|||
return;
|
||||
};
|
||||
if let Ok(()) = message {
|
||||
let _ =
|
||||
task_source.queue_with_canceller(trusted.resolve_task(true), &canceller);
|
||||
let _ = task_source.queue(trusted.resolve_task(true));
|
||||
} else {
|
||||
let _ =
|
||||
task_source.queue_with_canceller(trusted.resolve_task(false), &canceller);
|
||||
let _ = task_source.queue(trusted.resolve_task(false));
|
||||
};
|
||||
}),
|
||||
);
|
||||
if let Some(mut r) = window.webxr_registry() {
|
||||
if let Some(mut r) = global.as_window().webxr_registry() {
|
||||
r.supports_session(mode.convert(), sender);
|
||||
}
|
||||
|
||||
|
@ -239,9 +234,7 @@ impl XRSystemMethods<crate::DomTypeHolder> for XRSystem {
|
|||
|
||||
let mut trusted = Some(TrustedPromise::new(promise.clone()));
|
||||
let this = Trusted::new(self);
|
||||
let (task_source, canceller) = window
|
||||
.task_manager()
|
||||
.dom_manipulation_task_source_with_canceller();
|
||||
let task_source = global.task_manager().dom_manipulation_task_source();
|
||||
let (sender, receiver) = ipc::channel(global.time_profiler_chan().clone()).unwrap();
|
||||
let (frame_sender, frame_receiver) = ipc_crate::channel().unwrap();
|
||||
let mut frame_receiver = Some(frame_receiver);
|
||||
|
@ -258,12 +251,9 @@ impl XRSystemMethods<crate::DomTypeHolder> for XRSystem {
|
|||
error!("requestSession callback given incorrect payload");
|
||||
return;
|
||||
};
|
||||
let _ = task_source.queue_with_canceller(
|
||||
task!(request_session: move || {
|
||||
this.root().session_obtained(message, trusted.root(), mode, frame_receiver);
|
||||
}),
|
||||
&canceller,
|
||||
);
|
||||
let _ = task_source.queue(task!(request_session: move || {
|
||||
this.root().session_obtained(message, trusted.root(), mode, frame_receiver);
|
||||
}));
|
||||
}),
|
||||
);
|
||||
if let Some(mut r) = window.webxr_registry() {
|
||||
|
@ -314,9 +304,7 @@ impl XRSystem {
|
|||
// https://github.com/immersive-web/navigation/issues/10
|
||||
pub fn dispatch_sessionavailable(&self) {
|
||||
let xr = Trusted::new(self);
|
||||
let global = self.global();
|
||||
let window = global.as_window();
|
||||
window
|
||||
self.global()
|
||||
.task_manager()
|
||||
.dom_manipulation_task_source()
|
||||
.queue(
|
||||
|
@ -327,8 +315,7 @@ impl XRSystem {
|
|||
ScriptThread::set_user_interacting(true);
|
||||
xr.upcast::<EventTarget>().fire_bubbling_event(atom!("sessionavailable"), CanGc::note());
|
||||
ScriptThread::set_user_interacting(interacting);
|
||||
}),
|
||||
window.upcast(),
|
||||
})
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
|
|
|
@ -147,13 +147,10 @@ impl XRTestMethods<crate::DomTypeHolder> for XRTest {
|
|||
};
|
||||
|
||||
let global = self.global();
|
||||
let window = global.as_window();
|
||||
let this = Trusted::new(self);
|
||||
let mut trusted = Some(TrustedPromise::new(p.clone()));
|
||||
|
||||
let (task_source, canceller) = window
|
||||
.task_manager()
|
||||
.dom_manipulation_task_source_with_canceller();
|
||||
let task_source = global.task_manager().dom_manipulation_task_source();
|
||||
let (sender, receiver) = ipc::channel(global.time_profiler_chan().clone()).unwrap();
|
||||
|
||||
ROUTER.add_typed_route(
|
||||
|
@ -166,15 +163,12 @@ impl XRTestMethods<crate::DomTypeHolder> for XRTest {
|
|||
let message =
|
||||
message.expect("SimulateDeviceConnection callback given incorrect payload");
|
||||
|
||||
let _ = task_source.queue_with_canceller(
|
||||
task!(request_session: move || {
|
||||
this.root().device_obtained(message, trusted);
|
||||
}),
|
||||
&canceller,
|
||||
);
|
||||
let _ = task_source.queue(task!(request_session: move || {
|
||||
this.root().device_obtained(message, trusted);
|
||||
}));
|
||||
}),
|
||||
);
|
||||
if let Some(mut r) = window.webxr_registry() {
|
||||
if let Some(mut r) = global.as_window().webxr_registry() {
|
||||
r.simulate_device_connection(init, sender);
|
||||
}
|
||||
|
||||
|
@ -206,10 +200,7 @@ impl XRTestMethods<crate::DomTypeHolder> for XRTest {
|
|||
devices.clear();
|
||||
|
||||
let mut trusted = Some(TrustedPromise::new(p.clone()));
|
||||
let (task_source, canceller) = global
|
||||
.as_window()
|
||||
.task_manager()
|
||||
.dom_manipulation_task_source_with_canceller();
|
||||
let task_source = global.task_manager().dom_manipulation_task_source();
|
||||
|
||||
ROUTER.add_typed_route(
|
||||
receiver.to_ipc_receiver(),
|
||||
|
@ -219,8 +210,7 @@ impl XRTestMethods<crate::DomTypeHolder> for XRTest {
|
|||
let trusted = trusted
|
||||
.take()
|
||||
.expect("DisconnectAllDevices disconnected more devices than expected");
|
||||
let _ =
|
||||
task_source.queue_with_canceller(trusted.resolve_task(()), &canceller);
|
||||
let _ = task_source.queue(trusted.resolve_task(()));
|
||||
}
|
||||
}),
|
||||
);
|
||||
|
|
|
@ -11,7 +11,6 @@ use std::default::Default;
|
|||
use std::io::{stderr, stdout, Write};
|
||||
use std::ptr::NonNull;
|
||||
use std::rc::Rc;
|
||||
use std::sync::atomic::Ordering;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::time::{Duration, Instant};
|
||||
|
||||
|
@ -153,12 +152,9 @@ use crate::messaging::{
|
|||
};
|
||||
use crate::microtask::MicrotaskQueue;
|
||||
use crate::realms::{enter_realm, InRealm};
|
||||
use crate::script_runtime::{
|
||||
CanGc, CommonScriptMsg, JSContext, Runtime, ScriptChan, ScriptPort, ScriptThreadEventCategory,
|
||||
};
|
||||
use crate::script_runtime::{CanGc, JSContext, Runtime, ScriptChan, ScriptPort};
|
||||
use crate::script_thread::ScriptThread;
|
||||
use crate::task_manager::TaskManager;
|
||||
use crate::task_source::TaskSourceName;
|
||||
use crate::timers::{IsInterval, TimerCallback};
|
||||
use crate::unminify::unminified_path;
|
||||
use crate::webdriver_handlers::jsval_to_webdriver;
|
||||
|
@ -208,7 +204,6 @@ pub struct Window {
|
|||
globalscope: GlobalScope,
|
||||
#[ignore_malloc_size_of = "trait objects are hard"]
|
||||
script_chan: MainThreadScriptChan,
|
||||
task_manager: TaskManager,
|
||||
#[no_trace]
|
||||
#[ignore_malloc_size_of = "TODO: Add MallocSizeOf support to layout"]
|
||||
layout: RefCell<Box<dyn Layout>>,
|
||||
|
@ -383,10 +378,6 @@ pub struct Window {
|
|||
}
|
||||
|
||||
impl Window {
|
||||
pub fn task_manager(&self) -> &TaskManager {
|
||||
&self.task_manager
|
||||
}
|
||||
|
||||
pub fn layout(&self) -> Ref<Box<dyn Layout>> {
|
||||
self.layout.borrow()
|
||||
}
|
||||
|
@ -411,7 +402,8 @@ impl Window {
|
|||
*self.js_runtime.borrow_for_script_deallocation() = None;
|
||||
self.window_proxy.set(None);
|
||||
self.current_state.set(WindowState::Zombie);
|
||||
self.ignore_all_tasks();
|
||||
self.task_manager()
|
||||
.cancel_all_tasks_and_ignore_future_tasks();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -426,16 +418,8 @@ impl Window {
|
|||
// Step 4 of https://html.spec.whatwg.org/multipage/#discard-a-document
|
||||
// Other steps performed when the `PipelineExit` message
|
||||
// is handled by the ScriptThread.
|
||||
self.ignore_all_tasks();
|
||||
}
|
||||
|
||||
/// Cancel all current, and ignore all subsequently queued, tasks.
|
||||
pub fn ignore_all_tasks(&self) {
|
||||
let mut ignore_flags = self.task_manager.task_cancellers.borrow_mut();
|
||||
for task_source_name in TaskSourceName::all() {
|
||||
let flag = ignore_flags.entry(*task_source_name).or_default();
|
||||
flag.store(true, Ordering::SeqCst);
|
||||
}
|
||||
self.task_manager()
|
||||
.cancel_all_tasks_and_ignore_future_tasks();
|
||||
}
|
||||
|
||||
/// Get a sender to the time profiler thread.
|
||||
|
@ -572,6 +556,10 @@ impl Window {
|
|||
pub fn dispatch_event_with_target_override(&self, event: &Event, can_gc: CanGc) -> EventStatus {
|
||||
event.dispatch(self.upcast(), true, can_gc)
|
||||
}
|
||||
|
||||
pub(crate) fn task_manager(&self) -> &TaskManager {
|
||||
self.upcast::<GlobalScope>().task_manager()
|
||||
}
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#atob
|
||||
|
@ -825,9 +813,10 @@ impl WindowMethods<crate::DomTypeHolder> for Window {
|
|||
window.send_to_constellation(ScriptMsg::DiscardTopLevelBrowsingContext);
|
||||
}
|
||||
});
|
||||
self.task_manager()
|
||||
self.global()
|
||||
.task_manager()
|
||||
.dom_manipulation_task_source()
|
||||
.queue(task, self.upcast::<GlobalScope>())
|
||||
.queue(task)
|
||||
.expect("Queuing window_close_browsing_context task to work");
|
||||
}
|
||||
}
|
||||
|
@ -1657,29 +1646,6 @@ impl Window {
|
|||
self.document.get().is_some()
|
||||
}
|
||||
|
||||
/// Cancels all the tasks associated with that window.
|
||||
///
|
||||
/// This sets the current `task_manager.task_cancellers` sentinel value to
|
||||
/// `true` and replaces it with a brand new one for future tasks.
|
||||
pub fn cancel_all_tasks(&self) {
|
||||
let mut ignore_flags = self.task_manager.task_cancellers.borrow_mut();
|
||||
for task_source_name in TaskSourceName::all() {
|
||||
let flag = ignore_flags.entry(*task_source_name).or_default();
|
||||
let cancelled = std::mem::take(&mut *flag);
|
||||
cancelled.store(true, Ordering::SeqCst);
|
||||
}
|
||||
}
|
||||
|
||||
/// Cancels all the tasks from a given task source.
|
||||
/// This sets the current sentinel value to
|
||||
/// `true` and replaces it with a brand new one for future tasks.
|
||||
pub fn cancel_all_tasks_from_source(&self, task_source_name: TaskSourceName) {
|
||||
let mut ignore_flags = self.task_manager.task_cancellers.borrow_mut();
|
||||
let flag = ignore_flags.entry(task_source_name).or_default();
|
||||
let cancelled = std::mem::take(&mut *flag);
|
||||
cancelled.store(true, Ordering::SeqCst);
|
||||
}
|
||||
|
||||
pub fn clear_js_runtime(&self) {
|
||||
self.upcast::<GlobalScope>()
|
||||
.remove_web_messaging_and_dedicated_workers_infra();
|
||||
|
@ -1721,7 +1687,8 @@ impl Window {
|
|||
if let Some(performance) = self.performance.get() {
|
||||
performance.clear_and_disable_performance_entry_buffer();
|
||||
}
|
||||
self.ignore_all_tasks();
|
||||
self.task_manager()
|
||||
.cancel_all_tasks_and_ignore_future_tasks();
|
||||
}
|
||||
|
||||
/// <https://drafts.csswg.org/cssom-view/#dom-window-scroll>
|
||||
|
@ -2368,17 +2335,10 @@ impl Window {
|
|||
CanGc::note());
|
||||
event.upcast::<Event>().fire(this.upcast::<EventTarget>(), CanGc::note());
|
||||
});
|
||||
// FIXME(nox): Why are errors silenced here?
|
||||
let _ = self.script_chan.send(CommonScriptMsg::Task(
|
||||
ScriptThreadEventCategory::DomEvent,
|
||||
Box::new(
|
||||
self.task_manager
|
||||
.task_canceller(TaskSourceName::DOMManipulation)
|
||||
.wrap_task(task),
|
||||
),
|
||||
Some(self.pipeline_id()),
|
||||
TaskSourceName::DOMManipulation,
|
||||
));
|
||||
let _ = self
|
||||
.task_manager()
|
||||
.dom_manipulation_task_source()
|
||||
.queue(task);
|
||||
doc.set_url(load_data.url.clone());
|
||||
return;
|
||||
}
|
||||
|
@ -2715,7 +2675,6 @@ impl Window {
|
|||
pub(crate) fn new(
|
||||
runtime: Rc<Runtime>,
|
||||
script_chan: MainThreadScriptChan,
|
||||
task_manager: TaskManager,
|
||||
layout: Box<dyn Layout>,
|
||||
image_cache_chan: Sender<ImageCacheMsg>,
|
||||
image_cache: Arc<dyn ImageCache>,
|
||||
|
@ -2726,7 +2685,7 @@ impl Window {
|
|||
devtools_chan: Option<IpcSender<ScriptToDevtoolsControlMsg>>,
|
||||
constellation_chan: ScriptToConstellationChan,
|
||||
control_chan: IpcSender<ConstellationControlMsg>,
|
||||
pipelineid: PipelineId,
|
||||
pipeline_id: PipelineId,
|
||||
parent_info: Option<PipelineId>,
|
||||
window_size: WindowSizeData,
|
||||
origin: MutableOrigin,
|
||||
|
@ -2751,7 +2710,7 @@ impl Window {
|
|||
inherited_secure_context: Option<bool>,
|
||||
) -> DomRoot<Self> {
|
||||
let error_reporter = CSSErrorReporter {
|
||||
pipelineid,
|
||||
pipelineid: pipeline_id,
|
||||
script_chan: Arc::new(Mutex::new(control_chan)),
|
||||
};
|
||||
|
||||
|
@ -2762,7 +2721,7 @@ impl Window {
|
|||
|
||||
let win = Box::new(Self {
|
||||
globalscope: GlobalScope::new_inherited(
|
||||
pipelineid,
|
||||
pipeline_id,
|
||||
devtools_chan,
|
||||
mem_profiler_chan,
|
||||
time_profiler_chan,
|
||||
|
@ -2779,7 +2738,6 @@ impl Window {
|
|||
unminify_js,
|
||||
),
|
||||
script_chan,
|
||||
task_manager,
|
||||
layout: RefCell::new(layout),
|
||||
image_cache_chan,
|
||||
image_cache,
|
||||
|
@ -2840,6 +2798,10 @@ impl Window {
|
|||
unsafe { WindowBinding::Wrap(JSContext::from_ptr(runtime.cx()), win) }
|
||||
}
|
||||
|
||||
pub(crate) fn event_loop_sender(&self) -> Box<dyn ScriptChan + Send> {
|
||||
Box::new(self.script_chan.clone())
|
||||
}
|
||||
|
||||
pub fn pipeline_id(&self) -> PipelineId {
|
||||
self.upcast::<GlobalScope>().pipeline_id()
|
||||
}
|
||||
|
@ -2983,19 +2945,11 @@ impl Window {
|
|||
);
|
||||
}
|
||||
});
|
||||
// FIXME(nox): Why are errors silenced here?
|
||||
// TODO(#12718): Use the "posted message task source".
|
||||
// TODO: When switching to the right task source, update the task_canceller call too.
|
||||
let _ = self.script_chan.send(CommonScriptMsg::Task(
|
||||
ScriptThreadEventCategory::DomEvent,
|
||||
Box::new(
|
||||
self.task_manager
|
||||
.task_canceller(TaskSourceName::DOMManipulation)
|
||||
.wrap_task(task),
|
||||
),
|
||||
Some(self.pipeline_id()),
|
||||
TaskSourceName::DOMManipulation,
|
||||
));
|
||||
let _ = self
|
||||
.task_manager()
|
||||
.dom_manipulation_task_source()
|
||||
.queue(task);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -220,12 +220,15 @@ impl WorkerMethods<crate::DomTypeHolder> for Worker {
|
|||
let (control_sender, control_receiver) = unbounded();
|
||||
let (context_sender, context_receiver) = unbounded();
|
||||
|
||||
let event_loop_sender = global
|
||||
.event_loop_sender()
|
||||
.expect("Tried to create a worker in a worker while not handling a message?");
|
||||
let join_handle = DedicatedWorkerGlobalScope::run_worker_scope(
|
||||
init,
|
||||
worker_url,
|
||||
devtools_receiver,
|
||||
worker_ref,
|
||||
global.script_chan(),
|
||||
event_loop_sender,
|
||||
sender,
|
||||
receiver,
|
||||
worker_load_origin,
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use std::cell::{OnceCell, RefCell, RefMut};
|
||||
use std::cell::{RefCell, RefMut};
|
||||
use std::default::Default;
|
||||
use std::rc::Rc;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
|
@ -44,13 +44,12 @@ use crate::dom::bindings::reflector::DomObject;
|
|||
use crate::dom::bindings::root::{DomRoot, MutNullableDom};
|
||||
use crate::dom::bindings::settings_stack::AutoEntryScript;
|
||||
use crate::dom::bindings::str::{DOMString, USVString};
|
||||
use crate::dom::bindings::trace::{CustomTraceable, RootedTraceableBox};
|
||||
use crate::dom::bindings::trace::RootedTraceableBox;
|
||||
use crate::dom::crypto::Crypto;
|
||||
use crate::dom::dedicatedworkerglobalscope::DedicatedWorkerGlobalScope;
|
||||
use crate::dom::globalscope::GlobalScope;
|
||||
use crate::dom::performance::Performance;
|
||||
use crate::dom::promise::Promise;
|
||||
use crate::dom::serviceworkerglobalscope::ServiceWorkerGlobalScope;
|
||||
#[cfg(feature = "webgpu")]
|
||||
use crate::dom::webgpu::identityhub::IdentityHub;
|
||||
use crate::dom::window::{base64_atob, base64_btoa};
|
||||
|
@ -60,7 +59,6 @@ use crate::fetch;
|
|||
use crate::realms::{enter_realm, InRealm};
|
||||
use crate::script_runtime::{CanGc, CommonScriptMsg, JSContext, Runtime, ScriptChan, ScriptPort};
|
||||
use crate::task::TaskCanceller;
|
||||
use crate::task_manager::TaskManager;
|
||||
use crate::timers::{IsInterval, TimerCallback};
|
||||
|
||||
pub fn prepare_workerscope_init(
|
||||
|
@ -124,13 +122,10 @@ pub struct WorkerGlobalScope {
|
|||
navigation_start: CrossProcessInstant,
|
||||
performance: MutNullableDom<Performance>,
|
||||
|
||||
/// A [`TimerScheduler`] used to schedule timers for this [`ServiceWorkerGlobalScope`].
|
||||
/// A [`TimerScheduler`] used to schedule timers for this [`WorkerGlobalScope`].
|
||||
/// Timers are handled in the service worker event loop.
|
||||
#[no_trace]
|
||||
timer_scheduler: RefCell<TimerScheduler>,
|
||||
|
||||
/// A [`TaskManager`] for this [`WorkerGlobalScope`].
|
||||
task_manager: OnceCell<TaskManager>,
|
||||
}
|
||||
|
||||
impl WorkerGlobalScope {
|
||||
|
@ -185,7 +180,6 @@ impl WorkerGlobalScope {
|
|||
navigation_start: CrossProcessInstant::now(),
|
||||
performance: Default::default(),
|
||||
timer_scheduler: RefCell::default(),
|
||||
task_manager: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -232,12 +226,6 @@ impl WorkerGlobalScope {
|
|||
self.worker_id
|
||||
}
|
||||
|
||||
pub fn task_canceller(&self) -> TaskCanceller {
|
||||
TaskCanceller {
|
||||
cancelled: self.closing.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn pipeline_id(&self) -> PipelineId {
|
||||
self.globalscope.pipeline_id()
|
||||
}
|
||||
|
@ -250,6 +238,14 @@ impl WorkerGlobalScope {
|
|||
pub(crate) fn timer_scheduler(&self) -> RefMut<TimerScheduler> {
|
||||
self.timer_scheduler.borrow_mut()
|
||||
}
|
||||
|
||||
/// Return a copy to the shared task canceller that is used to cancel all tasks
|
||||
/// when this worker is closing.
|
||||
pub(crate) fn shared_task_canceller(&self) -> TaskCanceller {
|
||||
TaskCanceller {
|
||||
cancelled: self.closing.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl WorkerGlobalScopeMethods<crate::DomTypeHolder> for WorkerGlobalScope {
|
||||
|
@ -495,23 +491,6 @@ impl WorkerGlobalScope {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn script_chan(&self) -> Box<dyn ScriptChan + Send> {
|
||||
let dedicated = self.downcast::<DedicatedWorkerGlobalScope>();
|
||||
let service_worker = self.downcast::<ServiceWorkerGlobalScope>();
|
||||
if let Some(dedicated) = dedicated {
|
||||
dedicated.script_chan()
|
||||
} else if let Some(service_worker) = service_worker {
|
||||
return service_worker.script_chan();
|
||||
} else {
|
||||
panic!("need to implement a sender for SharedWorker")
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn task_manager(&self) -> &TaskManager {
|
||||
self.task_manager
|
||||
.get_or_init(|| TaskManager::new(self.script_chan(), self.pipeline_id()))
|
||||
}
|
||||
|
||||
pub fn new_script_pair(&self) -> (Box<dyn ScriptChan + Send>, Box<dyn ScriptPort + Send>) {
|
||||
let dedicated = self.downcast::<DedicatedWorkerGlobalScope>();
|
||||
if let Some(dedicated) = dedicated {
|
||||
|
@ -542,5 +521,8 @@ impl WorkerGlobalScope {
|
|||
|
||||
pub fn close(&self) {
|
||||
self.closing.store(true, Ordering::SeqCst);
|
||||
self.upcast::<GlobalScope>()
|
||||
.task_manager()
|
||||
.cancel_all_tasks_and_ignore_future_tasks();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1566,6 +1566,7 @@ impl XMLHttpRequest {
|
|||
sender,
|
||||
pipeline_id: global.pipeline_id(),
|
||||
name: TaskSourceName::Networking,
|
||||
canceller: Default::default(),
|
||||
},
|
||||
Some(receiver),
|
||||
)
|
||||
|
|
|
@ -26,10 +26,7 @@ pub fn generate_cache_listener_for_element<
|
|||
let trusted_node = Trusted::new(elem);
|
||||
let (responder_sender, responder_receiver) = ipc::channel().unwrap();
|
||||
|
||||
let window = elem.owner_window();
|
||||
let (task_source, canceller) = window
|
||||
.task_manager()
|
||||
.networking_task_source_with_canceller();
|
||||
let task_source = elem.owner_window().task_manager().networking_task_source();
|
||||
let generation = elem.generation_id();
|
||||
|
||||
ROUTER.add_typed_route(
|
||||
|
@ -38,16 +35,13 @@ pub fn generate_cache_listener_for_element<
|
|||
let element = trusted_node.clone();
|
||||
let image: PendingImageResponse = message.unwrap();
|
||||
debug!("Got image {:?}", image);
|
||||
let _ = task_source.queue_with_canceller(
|
||||
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_id() {
|
||||
element.process_image_response(image.response, CanGc::note());
|
||||
}
|
||||
}),
|
||||
&canceller,
|
||||
);
|
||||
let _ = task_source.queue(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_id() {
|
||||
element.process_image_response(image.response, CanGc::note());
|
||||
}
|
||||
}));
|
||||
}),
|
||||
);
|
||||
|
||||
|
|
|
@ -434,7 +434,7 @@ pub fn follow_hyperlink(
|
|||
target_window
|
||||
.task_manager()
|
||||
.dom_manipulation_task_source()
|
||||
.queue(task, target_window.upcast())
|
||||
.queue(task)
|
||||
.unwrap();
|
||||
};
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ use crate::dom::globalscope::GlobalScope;
|
|||
use crate::dom::performanceentry::PerformanceEntry;
|
||||
use crate::dom::performanceresourcetiming::{InitiatorType, PerformanceResourceTiming};
|
||||
use crate::script_runtime::CanGc;
|
||||
use crate::task::{TaskCanceller, TaskOnce};
|
||||
use crate::task::TaskOnce;
|
||||
use crate::task_source::TaskSource;
|
||||
|
||||
/// An off-thread sink for async network event tasks. All such events are forwarded to
|
||||
|
@ -24,7 +24,6 @@ use crate::task_source::TaskSource;
|
|||
pub struct NetworkListener<Listener: PreInvoke + Send + 'static> {
|
||||
pub context: Arc<Mutex<Listener>>,
|
||||
pub task_source: TaskSource,
|
||||
pub canceller: Option<TaskCanceller>,
|
||||
}
|
||||
|
||||
pub trait ResourceTimingListener {
|
||||
|
@ -75,15 +74,11 @@ pub fn submit_timing_data(
|
|||
|
||||
impl<Listener: PreInvoke + Send + 'static> NetworkListener<Listener> {
|
||||
pub fn notify<A: Action<Listener> + Send + 'static>(&self, action: A) {
|
||||
let task = ListenerTask {
|
||||
let result = self.task_source.queue(ListenerTask {
|
||||
context: self.context.clone(),
|
||||
action,
|
||||
};
|
||||
let result = if let Some(ref canceller) = self.canceller {
|
||||
self.task_source.queue_with_canceller(task, canceller)
|
||||
} else {
|
||||
self.task_source.queue_unconditionally(task)
|
||||
};
|
||||
});
|
||||
|
||||
if let Err(err) = result {
|
||||
warn!("failed to deliver network data: {:?}", err);
|
||||
}
|
||||
|
|
|
@ -75,7 +75,6 @@ use crate::network_listener::{self, NetworkListener, PreInvoke, ResourceTimingLi
|
|||
use crate::realms::{enter_realm, AlreadyInRealm, InRealm};
|
||||
use crate::script_runtime::{CanGc, JSContext as SafeJSContext};
|
||||
use crate::task::TaskBox;
|
||||
use crate::task_source::TaskSourceName;
|
||||
|
||||
#[allow(unsafe_code)]
|
||||
unsafe fn gen_type_error(global: &GlobalScope, string: String) -> RethrowError {
|
||||
|
@ -1768,13 +1767,9 @@ fn fetch_single_module_script(
|
|||
resource_timing: ResourceFetchTiming::new(ResourceTimingType::Resource),
|
||||
}));
|
||||
|
||||
let task_source = global.task_manager().networking_task_source();
|
||||
let canceller = global.task_canceller(TaskSourceName::Networking);
|
||||
|
||||
let network_listener = NetworkListener {
|
||||
context,
|
||||
task_source,
|
||||
canceller: Some(canceller),
|
||||
task_source: global.task_manager().networking_task_source(),
|
||||
};
|
||||
match document {
|
||||
Some(document) => {
|
||||
|
|
|
@ -399,8 +399,7 @@ unsafe extern "C" fn promise_rejection_tracker(
|
|||
);
|
||||
|
||||
event.upcast::<Event>().fire(&target, CanGc::note());
|
||||
}),
|
||||
global.upcast(),
|
||||
})
|
||||
).unwrap();
|
||||
},
|
||||
};
|
||||
|
@ -455,7 +454,7 @@ unsafe extern "C" fn content_security_policy_allows(
|
|||
global
|
||||
.task_manager()
|
||||
.dom_manipulation_task_source()
|
||||
.queue(task, &global)
|
||||
.queue(task)
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
@ -529,8 +528,7 @@ pub fn notify_about_rejected_promises(global: &GlobalScope) {
|
|||
target.global().add_consumed_rejection(promise.reflector().get_jsobject().into_handle());
|
||||
}
|
||||
}
|
||||
}),
|
||||
global.upcast(),
|
||||
})
|
||||
).unwrap();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -152,7 +152,6 @@ use crate::script_runtime::{
|
|||
CanGc, CommonScriptMsg, JSContext, Runtime, ScriptChan, ScriptThreadEventCategory,
|
||||
ThreadSafeJSContext,
|
||||
};
|
||||
use crate::task_manager::TaskManager;
|
||||
use crate::task_queue::TaskQueue;
|
||||
use crate::task_source::{TaskSource, TaskSourceName};
|
||||
use crate::{devtools, webdriver_handlers};
|
||||
|
@ -693,7 +692,7 @@ impl ScriptThread {
|
|||
global
|
||||
.task_manager()
|
||||
.dom_manipulation_task_source()
|
||||
.queue(task, global.upcast())
|
||||
.queue(task)
|
||||
.expect("Enqueing navigate js task on the DOM manipulation task source failed");
|
||||
} else {
|
||||
if let Some(ref sender) = script_thread.senders.devtools_server_sender {
|
||||
|
@ -907,6 +906,7 @@ impl ScriptThread {
|
|||
sender: self_sender.as_boxed(),
|
||||
pipeline_id: state.id,
|
||||
name: TaskSourceName::Networking,
|
||||
canceller: Default::default(),
|
||||
}));
|
||||
let cx = runtime.cx();
|
||||
|
||||
|
@ -1033,8 +1033,10 @@ impl ScriptThread {
|
|||
fn prepare_for_shutdown_inner(&self) {
|
||||
let docs = self.documents.borrow();
|
||||
for (_, document) in docs.iter() {
|
||||
let window = document.window();
|
||||
window.ignore_all_tasks();
|
||||
document
|
||||
.window()
|
||||
.task_manager()
|
||||
.cancel_all_tasks_and_ignore_future_tasks();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1407,6 +1409,7 @@ impl ScriptThread {
|
|||
//
|
||||
// This task is empty because any new IPC messages in the ScriptThread trigger a
|
||||
// rendering update when animations are not running.
|
||||
let _realm = enter_realm(&*document);
|
||||
let rendering_task_source = document.window().task_manager().rendering_task_source();
|
||||
let _ =
|
||||
rendering_task_source.queue_unconditionally(task!(update_the_rendering: move || { }));
|
||||
|
@ -3129,10 +3132,6 @@ impl ScriptThread {
|
|||
pipeline_id: incomplete.pipeline_id,
|
||||
};
|
||||
|
||||
let task_manager = TaskManager::new(
|
||||
Box::new(self.senders.self_sender.clone()),
|
||||
incomplete.pipeline_id,
|
||||
);
|
||||
let paint_time_metrics = PaintTimeMetrics::new(
|
||||
incomplete.pipeline_id,
|
||||
self.senders.time_profiler_sender.clone(),
|
||||
|
@ -3161,7 +3160,6 @@ impl ScriptThread {
|
|||
let window = Window::new(
|
||||
self.js_runtime.clone(),
|
||||
self.senders.self_sender.clone(),
|
||||
task_manager,
|
||||
self.layout_factory.create(layout_config),
|
||||
self.senders.image_cache_sender.clone(),
|
||||
self.image_cache.clone(),
|
||||
|
|
|
@ -67,15 +67,15 @@ impl fmt::Debug for dyn TaskBox {
|
|||
}
|
||||
|
||||
/// Encapsulated state required to create cancellable tasks from non-script threads.
|
||||
#[derive(Clone)]
|
||||
#[derive(Clone, Default, JSTraceable, MallocSizeOf)]
|
||||
pub struct TaskCanceller {
|
||||
#[ignore_malloc_size_of = "This is difficult, because only one of them should be measured"]
|
||||
pub cancelled: Arc<AtomicBool>,
|
||||
}
|
||||
|
||||
impl TaskCanceller {
|
||||
/// Returns a wrapped `task` that will be cancelled if the `TaskCanceller`
|
||||
/// says so.
|
||||
pub fn wrap_task<T>(&self, task: T) -> impl TaskOnce
|
||||
/// Returns a wrapped `task` that will be cancelled if the `TaskCanceller` says so.
|
||||
pub(crate) fn wrap_task<T>(&self, task: T) -> impl TaskOnce
|
||||
where
|
||||
T: TaskOnce,
|
||||
{
|
||||
|
|
|
@ -2,110 +2,148 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use core::cell::RefCell;
|
||||
use core::sync::atomic::Ordering;
|
||||
use std::collections::HashMap;
|
||||
use std::sync::atomic::AtomicBool;
|
||||
use std::sync::Arc;
|
||||
|
||||
use base::id::PipelineId;
|
||||
|
||||
use crate::dom::bindings::cell::DomRefCell;
|
||||
use crate::script_runtime::ScriptChan;
|
||||
use crate::task::TaskCanceller;
|
||||
use crate::task_source::{TaskSource, TaskSourceName};
|
||||
|
||||
macro_rules! task_source_functions {
|
||||
($self:ident, $task_source:ident) => {
|
||||
pub(crate) fn $task_source(&$self) -> TaskSource {
|
||||
$self.$task_source.clone()
|
||||
}
|
||||
};
|
||||
($self:ident, $with_canceller:ident, $task_source:ident) => {
|
||||
pub(crate) fn $with_canceller(&$self) -> (TaskSource, TaskCanceller) {
|
||||
($self.$task_source.clone(), $self.task_canceller($self.$task_source.name))
|
||||
}
|
||||
#[derive(JSTraceable, MallocSizeOf)]
|
||||
enum TaskCancellers {
|
||||
/// A shared canceller that is used for workers, which can create multiple TaskManagers, but all
|
||||
/// of them need to have the same canceller flag for all task sources.
|
||||
Shared(TaskCanceller),
|
||||
/// For `Window` each `TaskSource` has its own canceller.
|
||||
OnePerTaskSource(RefCell<HashMap<TaskSourceName, TaskCanceller>>),
|
||||
}
|
||||
|
||||
impl TaskCancellers {
|
||||
fn get(&self, name: TaskSourceName) -> TaskCanceller {
|
||||
match self {
|
||||
Self::Shared(canceller) => canceller.clone(),
|
||||
Self::OnePerTaskSource(map) => map.borrow_mut().entry(name).or_default().clone(),
|
||||
}
|
||||
}
|
||||
|
||||
fn cancel_all_tasks_and_ignore_future_tasks(&self) {
|
||||
match self {
|
||||
Self::Shared(canceller) => canceller.cancelled.store(true, Ordering::SeqCst),
|
||||
Self::OnePerTaskSource(..) => {
|
||||
// We must create the canceller if they aren't created because we want future
|
||||
// tasks to be ignored completely.
|
||||
for task_source_name in TaskSourceName::all() {
|
||||
self.get(*task_source_name)
|
||||
.cancelled
|
||||
.store(true, Ordering::SeqCst)
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn cancel_pending_tasks_for_source(&self, task_source_name: TaskSourceName) {
|
||||
let Self::OnePerTaskSource(map) = self else {
|
||||
unreachable!(
|
||||
"It isn't possible to cancel pending tasks for Worker \
|
||||
TaskManager's without ignoring future tasks."
|
||||
)
|
||||
};
|
||||
|
||||
// Remove the canceller from the map so that the next time a task like this is
|
||||
// queued, it has a fresh, uncancelled canceller.
|
||||
if let Some(canceller) = map.borrow_mut().remove(&task_source_name) {
|
||||
// Cancel any tasks that use the current canceller.
|
||||
canceller.cancelled.store(true, Ordering::SeqCst);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! task_source_functions {
|
||||
($self:ident, $task_source:ident, $task_source_name:ident) => {
|
||||
pub(crate) fn $task_source(&$self) -> TaskSource {
|
||||
$self.$task_source.clone()
|
||||
$self.task_source_for_task_source_name(TaskSourceName::$task_source_name)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[derive(JSTraceable, MallocSizeOf)]
|
||||
pub struct TaskManager {
|
||||
#[ignore_malloc_size_of = "task sources are hard"]
|
||||
pub task_cancellers: DomRefCell<HashMap<TaskSourceName, Arc<AtomicBool>>>,
|
||||
dom_manipulation_task_source: TaskSource,
|
||||
file_reading_task_source: TaskSource,
|
||||
gamepad_task_source: TaskSource,
|
||||
history_traversal_task_source: TaskSource,
|
||||
media_element_task_source: TaskSource,
|
||||
networking_task_source: TaskSource,
|
||||
performance_timeline_task_source: TaskSource,
|
||||
port_message_queue: TaskSource,
|
||||
user_interaction_task_source: TaskSource,
|
||||
remote_event_task_source: TaskSource,
|
||||
rendering_task_source: TaskSource,
|
||||
timer_task_source: TaskSource,
|
||||
websocket_task_source: TaskSource,
|
||||
#[ignore_malloc_size_of = "We need to push the measurement of this down into the ScriptChan trait"]
|
||||
sender: RefCell<Option<Box<dyn ScriptChan + Send>>>,
|
||||
#[no_trace]
|
||||
pipeline_id: PipelineId,
|
||||
cancellers: TaskCancellers,
|
||||
}
|
||||
|
||||
impl TaskManager {
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub(crate) fn new(sender: Box<dyn ScriptChan + Send>, pipeline_id: PipelineId) -> Self {
|
||||
let task_source = |name| TaskSource {
|
||||
sender: sender.as_boxed(),
|
||||
pipeline_id,
|
||||
name,
|
||||
pub(crate) fn new(
|
||||
sender: Option<Box<dyn ScriptChan + Send>>,
|
||||
pipeline_id: PipelineId,
|
||||
shared_canceller: Option<TaskCanceller>,
|
||||
) -> Self {
|
||||
let cancellers = match shared_canceller {
|
||||
Some(shared_canceller) => TaskCancellers::Shared(shared_canceller),
|
||||
None => TaskCancellers::OnePerTaskSource(Default::default()),
|
||||
};
|
||||
let sender = RefCell::new(sender);
|
||||
|
||||
TaskManager {
|
||||
dom_manipulation_task_source: task_source(TaskSourceName::DOMManipulation),
|
||||
file_reading_task_source: task_source(TaskSourceName::FileReading),
|
||||
gamepad_task_source: task_source(TaskSourceName::Gamepad),
|
||||
history_traversal_task_source: task_source(TaskSourceName::HistoryTraversal),
|
||||
media_element_task_source: task_source(TaskSourceName::MediaElement),
|
||||
networking_task_source: task_source(TaskSourceName::Networking),
|
||||
performance_timeline_task_source: task_source(TaskSourceName::PerformanceTimeline),
|
||||
port_message_queue: task_source(TaskSourceName::PortMessage),
|
||||
user_interaction_task_source: task_source(TaskSourceName::UserInteraction),
|
||||
remote_event_task_source: task_source(TaskSourceName::RemoteEvent),
|
||||
rendering_task_source: task_source(TaskSourceName::Rendering),
|
||||
timer_task_source: task_source(TaskSourceName::Timer),
|
||||
websocket_task_source: task_source(TaskSourceName::WebSocket),
|
||||
task_cancellers: Default::default(),
|
||||
sender,
|
||||
pipeline_id,
|
||||
cancellers,
|
||||
}
|
||||
}
|
||||
|
||||
task_source_functions!(
|
||||
self,
|
||||
dom_manipulation_task_source_with_canceller,
|
||||
dom_manipulation_task_source
|
||||
);
|
||||
task_source_functions!(self, gamepad_task_source);
|
||||
task_source_functions!(
|
||||
self,
|
||||
media_element_task_source_with_canceller,
|
||||
media_element_task_source
|
||||
);
|
||||
task_source_functions!(self, user_interaction_task_source);
|
||||
task_source_functions!(
|
||||
self,
|
||||
networking_task_source_with_canceller,
|
||||
networking_task_source
|
||||
);
|
||||
task_source_functions!(self, file_reading_task_source);
|
||||
task_source_functions!(self, performance_timeline_task_source);
|
||||
task_source_functions!(self, port_message_queue);
|
||||
task_source_functions!(self, remote_event_task_source);
|
||||
task_source_functions!(self, rendering_task_source);
|
||||
task_source_functions!(self, timer_task_source);
|
||||
task_source_functions!(self, websocket_task_source);
|
||||
fn task_source_for_task_source_name(&self, name: TaskSourceName) -> TaskSource {
|
||||
let Some(sender) = self
|
||||
.sender
|
||||
.borrow()
|
||||
.as_ref()
|
||||
.map(|sender| sender.as_boxed())
|
||||
else {
|
||||
unreachable!("Tried to enqueue task for DedicatedWorker while not handling a message.")
|
||||
};
|
||||
|
||||
pub fn task_canceller(&self, name: TaskSourceName) -> TaskCanceller {
|
||||
let mut flags = self.task_cancellers.borrow_mut();
|
||||
let cancel_flag = flags.entry(name).or_default();
|
||||
TaskCanceller {
|
||||
cancelled: cancel_flag.clone(),
|
||||
TaskSource {
|
||||
sender,
|
||||
pipeline_id: self.pipeline_id,
|
||||
name,
|
||||
canceller: self.cancellers.get(name),
|
||||
}
|
||||
}
|
||||
|
||||
/// Update the sender for this [`TaskSource`]. This is used by dedicated workers, which only have a
|
||||
/// sender while handling messages (as their sender prevents the main thread Worker object from being
|
||||
/// garbage collected).
|
||||
pub(crate) fn set_sender(&self, sender: Option<Box<dyn ScriptChan + Send>>) {
|
||||
*self.sender.borrow_mut() = sender;
|
||||
}
|
||||
|
||||
/// Cancel all queued but unexecuted tasks and ignore all subsequently queued tasks.
|
||||
pub(crate) fn cancel_all_tasks_and_ignore_future_tasks(&self) {
|
||||
self.cancellers.cancel_all_tasks_and_ignore_future_tasks();
|
||||
}
|
||||
|
||||
/// Cancel all queued but unexecuted tasks for the given task source, but subsequently queued
|
||||
/// tasks will not be ignored.
|
||||
pub(crate) fn cancel_pending_tasks_for_source(&self, task_source_name: TaskSourceName) {
|
||||
self.cancellers
|
||||
.cancel_pending_tasks_for_source(task_source_name);
|
||||
}
|
||||
|
||||
task_source_functions!(self, dom_manipulation_task_source, DOMManipulation);
|
||||
task_source_functions!(self, file_reading_task_source, FileReading);
|
||||
task_source_functions!(self, gamepad_task_source, Gamepad);
|
||||
task_source_functions!(self, media_element_task_source, MediaElement);
|
||||
task_source_functions!(self, networking_task_source, Networking);
|
||||
task_source_functions!(self, performance_timeline_task_source, PerformanceTimeline);
|
||||
task_source_functions!(self, port_message_queue, PortMessage);
|
||||
task_source_functions!(self, remote_event_task_source, RemoteEvent);
|
||||
task_source_functions!(self, rendering_task_source, Rendering);
|
||||
task_source_functions!(self, timer_task_source, Timer);
|
||||
task_source_functions!(self, user_interaction_task_source, UserInteraction);
|
||||
task_source_functions!(self, websocket_task_source, WebSocket);
|
||||
}
|
||||
|
|
|
@ -9,12 +9,9 @@ use base::id::PipelineId;
|
|||
use malloc_size_of_derive::MallocSizeOf;
|
||||
use servo_atoms::Atom;
|
||||
|
||||
use crate::dom::bindings::inheritance::Castable;
|
||||
use crate::dom::bindings::refcounted::Trusted;
|
||||
use crate::dom::event::{EventBubbles, EventCancelable, EventTask, SimpleEventTask};
|
||||
use crate::dom::eventtarget::EventTarget;
|
||||
use crate::dom::types::GlobalScope;
|
||||
use crate::dom::window::Window;
|
||||
use crate::script_runtime::{CommonScriptMsg, ScriptChan, ScriptThreadEventCategory};
|
||||
use crate::task::{TaskCanceller, TaskOnce};
|
||||
|
||||
|
@ -92,34 +89,23 @@ pub(crate) struct TaskSource {
|
|||
#[no_trace]
|
||||
pub pipeline_id: PipelineId,
|
||||
pub name: TaskSourceName,
|
||||
pub canceller: TaskCanceller,
|
||||
}
|
||||
|
||||
impl TaskSource {
|
||||
pub(crate) fn queue_with_canceller<T>(
|
||||
&self,
|
||||
task: T,
|
||||
canceller: &TaskCanceller,
|
||||
) -> Result<(), ()>
|
||||
pub(crate) fn queue<T>(&self, task: T) -> Result<(), ()>
|
||||
where
|
||||
T: TaskOnce + 'static,
|
||||
{
|
||||
let msg = CommonScriptMsg::Task(
|
||||
self.name.into(),
|
||||
Box::new(canceller.wrap_task(task)),
|
||||
Box::new(self.canceller.wrap_task(task)),
|
||||
Some(self.pipeline_id),
|
||||
self.name,
|
||||
);
|
||||
self.sender.send(msg).map_err(|_| ())
|
||||
}
|
||||
|
||||
pub(crate) fn queue<T>(&self, task: T, global: &GlobalScope) -> Result<(), ()>
|
||||
where
|
||||
T: TaskOnce + 'static,
|
||||
{
|
||||
let canceller = global.task_canceller(self.name);
|
||||
self.queue_with_canceller(task, &canceller)
|
||||
}
|
||||
|
||||
/// This queues a task that will not be cancelled when its associated global scope gets destroyed.
|
||||
pub(crate) fn queue_unconditionally<T>(&self, task: T) -> Result<(), ()>
|
||||
where
|
||||
|
@ -133,9 +119,9 @@ impl TaskSource {
|
|||
))
|
||||
}
|
||||
|
||||
pub(crate) fn queue_simple_event(&self, target: &EventTarget, name: Atom, window: &Window) {
|
||||
pub(crate) fn queue_simple_event(&self, target: &EventTarget, name: Atom) {
|
||||
let target = Trusted::new(target);
|
||||
let _ = self.queue(SimpleEventTask { target, name }, window.upcast());
|
||||
let _ = self.queue(SimpleEventTask { target, name });
|
||||
}
|
||||
|
||||
pub(crate) fn queue_event(
|
||||
|
@ -144,16 +130,14 @@ impl TaskSource {
|
|||
name: Atom,
|
||||
bubbles: EventBubbles,
|
||||
cancelable: EventCancelable,
|
||||
window: &Window,
|
||||
) {
|
||||
let target = Trusted::new(target);
|
||||
let task = EventTask {
|
||||
let _ = self.queue(EventTask {
|
||||
target,
|
||||
name,
|
||||
bubbles,
|
||||
cancelable,
|
||||
};
|
||||
let _ = self.queue(task, window.upcast());
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -163,6 +147,7 @@ impl Clone for TaskSource {
|
|||
sender: self.sender.as_boxed(),
|
||||
pipeline_id: self.pipeline_id,
|
||||
name: self.name,
|
||||
canceller: self.canceller.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue