mirror of
https://github.com/RGBCube/serenity
synced 2025-05-31 04:48:14 +00:00
LibWeb: Implement the infrastructure necessary for requestIdleCallback
This includes a bug fix for the event loop processing steps which has not been merged yet: https://github.com/whatwg/html/pull/7768
This commit is contained in:
parent
73da139cd7
commit
836d2ff259
6 changed files with 209 additions and 31 deletions
|
@ -27,6 +27,7 @@
|
|||
#include <LibWeb/HighResolutionTime/Performance.h>
|
||||
#include <LibWeb/Layout/InitialContainingBlock.h>
|
||||
#include <LibWeb/Page/Page.h>
|
||||
#include <LibWeb/RequestIdleCallback/IdleDeadline.h>
|
||||
#include <LibWeb/Selection/Selection.h>
|
||||
|
||||
namespace Web::HTML {
|
||||
|
@ -107,6 +108,20 @@ void run_animation_frame_callbacks(DOM::Document&, double)
|
|||
request_animation_frame_driver().run();
|
||||
}
|
||||
|
||||
class IdleCallback : public RefCounted<IdleCallback> {
|
||||
public:
|
||||
explicit IdleCallback(Function<JS::Completion(NonnullRefPtr<RequestIdleCallback::IdleDeadline>)> handler)
|
||||
: m_handler(move(handler))
|
||||
{
|
||||
}
|
||||
~IdleCallback() = default;
|
||||
|
||||
JS::Completion invoke(NonnullRefPtr<RequestIdleCallback::IdleDeadline> deadline) { return m_handler(move(deadline)); }
|
||||
|
||||
private:
|
||||
Function<JS::Completion(NonnullRefPtr<RequestIdleCallback::IdleDeadline>)> m_handler;
|
||||
};
|
||||
|
||||
NonnullRefPtr<Window> Window::create_with_document(DOM::Document& document)
|
||||
{
|
||||
return adopt_ref(*new Window(document));
|
||||
|
@ -637,4 +652,54 @@ void Window::set_name(String const& name)
|
|||
browsing_context()->set_name(name);
|
||||
}
|
||||
|
||||
// https://w3c.github.io/requestidlecallback/#start-an-idle-period-algorithm
|
||||
void Window::start_an_idle_period()
|
||||
{
|
||||
// 1. Optionally, if the user agent determines the idle period should be delayed, return from this algorithm.
|
||||
if (!wrapper())
|
||||
return;
|
||||
// 2. Let pending_list be window's list of idle request callbacks.
|
||||
auto& pending_list = m_idle_request_callbacks;
|
||||
// 3. Let run_list be window's list of runnable idle callbacks.
|
||||
auto& run_list = m_runnable_idle_callbacks;
|
||||
run_list.extend(pending_list);
|
||||
// 4. Clear pending_list.
|
||||
pending_list.clear();
|
||||
|
||||
// FIXME: This might not agree with the spec, but currently we use 100% CPU if we keep queueing tasks
|
||||
if (run_list.is_empty())
|
||||
return;
|
||||
|
||||
// 5. Queue a task on the queue associated with the idle-task task source,
|
||||
// which performs the steps defined in the invoke idle callbacks algorithm with window and getDeadline as parameters.
|
||||
HTML::queue_global_task(HTML::Task::Source::IdleTask, *wrapper(), [window = NonnullRefPtr(*this)]() mutable {
|
||||
window->invoke_idle_callbacks();
|
||||
});
|
||||
}
|
||||
|
||||
// https://w3c.github.io/requestidlecallback/#invoke-idle-callbacks-algorithm
|
||||
void Window::invoke_idle_callbacks()
|
||||
{
|
||||
auto& event_loop = main_thread_event_loop();
|
||||
// 1. If the user-agent believes it should end the idle period early due to newly scheduled high-priority work, return from the algorithm.
|
||||
// 2. Let now be the current time.
|
||||
auto now = event_loop.unsafe_shared_current_time();
|
||||
// 3. If now is less than the result of calling getDeadline and the window's list of runnable idle callbacks is not empty:
|
||||
if (now < event_loop.compute_deadline() && !m_runnable_idle_callbacks.is_empty()) {
|
||||
// 1. Pop the top callback from window's list of runnable idle callbacks.
|
||||
auto callback = m_runnable_idle_callbacks.take_first();
|
||||
// 2. Let deadlineArg be a new IdleDeadline whose [get deadline time algorithm] is getDeadline.
|
||||
auto deadline_arg = RequestIdleCallback::IdleDeadline::create();
|
||||
// 3. Call callback with deadlineArg as its argument. If an uncaught runtime script error occurs, then report the exception.
|
||||
auto result = callback->invoke(deadline_arg);
|
||||
if (result.is_error())
|
||||
HTML::report_exception(result);
|
||||
// 4. If window's list of runnable idle callbacks is not empty, queue a task which performs the steps
|
||||
// in the invoke idle callbacks algorithm with getDeadline and window as a parameters and return from this algorithm
|
||||
HTML::queue_global_task(HTML::Task::Source::IdleTask, *wrapper(), [window = NonnullRefPtr(*this)]() mutable {
|
||||
window->invoke_idle_callbacks();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue