Bläddra i källkod

LibWeb/HTML: Port Window.requestIdleCallback() to IDL

Linus Groh 2 år sedan
förälder
incheckning
b410804f54

+ 28 - 39
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<RequestIdleCallback::IdleDeadline> deadline) -> JS::Completion {
-        return WebIDL::invoke_callback(const_cast<WebIDL::CallbackType&>(*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<void> Window::initialize_web_interfaces(Badge<WindowEnvironm
 
     define_native_function(realm, "queueMicrotask", queue_microtask, 1, attr);
 
-    define_native_function(realm, "requestIdleCallback", request_idle_callback, 1, attr);
     define_native_function(realm, "cancelIdleCallback", cancel_idle_callback, 1, attr);
 
     define_native_function(realm, "structuredClone", structured_clone, 1, attr);
@@ -1476,6 +1452,34 @@ double Window::device_pixel_ratio() const
     return 1;
 }
 
+// https://w3c.github.io/requestidlecallback/#dom-window-requestidlecallback
+u32 Window::request_idle_callback(WebIDL::CallbackType& callback, RequestIdleCallback::IdleRequestOptions const& options)
+{
+    // 1. Let window be this Window object.
+
+    // 2. Increment the window's idle callback identifier by one.
+    m_idle_callback_identifier++;
+
+    // 3. Let handle be the current value of window's idle callback identifier.
+    auto handle = 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<RequestIdleCallback::IdleDeadline> 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<Selection::Selection> 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::TypeError>(JS::ErrorType::BadArgCountAtLeastOne, "requestIdleCallback");
-    auto* callback_object = TRY(vm.argument(0).to_object(vm));
-    if (!callback_object->is_function())
-        return vm.throw_completion<JS::TypeError>(JS::ErrorType::NotAFunctionNoParam);
-    // FIXME: accept options object
-
-    auto callback = vm.heap().allocate_without_realm<WebIDL::CallbackType>(*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));

+ 3 - 2
Userland/Libraries/LibWeb/HTML/Window.h

@@ -25,6 +25,7 @@
 #include <LibWeb/HTML/Scripting/ImportMap.h>
 #include <LibWeb/HTML/WindowEventHandlers.h>
 #include <LibWeb/HTML/WindowOrWorkerGlobalScope.h>
+#include <LibWeb/RequestIdleCallback/IdleRequest.h>
 
 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<Selection::Selection> get_selection() const;
 
     WebIDL::ExceptionOr<JS::NonnullGCPtr<HighResolutionTime::Performance>> 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 };

+ 4 - 0
Userland/Libraries/LibWeb/HTML/Window.idl

@@ -7,6 +7,7 @@
 #import <HighResolutionTime/Performance.idl>
 #import <HTML/Navigator.idl>
 #import <HTML/WindowOrWorkerGlobalScope.idl>
+#import <RequestIdleCallback/IdleRequest.idl>
 
 // 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();
 

+ 18 - 0
Userland/Libraries/LibWeb/RequestIdleCallback/IdleRequest.h

@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2023, Linus Groh <linusg@serenityos.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#pragma once
+
+#include <AK/Forward.h>
+#include <AK/Types.h>
+
+namespace Web::RequestIdleCallback {
+
+struct IdleRequestOptions {
+    Optional<u32> timeout { 0 };
+};
+
+}

+ 6 - 0
Userland/Libraries/LibWeb/RequestIdleCallback/IdleRequest.idl

@@ -0,0 +1,6 @@
+#import <RequestIdleCallback/IdleDeadline.idl>
+
+dictionary IdleRequestOptions {
+    unsigned long timeout;
+};
+callback IdleRequestCallback = undefined (IdleDeadline deadline);