LibWeb: Use FetchControllerHolder in HTMLLinkElement::preload()

The report_timing lambda was capturing `this` and reading
m_fetch_controller when invoked. This is fragile because
m_fetch_controller could be overwritten by a subsequent preload
before the first preload's callbacks run.

Use a FetchControllerHolder to bind the controller to each specific
fetch. The holder is captured by the lambda and populated after
fetch() returns, ensuring callbacks always use the correct controller.
This commit is contained in:
Andreas Kling
2026-01-17 10:46:28 +01:00
committed by Andreas Kling
parent a39f3c383b
commit 07b10d7ebf
Notes: github-actions[bot] 2026-01-17 23:31:40 +00:00

View File

@@ -693,11 +693,11 @@ void HTMLLinkElement::preload(LinkProcessingOptions& options, GC::Ptr<GC::Functi
request->set_initiator_type(Fetch::Infrastructure::Request::InitiatorType::EarlyHint);
// 9. Let controller be null.
m_fetch_controller = nullptr;
auto controller_holder = Fetch::Infrastructure::FetchControllerHolder::create(vm);
// 10. Let reportTiming given a Document document be to report timing for controller given document's relevant global object.
auto report_timing = GC::Function<void(DOM::Document const&)>::create(realm.heap(), [this](DOM::Document const& document) {
m_fetch_controller->report_timing(relevant_global_object(document));
auto report_timing = GC::Function<void(DOM::Document const&)>::create(realm.heap(), [controller_holder](DOM::Document const& document) {
controller_holder->controller()->report_timing(relevant_global_object(document));
});
// 11. Set controller to the result of fetching request, with processResponseConsumeBody set to the following steps
@@ -734,6 +734,7 @@ void HTMLLinkElement::preload(LinkProcessingOptions& options, GC::Ptr<GC::Functi
};
m_fetch_controller = Fetch::Fetching::fetch(realm, *request, Fetch::Infrastructure::FetchAlgorithms::create(vm, move(fetch_algorithms_input)));
controller_holder->set_controller(*m_fetch_controller);
// 12. Let commit be the following steps given a Document document:
auto commit = GC::Function<void(DOM::Document&)>::create(realm.heap(), [entry, report_timing](DOM::Document& document) {