LibWeb: Add popstate event support
It is going to be useful in writing tests for History API.
This commit is contained in:
parent
0ffc338406
commit
ee3dd7977d
Notes:
sideshowbarker
2024-07-17 16:42:19 +09:00
Author: https://github.com/kalenikaliaksandr Commit: https://github.com/SerenityOS/serenity/commit/ee3dd7977d Pull-request: https://github.com/SerenityOS/serenity/pull/23933
11 changed files with 134 additions and 3 deletions
9
Tests/LibWeb/Text/data/iframe-popstate-event.html
Normal file
9
Tests/LibWeb/Text/data/iframe-popstate-event.html
Normal file
|
@ -0,0 +1,9 @@
|
|||
<script>
|
||||
window.history.pushState({}, '', '');
|
||||
|
||||
window.addEventListener('popstate', (e) => {
|
||||
parent.postMessage('popstate event from iframe', '*');
|
||||
});
|
||||
|
||||
window.history.back();
|
||||
</script>
|
|
@ -0,0 +1 @@
|
|||
popstate event from iframe
|
|
@ -0,0 +1,10 @@
|
|||
<script src="../include.js"></script>
|
||||
<iframe src="../../data/iframe-popstate-event.html"></iframe>
|
||||
<script>
|
||||
asyncTest(done => {
|
||||
window.addEventListener("message", event => {
|
||||
println(event.data);
|
||||
done();
|
||||
});
|
||||
});
|
||||
</script>
|
|
@ -380,6 +380,7 @@ set(SOURCES
|
|||
HTML/Origin.cpp
|
||||
HTML/PageTransitionEvent.cpp
|
||||
HTML/PolicyContainers.cpp
|
||||
HTML/PopStateEvent.cpp
|
||||
HTML/Parser/Entities.cpp
|
||||
HTML/Parser/HTMLEncodingDetection.cpp
|
||||
HTML/Parser/HTMLParser.cpp
|
||||
|
|
|
@ -88,6 +88,7 @@
|
|||
#include <LibWeb/HTML/Numbers.h>
|
||||
#include <LibWeb/HTML/Origin.h>
|
||||
#include <LibWeb/HTML/Parser/HTMLParser.h>
|
||||
#include <LibWeb/HTML/PopStateEvent.h>
|
||||
#include <LibWeb/HTML/Scripting/ClassicScript.h>
|
||||
#include <LibWeb/HTML/Scripting/ExceptionReporter.h>
|
||||
#include <LibWeb/HTML/Scripting/WindowEnvironmentSettingsObject.h>
|
||||
|
@ -3993,9 +3994,15 @@ void Document::update_for_history_step_application(JS::NonnullGCPtr<HTML::Sessio
|
|||
navigation->update_the_navigation_api_entries_for_a_same_document_navigation(entry, Bindings::NavigationType::Traverse);
|
||||
}
|
||||
|
||||
// FIXME: 2. Fire an event named popstate at document's relevant global object, using PopStateEvent,
|
||||
// with the state attribute initialized to document's history object's state and hasUAVisualTransition initialized to true
|
||||
// if a visual transition, to display a cached rendered state of the latest entry, was done by the user agent.
|
||||
// 2. Fire an event named popstate at document's relevant global object, using PopStateEvent,
|
||||
// with the state attribute initialized to document's history object's state and hasUAVisualTransition initialized to true
|
||||
// if a visual transition, to display a cached rendered state of the latest entry, was done by the user agent.
|
||||
// FIXME: Initialise hasUAVisualTransition
|
||||
HTML::PopStateEventInit popstate_event_init;
|
||||
popstate_event_init.state = history()->unsafe_state();
|
||||
auto& relevant_global_object = verify_cast<HTML::Window>(HTML::relevant_global_object(*this));
|
||||
auto pop_state_event = HTML::PopStateEvent::create(realm(), "popstate"_fly_string, popstate_event_init);
|
||||
relevant_global_object.dispatch_event(pop_state_event);
|
||||
|
||||
// FIXME: 3. Restore persisted state given entry.
|
||||
|
||||
|
|
|
@ -77,6 +77,11 @@ WebIDL::ExceptionOr<JS::Value> History::state() const
|
|||
return m_state;
|
||||
}
|
||||
|
||||
JS::Value History::unsafe_state() const
|
||||
{
|
||||
return m_state;
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/history.html#dom-history-go
|
||||
WebIDL::ExceptionOr<void> History::go(WebIDL::Long delta = 0)
|
||||
{
|
||||
|
|
|
@ -34,6 +34,7 @@ public:
|
|||
u64 m_index { 0 };
|
||||
u64 m_length { 0 };
|
||||
|
||||
JS::Value unsafe_state() const;
|
||||
void set_state(JS::Value s) { m_state = s; }
|
||||
|
||||
private:
|
||||
|
|
45
Userland/Libraries/LibWeb/HTML/PopStateEvent.cpp
Normal file
45
Userland/Libraries/LibWeb/HTML/PopStateEvent.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/Intrinsics.h>
|
||||
#include <LibWeb/Bindings/PopStateEventPrototype.h>
|
||||
#include <LibWeb/HTML/PopStateEvent.h>
|
||||
|
||||
namespace Web::HTML {
|
||||
|
||||
JS_DEFINE_ALLOCATOR(PopStateEvent);
|
||||
|
||||
[[nodiscard]] JS::NonnullGCPtr<PopStateEvent> PopStateEvent::create(JS::Realm& realm, FlyString const& event_name, PopStateEventInit const& event_init)
|
||||
{
|
||||
return realm.heap().allocate<PopStateEvent>(realm, realm, event_name, event_init);
|
||||
}
|
||||
|
||||
JS::NonnullGCPtr<PopStateEvent> PopStateEvent::construct_impl(JS::Realm& realm, FlyString const& event_name, PopStateEventInit const& event_init)
|
||||
{
|
||||
return realm.heap().allocate<PopStateEvent>(realm, realm, event_name, event_init);
|
||||
}
|
||||
|
||||
PopStateEvent::PopStateEvent(JS::Realm& realm, FlyString const& event_name, PopStateEventInit const& event_init)
|
||||
: DOM::Event(realm, event_name, event_init)
|
||||
, m_state(event_init.state)
|
||||
{
|
||||
}
|
||||
|
||||
void PopStateEvent::initialize(JS::Realm& realm)
|
||||
{
|
||||
Base::initialize(realm);
|
||||
WEB_SET_PROTOTYPE_FOR_INTERFACE(PopStateEvent);
|
||||
}
|
||||
|
||||
void PopStateEvent::visit_edges(JS::Cell::Visitor& visitor)
|
||||
{
|
||||
Base::visit_edges(visitor);
|
||||
visitor.visit(m_state);
|
||||
}
|
||||
|
||||
}
|
36
Userland/Libraries/LibWeb/HTML/PopStateEvent.h
Normal file
36
Userland/Libraries/LibWeb/HTML/PopStateEvent.h
Normal file
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* 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 PopStateEventInit : public DOM::EventInit {
|
||||
JS::Value state { JS::js_null() };
|
||||
};
|
||||
|
||||
class PopStateEvent final : public DOM::Event {
|
||||
WEB_PLATFORM_OBJECT(PopStateEvent, DOM::Event);
|
||||
JS_DECLARE_ALLOCATOR(PopStateEvent);
|
||||
|
||||
public:
|
||||
[[nodiscard]] static JS::NonnullGCPtr<PopStateEvent> create(JS::Realm&, FlyString const& event_name, PopStateEventInit const&);
|
||||
[[nodiscard]] static JS::NonnullGCPtr<PopStateEvent> construct_impl(JS::Realm&, FlyString const& event_name, PopStateEventInit const&);
|
||||
|
||||
JS::Value const& state() const { return m_state; }
|
||||
|
||||
private:
|
||||
PopStateEvent(JS::Realm&, FlyString const& event_name, PopStateEventInit const& event_init);
|
||||
|
||||
virtual void initialize(JS::Realm&) override;
|
||||
virtual void visit_edges(JS::Cell::Visitor& visitor) override;
|
||||
|
||||
JS::Value m_state { JS::js_null() };
|
||||
};
|
||||
|
||||
}
|
15
Userland/Libraries/LibWeb/HTML/PopStateEvent.idl
Normal file
15
Userland/Libraries/LibWeb/HTML/PopStateEvent.idl
Normal file
|
@ -0,0 +1,15 @@
|
|||
#import <DOM/Event.idl>
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/nav-history-apis.html#popstateevent
|
||||
[Exposed=Window]
|
||||
interface PopStateEvent : Event {
|
||||
constructor(DOMString type, optional PopStateEventInit eventInitDict = {});
|
||||
|
||||
readonly attribute any state;
|
||||
// FIXME: readonly attribute boolean hasUAVisualTransition;
|
||||
};
|
||||
|
||||
dictionary PopStateEventInit : EventInit {
|
||||
any state = null;
|
||||
// FIXME: boolean hasUAVisualTransition = false;
|
||||
};
|
|
@ -197,6 +197,7 @@ libweb_js_bindings(HTML/PageTransitionEvent)
|
|||
libweb_js_bindings(HTML/Path2D)
|
||||
libweb_js_bindings(HTML/Plugin)
|
||||
libweb_js_bindings(HTML/PluginArray)
|
||||
libweb_js_bindings(HTML/PopStateEvent)
|
||||
libweb_js_bindings(HTML/PromiseRejectionEvent)
|
||||
libweb_js_bindings(HTML/Storage)
|
||||
libweb_js_bindings(HTML/SubmitEvent)
|
||||
|
|
Loading…
Add table
Reference in a new issue