A play's trace holds the playlist, audio and saved place it fetched (#192)

hls.js sends traceparent on its own requests (xhrSetup); a beacon, which
cannot set a header, and Safari's player, fetching the playlist itself,
carry it in the query, which the server reads where there is no header.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-11 14:41:28 +00:00
parent 35fca0a6a2
commit cd9aef36a1
4 changed files with 32 additions and 10 deletions

View File

@@ -1806,12 +1806,16 @@ test('DeadAir is off until turned on for a show, then plays it shortened, with y
// speed pressed. The element's own src is then hls.js's blob: address.
// How long it took to start goes to the server's log, under the trace of the tap (#190).
const started = page.waitForRequest(r => r.url().endsWith('/api/client') && r.postDataJSON()?.ev === 'play_start');
const piece = page.waitForRequest(r => r.url().endsWith('/deadair.mp3'));
await row.locator('[data-a=play]').click();
await expect.poll(() => page.evaluate(() => player.src)).toMatch(/\/deadair\.m3u8$/);
const report = await started;
expect(report.postDataJSON()).toMatchObject({ deadair: true });
expect(report.postDataJSON().ms).toBeGreaterThan(0);
expect(report.headers().traceparent).toMatch(/^00-[0-9a-f]{32}-[0-9a-f]{16}-01$/);
// hls.js's own requests carry the same trace as the tap that played them (#192).
const traceOf = h => h.traceparent?.split('-')[1];
expect(traceOf((await piece).headers())).toBe(traceOf(report.headers()));
await expect.poll(() => page.evaluate(() => document.querySelector('#audio').currentTime), { timeout: 15_000 }).toBeGreaterThan(0.5);
await expect(page.locator('#pdead')).toHaveAttribute('aria-pressed', 'true');
// Off from the player: the original, from the same place.