mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-07-29 12:19:54 +00:00
LibWeb: Implement BeforeUnloadEvent
This is required to support legacy behavior of the `returnValue` attribute.
This commit is contained in:
parent
d00adabc3c
commit
99ef078c97
Notes:
github-actions[bot]
2024-10-05 07:18:41 +00:00
Author: https://github.com/tcl3
Commit: 99ef078c97
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/1614
Reviewed-by: https://github.com/awesomekling
9 changed files with 95 additions and 5 deletions
|
@ -21,6 +21,7 @@ AudioScheduledSourceNode
|
||||||
AudioTrack
|
AudioTrack
|
||||||
AudioTrackList
|
AudioTrackList
|
||||||
BaseAudioContext
|
BaseAudioContext
|
||||||
|
BeforeUnloadEvent
|
||||||
BigInt
|
BigInt
|
||||||
BigInt64Array
|
BigInt64Array
|
||||||
BigUint64Array
|
BigUint64Array
|
||||||
|
|
|
@ -163,6 +163,7 @@ set(SOURCES
|
||||||
DOM/AccessibilityTreeNode.cpp
|
DOM/AccessibilityTreeNode.cpp
|
||||||
DOM/AdoptedStyleSheets.cpp
|
DOM/AdoptedStyleSheets.cpp
|
||||||
DOM/Attr.cpp
|
DOM/Attr.cpp
|
||||||
|
DOM/BeforeUnloadEvent.cpp
|
||||||
DOM/CDATASection.cpp
|
DOM/CDATASection.cpp
|
||||||
DOM/CharacterData.cpp
|
DOM/CharacterData.cpp
|
||||||
DOM/Comment.cpp
|
DOM/Comment.cpp
|
||||||
|
|
33
Userland/Libraries/LibWeb/DOM/BeforeUnloadEvent.cpp
Normal file
33
Userland/Libraries/LibWeb/DOM/BeforeUnloadEvent.cpp
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2024, Tim Ledbetter <tim.ledbetter@ladybird.org>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <LibWeb/Bindings/BeforeUnloadEventPrototype.h>
|
||||||
|
#include <LibWeb/Bindings/Intrinsics.h>
|
||||||
|
#include <LibWeb/DOM/BeforeUnloadEvent.h>
|
||||||
|
|
||||||
|
namespace Web::DOM {
|
||||||
|
|
||||||
|
JS_DEFINE_ALLOCATOR(BeforeUnloadEvent);
|
||||||
|
|
||||||
|
JS::NonnullGCPtr<BeforeUnloadEvent> BeforeUnloadEvent::create(JS::Realm& realm, FlyString const& event_name, DOM::EventInit const& event_init)
|
||||||
|
{
|
||||||
|
return realm.heap().allocate<BeforeUnloadEvent>(realm, realm, event_name, event_init);
|
||||||
|
}
|
||||||
|
|
||||||
|
BeforeUnloadEvent::BeforeUnloadEvent(JS::Realm& realm, FlyString const& event_name, DOM::EventInit const& event_init)
|
||||||
|
: DOM::Event(realm, event_name, event_init)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
BeforeUnloadEvent::~BeforeUnloadEvent() = default;
|
||||||
|
|
||||||
|
void BeforeUnloadEvent::initialize(JS::Realm& realm)
|
||||||
|
{
|
||||||
|
Base::initialize(realm);
|
||||||
|
WEB_SET_PROTOTYPE_FOR_INTERFACE(BeforeUnloadEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
34
Userland/Libraries/LibWeb/DOM/BeforeUnloadEvent.h
Normal file
34
Userland/Libraries/LibWeb/DOM/BeforeUnloadEvent.h
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2024, Tim Ledbetter <tim.ledbetter@ladybird.org>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <AK/FlyString.h>
|
||||||
|
#include <LibWeb/DOM/Event.h>
|
||||||
|
|
||||||
|
namespace Web::DOM {
|
||||||
|
|
||||||
|
class BeforeUnloadEvent final : public DOM::Event {
|
||||||
|
WEB_PLATFORM_OBJECT(BeforeUnloadEvent, DOM::Event);
|
||||||
|
JS_DECLARE_ALLOCATOR(BeforeUnloadEvent);
|
||||||
|
|
||||||
|
public:
|
||||||
|
[[nodiscard]] static JS::NonnullGCPtr<BeforeUnloadEvent> create(JS::Realm&, FlyString const& event_name, DOM::EventInit const& = {});
|
||||||
|
|
||||||
|
BeforeUnloadEvent(JS::Realm&, FlyString const& event_name, DOM::EventInit const&);
|
||||||
|
|
||||||
|
virtual ~BeforeUnloadEvent() override;
|
||||||
|
|
||||||
|
String const& return_value() const { return m_return_value; }
|
||||||
|
void set_return_value(String const& return_value) { m_return_value = return_value; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
virtual void initialize(JS::Realm&) override;
|
||||||
|
|
||||||
|
String m_return_value;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
7
Userland/Libraries/LibWeb/DOM/BeforeUnloadEvent.idl
Normal file
7
Userland/Libraries/LibWeb/DOM/BeforeUnloadEvent.idl
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
#import <DOM/Event.idl>
|
||||||
|
|
||||||
|
// https://html.spec.whatwg.org/multipage/nav-history-apis.html#the-beforeunloadevent-interface
|
||||||
|
[Exposed=Window]
|
||||||
|
interface BeforeUnloadEvent : Event {
|
||||||
|
attribute DOMString returnValue;
|
||||||
|
};
|
|
@ -38,6 +38,7 @@
|
||||||
#include <LibWeb/Cookie/ParsedCookie.h>
|
#include <LibWeb/Cookie/ParsedCookie.h>
|
||||||
#include <LibWeb/DOM/AdoptedStyleSheets.h>
|
#include <LibWeb/DOM/AdoptedStyleSheets.h>
|
||||||
#include <LibWeb/DOM/Attr.h>
|
#include <LibWeb/DOM/Attr.h>
|
||||||
|
#include <LibWeb/DOM/BeforeUnloadEvent.h>
|
||||||
#include <LibWeb/DOM/CDATASection.h>
|
#include <LibWeb/DOM/CDATASection.h>
|
||||||
#include <LibWeb/DOM/Comment.h>
|
#include <LibWeb/DOM/Comment.h>
|
||||||
#include <LibWeb/DOM/CustomEvent.h>
|
#include <LibWeb/DOM/CustomEvent.h>
|
||||||
|
@ -1746,7 +1747,7 @@ WebIDL::ExceptionOr<JS::NonnullGCPtr<Event>> Document::create_event(StringView i
|
||||||
// 2. If interface is an ASCII case-insensitive match for any of the strings in the first column in the following table,
|
// 2. If interface is an ASCII case-insensitive match for any of the strings in the first column in the following table,
|
||||||
// then set constructor to the interface in the second column on the same row as the matching string:
|
// then set constructor to the interface in the second column on the same row as the matching string:
|
||||||
if (Infra::is_ascii_case_insensitive_match(interface, "beforeunloadevent"sv)) {
|
if (Infra::is_ascii_case_insensitive_match(interface, "beforeunloadevent"sv)) {
|
||||||
event = Event::create(realm, FlyString {}); // FIXME: Create BeforeUnloadEvent
|
event = BeforeUnloadEvent::create(realm, FlyString {});
|
||||||
} else if (Infra::is_ascii_case_insensitive_match(interface, "compositionevent"sv)) {
|
} else if (Infra::is_ascii_case_insensitive_match(interface, "compositionevent"sv)) {
|
||||||
event = Event::create(realm, FlyString {}); // FIXME: Create CompositionEvent
|
event = Event::create(realm, FlyString {}); // FIXME: Create CompositionEvent
|
||||||
} else if (Infra::is_ascii_case_insensitive_match(interface, "customevent"sv)) {
|
} else if (Infra::is_ascii_case_insensitive_match(interface, "customevent"sv)) {
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
#include <LibWeb/Bindings/EventTargetPrototype.h>
|
#include <LibWeb/Bindings/EventTargetPrototype.h>
|
||||||
#include <LibWeb/Bindings/MainThreadVM.h>
|
#include <LibWeb/Bindings/MainThreadVM.h>
|
||||||
#include <LibWeb/DOM/AbortSignal.h>
|
#include <LibWeb/DOM/AbortSignal.h>
|
||||||
|
#include <LibWeb/DOM/BeforeUnloadEvent.h>
|
||||||
#include <LibWeb/DOM/DOMEventListener.h>
|
#include <LibWeb/DOM/DOMEventListener.h>
|
||||||
#include <LibWeb/DOM/Document.h>
|
#include <LibWeb/DOM/Document.h>
|
||||||
#include <LibWeb/DOM/Event.h>
|
#include <LibWeb/DOM/Event.h>
|
||||||
|
@ -690,10 +691,20 @@ JS::ThrowCompletionOr<void> EventTarget::process_event_handler_for_event(FlyStri
|
||||||
// FIXME: Ideally, invoke_callback would convert JS::Value to the appropriate return type for us as per the spec, but it doesn't currently.
|
// FIXME: Ideally, invoke_callback would convert JS::Value to the appropriate return type for us as per the spec, but it doesn't currently.
|
||||||
auto return_value = *return_value_or_error.value();
|
auto return_value = *return_value_or_error.value();
|
||||||
|
|
||||||
// FIXME: If event is a BeforeUnloadEvent object and event's type is beforeunload
|
// 5. Process return value as follows:
|
||||||
// If return value is not null, then: (NOTE: When implementing, if we still return a JS::Value from invoke_callback, use is_nullish instead of is_null, as "null" refers to IDL null, which is JS null or undefined)
|
if (is<BeforeUnloadEvent>(event) && event.type() == "beforeunload") {
|
||||||
// 1. Set event's canceled flag.
|
// -> If event is a BeforeUnloadEvent object and event's type is "beforeunload"
|
||||||
// 2. If event's returnValue attribute's value is the empty string, then set event's returnValue attribute's value to return value.
|
// If return value is not null, then:
|
||||||
|
if (!return_value.is_nullish()) {
|
||||||
|
// 1. Set event's canceled flag.
|
||||||
|
event.set_cancelled(true);
|
||||||
|
|
||||||
|
// 2. If event's returnValue attribute's value is the empty string, then set event's returnValue attribute's value to return value.
|
||||||
|
auto& before_unload_event = static_cast<BeforeUnloadEvent&>(event);
|
||||||
|
if (before_unload_event.return_value().is_empty())
|
||||||
|
before_unload_event.set_return_value(TRY(return_value.to_string(vm())));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (special_error_event_handling) {
|
if (special_error_event_handling) {
|
||||||
// -> If special error event handling is true
|
// -> If special error event handling is true
|
||||||
|
|
|
@ -244,6 +244,7 @@ class AbortSignal;
|
||||||
class AbstractRange;
|
class AbstractRange;
|
||||||
class AccessibilityTreeNode;
|
class AccessibilityTreeNode;
|
||||||
class Attr;
|
class Attr;
|
||||||
|
class BeforeUnloadEvent;
|
||||||
class CDATASection;
|
class CDATASection;
|
||||||
class CharacterData;
|
class CharacterData;
|
||||||
class Comment;
|
class Comment;
|
||||||
|
|
|
@ -46,6 +46,7 @@ libweb_js_bindings(DOM/AbstractRange)
|
||||||
libweb_js_bindings(DOM/Attr)
|
libweb_js_bindings(DOM/Attr)
|
||||||
libweb_js_bindings(DOM/AbortController)
|
libweb_js_bindings(DOM/AbortController)
|
||||||
libweb_js_bindings(DOM/AbortSignal)
|
libweb_js_bindings(DOM/AbortSignal)
|
||||||
|
libweb_js_bindings(DOM/BeforeUnloadEvent)
|
||||||
libweb_js_bindings(DOM/CDATASection)
|
libweb_js_bindings(DOM/CDATASection)
|
||||||
libweb_js_bindings(DOM/CharacterData)
|
libweb_js_bindings(DOM/CharacterData)
|
||||||
libweb_js_bindings(DOM/Comment)
|
libweb_js_bindings(DOM/Comment)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue