From b410804f54b64b7c62624a76d56ae18699e73d8a Mon Sep 17 00:00:00 2001 From: Linus Groh Date: Mon, 6 Mar 2023 23:38:44 +0000 Subject: [PATCH] LibWeb/HTML: Port Window.requestIdleCallback() to IDL --- Userland/Libraries/LibWeb/HTML/Window.cpp | 67 ++++++++----------- Userland/Libraries/LibWeb/HTML/Window.h | 5 +- Userland/Libraries/LibWeb/HTML/Window.idl | 4 ++ .../LibWeb/RequestIdleCallback/IdleRequest.h | 18 +++++ .../RequestIdleCallback/IdleRequest.idl | 6 ++ 5 files changed, 59 insertions(+), 41 deletions(-) create mode 100644 Userland/Libraries/LibWeb/RequestIdleCallback/IdleRequest.h create mode 100644 Userland/Libraries/LibWeb/RequestIdleCallback/IdleRequest.idl diff --git a/Userland/Libraries/LibWeb/HTML/Window.cpp b/Userland/Libraries/LibWeb/HTML/Window.cpp index a1b4024b9cf..f63472e5461 100644 --- a/Userland/Libraries/LibWeb/HTML/Window.cpp +++ b/Userland/Libraries/LibWeb/HTML/Window.cpp @@ -826,29 +826,6 @@ void Window::invoke_idle_callbacks() } } -// https://w3c.github.io/requestidlecallback/#the-requestidlecallback-method -u32 Window::request_idle_callback_impl(WebIDL::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 = JS::make_handle(callback)](JS::NonnullGCPtr deadline) -> JS::Completion { - return WebIDL::invoke_callback(const_cast(*callback), {}, deadline.ptr()); - }; - 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_impl(u32 handle) { @@ -955,7 +932,6 @@ WebIDL::ExceptionOr Window::initialize_web_interfaces(Badge deadline) -> JS::Completion { + return WebIDL::invoke_callback(*callback, {}, deadline.ptr()); + }; + 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. + (void)options; +} + // https://w3c.github.io/selection-api/#dom-window-getselection JS::GCPtr Window::get_selection() const { @@ -1613,21 +1617,6 @@ JS_DEFINE_NATIVE_FUNCTION(Window::queue_microtask) return JS::js_undefined(); } -JS_DEFINE_NATIVE_FUNCTION(Window::request_idle_callback) -{ - auto* impl = TRY(impl_from(vm)); - if (!vm.argument_count()) - return vm.throw_completion(JS::ErrorType::BadArgCountAtLeastOne, "requestIdleCallback"); - auto* callback_object = TRY(vm.argument(0).to_object(vm)); - if (!callback_object->is_function()) - return vm.throw_completion(JS::ErrorType::NotAFunctionNoParam); - // FIXME: accept options object - - auto callback = vm.heap().allocate_without_realm(*callback_object, HTML::incumbent_settings_object()); - - return JS::Value(impl->request_idle_callback_impl(*callback)); -} - JS_DEFINE_NATIVE_FUNCTION(Window::cancel_idle_callback) { auto* impl = TRY(impl_from(vm)); diff --git a/Userland/Libraries/LibWeb/HTML/Window.h b/Userland/Libraries/LibWeb/HTML/Window.h index 4c5ec932237..e0dd30fd57a 100644 --- a/Userland/Libraries/LibWeb/HTML/Window.h +++ b/Userland/Libraries/LibWeb/HTML/Window.h @@ -25,6 +25,7 @@ #include #include #include +#include namespace Web::HTML { @@ -119,7 +120,6 @@ public: void start_an_idle_period(); - u32 request_idle_callback_impl(WebIDL::CallbackType& callback); void cancel_idle_callback_impl(u32); AnimationFrameCallbackDriver& animation_frame_callback_driver() { return m_animation_frame_callback_driver; } @@ -180,6 +180,8 @@ public: i32 outer_height() const; double device_pixel_ratio() const; + u32 request_idle_callback(WebIDL::CallbackType&, RequestIdleCallback::IdleRequestOptions const&); + JS::GCPtr get_selection() const; WebIDL::ExceptionOr> performance(); @@ -262,7 +264,6 @@ private: JS_DECLARE_NATIVE_FUNCTION(queue_microtask); - JS_DECLARE_NATIVE_FUNCTION(request_idle_callback); JS_DECLARE_NATIVE_FUNCTION(cancel_idle_callback); HTML::Location* m_location { nullptr }; diff --git a/Userland/Libraries/LibWeb/HTML/Window.idl b/Userland/Libraries/LibWeb/HTML/Window.idl index 31a4a2f0749..69f3a148159 100644 --- a/Userland/Libraries/LibWeb/HTML/Window.idl +++ b/Userland/Libraries/LibWeb/HTML/Window.idl @@ -7,6 +7,7 @@ #import #import #import +#import // https://html.spec.whatwg.org/multipage/nav-history-apis.html#window [Global=Window, Exposed=Window, LegacyUnenumerableNamedProperties, UseNewAKString] @@ -77,6 +78,9 @@ interface Window : EventTarget { [Replaceable] readonly attribute long outerHeight; [Replaceable] readonly attribute double devicePixelRatio; + // https://w3c.github.io/requestidlecallback/#window_extensions + unsigned long requestIdleCallback(IdleRequestCallback callback, optional IdleRequestOptions options = {}); + // https://w3c.github.io/selection-api/#extensions-to-window-interface Selection? getSelection(); diff --git a/Userland/Libraries/LibWeb/RequestIdleCallback/IdleRequest.h b/Userland/Libraries/LibWeb/RequestIdleCallback/IdleRequest.h new file mode 100644 index 00000000000..daf2b16123f --- /dev/null +++ b/Userland/Libraries/LibWeb/RequestIdleCallback/IdleRequest.h @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2023, Linus Groh + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include + +namespace Web::RequestIdleCallback { + +struct IdleRequestOptions { + Optional timeout { 0 }; +}; + +} diff --git a/Userland/Libraries/LibWeb/RequestIdleCallback/IdleRequest.idl b/Userland/Libraries/LibWeb/RequestIdleCallback/IdleRequest.idl new file mode 100644 index 00000000000..c8f75170a63 --- /dev/null +++ b/Userland/Libraries/LibWeb/RequestIdleCallback/IdleRequest.idl @@ -0,0 +1,6 @@ +#import + +dictionary IdleRequestOptions { + unsigned long timeout; +}; +callback IdleRequestCallback = undefined (IdleDeadline deadline);