diff --git a/Userland/Libraries/LibWeb/CMakeLists.txt b/Userland/Libraries/LibWeb/CMakeLists.txt index da046c9cc45..3d0a45fc3c4 100644 --- a/Userland/Libraries/LibWeb/CMakeLists.txt +++ b/Userland/Libraries/LibWeb/CMakeLists.txt @@ -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 diff --git a/Userland/Libraries/LibWeb/Forward.h b/Userland/Libraries/LibWeb/Forward.h index aba1ae04b07..4c324bfbdb3 100644 --- a/Userland/Libraries/LibWeb/Forward.h +++ b/Userland/Libraries/LibWeb/Forward.h @@ -812,6 +812,8 @@ using Promise = JS::PromiseCapability; } namespace Web::WebDriver { +class HeapTimer; + struct ActionObject; struct InputState; }; diff --git a/Userland/Libraries/LibWeb/WebDriver/ExecuteScript.cpp b/Userland/Libraries/LibWeb/WebDriver/ExecuteScript.cpp index 00d17cda6e8..76faf3d0e4b 100644 --- a/Userland/Libraries/LibWeb/WebDriver/ExecuteScript.cpp +++ b/Userland/Libraries/LibWeb/WebDriver/ExecuteScript.cpp @@ -33,6 +33,7 @@ #include #include #include +#include namespace Web::WebDriver { @@ -301,61 +302,14 @@ static JS::ThrowCompletionOr 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 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(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 m_timer; - JS::GCPtr 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 arguments, Optional const& timeout_ms, JS::NonnullGCPtr 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. diff --git a/Userland/Libraries/LibWeb/WebDriver/HeapTimer.cpp b/Userland/Libraries/LibWeb/WebDriver/HeapTimer.cpp new file mode 100644 index 00000000000..954736728f3 --- /dev/null +++ b/Userland/Libraries/LibWeb/WebDriver/HeapTimer.cpp @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2024, Tim Flynn + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include + +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> 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(timeout_ms)); + m_timer->set_single_shot(true); + m_timer->start(); +} + +void HeapTimer::stop() +{ + m_on_timeout = nullptr; + m_timer->stop(); +} + +} diff --git a/Userland/Libraries/LibWeb/WebDriver/HeapTimer.h b/Userland/Libraries/LibWeb/WebDriver/HeapTimer.h new file mode 100644 index 00000000000..69749c6966a --- /dev/null +++ b/Userland/Libraries/LibWeb/WebDriver/HeapTimer.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2024, Tim Flynn + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include +#include + +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> on_timeout); + void stop(); + + bool is_timed_out() const { return m_timed_out; } + +private: + virtual void visit_edges(JS::Cell::Visitor& visitor) override; + + NonnullRefPtr m_timer; + JS::GCPtr> m_on_timeout; + bool m_timed_out { false }; +}; + +}