diff --git a/dom/html/nsGenericHTMLElement.cpp b/dom/html/nsGenericHTMLElement.cpp
index ce3d6b36b7d76..e8063ea3577cd 100644
--- a/dom/html/nsGenericHTMLElement.cpp
+++ b/dom/html/nsGenericHTMLElement.cpp
@@ -668,45 +668,42 @@ constexpr PopoverAttributeState ToPopoverAttributeState(
} // namespace
void nsGenericHTMLElement::AfterSetPopoverAttr() {
- const nsAttrValue* newValue = GetParsedAttr(nsGkAtoms::popover);
-
- const PopoverAttributeState newState = [&newValue]() {
- if (newValue) {
- MOZ_ASSERT(newValue->Type() == nsAttrValue::eEnum);
+ auto mapPopoverState = [](const nsAttrValue* value) -> PopoverAttributeState {
+ if (value) {
+ MOZ_ASSERT(value->Type() == nsAttrValue::eEnum);
const auto popoverAttributeKeyword =
- static_cast(newValue->GetEnumValue());
+ static_cast(value->GetEnumValue());
return ToPopoverAttributeState(popoverAttributeKeyword);
}
// The missing value default is the no popover state, see
// .
return PopoverAttributeState::None;
- }();
+ };
+
+ PopoverAttributeState newState =
+ mapPopoverState(GetParsedAttr(nsGkAtoms::popover));
const PopoverAttributeState oldState = GetPopoverAttributeState();
if (newState != oldState) {
- EnsurePopoverData().SetPopoverAttributeState(newState);
-
- HidePopoverInternal(/* aFocusPreviousElement = */ true,
- /* aFireEvents = */ true, IgnoreErrors());
-
- // In case `HidePopoverInternal` changed the state, keep the corresponding
- // changes and don't overwrite anything here.
- if (newState == GetPopoverAttributeState()) {
- if (newState == PopoverAttributeState::None) {
- // `HidePopoverInternal` above didn't remove the element from the top
- // layer, because in that call, the element's popover attribute state
- // was already `None`. Revisit this, when the spec is corrected
- // (bug 1835811).
- OwnerDoc()->RemovePopoverFromTopLayer(*this);
-
- ClearPopoverData();
- RemoveStates(ElementState::POPOVER_OPEN);
- } else {
- // TODO: what if `HidePopoverInternal` called `ShowPopup()`?
- PopoverPseudoStateUpdate(false, true);
- }
+ PopoverPseudoStateUpdate(false, true);
+
+ if (IsPopoverOpen()) {
+ HidePopoverInternal(/* aFocusPreviousElement = */ true,
+ /* aFireEvents = */ true, IgnoreErrors());
+ // Event handlers could have removed the popover attribute, or changed
+ // its value.
+ newState = mapPopoverState(GetParsedAttr(nsGkAtoms::popover));
+ }
+
+ if (newState == PopoverAttributeState::None) {
+ OwnerDoc()->RemovePopoverFromTopLayer(*this);
+ ClearPopoverData();
+ RemoveStates(ElementState::POPOVER_OPEN);
+ } else {
+ // TODO: what if `HidePopoverInternal` called `ShowPopup()`?
+ EnsurePopoverData().SetPopoverAttributeState(newState);
}
}
}
diff --git a/testing/web-platform/meta/html/semantics/popovers/popover-attribute-basic.html.ini b/testing/web-platform/meta/html/semantics/popovers/popover-attribute-basic.html.ini
index 9d7dbe1296447..fd6307273cae4 100644
--- a/testing/web-platform/meta/html/semantics/popovers/popover-attribute-basic.html.ini
+++ b/testing/web-platform/meta/html/semantics/popovers/popover-attribute-basic.html.ini
@@ -14,30 +14,12 @@
[Changing a popover from auto to undefined (via attr), and then auto during 'beforetoggle' works]
expected: FAIL
- [Changing a popover from auto to undefined (via attr), and then manual during 'beforetoggle' works]
- expected: FAIL
-
- [Changing a popover from auto to undefined (via attr), and then invalid during 'beforetoggle' works]
- expected: FAIL
-
- [Changing a popover from auto to undefined (via attr), and then null during 'beforetoggle' works]
- expected: FAIL
-
[Changing a popover from manual to auto (via attr), and then auto during 'beforetoggle' works]
expected: FAIL
[Changing a popover from manual to undefined (via attr), and then auto during 'beforetoggle' works]
expected: FAIL
- [Changing a popover from manual to undefined (via attr), and then manual during 'beforetoggle' works]
- expected: FAIL
-
- [Changing a popover from manual to undefined (via attr), and then invalid during 'beforetoggle' works]
- expected: FAIL
-
- [Changing a popover from manual to undefined (via attr), and then null during 'beforetoggle' works]
- expected: FAIL
-
[Changing a popover from auto to manual (via idl), and then auto during 'beforetoggle' works]
expected: FAIL
@@ -58,27 +40,3 @@
[Changing a popover from manual to undefined (via idl), and then auto during 'beforetoggle' works]
expected: FAIL
-
- [Changing a popover from auto to null (via idl), and then manual during 'beforetoggle' works]
- expected: FAIL
-
- [Changing a popover from auto to null (via idl), and then invalid during 'beforetoggle' works]
- expected: FAIL
-
- [Changing a popover from auto to undefined (via idl), and then manual during 'beforetoggle' works]
- expected: FAIL
-
- [Changing a popover from auto to undefined (via idl), and then invalid during 'beforetoggle' works]
- expected: FAIL
-
- [Changing a popover from manual to null (via idl), and then manual during 'beforetoggle' works]
- expected: FAIL
-
- [Changing a popover from manual to null (via idl), and then invalid during 'beforetoggle' works]
- expected: FAIL
-
- [Changing a popover from manual to undefined (via idl), and then manual during 'beforetoggle' works]
- expected: FAIL
-
- [Changing a popover from manual to undefined (via idl), and then invalid during 'beforetoggle' works]
- expected: FAIL