From 3e8c8b185ee50d38f46472fe97dc422c11d7917c Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Sun, 17 Nov 2024 21:54:03 +0100 Subject: [PATCH] LibWeb: Use WindowProxy instead of Window in UI Events IDL I believe this is an error in the UI Events spec, and it should be updated to match the HTML spec (which uses WindowProxy everywhere). This fixes a bunch of issues already covered by existing WPT tests. Spec bug: https://github.com/w3c/uievents/issues/388 Note that WebKit has been using WindowProxy instead of Window in UI Events IDL since 2018: https://github.com/WebKit/WebKit/commit/816158b4aa33e65f8ffa931ad17453883f91818a --- Libraries/LibWeb/HTML/Focus.cpp | 2 +- Libraries/LibWeb/Page/DragAndDropEventHandler.cpp | 2 +- Libraries/LibWeb/UIEvents/CompositionEvent.cpp | 2 +- Libraries/LibWeb/UIEvents/CompositionEvent.h | 2 +- Libraries/LibWeb/UIEvents/CompositionEvent.idl | 2 +- Libraries/LibWeb/UIEvents/KeyboardEvent.cpp | 2 +- Libraries/LibWeb/UIEvents/KeyboardEvent.h | 2 +- Libraries/LibWeb/UIEvents/KeyboardEvent.idl | 2 +- Libraries/LibWeb/UIEvents/MouseEvent.cpp | 2 +- Libraries/LibWeb/UIEvents/MouseEvent.h | 2 +- Libraries/LibWeb/UIEvents/MouseEvent.idl | 2 +- Libraries/LibWeb/UIEvents/TextEvent.cpp | 2 +- Libraries/LibWeb/UIEvents/TextEvent.h | 2 +- Libraries/LibWeb/UIEvents/TextEvent.idl | 2 +- Libraries/LibWeb/UIEvents/UIEvent.cpp | 1 + Libraries/LibWeb/UIEvents/UIEvent.h | 8 ++++---- Libraries/LibWeb/UIEvents/UIEvent.idl | 6 +++--- .../LibWeb/BindingsGenerator/IDLGenerators.cpp | 1 + .../dom/events/Event-init-while-dispatching.txt | 5 ++--- .../dom/events/Event-subclasses-constructors.txt | 15 +++++++-------- 20 files changed, 32 insertions(+), 32 deletions(-) diff --git a/Libraries/LibWeb/HTML/Focus.cpp b/Libraries/LibWeb/HTML/Focus.cpp index 9c50691d6d6..5512eb25df0 100644 --- a/Libraries/LibWeb/HTML/Focus.cpp +++ b/Libraries/LibWeb/HTML/Focus.cpp @@ -27,7 +27,7 @@ static void fire_a_focus_event(GC::Ptr focus_event_target, GC: // object, and the composed flag set. UIEvents::FocusEventInit focus_event_init {}; focus_event_init.related_target = related_focus_target; - focus_event_init.view = verify_cast(focus_event_target->realm().global_object()); + focus_event_init.view = verify_cast(focus_event_target->realm().global_object()).window(); auto focus_event = UIEvents::FocusEvent::create(focus_event_target->realm(), event_name, focus_event_init); // AD-HOC: support bubbling focus events, used for focusin & focusout. diff --git a/Libraries/LibWeb/Page/DragAndDropEventHandler.cpp b/Libraries/LibWeb/Page/DragAndDropEventHandler.cpp index 92c919f0834..452f77cd6b3 100644 --- a/Libraries/LibWeb/Page/DragAndDropEventHandler.cpp +++ b/Libraries/LibWeb/Page/DragAndDropEventHandler.cpp @@ -561,7 +561,7 @@ GC::Ref DragAndDropEventHandler::fire_a_drag_and_drop_event( if (target) { auto& window = static_cast(HTML::relevant_global_object(*target)); - event_init.view = window; + event_init.view = window.window(); } // If e is not dragleave or dragend, then initialize event's cancelable attribute to true. diff --git a/Libraries/LibWeb/UIEvents/CompositionEvent.cpp b/Libraries/LibWeb/UIEvents/CompositionEvent.cpp index 150d5c57700..93c8e19e087 100644 --- a/Libraries/LibWeb/UIEvents/CompositionEvent.cpp +++ b/Libraries/LibWeb/UIEvents/CompositionEvent.cpp @@ -37,7 +37,7 @@ void CompositionEvent::initialize(JS::Realm& realm) } // https://w3c.github.io/uievents/#dom-compositionevent-initcompositionevent -void CompositionEvent::init_composition_event(String const& type, bool bubbles, bool cancelable, HTML::Window* view, String const& data) +void CompositionEvent::init_composition_event(String const& type, bool bubbles, bool cancelable, GC::Ptr view, String const& data) { // Initializes attributes of a CompositionEvent object. This method has the same behavior as UIEvent.initUIEvent(). // The value of detail remains undefined. diff --git a/Libraries/LibWeb/UIEvents/CompositionEvent.h b/Libraries/LibWeb/UIEvents/CompositionEvent.h index 86edff9fe0b..f2118a0620b 100644 --- a/Libraries/LibWeb/UIEvents/CompositionEvent.h +++ b/Libraries/LibWeb/UIEvents/CompositionEvent.h @@ -27,7 +27,7 @@ public: // https://w3c.github.io/uievents/#dom-compositionevent-data String data() const { return m_data; } - void init_composition_event(String const& type, bool bubbles, bool cancelable, HTML::Window* view, String const& data); + void init_composition_event(String const& type, bool bubbles, bool cancelable, GC::Ptr view, String const& data); private: CompositionEvent(JS::Realm&, FlyString const& event_name, CompositionEventInit const&); diff --git a/Libraries/LibWeb/UIEvents/CompositionEvent.idl b/Libraries/LibWeb/UIEvents/CompositionEvent.idl index 885b1a1a24c..f73b6779665 100644 --- a/Libraries/LibWeb/UIEvents/CompositionEvent.idl +++ b/Libraries/LibWeb/UIEvents/CompositionEvent.idl @@ -8,7 +8,7 @@ interface CompositionEvent : UIEvent { // https://w3c.github.io/uievents/#dom-compositionevent-initcompositionevent // FIXME: The spec uses WindowProxy rather than Window (see https://github.com/w3c/uievents/pull/379). - undefined initCompositionEvent(DOMString typeArg, optional boolean bubblesArg = false, optional boolean cancelableArg = false, optional Window? viewArg = null, optional DOMString dataArg = ""); + undefined initCompositionEvent(DOMString typeArg, optional boolean bubblesArg = false, optional boolean cancelableArg = false, optional WindowProxy? viewArg = null, optional DOMString dataArg = ""); }; // https://w3c.github.io/uievents/#dictdef-compositioneventinit diff --git a/Libraries/LibWeb/UIEvents/KeyboardEvent.cpp b/Libraries/LibWeb/UIEvents/KeyboardEvent.cpp index 412bc7131f4..fda31a480fb 100644 --- a/Libraries/LibWeb/UIEvents/KeyboardEvent.cpp +++ b/Libraries/LibWeb/UIEvents/KeyboardEvent.cpp @@ -730,7 +730,7 @@ bool KeyboardEvent::get_modifier_state(String const& key_arg) const } // https://w3c.github.io/uievents/#dom-keyboardevent-initkeyboardevent -void KeyboardEvent::init_keyboard_event(String const& type, bool bubbles, bool cancelable, HTML::Window* view, String const& key, WebIDL::UnsignedLong location, bool ctrl_key, bool alt_key, bool shift_key, bool meta_key) +void KeyboardEvent::init_keyboard_event(String const& type, bool bubbles, bool cancelable, GC::Ptr view, String const& key, WebIDL::UnsignedLong location, bool ctrl_key, bool alt_key, bool shift_key, bool meta_key) { // Initializes attributes of a KeyboardEvent object. This method has the same behavior as UIEvent.initUIEvent(). // The value of detail remains undefined. diff --git a/Libraries/LibWeb/UIEvents/KeyboardEvent.h b/Libraries/LibWeb/UIEvents/KeyboardEvent.h index a90eac16898..f7aeccf97ac 100644 --- a/Libraries/LibWeb/UIEvents/KeyboardEvent.h +++ b/Libraries/LibWeb/UIEvents/KeyboardEvent.h @@ -62,7 +62,7 @@ public: virtual u32 which() const override { return m_key_code; } - void init_keyboard_event(String const& type, bool bubbles, bool cancelable, HTML::Window* view, String const& key, WebIDL::UnsignedLong location, bool ctrl_key, bool alt_key, bool shift_key, bool meta_key); + void init_keyboard_event(String const& type, bool bubbles, bool cancelable, GC::Ptr view, String const& key, WebIDL::UnsignedLong location, bool ctrl_key, bool alt_key, bool shift_key, bool meta_key); private: KeyboardEvent(JS::Realm&, FlyString const& event_name, KeyboardEventInit const& event_init); diff --git a/Libraries/LibWeb/UIEvents/KeyboardEvent.idl b/Libraries/LibWeb/UIEvents/KeyboardEvent.idl index 3d035c5bd55..d466e527a81 100644 --- a/Libraries/LibWeb/UIEvents/KeyboardEvent.idl +++ b/Libraries/LibWeb/UIEvents/KeyboardEvent.idl @@ -30,7 +30,7 @@ interface KeyboardEvent : UIEvent { boolean getModifierState(DOMString keyArg); // https://w3c.github.io/uievents/#dom-keyboardevent-initkeyboardevent - undefined initKeyboardEvent(DOMString typeArg, optional boolean bubblesArg = false, optional boolean cancelableArg = false, optional Window? viewArg = null, optional DOMString keyArg = "", optional unsigned long locationArg = 0, optional boolean ctrlKey = false, optional boolean altKey = false, optional boolean shiftKey = false, optional boolean metaKey = false); + undefined initKeyboardEvent(DOMString typeArg, optional boolean bubblesArg = false, optional boolean cancelableArg = false, optional WindowProxy? viewArg = null, optional DOMString keyArg = "", optional unsigned long locationArg = 0, optional boolean ctrlKey = false, optional boolean altKey = false, optional boolean shiftKey = false, optional boolean metaKey = false); }; diff --git a/Libraries/LibWeb/UIEvents/MouseEvent.cpp b/Libraries/LibWeb/UIEvents/MouseEvent.cpp index f032ed7fe60..057641d163c 100644 --- a/Libraries/LibWeb/UIEvents/MouseEvent.cpp +++ b/Libraries/LibWeb/UIEvents/MouseEvent.cpp @@ -97,7 +97,7 @@ bool MouseEvent::get_modifier_state(String const& key_arg) const } // https://w3c.github.io/uievents/#dom-mouseevent-initmouseevent -void MouseEvent::init_mouse_event(String const& type, bool bubbles, bool cancelable, HTML::Window* view, WebIDL::Long detail, WebIDL::Long screen_x, WebIDL::Long screen_y, WebIDL::Long client_x, WebIDL::Long client_y, bool ctrl_key, bool alt_key, bool shift_key, bool meta_key, WebIDL::Short button, DOM::EventTarget* related_target) +void MouseEvent::init_mouse_event(String const& type, bool bubbles, bool cancelable, GC::Ptr view, WebIDL::Long detail, WebIDL::Long screen_x, WebIDL::Long screen_y, WebIDL::Long client_x, WebIDL::Long client_y, bool ctrl_key, bool alt_key, bool shift_key, bool meta_key, WebIDL::Short button, DOM::EventTarget* related_target) { // Initializes attributes of a MouseEvent object. This method has the same behavior as UIEvent.initUIEvent(). diff --git a/Libraries/LibWeb/UIEvents/MouseEvent.h b/Libraries/LibWeb/UIEvents/MouseEvent.h index 45044b5f06d..16b393154c7 100644 --- a/Libraries/LibWeb/UIEvents/MouseEvent.h +++ b/Libraries/LibWeb/UIEvents/MouseEvent.h @@ -77,7 +77,7 @@ public: virtual u32 which() const override { return m_button + 1; } - void init_mouse_event(String const& type, bool bubbles, bool cancelable, HTML::Window* view, WebIDL::Long detail, WebIDL::Long screen_x, WebIDL::Long screen_y, WebIDL::Long client_x, WebIDL::Long client_y, bool ctrl_key, bool alt_key, bool shift_key, bool meta_key, WebIDL::Short button, DOM::EventTarget* related_target); + void init_mouse_event(String const& type, bool bubbles, bool cancelable, GC::Ptr view, WebIDL::Long detail, WebIDL::Long screen_x, WebIDL::Long screen_y, WebIDL::Long client_x, WebIDL::Long client_y, bool ctrl_key, bool alt_key, bool shift_key, bool meta_key, WebIDL::Short button, DOM::EventTarget* related_target); protected: MouseEvent(JS::Realm&, FlyString const& event_name, MouseEventInit const& event_init, double page_x, double page_y, double offset_x, double offset_y); diff --git a/Libraries/LibWeb/UIEvents/MouseEvent.idl b/Libraries/LibWeb/UIEvents/MouseEvent.idl index e7b5985b000..84fe8c491d3 100644 --- a/Libraries/LibWeb/UIEvents/MouseEvent.idl +++ b/Libraries/LibWeb/UIEvents/MouseEvent.idl @@ -34,7 +34,7 @@ interface MouseEvent : UIEvent { boolean getModifierState(DOMString keyArg); // https://w3c.github.io/uievents/#dom-mouseevent-initmouseevent - undefined initMouseEvent(DOMString typeArg, optional boolean bubblesArg = false, optional boolean cancelableArg = false, optional Window? viewArg = null, optional long detailArg = 0, optional long screenXArg = 0, optional long screenYArg = 0, optional long clientXArg = 0, optional long clientYArg = 0, optional boolean ctrlKeyArg = false, optional boolean altKeyArg = false, optional boolean shiftKeyArg = false, optional boolean metaKeyArg = false, optional short buttonArg = 0, optional EventTarget? relatedTargetArg = null); + undefined initMouseEvent(DOMString typeArg, optional boolean bubblesArg = false, optional boolean cancelableArg = false, optional WindowProxy? viewArg = null, optional long detailArg = 0, optional long screenXArg = 0, optional long screenYArg = 0, optional long clientXArg = 0, optional long clientYArg = 0, optional boolean ctrlKeyArg = false, optional boolean altKeyArg = false, optional boolean shiftKeyArg = false, optional boolean metaKeyArg = false, optional short buttonArg = 0, optional EventTarget? relatedTargetArg = null); }; // https://w3c.github.io/uievents/#idl-mouseeventinit diff --git a/Libraries/LibWeb/UIEvents/TextEvent.cpp b/Libraries/LibWeb/UIEvents/TextEvent.cpp index 1b8ed6632ff..663b7350e7d 100644 --- a/Libraries/LibWeb/UIEvents/TextEvent.cpp +++ b/Libraries/LibWeb/UIEvents/TextEvent.cpp @@ -31,7 +31,7 @@ void TextEvent::initialize(JS::Realm& realm) } // https://w3c.github.io/uievents/#dom-textevent-inittextevent -void TextEvent::init_text_event(String const& type, bool bubbles, bool cancelable, HTML::Window* view, String const& data) +void TextEvent::init_text_event(String const& type, bool bubbles, bool cancelable, GC::Ptr view, String const& data) { // Initializes attributes of a TextEvent object. This method has the same behavior as UIEvent.initUIEvent(). // The value of detail remains undefined. diff --git a/Libraries/LibWeb/UIEvents/TextEvent.h b/Libraries/LibWeb/UIEvents/TextEvent.h index 47819ce92c1..6db081b28e3 100644 --- a/Libraries/LibWeb/UIEvents/TextEvent.h +++ b/Libraries/LibWeb/UIEvents/TextEvent.h @@ -22,7 +22,7 @@ public: // https://w3c.github.io/uievents/#dom-textevent-data String data() const { return m_data; } - void init_text_event(String const& type, bool bubbles, bool cancelable, HTML::Window* view, String const& data); + void init_text_event(String const& type, bool bubbles, bool cancelable, GC::Ptr view, String const& data); private: TextEvent(JS::Realm&, FlyString const& event_name); diff --git a/Libraries/LibWeb/UIEvents/TextEvent.idl b/Libraries/LibWeb/UIEvents/TextEvent.idl index d50e8cc0d66..8435179d6d8 100644 --- a/Libraries/LibWeb/UIEvents/TextEvent.idl +++ b/Libraries/LibWeb/UIEvents/TextEvent.idl @@ -4,5 +4,5 @@ [Exposed=Window] interface TextEvent : UIEvent { readonly attribute DOMString data; - undefined initTextEvent(DOMString type, optional boolean bubbles = false, optional boolean cancelable = false, optional Window? view = null, optional DOMString data = "undefined"); + undefined initTextEvent(DOMString type, optional boolean bubbles = false, optional boolean cancelable = false, optional WindowProxy? view = null, optional DOMString data = "undefined"); }; diff --git a/Libraries/LibWeb/UIEvents/UIEvent.cpp b/Libraries/LibWeb/UIEvents/UIEvent.cpp index 51fbfd78440..fbc1c9ee1ec 100644 --- a/Libraries/LibWeb/UIEvents/UIEvent.cpp +++ b/Libraries/LibWeb/UIEvents/UIEvent.cpp @@ -6,6 +6,7 @@ #include #include +#include #include namespace Web::UIEvents { diff --git a/Libraries/LibWeb/UIEvents/UIEvent.h b/Libraries/LibWeb/UIEvents/UIEvent.h index 64c0e1902c2..27446532988 100644 --- a/Libraries/LibWeb/UIEvents/UIEvent.h +++ b/Libraries/LibWeb/UIEvents/UIEvent.h @@ -13,7 +13,7 @@ namespace Web::UIEvents { struct UIEventInit : public DOM::EventInit { - GC::Ptr view; + GC::Ptr view; int detail { 0 }; }; @@ -27,11 +27,11 @@ public: virtual ~UIEvent() override; - HTML::Window const* view() const { return m_view.ptr(); } + GC::Ptr const view() const { return m_view; } int detail() const { return m_detail; } virtual u32 which() const { return 0; } - void init_ui_event(String const& type, bool bubbles, bool cancelable, HTML::Window* view, int detail) + void init_ui_event(String const& type, bool bubbles, bool cancelable, GC::Ptr view, int detail) { // Initializes attributes of an UIEvent object. This method has the same behavior as initEvent(). @@ -54,7 +54,7 @@ protected: virtual void initialize(JS::Realm&) override; virtual void visit_edges(Cell::Visitor&) override; - GC::Ptr m_view; + GC::Ptr m_view; int m_detail { 0 }; }; diff --git a/Libraries/LibWeb/UIEvents/UIEvent.idl b/Libraries/LibWeb/UIEvents/UIEvent.idl index c974667e2e9..1bb95b05789 100644 --- a/Libraries/LibWeb/UIEvents/UIEvent.idl +++ b/Libraries/LibWeb/UIEvents/UIEvent.idl @@ -5,16 +5,16 @@ [Exposed=Window] interface UIEvent : Event { constructor(DOMString type, optional UIEventInit eventInitDict = {}); - readonly attribute Window? view; + readonly attribute WindowProxy? view; readonly attribute long detail; // Obsolete - [ImplementedAs=init_ui_event] undefined initUIEvent(DOMString typeArg, optional boolean bubblesArg = false, optional boolean cancelableArg = false, optional Window? viewArg = null, optional long detailArg = 0); + [ImplementedAs=init_ui_event] undefined initUIEvent(DOMString typeArg, optional boolean bubblesArg = false, optional boolean cancelableArg = false, optional WindowProxy? viewArg = null, optional long detailArg = 0); readonly attribute unsigned long which; }; // https://w3c.github.io/uievents/#idl-uieventinit dictionary UIEventInit : EventInit { - Window? view = null; + WindowProxy? view = null; long detail = 0; }; diff --git a/Meta/Lagom/Tools/CodeGenerators/LibWeb/BindingsGenerator/IDLGenerators.cpp b/Meta/Lagom/Tools/CodeGenerators/LibWeb/BindingsGenerator/IDLGenerators.cpp index c53cfa63a5a..f44ce4d57e9 100644 --- a/Meta/Lagom/Tools/CodeGenerators/LibWeb/BindingsGenerator/IDLGenerators.cpp +++ b/Meta/Lagom/Tools/CodeGenerators/LibWeb/BindingsGenerator/IDLGenerators.cpp @@ -102,6 +102,7 @@ static bool is_platform_object(Type const& type) "VideoTrackList"sv, "WebGLRenderingContext"sv, "Window"sv, + "WindowProxy"sv, "WritableStream"sv, }; if (type.name().ends_with("Element"sv)) diff --git a/Tests/LibWeb/Text/expected/wpt-import/dom/events/Event-init-while-dispatching.txt b/Tests/LibWeb/Text/expected/wpt-import/dom/events/Event-init-while-dispatching.txt index 4157cb77678..9a5afaf7dd4 100644 --- a/Tests/LibWeb/Text/expected/wpt-import/dom/events/Event-init-while-dispatching.txt +++ b/Tests/LibWeb/Text/expected/wpt-import/dom/events/Event-init-while-dispatching.txt @@ -6,11 +6,10 @@ Rerun Found 5 tests -4 Pass -1 Fail +5 Pass Details Result Test Name MessagePass Calling initKeyboardEvent while dispatching. Pass Calling initMouseEvent while dispatching. Pass Calling initCustomEvent while dispatching. -Fail Calling initUIEvent while dispatching. Not an object of type Window +Pass Calling initUIEvent while dispatching. Pass Calling initEvent while dispatching. \ No newline at end of file diff --git a/Tests/LibWeb/Text/expected/wpt-import/dom/events/Event-subclasses-constructors.txt b/Tests/LibWeb/Text/expected/wpt-import/dom/events/Event-subclasses-constructors.txt index fa23229c0ef..52b23e6fd8f 100644 --- a/Tests/LibWeb/Text/expected/wpt-import/dom/events/Event-subclasses-constructors.txt +++ b/Tests/LibWeb/Text/expected/wpt-import/dom/events/Event-subclasses-constructors.txt @@ -6,8 +6,7 @@ Rerun Found 49 tests -43 Pass -6 Fail +49 Pass Details Result Test Name MessagePass Event constructor (no argument) Pass Event constructor (undefined argument) @@ -20,37 +19,37 @@ Pass UIEvent constructor (undefined argument) Pass UIEvent constructor (null argument) Pass UIEvent constructor (empty argument) Pass UIEvent constructor (argument with default values) -Fail UIEvent constructor (argument with non-default values) Not an object of type Window +Pass UIEvent constructor (argument with non-default values) Pass FocusEvent constructor (no argument) Pass FocusEvent constructor (undefined argument) Pass FocusEvent constructor (null argument) Pass FocusEvent constructor (empty argument) Pass FocusEvent constructor (argument with default values) -Fail FocusEvent constructor (argument with non-default values) Not an object of type Window +Pass FocusEvent constructor (argument with non-default values) Pass MouseEvent constructor (no argument) Pass MouseEvent constructor (undefined argument) Pass MouseEvent constructor (null argument) Pass MouseEvent constructor (empty argument) Pass MouseEvent constructor (argument with default values) -Fail MouseEvent constructor (argument with non-default values) Not an object of type Window +Pass MouseEvent constructor (argument with non-default values) Pass WheelEvent constructor (no argument) Pass WheelEvent constructor (undefined argument) Pass WheelEvent constructor (null argument) Pass WheelEvent constructor (empty argument) Pass WheelEvent constructor (argument with default values) -Fail WheelEvent constructor (argument with non-default values) Not an object of type Window +Pass WheelEvent constructor (argument with non-default values) Pass KeyboardEvent constructor (no argument) Pass KeyboardEvent constructor (undefined argument) Pass KeyboardEvent constructor (null argument) Pass KeyboardEvent constructor (empty argument) Pass KeyboardEvent constructor (argument with default values) -Fail KeyboardEvent constructor (argument with non-default values) Not an object of type Window +Pass KeyboardEvent constructor (argument with non-default values) Pass CompositionEvent constructor (no argument) Pass CompositionEvent constructor (undefined argument) Pass CompositionEvent constructor (null argument) Pass CompositionEvent constructor (empty argument) Pass CompositionEvent constructor (argument with default values) -Fail CompositionEvent constructor (argument with non-default values) Not an object of type Window +Pass CompositionEvent constructor (argument with non-default values) Pass SubclassedEvent constructor (no argument) Pass SubclassedEvent constructor (undefined argument) Pass SubclassedEvent constructor (null argument)