diff --git a/Userland/Libraries/LibWeb/HTML/EventLoop/EventLoop.cpp b/Userland/Libraries/LibWeb/HTML/EventLoop/EventLoop.cpp
index 0c3d586f9c9..dfcd55c15d9 100644
--- a/Userland/Libraries/LibWeb/HTML/EventLoop/EventLoop.cpp
+++ b/Userland/Libraries/LibWeb/HTML/EventLoop/EventLoop.cpp
@@ -605,4 +605,46 @@ double EventLoop::compute_deadline() const
return deadline;
}
+EventLoop::PauseHandle::PauseHandle(EventLoop& event_loop, JS::Object const& global, HighResolutionTime::DOMHighResTimeStamp time_before_pause)
+ : event_loop(event_loop)
+ , global(global)
+ , time_before_pause(time_before_pause)
+{
+}
+
+EventLoop::PauseHandle::~PauseHandle()
+{
+ event_loop->unpause({}, *global, time_before_pause);
+}
+
+// https://html.spec.whatwg.org/multipage/webappapis.html#pause
+EventLoop::PauseHandle EventLoop::pause()
+{
+ // 1. Let global be the current global object.
+ auto& global = current_principal_global_object();
+
+ // 2. Let timeBeforePause be the current high resolution time given global.
+ auto time_before_pause = HighResolutionTime::current_high_resolution_time(global);
+
+ // 3. If necessary, update the rendering or user interface of any Document or navigable to reflect the current state.
+ if (!m_is_running_rendering_task)
+ update_the_rendering();
+
+ // 4. Wait until the condition goal is met. While a user agent has a paused task, the corresponding event loop must
+ // not run further tasks, and any script in the currently running task must block. User agents should remain
+ // responsive to user input while paused, however, albeit in a reduced capacity since the event loop will not be
+ // doing anything.
+ m_execution_paused = true;
+
+ return PauseHandle { *this, global, time_before_pause };
+}
+
+void EventLoop::unpause(Badge, JS::Object const& global, HighResolutionTime::DOMHighResTimeStamp time_before_pause)
+{
+ m_execution_paused = false;
+
+ // FIXME: 5. Record pause duration given the duration from timeBeforePause to the current high resolution time given global.
+ [[maybe_unused]] auto pause_duration = HighResolutionTime::current_high_resolution_time(global) - time_before_pause;
+}
+
}
diff --git a/Userland/Libraries/LibWeb/HTML/EventLoop/EventLoop.h b/Userland/Libraries/LibWeb/HTML/EventLoop/EventLoop.h
index b743ab6ab40..f33ca7faa99 100644
--- a/Userland/Libraries/LibWeb/HTML/EventLoop/EventLoop.h
+++ b/Userland/Libraries/LibWeb/HTML/EventLoop/EventLoop.h
@@ -7,10 +7,13 @@
#pragma once
#include
+#include
#include
#include
#include
+#include
#include
+#include
namespace Web::HTML {
@@ -18,6 +21,18 @@ class EventLoop : public JS::Cell {
JS_CELL(EventLoop, JS::Cell);
JS_DECLARE_ALLOCATOR(EventLoop);
+ struct PauseHandle {
+ PauseHandle(EventLoop&, JS::Object const& global, HighResolutionTime::DOMHighResTimeStamp);
+ ~PauseHandle();
+
+ AK_MAKE_NONCOPYABLE(PauseHandle);
+ AK_MAKE_NONMOVABLE(PauseHandle);
+
+ JS::NonnullGCPtr event_loop;
+ JS::NonnullGCPtr global;
+ HighResolutionTime::DOMHighResTimeStamp const time_before_pause;
+ };
+
public:
enum class Type {
// https://html.spec.whatwg.org/multipage/webappapis.html#window-event-loop
@@ -71,8 +86,8 @@ public:
double compute_deadline() const;
- // https://html.spec.whatwg.org/multipage/webappapis.html#pause
- void set_execution_paused(bool execution_paused) { m_execution_paused = execution_paused; }
+ [[nodiscard]] PauseHandle pause();
+ void unpause(Badge, JS::Object const& global, HighResolutionTime::DOMHighResTimeStamp);
bool execution_paused() const { return m_execution_paused; }
private:
diff --git a/Userland/Libraries/LibWeb/Page/Page.cpp b/Userland/Libraries/LibWeb/Page/Page.cpp
index d14bfc957ea..08336a847ed 100644
--- a/Userland/Libraries/LibWeb/Page/Page.cpp
+++ b/Userland/Libraries/LibWeb/Page/Page.cpp
@@ -6,7 +6,6 @@
* SPDX-License-Identifier: BSD-2-Clause
*/
-#include
#include
#include
#include
@@ -265,9 +264,7 @@ template
static ResponseType spin_event_loop_until_dialog_closed(PageClient& client, Optional& response, SourceLocation location = SourceLocation::current())
{
auto& event_loop = Web::HTML::current_principal_settings_object().responsible_event_loop();
-
- ScopeGuard guard { [&] { event_loop.set_execution_paused(false); } };
- event_loop.set_execution_paused(true);
+ auto pause_handle = event_loop.pause();
Web::Platform::EventLoopPlugin::the().spin_until(JS::create_heap_function(event_loop.heap(), [&]() {
return response.has_value() || !client.is_connection_open();