Loading dom/base/Document.cpp +37 −19 Original line number Diff line number Diff line Loading @@ -15002,6 +15002,18 @@ void Document::HideAllPopoversUntil(nsINode& aEndpoint, return; } // https://github.com/whatwg/html/pull/9198 auto needRepeatingHide = [&]() { auto autoList = AutoPopoverList(); return autoList.Contains(&aEndpoint) && &aEndpoint != autoList.LastElement(); }; MOZ_ASSERT((&aEndpoint)->IsElement() && (&aEndpoint)->AsElement()->IsAutoPopover()); bool repeatingHide = false; bool fireEvents = aFireEvents; do { RefPtr<const Element> lastToHide = nullptr; bool foundEndpoint = false; for (const Element* popover : AutoPopoverList()) { Loading @@ -15023,8 +15035,14 @@ void Document::HideAllPopoversUntil(nsINode& aEndpoint, if (!topmost) { break; } HidePopover(*topmost, aFocusPreviousElement, aFireEvents, IgnoreErrors()); HidePopover(*topmost, aFocusPreviousElement, fireEvents, IgnoreErrors()); } repeatingHide = needRepeatingHide(); if (repeatingHide) { fireEvents = false; } } while (repeatingHide); } MOZ_CAN_RUN_SCRIPT_BOUNDARY void Loading dom/html/nsGenericHTMLElement.cpp +2 −2 Original line number Diff line number Diff line Loading @@ -3369,9 +3369,9 @@ void nsGenericHTMLElement::ShowPopover(ErrorResult& aRv) { bool shouldRestoreFocus = false; nsWeakPtr originallyFocusedElement; if (IsAutoPopover()) { RefPtr<Element> ancestor = GetTopmostPopoverAncestor(); RefPtr<nsINode> ancestor = GetTopmostPopoverAncestor(); if (!ancestor) { ancestor = document->GetDocumentElement(); ancestor = document; } document->HideAllPopoversUntil(*ancestor, false, true); Loading testing/web-platform/tests/html/semantics/popovers/popover-light-dismiss.html +27 −0 Original line number Diff line number Diff line Loading @@ -587,3 +587,30 @@ promise_test(async () => { p20.hidePopover(); // Cleanup },'Show an unrelated popover during "hide popover"'); </script> <div id=p21 popover>21 <div id=p22 popover>22</div> <div id=p23 popover>23</div> <div id=p24 popover>24</div> </div> <script> promise_test(async () => { p21.showPopover(); p22.showPopover(); let events = []; const logEvents = (e) => { events.push(`${e.newState === 'open' ? 'show' : 'hide'} ${e.target.id}`) }; p22.addEventListener('beforetoggle', (e) => { logEvents(e); p24.showPopover() }); p23.addEventListener('beforetoggle', logEvents); p24.addEventListener('beforetoggle', logEvents); p23.showPopover(); assert_array_equals(events, ['show p23', 'hide p22', 'show p24'], 'hiding p24 does not fire event'); assert_false(p22.matches(':popover-open')); assert_true(p23.matches(':popover-open')); assert_false(p24.matches(':popover-open')); p21.hidePopover(); // Cleanup },'Show other auto popover during "hide all popover until"'); </script> Loading
dom/base/Document.cpp +37 −19 Original line number Diff line number Diff line Loading @@ -15002,6 +15002,18 @@ void Document::HideAllPopoversUntil(nsINode& aEndpoint, return; } // https://github.com/whatwg/html/pull/9198 auto needRepeatingHide = [&]() { auto autoList = AutoPopoverList(); return autoList.Contains(&aEndpoint) && &aEndpoint != autoList.LastElement(); }; MOZ_ASSERT((&aEndpoint)->IsElement() && (&aEndpoint)->AsElement()->IsAutoPopover()); bool repeatingHide = false; bool fireEvents = aFireEvents; do { RefPtr<const Element> lastToHide = nullptr; bool foundEndpoint = false; for (const Element* popover : AutoPopoverList()) { Loading @@ -15023,8 +15035,14 @@ void Document::HideAllPopoversUntil(nsINode& aEndpoint, if (!topmost) { break; } HidePopover(*topmost, aFocusPreviousElement, aFireEvents, IgnoreErrors()); HidePopover(*topmost, aFocusPreviousElement, fireEvents, IgnoreErrors()); } repeatingHide = needRepeatingHide(); if (repeatingHide) { fireEvents = false; } } while (repeatingHide); } MOZ_CAN_RUN_SCRIPT_BOUNDARY void Loading
dom/html/nsGenericHTMLElement.cpp +2 −2 Original line number Diff line number Diff line Loading @@ -3369,9 +3369,9 @@ void nsGenericHTMLElement::ShowPopover(ErrorResult& aRv) { bool shouldRestoreFocus = false; nsWeakPtr originallyFocusedElement; if (IsAutoPopover()) { RefPtr<Element> ancestor = GetTopmostPopoverAncestor(); RefPtr<nsINode> ancestor = GetTopmostPopoverAncestor(); if (!ancestor) { ancestor = document->GetDocumentElement(); ancestor = document; } document->HideAllPopoversUntil(*ancestor, false, true); Loading
testing/web-platform/tests/html/semantics/popovers/popover-light-dismiss.html +27 −0 Original line number Diff line number Diff line Loading @@ -587,3 +587,30 @@ promise_test(async () => { p20.hidePopover(); // Cleanup },'Show an unrelated popover during "hide popover"'); </script> <div id=p21 popover>21 <div id=p22 popover>22</div> <div id=p23 popover>23</div> <div id=p24 popover>24</div> </div> <script> promise_test(async () => { p21.showPopover(); p22.showPopover(); let events = []; const logEvents = (e) => { events.push(`${e.newState === 'open' ? 'show' : 'hide'} ${e.target.id}`) }; p22.addEventListener('beforetoggle', (e) => { logEvents(e); p24.showPopover() }); p23.addEventListener('beforetoggle', logEvents); p24.addEventListener('beforetoggle', logEvents); p23.showPopover(); assert_array_equals(events, ['show p23', 'hide p22', 'show p24'], 'hiding p24 does not fire event'); assert_false(p22.matches(':popover-open')); assert_true(p23.matches(':popover-open')); assert_false(p24.matches(':popover-open')); p21.hidePopover(); // Cleanup },'Show other auto popover during "hide all popover until"'); </script>