fix(inspect): never reset a preview video that is still starting
Deferring load() to the next task was not enough: CI on b7db4c3 hung
WebKit one step later in the fresh-page regression. Reset with load()
only a settled video (metadata read, or failed); a starting one is
paused, loses its src before the URL is revoked and is removed, then
left to be collected. The ownership workflow waits for the video to
settle before asserting the reset.
This commit is contained in:
+4
-3
@@ -1297,9 +1297,10 @@ mapped differences"):
|
||||
video previews in the same `#local-preview` slot as `video.local-file-preview` with
|
||||
native `controls`, `playsInline`, `preload="metadata"` and `muted`, never autoplays
|
||||
inline, and is paused, has its `src` removed and is removed from the page on replacement
|
||||
or dispose, before its URL is revoked; its `load()` reset runs in the next task, because
|
||||
WebKit (GStreamer) blocked the page when a still-starting video was reset in the same
|
||||
task (`replacing a video that just started loading never blocks the page`).
|
||||
or dispose, before its URL is revoked. A settled video (metadata read, or failed) is then
|
||||
reset with `load()`; one still starting is not, because WebKit (GStreamer) blocked the
|
||||
page when such a pipeline was reset (`replacing a video that just started loading never
|
||||
blocks the page`).
|
||||
- **D63** (status line): one `p.small.spaced-16` in `#local-preview`, for states the
|
||||
concept never shows: "Drop one file at a time.", "Folders cannot be inspected. Choose
|
||||
one image or video file.", "This file type cannot be previewed or inspected here.
|
||||
|
||||
@@ -355,6 +355,8 @@ test('URLs and media end with their owning session', async ({ page }) => {
|
||||
});
|
||||
await choose(page, localFixture('core-tags.webm', 'video/webm'));
|
||||
await expect(preview(page).locator('video')).toBeVisible();
|
||||
// A settled video (metadata read, or failed) is reset with load() when it is released.
|
||||
await expect.poll(() => preview(page).locator('video').evaluate(node => node.readyState >= 1 || !!node.error)).toBe(true);
|
||||
// Replacement.
|
||||
await choose(page, parityPng('f02.png'));
|
||||
await expect(preview(page).locator('img.local-file-preview')).toBeVisible();
|
||||
@@ -393,9 +395,9 @@ test('URLs and media end with their owning session', async ({ page }) => {
|
||||
|
||||
test('replacing a video that just started loading never blocks the page', async ({ context, browserName }) => {
|
||||
test.setTimeout(120000);
|
||||
// WebKit (GStreamer) blocked the page when a video's pipeline was reset with load() in the same task that
|
||||
// removed its src, while it was still starting: the next chooser selection never completed. Each fresh page
|
||||
// replaces its first video as soon as it shows.
|
||||
// WebKit (GStreamer) blocked the page when a video whose pipeline was still starting was reset with load(): the
|
||||
// next chooser selection, or the steps after it, never completed. Each fresh page replaces its first video as
|
||||
// soon as it shows.
|
||||
for (let attempt = 0; attempt < 15; attempt++) {
|
||||
const page = await context.newPage();
|
||||
try {
|
||||
|
||||
@@ -39,13 +39,16 @@ function element(tag, className, text) {
|
||||
|
||||
/**
|
||||
* Stops a preview from holding its blob: URL: media is paused and its src dropped before the session revokes the URL.
|
||||
* The media resets with load() in the next task: WebKit (GStreamer) blocked the page when a starting video was reset in
|
||||
* the same task that removed its src.
|
||||
* A settled video (metadata read, or failed) is then reset with load() to free its decoder at once. A video still
|
||||
* starting is not: WebKit (GStreamer) blocked the page when such a pipeline was reset, so it is left to be collected.
|
||||
*/
|
||||
function releaseMedia(node) {
|
||||
if (!node) return;
|
||||
if (node instanceof HTMLMediaElement) { node.pause(); node.removeAttribute('src'); setTimeout(() => node.load(), 0); }
|
||||
else node.removeAttribute('src');
|
||||
if (node instanceof HTMLMediaElement) {
|
||||
const settled = node.readyState >= HTMLMediaElement.HAVE_METADATA || node.error !== null;
|
||||
node.pause(); node.removeAttribute('src');
|
||||
if (settled) node.load();
|
||||
} else node.removeAttribute('src');
|
||||
node.remove();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user