Skip to content

Conversation

@foolip
Copy link
Member

@foolip foolip commented Nov 25, 2025

Fixes #11958.

  • At least two implementers are interested (and none opposed):
  • Tests are written and can be reviewed and commented upon at:
  • Implementation bugs are filed:
    • Chromium: …
    • Gecko: …
    • WebKit: …
    • Deno (only for timers, structured clone, base64 utils, channel messaging, module resolution, web workers, and web storage): …
    • Node.js (only for timers, structured clone, base64 utils, channel messaging, and module resolution): …
  • Corresponding HTML AAM & ARIA in HTML issues & PRs:
  • MDN issue is filed: …
  • The top of this comment includes a clear commit message to use.

(See WHATWG Working Mode: Changes for more details.)


/media.html ( diff )

@foolip
Copy link
Member Author

foolip commented Nov 25, 2025

A test for this would be:

<!DOCTYPE html>
<title>Media Loading State: the :buffering and :stalled pseudo-classes</title>
<link rel="help" href="https://drafts.csswg.org/selectors/#media-loading-state">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/media.js"></script>
<body>
  <video width="300" height="300" muted autoplay></video>
  <script>
    // The order of "is currently stalled" changing and events firing changed in
    // https://github.com/whatwg/html/pull/11959. This test asserts that when
    // the stalled event is fired, :stalled already matches.
    async_test((t) => {
      assert_implements(CSS.supports("selector(:stalled)"), ":stalled is not supported");
      const video = document.querySelector("video");
      // Send the first 100 kB and then stall "forever" (1 hour).
      video.src = `/media/movie_300.webm?pipe=trickle(100000:d3600)&random=${Math.random()}`;
      video.addEventListener("stalled", t.step_func_done(() => {
        assert_true(video.matches(":stalled"), ":stalled matches in stalled event handler");
      }));
    }, "Test :stalled timing relative to stalled event");

    // Note: it would be good to also test that :stalled doesn't match when the
    // progress event is fired, but that would require resuming the loading
    // again on demand and pipe=trickle doesn't support this.
  </script>
</body>

Safari fails this test. Unfortunately this test runs into the issues I described in web-platform-tests/interop#1003 (comment), that I haven't found anything that robustly fires the stalled event in all browsers.

Copy link
Member

@annevk annevk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This makes much more sense. We should always change state before firing events. And changing the state and firing the event should happen in the same task.

In WebKit the event is queued and then the state is changed which would make it observable before the event is dispatched (as they happen in different tasks). That doesn't seem good either, but also doesn't explain why your test would fail which doesn't hit that scenario.

cc @jyavenard @jernoble

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Development

Successfully merging this pull request may close these issues.

Timing of "is currently stalled" vs progress and stalled events

3 participants