mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-25 00:50:22 +00:00
LibWeb: Make Platform::Timer GC-allocated
This will allow us to remove the use of SafeFunction in it's implementation. This requires a fair amount of plumbing to wire up the GC heap to the appropriate places in order to create the timers.
This commit is contained in:
parent
e44702f090
commit
ede3c91688
Notes:
github-actions[bot]
2024-10-30 19:57:28 +00:00
Author: https://github.com/shannonbooth Commit: https://github.com/LadybirdBrowser/ladybird/commit/ede3c916883 Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/2062 Reviewed-by: https://github.com/kalenikaliaksandr ✅
15 changed files with 52 additions and 38 deletions
|
@ -28,6 +28,14 @@ ImageStyleValue::ImageStyleValue(URL::URL const& url)
|
|||
|
||||
ImageStyleValue::~ImageStyleValue() = default;
|
||||
|
||||
void ImageStyleValue::visit_edges(JS::Cell::Visitor& visitor) const
|
||||
{
|
||||
// FIXME: visit_edges in non-GC allocated classes is confusing pattern.
|
||||
// Consider making CSSStyleValue to be GC allocated instead.
|
||||
visitor.visit(m_resource_request);
|
||||
visitor.visit(m_timer);
|
||||
}
|
||||
|
||||
void ImageStyleValue::load_any_resources(DOM::Document& document)
|
||||
{
|
||||
if (m_resource_request)
|
||||
|
@ -53,7 +61,7 @@ void ImageStyleValue::load_any_resources(DOM::Document& document)
|
|||
|
||||
auto image_data = m_resource_request->image_data();
|
||||
if (image_data->is_animated() && image_data->frame_count() > 1) {
|
||||
m_timer = Platform::Timer::create();
|
||||
m_timer = Platform::Timer::create(m_document->heap());
|
||||
m_timer->set_interval(image_data->frame_duration(0));
|
||||
m_timer->on_timeout = [this] { animate(); };
|
||||
m_timer->start();
|
||||
|
|
|
@ -28,12 +28,7 @@ public:
|
|||
}
|
||||
virtual ~ImageStyleValue() override;
|
||||
|
||||
void visit_edges(JS::Cell::Visitor& visitor) const
|
||||
{
|
||||
// FIXME: visit_edges in non-GC allocated classes is confusing pattern.
|
||||
// Consider making CSSStyleValue to be GC allocated instead.
|
||||
visitor.visit(m_resource_request);
|
||||
}
|
||||
void visit_edges(JS::Cell::Visitor& visitor) const;
|
||||
|
||||
virtual String to_string() const override;
|
||||
virtual bool equals(CSSStyleValue const& other) const override;
|
||||
|
@ -67,7 +62,7 @@ private:
|
|||
|
||||
size_t m_current_frame_index { 0 };
|
||||
size_t m_loops_completed { 0 };
|
||||
RefPtr<Platform::Timer> m_timer;
|
||||
JS::GCPtr<Platform::Timer> m_timer;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -48,12 +48,13 @@ void EventLoop::visit_edges(Visitor& visitor)
|
|||
visitor.visit(m_currently_running_task);
|
||||
visitor.visit(m_backup_incumbent_settings_object_stack);
|
||||
visitor.visit(m_rendering_task_function);
|
||||
visitor.visit(m_system_event_loop_timer);
|
||||
}
|
||||
|
||||
void EventLoop::schedule()
|
||||
{
|
||||
if (!m_system_event_loop_timer) {
|
||||
m_system_event_loop_timer = Platform::Timer::create_single_shot(0, [this] {
|
||||
m_system_event_loop_timer = Platform::Timer::create_single_shot(heap(), 0, [this] {
|
||||
process();
|
||||
});
|
||||
}
|
||||
|
|
|
@ -96,7 +96,7 @@ private:
|
|||
// https://html.spec.whatwg.org/multipage/webappapis.html#last-idle-period-start-time
|
||||
double m_last_idle_period_start_time { 0 };
|
||||
|
||||
RefPtr<Platform::Timer> m_system_event_loop_timer;
|
||||
JS::GCPtr<Platform::Timer> m_system_event_loop_timer;
|
||||
|
||||
// https://html.spec.whatwg.org/#performing-a-microtask-checkpoint
|
||||
bool m_performing_a_microtask_checkpoint { false };
|
||||
|
|
|
@ -414,8 +414,9 @@ void ResourceLoader::load(LoadRequest& request, SuccessCallback success_callback
|
|||
}
|
||||
|
||||
if (timeout.has_value() && timeout.value() > 0) {
|
||||
auto timer = Platform::Timer::create_single_shot(timeout.value(), nullptr);
|
||||
auto timer = Platform::Timer::create_single_shot(m_heap, timeout.value(), nullptr);
|
||||
timer->on_timeout = [timer, protocol_request, timeout_callback = move(timeout_callback)] {
|
||||
(void)timer;
|
||||
protocol_request->stop();
|
||||
if (timeout_callback)
|
||||
timeout_callback();
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <AK/Forward.h>
|
||||
#include <LibJS/Heap/GCPtr.h>
|
||||
#include <LibJS/SafeFunction.h>
|
||||
#include <LibWeb/Forward.h>
|
||||
|
||||
|
@ -21,7 +22,7 @@ public:
|
|||
|
||||
virtual void spin_until(JS::SafeFunction<bool()> goal_condition) = 0;
|
||||
virtual void deferred_invoke(ESCAPING JS::SafeFunction<void()>) = 0;
|
||||
virtual NonnullRefPtr<Timer> create_timer() = 0;
|
||||
virtual JS::NonnullGCPtr<Timer> create_timer(JS::Heap&) = 0;
|
||||
virtual void quit() = 0;
|
||||
};
|
||||
|
||||
|
|
|
@ -25,9 +25,9 @@ void EventLoopPluginSerenity::deferred_invoke(JS::SafeFunction<void()> function)
|
|||
Core::deferred_invoke(move(function));
|
||||
}
|
||||
|
||||
NonnullRefPtr<Timer> EventLoopPluginSerenity::create_timer()
|
||||
JS::NonnullGCPtr<Timer> EventLoopPluginSerenity::create_timer(JS::Heap& heap)
|
||||
{
|
||||
return TimerSerenity::create();
|
||||
return TimerSerenity::create(heap);
|
||||
}
|
||||
|
||||
void EventLoopPluginSerenity::quit()
|
||||
|
|
|
@ -17,7 +17,7 @@ public:
|
|||
|
||||
virtual void spin_until(JS::SafeFunction<bool()> goal_condition) override;
|
||||
virtual void deferred_invoke(JS::SafeFunction<void()>) override;
|
||||
virtual NonnullRefPtr<Timer> create_timer() override;
|
||||
virtual JS::NonnullGCPtr<Timer> create_timer(JS::Heap&) override;
|
||||
virtual void quit() override;
|
||||
};
|
||||
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <AK/NonnullRefPtr.h>
|
||||
#include <LibWeb/Platform/EventLoopPlugin.h>
|
||||
#include <LibWeb/Platform/Timer.h>
|
||||
|
||||
|
@ -12,23 +11,23 @@ namespace Web::Platform {
|
|||
|
||||
Timer::~Timer() = default;
|
||||
|
||||
NonnullRefPtr<Timer> Timer::create()
|
||||
JS::NonnullGCPtr<Timer> Timer::create(JS::Heap& heap)
|
||||
{
|
||||
return EventLoopPlugin::the().create_timer();
|
||||
return EventLoopPlugin::the().create_timer(heap);
|
||||
}
|
||||
|
||||
NonnullRefPtr<Timer> Timer::create_repeating(int interval_ms, JS::SafeFunction<void()>&& timeout_handler)
|
||||
JS::NonnullGCPtr<Timer> Timer::create_repeating(JS::Heap& heap, int interval_ms, JS::SafeFunction<void()>&& timeout_handler)
|
||||
{
|
||||
auto timer = EventLoopPlugin::the().create_timer();
|
||||
auto timer = EventLoopPlugin::the().create_timer(heap);
|
||||
timer->set_single_shot(false);
|
||||
timer->set_interval(interval_ms);
|
||||
timer->on_timeout = move(timeout_handler);
|
||||
return timer;
|
||||
}
|
||||
|
||||
NonnullRefPtr<Timer> Timer::create_single_shot(int interval_ms, JS::SafeFunction<void()>&& timeout_handler)
|
||||
JS::NonnullGCPtr<Timer> Timer::create_single_shot(JS::Heap& heap, int interval_ms, JS::SafeFunction<void()>&& timeout_handler)
|
||||
{
|
||||
auto timer = EventLoopPlugin::the().create_timer();
|
||||
auto timer = EventLoopPlugin::the().create_timer(heap);
|
||||
timer->set_single_shot(true);
|
||||
timer->set_interval(interval_ms);
|
||||
timer->on_timeout = move(timeout_handler);
|
||||
|
|
|
@ -7,15 +7,18 @@
|
|||
#pragma once
|
||||
|
||||
#include <AK/RefCounted.h>
|
||||
#include <LibJS/Heap/Cell.h>
|
||||
#include <LibJS/SafeFunction.h>
|
||||
|
||||
namespace Web::Platform {
|
||||
|
||||
class Timer : public RefCounted<Timer> {
|
||||
class Timer : public JS::Cell {
|
||||
JS_CELL(Timer, JS::Cell);
|
||||
|
||||
public:
|
||||
static NonnullRefPtr<Timer> create();
|
||||
static NonnullRefPtr<Timer> create_repeating(int interval_ms, JS::SafeFunction<void()>&& timeout_handler);
|
||||
static NonnullRefPtr<Timer> create_single_shot(int interval_ms, JS::SafeFunction<void()>&& timeout_handler);
|
||||
static JS::NonnullGCPtr<Timer> create(JS::Heap&);
|
||||
static JS::NonnullGCPtr<Timer> create_repeating(JS::Heap&, int interval_ms, JS::SafeFunction<void()>&& timeout_handler);
|
||||
static JS::NonnullGCPtr<Timer> create_single_shot(JS::Heap&, int interval_ms, JS::SafeFunction<void()>&& timeout_handler);
|
||||
|
||||
virtual ~Timer();
|
||||
|
||||
|
|
|
@ -7,12 +7,13 @@
|
|||
#include "TimerSerenity.h"
|
||||
#include <AK/NonnullRefPtr.h>
|
||||
#include <LibCore/Timer.h>
|
||||
#include <LibJS/Heap/Heap.h>
|
||||
|
||||
namespace Web::Platform {
|
||||
|
||||
NonnullRefPtr<TimerSerenity> TimerSerenity::create()
|
||||
JS::NonnullGCPtr<TimerSerenity> TimerSerenity::create(JS::Heap& heap)
|
||||
{
|
||||
return adopt_ref(*new TimerSerenity);
|
||||
return heap.allocate_without_realm<TimerSerenity>();
|
||||
}
|
||||
|
||||
TimerSerenity::TimerSerenity()
|
||||
|
|
|
@ -6,15 +6,16 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <AK/NonnullRefPtr.h>
|
||||
#include <LibCore/Forward.h>
|
||||
#include <LibWeb/Platform/Timer.h>
|
||||
|
||||
namespace Web::Platform {
|
||||
|
||||
class TimerSerenity final : public Timer {
|
||||
JS_CELL(TimerSerenity, Timer);
|
||||
|
||||
public:
|
||||
static NonnullRefPtr<TimerSerenity> create();
|
||||
static JS::NonnullGCPtr<TimerSerenity> create(JS::Heap&);
|
||||
|
||||
virtual ~TimerSerenity();
|
||||
|
||||
|
|
|
@ -876,11 +876,12 @@ WebIDL::ExceptionOr<void> XMLHttpRequest::send(Optional<DocumentOrXMLHttpRequest
|
|||
// 1. Wait until either req’s done flag is set or this’s timeout is not 0 and this’s timeout milliseconds have passed since now.
|
||||
// 2. If req’s done flag is unset, then set this’s timed out flag and terminate this’s fetch controller.
|
||||
if (m_timeout != 0) {
|
||||
auto timer = Platform::Timer::create_single_shot(m_timeout, nullptr);
|
||||
auto timer = Platform::Timer::create_single_shot(heap(), m_timeout, nullptr);
|
||||
|
||||
// NOTE: `timer` is kept alive by copying the NNRP into the lambda, incrementing its ref-count.
|
||||
// NOTE: `timer` is kept alive by capturing into the lambda for the GC to see
|
||||
// NOTE: `this` and `request` is kept alive by Platform::Timer using JS::SafeFunction.
|
||||
timer->on_timeout = [this, request, timer]() {
|
||||
(void)timer;
|
||||
if (!request->done()) {
|
||||
m_timed_out = true;
|
||||
m_fetch_controller->terminate();
|
||||
|
@ -929,10 +930,11 @@ WebIDL::ExceptionOr<void> XMLHttpRequest::send(Optional<DocumentOrXMLHttpRequest
|
|||
bool did_time_out = false;
|
||||
|
||||
if (m_timeout != 0) {
|
||||
auto timer = Platform::Timer::create_single_shot(m_timeout, nullptr);
|
||||
auto timer = Platform::Timer::create_single_shot(heap(), m_timeout, nullptr);
|
||||
|
||||
// NOTE: `timer` is kept alive by copying the NNRP into the lambda, incrementing its ref-count.
|
||||
// NOTE: `timer` is kept alive by capturing into the lambda for the GC to see
|
||||
timer->on_timeout = [timer, &did_time_out]() {
|
||||
(void)timer;
|
||||
did_time_out = true;
|
||||
};
|
||||
|
||||
|
|
|
@ -53,11 +53,12 @@
|
|||
|
||||
namespace WebContent {
|
||||
|
||||
ConnectionFromClient::ConnectionFromClient(IPC::Transport transport)
|
||||
ConnectionFromClient::ConnectionFromClient(JS::Heap& heap, IPC::Transport transport)
|
||||
: IPC::ConnectionFromClient<WebContentClientEndpoint, WebContentServerEndpoint>(*this, move(transport), 1)
|
||||
, m_heap(heap)
|
||||
, m_page_host(PageHost::create(*this))
|
||||
{
|
||||
m_input_event_queue_timer = Web::Platform::Timer::create_single_shot(0, [this] { process_next_input_event(); });
|
||||
m_input_event_queue_timer = Web::Platform::Timer::create_single_shot(m_heap, 0, [this] { process_next_input_event(); });
|
||||
}
|
||||
|
||||
ConnectionFromClient::~ConnectionFromClient() = default;
|
||||
|
|
|
@ -48,7 +48,7 @@ public:
|
|||
Function<void(IPC::File const&)> on_image_decoder_connection;
|
||||
|
||||
private:
|
||||
explicit ConnectionFromClient(IPC::Transport);
|
||||
explicit ConnectionFromClient(JS::Heap&, IPC::Transport);
|
||||
|
||||
Optional<PageClient&> page(u64 index, SourceLocation = SourceLocation::current());
|
||||
Optional<PageClient const&> page(u64 index, SourceLocation = SourceLocation::current()) const;
|
||||
|
@ -150,6 +150,7 @@ private:
|
|||
|
||||
void report_finished_handling_input_event(u64 page_id, Web::EventResult event_was_handled);
|
||||
|
||||
JS::Heap& m_heap;
|
||||
NonnullOwnPtr<PageHost> m_page_host;
|
||||
|
||||
HashMap<int, Web::FileRequest> m_requested_files {};
|
||||
|
@ -166,7 +167,7 @@ private:
|
|||
|
||||
Queue<QueuedInputEvent> m_input_event_queue;
|
||||
|
||||
RefPtr<Web::Platform::Timer> m_input_event_queue_timer;
|
||||
JS::Handle<Web::Platform::Timer> m_input_event_queue_timer;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue