
The HTMLMediaElement, for example, contains spec text which states any ongoing fetch process must be "stopped". The spec does not indicate how to do this, so our implementation is rather ad-hoc. Our current implementation may cause a crash in places that assume one of the fetch algorithms that we set to null is *not* null. For example: if (fetch_params.process_response) { queue_fetch_task([]() { fetch_params.process_response(); }; } If the fetch process is stopped after queuing the fetch task, but not before the fetch task is run, we will crash when running this fetch algorithm. We now track queued fetch tasks on the fetch controller. When the fetch process is stopped, we cancel any such pending task. It is a little bit awkward maintaining a fetch task ID. Ideally, we could use the underlying task ID throughout. But we do not have access to the underlying task nor its ID when the task is running, at which point we need some ID to remove from the pending task list.
37 lines
1.4 KiB
C++
37 lines
1.4 KiB
C++
/*
|
|
* Copyright (c) 2022, Linus Groh <linusg@serenityos.org>
|
|
*
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
|
*/
|
|
|
|
#include <LibWeb/Fetch/Infrastructure/FetchController.h>
|
|
#include <LibWeb/Fetch/Infrastructure/Task.h>
|
|
#include <LibWeb/HTML/EventLoop/EventLoop.h>
|
|
|
|
namespace Web::Fetch::Infrastructure {
|
|
|
|
// https://fetch.spec.whatwg.org/#queue-a-fetch-task
|
|
int queue_fetch_task(JS::Object& task_destination, JS::SafeFunction<void()> algorithm)
|
|
{
|
|
// FIXME: 1. If taskDestination is a parallel queue, then enqueue algorithm to taskDestination.
|
|
|
|
// 2. Otherwise, queue a global task on the networking task source with taskDestination and algorithm.
|
|
return HTML::queue_global_task(HTML::Task::Source::Networking, task_destination, move(algorithm));
|
|
}
|
|
|
|
// AD-HOC: This overload allows tracking the queued task within the fetch controller so that we may cancel queued tasks
|
|
// when the spec indicates that we must stop an ongoing fetch.
|
|
int queue_fetch_task(JS::NonnullGCPtr<FetchController> fetch_controller, JS::Object& task_destination, JS::SafeFunction<void()> algorithm)
|
|
{
|
|
auto fetch_task_id = fetch_controller->next_fetch_task_id();
|
|
|
|
int event_id = queue_fetch_task(task_destination, [fetch_controller, fetch_task_id, algorithm = move(algorithm)]() {
|
|
fetch_controller->fetch_task_complete(fetch_task_id);
|
|
algorithm();
|
|
});
|
|
|
|
fetch_controller->fetch_task_queued(fetch_task_id, event_id);
|
|
return event_id;
|
|
}
|
|
|
|
}
|