summaryrefslogtreecommitdiff
path: root/Userland
diff options
context:
space:
mode:
authorSimon Wanner <skyrising@pvpctutorials.de>2022-04-01 19:46:29 +0200
committerLinus Groh <mail@linusgroh.de>2022-04-02 23:52:25 +0100
commitea9857a423a18639dae04159963a2d00d8914d94 (patch)
tree338fe509490387a2c2b8c186aac2381503061607 /Userland
parent836d2ff259fd2f78835e41578b234f20c7b572bf (diff)
downloadserenity-ea9857a423a18639dae04159963a2d00d8914d94.zip
LibWeb: Add the requestIdleCallback/cancelIdleCallback API
Diffstat (limited to 'Userland')
-rw-r--r--Userland/Libraries/LibWeb/Bindings/WindowObject.cpp28
-rw-r--r--Userland/Libraries/LibWeb/Bindings/WindowObject.h3
-rw-r--r--Userland/Libraries/LibWeb/HTML/Window.cpp47
-rw-r--r--Userland/Libraries/LibWeb/HTML/Window.h3
4 files changed, 80 insertions, 1 deletions
diff --git a/Userland/Libraries/LibWeb/Bindings/WindowObject.cpp b/Userland/Libraries/LibWeb/Bindings/WindowObject.cpp
index f22d6cb87b..edf89af246 100644
--- a/Userland/Libraries/LibWeb/Bindings/WindowObject.cpp
+++ b/Userland/Libraries/LibWeb/Bindings/WindowObject.cpp
@@ -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())
diff --git a/Userland/Libraries/LibWeb/Bindings/WindowObject.h b/Userland/Libraries/LibWeb/Bindings/WindowObject.h
index 04a662b5b0..8f99b77d16 100644
--- a/Userland/Libraries/LibWeb/Bindings/WindowObject.h
+++ b/Userland/Libraries/LibWeb/Bindings/WindowObject.h
@@ -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) \
diff --git a/Userland/Libraries/LibWeb/HTML/Window.cpp b/Userland/Libraries/LibWeb/HTML/Window.cpp
index 33b9a89841..4429d17c3c 100644
--- a/Userland/Libraries/LibWeb/HTML/Window.cpp
+++ b/Userland/Libraries/LibWeb/HTML/Window.cpp
@@ -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;
+ });
+}
+
}
diff --git a/Userland/Libraries/LibWeb/HTML/Window.h b/Userland/Libraries/LibWeb/HTML/Window.h
index ea931ca791..ba4ec8afab 100644
--- a/Userland/Libraries/LibWeb/HTML/Window.h
+++ b/Userland/Libraries/LibWeb/HTML/Window.h
@@ -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&);