mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-25 00:50:22 +00:00
LibWeb: Implement pausing the event loop a bit closer to the spec
Namely, this is to update the rendering before pausing the event loop.
This commit is contained in:
parent
5431db8c1c
commit
f4111ef1e1
Notes:
github-actions[bot]
2024-11-06 09:51:32 +00:00
Author: https://github.com/trflynn89 Commit: https://github.com/LadybirdBrowser/ladybird/commit/f4111ef1e1e Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/2178
3 changed files with 60 additions and 6 deletions
|
@ -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<PauseHandle>, 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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -7,10 +7,13 @@
|
|||
#pragma once
|
||||
|
||||
#include <AK/Function.h>
|
||||
#include <AK/Noncopyable.h>
|
||||
#include <AK/WeakPtr.h>
|
||||
#include <LibCore/Forward.h>
|
||||
#include <LibJS/Forward.h>
|
||||
#include <LibJS/Heap/GCPtr.h>
|
||||
#include <LibWeb/HTML/EventLoop/TaskQueue.h>
|
||||
#include <LibWeb/HighResolutionTime/DOMHighResTimeStamp.h>
|
||||
|
||||
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<EventLoop> event_loop;
|
||||
JS::NonnullGCPtr<JS::Object const> 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<PauseHandle>, JS::Object const& global, HighResolutionTime::DOMHighResTimeStamp);
|
||||
bool execution_paused() const { return m_execution_paused; }
|
||||
|
||||
private:
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <AK/ScopeGuard.h>
|
||||
#include <AK/SourceLocation.h>
|
||||
#include <LibIPC/Decoder.h>
|
||||
#include <LibIPC/Encoder.h>
|
||||
|
@ -265,9 +264,7 @@ template<typename ResponseType>
|
|||
static ResponseType spin_event_loop_until_dialog_closed(PageClient& client, Optional<ResponseType>& 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();
|
||||
|
|
Loading…
Reference in a new issue