mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-06-09 17:44:56 +09:00
LibWeb: Correctly implement event listeners default passive attribute
This commit implements the default value of the passive attribute of event listeners according to the spec.
This commit is contained in:
parent
4c7cd05078
commit
08589741f5
Notes:
github-actions[bot]
2024-12-25 14:58:22 +00:00
Author: https://github.com/skyz1
Commit: 08589741f5
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/3035
Reviewed-by: https://github.com/konradekk
Reviewed-by: https://github.com/tcl3 ✅
6 changed files with 82 additions and 49 deletions
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2022, Andreas Kling <andreas@ladybird.org>
|
||||
* Copyright (c) 2024, Glenn Skrzypczak <glenn.skrzypczak@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
@ -35,8 +36,8 @@ public:
|
|||
// capture (a boolean, initially false)
|
||||
bool capture { false };
|
||||
|
||||
// passive (a boolean, initially false)
|
||||
bool passive { false };
|
||||
// passive (null or a boolean, initially null)
|
||||
Optional<bool> passive;
|
||||
|
||||
// once (a boolean, initially false)
|
||||
bool once { false };
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2020-2022, Andreas Kling <andreas@ladybird.org>
|
||||
* Copyright (c) 2024, Glenn Skrzypczak <glenn.skrzypczak@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
@ -81,7 +82,7 @@ bool EventDispatcher::inner_invoke(Event& event, Vector<GC::Root<DOM::DOMEventLi
|
|||
}
|
||||
|
||||
// 9. If listener’s passive is true, then set event’s in passive listener flag.
|
||||
if (listener->passive)
|
||||
if (listener->passive == true)
|
||||
event.set_in_passive_listener(true);
|
||||
|
||||
// FIXME: 10. If global is a Window object, then record timing info for event listener given event and listener.
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
/*
|
||||
* Copyright (c) 2020-2022, Andreas Kling <andreas@ladybird.org>
|
||||
* Copyright (c) 2022, Luke Wilde <lukew@serenityos.org>
|
||||
* Copyright (c) 2024, Glenn Skrzypczak <glenn.skrzypczak@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
@ -110,7 +111,7 @@ static bool flatten_event_listener_options(Variant<AddEventListenerOptions, bool
|
|||
|
||||
struct FlattenedAddEventListenerOptions {
|
||||
bool capture { false };
|
||||
bool passive { false };
|
||||
Optional<bool> passive;
|
||||
bool once { false };
|
||||
GC::Ptr<AbortSignal> signal;
|
||||
};
|
||||
|
@ -121,22 +122,25 @@ static FlattenedAddEventListenerOptions flatten_add_event_listener_options(Varia
|
|||
// 1. Let capture be the result of flattening options.
|
||||
bool capture = flatten_event_listener_options(options);
|
||||
|
||||
// 2. Let once and passive be false.
|
||||
// 2. Let once be false.
|
||||
bool once = false;
|
||||
bool passive = false;
|
||||
|
||||
// 3. Let signal be null.
|
||||
// 3. Let passive and signal be null.
|
||||
Optional<bool> passive;
|
||||
GC::Ptr<AbortSignal> signal;
|
||||
|
||||
// 4. If options is a dictionary, then:
|
||||
if (options.has<AddEventListenerOptions>()) {
|
||||
auto& add_event_listener_options = options.get<AddEventListenerOptions>();
|
||||
auto const& add_event_listener_options = options.get<AddEventListenerOptions>();
|
||||
|
||||
// 1. Set passive to options["passive"] and once to options["once"].
|
||||
passive = add_event_listener_options.passive;
|
||||
// 1. Set once to options["once"].
|
||||
once = add_event_listener_options.once;
|
||||
|
||||
// 2. If options["signal"] exists, then set signal to options["signal"].
|
||||
// 2. If options["passive"] exists, then set passive to options["passive"].
|
||||
if (add_event_listener_options.passive.has_value())
|
||||
passive = add_event_listener_options.passive;
|
||||
|
||||
// 3. If options["signal"] exists, then set signal to options["signal"].
|
||||
if (add_event_listener_options.signal)
|
||||
signal = add_event_listener_options.signal;
|
||||
}
|
||||
|
@ -145,6 +149,28 @@ static FlattenedAddEventListenerOptions flatten_add_event_listener_options(Varia
|
|||
return FlattenedAddEventListenerOptions { .capture = capture, .passive = passive, .once = once, .signal = signal.ptr() };
|
||||
}
|
||||
|
||||
// https://dom.spec.whatwg.org/#default-passive-value
|
||||
static bool default_passive_value(FlyString const& type, EventTarget* event_target)
|
||||
{
|
||||
// 1. Return true if all of the following are true:
|
||||
// - type is one of "touchstart", "touchmove", "wheel", or "mousewheel".
|
||||
// - eventTarget is a Window object, or is a node whose node document is eventTarget, or is a node whose node document’s document element is eventTarget,
|
||||
// or is a node whose node document’s body element is eventTarget.
|
||||
if (AK::first_is_one_of(type, "touchstart"sv, "touchmove"sv, "wheel"sv, "mousewheel"sv)) {
|
||||
if (is<HTML::Window>(event_target))
|
||||
return true;
|
||||
|
||||
if (is<Node>(event_target)) {
|
||||
auto* node = verify_cast<Node>(event_target);
|
||||
if (&node->document() == event_target || node->document().document_element() == event_target || node->document().body() == event_target)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// 2. Return false.
|
||||
return false;
|
||||
}
|
||||
|
||||
// https://dom.spec.whatwg.org/#dom-eventtarget-addeventlistener
|
||||
void EventTarget::add_event_listener(FlyString const& type, IDLEventListener* callback, Variant<AddEventListenerOptions, bool> const& options)
|
||||
{
|
||||
|
@ -186,7 +212,12 @@ void EventTarget::add_an_event_listener(DOMEventListener& listener)
|
|||
if (!listener.callback)
|
||||
return;
|
||||
|
||||
// 4. If eventTarget’s event listener list does not contain an event listener whose type is listener’s type, callback is listener’s callback,
|
||||
// 4. If listener’s passive is null, then set it to the default passive value given listener’s type and eventTarget.
|
||||
if (!listener.passive.has_value()) {
|
||||
listener.passive = default_passive_value(listener.type, this);
|
||||
}
|
||||
|
||||
// 5. If eventTarget’s event listener list does not contain an event listener whose type is listener’s type, callback is listener’s callback,
|
||||
// and capture is listener’s capture, then append listener to eventTarget’s event listener list.
|
||||
auto it = event_listener_list.find_if([&](auto& entry) {
|
||||
return entry->type == listener.type
|
||||
|
@ -196,7 +227,7 @@ void EventTarget::add_an_event_listener(DOMEventListener& listener)
|
|||
if (it == event_listener_list.end())
|
||||
event_listener_list.append(listener);
|
||||
|
||||
// 5. If listener’s signal is not null, then add the following abort steps to it:
|
||||
// 6. If listener’s signal is not null, then add the following abort steps to it:
|
||||
if (listener.signal) {
|
||||
// NOTE: `this` and `listener` are protected by AbortSignal using GC::HeapFunction.
|
||||
listener.signal->add_abort_algorithm([this, &listener] {
|
||||
|
|
|
@ -20,7 +20,7 @@ dictionary EventListenerOptions {
|
|||
};
|
||||
|
||||
dictionary AddEventListenerOptions : EventListenerOptions {
|
||||
boolean passive = false;
|
||||
boolean passive;
|
||||
boolean once = false;
|
||||
AbortSignal signal;
|
||||
};
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2020-2022, Andreas Kling <andreas@ladybird.org>
|
||||
* Copyright (c) 2024, Glenn Skrzypczak <glenn.skrzypczak@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
@ -19,7 +20,7 @@ struct EventListenerOptions {
|
|||
};
|
||||
|
||||
struct AddEventListenerOptions : public EventListenerOptions {
|
||||
bool passive { false };
|
||||
Optional<bool> passive;
|
||||
bool once { false };
|
||||
GC::Ptr<AbortSignal> signal;
|
||||
};
|
||||
|
|
|
@ -2,82 +2,81 @@ Harness status: OK
|
|||
|
||||
Found 100 tests
|
||||
|
||||
68 Pass
|
||||
32 Fail
|
||||
Fail touchstart listener is passive by default for Window
|
||||
Fail touchstart listener is passive with {passive:undefined} for Window
|
||||
100 Pass
|
||||
Pass touchstart listener is passive by default for Window
|
||||
Pass touchstart listener is passive with {passive:undefined} for Window
|
||||
Pass touchstart listener is non-passive with {passive:false} for Window
|
||||
Pass touchstart listener is passive with {passive:true} for Window
|
||||
Fail touchstart listener is passive by default for HTMLDocument
|
||||
Fail touchstart listener is passive with {passive:undefined} for HTMLDocument
|
||||
Pass touchstart listener is passive by default for HTMLDocument
|
||||
Pass touchstart listener is passive with {passive:undefined} for HTMLDocument
|
||||
Pass touchstart listener is non-passive with {passive:false} for HTMLDocument
|
||||
Pass touchstart listener is passive with {passive:true} for HTMLDocument
|
||||
Fail touchstart listener is passive by default for HTMLHtmlElement
|
||||
Fail touchstart listener is passive with {passive:undefined} for HTMLHtmlElement
|
||||
Pass touchstart listener is passive by default for HTMLHtmlElement
|
||||
Pass touchstart listener is passive with {passive:undefined} for HTMLHtmlElement
|
||||
Pass touchstart listener is non-passive with {passive:false} for HTMLHtmlElement
|
||||
Pass touchstart listener is passive with {passive:true} for HTMLHtmlElement
|
||||
Fail touchstart listener is passive by default for HTMLBodyElement
|
||||
Fail touchstart listener is passive with {passive:undefined} for HTMLBodyElement
|
||||
Pass touchstart listener is passive by default for HTMLBodyElement
|
||||
Pass touchstart listener is passive with {passive:undefined} for HTMLBodyElement
|
||||
Pass touchstart listener is non-passive with {passive:false} for HTMLBodyElement
|
||||
Pass touchstart listener is passive with {passive:true} for HTMLBodyElement
|
||||
Pass touchstart listener is non-passive by default for HTMLDivElement
|
||||
Pass touchstart listener is non-passive with {passive:undefined} for HTMLDivElement
|
||||
Pass touchstart listener is non-passive with {passive:false} for HTMLDivElement
|
||||
Pass touchstart listener is passive with {passive:true} for HTMLDivElement
|
||||
Fail touchmove listener is passive by default for Window
|
||||
Fail touchmove listener is passive with {passive:undefined} for Window
|
||||
Pass touchmove listener is passive by default for Window
|
||||
Pass touchmove listener is passive with {passive:undefined} for Window
|
||||
Pass touchmove listener is non-passive with {passive:false} for Window
|
||||
Pass touchmove listener is passive with {passive:true} for Window
|
||||
Fail touchmove listener is passive by default for HTMLDocument
|
||||
Fail touchmove listener is passive with {passive:undefined} for HTMLDocument
|
||||
Pass touchmove listener is passive by default for HTMLDocument
|
||||
Pass touchmove listener is passive with {passive:undefined} for HTMLDocument
|
||||
Pass touchmove listener is non-passive with {passive:false} for HTMLDocument
|
||||
Pass touchmove listener is passive with {passive:true} for HTMLDocument
|
||||
Fail touchmove listener is passive by default for HTMLHtmlElement
|
||||
Fail touchmove listener is passive with {passive:undefined} for HTMLHtmlElement
|
||||
Pass touchmove listener is passive by default for HTMLHtmlElement
|
||||
Pass touchmove listener is passive with {passive:undefined} for HTMLHtmlElement
|
||||
Pass touchmove listener is non-passive with {passive:false} for HTMLHtmlElement
|
||||
Pass touchmove listener is passive with {passive:true} for HTMLHtmlElement
|
||||
Fail touchmove listener is passive by default for HTMLBodyElement
|
||||
Fail touchmove listener is passive with {passive:undefined} for HTMLBodyElement
|
||||
Pass touchmove listener is passive by default for HTMLBodyElement
|
||||
Pass touchmove listener is passive with {passive:undefined} for HTMLBodyElement
|
||||
Pass touchmove listener is non-passive with {passive:false} for HTMLBodyElement
|
||||
Pass touchmove listener is passive with {passive:true} for HTMLBodyElement
|
||||
Pass touchmove listener is non-passive by default for HTMLDivElement
|
||||
Pass touchmove listener is non-passive with {passive:undefined} for HTMLDivElement
|
||||
Pass touchmove listener is non-passive with {passive:false} for HTMLDivElement
|
||||
Pass touchmove listener is passive with {passive:true} for HTMLDivElement
|
||||
Fail wheel listener is passive by default for Window
|
||||
Fail wheel listener is passive with {passive:undefined} for Window
|
||||
Pass wheel listener is passive by default for Window
|
||||
Pass wheel listener is passive with {passive:undefined} for Window
|
||||
Pass wheel listener is non-passive with {passive:false} for Window
|
||||
Pass wheel listener is passive with {passive:true} for Window
|
||||
Fail wheel listener is passive by default for HTMLDocument
|
||||
Fail wheel listener is passive with {passive:undefined} for HTMLDocument
|
||||
Pass wheel listener is passive by default for HTMLDocument
|
||||
Pass wheel listener is passive with {passive:undefined} for HTMLDocument
|
||||
Pass wheel listener is non-passive with {passive:false} for HTMLDocument
|
||||
Pass wheel listener is passive with {passive:true} for HTMLDocument
|
||||
Fail wheel listener is passive by default for HTMLHtmlElement
|
||||
Fail wheel listener is passive with {passive:undefined} for HTMLHtmlElement
|
||||
Pass wheel listener is passive by default for HTMLHtmlElement
|
||||
Pass wheel listener is passive with {passive:undefined} for HTMLHtmlElement
|
||||
Pass wheel listener is non-passive with {passive:false} for HTMLHtmlElement
|
||||
Pass wheel listener is passive with {passive:true} for HTMLHtmlElement
|
||||
Fail wheel listener is passive by default for HTMLBodyElement
|
||||
Fail wheel listener is passive with {passive:undefined} for HTMLBodyElement
|
||||
Pass wheel listener is passive by default for HTMLBodyElement
|
||||
Pass wheel listener is passive with {passive:undefined} for HTMLBodyElement
|
||||
Pass wheel listener is non-passive with {passive:false} for HTMLBodyElement
|
||||
Pass wheel listener is passive with {passive:true} for HTMLBodyElement
|
||||
Pass wheel listener is non-passive by default for HTMLDivElement
|
||||
Pass wheel listener is non-passive with {passive:undefined} for HTMLDivElement
|
||||
Pass wheel listener is non-passive with {passive:false} for HTMLDivElement
|
||||
Pass wheel listener is passive with {passive:true} for HTMLDivElement
|
||||
Fail mousewheel listener is passive by default for Window
|
||||
Fail mousewheel listener is passive with {passive:undefined} for Window
|
||||
Pass mousewheel listener is passive by default for Window
|
||||
Pass mousewheel listener is passive with {passive:undefined} for Window
|
||||
Pass mousewheel listener is non-passive with {passive:false} for Window
|
||||
Pass mousewheel listener is passive with {passive:true} for Window
|
||||
Fail mousewheel listener is passive by default for HTMLDocument
|
||||
Fail mousewheel listener is passive with {passive:undefined} for HTMLDocument
|
||||
Pass mousewheel listener is passive by default for HTMLDocument
|
||||
Pass mousewheel listener is passive with {passive:undefined} for HTMLDocument
|
||||
Pass mousewheel listener is non-passive with {passive:false} for HTMLDocument
|
||||
Pass mousewheel listener is passive with {passive:true} for HTMLDocument
|
||||
Fail mousewheel listener is passive by default for HTMLHtmlElement
|
||||
Fail mousewheel listener is passive with {passive:undefined} for HTMLHtmlElement
|
||||
Pass mousewheel listener is passive by default for HTMLHtmlElement
|
||||
Pass mousewheel listener is passive with {passive:undefined} for HTMLHtmlElement
|
||||
Pass mousewheel listener is non-passive with {passive:false} for HTMLHtmlElement
|
||||
Pass mousewheel listener is passive with {passive:true} for HTMLHtmlElement
|
||||
Fail mousewheel listener is passive by default for HTMLBodyElement
|
||||
Fail mousewheel listener is passive with {passive:undefined} for HTMLBodyElement
|
||||
Pass mousewheel listener is passive by default for HTMLBodyElement
|
||||
Pass mousewheel listener is passive with {passive:undefined} for HTMLBodyElement
|
||||
Pass mousewheel listener is non-passive with {passive:false} for HTMLBodyElement
|
||||
Pass mousewheel listener is passive with {passive:true} for HTMLBodyElement
|
||||
Pass mousewheel listener is non-passive by default for HTMLDivElement
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue