Quellcode durchsuchen

LibWeb: Implement PromiseRejectionEvent

This paves the way for the rejectionhandled and unhandledrejection
events.

It's also used by core-js (in browsers, at least) to check whether
Promise needs to be polyfilled, so adding it should allow more websites
to leverage LibJS's native Promise implementation :^)
Linus Groh vor 3 Jahren
Ursprung
Commit
f952db1a1f

+ 3 - 0
Userland/Libraries/LibWeb/Bindings/EventWrapperFactory.cpp

@@ -15,6 +15,7 @@
 #include <LibWeb/Bindings/MouseEventWrapper.h>
 #include <LibWeb/Bindings/PageTransitionEventWrapper.h>
 #include <LibWeb/Bindings/ProgressEventWrapper.h>
+#include <LibWeb/Bindings/PromiseRejectionEventWrapper.h>
 #include <LibWeb/Bindings/SubmitEventWrapper.h>
 
 namespace Web::Bindings {
@@ -31,6 +32,8 @@ EventWrapper* wrap(JS::GlobalObject& global_object, DOM::Event& event)
         return static_cast<MessageEventWrapper*>(wrap_impl(global_object, static_cast<HTML::MessageEvent&>(event)));
     if (is<HTML::PageTransitionEvent>(event))
         return static_cast<PageTransitionEventWrapper*>(wrap_impl(global_object, static_cast<HTML::PageTransitionEvent&>(event)));
+    if (is<HTML::PromiseRejectionEvent>(event))
+        return static_cast<PromiseRejectionEventWrapper*>(wrap_impl(global_object, static_cast<HTML::PromiseRejectionEvent&>(event)));
     if (is<HTML::SubmitEvent>(event))
         return static_cast<SubmitEventWrapper*>(wrap_impl(global_object, static_cast<HTML::SubmitEvent&>(event)));
     if (is<UIEvents::KeyboardEvent>(event))

+ 3 - 0
Userland/Libraries/LibWeb/Bindings/WindowObjectHelper.h

@@ -231,6 +231,8 @@
 #include <LibWeb/Bindings/ProcessingInstructionPrototype.h>
 #include <LibWeb/Bindings/ProgressEventConstructor.h>
 #include <LibWeb/Bindings/ProgressEventPrototype.h>
+#include <LibWeb/Bindings/PromiseRejectionEventConstructor.h>
+#include <LibWeb/Bindings/PromiseRejectionEventPrototype.h>
 #include <LibWeb/Bindings/RangeConstructor.h>
 #include <LibWeb/Bindings/RangePrototype.h>
 #include <LibWeb/Bindings/ResizeObserverConstructor.h>
@@ -396,6 +398,7 @@
     ADD_WINDOW_OBJECT_INTERFACE(PerformanceTiming)         \
     ADD_WINDOW_OBJECT_INTERFACE(ProcessingInstruction)     \
     ADD_WINDOW_OBJECT_INTERFACE(ProgressEvent)             \
+    ADD_WINDOW_OBJECT_INTERFACE(PromiseRejectionEvent)     \
     ADD_WINDOW_OBJECT_INTERFACE(Range)                     \
     ADD_WINDOW_OBJECT_INTERFACE(ResizeObserver)            \
     ADD_WINDOW_OBJECT_INTERFACE(Screen)                    \

+ 1 - 0
Userland/Libraries/LibWeb/CMakeLists.txt

@@ -468,6 +468,7 @@ libweb_js_wrapper(HTML/MessageChannel)
 libweb_js_wrapper(HTML/MessageEvent)
 libweb_js_wrapper(HTML/MessagePort)
 libweb_js_wrapper(HTML/PageTransitionEvent)
+libweb_js_wrapper(HTML/PromiseRejectionEvent)
 libweb_js_wrapper(HTML/SubmitEvent)
 libweb_js_wrapper(HTML/WebSocket)
 libweb_js_wrapper(HighResolutionTime/Performance)

+ 2 - 0
Userland/Libraries/LibWeb/Forward.h

@@ -195,6 +195,7 @@ class MessageChannel;
 class MessageEvent;
 class MessagePort;
 class PageTransitionEvent;
+class PromiseRejectionEvent;
 class SubmitEvent;
 class WebSocket;
 }
@@ -400,6 +401,7 @@ class PerformanceTimingWrapper;
 class PerformanceWrapper;
 class ProcessingInstructionWrapper;
 class ProgressEventWrapper;
+class PromiseRejectionEventWrapper;
 class ResizeObserverWrapper;
 class ScreenWrapper;
 class ScriptExecutionContext;

+ 52 - 0
Userland/Libraries/LibWeb/HTML/PromiseRejectionEvent.h

@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2021, Linus Groh <linusg@serenityos.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#pragma once
+
+#include <LibJS/Runtime/Promise.h>
+#include <LibJS/Runtime/Value.h>
+#include <LibWeb/DOM/Event.h>
+
+namespace Web::HTML {
+
+struct PromiseRejectionEventInit : public DOM::EventInit {
+    JS::Handle<JS::Promise> promise;
+    JS::Value reason;
+};
+
+class PromiseRejectionEvent : public DOM::Event {
+public:
+    using WrapperType = Bindings::PromiseRejectionEventWrapper;
+
+    static NonnullRefPtr<PromiseRejectionEvent> create(FlyString const& event_name, PromiseRejectionEventInit const& event_init = {})
+    {
+        return adopt_ref(*new PromiseRejectionEvent(event_name, event_init));
+    }
+    static NonnullRefPtr<PromiseRejectionEvent> create_with_global_object(Bindings::WindowObject&, FlyString const& event_name, PromiseRejectionEventInit const& event_init)
+    {
+        return PromiseRejectionEvent::create(event_name, event_init);
+    }
+
+    virtual ~PromiseRejectionEvent() override = default;
+
+    // Needs to return a pointer for the generated JS bindings to work.
+    JS::Promise const* promise() const { return m_promise.cell(); }
+    JS::Value reason() const { return m_reason; }
+
+protected:
+    PromiseRejectionEvent(FlyString const& event_name, PromiseRejectionEventInit const& event_init)
+        : DOM::Event(event_name, event_init)
+        , m_promise(event_init.promise)
+        , m_reason(event_init.reason)
+    {
+    }
+
+    JS::Handle<JS::Promise> m_promise;
+    // FIXME: Protect this from GC! Currently we have no handle for arbitrary JS::Value.
+    JS::Value m_reason;
+};
+
+}

+ 14 - 0
Userland/Libraries/LibWeb/HTML/PromiseRejectionEvent.idl

@@ -0,0 +1,14 @@
+#import <DOM/Event.idl>
+
+[Exposed=(Window,Worker)]
+interface PromiseRejectionEvent : Event {
+    constructor(DOMString type, PromiseRejectionEventInit eventInitDict);
+
+    readonly attribute Promise<any> promise;
+    readonly attribute any reason;
+};
+
+dictionary PromiseRejectionEventInit : EventInit {
+    required Promise<any> promise;
+    any reason;
+};