refactor(spf): drop the redundant readyState check in sync-live-seekable-range

context.mediaSource is published only while open (setupMediaSource is the sole
writer; cleared on detach), and a non-null live window means the timeline-bearing
track is still Infinity-duration, so endOfStream hasn't ended the MS. Present +
live window ⟹ open, so the explicit `readyState !== 'open'` guard before
setLiveSeekableRange (which throws off-open) is redundant. The "until open" test
becomes a publish transition.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Christian Pillsbury
2026-06-25 10:00:44 -07:00
co-authored by Claude Opus 4.8
parent 5e161837d8
commit de2e1f823f
2 changed files with 22 additions and 8 deletions
@@ -57,13 +57,15 @@ function syncLiveSeekableRangeSetup({
return effect(() => {
const mediaSource = context.mediaSource.get();
const liveWindow = liveWindowFromState(state);
if (!mediaSource || mediaSource.readyState !== 'open' || !liveWindow) return;
if (!mediaSource || !liveWindow) return;
// Re-declared as the window slides so seekable tracks the live window
// (the full DVR range remains seekable; seek-to-live-edge starts near the edge).
// No try/catch: `setLiveSeekableRange` throws only on a non-'open' readyState
// (checked synchronously just above — no await between, so it can't change) or
// an invalid range (`liveWindowFor` guarantees 0 ≤ start ≤ end).
// No readyState check, no try/catch: `setLiveSeekableRange` throws only on a
// non-'open' readyState or an invalid range, and neither can occur here —
// `setupMediaSource` publishes `context.mediaSource` only while open, and a
// non-null live window means the timeline-bearing track is still `Infinity`
// (so `endOfStream` hasn't ended the MS); `liveWindowFor` guarantees 0 ≤ start ≤ end.
mediaSource.setLiveSeekableRange(liveWindow.start, liveWindow.end);
});
}
@@ -65,11 +65,23 @@ describe('syncLiveSeekableRange', () => {
cleanup();
});
it('does nothing until the MediaSource is open', () => {
const ms = fakeMediaSource('closed');
const cleanup = run({ presentation: makePresentation(), trackId: 'v-1', mediaSource: ms });
it('declares only once the MediaSource is published (open)', async () => {
// `setupMediaSource` publishes `context.mediaSource` only once open, so an
// unpublished (absent) MediaSource is the "not ready" gate — no `readyState`
// check needed (presence + a live window ⟹ open).
const ms = fakeMediaSource();
const state = {
presentation: signal<MaybeResolvedPresentation | undefined>(makePresentation()),
selectedVideoTrackId: signal<string | undefined>('v-1'),
};
const context = { mediaSource: signal<MediaSource | undefined>(undefined) };
const cleanup = syncLiveSeekableRange.setup({ state, context, config: {} }) as () => void;
expect(ms.setLiveSeekableRange).not.toHaveBeenCalled();
expect(ms.setLiveSeekableRange).not.toHaveBeenCalled(); // unpublished → no declaration
context.mediaSource.set(ms); // published (open)
await Promise.resolve(); // effect re-runs on a microtask
expect(ms.setLiveSeekableRange).toHaveBeenCalledWith(100, 110);
cleanup();
});