LibWeb: Add hashchange event support
This commit is contained in:
parent
efefd44a9f
commit
ccb363c443
Notes:
sideshowbarker
2024-07-17 08:27:05 +09:00
Author: https://github.com/kalenikaliaksandr Commit: https://github.com/SerenityOS/serenity/commit/ccb363c443 Pull-request: https://github.com/SerenityOS/serenity/pull/23968
11 changed files with 144 additions and 4 deletions
|
@ -113,6 +113,7 @@ source_set("HTML") {
|
|||
"HTMLUListElement.cpp",
|
||||
"HTMLUnknownElement.cpp",
|
||||
"HTMLVideoElement.cpp",
|
||||
"HashChangeEvent.cpp",
|
||||
"History.cpp",
|
||||
"ImageBitmap.cpp",
|
||||
"ImageData.cpp",
|
||||
|
|
|
@ -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",
|
||||
|
|
12
Tests/LibWeb/Text/data/iframe-hashchange-event.html
Normal file
12
Tests/LibWeb/Text/data/iframe-hashchange-event.html
Normal file
|
@ -0,0 +1,12 @@
|
|||
<!DOCTYPE html>
|
||||
<script>
|
||||
window.addEventListener('hashchange', (event) => {
|
||||
const oldURL = new URL(event.oldURL);
|
||||
const newURL = new URL(event.newURL);
|
||||
parent.postMessage(`hashchange oldURL.hash=${oldURL.hash} newURL.hash=${newURL.hash}`, "*");
|
||||
if (location.hash === "#test")
|
||||
location.hash = "#done";
|
||||
});
|
||||
|
||||
location.hash = "#test";
|
||||
</script>
|
|
@ -0,0 +1,2 @@
|
|||
hashchange oldURL.hash= newURL.hash=#test
|
||||
hashchange oldURL.hash=#test newURL.hash=#done
|
13
Tests/LibWeb/Text/input/navigation/hashchange-event.html
Normal file
13
Tests/LibWeb/Text/input/navigation/hashchange-event.html
Normal file
|
@ -0,0 +1,13 @@
|
|||
<script src="../include.js"></script>
|
||||
<iframe src="../../data/iframe-hashchange-event.html"></iframe>
|
||||
<script>
|
||||
asyncTest(done => {
|
||||
let messageCount = 0;
|
||||
window.addEventListener("message", event => {
|
||||
println(event.data);
|
||||
messageCount++;
|
||||
if (messageCount == 2)
|
||||
done();
|
||||
});
|
||||
});
|
||||
</script>
|
|
@ -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
|
||||
|
|
|
@ -79,6 +79,7 @@
|
|||
#include <LibWeb/HTML/HTMLObjectElement.h>
|
||||
#include <LibWeb/HTML/HTMLScriptElement.h>
|
||||
#include <LibWeb/HTML/HTMLTitleElement.h>
|
||||
#include <LibWeb/HTML/HashChangeEvent.h>
|
||||
#include <LibWeb/HTML/ListOfAvailableImages.h>
|
||||
#include <LibWeb/HTML/Location.h>
|
||||
#include <LibWeb/HTML/MessageEvent.h>
|
||||
|
@ -4023,10 +4024,19 @@ void Document::update_for_history_step_application(JS::NonnullGCPtr<HTML::Sessio
|
|||
|
||||
// FIXME: 3. Restore persisted state given entry.
|
||||
|
||||
// FIXME: 4. If oldURL's fragment is not equal to entry's URL's fragment, then queue a global task on the DOM manipulation task source
|
||||
// given document's relevant global object to fire an event named hashchange at document's relevant global object,
|
||||
// using HashChangeEvent, with the oldURL attribute initialized to the serialization of oldURL and the newURL attribute
|
||||
// initialized to the serialization of entry's URL.
|
||||
// 4. If oldURL's fragment is not equal to entry's URL's fragment, then queue a global task on the DOM manipulation task source
|
||||
// given document's relevant global object to fire an event named hashchange at document's relevant global object,
|
||||
// using HashChangeEvent, with the oldURL attribute initialized to the serialization of oldURL and the newURL attribute
|
||||
// initialized to the serialization of entry's URL.
|
||||
if (old_url.fragment() != entry->url().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:
|
||||
|
|
45
Userland/Libraries/LibWeb/HTML/HashChangeEvent.cpp
Normal file
45
Userland/Libraries/LibWeb/HTML/HashChangeEvent.cpp
Normal file
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* Copyright (c) 2024, Aliaksandr Kalenik <kalenik.aliaksandr@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <LibJS/Heap/Heap.h>
|
||||
#include <LibJS/Runtime/Realm.h>
|
||||
#include <LibWeb/Bindings/HashChangeEventPrototype.h>
|
||||
#include <LibWeb/Bindings/Intrinsics.h>
|
||||
#include <LibWeb/HTML/HashChangeEvent.h>
|
||||
|
||||
namespace Web::HTML {
|
||||
|
||||
JS_DEFINE_ALLOCATOR(HashChangeEvent);
|
||||
|
||||
[[nodiscard]] JS::NonnullGCPtr<HashChangeEvent> HashChangeEvent::create(JS::Realm& realm, FlyString const& event_name, HashChangeEventInit const& event_init)
|
||||
{
|
||||
return realm.heap().allocate<HashChangeEvent>(realm, realm, event_name, event_init);
|
||||
}
|
||||
|
||||
JS::NonnullGCPtr<HashChangeEvent> HashChangeEvent::construct_impl(JS::Realm& realm, FlyString const& event_name, HashChangeEventInit const& event_init)
|
||||
{
|
||||
return realm.heap().allocate<HashChangeEvent>(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);
|
||||
}
|
||||
|
||||
}
|
39
Userland/Libraries/LibWeb/HTML/HashChangeEvent.h
Normal file
39
Userland/Libraries/LibWeb/HTML/HashChangeEvent.h
Normal file
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* Copyright (c) 2024, Aliaksandr Kalenik <kalenik.aliaksandr@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <LibWeb/DOM/Event.h>
|
||||
|
||||
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<HashChangeEvent> create(JS::Realm&, FlyString const& event_name, HashChangeEventInit const&);
|
||||
[[nodiscard]] static JS::NonnullGCPtr<HashChangeEvent> 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;
|
||||
};
|
||||
|
||||
}
|
15
Userland/Libraries/LibWeb/HTML/HashChangeEvent.idl
Normal file
15
Userland/Libraries/LibWeb/HTML/HashChangeEvent.idl
Normal file
|
@ -0,0 +1,15 @@
|
|||
#import <DOM/Event.idl>
|
||||
|
||||
// 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 = "";
|
||||
};
|
|
@ -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)
|
||||
|
|
Loading…
Add table
Reference in a new issue