mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-04-21 03:55:24 +00:00
LibWeb: Run queued HTML tasks after associated document is destroyed
Before this change, tasks associated with a destroyed document would get stuck in the task queue forever, since document-associated tasks are not allowed to run when their document isn't fully active (and destroyed documents never become fully active again). This caused everything captured by task callbacks to leak. We now treat tasks for destroyed documents as runnable immediately, which gets them out of the queue. This fixes another massive GC leak on Speedometer.
This commit is contained in:
parent
53c9c6f3ee
commit
187f8c5460
Notes:
github-actions[bot]
2025-02-07 15:54:13 +00:00
Author: https://github.com/awesomekling Commit: https://github.com/LadybirdBrowser/ladybird/commit/187f8c54602 Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/3488 Reviewed-by: https://github.com/shannonbooth
3 changed files with 18 additions and 1 deletions
|
@ -3890,6 +3890,11 @@ void Document::destroy()
|
|||
return task.document() == this;
|
||||
});
|
||||
|
||||
// AD-HOC: Mark this document as destroyed. This makes any tasks scheduled for this document in the
|
||||
// future immediately runnable instead of blocking on the document becoming fully active.
|
||||
// This is important because otherwise those tasks will get stuck in the task queue forever.
|
||||
m_has_been_destroyed = true;
|
||||
|
||||
// 8. Set document's browsing context to null.
|
||||
m_browsing_context = nullptr;
|
||||
|
||||
|
|
|
@ -560,6 +560,8 @@ public:
|
|||
Vector<GC::Root<HTML::Navigable>> inclusive_ancestor_navigables();
|
||||
Vector<GC::Root<HTML::Navigable>> document_tree_child_navigables();
|
||||
|
||||
[[nodiscard]] bool has_been_destroyed() const { return m_has_been_destroyed; }
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/document-lifecycle.html#destroy-a-document
|
||||
void destroy();
|
||||
// https://html.spec.whatwg.org/multipage/document-lifecycle.html#destroy-a-document-and-its-descendants
|
||||
|
@ -873,6 +875,8 @@ private:
|
|||
GC::Ptr<HTML::HTMLParser> m_parser;
|
||||
bool m_active_parser_was_aborted { false };
|
||||
|
||||
bool m_has_been_destroyed { false };
|
||||
|
||||
String m_source;
|
||||
|
||||
GC::Ptr<HTML::HTMLScriptElement> m_pending_parsing_blocking_script;
|
||||
|
|
|
@ -51,7 +51,15 @@ void Task::execute()
|
|||
bool Task::is_runnable() const
|
||||
{
|
||||
// A task is runnable if its document is either null or fully active.
|
||||
return !m_document.ptr() || m_document->is_fully_active();
|
||||
if (!m_document)
|
||||
return true;
|
||||
|
||||
// AD-HOC: If the document has been destroyed, we'll consider the task runnable.
|
||||
// Otherwise it would get stuck here forever, since a destroyed document never becomes fully active again.
|
||||
if (m_document->has_been_destroyed())
|
||||
return true;
|
||||
|
||||
return m_document->is_fully_active();
|
||||
}
|
||||
|
||||
DOM::Document const* Task::document() const
|
||||
|
|
Loading…
Add table
Reference in a new issue