From ccb363c443f2ba1730b202107ca23bb5c0f49e3b Mon Sep 17 00:00:00 2001 From: Aliaksandr Kalenik Date: Mon, 15 Apr 2024 04:25:24 +0200 Subject: [PATCH] LibWeb: Add hashchange event support --- .../Userland/Libraries/LibWeb/HTML/BUILD.gn | 1 + .../Userland/Libraries/LibWeb/idl_files.gni | 1 + .../Text/data/iframe-hashchange-event.html | 12 +++++ .../expected/navigation/hashchange-event.txt | 2 + .../input/navigation/hashchange-event.html | 13 ++++++ Userland/Libraries/LibWeb/CMakeLists.txt | 1 + Userland/Libraries/LibWeb/DOM/Document.cpp | 18 ++++++-- .../Libraries/LibWeb/HTML/HashChangeEvent.cpp | 45 +++++++++++++++++++ .../Libraries/LibWeb/HTML/HashChangeEvent.h | 39 ++++++++++++++++ .../Libraries/LibWeb/HTML/HashChangeEvent.idl | 15 +++++++ Userland/Libraries/LibWeb/idl_files.cmake | 1 + 11 files changed, 144 insertions(+), 4 deletions(-) create mode 100644 Tests/LibWeb/Text/data/iframe-hashchange-event.html create mode 100644 Tests/LibWeb/Text/expected/navigation/hashchange-event.txt create mode 100644 Tests/LibWeb/Text/input/navigation/hashchange-event.html create mode 100644 Userland/Libraries/LibWeb/HTML/HashChangeEvent.cpp create mode 100644 Userland/Libraries/LibWeb/HTML/HashChangeEvent.h create mode 100644 Userland/Libraries/LibWeb/HTML/HashChangeEvent.idl diff --git a/Meta/gn/secondary/Userland/Libraries/LibWeb/HTML/BUILD.gn b/Meta/gn/secondary/Userland/Libraries/LibWeb/HTML/BUILD.gn index 78db885a46f..969f66e800e 100644 --- a/Meta/gn/secondary/Userland/Libraries/LibWeb/HTML/BUILD.gn +++ b/Meta/gn/secondary/Userland/Libraries/LibWeb/HTML/BUILD.gn @@ -113,6 +113,7 @@ source_set("HTML") { "HTMLUListElement.cpp", "HTMLUnknownElement.cpp", "HTMLVideoElement.cpp", + "HashChangeEvent.cpp", "History.cpp", "ImageBitmap.cpp", "ImageData.cpp", diff --git a/Meta/gn/secondary/Userland/Libraries/LibWeb/idl_files.gni b/Meta/gn/secondary/Userland/Libraries/LibWeb/idl_files.gni index aa0c0675547..3b57613c5fa 100644 --- a/Meta/gn/secondary/Userland/Libraries/LibWeb/idl_files.gni +++ b/Meta/gn/secondary/Userland/Libraries/LibWeb/idl_files.gni @@ -117,6 +117,7 @@ standard_idl_files = [ "//Userland/Libraries/LibWeb/HTML/DataTransfer.idl", "//Userland/Libraries/LibWeb/HTML/ErrorEvent.idl", "//Userland/Libraries/LibWeb/HTML/FormDataEvent.idl", + "//Userland/Libraries/LibWeb/HTML/HashChangeEvent.idl", "//Userland/Libraries/LibWeb/HTML/History.idl", "//Userland/Libraries/LibWeb/HTML/HTMLAllCollection.idl", "//Userland/Libraries/LibWeb/HTML/HTMLAnchorElement.idl", diff --git a/Tests/LibWeb/Text/data/iframe-hashchange-event.html b/Tests/LibWeb/Text/data/iframe-hashchange-event.html new file mode 100644 index 00000000000..2a82ff445cd --- /dev/null +++ b/Tests/LibWeb/Text/data/iframe-hashchange-event.html @@ -0,0 +1,12 @@ + + diff --git a/Tests/LibWeb/Text/expected/navigation/hashchange-event.txt b/Tests/LibWeb/Text/expected/navigation/hashchange-event.txt new file mode 100644 index 00000000000..413ed9a430f --- /dev/null +++ b/Tests/LibWeb/Text/expected/navigation/hashchange-event.txt @@ -0,0 +1,2 @@ + hashchange oldURL.hash= newURL.hash=#test +hashchange oldURL.hash=#test newURL.hash=#done diff --git a/Tests/LibWeb/Text/input/navigation/hashchange-event.html b/Tests/LibWeb/Text/input/navigation/hashchange-event.html new file mode 100644 index 00000000000..7d92aef3a1f --- /dev/null +++ b/Tests/LibWeb/Text/input/navigation/hashchange-event.html @@ -0,0 +1,13 @@ + + + diff --git a/Userland/Libraries/LibWeb/CMakeLists.txt b/Userland/Libraries/LibWeb/CMakeLists.txt index c733043f30e..497868d486a 100644 --- a/Userland/Libraries/LibWeb/CMakeLists.txt +++ b/Userland/Libraries/LibWeb/CMakeLists.txt @@ -277,6 +277,7 @@ set(SOURCES HTML/FormControlInfrastructure.cpp HTML/FormDataEvent.cpp HTML/GlobalEventHandlers.cpp + HTML/HashChangeEvent.cpp HTML/History.cpp HTML/HTMLAllCollection.cpp HTML/HTMLAnchorElement.cpp diff --git a/Userland/Libraries/LibWeb/DOM/Document.cpp b/Userland/Libraries/LibWeb/DOM/Document.cpp index 99f96d1424a..f7e022b5e5f 100644 --- a/Userland/Libraries/LibWeb/DOM/Document.cpp +++ b/Userland/Libraries/LibWeb/DOM/Document.cpp @@ -79,6 +79,7 @@ #include #include #include +#include #include #include #include @@ -4023,10 +4024,19 @@ void Document::update_for_history_step_application(JS::NonnullGCPtrurl().fragment()) { + HTML::HashChangeEventInit hashchange_event_init; + hashchange_event_init.old_url = MUST(String::from_byte_string(old_url.serialize())); + hashchange_event_init.new_url = MUST(String::from_byte_string(entry->url().serialize())); + auto hashchange_event = HTML::HashChangeEvent::create(realm(), "hashchange"_fly_string, hashchange_event_init); + HTML::queue_global_task(HTML::Task::Source::DOMManipulation, relevant_global_object, [hashchange_event, &relevant_global_object]() { + relevant_global_object.dispatch_event(hashchange_event); + }); + } } // 6. Otherwise: diff --git a/Userland/Libraries/LibWeb/HTML/HashChangeEvent.cpp b/Userland/Libraries/LibWeb/HTML/HashChangeEvent.cpp new file mode 100644 index 00000000000..78e35921a29 --- /dev/null +++ b/Userland/Libraries/LibWeb/HTML/HashChangeEvent.cpp @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2024, Aliaksandr Kalenik + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include +#include +#include +#include + +namespace Web::HTML { + +JS_DEFINE_ALLOCATOR(HashChangeEvent); + +[[nodiscard]] JS::NonnullGCPtr HashChangeEvent::create(JS::Realm& realm, FlyString const& event_name, HashChangeEventInit const& event_init) +{ + return realm.heap().allocate(realm, realm, event_name, event_init); +} + +JS::NonnullGCPtr HashChangeEvent::construct_impl(JS::Realm& realm, FlyString const& event_name, HashChangeEventInit const& event_init) +{ + return realm.heap().allocate(realm, realm, event_name, event_init); +} + +HashChangeEvent::HashChangeEvent(JS::Realm& realm, FlyString const& event_name, HashChangeEventInit const& event_init) + : DOM::Event(realm, event_name, event_init) + , m_old_url(event_init.old_url) + , m_new_url(event_init.new_url) +{ +} + +void HashChangeEvent::initialize(JS::Realm& realm) +{ + Base::initialize(realm); + WEB_SET_PROTOTYPE_FOR_INTERFACE(HashChangeEvent); +} + +void HashChangeEvent::visit_edges(JS::Cell::Visitor& visitor) +{ + Base::visit_edges(visitor); +} + +} diff --git a/Userland/Libraries/LibWeb/HTML/HashChangeEvent.h b/Userland/Libraries/LibWeb/HTML/HashChangeEvent.h new file mode 100644 index 00000000000..2b51cc9b4a1 --- /dev/null +++ b/Userland/Libraries/LibWeb/HTML/HashChangeEvent.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2024, Aliaksandr Kalenik + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include + +namespace Web::HTML { + +struct HashChangeEventInit : public DOM::EventInit { + String old_url; + String new_url; +}; + +class HashChangeEvent final : public DOM::Event { + WEB_PLATFORM_OBJECT(HashChangeEvent, DOM::Event); + JS_DECLARE_ALLOCATOR(HashChangeEvent); + +public: + [[nodiscard]] static JS::NonnullGCPtr create(JS::Realm&, FlyString const& event_name, HashChangeEventInit const&); + [[nodiscard]] static JS::NonnullGCPtr construct_impl(JS::Realm&, FlyString const& event_name, HashChangeEventInit const&); + + String old_url() const { return m_old_url; } + String new_url() const { return m_new_url; } + +private: + HashChangeEvent(JS::Realm&, FlyString const& event_name, HashChangeEventInit const& event_init); + + virtual void initialize(JS::Realm&) override; + virtual void visit_edges(JS::Cell::Visitor& visitor) override; + + String m_old_url; + String m_new_url; +}; + +} diff --git a/Userland/Libraries/LibWeb/HTML/HashChangeEvent.idl b/Userland/Libraries/LibWeb/HTML/HashChangeEvent.idl new file mode 100644 index 00000000000..67656dcf4e0 --- /dev/null +++ b/Userland/Libraries/LibWeb/HTML/HashChangeEvent.idl @@ -0,0 +1,15 @@ +#import + +// https://html.spec.whatwg.org/multipage/nav-history-apis.html#hashchangeevent +[Exposed=Window] +interface HashChangeEvent : Event { + constructor(DOMString type, optional HashChangeEventInit eventInitDict = {}); + + readonly attribute USVString oldURL; + readonly attribute USVString newURL; +}; + +dictionary HashChangeEventInit : EventInit { + USVString oldURL = ""; + USVString newURL = ""; +}; diff --git a/Userland/Libraries/LibWeb/idl_files.cmake b/Userland/Libraries/LibWeb/idl_files.cmake index 05f2a9dcbfc..1f9db5188f3 100644 --- a/Userland/Libraries/LibWeb/idl_files.cmake +++ b/Userland/Libraries/LibWeb/idl_files.cmake @@ -102,6 +102,7 @@ libweb_js_bindings(HTML/DOMStringMap) libweb_js_bindings(HTML/DataTransfer) libweb_js_bindings(HTML/ErrorEvent) libweb_js_bindings(HTML/FormDataEvent) +libweb_js_bindings(HTML/HashChangeEvent) libweb_js_bindings(HTML/History) libweb_js_bindings(HTML/HTMLAllCollection) libweb_js_bindings(HTML/HTMLAnchorElement)