From 5ee65020a59e0d7a202faa0c0b0ccd78a5fa1a5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Ribaudo?= Date: Thu, 28 May 2026 19:25:01 +0200 Subject: [PATCH] Rework resource selection algorithm to avoid interleaved jumps --- source | 352 +++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 217 insertions(+), 135 deletions(-) diff --git a/source b/source index 2825d4d2f50..7b48b7e93b8 100644 --- a/source +++ b/source @@ -38660,9 +38660,7 @@ interface MediaError {
  1. Set this element's is currently stalled to false.

  2. -
  3. Abort any already-running instance of the resource selection algorithm for this - element.

  4. +
  5. Abort the overall resource selection of this element.

  6. Let pending tasks be a list of all tasks from the media element's media element event task source in one of the @@ -38792,6 +38790,9 @@ interface MediaError { +

  7. Set the media element's in-progress resource selection child + pointer to null.

  8. +
  9. Set the element's networkState attribute to the NETWORK_NO_SOURCE value.

  10. @@ -38824,8 +38825,7 @@ interface MediaError {

    ⌛ Otherwise, if the media element does not have an assigned media provider object and does not have a src attribute, but does have a source element child, then - let mode be children and let candidate - be the first such source element child in tree order.

    + let mode be children.

    ⌛ Otherwise, the media element has no assigned media provider object and has neither a MediaError {

      -
    1. -

      ⌛ Let pointer be a position defined by two adjacent nodes in the - media element's child list, treating the start of the list (before the first - child in the list, if any) and end of the list (after the last child in the list, if any) as - nodes in their own right. One node is the node before pointer, and the - other node is the node after pointer. Initially, let pointer be the position between the candidate node and the - next node, if there are any, or the end of the list, if it is the last node.

      - -

      As nodes are inserted, removed, and moved into the media element, - pointer must be updated as follows:

      - -
      -
      If a new node is inserted or moved between the two nodes that define - pointer
      -
      Let pointer be the point between the node before pointer and the - new node. In other words, insertions at pointer go after - pointer.
      - -
      If the node before pointer is removed
      -
      Let pointer be the point between the node after pointer and the - node before the node after pointer. In other words, pointer doesn't - move relative to the remaining nodes.
      - -
      If the node after pointer is removed
      -
      Let pointer be the point between the node before pointer and the - node after the node before pointer. Just as with the previous case, - pointer doesn't move relative to the remaining nodes.
      -
      +
    2. ⌛ Set the media element's in-progress resource selection + child pointer to the position between the start of media element's child + list and its first child.

    3. -

      Other changes don't affect pointer.

      - +
    4. Continue the resource selection algorithm for children given the + media element.

    5. -
    6. Process candidate: If candidate does not have a - src attribute, or if its src attribute's value is the empty string, then end the - synchronous section, and jump down to the failed with elements step - below.

    7. +
    8. End the synchronous section, wait for continue the resource + selection algorithm for children's parallel steps to + complete, and continue the remaining steps in parallel.

    9. -
    10. ⌛ If candidate has a media - attribute whose value does not match the - environment, then end the synchronous section, and jump down to the - failed with elements step below.

    11. +
    12. Return. The element won't attempt to load another resource until either this algorithm + or continue the resource selection algorithm for children are triggered + again.

    13. +
    +
    + -
  11. ⌛ Let urlRecord be the result of encoding-parsing a URL - given candidate's src attribute's value, - relative to candidate's node document when the src attribute was last changed.

    - +

    The dedicated media source failure steps with a list of promises + promises are the following steps:

    -
  12. ⌛ If urlRecord is failure, then end the synchronous - section, and jump down to the failed with elements step below.

  13. +
      +
    1. Set the error attribute to the result of + creating a MediaError with MEDIA_ERR_SRC_NOT_SUPPORTED.

    2. -
    3. ⌛ If candidate has a type attribute whose value, when parsed as a MIME - type (including any codecs described by the codecs parameter, for - types that define that parameter), represents a type that the user agent knows it cannot - render, then end the synchronous section, and jump down to the failed with elements step below.

    4. +
    5. Forget the media element's media-resource-specific tracks.

    6. -
    7. ⌛ Set the currentSrc attribute to - the result of applying the URL serializer to - urlRecord.

    8. +
    9. Set the element's networkState attribute to + the NETWORK_NO_SOURCE value.

    10. -
    11. End the synchronous section, continuing the remaining steps - in parallel.

    12. +
    13. Set the element's show poster flag to true.

    14. -
    15. Run the resource fetch algorithm - with urlRecord. If that algorithm returns without aborting this one, - then the load failed.

    16. +
    17. Fire an event named error at the media element.

    18. -
    19. Failed with elements: Queue a media element task given the - media element to fire an event named - error at candidate.

    20. +
    21. Reject pending play promises with promises and a + "NotSupportedError" DOMException.

    22. -
    23. Await a stable state. The synchronous section - consists of all the remaining steps of this algorithm until the algorithm says the - synchronous section has ended. (Steps in synchronous sections are marked with ⌛.)

    24. +
    25. Set the element's delaying-the-load-event flag to false. This stops delaying the load event.

    26. +
    + +
+ -
  • Forget the media element's media-resource-specific - tracks.

  • +
    +

    To abort the overall resource selection of a media element, abort its + resource selection algorithm, if running, and + any continue the resource selection algorithm for children invocation running for it, + together with any resource fetch algorithm + invoked therein, and set the media element's in-progress resource selection + child pointer to null.

    +
    -
  • Find next candidate: Let candidate be - null.

  • +
    +

    To continue the resource selection algorithm for children given a media + element:

    -
  • Search loop: If the node after pointer is - the end of the list, then jump to the waiting step below.

  • +
      +
    1. Let pointer be the media element's in-progress resource + selection child pointer.

    2. -
    3. ⌛ If the node after pointer is a source element, - let candidate be that element.

    4. +
    5. Let candidate be null.

    6. -
    7. ⌛ Advance pointer so that the node before pointer is now the node that was after pointer, and the node - after pointer is the node after the node that used to be after pointer, if any.

    8. +
    9. +

      While candidate is not a source element + and the node after pointer is not the end of the list:

      -
    10. ⌛ If candidate is null, jump back to the search - loop step. Otherwise, jump back to the process candidate step.

    11. +
        +
      1. Set candidate to the node after pointer.

      2. -
      3. Waiting: Set the element's networkState attribute to the NETWORK_NO_SOURCE value.

      4. +
      5. Advance pointer to the position between candidate and the next + node (or the end of the list).

      6. +
      + -
    12. ⌛ Set the element's show poster flag to true.

    13. +
    14. Set the media element's in-progress resource selection child + pointer to pointer.

    15. -
    16. Queue a media element task given the media element - to set the element's delaying-the-load-event flag to false. This stops delaying the load event.

    17. +
    18. +

      If candidate is not a source element:

      -
    19. End the synchronous section, continuing the remaining steps - in parallel.

    20. +
        +
      1. Set the media element's networkState attribute to the NETWORK_NO_SOURCE value.

      2. -
      3. Wait until the node after pointer is a node other than the end of - the list. (This step might wait forever.)

      4. +
      5. Set the media element's show poster flag to true.

      6. -
      7. Await a stable state. The synchronous section - consists of all the remaining steps of this algorithm until the algorithm says the - synchronous section has ended. (Steps in synchronous sections are marked with ⌛.)

      8. +
      9. Queue a media element task given the media element to set the + media element's delaying-the-load-event flag to false. This stops + delaying the load event.

      10. -
      11. ⌛ Set the element's delaying-the-load-event flag back to true (this - delays the load event again, in case it hasn't been - fired yet).

        +
      12. Return.
      13. +
      + -
    21. ⌛ Set the networkState back to NETWORK_LOADING.

    22. +
    23. Let urlRecord be the media source child url record of + candidate.

    24. -
    25. ⌛ Jump back to the find next candidate step above.

    26. -
    - - +
  • If urlRecord is not failure, set the currentSrc attribute to the result of applying the URL serializer to urlRecord.

  • -

    The dedicated media source failure steps with a list of promises - promises are the following steps:

    +
  • +

    Run the following steps in parallel:

      -
    1. Set the error attribute to the result of - creating a MediaError with MEDIA_ERR_SRC_NOT_SUPPORTED.

    2. +
    3. If urlRecord is not failure, run the resource fetch algorithm with urlRecord. + If that algorithm returns without aborting this one, then the load failed.

    4. -
    5. Forget the media element's media-resource-specific tracks.

    6. +
    7. Queue a media element task given the media element to fire an event named error at candidate.

    8. -
    9. Set the element's networkState attribute to - the NETWORK_NO_SOURCE value.

    10. +
    11. Await a stable state. The synchronous section consists of all + the remaining steps of this algorithm until the algorithm says the synchronous + section has ended. (Steps in synchronous + sections are marked with ⌛.)

    12. -
    13. Set the element's show poster flag to true.

    14. +
    15. Forget the media element's media-resource-specific tracks.

    16. -
    17. Fire an event named error at the media element.

    18. +
    19. Continue the resource selection algorithm for children given the + media element.

    20. -
    21. Reject pending play promises with promises and a - "NotSupportedError" DOMException.

    22. +
    23. End the synchronous section, and wait for continue the resource + selection algorithm for children's parallel steps to + complete.

    24. +
    +
  • + +
    -
  • Set the element's delaying-the-load-event flag to false. This stops delaying the load event.

  • + +
    +

    A media element has an in-progress resource + selection child pointer, which is either null or a position + defined by two adjacent nodes in the media element's + child list, treating the start of the list (before the first child + in the list, if any) and end of the list (after the last child in + the list, if any) as nodes in their own right. One node is the node + before the pointer, and the other node is the node after the + pointer. It is initially null.

    + +

    As nodes are inserted, removed, and moved into the media element, its + in-progress resource selection child pointer, if non-null, must be updated as + follows:

    + +
    +
    If a new node is inserted or moved between the two nodes that define the pointer
    +
    +
      +
    1. Set the in-progress resource selection child pointer to the point between + the node before the pointer and the new node. In other words, insertions at the pointer go + after the pointer.

    2. + +
    3. Await a stable state. The synchronous section consists of all + the remaining steps of this algorithm. (Steps in the synchronous section are marked + with ⌛.)

    4. + +
    5. +

      ⌛ If the media element's networkState is NETWORK_NO_SOURCE:

      + +

      This happens when the continue the resource selection algorithm for + children terminated due to having tried all the source elements and not + having found a suitable one. There is no other resource selection algorithm or continue + the resource selection algorithm for children currently running for this media + element.

      + +
        +
      1. ⌛ Set the media element's delaying-the-load-event flag back to + true (this delays the load event again, in case it + hasn't been fired yet).

      2. + +
      3. ⌛ Set the media element's networkState to NETWORK_LOADING.

      4. + +
      5. ⌛ Run the continue the resource selection algorithm for children given the + media element.

      6. +
      +
    +
    + +
    If the node before the pointer is removed
    +
    Set the in-progress resource selection child pointer to the point between the + node after the pointer and the node before the node after the pointer. In other words, the + pointer doesn't move relative to the remaining nodes.
    + +
    If the node after the pointer is removed
    +
    Set the in-progress resource selection child pointer to be the point between the + node before the pointer and the node after the node before the pointer. Just as with the previous + case, the pointer doesn't move relative to the remaining nodes.
    +
    +
    + +
    +

    To get the media source child url record of a source element + candidate, run these steps. They return failure or a URL record.

    + +
      +
    1. +

      If any of the following conditions is true:

      + +
        +
      • candidate does not have a src + attribute;

      • +
      • candidate's src attribute's value is + the empty string;

      • +
      • or candidate has a media attribute + whose value does not match the + environment,

      • +
      + +

      then return failure.

    2. + +
    3. Let urlRecord be the result of encoding-parsing a URL + given candidate's src attribute's value, + relative to candidate's node document when the src attribute was last changed.

      + + +
    4. If urlRecord is failure, return failure.

    5. + +
    6. If candidate has a type attribute + whose value, when parsed as a MIME type (including any codecs described by the + codecs parameter, for types that define that parameter), represents + a type that the user agent knows it cannot render, return failure.

    7. + +
    8. Return urlRecord.

    @@ -39731,8 +39814,8 @@ interface MediaError {
  • Fire an event named error at the media element.

  • -
  • Abort the overall resource selection - algorithm.

  • +
  • Abort the overall resource selection of the media + element.

  • @@ -39762,8 +39845,8 @@ interface MediaError {
  • Fire an event named error at the media element.

  • -
  • Abort the overall resource selection - algorithm.

  • +
  • Abort the overall resource selection of the media + element.

  • @@ -39801,8 +39884,7 @@ interface MediaError {
  • Set the element's delaying-the-load-event flag to false. This stops delaying the load event.

  • -
  • Abort the overall resource selection - algorithm.

  • +
  • Abort the overall resource selection of the media element.

  • @@ -39835,9 +39917,9 @@ interface MediaError { -
  • Final step: If the user agent ever reaches this step (which can only happen if the entire resource - gets loaded and kept available): abort the overall resource selection algorithm.

  • +
  • Final step: If the user agent ever reaches this step (which can only happen if the + entire resource gets loaded and kept available): Abort the overall resource + selection of the media element.