mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-09-30 00:31:14 +00:00
LibWeb: Clear all active timers when document is destroyed
This change implements a step from the document's destroy procedure in the specification, saying that all active timers should be cleared. By doing this, we also fix the leaking of a document in case where we have navigated away from a page that has scheduled timers that haven't yet been triggered.
This commit is contained in:
parent
73ef102b01
commit
67c727177e
Notes:
sideshowbarker
2024-07-17 08:45:34 +09:00
Author: https://github.com/kalenikaliaksandr Commit: https://github.com/SerenityOS/serenity/commit/67c727177e Pull-request: https://github.com/SerenityOS/serenity/pull/21234
|
@ -2656,6 +2656,27 @@ Vector<JS::Handle<HTML::BrowsingContext>> Document::list_of_descendant_browsing_
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://html.spec.whatwg.org/multipage/document-lifecycle.html#unloading-document-cleanup-steps
|
||||||
|
void Document::run_unloading_cleanup_steps()
|
||||||
|
{
|
||||||
|
// 1. Let window be document's relevant global object.
|
||||||
|
auto* window = dynamic_cast<HTML::WindowOrWorkerGlobalScopeMixin*>(&HTML::relevant_global_object(*this));
|
||||||
|
VERIFY(window);
|
||||||
|
|
||||||
|
// FIXME: 2. For each WebSocket object webSocket whose relevant global object is window, make disappear webSocket.
|
||||||
|
// If this affected any WebSocket objects, then set document's salvageable state to false.
|
||||||
|
|
||||||
|
// FIXME: 3. For each WebTransport object transport whose relevant global object is window, run the context cleanup steps given transport.
|
||||||
|
|
||||||
|
// 4. If document's salvageable state is false, then:
|
||||||
|
if (m_salvageable) {
|
||||||
|
// FIXME: 1. For each EventSource object eventSource whose relevant global object is equal to window, forcibly close eventSource.
|
||||||
|
|
||||||
|
// 2. Clear window's map of active timers.
|
||||||
|
window->clear_map_of_active_timers();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/document-lifecycle.html#destroy-a-document
|
// https://html.spec.whatwg.org/multipage/document-lifecycle.html#destroy-a-document
|
||||||
void Document::destroy()
|
void Document::destroy()
|
||||||
{
|
{
|
||||||
|
@ -2668,7 +2689,8 @@ void Document::destroy()
|
||||||
// 2. Set document's salvageable state to false.
|
// 2. Set document's salvageable state to false.
|
||||||
m_salvageable = false;
|
m_salvageable = false;
|
||||||
|
|
||||||
// FIXME: 3. Run any unloading document cleanup steps for document that are defined by this specification and other applicable specifications.
|
// 3. Run any unloading document cleanup steps for document that are defined by this specification and other applicable specifications.
|
||||||
|
run_unloading_cleanup_steps();
|
||||||
|
|
||||||
// 5. Remove any tasks whose document is document from any task queue (without running those tasks).
|
// 5. Remove any tasks whose document is document from any task queue (without running those tasks).
|
||||||
HTML::main_thread_event_loop().task_queue().remove_tasks_matching([this](auto& task) {
|
HTML::main_thread_event_loop().task_queue().remove_tasks_matching([this](auto& task) {
|
||||||
|
|
|
@ -545,6 +545,8 @@ private:
|
||||||
|
|
||||||
void tear_down_layout_tree();
|
void tear_down_layout_tree();
|
||||||
|
|
||||||
|
void run_unloading_cleanup_steps();
|
||||||
|
|
||||||
void evaluate_media_rules();
|
void evaluate_media_rules();
|
||||||
|
|
||||||
WebIDL::ExceptionOr<void> run_the_document_write_steps(StringView);
|
WebIDL::ExceptionOr<void> run_the_document_write_steps(StringView);
|
||||||
|
|
|
@ -34,6 +34,7 @@ void Timer::visit_edges(Cell::Visitor& visitor)
|
||||||
|
|
||||||
Timer::~Timer()
|
Timer::~Timer()
|
||||||
{
|
{
|
||||||
|
VERIFY(!m_timer->is_active());
|
||||||
}
|
}
|
||||||
|
|
||||||
void Timer::start()
|
void Timer::start()
|
||||||
|
@ -41,4 +42,9 @@ void Timer::start()
|
||||||
m_timer->start();
|
m_timer->start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Timer::stop()
|
||||||
|
{
|
||||||
|
m_timer->stop();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,7 @@ public:
|
||||||
virtual ~Timer() override;
|
virtual ~Timer() override;
|
||||||
|
|
||||||
void start();
|
void start();
|
||||||
|
void stop();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Timer(JS::Object& window, i32 milliseconds, Function<void()> callback, i32 id);
|
Timer(JS::Object& window, i32 milliseconds, Function<void()> callback, i32 id);
|
||||||
|
|
|
@ -183,15 +183,26 @@ i32 WindowOrWorkerGlobalScopeMixin::set_interval(TimerHandler handler, i32 timeo
|
||||||
// https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html#dom-cleartimeout
|
// https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html#dom-cleartimeout
|
||||||
void WindowOrWorkerGlobalScopeMixin::clear_timeout(i32 id)
|
void WindowOrWorkerGlobalScopeMixin::clear_timeout(i32 id)
|
||||||
{
|
{
|
||||||
|
if (auto timer = m_timers.get(id); timer.has_value())
|
||||||
|
timer.value()->stop();
|
||||||
m_timers.remove(id);
|
m_timers.remove(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html#dom-clearinterval
|
// https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html#dom-clearinterval
|
||||||
void WindowOrWorkerGlobalScopeMixin::clear_interval(i32 id)
|
void WindowOrWorkerGlobalScopeMixin::clear_interval(i32 id)
|
||||||
{
|
{
|
||||||
|
if (auto timer = m_timers.get(id); timer.has_value())
|
||||||
|
timer.value()->stop();
|
||||||
m_timers.remove(id);
|
m_timers.remove(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WindowOrWorkerGlobalScopeMixin::clear_map_of_active_timers()
|
||||||
|
{
|
||||||
|
for (auto& it : m_timers)
|
||||||
|
it.value->stop();
|
||||||
|
m_timers.clear();
|
||||||
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html#timer-initialisation-steps
|
// https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html#timer-initialisation-steps
|
||||||
// With no active script fix from https://github.com/whatwg/html/pull/9712
|
// With no active script fix from https://github.com/whatwg/html/pull/9712
|
||||||
i32 WindowOrWorkerGlobalScopeMixin::run_timer_initialization_steps(TimerHandler handler, i32 timeout, JS::MarkedVector<JS::Value> arguments, Repeat repeat, Optional<i32> previous_id)
|
i32 WindowOrWorkerGlobalScopeMixin::run_timer_initialization_steps(TimerHandler handler, i32 timeout, JS::MarkedVector<JS::Value> arguments, Repeat repeat, Optional<i32> previous_id)
|
||||||
|
|
|
@ -46,6 +46,7 @@ public:
|
||||||
i32 set_interval(TimerHandler, i32 timeout, JS::MarkedVector<JS::Value> arguments);
|
i32 set_interval(TimerHandler, i32 timeout, JS::MarkedVector<JS::Value> arguments);
|
||||||
void clear_timeout(i32);
|
void clear_timeout(i32);
|
||||||
void clear_interval(i32);
|
void clear_interval(i32);
|
||||||
|
void clear_map_of_active_timers();
|
||||||
|
|
||||||
PerformanceTimeline::PerformanceEntryTuple& relevant_performance_entry_tuple(FlyString const& entry_type);
|
PerformanceTimeline::PerformanceEntryTuple& relevant_performance_entry_tuple(FlyString const& entry_type);
|
||||||
void queue_performance_entry(JS::NonnullGCPtr<PerformanceTimeline::PerformanceEntry> new_entry);
|
void queue_performance_entry(JS::NonnullGCPtr<PerformanceTimeline::PerformanceEntry> new_entry);
|
||||||
|
|
Loading…
Reference in a new issue