mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-21 23:20:20 +00:00
LibWeb: Add the requestIdleCallback/cancelIdleCallback API
This commit is contained in:
parent
836d2ff259
commit
ea9857a423
Notes:
sideshowbarker
2024-07-17 14:36:12 +09:00
Author: https://github.com/skyrising Commit: https://github.com/SerenityOS/serenity/commit/ea9857a423 Pull-request: https://github.com/SerenityOS/serenity/pull/13413 Reviewed-by: https://github.com/linusg
4 changed files with 80 additions and 1 deletions
|
@ -91,6 +91,9 @@ void WindowObject::initialize_global_object()
|
|||
|
||||
define_native_function("queueMicrotask", queue_microtask, 1, attr);
|
||||
|
||||
define_native_function("requestIdleCallback", request_idle_callback, 1, attr);
|
||||
define_native_function("cancelIdleCallback", cancel_idle_callback, 1, attr);
|
||||
|
||||
define_native_function("getComputedStyle", get_computed_style, 1, attr);
|
||||
define_native_function("matchMedia", match_media, 1, attr);
|
||||
define_native_function("getSelection", get_selection, 0, attr);
|
||||
|
@ -333,6 +336,31 @@ JS_DEFINE_NATIVE_FUNCTION(WindowObject::queue_microtask)
|
|||
return JS::js_undefined();
|
||||
}
|
||||
|
||||
JS_DEFINE_NATIVE_FUNCTION(WindowObject::request_idle_callback)
|
||||
{
|
||||
auto* impl = TRY(impl_from(vm, global_object));
|
||||
if (!vm.argument_count())
|
||||
return vm.throw_completion<JS::TypeError>(global_object, JS::ErrorType::BadArgCountAtLeastOne, "requestIdleCallback");
|
||||
auto* callback_object = TRY(vm.argument(0).to_object(global_object));
|
||||
if (!callback_object->is_function())
|
||||
return vm.throw_completion<JS::TypeError>(global_object, JS::ErrorType::NotAFunctionNoParam);
|
||||
// FIXME: accept options object
|
||||
|
||||
auto callback = adopt_own(*new Bindings::CallbackType(JS::make_handle(callback_object), HTML::incumbent_settings_object()));
|
||||
|
||||
return JS::Value(impl->request_idle_callback(move(callback)));
|
||||
}
|
||||
|
||||
JS_DEFINE_NATIVE_FUNCTION(WindowObject::cancel_idle_callback)
|
||||
{
|
||||
auto* impl = TRY(impl_from(vm, global_object));
|
||||
if (!vm.argument_count())
|
||||
return vm.throw_completion<JS::TypeError>(global_object, JS::ErrorType::BadArgCountOne, "cancelIdleCallback");
|
||||
auto id = TRY(vm.argument(0).to_u32(global_object));
|
||||
impl->cancel_idle_callback(id);
|
||||
return JS::js_undefined();
|
||||
}
|
||||
|
||||
JS_DEFINE_NATIVE_FUNCTION(WindowObject::atob)
|
||||
{
|
||||
if (!vm.argument_count())
|
||||
|
|
|
@ -131,6 +131,9 @@ private:
|
|||
|
||||
JS_DECLARE_NATIVE_FUNCTION(queue_microtask);
|
||||
|
||||
JS_DECLARE_NATIVE_FUNCTION(request_idle_callback);
|
||||
JS_DECLARE_NATIVE_FUNCTION(cancel_idle_callback);
|
||||
|
||||
JS_DECLARE_NATIVE_FUNCTION(crypto_getter);
|
||||
|
||||
#define __ENUMERATE(attribute, event_name) \
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include <LibJS/Runtime/AbstractOperations.h>
|
||||
#include <LibJS/Runtime/FunctionObject.h>
|
||||
#include <LibWeb/Bindings/IDLAbstractOperations.h>
|
||||
#include <LibWeb/Bindings/IdleDeadlineWrapper.h>
|
||||
#include <LibWeb/CSS/Parser/Parser.h>
|
||||
#include <LibWeb/CSS/ResolvedCSSStyleDeclaration.h>
|
||||
#include <LibWeb/Crypto/Crypto.h>
|
||||
|
@ -110,16 +111,19 @@ void run_animation_frame_callbacks(DOM::Document&, double)
|
|||
|
||||
class IdleCallback : public RefCounted<IdleCallback> {
|
||||
public:
|
||||
explicit IdleCallback(Function<JS::Completion(NonnullRefPtr<RequestIdleCallback::IdleDeadline>)> handler)
|
||||
explicit IdleCallback(Function<JS::Completion(NonnullRefPtr<RequestIdleCallback::IdleDeadline>)> handler, u32 handle)
|
||||
: m_handler(move(handler))
|
||||
, m_handle(handle)
|
||||
{
|
||||
}
|
||||
~IdleCallback() = default;
|
||||
|
||||
JS::Completion invoke(NonnullRefPtr<RequestIdleCallback::IdleDeadline> deadline) { return m_handler(move(deadline)); }
|
||||
u32 handle() const { return m_handle; }
|
||||
|
||||
private:
|
||||
Function<JS::Completion(NonnullRefPtr<RequestIdleCallback::IdleDeadline>)> m_handler;
|
||||
u32 m_handle { 0 };
|
||||
};
|
||||
|
||||
NonnullRefPtr<Window> Window::create_with_document(DOM::Document& document)
|
||||
|
@ -702,4 +706,45 @@ void Window::invoke_idle_callbacks()
|
|||
}
|
||||
}
|
||||
|
||||
// https://w3c.github.io/requestidlecallback/#the-requestidlecallback-method
|
||||
u32 Window::request_idle_callback(NonnullOwnPtr<Bindings::CallbackType> callback)
|
||||
{
|
||||
// 1. Let window be this Window object.
|
||||
auto& window = *this;
|
||||
// 2. Increment the window's idle callback identifier by one.
|
||||
window.m_idle_callback_identifier++;
|
||||
// 3. Let handle be the current value of window's idle callback identifier.
|
||||
auto handle = window.m_idle_callback_identifier;
|
||||
// 4. Push callback to the end of window's list of idle request callbacks, associated with handle.
|
||||
auto handler = [callback = move(callback)](NonnullRefPtr<RequestIdleCallback::IdleDeadline> deadline) -> JS::Completion {
|
||||
auto& global_object = callback->callback.cell()->global_object();
|
||||
auto* wrapped_deadline = Bindings::wrap(global_object, *deadline);
|
||||
return Bindings::IDL::invoke_callback(const_cast<Bindings::CallbackType&>(*callback), {}, JS::Value(wrapped_deadline));
|
||||
};
|
||||
window.m_idle_request_callbacks.append(adopt_ref(*new IdleCallback(move(handler), handle)));
|
||||
// 5. Return handle and then continue running this algorithm asynchronously.
|
||||
return handle;
|
||||
// FIXME: 6. If the timeout property is present in options and has a positive value:
|
||||
// FIXME: 1. Wait for timeout milliseconds.
|
||||
// FIXME: 2. Wait until all invocations of this algorithm, whose timeout added to their posted time occurred before this one's, have completed.
|
||||
// FIXME: 3. Optionally, wait a further user-agent defined length of time.
|
||||
// FIXME: 4. Queue a task on the queue associated with the idle-task task source, which performs the invoke idle callback timeout algorithm, passing handle and window as arguments.
|
||||
}
|
||||
|
||||
// https://w3c.github.io/requestidlecallback/#the-cancelidlecallback-method
|
||||
void Window::cancel_idle_callback(u32 handle)
|
||||
{
|
||||
// 1. Let window be this Window object.
|
||||
auto& window = *this;
|
||||
// 2. Find the entry in either the window's list of idle request callbacks or list of runnable idle callbacks
|
||||
// that is associated with the value handle.
|
||||
// 3. If there is such an entry, remove it from both window's list of idle request callbacks and the list of runnable idle callbacks.
|
||||
window.m_idle_request_callbacks.remove_first_matching([handle](auto& callback) {
|
||||
return callback->handle() == handle;
|
||||
});
|
||||
window.m_runnable_idle_callbacks.remove_first_matching([handle](auto& callback) {
|
||||
return callback->handle() == handle;
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -119,6 +119,9 @@ public:
|
|||
|
||||
void start_an_idle_period();
|
||||
|
||||
u32 request_idle_callback(NonnullOwnPtr<Bindings::CallbackType> callback);
|
||||
void cancel_idle_callback(u32);
|
||||
|
||||
private:
|
||||
explicit Window(DOM::Document&);
|
||||
|
||||
|
|
Loading…
Reference in a new issue