LibWeb: Hide visible popover when type is changed

This commit is contained in:
Gingeh 2025-01-27 21:38:18 +11:00 committed by Andrew Kaster
commit b056e27afd
Notes: github-actions[bot] 2025-01-30 22:49:27 +00:00
4 changed files with 40 additions and 6 deletions

View file

@ -619,6 +619,27 @@ void HTMLElement::attribute_changed(FlyString const& name, Optional<String> cons
} }
ENUMERATE_GLOBAL_EVENT_HANDLERS(__ENUMERATE) ENUMERATE_GLOBAL_EVENT_HANDLERS(__ENUMERATE)
#undef __ENUMERATE #undef __ENUMERATE
[&]() {
// https://html.spec.whatwg.org/multipage/popover.html#the-popover-attribute:concept-element-attributes-change-ext
// https://whatpr.org/html/9457/popover.html#the-popover-attribute:concept-element-attributes-change-ext
// The following attribute change steps, given element, localName, oldValue, value, and namespace, are used for all HTML elements:
// 1. If namespace is not null, then return.
if (namespace_.has_value())
return;
// 2. If localName is not popover, then return.
if (name != HTML::AttributeNames::popover)
return;
// 3. If element's popover visibility state is in the showing state
// and oldValue and value are in different states,
// then run the hide popover algorithm given element, true, true, false, and true.
if (m_popover_visibility_state == PopoverVisibilityState::Showing
&& popover_value_to_state(old_value) != popover_value_to_state(value))
MUST(hide_popover(FocusPreviousElement::Yes, FireEvents::Yes, ThrowExceptions::No, IgnoreDomState::Yes));
}();
} }
WebIDL::ExceptionOr<void> HTMLElement::cloned(Web::DOM::Node& copy, bool clone_children) const WebIDL::ExceptionOr<void> HTMLElement::cloned(Web::DOM::Node& copy, bool clone_children) const
@ -957,13 +978,8 @@ WebIDL::ExceptionOr<GC::Ref<ElementInternals>> HTMLElement::attach_internals()
return { internals }; return { internals };
} }
// https://html.spec.whatwg.org/multipage/popover.html#dom-popover Optional<String> HTMLElement::popover_value_to_state(Optional<String> value)
Optional<String> HTMLElement::popover() const
{ {
// FIXME: This should probably be `Reflect` in the IDL.
// The popover IDL attribute must reflect the popover attribute, limited to only known values.
auto value = get_attribute(HTML::AttributeNames::popover);
if (!value.has_value()) if (!value.has_value())
return {}; return {};
@ -975,6 +991,15 @@ Optional<String> HTMLElement::popover() const
return "manual"_string; return "manual"_string;
} }
// https://html.spec.whatwg.org/multipage/popover.html#dom-popover
Optional<String> HTMLElement::popover() const
{
// FIXME: This should probably be `Reflect` in the IDL.
// The popover IDL attribute must reflect the popover attribute, limited to only known values.
auto value = get_attribute(HTML::AttributeNames::popover);
return popover_value_to_state(value);
}
// https://html.spec.whatwg.org/multipage/popover.html#dom-popover // https://html.spec.whatwg.org/multipage/popover.html#dom-popover
WebIDL::ExceptionOr<void> HTMLElement::set_popover(Optional<String> value) WebIDL::ExceptionOr<void> HTMLElement::set_popover(Optional<String> value)
{ {

View file

@ -168,6 +168,8 @@ private:
void queue_a_popover_toggle_event_task(String old_state, String new_state); void queue_a_popover_toggle_event_task(String old_state, String new_state);
static Optional<String> popover_value_to_state(Optional<String> value);
// https://html.spec.whatwg.org/multipage/custom-elements.html#attached-internals // https://html.spec.whatwg.org/multipage/custom-elements.html#attached-internals
GC::Ptr<ElementInternals> m_attached_internals; GC::Ptr<ElementInternals> m_attached_internals;

View file

@ -1,2 +1,3 @@
Didn't crash when showing recently hidden popover Didn't crash when showing recently hidden popover
Didn't crash when removing visible popover Didn't crash when removing visible popover
Didn't crash when removing popover with changed attribute

View file

@ -1,6 +1,7 @@
<!DOCTYPE html> <!DOCTYPE html>
<script src="include.js"></script> <script src="include.js"></script>
<div popover id="pop"></div> <div popover id="pop"></div>
<div popover id="pop2"></div>
<script> <script>
test(() => { test(() => {
const pop = document.getElementById("pop"); const pop = document.getElementById("pop");
@ -10,5 +11,10 @@
println("Didn't crash when showing recently hidden popover"); println("Didn't crash when showing recently hidden popover");
pop.remove(); pop.remove();
println("Didn't crash when removing visible popover"); println("Didn't crash when removing visible popover");
const pop2 = document.getElementById("pop2");
pop2.showPopover();
pop2.popover = undefined;
pop2.remove();
println("Didn't crash when removing popover with changed attribute");
}); });
</script> </script>