LibWeb: Abort ongoing fetch before starting a new link element fetch

If we decide to fetch another linked resource, we don't care about the
earlier fetch and can safely abort it.

This fixes an issue on GitHub where we'd load the same style sheet
multiple times and invalidate style for the entire document every time
it finished fetching.

By aborting the ongoing fetch, no excess invalidation happens.

(cherry picked from commit 57e26ed6b9b2c0cf1e4f5ac3e85ca0c7f3647caa)
This commit is contained in:
Andreas Kling 2024-09-22 13:29:49 +02:00 committed by Nico Weber
parent 88b2d705e2
commit 4172811f75
2 changed files with 7 additions and 1 deletions

View file

@ -19,6 +19,7 @@
#include <LibWeb/DOM/ShadowRoot.h>
#include <LibWeb/Fetch/Fetching/Fetching.h>
#include <LibWeb/Fetch/Infrastructure/FetchAlgorithms.h>
#include <LibWeb/Fetch/Infrastructure/FetchController.h>
#include <LibWeb/Fetch/Infrastructure/HTTP/Requests.h>
#include <LibWeb/Fetch/Infrastructure/HTTP/Responses.h>
#include <LibWeb/HTML/EventNames.h>
@ -363,7 +364,9 @@ void HTMLLinkElement::default_fetch_and_process_linked_resource()
process_linked_resource(success, response, body_bytes);
};
Fetch::Fetching::fetch(realm(), *request, Fetch::Infrastructure::FetchAlgorithms::create(vm(), move(fetch_algorithms_input))).release_value_but_fixme_should_propagate_errors();
if (m_fetch_controller)
m_fetch_controller->abort(realm(), {});
m_fetch_controller = MUST(Fetch::Fetching::fetch(realm(), *request, Fetch::Infrastructure::FetchAlgorithms::create(vm(), move(fetch_algorithms_input))));
}
// https://html.spec.whatwg.org/multipage/links.html#link-type-stylesheet:process-the-linked-resource
@ -605,6 +608,7 @@ WebIDL::ExceptionOr<void> HTMLLinkElement::load_fallback_favicon_if_needed(JS::N
void HTMLLinkElement::visit_edges(Cell::Visitor& visitor)
{
Base::visit_edges(visitor);
visitor.visit(m_fetch_controller);
visitor.visit(m_loaded_style_sheet);
visitor.visit(m_rel_list);
}

View file

@ -137,6 +137,8 @@ private:
};
};
JS::GCPtr<Fetch::Infrastructure::FetchController> m_fetch_controller;
JS::GCPtr<CSS::CSSStyleSheet> m_loaded_style_sheet;
Optional<DOM::DocumentLoadEventDelayer> m_document_load_event_delayer;