ladybird/Userland/Libraries/LibWeb/HTML/NavigateEvent.h
Andreas Kling bfd354492e LibWeb: Put most LibWeb GC objects in type-specific heap blocks
With this change, we now have ~1200 CellAllocators across both LibJS and
LibWeb in a normal WebContent instance.

This gives us a minimum heap size of 4.7 MiB in the scenario where we
only have one cell allocated per type. Of course, in practice there will
be many more of each type, so the effective overhead is quite a bit
smaller than that in practice.

I left a few types unconverted to this mechanism because I got tired of
doing this. :^)
2023-11-19 22:00:48 +01:00

163 lines
7 KiB
C++

/*
* Copyright (c) 2023, Andrew Kaster <akaster@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <LibWeb/Bindings/NavigateEventPrototype.h>
#include <LibWeb/DOM/Event.h>
#include <LibWeb/HTML/NavigationType.h>
#include <LibWeb/HTML/StructuredSerialize.h>
namespace Web::HTML {
// https://html.spec.whatwg.org/multipage/nav-history-apis.html#navigateeventinit
struct NavigateEventInit : public DOM::EventInit {
Bindings::NavigationType navigation_type = Bindings::NavigationType::Push;
JS::GCPtr<NavigationDestination> destination;
bool can_intercept = false;
bool user_initiated = false;
bool hash_change = false;
JS::GCPtr<DOM::AbortSignal> signal;
JS::GCPtr<XHR::FormData> form_data = nullptr;
Optional<String> download_request = {};
Optional<JS::Value> info;
bool has_ua_visual_transition = false;
};
// https://html.spec.whatwg.org/multipage/nav-history-apis.html#navigationintercepthandler
using NavigationInterceptHandler = JS::NonnullGCPtr<WebIDL::CallbackType>;
// https://html.spec.whatwg.org/multipage/nav-history-apis.html#navigationinterceptoptions
struct NavigationInterceptOptions {
JS::GCPtr<WebIDL::CallbackType> handler;
Optional<Bindings::NavigationFocusReset> focus_reset;
Optional<Bindings::NavigationScrollBehavior> scroll;
};
// https://html.spec.whatwg.org/multipage/nav-history-apis.html#navigateevent
class NavigateEvent : public DOM::Event {
WEB_PLATFORM_OBJECT(NavigateEvent, DOM::Event);
JS_DECLARE_ALLOCATOR(NavigateEvent);
public:
// https://html.spec.whatwg.org/multipage/nav-history-apis.html#concept-navigateevent-interception-state
enum class InterceptionState {
None,
Intercepted,
Committed,
Scrolled,
Finished
};
[[nodiscard]] static JS::NonnullGCPtr<NavigateEvent> construct_impl(JS::Realm&, FlyString const& event_name, NavigateEventInit const&);
// The navigationType, destination, canIntercept, userInitiated, hashChange, signal, formData,
// downloadRequest, info, and hasUAVisualTransition attributes must return the values they are initialized to.
Bindings::NavigationType navigation_type() const { return m_navigation_type; }
JS::NonnullGCPtr<NavigationDestination> destination() const { return m_destination; }
bool can_intercept() const { return m_can_intercept; }
bool user_initiated() const { return m_user_initiated; }
bool hash_change() const { return m_hash_change; }
JS::NonnullGCPtr<DOM::AbortSignal> signal() const { return m_signal; }
JS::GCPtr<XHR::FormData> form_data() const { return m_form_data; }
Optional<String> download_request() const { return m_download_request; }
JS::Value info() const { return m_info; }
bool has_ua_visual_transition() const { return m_has_ua_visual_transition; }
WebIDL::ExceptionOr<void> intercept(NavigationInterceptOptions const&);
WebIDL::ExceptionOr<void> scroll();
virtual ~NavigateEvent() override;
JS::NonnullGCPtr<DOM::AbortController> abort_controller() const { return *m_abort_controller; }
InterceptionState interception_state() const { return m_interception_state; }
Vector<NavigationInterceptHandler> const& navigation_handler_list() const { return m_navigation_handler_list; }
void set_abort_controller(JS::NonnullGCPtr<DOM::AbortController> c) { m_abort_controller = c; }
void set_interception_state(InterceptionState s) { m_interception_state = s; }
void set_classic_history_api_state(Optional<SerializationRecord> r) { m_classic_history_api_state = move(r); }
void finish(bool did_fulfill);
private:
NavigateEvent(JS::Realm&, FlyString const& event_name, NavigateEventInit const& event_init);
virtual void initialize(JS::Realm&) override;
virtual void visit_edges(Cell::Visitor&) override;
WebIDL::ExceptionOr<void> perform_shared_checks();
void process_scroll_behavior();
void potentially_process_scroll_behavior();
void potentially_reset_the_focus();
// https://html.spec.whatwg.org/multipage/nav-history-apis.html#concept-navigateevent-interception-state
InterceptionState m_interception_state = InterceptionState::None;
// https://html.spec.whatwg.org/multipage/nav-history-apis.html#concept-navigateevent-navigation-handler-list
Vector<NavigationInterceptHandler> m_navigation_handler_list;
// https://html.spec.whatwg.org/multipage/nav-history-apis.html#concept-navigateevent-focusreset
Optional<Bindings::NavigationFocusReset> m_focus_reset_behavior = {};
// https://html.spec.whatwg.org/multipage/nav-history-apis.html#concept-navigateevent-scroll
Optional<Bindings::NavigationScrollBehavior> m_scroll_behavior = {};
// https://html.spec.whatwg.org/multipage/nav-history-apis.html#concept-navigateevent-abort-controller
JS::GCPtr<DOM::AbortController> m_abort_controller = { nullptr };
// https://html.spec.whatwg.org/multipage/nav-history-apis.html#concept-navigateevent-classic-history-api-state
Optional<SerializationRecord> m_classic_history_api_state = {};
// https://html.spec.whatwg.org/multipage/nav-history-apis.html#dom-navigateevent-navigationtype
Bindings::NavigationType m_navigation_type = { Bindings::NavigationType::Push };
// https://html.spec.whatwg.org/multipage/nav-history-apis.html#dom-navigateevent-destination
JS::NonnullGCPtr<NavigationDestination> m_destination;
// https://html.spec.whatwg.org/multipage/nav-history-apis.html#dom-navigateevent-canintercept
bool m_can_intercept = { false };
// https://html.spec.whatwg.org/multipage/nav-history-apis.html#dom-navigateevent-userinitiated
bool m_user_initiated = { false };
// https://html.spec.whatwg.org/multipage/nav-history-apis.html#dom-navigateevent-hashchange
bool m_hash_change = { false };
// https://html.spec.whatwg.org/multipage/nav-history-apis.html#dom-navigateevent-signal
JS::NonnullGCPtr<DOM::AbortSignal> m_signal;
// https://html.spec.whatwg.org/multipage/nav-history-apis.html#dom-navigateevent-formdata
JS::GCPtr<XHR::FormData> m_form_data;
// https://html.spec.whatwg.org/multipage/nav-history-apis.html#dom-navigateevent-downloadrequest
Optional<String> m_download_request;
// https://html.spec.whatwg.org/multipage/nav-history-apis.html#dom-navigateevent-info
JS::Value m_info;
// https://html.spec.whatwg.org/multipage/nav-history-apis.html#dom-navigateevent-hasuavisualtransition
bool m_has_ua_visual_transition { false };
};
}
namespace AK {
template<>
struct Formatter<Web::Bindings::NavigationScrollBehavior> : Formatter<StringView> {
ErrorOr<void> format(FormatBuilder& builder, Web::Bindings::NavigationScrollBehavior const& value)
{
return Formatter<StringView>::format(builder, Web::Bindings::idl_enum_to_string(value));
}
};
template<>
struct Formatter<Web::Bindings::NavigationFocusReset> : Formatter<StringView> {
ErrorOr<void> format(FormatBuilder& builder, Web::Bindings::NavigationFocusReset const& value)
{
return Formatter<StringView>::format(builder, Web::Bindings::idl_enum_to_string(value));
}
};
}