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:
Martin Robinson 2025-01-04 09:41:50 +01:00 committed by GitHub
parent 75a22cfe2e
commit b2eda71952
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
54 changed files with 1060 additions and 1516 deletions

View file

@ -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 requests 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,