mirror of
https://github.com/zoriya/v10.git
synced 2026-08-16 02:45:09 +00:00
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:
co-authored by
Claude Opus 4.8
parent
5e161837d8
commit
de2e1f823f
@@ -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();
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user