LibWeb: Move WebDriver's HeapTimer helper class to its own file

And generalize it a tiny bit to be reusable outside of ExecuteScript.
This commit is contained in:
Timothy Flynn 2024-10-25 11:02:31 -04:00 committed by Andreas Kling
parent 74ef9dc393
commit 8598d4670d
Notes: github-actions[bot] 2024-10-26 09:26:52 +00:00
5 changed files with 104 additions and 56 deletions

View file

@ -747,6 +747,7 @@ set(SOURCES
WebDriver/ElementReference.cpp
WebDriver/Error.cpp
WebDriver/ExecuteScript.cpp
WebDriver/HeapTimer.cpp
WebDriver/InputSource.cpp
WebDriver/InputState.cpp
WebDriver/Response.cpp

View file

@ -812,6 +812,8 @@ using Promise = JS::PromiseCapability;
}
namespace Web::WebDriver {
class HeapTimer;
struct ActionObject;
struct InputState;
};

View file

@ -33,6 +33,7 @@
#include <LibWeb/WebDriver/Contexts.h>
#include <LibWeb/WebDriver/ElementReference.h>
#include <LibWeb/WebDriver/ExecuteScript.h>
#include <LibWeb/WebDriver/HeapTimer.h>
namespace Web::WebDriver {
@ -301,61 +302,14 @@ static JS::ThrowCompletionOr<JS::Value> execute_a_function_body(HTML::BrowsingCo
return completion;
}
class HeapTimer : public JS::Cell {
JS_CELL(HeapTimer, JS::Cell);
JS_DECLARE_ALLOCATOR(HeapTimer);
static ExecuteScriptResultSerialized create_timeout_result()
{
JsonObject error_object;
error_object.set("name", "Error");
error_object.set("message", "Script Timeout");
public:
explicit HeapTimer()
: m_timer(Core::Timer::create())
{
}
virtual ~HeapTimer() override = default;
void start(u64 timeout_ms, JS::NonnullGCPtr<OnScriptComplete> on_timeout)
{
m_on_timeout = on_timeout;
m_timer->on_timeout = [this]() {
m_timed_out = true;
if (m_on_timeout) {
auto error_object = JsonObject {};
error_object.set("name", "Error");
error_object.set("message", "Script Timeout");
m_on_timeout->function()({ ExecuteScriptResultType::Timeout, move(error_object) });
m_on_timeout = nullptr;
}
};
m_timer->set_interval(static_cast<int>(timeout_ms));
m_timer->set_single_shot(true);
m_timer->start();
}
void stop()
{
m_on_timeout = nullptr;
m_timer->stop();
}
bool is_timed_out() const { return m_timed_out; }
private:
virtual void visit_edges(JS::Cell::Visitor& visitor) override
{
Base::visit_edges(visitor);
visitor.visit(m_on_timeout);
}
NonnullRefPtr<Core::Timer> m_timer;
JS::GCPtr<OnScriptComplete> m_on_timeout;
bool m_timed_out { false };
};
JS_DEFINE_ALLOCATOR(HeapTimer);
return { ExecuteScriptResultType::Timeout, move(error_object) };
}
void execute_script(HTML::BrowsingContext const& browsing_context, ByteString body, JS::MarkedVector<JS::Value> arguments, Optional<u64> const& timeout_ms, JS::NonnullGCPtr<OnScriptComplete> on_complete)
{
@ -369,7 +323,9 @@ void execute_script(HTML::BrowsingContext const& browsing_context, ByteString bo
// 6. If timeout is not null:
if (timeout_ms.has_value()) {
// 1. Start the timer with timer and timeout.
timer->start(timeout_ms.value(), on_complete);
timer->start(timeout_ms.value(), JS::create_heap_function(vm.heap(), [on_complete]() {
on_complete->function()(create_timeout_result());
}));
}
// AD-HOC: An execution context is required for Promise creation hooks.
@ -445,7 +401,9 @@ void execute_async_script(HTML::BrowsingContext const& browsing_context, ByteStr
// 6. If timeout is not null:
if (timeout_ms.has_value()) {
// 1. Start the timer with timer and timeout.
timer->start(timeout_ms.value(), on_complete);
timer->start(timeout_ms.value(), JS::create_heap_function(vm.heap(), [on_complete]() {
on_complete->function()(create_timeout_result());
}));
}
// AD-HOC: An execution context is required for Promise creation hooks.

View file

@ -0,0 +1,51 @@
/*
* Copyright (c) 2024, Tim Flynn <trflynn89@ladybird.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibCore/Timer.h>
#include <LibWeb/WebDriver/HeapTimer.h>
namespace Web::WebDriver {
JS_DEFINE_ALLOCATOR(HeapTimer);
HeapTimer::HeapTimer()
: m_timer(Core::Timer::create())
{
}
HeapTimer::~HeapTimer() = default;
void HeapTimer::visit_edges(JS::Cell::Visitor& visitor)
{
Base::visit_edges(visitor);
visitor.visit(m_on_timeout);
}
void HeapTimer::start(u64 timeout_ms, JS::NonnullGCPtr<JS::HeapFunction<void()>> on_timeout)
{
m_on_timeout = on_timeout;
m_timer->on_timeout = [this]() {
m_timed_out = true;
if (m_on_timeout) {
m_on_timeout->function()();
m_on_timeout = nullptr;
}
};
m_timer->set_interval(static_cast<int>(timeout_ms));
m_timer->set_single_shot(true);
m_timer->start();
}
void HeapTimer::stop()
{
m_on_timeout = nullptr;
m_timer->stop();
}
}

View file

@ -0,0 +1,36 @@
/*
* Copyright (c) 2024, Tim Flynn <trflynn89@ladybird.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <LibCore/Forward.h>
#include <LibJS/Heap/GCPtr.h>
#include <LibJS/Heap/HeapFunction.h>
namespace Web::WebDriver {
class HeapTimer : public JS::Cell {
JS_CELL(HeapTimer, JS::Cell);
JS_DECLARE_ALLOCATOR(HeapTimer);
public:
explicit HeapTimer();
virtual ~HeapTimer() override;
void start(u64 timeout_ms, JS::NonnullGCPtr<JS::HeapFunction<void()>> on_timeout);
void stop();
bool is_timed_out() const { return m_timed_out; }
private:
virtual void visit_edges(JS::Cell::Visitor& visitor) override;
NonnullRefPtr<Core::Timer> m_timer;
JS::GCPtr<JS::HeapFunction<void()>> m_on_timeout;
bool m_timed_out { false };
};
}