From 04c3483663f52beaaddfdf09bdf2fe5ee4b5d8f6 Mon Sep 17 00:00:00 2001 From: Jake Archibald Date: Wed, 8 Apr 2026 13:45:40 +0100 Subject: [PATCH 01/24] Show popover fixed --- source | 372 ++++++++++++++++----------------------------------------- 1 file changed, 101 insertions(+), 271 deletions(-) diff --git a/source b/source index cd0d47cc723..3e808c31312 100644 --- a/source +++ b/source @@ -65771,18 +65771,14 @@ interface HTMLDialogElement : HTMLElement {
  • Let document be this's node document.

  • Let hideUntil be the result of running topmost popover ancestor - given this, document's showing hint popover list, null, and - false.

  • - -
  • If hideUntil is null, then set hideUntil to the result of running - topmost popover ancestor given this, document's - showing auto popover list, null, and false.

  • + given this, null, and false.

  • If hideUntil is null, then set hideUntil to document.

  • -
  • Run hide all popovers until given - hideUntil, false, and true.

  • +
  • Run hide popover stack until given hideUntil, document, Hint, false, and true.

  • + +
  • Run hide popover stack until given hideUntil, document, Auto, false, and true.

  • Run the dialog focusing steps given this.

  • @@ -66038,18 +66034,14 @@ interface HTMLDialogElement : HTMLElement {
  • Let document be subject's node document.

  • Let hideUntil be the result of running topmost popover ancestor - given subject, document's showing hint popover list, null, and - false.

  • - -
  • If hideUntil is null, then set hideUntil to the result of running - topmost popover ancestor given subject, document's - showing auto popover list, null, and false.

  • + given subject, null, and false.

  • If hideUntil is null, then set hideUntil to document.

  • -
  • Run hide all popovers until given - hideUntil, false, and true.

  • +
  • Run hide popover stack until given hideUntil, document, Hint, false, and true.

  • + +
  • Run hide popover stack until given hideUntil, document, Auto, false, and true.

  • Run the dialog focusing steps given subject.

  • @@ -91252,6 +91244,32 @@ dictionary DragEventInit : MouseEventInit {
  • If the result of running check popover validity given element, false, throwExceptions, and null is false, then return.

  • +
  • +

    Let checkAncestor be the following steps:

    + +
      +
    1. Let ancestor be the result of running the topmost popover ancestor algorithm given element, source, and true.

    2. + +
    3. +

      If ancestor is not null, element's popover attribute is in the Auto state, and ancestor's popover attribute is in the Hint state, then: +

      + +
        +
      1. If throwExceptions is true, then throw an + "InvalidStateError" DOMException.

      2. + +
      3. Return false.

      4. +
      + +

      Hint popovers are lower priority than Auto popovers, so an Auto popover cannot have a Hint popover as a 'parent'.

      +
    4. +
    +
  • + +
  • If the result of running checkAncestor is false, then return.

  • +
  • Let document be element's node document.

  • Assert: element's popover trigger is null.

  • @@ -91294,90 +91312,29 @@ dictionary DragEventInit : MouseEventInit { changed its popover attribute.

    -
  • Let shouldRestoreFocus be false.

  • - -
  • Let originalType be the current state of element's popover attribute.

  • - -
  • Let stackToAppendTo be null.

  • - -
  • Let autoAncestor be the result of running the topmost popover - ancestor algorithm given element, document's showing auto - popover list, source, and true.

  • - -
  • Let hintAncestor be the result of running the topmost popover - ancestor algorithm given element, document's showing hint - popover list, source, and true.

  • -
  • -

    If originalType is the Auto state, - then:

    - -
      -
    1. Run close entire popover list given document's showing - hint popover list, shouldRestoreFocus, and fireEvents.

    2. - -
    3. Let ancestor be the result of running the topmost popover - ancestor algorithm given element, document's showing auto - popover list, source, and true.

    4. - -
    5. If ancestor is null, then set ancestor to - document.

    6. - -
    7. Run hide all popovers until given - ancestor, shouldRestoreFocus, and fireEvents.

    8. +

      If the result of running checkAncestor is false, then run cleanupShowingFlag and return.

      -
    9. Set stackToAppendTo to "auto".

    10. -
    +

    These checks are performed again because firing the beforetoggle event could have modified element state.

  • -
  • -

    If originalType is the Hint state, - then:

    - -
      -
    1. -

      If hintAncestor is not null, then:

      - -
        -
      1. Run hide all popovers until given - hintAncestor, shouldRestoreFocus, and fireEvents.

      2. - -
      3. Set stackToAppendTo to "hint".

      4. -
      -
    2. - -
    3. -

      Otherwise:

      - -
        -
      1. Run close entire popover list given document's showing - hint popover list, shouldRestoreFocus, and fireEvents.

      2. +
      3. Let shouldRestoreFocus be false.

      4. -
      5. -

        If autoAncestor is not null, then:

        +
      6. Let originalType be the current state of element's popover attribute.

      7. -
          -
        1. Run hide all popovers until given - autoAncestor, shouldRestoreFocus, and fireEvents.

        2. +
        3. Let ancestor be the result of running the topmost popover ancestor algorithm given element, source, and true.

        4. -
        5. Set stackToAppendTo to "auto".

        6. -
        - +
      8. If originalType is the Auto or Hint state, then run hide popover stack until given ancestor, document, Hint, shouldRestoreFocus, and fireEvents.

      9. -
      10. Otherwise, set stackToAppendTo to "hint".

      11. -
      -
    4. -
    -
  • +
  • If originalType is the Auto state, then run hide popover stack until given ancestor, document, Auto, shouldRestoreFocus, and fireEvents.

  • If originalType is Auto or Hint, then:

      -
    1. Assert: stackToAppendTo is not null.

    2. -
    3. If originalType is not equal to the value of element's popover attribute, then:

      @@ -91395,13 +91352,18 @@ dictionary DragEventInit : MouseEventInit { false, throwExceptions, and document is false, then run cleanupShowingFlag and return.

      -

      Check popover validity is called again because running hide all popovers until above could have fired the +

      Check popover validity is called again because running hide popover stack until above could have fired the beforetoggle event, and an event handler could have disconnected this element or changed its popover attribute.

    4. +
    5. +

      If the result of running checkAncestor is false, then run cleanupShowingFlag and return.

      + +

      These checks are performed again because running hide popover stack until above could have fired the beforetoggle event, and an event handler could have altered DOM state.

      +
    6. +
    7. If the result of running topmost auto or hint popover on document is null, then set shouldRestoreFocus to @@ -91412,7 +91374,7 @@ dictionary DragEventInit : MouseEventInit {

    8. -

      If stackToAppendTo is "auto":

      +

      If originalType is Auto:

      1. Assert: document's showing auto popover list does @@ -91425,8 +91387,7 @@ dictionary DragEventInit : MouseEventInit {

        Otherwise:

          -
        1. Assert: stackToAppendTo is "hint".

        2. +
        3. Assert: originalType is Hint.

        4. Assert: document's showing hint popover list does not contain element.

        5. @@ -91478,6 +91439,8 @@ dictionary DragEventInit : MouseEventInit { data-x="attr-popover-none-state">No Popover state, then set element's previously focused element to originallyFocusedElement.

          +
        6. If originalType is Hint and ancestor's opened in popover mode is "auto", then set document's hint stack parent to ancestor.

        7. +
        8. Queue a popover toggle event task given element, "closed", "open", and source.

        9. @@ -91583,7 +91546,7 @@ dictionary DragEventInit : MouseEventInit { or "hint", then:

            -
          1. Run hide all popovers until given +

          2. Run hide all popovers until TODO FIX given element, focusPreviousElement, and fireEvents.

          3. @@ -91591,8 +91554,7 @@ dictionary DragEventInit : MouseEventInit { true, throwExceptions, and null is false, then run cleanupSteps and return.

            -

            Check popover validity is called again because running hide all popovers until could have disconnected +

            Check popover validity is called again because running hide all popovers until TODO fix could have disconnected element or changed its popover attribute.

          @@ -91615,8 +91577,7 @@ dictionary DragEventInit : MouseEventInit { element.

        10. If autoPopoverListContainsElement is true and document's - showing auto popover list's last item is not element, then run hide all popovers until given element, + showing auto popover list's last item is not element, then run hide all popovers until TODO fix given element, focusPreviousElement, and false.

        11. @@ -91716,138 +91677,58 @@ dictionary DragEventInit : MouseEventInit {
          -

          To hide all popovers until, given an HTML element or Document endpoint, a boolean - focusPreviousElement, and a boolean fireEvents:

          +

          To hide popover stack until, given an HTML + element or null endpoint, Document document, + an Auto or Hint stackType, + a boolean focusPreviousElement, and a boolean fireEvents:

            -
          1. If endpoint is an HTML element and - endpoint is not in the popover showing - state, then return.

          2. +
          3. Let popoverList be document's showing auto popover list if stackType is Auto, otherwise document's showing hint popover list.

          4. -
          5. Let document be endpoint's node document.

          6. +
          7. Let lastHideIndex be 0 if popoverList does not contain endpoint, otherwise the index of endpoint in popoverList plus 1.

          8. -
          9. Assert: endpoint is a Document or - endpoint's popover visibility state is showing.

          10. - -
          11. Assert: endpoint is a Document or - endpoint's popover attribute is in the Auto state or endpoint's popover attribute is in the Hint state.

          12. - -
          13. -

            If endpoint is a Document:

            - -
              -
            1. Run close entire popover list given document's showing - hint popover list, focusPreviousElement, and fireEvents.

            2. - -
            3. Run close entire popover list given document's showing - auto popover list, focusPreviousElement, and fireEvents.

            4. - -
            5. Return.

            6. -
            -
          14. - -
          15. -

            If document's showing hint popover list contains - endpoint:

            - -
              -
            1. Assert: endpoint's popover - attribute is in the Hint state.

            2. - -
            3. Run hide popover stack until given endpoint, - document's showing hint popover list, focusPreviousElement, - and fireEvents.

            4. - -
            5. Return.

            6. -
            -
          16. +
          17. Let toHide be a slice of popoverList from index lastHideIndex.

          18. -
          19. Run close entire popover list given document's showing hint - popover list, focusPreviousElement, and fireEvents.

          20. +
          21. Reverse toHide.

          22. -
          23. If document's showing auto popover list does not contain - endpoint, then return.

          24. +
          25. Let toRemain be a slice of popoverList from index 0 to lastHideIndex.

          26. -
          27. Run hide popover stack until given endpoint, document's - showing auto popover list, focusPreviousElement, and - fireEvents.

          28. -
          -
          +
        12. For each popover in toHide, run the hide popover algorithm given popover, focusPreviousElement, fireEvents, false, and null.

        13. -
          -

          To hide popover stack until, given an HTML - element endpoint, a list popoverList, a boolean - focusPreviousElement, and a boolean fireEvents:

          +
        14. Let newPopoverList be document's showing auto popover list if stackType is Auto, otherwise document's showing hint popover list.

        15. -
            -
          1. Let repeatingHide be false.

          2. +
          3. Reverse newPopoverList.

          4. -

            Perform the following steps at least once:

            +

            For each popover in newPopoverList:

              -
            1. Let lastToHide be null.

            2. +
            3. If toRemain contains popover, then continue.

            4. -

              For each popover in popoverList:

              - -
                -
              1. If popover is endpoint, then break.

              2. +

                Run the hide popover algorithm given popover, focusPreviousElement, false, false, and null.

                -
              3. Set lastToHide to popover.

              4. -
              +

              This happens if popovers are shown whilst hiding popovers. For example, in beforetoggle events. This is usually a developer error, so user agents are encouraged to show a warning. In this additional hiding phase, fireEvents is ignored, and false is used instead.

            5. - -
            6. If lastToHide is null, then return.

            7. - -
            8. -

              While lastToHide's popover visibility state is showing:

              - -
                -
              1. Assert: popoverList is not empty.

              2. - -
              3. Run the hide popover algorithm given the last item in - popoverList, focusPreviousElement, fireEvents, false, and - null.

              4. -
              -
            9. - -
            10. Assert: repeatingHide is false or popoverList's last - item is endpoint.

            11. - -
            12. Set repeatingHide to true if popoverList contains - endpoint and popoverList's last item is not endpoint, - otherwise false.

            13. - -
            14. If repeatingHide is true, then set fireEvents to false.

            - -

            and keep performing them while repeatingHide is true.

          -

          The hide all popovers until - algorithm is used in several cases to hide all popovers that don't stay open when something +

          The hide all popovers until + algorithm TODO fix is used in several cases to hide all popovers that don't stay open when something happens. For example, during light-dismiss of a popover, this algorithm ensures that we close only the popovers that aren't related to the node clicked by the user.

          To find the topmost popover ancestor, given a Node - newPopoverOrTopLayerElement, a list popoverList, an newPopoverOrTopLayerElement, an HTML element or null source, and a boolean isPopover, perform the following steps. They return an HTML element or null.

          -

          The topmost popover ancestor algorithm will return the topmost (latest in the - showing auto popover list) ancestor popover for the provided popover or top layer +

          The topmost popover ancestor algorithm will return the topmost ancestor popover for the provided popover or top layer element. Popovers can be related to each other in several ways, creating a tree of popovers. There are two paths through which one popover (call it the "child" popover) can have a topmost ancestor popover (call it the "parent" popover):

          @@ -91856,18 +91737,18 @@ dictionary DragEventInit : MouseEventInit {
        16. The popovers are nested within each other in the node tree. In this case, the descendant popover is the "child" and its topmost ancestor popover is the "parent".

        17. -
        18. A popover trigger element (e.g., a button) has a popovertarget attribute pointing to a popover. In this case, +

        19. An element is the 'source' of the popover (e.g., a button with command in the Show Popover state). In this case, the popover is the "child", and the popover subtree the trigger element is in is the "parent". The trigger element has to be in a popover and reference an open popover.

        In each of the relationships formed above, the parent popover has to be strictly earlier in - the showing auto popover list than the child popover, or it does not form a valid + the showing auto popover list or showing hint popover list than the child popover, or it does not form a valid ancestral relationship. This eliminates non-showing popovers and self-pointers (e.g., a popover containing an invoking element that points back to the containing popover), and it allows for the construction of a well-formed tree from the (possibly cyclic) graph of connections. Only Auto popovers are considered.

        + data-x="attr-popover-auto-state">Auto and Hint popovers are considered.

        If the provided element is a top layer element such as a dialog which is not showing as a popover, then topmost popover ancestor will only look in the node tree @@ -91901,81 +91782,21 @@ dictionary DragEventInit : MouseEventInit {

    9. -
    10. Let popoverPositions be an empty ordered map.

    11. - -
    12. Let index be 0.

    13. +
    14. Let document be newPopoverOrTopLayerElement's node document.

    15. -
    16. -

      For each popover of popoverList:

      +
    17. Let combinedPopovers be document's showing auto popover list extended with document's showing hint popover list.

    18. -
        -
      1. Set popoverPositions[popover] to - index.

      2. +
      3. Let popoverAncestorIndex be the index of the last item in combinedPopovers of which newPopoverOrTopLayerElement is a flat tree descendant, otherwise infinity.

      4. -
      5. Increment index by 1.

      6. -
      - +
    19. Let sourceAncestorIndex be infinity.

    20. -
    21. If isPopover is true, then set - popoverPositions[newPopoverOrTopLayerElement] to index.

    22. +
    23. If source is not null, then set sourceAncestorIndex to the index of the last item in combinedPopovers of which source is a flat tree descendant, otherwise infinity.

    24. -
    25. Increment index by 1.

    26. +
    27. Let ancestorIndex be the minimum of popoverAncestorIndex and sourceAncestorIndex.

    28. -
    29. Let topmostPopoverAncestor be null.

    30. +
    31. If ancestorIndex is infinity, then return null.

    32. -
    33. -

      Let checkAncestor be an algorithm which performs the following steps given - candidate:

      - -
        -
      1. If candidate is null, then return.

      2. - -
      3. Let okNesting be false.

      4. - -
      5. Let candidateAncestor be null.

      6. - -
      7. -

        While okNesting is false:

        - -
          -
        1. Set candidateAncestor to the result of running nearest inclusive open - popover given candidate.

        2. - -
        3. If candidateAncestor is null or popoverPositions does not - contain candidateAncestor, then return.

        4. - -
        5. Assert: candidateAncestor's popover attribute is not in the Manual or None state.

        6. - -
        7. Set okNesting to true if isPopover is false, - newPopoverOrTopLayerElement's popover attribute - is in the Hint state, or - candidateAncestor's popover attribute is in the - Auto state.

        8. - -
        9. If okNesting is false, then set candidate to - candidateAncestor's parent in the flat tree.

        10. -
        -
      8. - -
      9. Let candidatePosition be - popoverPositions[candidateAncestor].

      10. - -
      11. If topmostPopoverAncestor is null or - popoverPositions[topmostPopoverAncestor] is less than - candidatePosition, then set topmostPopoverAncestor to - candidateAncestor.

      12. -
      -
    34. - -
    35. Run checkAncestor given newPopoverOrTopLayerElement's parent node - within the flat tree.

    36. - -
    37. Run checkAncestor given source.

    38. - -
    39. Return topmostPopoverAncestor.

    40. +
    41. Return combinedPopovers[ancestorIndex].

    @@ -92194,13 +92015,22 @@ dictionary DragEventInit : MouseEventInit { +

    Each Document has a hint stack parent, which is an + HTML element or null, initially null.

    + +
    +

    The hint stack parent tracks which item in the showing auto popover list is the 'parent' of the first item in the showing hint popover list, or null if the first item in showing hint popover list is not 'child' to an item in the showing auto popover list.

    + +

    Therefore, when the hint stack parent is not null, it will have an opened in popover mode of "auto".

    +
    +

    To close entire popover list given a list popoverList, a boolean focusPreviousElement, and a boolean fireEvents:

    1. -

      While popoverList is not empty:

      +

      While popoverList is not empty:

      1. Run the hide popover algorithm given popoverList's last item, @@ -92414,8 +92244,8 @@ dictionary DragEventInit : MouseEventInit {

      2. If ancestor is null, then set ancestor to document.

      3. -
      4. If sameTarget is true, then run hide - all popovers until given ancestor, false, and true.

      5. +
      6. If sameTarget is true, then run hide + all popovers until TODO fix given ancestor, false, and true.

    From f4714ea5e2046f3437337375ff3c8e375586d54a Mon Sep 17 00:00:00 2001 From: Jake Archibald Date: Wed, 8 Apr 2026 14:43:30 +0100 Subject: [PATCH 02/24] The rest of the owl --- source | 72 ++++++++++++++++++++++++++++------------------------------ 1 file changed, 35 insertions(+), 37 deletions(-) diff --git a/source b/source index 3e808c31312..3c3d69a579c 100644 --- a/source +++ b/source @@ -91365,7 +91365,7 @@ dictionary DragEventInit : MouseEventInit {
  • -

    If the result of running topmost auto or hint +

    If the result of running topmost auto or hint popover on document is null, then set shouldRestoreFocus to true.

    @@ -91541,29 +91541,36 @@ dictionary DragEventInit : MouseEventInit {
  • +
  • Let autoPopoverListContainsElement be true if document's showing auto popover list contains element.

  • + +
  • Let hintPopoverListContainsElement be true if document's showing hint popover list contains element.

  • +
  • If element's opened in popover mode is "auto" or "hint", then:

      -
    1. Run hide all popovers until TODO FIX given - element, focusPreviousElement, and fireEvents.

    2. +
    3. If hintPopoverListContainsElement is true, then hide popover stack until given element, document, Hint, focusPreviousElement, and fireEvents.

    4. + +
    5. +

      If element is document's hint stack parent, then hide popover stack until given null, document, Hint, focusPreviousElement, and fireEvents.

      + +

      If the document's hint stack parent is to hide, then all hint popovers are hidden.

      +
    6. + +
    7. If autoPopoverListContainsElement is true, then hide popover stack until given element, document, Auto, focusPreviousElement, and fireEvents.

    8. If the result of running check popover validity given element, true, throwExceptions, and null is false, then run cleanupSteps and return.

      -

      Check popover validity is called again because running hide all popovers until TODO fix could have disconnected +

      Check popover validity is called again because running hide popover stack until could have disconnected element or changed its popover attribute.

  • -
  • Let autoPopoverListContainsElement be true if document's - showing auto popover list's last item is element, otherwise - false.

  • -
  • If fireEvents is true:

    @@ -91576,9 +91583,17 @@ dictionary DragEventInit : MouseEventInit { data-x="dom-ToggleEvent-source">source attribute set to source at element.

  • -
  • If autoPopoverListContainsElement is true and document's - showing auto popover list's last item is not element, then run hide all popovers until TODO fix given element, - focusPreviousElement, and false.

  • +
  • +

    If autoPopoverListContainsElement is true and document's showing auto popover list's last item is not element, then run hide popover stack until given element, document, Auto, focusPreviousElement, and false.

    + +

    This happens if popovers are shown during the beforetoggle event. This is usually a developer error, so user agents are encouraged to show a warning.

    +
  • + +
  • +

    If hintPopoverListContainsElement is true and document's showing hint popover list's last item is not element, then run hide popover stack until given element, document, Hint, focusPreviousElement, and false.

    + +

    This happens if popovers are shown during the beforetoggle event. This is usually a developer error, so user agents are encouraged to show a warning.

    +
  • If the result of running check popover validity given element, @@ -91607,6 +91622,8 @@ dictionary DragEventInit : MouseEventInit {

  • Set element's popover visibility state to hidden.

  • +
  • If element is document's hint stack parent, or document's showing hint popover list is empty, then set document's hint stack parent to null.

  • +
  • If fireEvents is true, then queue a popover toggle event task given element, "open", "closed", and source.

  • @@ -91828,7 +91845,7 @@ dictionary DragEventInit : MouseEventInit {
    -

    To find the topmost auto or hint popover given a +

    To find the topmost auto or hint popover given a Document document, perform the following steps. They return an HTML element or null.

    @@ -92024,22 +92041,6 @@ dictionary DragEventInit : MouseEventInit {

    Therefore, when the hint stack parent is not null, it will have an opened in popover mode of "auto".

    -
    -

    To close entire popover list given a list popoverList, a - boolean focusPreviousElement, and a boolean fireEvents:

    - -
      -
    1. -

      While popoverList is not empty:

      - -
        -
      1. Run the hide popover algorithm given popoverList's last item, - focusPreviousElement, fireEvents, false, and null.

      2. -
      -
    2. -
    -
    -

    The popover target attributes

    Buttons may have the following content attributes:

    @@ -92202,7 +92203,7 @@ dictionary DragEventInit : MouseEventInit {

    "Light dismiss" means that clicking outside of a popover whose popover attribute is in the Auto state will close the popover. This is in addition to + data-x="attr-popover-auto-state">Auto or Hint state will close the popover. This is in addition to how such popovers respond to close requests.

    @@ -92218,10 +92219,7 @@ dictionary DragEventInit : MouseEventInit {
  • Let document be target's node document.

  • -
  • Let topmostPopover be the result of running topmost auto popover - given document.

  • - -
  • If topmostPopover is null, then return.

  • +
  • If the result of running topmost auto or hint popover given document is null, then return.

  • If event's type is "pointerdown", then: set document's popover @@ -92241,11 +92239,11 @@ dictionary DragEventInit : MouseEventInit {

  • Set document's popover pointerdown target to null.

  • -
  • If ancestor is null, then set ancestor to - document.

  • +
  • If sameTarget is false, then return

  • + +
  • Run hide popover stack until given ancestor, document, Hint, false, and true.

  • -
  • If sameTarget is true, then run hide - all popovers until TODO fix given ancestor, false, and true.

  • +
  • Run hide popover stack until given ancestor, document, Auto, false, and true.

  • From 3bca74f741d92ea0a7751721999e527a11bc89d9 Mon Sep 17 00:00:00 2001 From: Jake Archibald Date: Wed, 8 Apr 2026 14:50:44 +0100 Subject: [PATCH 03/24] No need to set hideUntil to document --- source | 3 --- 1 file changed, 3 deletions(-) diff --git a/source b/source index 3c3d69a579c..1d13dec1506 100644 --- a/source +++ b/source @@ -65773,9 +65773,6 @@ interface HTMLDialogElement : HTMLElement {
  • Let hideUntil be the result of running topmost popover ancestor given this, null, and false.

  • -
  • If hideUntil is null, then set hideUntil to - document.

  • -
  • Run hide popover stack until given hideUntil, document, Hint, false, and true.

  • Run hide popover stack until given hideUntil, document, Auto, false, and true.

  • From dc41ca8976b71c547812f45dfbd0c75041708848 Mon Sep 17 00:00:00 2001 From: Jake Archibald Date: Wed, 8 Apr 2026 14:52:11 +0100 Subject: [PATCH 04/24] Another document set --- source | 3 --- 1 file changed, 3 deletions(-) diff --git a/source b/source index 1d13dec1506..45498feff8e 100644 --- a/source +++ b/source @@ -66033,9 +66033,6 @@ interface HTMLDialogElement : HTMLElement {
  • Let hideUntil be the result of running topmost popover ancestor given subject, null, and false.

  • -
  • If hideUntil is null, then set hideUntil to - document.

  • -
  • Run hide popover stack until given hideUntil, document, Hint, false, and true.

  • Run hide popover stack until given hideUntil, document, Auto, false, and true.

  • From 4518fd07508c4166d0fd8f02aefc9affa42d88e1 Mon Sep 17 00:00:00 2001 From: Jake Archibald Date: Wed, 8 Apr 2026 16:19:37 +0100 Subject: [PATCH 05/24] Missing return true --- source | 2 ++ 1 file changed, 2 insertions(+) diff --git a/source b/source index 45498feff8e..4c1581a77a8 100644 --- a/source +++ b/source @@ -91259,6 +91259,8 @@ dictionary DragEventInit : MouseEventInit {

    Hint popovers are lower priority than Auto popovers, so an Auto popover cannot have a Hint popover as a 'parent'.

    + +
  • Return true.

  • From e345ff08d95a70d738bdc83829e6383835e602df Mon Sep 17 00:00:00 2001 From: Jake Archibald Date: Thu, 9 Apr 2026 11:38:53 +0100 Subject: [PATCH 06/24] Minor changes --- source | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/source b/source index 4c1581a77a8..72a865a5409 100644 --- a/source +++ b/source @@ -91247,7 +91247,7 @@ dictionary DragEventInit : MouseEventInit {
  • If ancestor is not null, element's popover attribute is in the Auto state, and ancestor's popover attribute is in the Hint state, then: + data-x="attr-popover">popover attribute is in the Hint state:

      @@ -91696,9 +91696,9 @@ dictionary DragEventInit : MouseEventInit { a boolean focusPreviousElement, and a boolean fireEvents:

        -
      1. Let popoverList be document's showing auto popover list if stackType is Auto, otherwise document's showing hint popover list.

      2. +
      3. Let popoverList be document's showing auto popover list if stackType is Auto; otherwise document's showing hint popover list.

      4. -
      5. Let lastHideIndex be 0 if popoverList does not contain endpoint, otherwise the index of endpoint in popoverList plus 1.

      6. +
      7. Let lastHideIndex be 0 if popoverList does not contain endpoint; otherwise the index of endpoint in popoverList plus 1.

      8. Let toHide be a slice of popoverList from index lastHideIndex.

      9. @@ -91706,9 +91706,9 @@ dictionary DragEventInit : MouseEventInit {
      10. Let toRemain be a slice of popoverList from index 0 to lastHideIndex.

      11. -
      12. For each popover in toHide, run the hide popover algorithm given popover, focusPreviousElement, fireEvents, false, and null.

      13. +
      14. For each popover of toHide: run the hide popover algorithm given popover, focusPreviousElement, fireEvents, false, and null.

      15. -
      16. Let newPopoverList be document's showing auto popover list if stackType is Auto, otherwise document's showing hint popover list.

      17. +
      18. Let newPopoverList be document's showing auto popover list if stackType is Auto; otherwise document's showing hint popover list.

      19. Reverse newPopoverList.

      20. @@ -91728,7 +91728,7 @@ dictionary DragEventInit : MouseEventInit {
  • -

    The hide all popovers until +

    The hide popover stack until algorithm TODO fix is used in several cases to hide all popovers that don't stay open when something happens. For example, during light-dismiss of a popover, this algorithm ensures that we close only the popovers that aren't related to the node clicked by the user.

    From 8f4f8fd152fce7bb9c9b9ac99bf5593a91b2bf7b Mon Sep 17 00:00:00 2001 From: Jake Archibald Date: Thu, 9 Apr 2026 12:12:53 +0100 Subject: [PATCH 07/24] Hint first, and make it clear the conditions are exclusive --- source | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source b/source index 72a865a5409..9e72ae934c5 100644 --- a/source +++ b/source @@ -91580,13 +91580,13 @@ dictionary DragEventInit : MouseEventInit { element.

  • -

    If autoPopoverListContainsElement is true and document's showing auto popover list's last item is not element, then run hide popover stack until given element, document, Auto, focusPreviousElement, and false.

    +

    If hintPopoverListContainsElement is true and document's showing hint popover list's last item is not element, then run hide popover stack until given element, document, Hint, focusPreviousElement, and false.

    This happens if popovers are shown during the beforetoggle event. This is usually a developer error, so user agents are encouraged to show a warning.

  • -

    If hintPopoverListContainsElement is true and document's showing hint popover list's last item is not element, then run hide popover stack until given element, document, Hint, focusPreviousElement, and false.

    +

    Otherwise, if autoPopoverListContainsElement is true and document's showing auto popover list's last item is not element, run hide popover stack until given element, document, Auto, focusPreviousElement, and false.

    This happens if popovers are shown during the beforetoggle event. This is usually a developer error, so user agents are encouraged to show a warning.

  • From 31a54ee9bcb4d9f422b1fa0b0e7468faf8f9244f Mon Sep 17 00:00:00 2001 From: Jake Archibald Date: Thu, 9 Apr 2026 12:27:47 +0100 Subject: [PATCH 08/24] Actually remove the TODO lol --- source | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source b/source index 9e72ae934c5..eea5073b651 100644 --- a/source +++ b/source @@ -91729,7 +91729,7 @@ dictionary DragEventInit : MouseEventInit {

    The hide popover stack until - algorithm TODO fix is used in several cases to hide all popovers that don't stay open when something + algorithm is used in several cases to hide all popovers that don't stay open when something happens. For example, during light-dismiss of a popover, this algorithm ensures that we close only the popovers that aren't related to the node clicked by the user.

    From afc6003c15d99743b3c5511a7bf6bd5b44418bd6 Mon Sep 17 00:00:00 2001 From: Jake Archibald Date: Thu, 9 Apr 2026 12:39:26 +0100 Subject: [PATCH 09/24] Create algo for closing hint then auto popovers --- source | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/source b/source index eea5073b651..bccfbc7b5f7 100644 --- a/source +++ b/source @@ -65773,9 +65773,7 @@ interface HTMLDialogElement : HTMLElement {
  • Let hideUntil be the result of running topmost popover ancestor given this, null, and false.

  • -
  • Run hide popover stack until given hideUntil, document, Hint, false, and true.

  • - -
  • Run hide popover stack until given hideUntil, document, Auto, false, and true.

  • +
  • Run hide popovers until given hideUntil, document, false, and true.

  • Run the dialog focusing steps given this.

  • @@ -66033,9 +66031,7 @@ interface HTMLDialogElement : HTMLElement {
  • Let hideUntil be the result of running topmost popover ancestor given subject, null, and false.

  • -
  • Run hide popover stack until given hideUntil, document, Hint, false, and true.

  • - -
  • Run hide popover stack until given hideUntil, document, Auto, false, and true.

  • +
  • Run hide popovers until given hideUntil, document, false, and true.

  • Run the dialog focusing steps given subject.

  • @@ -91689,6 +91685,18 @@ dictionary DragEventInit : MouseEventInit { +
    +

    To hide popovers until, given an HTML + element or null endpoint, Document document, + a boolean focusPreviousElement, and a boolean fireEvents:

    + +
      +
    1. Run hide popover stack until given endpoint, document, Hint, focusPreviousElement, and fireEvents.

    2. + +
    3. Run hide popover stack until given endpoint, document, Auto, focusPreviousElement, and fireEvents.

    4. +
    +
    +

    To hide popover stack until, given an HTML element or null endpoint, Document document, @@ -92237,9 +92245,7 @@ dictionary DragEventInit : MouseEventInit {

  • If sameTarget is false, then return

  • -
  • Run hide popover stack until given ancestor, document, Hint, false, and true.

  • - -
  • Run hide popover stack until given ancestor, document, Auto, false, and true.

  • +
  • Run hide popovers given ancestor, document, false, and true.

  • From d2fd3f5989b8c8f84089613de9625a18f1bf283a Mon Sep 17 00:00:00 2001 From: Jake Archibald Date: Thu, 9 Apr 2026 12:46:34 +0100 Subject: [PATCH 10/24] Fixing silly mistakes --- source | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/source b/source index bccfbc7b5f7..00a50354fd2 100644 --- a/source +++ b/source @@ -91691,9 +91691,9 @@ dictionary DragEventInit : MouseEventInit { a boolean focusPreviousElement, and a boolean fireEvents:

      -
    1. Run hide popover stack until given endpoint, document, Hint, focusPreviousElement, and fireEvents.

    2. +
    3. Run hide popover stack until given endpoint, document, Hint, focusPreviousElement, and fireEvents.

    4. -
    5. Run hide popover stack until given endpoint, document, Auto, focusPreviousElement, and fireEvents.

    6. +
    7. Run hide popover stack until given endpoint, document, Auto, focusPreviousElement, and fireEvents.

    @@ -92245,7 +92245,7 @@ dictionary DragEventInit : MouseEventInit {
  • If sameTarget is false, then return

  • -
  • Run hide popovers given ancestor, document, false, and true.

  • +
  • Run hide popovers until given ancestor, document, false, and true.

  • From 657f63895c11d47288d4eece5e0c3cfd5facf578 Mon Sep 17 00:00:00 2001 From: Jake Archibald Date: Fri, 10 Apr 2026 12:26:56 +0100 Subject: [PATCH 11/24] Don't hide autos if endpoint is in the hint stack --- source | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/source b/source index 00a50354fd2..e5b0ae7efb4 100644 --- a/source +++ b/source @@ -91691,8 +91691,12 @@ dictionary DragEventInit : MouseEventInit { a boolean focusPreviousElement, and a boolean fireEvents:

      +
    1. Let endpointIsHint be true if document's showing hint popover list contains endpoint; otherwise false.

    2. +
    3. Run hide popover stack until given endpoint, document, Hint, focusPreviousElement, and fireEvents.

    4. +
    5. If endpointIsHint, then return.

    6. +
    7. Run hide popover stack until given endpoint, document, Auto, focusPreviousElement, and fireEvents.

    From 84eee6f01def200a8795141d21fa1b6c36526c61 Mon Sep 17 00:00:00 2001 From: Jake Archibald Date: Tue, 14 Apr 2026 17:47:06 +0100 Subject: [PATCH 12/24] Use infra list slice & reverse --- source | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/source b/source index e5b0ae7efb4..b8a2f62641a 100644 --- a/source +++ b/source @@ -2334,10 +2334,14 @@ a.setAttribute('href', 'https://example.com/'); // change the content attribute indices, is empty, item, - iterate, and + iterate, clone sort in ascending order - sort in descending order + sort in descending order + slice (and its + from and + to options), and + reverse
  • The stack data structure and the associated definitions for push and pop
  • @@ -91712,11 +91716,9 @@ dictionary DragEventInit : MouseEventInit {
  • Let lastHideIndex be 0 if popoverList does not contain endpoint; otherwise the index of endpoint in popoverList plus 1.

  • -
  • Let toHide be a slice of popoverList from index lastHideIndex.

  • +
  • Let toHide be a slice of popoverList from lastHideIndex, in reverse order.

  • -
  • Reverse toHide.

  • - -
  • Let toRemain be a slice of popoverList from index 0 to lastHideIndex.

  • +
  • Let toRemain be a slice of popoverList from 0 to lastHideIndex.

  • For each popover of toHide: run the hide popover algorithm given popover, focusPreviousElement, fireEvents, false, and null.

  • From 7a711868ddda2c91a85fda07e73817abae982259 Mon Sep 17 00:00:00 2001 From: Jake Archibald Date: Fri, 17 Apr 2026 12:00:27 +0100 Subject: [PATCH 13/24] Change arg order of popover hide --- source | 33 ++++++++++++++------------------- 1 file changed, 14 insertions(+), 19 deletions(-) diff --git a/source b/source index b8a2f62641a..d78ee7607f8 100644 --- a/source +++ b/source @@ -65777,7 +65777,7 @@ interface HTMLDialogElement : HTMLElement {
  • Let hideUntil be the result of running topmost popover ancestor given this, null, and false.

  • -
  • Run hide popovers until given hideUntil, document, false, and true.

  • +
  • Run hide popovers until given document, hideUntil, false, and true.

  • Run the dialog focusing steps given this.

  • @@ -66035,7 +66035,7 @@ interface HTMLDialogElement : HTMLElement {
  • Let hideUntil be the result of running topmost popover ancestor given subject, null, and false.

  • -
  • Run hide popovers until given hideUntil, document, false, and true.

  • +
  • Run hide popovers until given document, hideUntil, false, and true.

  • Run the dialog focusing steps given subject.

  • @@ -91322,9 +91322,9 @@ dictionary DragEventInit : MouseEventInit {
  • Let ancestor be the result of running the topmost popover ancestor algorithm given element, source, and true.

  • -
  • If originalType is the Auto or Hint state, then run hide popover stack until given ancestor, document, Hint, shouldRestoreFocus, and fireEvents.

  • +
  • If originalType is the Auto or Hint state, then run hide popover stack until given document, ancestor, Hint, shouldRestoreFocus, and fireEvents.

  • -
  • If originalType is the Auto state, then run hide popover stack until given ancestor, document, Auto, shouldRestoreFocus, and fireEvents.

  • +
  • If originalType is the Auto state, then run hide popover stack until given document, ancestor, Auto, shouldRestoreFocus, and fireEvents.

  • If originalType is Auto or DragEventInit : MouseEventInit { or "hint", then:

      -
    1. If hintPopoverListContainsElement is true, then hide popover stack until given element, document, Hint, focusPreviousElement, and fireEvents.

    2. +
    3. If hintPopoverListContainsElement is true, then hide popover stack until given document, element, Hint, focusPreviousElement, and fireEvents.

    4. -

      If element is document's hint stack parent, then hide popover stack until given null, document, Hint, focusPreviousElement, and fireEvents.

      +

      If element is document's hint stack parent, then hide popover stack until given document, null, Hint, focusPreviousElement, and fireEvents.

      If the document's hint stack parent is to hide, then all hint popovers are hidden.

    5. -
    6. If autoPopoverListContainsElement is true, then hide popover stack until given element, document, Auto, focusPreviousElement, and fireEvents.

    7. +
    8. If autoPopoverListContainsElement is true, then hide popover stack until given document, element, Auto, focusPreviousElement, and fireEvents.

    9. If the result of running check popover validity given element, @@ -91580,13 +91580,13 @@ dictionary DragEventInit : MouseEventInit { element.

    10. -

      If hintPopoverListContainsElement is true and document's showing hint popover list's last item is not element, then run hide popover stack until given element, document, Hint, focusPreviousElement, and false.

      +

      If hintPopoverListContainsElement is true and document's showing hint popover list's last item is not element, then run hide popover stack until given document, element, Hint, focusPreviousElement, and false.

      This happens if popovers are shown during the beforetoggle event. This is usually a developer error, so user agents are encouraged to show a warning.

    11. -

      Otherwise, if autoPopoverListContainsElement is true and document's showing auto popover list's last item is not element, run hide popover stack until given element, document, Auto, focusPreviousElement, and false.

      +

      Otherwise, if autoPopoverListContainsElement is true and document's showing auto popover list's last item is not element, run hide popover stack until given document, element, Auto, focusPreviousElement, and false.

      This happens if popovers are shown during the beforetoggle event. This is usually a developer error, so user agents are encouraged to show a warning.

    12. @@ -91690,26 +91690,21 @@ dictionary DragEventInit : MouseEventInit {
      -

      To hide popovers until, given an HTML - element or null endpoint, Document document, - a boolean focusPreviousElement, and a boolean fireEvents:

      +

      To hide popovers until, given a Document document, an HTML element or null endpoint, a boolean focusPreviousElement, and a boolean fireEvents:

      1. Let endpointIsHint be true if document's showing hint popover list contains endpoint; otherwise false.

      2. -
      3. Run hide popover stack until given endpoint, document, Hint, focusPreviousElement, and fireEvents.

      4. +
      5. Run hide popover stack until given document, endpoint, Hint, focusPreviousElement, and fireEvents.

      6. If endpointIsHint, then return.

      7. -
      8. Run hide popover stack until given endpoint, document, Auto, focusPreviousElement, and fireEvents.

      9. +
      10. Run hide popover stack until given document, endpoint, Auto, focusPreviousElement, and fireEvents.

      -

      To hide popover stack until, given an HTML - element or null endpoint, Document document, - an Auto or Hint stackType, - a boolean focusPreviousElement, and a boolean fireEvents:

      +

      To hide popover stack until, given a Document document, an HTML element or null endpoint, an Auto or Hint stackType, a boolean focusPreviousElement, and a boolean fireEvents:

      1. Let popoverList be document's showing auto popover list if stackType is Auto; otherwise document's showing hint popover list.

      2. @@ -92251,7 +92246,7 @@ dictionary DragEventInit : MouseEventInit {
      3. If sameTarget is false, then return

      4. -
      5. Run hide popovers until given ancestor, document, false, and true.

      6. +
      7. Run hide popovers until given document, ancestor, false, and true.

    From 470b816314b4b928e46c169494dcb5ab76acbada Mon Sep 17 00:00:00 2001 From: Jake Archibald Date: Fri, 17 Apr 2026 12:08:55 +0100 Subject: [PATCH 14/24] Set hint stack branch earlier --- source | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source b/source index d78ee7607f8..09351539a8a 100644 --- a/source +++ b/source @@ -91420,6 +91420,8 @@ dictionary DragEventInit : MouseEventInit {
  • Add an element to the top layer given element.

  • +
  • If originalType is Hint and ancestor's opened in popover mode is "auto", then set document's hint stack parent to ancestor.

  • +
  • Set element's popover visibility state to showing.

  • @@ -91435,8 +91437,6 @@ dictionary DragEventInit : MouseEventInit { data-x="attr-popover-none-state">No Popover state, then set element's previously focused element to originallyFocusedElement.

    -
  • If originalType is Hint and ancestor's opened in popover mode is "auto", then set document's hint stack parent to ancestor.

  • -
  • Queue a popover toggle event task given element, "closed", "open", and source.

  • From f6816de854c3072852d6968a28f3c4c9841a1152 Mon Sep 17 00:00:00 2001 From: Jake Archibald Date: Fri, 17 Apr 2026 12:10:01 +0100 Subject: [PATCH 15/24] Add missing 'otherwise's --- source | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source b/source index 09351539a8a..1511a80e9f2 100644 --- a/source +++ b/source @@ -91537,9 +91537,9 @@ dictionary DragEventInit : MouseEventInit { -
  • Let autoPopoverListContainsElement be true if document's showing auto popover list contains element.

  • +
  • Let autoPopoverListContainsElement be true if document's showing auto popover list contains element; otherwise false.

  • -
  • Let hintPopoverListContainsElement be true if document's showing hint popover list contains element.

  • +
  • Let hintPopoverListContainsElement be true if document's showing hint popover list contains element; otherwise false.

  • If element's opened in popover mode is "auto" From 2dbb9bf71495872a5c7f298e282311ce35422a05 Mon Sep 17 00:00:00 2001 From: Jake Archibald Date: Fri, 17 Apr 2026 12:23:44 +0100 Subject: [PATCH 16/24] options to arguments --- source | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source b/source index 1511a80e9f2..e7ec189f972 100644 --- a/source +++ b/source @@ -2340,7 +2340,7 @@ a.setAttribute('href', 'https://example.com/'); // change the content attribute sort in descending order slice (and its from and - to options), and + to arguments), and reverse

  • The stack data structure and the associated definitions for push and From 49376558abbd44846f61966aa41cf6720236459f Mon Sep 17 00:00:00 2001 From: Jake Archibald Date: Fri, 17 Apr 2026 12:24:57 +0100 Subject: [PATCH 17/24] Rename cleanupShowingFlag to cleanupShowingSteps --- source | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/source b/source index e7ec189f972..3179233c630 100644 --- a/source +++ b/source @@ -91281,7 +91281,7 @@ dictionary DragEventInit : MouseEventInit {
  • Set element's popover showing or hiding to true.

  • -

    Let cleanupShowingFlag be the following steps:

    +

    Let cleanupShowingSteps be the following steps:

    1. If nestedShow is false, then set element's popover showing @@ -91296,12 +91296,12 @@ dictionary DragEventInit : MouseEventInit { data-x="">closed", the newState attribute initialized to "open", and the source attribute initialized to source at - element is false, then run cleanupShowingFlag and return.

    2. + element is false, then run cleanupShowingSteps and return.

    3. If the result of running check popover validity given element, false, throwExceptions, and document is false, then run - cleanupShowingFlag and return.

      + cleanupShowingSteps and return.

      Check popover validity is called again because firing the beforetoggle event could have disconnected this element or @@ -91309,7 +91309,7 @@ dictionary DragEventInit : MouseEventInit {

    4. -

      If the result of running checkAncestor is false, then run cleanupShowingFlag and return.

      +

      If the result of running checkAncestor is false, then run cleanupShowingSteps and return.

      These checks are performed again because firing the beforetoggle event could have modified element state.

      @@ -91346,7 +91346,7 @@ dictionary DragEventInit : MouseEventInit {
    5. If the result of running check popover validity given element, false, throwExceptions, and document is false, then run - cleanupShowingFlag and return.

      + cleanupShowingSteps and return.

      Check popover validity is called again because running hide popover stack until above could have fired the beforetoggle event, and an event handler could have @@ -91355,7 +91355,7 @@ dictionary DragEventInit : MouseEventInit {

    6. -

      If the result of running checkAncestor is false, then run cleanupShowingFlag and return.

      +

      If the result of running checkAncestor is false, then run cleanupShowingSteps and return.

      These checks are performed again because running hide popover stack until above could have fired the beforetoggle event, and an event handler could have altered DOM state.

    7. @@ -91440,7 +91440,7 @@ dictionary DragEventInit : MouseEventInit {
    8. Queue a popover toggle event task given element, "closed", "open", and source.

    9. -
    10. Run cleanupShowingFlag.

    11. +
    12. Run cleanupShowingSteps.

    From 3e4a889577ce3f5c541cb9dd9824e2a320300be8 Mon Sep 17 00:00:00 2001 From: Jake Archibald Date: Fri, 17 Apr 2026 13:05:08 +0100 Subject: [PATCH 18/24] Correct popover click behavior --- source | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/source b/source index 3179233c630..bc5fb07951d 100644 --- a/source +++ b/source @@ -92246,7 +92246,19 @@ dictionary DragEventInit : MouseEventInit {
  • If sameTarget is false, then return

  • -
  • Run hide popovers until given document, ancestor, false, and true.

  • +
  • Let endpointIsHint be true if document's showing hint popover list contains ancestor; otherwise false.

  • + +
  • Run hide popover stack until given document, ancestor, Hint, false, and true.

  • + +
  • Let autoEndpoint be ancestor.

  • + +
  • +

    If endpointIsHint, then set autoEndpoint to document's hint stack parent.

    + +

    This means, if a hint popover is clicked, auto popovers are closed, except those that are parent to the clicked hint popover.

    +
  • + +
  • Run hide popover stack until given document, autoEndpoint, Auto, false, and true.

  • From acfe14a41cd4a70f89df5a523dbe8a12e024bf49 Mon Sep 17 00:00:00 2001 From: Jake Archibald Date: Fri, 17 Apr 2026 13:33:09 +0100 Subject: [PATCH 19/24] Fix topmost popover ancestor --- source | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/source b/source index bc5fb07951d..e9336157437 100644 --- a/source +++ b/source @@ -91808,15 +91808,15 @@ dictionary DragEventInit : MouseEventInit {
  • Let combinedPopovers be document's showing auto popover list extended with document's showing hint popover list.

  • -
  • Let popoverAncestorIndex be the index of the last item in combinedPopovers of which newPopoverOrTopLayerElement is a flat tree descendant, otherwise infinity.

  • +
  • Let popoverAncestorIndex be the index of the last item in combinedPopovers of which newPopoverOrTopLayerElement is a flat tree descendant, otherwise -1.

  • -
  • Let sourceAncestorIndex be infinity.

  • +
  • Let sourceAncestorIndex be -1.

  • -
  • If source is not null, then set sourceAncestorIndex to the index of the last item in combinedPopovers of which source is a flat tree descendant, otherwise infinity.

  • +
  • If source is not null, then set sourceAncestorIndex to the index of the last item in combinedPopovers of which source is a flat tree descendant, otherwise -1.

  • -
  • Let ancestorIndex be the minimum of popoverAncestorIndex and sourceAncestorIndex.

  • +
  • Let ancestorIndex be the maximum of popoverAncestorIndex and sourceAncestorIndex.

  • -
  • If ancestorIndex is infinity, then return null.

  • +
  • If ancestorIndex is -1, then return null.

  • Return combinedPopovers[ancestorIndex].

  • From 0f6701f0ec801ba0e64750942f2ffc6bb89abdc3 Mon Sep 17 00:00:00 2001 From: Jake Archibald Date: Fri, 17 Apr 2026 15:18:53 +0100 Subject: [PATCH 20/24] Allow auto within hint by downgrading to hint --- source | 80 ++++++++++++++++++++-------------------------------------- 1 file changed, 27 insertions(+), 53 deletions(-) diff --git a/source b/source index e9336157437..60bd306d7be 100644 --- a/source +++ b/source @@ -91171,7 +91171,8 @@ dictionary DragEventInit : MouseEventInit { which is a close watcher or null, initially null.

    Every HTML element has an opened in popover - mode, which is a string or null, initially null.

    + mode, which is "auto", "hint", or null, + initially null.

    The following attribute change @@ -91238,34 +91239,6 @@ dictionary DragEventInit : MouseEventInit {

  • If the result of running check popover validity given element, false, throwExceptions, and null is false, then return.

  • -
  • -

    Let checkAncestor be the following steps:

    - -
      -
    1. Let ancestor be the result of running the topmost popover ancestor algorithm given element, source, and true.

    2. - -
    3. -

      If ancestor is not null, element's popover attribute is in the Auto state, and ancestor's popover attribute is in the Hint state: -

      - -
        -
      1. If throwExceptions is true, then throw an - "InvalidStateError" DOMException.

      2. - -
      3. Return false.

      4. -
      - -

      Hint popovers are lower priority than Auto popovers, so an Auto popover cannot have a Hint popover as a 'parent'.

      -
    4. - -
    5. Return true.

    6. -
    -
  • - -
  • If the result of running checkAncestor is false, then return.

  • -
  • Let document be element's node document.

  • Assert: element's popover trigger is null.

  • @@ -91308,13 +91281,6 @@ dictionary DragEventInit : MouseEventInit { changed its popover attribute.

    -
  • -

    If the result of running checkAncestor is false, then run cleanupShowingSteps and return.

    - -

    These checks are performed again because firing the beforetoggle event could have modified element state.

    -
  • -
  • Let shouldRestoreFocus be false.

  • Let originalType be the current state of element's DragEventInit : MouseEventInit {

  • Let ancestor be the result of running the topmost popover ancestor algorithm given element, source, and true.

  • -
  • If originalType is the Auto or Hint state, then run hide popover stack until given document, ancestor, Hint, shouldRestoreFocus, and fireEvents.

  • +
  • Let effectiveType be originalType.

  • -
  • If originalType is the Auto state, then run hide popover stack until given document, ancestor, Auto, shouldRestoreFocus, and fireEvents.

  • +
  • +

    If all of the following are true:

    + +
      +
    • ancestor is not null;

    • + +
    • ancestor's opened in popover mode is "hint"; and

    • + +
    • effectiveType is the Auto state,

    • +
    + +

    then set effectiveType to the Hint state.

    + +

    Hint popovers are lower priority than Auto popovers, so an Auto popover cannot have a Hint popover as a 'parent'. To resolve this case, the effectiveType is 'downgraded' to Hint.

    +
  • + +
  • If effectiveType is the Auto or Hint state, then run hide popover stack until given document, ancestor, Hint, shouldRestoreFocus, and fireEvents.

  • + +
  • If effectiveType is the Auto state, then run hide popover stack until given document, ancestor, Auto, shouldRestoreFocus, and fireEvents.

  • -

    If originalType is Auto or If effectiveType is Auto or Hint, then:

      @@ -91354,12 +91338,6 @@ dictionary DragEventInit : MouseEventInit { attribute.

      -
    1. -

      If the result of running checkAncestor is false, then run cleanupShowingSteps and return.

      - -

      These checks are performed again because running hide popover stack until above could have fired the beforetoggle event, and an event handler could have altered DOM state.

      -
    2. -
    3. If the result of running topmost auto or hint popover on document is null, then set shouldRestoreFocus to @@ -91370,7 +91348,7 @@ dictionary DragEventInit : MouseEventInit {

    4. -

      If originalType is Auto:

      +

      If effectiveType is Auto:

      1. Assert: document's showing auto popover list does @@ -91383,7 +91361,7 @@ dictionary DragEventInit : MouseEventInit {

        Otherwise:

          -
        1. Assert: originalType is Hint.

        2. +
        3. Assert: effectiveType is Hint.

        4. Assert: document's showing hint popover list does not contain element.

        5. @@ -91420,7 +91398,7 @@ dictionary DragEventInit : MouseEventInit {
        6. Add an element to the top layer given element.

        7. -
        8. If originalType is Hint and ancestor's opened in popover mode is "auto", then set document's hint stack parent to ancestor.

        9. +
        10. If effectiveType is Hint and ancestor's opened in popover mode is "auto", then set document's hint stack parent to ancestor.

        11. Set element's popover visibility state to showing.

        12. @@ -91834,11 +91812,7 @@ dictionary DragEventInit : MouseEventInit {

          While currentNode is not null:

            -
          1. If currentNode's popover attribute is in - the Auto state or the Hint state, and currentNode's - popover visibility state is showing, - then return currentNode.

          2. +
          3. If currentNode's opened in popover mode is "auto" or "hint", and currentNode's popover visibility state is showing, then return currentNode.

          4. Set currentNode to currentNode's parent in the flat tree.

          5. From f99432c54a5d6f5c271683fdba7edf5b9237ae6b Mon Sep 17 00:00:00 2001 From: Jake Archibald Date: Fri, 17 Apr 2026 15:57:19 +0100 Subject: [PATCH 21/24] Disallow showing a popover while another is showing --- source | 50 ++++++++++++++++++++++++++++---------------------- 1 file changed, 28 insertions(+), 22 deletions(-) diff --git a/source b/source index 60bd306d7be..a34adf92cb7 100644 --- a/source +++ b/source @@ -91161,8 +91161,7 @@ dictionary DragEventInit : MouseEventInit {

            Every HTML element has a popover trigger, which is an HTML element or null, initially set to null.

            -

            Every HTML element has a popover showing or - hiding, which is a boolean, initially set to false.

            +

            Every HTML element has a popover hiding, which is a boolean, initially set to false.

            Every HTML element popover toggle task tracker, which is a toggle task tracker or null, initially null.

            @@ -91174,6 +91173,10 @@ dictionary DragEventInit : MouseEventInit { mode, which is "auto", "hint", or null, initially null.

            +

            Every Document has a hiding popover nesting count, which is a number, initially 0.

            + +

            Every Document has a showing popover, which is a boolean, initially false.

            +

            The following attribute change steps, given element, localName, oldValue, @@ -91236,29 +91239,34 @@ dictionary DragEventInit : MouseEventInit { element or null source:

              +
            1. Let document be element's node document.

            2. + +
            3. +

              If document's showing popover is true, then:

              + +
                +
              1. If throwExceptions is true, then throw a "InvalidStateError" + DOMException.

              2. + +
              3. Return.

              4. +
              +
            4. + +
            5. Set document's showing popover to true.

            6. +
            7. If the result of running check popover validity given element, false, throwExceptions, and null is false, then return.

            8. -
            9. Let document be element's node document.

            10. -
            11. Assert: element's popover trigger is null.

            12. Assert: element is not in document's top layer.

            13. -
            14. Let nestedShow be element's popover showing or - hiding.

            15. - -
            16. Let fireEvents be the boolean negation of nestedShow.

            17. - -
            18. Set element's popover showing or hiding to true.

            19. -
            20. Let cleanupShowingSteps be the following steps:

                -
              1. If nestedShow is false, then set element's popover showing - or hiding to false.

              2. +
              3. Set document's showing popover to false.

            21. @@ -91306,9 +91314,9 @@ dictionary DragEventInit : MouseEventInit {

              Hint popovers are lower priority than Auto popovers, so an Auto popover cannot have a Hint popover as a 'parent'. To resolve this case, the effectiveType is 'downgraded' to Hint.

              -
            22. If effectiveType is the Auto or Hint state, then run hide popover stack until given document, ancestor, Hint, shouldRestoreFocus, and fireEvents.

            23. +
            24. If effectiveType is the Auto or Hint state, then run hide popover stack until given document, ancestor, Hint, shouldRestoreFocus, and true.

            25. -
            26. If effectiveType is the Auto state, then run hide popover stack until given document, ancestor, Auto, shouldRestoreFocus, and fireEvents.

            27. +
            28. If effectiveType is the Auto state, then run hide popover stack until given document, ancestor, Auto, shouldRestoreFocus, and true.

            29. If effectiveType is Auto or DragEventInit : MouseEventInit { data-x="attr-popover-none-state">No Popover state, then set element's previously focused element to originallyFocusedElement.

            30. +
            31. Run cleanupShowingSteps.

            32. +
            33. Queue a popover toggle event task given element, "closed", "open", and source.

            34. - -
            35. Run cleanupShowingSteps.

            @@ -91488,10 +91496,9 @@ dictionary DragEventInit : MouseEventInit {
          6. Let document be element's node document.

          7. -
          8. Let nestedHide be element's popover showing or - hiding.

          9. +
          10. Let nestedHide be element's popover hiding.

          11. -
          12. Set element's popover showing or hiding to true.

          13. +
          14. Set element's popover hiding to true.

          15. If nestedHide is true, then set fireEvents to false.

          16. @@ -91499,8 +91506,7 @@ dictionary DragEventInit : MouseEventInit {

            Let cleanupSteps be the following steps:

              -
            1. If nestedHide is false, then set element's popover showing - or hiding to false.

            2. +
            3. If nestedHide is false, then set element's popover hiding to false.

            4. If element's popover close watcher is not null, then:

              From 7ca5f3d4f0b4aab88806d4d8e3c1efd8032b4009 Mon Sep 17 00:00:00 2001 From: Jake Archibald Date: Fri, 17 Apr 2026 16:07:00 +0100 Subject: [PATCH 22/24] Prevent showing a popover during the show or hide of another popover --- source | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/source b/source index a34adf92cb7..4f6e8aa5968 100644 --- a/source +++ b/source @@ -91242,7 +91242,7 @@ dictionary DragEventInit : MouseEventInit {
            5. Let document be element's node document.

            6. -

              If document's showing popover is true, then:

              +

              If document's showing popover is true, or document's hiding popover nesting count is not 0, then:

              1. If throwExceptions is true, then throw a "InvalidStateError" @@ -91250,6 +91250,8 @@ dictionary DragEventInit : MouseEventInit {

              2. Return.

              + +

              This prevents showing a popover during the show or hide of another popover.

            7. Set document's showing popover to true.

            8. @@ -91502,6 +91504,8 @@ dictionary DragEventInit : MouseEventInit {
            9. If nestedHide is true, then set fireEvents to false.

            10. +
            11. Increment document's hiding popover nesting count.

            12. +
            13. Let cleanupSteps be the following steps:

              @@ -91518,6 +91522,8 @@ dictionary DragEventInit : MouseEventInit {
            14. Set element's popover close watcher to null.

            + +
          17. Decrement document's hiding popover nesting count.

          @@ -91563,18 +91569,6 @@ dictionary DragEventInit : MouseEventInit { data-x="dom-ToggleEvent-source">source
          attribute set to source at element.

          -
        13. -

          If hintPopoverListContainsElement is true and document's showing hint popover list's last item is not element, then run hide popover stack until given document, element, Hint, focusPreviousElement, and false.

          - -

          This happens if popovers are shown during the beforetoggle event. This is usually a developer error, so user agents are encouraged to show a warning.

          -
        14. - -
        15. -

          Otherwise, if autoPopoverListContainsElement is true and document's showing auto popover list's last item is not element, run hide popover stack until given document, element, Auto, focusPreviousElement, and false.

          - -

          This happens if popovers are shown during the beforetoggle event. This is usually a developer error, so user agents are encouraged to show a warning.

          -
        16. -
        17. If the result of running check popover validity given element, true, throwExceptions, and null is false, then run cleanupSteps and From c6a01ba53a047e96a2f0047787b6cd46efeae8ac Mon Sep 17 00:00:00 2001 From: Jake Archibald Date: Mon, 27 Apr 2026 18:52:03 -0400 Subject: [PATCH 23/24] Correct handling of throw Co-authored-by: Copilot --- source | 187 +++++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 130 insertions(+), 57 deletions(-) diff --git a/source b/source index 4f6e8aa5968..28d6fc9fa97 100644 --- a/source +++ b/source @@ -56311,10 +56311,9 @@ interface HTMLButtonElement : HTMLElement { data-x="attr-button-command-hide-popover-state">Hide Popover state:

            -
          1. If the result of running check popover validity given - target, true, false, and null is true, then run the - hide popover algorithm given target, true, true, false, and - element.

          2. +
          3. Let validity be the result of running check popover validity given target, true, and null. If this throws an exception, catch it, and let validity be false.

          4. + +
          5. If validity is true, then run the hide popover algorithm given target, true, true, false, and element.

        18. @@ -56323,15 +56322,25 @@ interface HTMLButtonElement : HTMLElement { data-x="attr-button-command-toggle-popover-state">Toggle Popover state:

            -
          1. If the result of running check popover validity given - target, false, false, and null is true, then run the - show popover algorithm given target, false, and - element.

          2. +
          3. Let validity be the result of running check popover validity + given target, false, and null. If this throws an exception, catch it, and let + validity be false.

          4. + +
          5. If validity is true, then run the show popover + algorithm given target, false, and element.

          6. + +
          7. +

            Otherwise:

            -
          8. Otherwise, if the result of running check popover validity given - target, true, false, and null is true, then run the - hide popover algorithm given target, true, - true, false, and element.

          9. +
              +
            1. Let validity be the result of running check popover + validity given target, true, and null. If this throws an exception, catch + it, and let validity be false.

            2. + +
            3. If validity is true, then run the hide popover algorithm + given target, true, true, false, and element.

            4. +
            +
          @@ -56340,10 +56349,12 @@ interface HTMLButtonElement : HTMLElement { data-x="attr-button-command-show-popover-state">Show Popover state:

            -
          1. If the result of running check popover validity given target, - false, false, and null is true, then run the show popover algorithm given target, false, and - element.

          2. +
          3. Let validity be the result of running check popover validity + given target, false, and null. If this throws an exception, catch it, and let + validity be false.

          4. + +
          5. If validity is true, then run the show popover + algorithm given target, false, and element.

          @@ -91256,8 +91267,11 @@ dictionary DragEventInit : MouseEventInit {
        19. Set document's showing popover to true.

        20. -
        21. If the result of running check popover validity given element, - false, throwExceptions, and null is false, then return.

        22. +
        23. Let validityResult be the result of running check popover validity + given element, false, and null. If this throws an exception, catch it, and let + validityResult be false.

        24. + +
        25. If validityResult is false, then return.

        26. Assert: element's popover trigger is null.

        27. @@ -91282,15 +91296,26 @@ dictionary DragEventInit : MouseEventInit { element is false, then run cleanupShowingSteps and return.

        28. -

          If the result of running check popover validity given element, false, - throwExceptions, and document is false, then run - cleanupShowingSteps and return.

          +

          Set validityResult to the result of running check popover validity given + element, false, and document. If this throws an exception, catch it, and set validityResult to that exception.

          Check popover validity is called again because firing the beforetoggle event could have disconnected this element or changed its popover attribute.

        29. +
        30. +

          If validityResult is not true:

          + +
            +
          1. Run cleanupShowingSteps.

          2. + +
          3. If throwExceptions is true and validityResult is a {{DOMException}}, then throw validityResult.

          4. + +
          5. Otherwise, return.

          6. +
          +
        31. +
        32. Let shouldRestoreFocus be false.

        33. Let originalType be the current state of element's DragEventInit : MouseEventInit { data-x="attr-popover">popover attribute, then:

            +
          1. Run cleanupShowingSteps.

          2. +
          3. If throwExceptions is true, then throw an "InvalidStateError" DOMException.

          4. @@ -91338,9 +91365,9 @@ dictionary DragEventInit : MouseEventInit {
          5. -

            If the result of running check popover validity given element, - false, throwExceptions, and document is false, then run - cleanupShowingSteps and return.

            +

            Set validityResult to the result of running check popover validity + given element, false, and document. If this throws an exception, catch + it, and set validityResult to that exception.

            Check popover validity is called again because running hide popover stack until above could have fired the beforetoggle event, and an event handler could have @@ -91348,6 +91375,19 @@ dictionary DragEventInit : MouseEventInit { attribute.

          6. +
          7. +

            If validityResult is not true:

            + +
              +
            1. Run cleanupShowingSteps.

            2. + +
            3. If throwExceptions is true and validityResult is a + {{DOMException}}, then throw validityResult.

            4. + +
            5. Otherwise, return.

            6. +
            +
          8. +
          9. If the result of running topmost auto or hint popover on document is null, then set shouldRestoreFocus to @@ -91493,8 +91533,20 @@ dictionary DragEventInit : MouseEventInit { elements">HTML element or null source:

              -
            1. If the result of running check popover validity given element, - true, throwExceptions, and null is false, then return.

            2. +
            3. Let validityResult be the result of running check popover validity + given element, true, and null. If this throws an exception, catch it, and let + validityResult be that exception.

            4. + +
            5. +

              If validityResult is not true:

              + +
                +
              1. If throwExceptions is true and validityResult is a + {{DOMException}}, then throw validityResult.

              2. + +
              3. Otherwise, return.

              4. +
              +
            6. Let document be element's node document.

            7. @@ -91547,13 +91599,26 @@ dictionary DragEventInit : MouseEventInit {
            8. If autoPopoverListContainsElement is true, then hide popover stack until given document, element, Auto, focusPreviousElement, and fireEvents.

            9. -

              If the result of running check popover validity given element, - true, throwExceptions, and null is false, then run cleanupSteps and - return.

              +

              Set validityResult to the result of running check popover validity + given element, true, and null. If this throws an exception, catch it, and set + validityResult to that exception.

              Check popover validity is called again because running hide popover stack until could have disconnected element or changed its popover attribute.

            10. + +
            11. +

              If validityResult is not true:

              + +
                +
              1. Run cleanupSteps.

              2. + +
              3. If throwExceptions is true and validityResult is a + {{DOMException}}, then throw validityResult.

              4. + +
              5. Otherwise, return.

              6. +
              +
          10. @@ -91570,15 +91635,28 @@ dictionary DragEventInit : MouseEventInit { element.

          11. -

            If the result of running check popover validity given element, - true, throwExceptions, and null is false, then run cleanupSteps and - return.

            +

            Set validityResult to the result of running check popover validity + given element, true, and null. If this throws an exception, catch it, and set + validityResult to that exception.

            Check popover validity is called again because firing the beforetoggle event could have disconnected element or changed its popover attribute.

          12. +
          13. +

            If validityResult is not true:

            + +
              +
            1. Run cleanupSteps.

            2. + +
            3. If throwExceptions is true and validityResult is a + {{DOMException}}, then throw validityResult.

            4. + +
            5. Otherwise, return.

            6. +
            +
          14. +
          15. Request an element to be removed from the top layer given element.

          16. @@ -91657,8 +91735,8 @@ dictionary DragEventInit : MouseEventInit { visibility state is showing; otherwise false.

            -
          17. Run check popover validity given expectedToBeShowing, true, and - null.

          18. +
          19. Run check popover validity given this, + expectedToBeShowing, and null.

        34. @@ -91878,21 +91956,15 @@ dictionary DragEventInit : MouseEventInit {

          To check popover validity for an HTML element - element given a boolean expectedToBeShowing, a boolean - throwExceptions, and a Document or null expectedDocument, - perform the following steps. They throw an exception or return a boolean.

          + element given a boolean expectedToBeShowing and a Document or + null expectedDocument, perform the following steps. They throw an exception or return + a boolean.

          1. If element's popover attribute is in the No Popover state, then:

            - -
              -
            1. If throwExceptions is true, then throw a - "NotSupportedError" DOMException.

            2. - -
            3. Return false.

            4. -
            + data-x="attr-popover-none-state">No Popover state, then throw a + "NotSupportedError" DOMException.

          2. @@ -91927,14 +91999,7 @@ dictionary DragEventInit : MouseEventInit {
          3. element's fullscreen flag is set,

          4. -

            then:

            - -
              -
            1. If throwExceptions is true, then throw an - "InvalidStateError" DOMException.

            2. - -
            3. Return false.

            4. -
            +

            then throw an "InvalidStateError" DOMException.

          5. Return true.

          6. @@ -92144,10 +92209,18 @@ dictionary DragEventInit : MouseEventInit { data-x="popover-showing-state">showing, then run the hide popover algorithm given popover, true, true, false, and node.

            -
          7. Otherwise, if popover's popover visibility state is hidden and the result of running check popover - validity given popover, false, false, and null is true, then run show - popover given popover, false, and node.

          8. +
          9. +

            Otherwise:

            + +
              +
            1. Let validity be the result of running check popover validity + given popover, false, and null. If this throws an exception, catch it, and let + validity be false.

            2. + +
            3. If validity is true, then run show popover given + popover, false, and node.

            4. +
            +
          From d70b0a82d3287d43b791bd99a11142fef3078124 Mon Sep 17 00:00:00 2001 From: Jake Archibald Date: Mon, 27 Apr 2026 18:55:14 -0400 Subject: [PATCH 24/24] Wrap --- source | 301 ++++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 203 insertions(+), 98 deletions(-) diff --git a/source b/source index 28d6fc9fa97..95d06347d11 100644 --- a/source +++ b/source @@ -56311,9 +56311,12 @@ interface HTMLButtonElement : HTMLElement { data-x="attr-button-command-hide-popover-state">Hide Popover state:

            -
          1. Let validity be the result of running check popover validity given target, true, and null. If this throws an exception, catch it, and let validity be false.

          2. +
          3. Let validity be the result of running check popover validity + given target, true, and null. If this throws an exception, catch it, and let + validity be false.

          4. -
          5. If validity is true, then run the hide popover algorithm given target, true, true, false, and element.

          6. +
          7. If validity is true, then run the hide popover algorithm given + target, true, true, false, and element.

          @@ -56333,9 +56336,9 @@ interface HTMLButtonElement : HTMLElement {

          Otherwise:

            -
          1. Let validity be the result of running check popover - validity given target, true, and null. If this throws an exception, catch - it, and let validity be false.

          2. +
          3. Let validity be the result of running check popover validity + given target, true, and null. If this throws an exception, catch it, and let + validity be false.

          4. If validity is true, then run the hide popover algorithm given target, true, true, false, and element.

          5. @@ -65788,7 +65791,8 @@ interface HTMLDialogElement : HTMLElement {
          6. Let hideUntil be the result of running topmost popover ancestor given this, null, and false.

          7. -
          8. Run hide popovers until given document, hideUntil, false, and true.

          9. +
          10. Run hide popovers until given document, hideUntil, + false, and true.

          11. Run the dialog focusing steps given this.

          @@ -66046,7 +66050,8 @@ interface HTMLDialogElement : HTMLElement {
        35. Let hideUntil be the result of running topmost popover ancestor given subject, null, and false.

        36. -
        37. Run hide popovers until given document, hideUntil, false, and true.

        38. +
        39. Run hide popovers until given document, hideUntil, + false, and true.

        40. Run the dialog focusing steps given subject.

        @@ -91172,7 +91177,8 @@ dictionary DragEventInit : MouseEventInit {

        Every HTML element has a popover trigger, which is an HTML element or null, initially set to null.

        -

        Every HTML element has a popover hiding, which is a boolean, initially set to false.

        +

        Every HTML element has a popover hiding, which + is a boolean, initially set to false.

        Every HTML element popover toggle task tracker, which is a toggle task tracker or null, initially null.

        @@ -91184,9 +91190,11 @@ dictionary DragEventInit : MouseEventInit { mode, which is "auto", "hint", or null, initially null.

        -

        Every Document has a hiding popover nesting count, which is a number, initially 0.

        +

        Every Document has a hiding popover nesting count, which is a number, + initially 0.

        -

        Every Document has a showing popover, which is a boolean, initially false.

        +

        Every Document has a showing popover, which is a boolean, initially + false.

        The following attribute change @@ -91253,11 +91261,12 @@ dictionary DragEventInit : MouseEventInit {

      2. Let document be element's node document.

      3. -

        If document's showing popover is true, or document's hiding popover nesting count is not 0, then:

        +

        If document's showing popover is true, or document's + hiding popover nesting count is not 0, then:

          -
        1. If throwExceptions is true, then throw a "InvalidStateError" - DOMException.

        2. +
        3. If throwExceptions is true, then throw a + "InvalidStateError" DOMException.

        4. Return.

        @@ -91296,8 +91305,9 @@ dictionary DragEventInit : MouseEventInit { element is false, then run cleanupShowingSteps and return.

      4. -

        Set validityResult to the result of running check popover validity given - element, false, and document. If this throws an exception, catch it, and set validityResult to that exception.

        +

        Set validityResult to the result of running check popover validity + given element, false, and document. If this throws an exception, catch it, + and set validityResult to that exception.

        Check popover validity is called again because firing the beforetoggle event could have disconnected this element or @@ -91310,7 +91320,8 @@ dictionary DragEventInit : MouseEventInit {

        1. Run cleanupShowingSteps.

        2. -
        3. If throwExceptions is true and validityResult is a {{DOMException}}, then throw validityResult.

        4. +
        5. If throwExceptions is true and validityResult is a + {{DOMException}}, then throw validityResult.

        6. Otherwise, return.

        @@ -91321,7 +91332,8 @@ dictionary DragEventInit : MouseEventInit {
      5. Let originalType be the current state of element's popover attribute.

      6. -
      7. Let ancestor be the result of running the topmost popover ancestor algorithm given element, source, and true.

      8. +
      9. Let ancestor be the result of running the topmost popover ancestor + algorithm given element, source, and true.

      10. Let effectiveType be originalType.

      11. @@ -91331,19 +91343,33 @@ dictionary DragEventInit : MouseEventInit {
        • ancestor is not null;

        • -
        • ancestor's opened in popover mode is "hint"; and

        • +
        • ancestor's opened in popover mode is "hint"; and

        • -
        • effectiveType is the Auto state,

        • +
        • effectiveType is the Auto + state,

        -

        then set effectiveType to the Hint state.

        +

        then set effectiveType to the Hint + state.

        -

        Hint popovers are lower priority than Auto popovers, so an Auto popover cannot have a Hint popover as a 'parent'. To resolve this case, the effectiveType is 'downgraded' to Hint.

        +

        Hint popovers are lower priority + than Auto popovers, so an Auto popover cannot have a Hint popover as a 'parent'. To resolve this case, the + effectiveType is 'downgraded' to Hint.

        -
      12. If effectiveType is the Auto or Hint state, then run hide popover stack until given document, ancestor, Hint, shouldRestoreFocus, and true.

      13. +
      14. If effectiveType is the Auto or + Hint state, then run hide popover stack + until given document, ancestor, Hint, shouldRestoreFocus, and true.

      15. -
      16. If effectiveType is the Auto state, then run hide popover stack until given document, ancestor, Auto, shouldRestoreFocus, and true.

      17. +
      18. If effectiveType is the Auto + state, then run hide popover stack until given document, + ancestor, Auto, + shouldRestoreFocus, and true.

      19. If effectiveType is Auto or DragEventInit : MouseEventInit { given element, false, and document. If this throws an exception, catch it, and set validityResult to that exception.

        -

        Check popover validity is called again because running hide popover stack until above could have fired the - beforetoggle event, and an event handler could have +

        Check popover validity is called again because running hide + popover stack until above could have fired the beforetoggle event, and an event handler could have disconnected this element or changed its popover attribute.

      20. @@ -91389,9 +91416,8 @@ dictionary DragEventInit : MouseEventInit {
      21. -

        If the result of running topmost auto or hint - popover on document is null, then set shouldRestoreFocus to - true.

        +

        If the result of running topmost auto or hint popover on document + is null, then set shouldRestoreFocus to true.

        This ensures that focus is returned to the previously-focused element only for the first popover in a stack.

        @@ -91411,7 +91437,8 @@ dictionary DragEventInit : MouseEventInit {

        Otherwise:

          -
        1. Assert: effectiveType is Hint.

        2. +
        3. Assert: effectiveType is Hint.

        4. Assert: document's showing hint popover list does not contain element.

        5. @@ -91448,7 +91475,9 @@ dictionary DragEventInit : MouseEventInit {
        6. Add an element to the top layer given element.

        7. -
        8. If effectiveType is Hint and ancestor's opened in popover mode is "auto", then set document's hint stack parent to ancestor.

        9. +
        10. If effectiveType is Hint and + ancestor's opened in popover mode is "auto", then + set document's hint stack parent to ancestor.

        11. Set element's popover visibility state to showing.

        12. @@ -91562,7 +91591,8 @@ dictionary DragEventInit : MouseEventInit {

          Let cleanupSteps be the following steps:

            -
          1. If nestedHide is false, then set element's popover hiding to false.

          2. +
          3. If nestedHide is false, then set element's popover + hiding to false.

          4. If element's popover close watcher is not null, then:

            @@ -91579,32 +91609,47 @@ dictionary DragEventInit : MouseEventInit {
          -
        13. Let autoPopoverListContainsElement be true if document's showing auto popover list contains element; otherwise false.

        14. +
        15. Let autoPopoverListContainsElement be true if document's + showing auto popover list contains + element; otherwise false.

        16. -
        17. Let hintPopoverListContainsElement be true if document's showing hint popover list contains element; otherwise false.

        18. +
        19. Let hintPopoverListContainsElement be true if document's + showing hint popover list contains + element; otherwise false.

        20. If element's opened in popover mode is "auto" or "hint", then:

            -
          1. If hintPopoverListContainsElement is true, then hide popover stack until given document, element, Hint, focusPreviousElement, and fireEvents.

          2. +
          3. If hintPopoverListContainsElement is true, then hide popover stack + until given document, element, Hint, focusPreviousElement, and + fireEvents.

          4. -

            If element is document's hint stack parent, then hide popover stack until given document, null, Hint, focusPreviousElement, and fireEvents.

            +

            If element is document's hint stack parent, then + hide popover stack until given document, null, Hint, focusPreviousElement, and + fireEvents.

            -

            If the document's hint stack parent is to hide, then all hint popovers are hidden.

            +

            If the document's hint stack parent is to hide, then + all hint popovers are hidden.

          5. -
          6. If autoPopoverListContainsElement is true, then hide popover stack until given document, element, Auto, focusPreviousElement, and fireEvents.

          7. +
          8. If autoPopoverListContainsElement is true, then hide popover stack + until given document, element, Auto, focusPreviousElement, and + fireEvents.

          9. Set validityResult to the result of running check popover validity given element, true, and null. If this throws an exception, catch it, and set validityResult to that exception.

            -

            Check popover validity is called again because running hide popover stack until could have disconnected - element or changed its popover attribute.

            +

            Check popover validity is called again because running hide + popover stack until could have disconnected element or changed its popover attribute.

          10. @@ -91674,7 +91719,10 @@ dictionary DragEventInit : MouseEventInit {
          11. Set element's popover visibility state to hidden.

          12. -
          13. If element is document's hint stack parent, or document's showing hint popover list is empty, then set document's hint stack parent to null.

          14. +
          15. If element is document's hint stack parent, or + document's showing hint popover list is empty, then set document's hint stack parent to + null.

          16. If fireEvents is true, then queue a popover toggle event task given element, "open", "closed", and @@ -91746,87 +91794,118 @@ dictionary DragEventInit : MouseEventInit {

  • -

    To hide popovers until, given a Document document, an HTML element or null endpoint, a boolean focusPreviousElement, and a boolean fireEvents:

    +

    To hide popovers until, given a Document document, an HTML element or null endpoint, a boolean + focusPreviousElement, and a boolean fireEvents:

      -
    1. Let endpointIsHint be true if document's showing hint popover list contains endpoint; otherwise false.

    2. +
    3. Let endpointIsHint be true if document's showing hint popover + list contains endpoint; otherwise + false.

    4. -
    5. Run hide popover stack until given document, endpoint, Hint, focusPreviousElement, and fireEvents.

    6. +
    7. Run hide popover stack until given document, endpoint, + Hint, focusPreviousElement, and + fireEvents.

    8. If endpointIsHint, then return.

    9. -
    10. Run hide popover stack until given document, endpoint, Auto, focusPreviousElement, and fireEvents.

    11. +
    12. Run hide popover stack until given document, endpoint, + Auto, focusPreviousElement, and + fireEvents.

    -

    To hide popover stack until, given a Document document, an HTML element or null endpoint, an Auto or Hint stackType, a boolean focusPreviousElement, and a boolean fireEvents:

    +

    To hide popover stack until, given a Document document, an + HTML element or null endpoint, an Auto or Hint + stackType, a boolean focusPreviousElement, and a boolean + fireEvents:

      -
    1. Let popoverList be document's showing auto popover list if stackType is Auto; otherwise document's showing hint popover list.

    2. +
    3. Let popoverList be document's showing auto popover list + if stackType is Auto; otherwise + document's showing hint popover list.

    4. -
    5. Let lastHideIndex be 0 if popoverList does not contain endpoint; otherwise the index of endpoint in popoverList plus 1.

    6. +
    7. Let lastHideIndex be 0 if popoverList does not contain endpoint; otherwise the index of endpoint in + popoverList plus 1.

    8. -
    9. Let toHide be a slice of popoverList from lastHideIndex, in reverse order.

    10. +
    11. Let toHide be a slice of + popoverList from lastHideIndex, in + reverse order.

    12. -
    13. Let toRemain be a slice of popoverList from 0 to lastHideIndex.

    14. +
    15. Let toRemain be a slice of + popoverList from 0 to lastHideIndex.

    16. -
    17. For each popover of toHide: run the hide popover algorithm given popover, focusPreviousElement, fireEvents, false, and null.

    18. +
    19. For each popover of toHide: run + the hide popover algorithm given popover, + focusPreviousElement, fireEvents, false, and null.

    20. -
    21. Let newPopoverList be document's showing auto popover list if stackType is Auto; otherwise document's showing hint popover list.

    22. +
    23. Let newPopoverList be document's showing auto popover + list if stackType is Auto; + otherwise document's showing hint popover list.

    24. Reverse newPopoverList.

    25. -

      For each popover in newPopoverList:

      +

      For each popover in + newPopoverList:

        -
      1. If toRemain contains popover, then continue.

      2. +
      3. If toRemain contains popover, + then continue.

      4. -

        Run the hide popover algorithm given popover, focusPreviousElement, false, false, and null.

        +

        Run the hide popover algorithm given popover, + focusPreviousElement, false, false, and null.

        -

        This happens if popovers are shown whilst hiding popovers. For example, in beforetoggle events. This is usually a developer error, so user agents are encouraged to show a warning. In this additional hiding phase, fireEvents is ignored, and false is used instead.

        +

        This happens if popovers are shown whilst hiding popovers. For example, in + beforetoggle events. This is usually a developer + error, so user agents are encouraged to show a warning. In this additional hiding phase, + fireEvents is ignored, and false is used instead.

    -

    The hide popover stack until - algorithm is used in several cases to hide all popovers that don't stay open when something - happens. For example, during light-dismiss of a popover, this algorithm ensures that we close only - the popovers that aren't related to the node clicked by the user.

    +

    The hide popover stack until algorithm is used in several cases to + hide all popovers that don't stay open when something happens. For example, during light-dismiss + of a popover, this algorithm ensures that we close only the popovers that aren't related to the + node clicked by the user.

    To find the topmost popover ancestor, given a Node - newPopoverOrTopLayerElement, an HTML element or null source, and a boolean - isPopover, perform the following steps. They return an HTML element or null.

    + newPopoverOrTopLayerElement, an HTML element or + null source, and a boolean isPopover, perform the following steps. They + return an HTML element or null.

    -

    The topmost popover ancestor algorithm will return the topmost ancestor popover for the provided popover or top layer - element. Popovers can be related to each other in several ways, creating a tree of popovers. - There are two paths through which one popover (call it the "child" popover) can have a topmost - ancestor popover (call it the "parent" popover):

    +

    The topmost popover ancestor algorithm will return the topmost ancestor popover + for the provided popover or top layer element. Popovers can be related to each other in several + ways, creating a tree of popovers. There are two paths through which one popover (call it the + "child" popover) can have a topmost ancestor popover (call it the "parent" popover):

    1. The popovers are nested within each other in the node tree. In this case, the descendant popover is the "child" and its topmost ancestor popover is the "parent".

    2. -
    3. An element is the 'source' of the popover (e.g., a button with command in the Show Popover state). In this case, - the popover is the "child", and the popover subtree the trigger element is in is the - "parent". The trigger element has to be in a popover and reference an open popover.

    4. +
    5. An element is the 'source' of the popover (e.g., a button with command in the Show Popover state). In this case, the + popover is the "child", and the popover subtree the trigger element is in is the "parent". The + trigger element has to be in a popover and reference an open popover.

    In each of the relationships formed above, the parent popover has to be strictly earlier in - the showing auto popover list or showing hint popover list than the child popover, or it does not form a valid - ancestral relationship. This eliminates non-showing popovers and self-pointers (e.g., a popover - containing an invoking element that points back to the containing popover), and it allows for the - construction of a well-formed tree from the (possibly cyclic) graph of connections. Only Auto and Hint popovers are considered.

    + the showing auto popover list or showing hint popover list than the + child popover, or it does not form a valid ancestral relationship. This eliminates non-showing + popovers and self-pointers (e.g., a popover containing an invoking element that points back to + the containing popover), and it allows for the construction of a well-formed tree from the + (possibly cyclic) graph of connections. Only Auto + and Hint popovers are considered.

    If the provided element is a top layer element such as a dialog which is not showing as a popover, then topmost popover ancestor will only look in the node tree @@ -91860,17 +91939,26 @@ dictionary DragEventInit : MouseEventInit { -

  • Let document be newPopoverOrTopLayerElement's node document.

  • +
  • Let document be newPopoverOrTopLayerElement's node + document.

  • -
  • Let combinedPopovers be document's showing auto popover list extended with document's showing hint popover list.

  • +
  • Let combinedPopovers be document's showing auto popover + list extended with document's showing + hint popover list.

  • -
  • Let popoverAncestorIndex be the index of the last item in combinedPopovers of which newPopoverOrTopLayerElement is a flat tree descendant, otherwise -1.

  • +
  • Let popoverAncestorIndex be the index of the last item in combinedPopovers of which newPopoverOrTopLayerElement + is a flat tree descendant, otherwise -1.

  • Let sourceAncestorIndex be -1.

  • -
  • If source is not null, then set sourceAncestorIndex to the index of the last item in combinedPopovers of which source is a flat tree descendant, otherwise -1.

  • +
  • If source is not null, then set sourceAncestorIndex to the index of + the last item in combinedPopovers of which + source is a flat tree descendant, + otherwise -1.

  • -
  • Let ancestorIndex be the maximum of popoverAncestorIndex and sourceAncestorIndex.

  • +
  • Let ancestorIndex be the maximum of popoverAncestorIndex and + sourceAncestorIndex.

  • If ancestorIndex is -1, then return null.

  • @@ -91890,7 +91978,10 @@ dictionary DragEventInit : MouseEventInit {

    While currentNode is not null:

      -
    1. If currentNode's opened in popover mode is "auto" or "hint", and currentNode's popover visibility state is showing, then return currentNode.

    2. +
    3. If currentNode's opened in popover mode is "auto" or "hint", and currentNode's + popover visibility state is showing, + then return currentNode.

    4. Set currentNode to currentNode's parent in the flat tree.

    5. @@ -91902,8 +91993,8 @@ dictionary DragEventInit : MouseEventInit {
    -

    To find the topmost auto or hint popover given a - Document document, perform the following steps. They return an To find the topmost auto or hint popover given + a Document document, perform the following steps. They return an HTML element or null.

      @@ -91957,8 +92048,8 @@ dictionary DragEventInit : MouseEventInit {

      To check popover validity for an HTML element element given a boolean expectedToBeShowing and a Document or - null expectedDocument, perform the following steps. They throw an exception or return - a boolean.

      + null expectedDocument, perform the following steps. They throw an exception or return a + boolean.

      1. @@ -92076,13 +92167,17 @@ dictionary DragEventInit : MouseEventInit {
      -

      Each Document has a hint stack parent, which is an - HTML element or null, initially null.

      +

      Each Document has a hint stack parent, which is an HTML element or null, initially null.

      -

      The hint stack parent tracks which item in the showing auto popover list is the 'parent' of the first item in the showing hint popover list, or null if the first item in showing hint popover list is not 'child' to an item in the showing auto popover list.

      +

      The hint stack parent tracks which item in the showing auto popover + list is the 'parent' of the first item in the showing hint popover list, or + null if the first item in showing hint popover list is not 'child' to an item in the + showing auto popover list.

      -

      Therefore, when the hint stack parent is not null, it will have an opened in popover mode of "auto".

      +

      Therefore, when the hint stack parent is not null, it will have an opened + in popover mode of "auto".

      The popover target attributes

      @@ -92255,8 +92350,9 @@ dictionary DragEventInit : MouseEventInit {

      "Light dismiss" means that clicking outside of a popover whose popover attribute is in the Auto or Hint state will close the popover. This is in addition to - how such popovers respond to close requests.

      + data-x="attr-popover-auto-state">Auto or Hint + state will close the popover. This is in addition to how such popovers respond to close requests.

      To light dismiss open popovers, given a PointerEvent @@ -92271,7 +92367,8 @@ dictionary DragEventInit : MouseEventInit {

    1. Let document be target's node document.

    2. -
    3. If the result of running topmost auto or hint popover given document is null, then return.

    4. +
    5. If the result of running topmost auto or hint popover given + document is null, then return.

    6. If event's type is "pointerdown", then: set document's popover @@ -92293,19 +92390,27 @@ dictionary DragEventInit : MouseEventInit {

    7. If sameTarget is false, then return

    8. -
    9. Let endpointIsHint be true if document's showing hint popover list contains ancestor; otherwise false.

    10. +
    11. Let endpointIsHint be true if document's showing hint + popover list contains ancestor; otherwise + false.

    12. -
    13. Run hide popover stack until given document, ancestor, Hint, false, and true.

    14. +
    15. Run hide popover stack until given document, + ancestor, Hint, false, and + true.

    16. Let autoEndpoint be ancestor.

    17. -

      If endpointIsHint, then set autoEndpoint to document's hint stack parent.

      +

      If endpointIsHint, then set autoEndpoint to document's + hint stack parent.

      -

      This means, if a hint popover is clicked, auto popovers are closed, except those that are parent to the clicked hint popover.

      +

      This means, if a hint popover is clicked, auto popovers are closed, except + those that are parent to the clicked hint popover.

    18. -
    19. Run hide popover stack until given document, autoEndpoint, Auto, false, and true.

    20. +
    21. Run hide popover stack until given document, + autoEndpoint, Auto, false, and + true.