Browse Source

LibWeb: Expose the GlobalEventHandlers mixin on the Window object

We now expose all the `onfoo` event handler attributes on the window
object. This makes `window.onload = ...` actually work. :^)
Andreas Kling 3 years ago
parent
commit
635ab6db0b

+ 41 - 0
Userland/Libraries/LibWeb/Bindings/WindowObject.cpp

@@ -19,6 +19,7 @@
 #include <LibWeb/Bindings/EventTargetPrototype.h>
 #include <LibWeb/Bindings/EventWrapper.h>
 #include <LibWeb/Bindings/EventWrapperFactory.h>
+#include <LibWeb/Bindings/ExceptionOrUtils.h>
 #include <LibWeb/Bindings/HistoryWrapper.h>
 #include <LibWeb/Bindings/LocationObject.h>
 #include <LibWeb/Bindings/MediaQueryListWrapper.h>
@@ -31,6 +32,7 @@
 #include <LibWeb/DOM/Document.h>
 #include <LibWeb/DOM/Event.h>
 #include <LibWeb/DOM/Window.h>
+#include <LibWeb/HTML/EventHandler.h>
 #include <LibWeb/Origin.h>
 #include <LibWeb/Page/BrowsingContext.h>
 #include <LibWeb/Page/Page.h>
@@ -104,6 +106,12 @@ void WindowObject::initialize_global_object()
     // WebAssembly "namespace"
     define_direct_property("WebAssembly", heap().allocate<WebAssemblyObject>(*this, *this), JS::Attribute::Enumerable | JS::Attribute::Configurable);
 
+    // HTML::GlobalEventHandlers
+#define __ENUMERATE(attribute, event_name) \
+    define_native_accessor(#attribute, attribute##_getter, attribute##_setter, attr);
+    ENUMERATE_GLOBAL_EVENT_HANDLERS(__ENUMERATE);
+#undef __ENUMERATE
+
     ADD_WINDOW_OBJECT_INTERFACES;
 }
 
@@ -674,4 +682,37 @@ JS_DEFINE_NATIVE_FUNCTION(WindowObject::history_getter)
     return wrap(global_object, impl->associated_document().history());
 }
 
+#define __ENUMERATE(attribute, event_name)                              \
+    JS_DEFINE_NATIVE_FUNCTION(WindowObject::attribute##_getter)         \
+    {                                                                   \
+        auto* impl = impl_from(vm, global_object);                      \
+        if (!impl)                                                      \
+            return {};                                                  \
+        auto retval = impl->attribute();                                \
+        if (retval.callback.is_null())                                  \
+            return JS::js_null();                                       \
+        return retval.callback.cell();                                  \
+    }                                                                   \
+    JS_DEFINE_NATIVE_FUNCTION(WindowObject::attribute##_setter)         \
+    {                                                                   \
+        auto* impl = impl_from(vm, global_object);                      \
+        if (!impl)                                                      \
+            return {};                                                  \
+        auto value = vm.argument(0);                                    \
+        HTML::EventHandler cpp_value;                                   \
+        if (value.is_function()) {                                      \
+            cpp_value.callback = JS::make_handle(&value.as_function()); \
+        } else if (value.is_string()) {                                 \
+            cpp_value.string = value.as_string().string();              \
+        } else {                                                        \
+            return {};                                                  \
+        }                                                               \
+        (void)throw_dom_exception_if_needed(vm, global_object, [&] {    \
+            return impl->set_##attribute(cpp_value);                    \
+        });                                                             \
+        return {};                                                      \
+    }
+ENUMERATE_GLOBAL_EVENT_HANDLERS(__ENUMERATE)
+#undef __ENUMERATE
+
 }

+ 7 - 0
Userland/Libraries/LibWeb/Bindings/WindowObject.h

@@ -11,6 +11,7 @@
 #include <AK/Weakable.h>
 #include <LibJS/Runtime/GlobalObject.h>
 #include <LibWeb/Forward.h>
+#include <LibWeb/HTML/GlobalEventHandlers.h>
 
 namespace Web {
 namespace Bindings {
@@ -98,6 +99,12 @@ private:
     JS_DECLARE_NATIVE_FUNCTION(get_computed_style);
     JS_DECLARE_NATIVE_FUNCTION(match_media);
 
+#define __ENUMERATE(attribute, event_name)          \
+    JS_DECLARE_NATIVE_FUNCTION(attribute##_getter); \
+    JS_DECLARE_NATIVE_FUNCTION(attribute##_setter);
+    ENUMERATE_GLOBAL_EVENT_HANDLERS(__ENUMERATE);
+#undef __ENUMERATE
+
     NonnullRefPtr<DOM::Window> m_impl;
 
     LocationObject* m_location_object { nullptr };

+ 6 - 1
Userland/Libraries/LibWeb/DOM/Window.h

@@ -16,6 +16,7 @@
 #include <LibWeb/CSS/Screen.h>
 #include <LibWeb/DOM/Event.h>
 #include <LibWeb/DOM/EventTarget.h>
+#include <LibWeb/HTML/GlobalEventHandlers.h>
 
 namespace Web::DOM {
 
@@ -23,7 +24,8 @@ class RequestAnimationFrameCallback;
 
 class Window final
     : public RefCounted<Window>
-    , public EventTarget {
+    , public EventTarget
+    , public HTML::GlobalEventHandlers {
 public:
     static NonnullRefPtr<Window> create_with_document(Document&);
     ~Window();
@@ -81,6 +83,9 @@ public:
 private:
     explicit Window(Document&);
 
+    // ^HTML::GlobalEventHandlers
+    virtual DOM::EventTarget& global_event_handlers_to_event_target() override { return *this; }
+
     // https://html.spec.whatwg.org/multipage/window-object.html#concept-document-window
     WeakPtr<Document> m_associated_document;