@amazon/vinyl 3.2.1 → 3.2.3-next.20261001143710

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (109) hide show
  1. package/README.md +2 -2
  2. package/dist/index.cjs +98 -43
  3. package/dist/index.cjs.map +3 -3
  4. package/dist/index.js +126 -68
  5. package/dist/index.js.map +3 -3
  6. package/dist/test/benchmark.es5.js +7 -6
  7. package/dist/test/benchmark.js +35 -30
  8. package/dist/test/benchmark.js.map +3 -3
  9. package/dist/test/integ.es5.js +329 -312
  10. package/dist/test/integ.js +519 -187
  11. package/dist/test/integ.js.map +4 -4
  12. package/dist/types/current/ad/AdControllerImpl.d.ts.map +1 -1
  13. package/dist/types/current/ad/AdControllerImpl.js +15 -1
  14. package/dist/types/current/ad/discoverHlsInterstitials.js +13 -1
  15. package/dist/types/current/drm/DrmControllerImpl.d.ts +6 -0
  16. package/dist/types/current/drm/DrmControllerImpl.d.ts.map +1 -1
  17. package/dist/types/current/drm/DrmControllerImpl.js +11 -1
  18. package/dist/types/current/drm/commonEme/MsCommonEme.d.ts.map +1 -1
  19. package/dist/types/current/drm/commonEme/MsCommonEme.js +2 -2
  20. package/dist/types/current/drm/commonEme/StandardCommonEme.d.ts.map +1 -1
  21. package/dist/types/current/drm/commonEme/StandardCommonEme.js +3 -2
  22. package/dist/types/current/drm/commonEme/WebKitCommonEme.d.ts.map +1 -1
  23. package/dist/types/current/drm/commonEme/WebKitCommonEme.js +2 -2
  24. package/dist/types/current/drm/dom/MSMediaKeys.d.ts +1 -1
  25. package/dist/types/current/drm/dom/MSMediaKeys.d.ts.map +1 -1
  26. package/dist/types/current/drm/dom/WebKitMediaKeys.d.ts +1 -1
  27. package/dist/types/current/drm/dom/WebKitMediaKeys.d.ts.map +1 -1
  28. package/dist/types/current/drm/util/extractContentId.js +2 -2
  29. package/dist/types/current/playback/PlaybackControllerImpl.d.ts +9 -3
  30. package/dist/types/current/playback/PlaybackControllerImpl.d.ts.map +1 -1
  31. package/dist/types/current/playback/PlaybackControllerImpl.js +38 -33
  32. package/dist/types/current/streaming/MediaQualityMetadata.d.ts +3 -1
  33. package/dist/types/current/streaming/MediaQualityMetadata.d.ts.map +1 -1
  34. package/dist/types/current/streaming/SegmentControllerImpl.d.ts +1 -1
  35. package/dist/types/current/streaming/buffering/BufferingController.d.ts +1 -1
  36. package/dist/types/current/streaming/buffering/BufferingController.d.ts.map +1 -1
  37. package/dist/types/current/streaming/buffering/BufferingController.js +14 -5
  38. package/dist/types/current/streaming/buffering/MediaSourceController.d.ts.map +1 -1
  39. package/dist/types/current/streaming/buffering/MediaSourceController.js +4 -0
  40. package/dist/types/current/text/discoverDashTextTracks.d.ts +2 -2
  41. package/dist/types/current/text/discoverDashTextTracks.js +4 -3
  42. package/dist/types/current/text/parseWebVtt.d.ts.map +1 -1
  43. package/dist/types/current/text/parseWebVtt.js +3 -2
  44. package/dist/types/current/track/TrackController.d.ts.map +1 -1
  45. package/dist/types/current/track/TrackController.js +7 -0
  46. package/dist/types/current/track/hls/HlsManifestData.d.ts +14 -1
  47. package/dist/types/current/track/hls/HlsManifestData.d.ts.map +1 -1
  48. package/dist/types/current/track/hls/buildHlsMediaTimeline.d.ts.map +1 -1
  49. package/dist/types/current/track/hls/buildHlsMediaTimeline.js +10 -2
  50. package/dist/types/current/track/hls/createUrlHlsManifestProvider.d.ts +3 -2
  51. package/dist/types/current/track/hls/createUrlHlsManifestProvider.d.ts.map +1 -1
  52. package/dist/types/current/track/hls/createUrlHlsManifestProvider.js +8 -3
  53. package/dist/types/current/track/mse/MseTrack.d.ts +0 -1
  54. package/dist/types/current/track/mse/MseTrack.d.ts.map +1 -1
  55. package/dist/types/current/track/mse/MseTrack.js +5 -6
  56. package/dist/types/current/tsconfig.tsbuildinfo +1 -1
  57. package/dist/types/ts3.7/drm/DrmControllerImpl.d.ts +6 -0
  58. package/dist/types/ts3.7/playback/PlaybackControllerImpl.d.ts +9 -3
  59. package/dist/types/ts3.7/streaming/MediaQualityMetadata.d.ts +3 -1
  60. package/dist/types/ts3.7/streaming/SegmentControllerImpl.d.ts +1 -1
  61. package/dist/types/ts3.7/streaming/buffering/BufferingController.d.ts +1 -1
  62. package/dist/types/ts3.7/text/discoverDashTextTracks.d.ts +2 -2
  63. package/dist/types/ts3.7/track/hls/HlsManifestData.d.ts +14 -1
  64. package/dist/types/ts3.7/track/hls/createUrlHlsManifestProvider.d.ts +3 -2
  65. package/dist/types/ts3.7/track/mse/MseTrack.d.ts +0 -1
  66. package/dist/types/ts4.1/drm/DrmControllerImpl.d.ts +6 -0
  67. package/dist/types/ts4.1/playback/PlaybackControllerImpl.d.ts +9 -3
  68. package/dist/types/ts4.1/streaming/MediaQualityMetadata.d.ts +3 -1
  69. package/dist/types/ts4.1/streaming/SegmentControllerImpl.d.ts +1 -1
  70. package/dist/types/ts4.1/streaming/buffering/BufferingController.d.ts +1 -1
  71. package/dist/types/ts4.1/text/discoverDashTextTracks.d.ts +2 -2
  72. package/dist/types/ts4.1/track/hls/HlsManifestData.d.ts +14 -1
  73. package/dist/types/ts4.1/track/hls/createUrlHlsManifestProvider.d.ts +3 -2
  74. package/dist/types/ts4.1/track/mse/MseTrack.d.ts +0 -1
  75. package/dist/types/ts4.7/drm/DrmControllerImpl.d.ts +6 -0
  76. package/dist/types/ts4.7/playback/PlaybackControllerImpl.d.ts +9 -3
  77. package/dist/types/ts4.7/streaming/MediaQualityMetadata.d.ts +3 -1
  78. package/dist/types/ts4.7/streaming/SegmentControllerImpl.d.ts +1 -1
  79. package/dist/types/ts4.7/streaming/buffering/BufferingController.d.ts +1 -1
  80. package/dist/types/ts4.7/text/discoverDashTextTracks.d.ts +2 -2
  81. package/dist/types/ts4.7/track/hls/HlsManifestData.d.ts +14 -1
  82. package/dist/types/ts4.7/track/hls/createUrlHlsManifestProvider.d.ts +3 -2
  83. package/dist/types/ts4.7/track/mse/MseTrack.d.ts +0 -1
  84. package/dist/unit/types/current/ad/AdControllerImpl.test.js +66 -0
  85. package/dist/unit/types/current/ad/discoverHlsInterstitials.test.js +29 -2
  86. package/dist/unit/types/current/drm/DrmControllerImpl.test.js +19 -1
  87. package/dist/unit/types/current/drm/commonEme/StandardCommonEme.test.js +12 -4
  88. package/dist/unit/types/current/drm/util/extractContentId.test.js +7 -0
  89. package/dist/unit/types/current/index.d.ts +1 -0
  90. package/dist/unit/types/current/index.d.ts.map +1 -1
  91. package/dist/unit/types/current/index.js +1 -0
  92. package/dist/unit/types/current/playback/PlaybackControllerImpl.test.js +15 -0
  93. package/dist/unit/types/current/streaming/MediaQualityMetadata.test.js +8 -0
  94. package/dist/unit/types/current/streaming/MseTrack.test.js +15 -0
  95. package/dist/unit/types/current/streaming/buffering/BufferingController.test.js +26 -0
  96. package/dist/unit/types/current/streaming/buffering/MediaSourceController.test.js +29 -0
  97. package/dist/unit/types/current/text/TextTrack.test.d.ts +2 -0
  98. package/dist/unit/types/current/text/TextTrack.test.d.ts.map +1 -0
  99. package/dist/unit/types/current/text/TextTrack.test.js +12 -0
  100. package/dist/unit/types/current/text/discoverDashTextTracks.test.js +17 -0
  101. package/dist/unit/types/current/text/parseWebVtt.test.js +26 -0
  102. package/dist/unit/types/current/track/TrackController.test.js +15 -60
  103. package/dist/unit/types/current/track/hls/buildHlsMediaTimeline.test.js +22 -0
  104. package/dist/unit/types/current/track/hls/createUrlHlsManifestProvider.test.js +23 -0
  105. package/dist/unit/types/current/tsconfig.tsbuildinfo +1 -1
  106. package/dist/vinylTestUtil/types/current/tsconfig.tsbuildinfo +1 -1
  107. package/docs/CUSTOMIZATION_GUIDE.md +310 -0
  108. package/package.json +10 -10
  109. package/docs/DASH_MANIFEST_TRANSFORM_GUIDE.md +0 -236
@@ -14,6 +14,13 @@ describe('extractContentId', () => {
14
14
  expect(extractContentId(createContentIdByteArray('skd://example0'))).toBe('example0');
15
15
  });
16
16
  });
17
+ describe('with an offset view', () => {
18
+ it('reads only the bytes the view spans', () => {
19
+ const padded = createContentIdByteArray('\0\0skd://example0\0\0');
20
+ const view = padded.subarray(4, padded.byteLength - 4);
21
+ expect(extractContentId(view)).toBe('example0');
22
+ });
23
+ });
17
24
  describe('without match', () => {
18
25
  it('throws ValidationError', () => {
19
26
  expect(() => {
@@ -67,6 +67,7 @@ import './text/parseWebVtt.test';
67
67
  import './text/pickPreferredTextTrack.test';
68
68
  import './text/SidecarTextTrackController.test';
69
69
  import './text/SidecarTextTrackLoader.test';
70
+ import './text/TextTrack.test';
70
71
  import './text/VttCueStyle.test';
71
72
  import './track/AutoResetController.test';
72
73
  import './track/createSegmentDataProvider.test';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../test/unit/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../test/unit/index.ts"],"names":[],"mappings":"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"}
@@ -67,6 +67,7 @@ import './text/parseWebVtt.test';
67
67
  import './text/pickPreferredTextTrack.test';
68
68
  import './text/SidecarTextTrackController.test';
69
69
  import './text/SidecarTextTrackLoader.test';
70
+ import './text/TextTrack.test';
70
71
  import './text/VttCueStyle.test';
71
72
  import './track/AutoResetController.test';
72
73
  import './track/createSegmentDataProvider.test';
@@ -496,6 +496,21 @@ describe('PlaybackController', () => {
496
496
  await clock.tick(controller.options.seekTimeout);
497
497
  await seekExpectation;
498
498
  });
499
+ it('resolves a superseded seek at once when its seeking event never fires', async () => {
500
+ // A source swap can leave the original seek's `seeking`
501
+ // event unfired (the default mock never emits it). A newer
502
+ // seek supersedes it; the stale one must resolve immediately
503
+ // rather than hang for the full seekTimeout.
504
+ setSeekable([[0, 100]]);
505
+ const first = controller.seekTo(50);
506
+ const second = controller.seekTo(60);
507
+ // No clock tick: the newer seek's abort resolves `first` now.
508
+ // (A full-timeout hang would require clock.tick(seekTimeout).)
509
+ await expectAsync(first).toBeResolved();
510
+ // `second`'s own `seeking` never fires either; park its
511
+ // rejection (settled on dispose) so it isn't unhandled.
512
+ second.catch(() => undefined);
513
+ });
499
514
  it('times out pending seeks after seekTimeout', async () => {
500
515
  const pendingSeekExpectation = expectAsync(controller.seekTo(60)).toBeRejectedWithError('seek timed out on seeking event after 30s');
501
516
  setSeekable([[0, 100]]);
@@ -3,6 +3,7 @@
3
3
  * SPDX-License-Identifier: Apache-2.0
4
4
  */
5
5
  import { DrmKeySystem, drmProtectionValidator } from '@amazon/vinyl';
6
+ import { expectTypeStrictlyEquals } from '@amazon/vinyl-util/browserTestUtil';
6
7
  describe('drmProtectionValidator', () => {
7
8
  it('validates a complete DrmProtection', () => {
8
9
  expect(drmProtectionValidator.isValid({
@@ -37,3 +38,10 @@ describe('drmProtectionValidator', () => {
37
38
  expect(drmProtectionValidator.isValid({ keySystem: 123 })).toBeFalse();
38
39
  });
39
40
  });
41
+ describe('ALL_CONTENT_TYPES', () => {
42
+ it('provides a comprehensive list of all content types', () => {
43
+ // The player emits quality-change events per entry; a missing type
44
+ // silently emits none, and `satisfies` alone does not catch it.
45
+ expectTypeStrictlyEquals(true);
46
+ });
47
+ });
@@ -224,6 +224,21 @@ describe('MseTrack', () => {
224
224
  abort: any(Abort),
225
225
  });
226
226
  });
227
+ it('aborts the drm session abort so key sessions close', async () => {
228
+ // Regression: MSE key sessions must be tied to the per-activation
229
+ // drmSessionAbort (fired by closeDrmSessions on deactivate), not a
230
+ // separate abort that never fires — otherwise sessions leak.
231
+ track = createTrack();
232
+ await awaitContentTypes();
233
+ getAudioStream().streamingQuality =
234
+ createEmptyMediaQualityMetadata();
235
+ track.activate({});
236
+ const { abort } = deps.drmController.initializeForPlayback.calls.mostRecent()
237
+ .args[1];
238
+ expect(abort.aborted()).toBeFalse();
239
+ track.deactivate();
240
+ expect(abort.aborted()).toBeTrue();
241
+ });
227
242
  });
228
243
  describe('error', () => {
229
244
  it('returns the first emitted error', async () => {
@@ -286,6 +286,32 @@ describe('BufferingControllerImpl', () => {
286
286
  expect(sourceBufferController.append).toHaveBeenCalledTimes(1);
287
287
  });
288
288
  });
289
+ describe('when the append budget grows while a segment is partly appended', () => {
290
+ it('appends only the bytes remaining in the segment', async () => {
291
+ // A budget wide enough to hold a whole segment, so draining the
292
+ // buffer can lift it back above the segment size mid-append.
293
+ bufferingController.dispose();
294
+ bufferingController = createBufferingController({
295
+ maxAppendSize: { audio: 500 },
296
+ minBuffer: 6,
297
+ });
298
+ bufferingController.activate();
299
+ setSegmentList([200, 400]);
300
+ await open(); // segment 0 appends whole, buffering 0-10s
301
+ await setTime(5); // segment 1 partly appends: 300 of 400 bytes
302
+ expect(getMostRecentAppendData().byteLength).toBe(300);
303
+ sourceBufferController.append.calls.reset();
304
+ // The playhead drains the buffer, widening the budget past the
305
+ // segment's full size.
306
+ await setTime(15.5);
307
+ const appended = sourceBufferController.append.calls
308
+ .allArgs()
309
+ .map(([data]) => data.byteLength);
310
+ // Only the 100 unappended bytes; re-appending all 400 would
311
+ // duplicate the 300 already buffered.
312
+ expect(appended[0]).toBe(100);
313
+ });
314
+ });
289
315
  describe('when contentType is undefined', () => {
290
316
  it('uses DEFAULT_MAX_APPEND_SIZE for max byte length', async () => {
291
317
  setSegmentList([DEFAULT_MAX_APPEND_SIZE * 2], 0, 'unknown');
@@ -89,6 +89,35 @@ describe('MediaSourceControllerImpl', () => {
89
89
  URL.revokeObjectURL.and.throwError(new Error('revoke failed'));
90
90
  expect(() => controller.deactivate()).not.toThrow();
91
91
  });
92
+ it('does not report a re-activated media source as ready to append', async () => {
93
+ // A track is deactivated and reactivated whenever an ad plays over
94
+ // it, and each activation builds its own media source, whose
95
+ // duration has not been set yet.
96
+ open();
97
+ await flushPromises();
98
+ const firstRef = controller.createSourceBuffer('audio', 'audio/mp4');
99
+ expect(controller.readyToAppend)
100
+ .withContext('ready on the first media source')
101
+ .toBeTrue();
102
+ firstRef.dispose(); // the buffering controller drops its buffers
103
+ controller.deactivate();
104
+ const secondSource = new MockMediaSource();
105
+ implementEventFakes(secondSource);
106
+ secondSource.addSourceBuffer.and.callFake(() => new MockSourceBuffer());
107
+ mediaSourceFactory.and.returnValue(secondSource);
108
+ controller.activate();
109
+ await flushPromises();
110
+ controller.createSourceBuffer('audio', 'audio/mp4');
111
+ expect(controller.readyToAppend)
112
+ .withContext('duration not yet set on the new media source')
113
+ .toBeFalse();
114
+ secondSource.readyState = 'open';
115
+ secondSource.dispatchEvent(mockEvent('sourceopen'));
116
+ await flushPromises();
117
+ expect(controller.readyToAppend)
118
+ .withContext('ready once the new duration is set')
119
+ .toBeTrue();
120
+ });
92
121
  });
93
122
  describe('duration', () => {
94
123
  it('sets media source duration after sourceopen', async () => {
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=TextTrack.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TextTrack.test.d.ts","sourceRoot":"","sources":["../../../../../test/unit/text/TextTrack.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,12 @@
1
+ /*
2
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */
5
+ import { expectTypeStrictlyEquals } from '@amazon/vinyl-util/browserTestUtil';
6
+ describe('ALL_TEXT_TRACK_EVENTS', () => {
7
+ it('provides a comprehensive list of all text track events', () => {
8
+ // The player redispatches exactly these; an omission silently stops an
9
+ // event reaching consumers, and `satisfies` alone does not catch it.
10
+ expectTypeStrictlyEquals(true);
11
+ });
12
+ });
@@ -42,6 +42,19 @@ describe('discoverDashTextTracks', () => {
42
42
  expect(result.length).toBe(1);
43
43
  expect(result[0].language).toBe('es');
44
44
  });
45
+ it('discovers a text AdaptationSet by its Representation mimeType', () => {
46
+ // DASH allows @mimeType on the Representation instead of the set.
47
+ const m = manifest(`
48
+ <AdaptationSet lang="fr">
49
+ <Representation id="fr-sub" mimeType="text/vtt" bandwidth="100">
50
+ <BaseURL>fr.vtt</BaseURL>
51
+ </Representation>
52
+ </AdaptationSet>`);
53
+ const result = discoverDashTextTracks(m, baseUrl);
54
+ expect(result.length).toBe(1);
55
+ expect(result[0].language).toBe('fr');
56
+ expect(result[0].uri).toBe('https://example.com/dash/fr.vtt');
57
+ });
45
58
  it('classifies kind=captions when role=caption is set', () => {
46
59
  const m = manifest(`
47
60
  <AdaptationSet contentType="text" lang="en" mimeType="text/vtt">
@@ -96,6 +109,10 @@ describe('discoverDashTextTracks', () => {
96
109
  </AdaptationSet>`);
97
110
  expect(discoverDashTextTracks(m, baseUrl)).toEqual([]);
98
111
  });
112
+ it('skips a non-text AdaptationSet with no Representation', () => {
113
+ const m = manifest(`<AdaptationSet contentType="audio"/>`);
114
+ expect(discoverDashTextTracks(m, baseUrl)).toEqual([]);
115
+ });
99
116
  it('skips text AdaptationSets carrying segmented codecs (stpp/wvtt)', () => {
100
117
  const m = manifest(`
101
118
  <AdaptationSet contentType="text" mimeType="application/mp4" codecs="stpp">
@@ -382,6 +382,32 @@ hi`;
382
382
  expect(cues.length).toBe(1);
383
383
  expect(cues[0].text).toBe('hi');
384
384
  });
385
+ it('parses a cue that follows the signature with no blank line', () => {
386
+ // The header block ends at a timing line as well as at a blank line
387
+ // (WebVTT file parsing breaks out of the header loop on `-->`), so a
388
+ // document omitting the blank line still yields its cues.
389
+ const text = `WEBVTT
390
+ 00:00:01.000 --> 00:00:02.000
391
+ hi
392
+
393
+ 00:00:03.000 --> 00:00:04.000
394
+ there`;
395
+ const cues = parseWebVtt(text).cues;
396
+ expect(cues.length).toBe(2);
397
+ expect(cues[0].startTime).toBe(1);
398
+ expect(cues[0].text).toBe('hi');
399
+ expect(cues[1].text).toBe('there');
400
+ });
401
+ it('keeps header lines as header when a cue follows with no blank line', () => {
402
+ const text = `WEBVTT
403
+ Kind: captions
404
+ 00:00:01.000 --> 00:00:02.000
405
+ hi`;
406
+ const cues = parseWebVtt(text).cues;
407
+ expect(cues.length).toBe(1);
408
+ expect(cues[0].id).toBeNull();
409
+ expect(cues[0].text).toBe('hi');
410
+ });
385
411
  it('handles trailing identifier without timing line', () => {
386
412
  // Identifier with no following timing line - cue is dropped, parser
387
413
  // breaks out cleanly without throwing.
@@ -597,49 +597,6 @@ describe('TrackControllerImpl', () => {
597
597
  expect(track.clearPrefetch).toHaveBeenCalledTimes(1);
598
598
  }
599
599
  });
600
- it('also clears prefetch on preloaded ad tracks', async () => {
601
- pending('REVIEW: the refactor no longer proactively preloads ad tracks ' +
602
- 'discovered on the current track (ad tracks are created on ' +
603
- 'adEntered only). Decide: intended removal (delete this spec) ' +
604
- 'or regression (restore discovery-time ad preloading).');
605
- const [main] = createLoadOptionsList(1);
606
- trackController.load(main);
607
- const track = trackController.activeTrack;
608
- const ads = {
609
- trackUri: main.uri,
610
- adBreaks: [
611
- {
612
- id: 'b1',
613
- startTime: 5,
614
- duration: 10,
615
- placement: 'midroll',
616
- restrict: {},
617
- once: false,
618
- resumeOffset: null,
619
- playoutLimit: null,
620
- resolutionTimeOffset: null,
621
- skipControl: () => null,
622
- ads: () => Promise.resolve([
623
- {
624
- id: 'a1',
625
- startTime: 5,
626
- duration: 10,
627
- uri: 'https://ads/a.m3u8',
628
- },
629
- ]),
630
- },
631
- ],
632
- };
633
- track.ads = ads;
634
- track.dispatch('adsChange', { previous: null, current: ads });
635
- // Ad resolution runs on microtasks.
636
- await Promise.resolve();
637
- await Promise.resolve();
638
- await Promise.resolve();
639
- const adTrack = trackController.getCachedTrack('https://ads/a.m3u8');
640
- trackController.clearPrefetch();
641
- expect(adTrack.clearPrefetch).toHaveBeenCalled();
642
- });
643
600
  });
644
601
  describe('clearQueue', () => {
645
602
  it('clears the queue without unloading the current track', async () => {
@@ -1124,6 +1081,21 @@ describe('TrackControllerImpl', () => {
1124
1081
  expect(adTrack).withContext('midroll ad track warmed').toBeDefined();
1125
1082
  expect(adTrack.preload).toHaveBeenCalled();
1126
1083
  });
1084
+ it('clears prefetch on a preloaded ad track', async () => {
1085
+ const [main] = createLoadOptionsList(1);
1086
+ factoryGivingBreak(main.uri, []); // records created tracks; no preroll
1087
+ trackController.load(main);
1088
+ await flushAds();
1089
+ deps.adController.dispatch('adPreload', {
1090
+ adBreak: midrollBreak('https://ads/mid.m3u8'),
1091
+ });
1092
+ await flushAds();
1093
+ const adTrack = created.get('https://ads/mid.m3u8');
1094
+ // Ad tracks are not in the content cache, so this only holds if
1095
+ // clearPrefetch reaches the per-parent ad track store too.
1096
+ trackController.clearPrefetch();
1097
+ expect(adTrack.clearPrefetch).toHaveBeenCalledTimes(1);
1098
+ });
1127
1099
  it('ignores adPreload when there is no parent track', () => {
1128
1100
  expect(() => deps.adController.dispatch('adPreload', {
1129
1101
  adBreak: midrollBreak('https://ads/mid.m3u8'),
@@ -1307,23 +1279,6 @@ describe('TrackControllerImpl', () => {
1307
1279
  const track = trackController.activeTrack;
1308
1280
  expect(track.activate).toHaveBeenCalledWith(objectContaining({ startTime: 3 }));
1309
1281
  });
1310
- it('skips the deferred resume if interrupted before the frame', async () => {
1311
- pending('REVIEW: content resume on adBreakCompleted is now synchronous ' +
1312
- '(no deferred/interruptible frame), so this interruption ' +
1313
- 'guard no longer applies. Decide: intended or restore deferral.');
1314
- const [main] = createLoadOptionsList(1);
1315
- trackController.load(main);
1316
- const changeSpy = createEventSpy(trackController, 'trackActivated');
1317
- deps.adController.dispatch('adBreakCompleted', {
1318
- adBreak: adBreak('midroll'),
1319
- resumePosition: 5,
1320
- });
1321
- // Interrupt: a new ad becomes current before the deferred resume runs.
1322
- deps.adController.currentAd = { ...ad, id: 'other' };
1323
- await clock.tick();
1324
- // The deferred setQueue was skipped; no track change occurred.
1325
- expect(changeSpy).not.toHaveBeenCalled();
1326
- });
1327
1282
  it('advances to the next track after a postroll ad when one exists', async () => {
1328
1283
  const list = createLoadOptionsList(2);
1329
1284
  trackController.load(...list);
@@ -542,6 +542,28 @@ describe('buildHlsMediaTimeline', () => {
542
542
  expect(initCall[1]?.headers).toEqual(jasmine.objectContaining({ Range: 'bytes=0-499' }));
543
543
  fetchSpy.and.callThrough();
544
544
  });
545
+ it('resolves segment and map URIs against the media playlist baseUrl', async () => {
546
+ const variant = createVariant('v1.m3u8', 128000);
547
+ const playlist = {
548
+ ...createMediaPlaylist([10]),
549
+ // The media playlist was redirected away from the main playlist's
550
+ // directory.
551
+ baseUrl: 'https://redirect.example.net/hls/v1.m3u8',
552
+ };
553
+ const manifestData = createManifestData([variant], playlist);
554
+ const fetchSpy = spyOn(globalThis, 'fetch').and.callFake(() => Promise.resolve(new Response(new ArrayBuffer(100))));
555
+ const timeline = buildHlsMediaTimeline(deps, manifestData);
556
+ const quality = timeline.periods[0].qualities[0];
557
+ const segment = await quality.getSegment(5);
558
+ await segment.initData();
559
+ await segment.data();
560
+ const urls = fetchSpy.calls.allArgs().map(([input]) => String(input));
561
+ expect(urls).toEqual([
562
+ 'https://redirect.example.net/hls/init.mp4',
563
+ 'https://redirect.example.net/hls/seg0.m4s',
564
+ ]);
565
+ fetchSpy.and.callThrough();
566
+ });
545
567
  it('getDuration throws when no variants', async () => {
546
568
  const manifestData = createManifestData([], createMediaPlaylist([]));
547
569
  const timeline = buildHlsMediaTimeline(deps, manifestData);
@@ -113,6 +113,29 @@ describe('fetchMediaPlaylist', () => {
113
113
  expect(playlist.segments.length).toBe(1);
114
114
  expect(String(mockRequester.request.calls.argsFor(0)[0])).toBe('https://example.com/path/audio.m3u8');
115
115
  });
116
+ it('sets the baseUrl from the response URL', async () => {
117
+ mockRequester.request.and.callFake(() => {
118
+ const resp = new Response(mediaM3u8);
119
+ Object.defineProperty(resp, 'url', {
120
+ value: 'https://redirected.com/hls/audio.m3u8',
121
+ });
122
+ return Promise.resolve(resp);
123
+ });
124
+ const playlist = await fetchMediaPlaylist({
125
+ uri: 'audio.m3u8',
126
+ baseUrl: 'https://example.com/path/main.m3u8',
127
+ defines: undefined,
128
+ });
129
+ expect(playlist.baseUrl).toBe('https://redirected.com/hls/audio.m3u8');
130
+ });
131
+ it('falls back to the requested URL when the response has no URL', async () => {
132
+ const playlist = await fetchMediaPlaylist({
133
+ uri: 'audio.m3u8',
134
+ baseUrl: 'https://example.com/path/main.m3u8',
135
+ defines: undefined,
136
+ });
137
+ expect(playlist.baseUrl).toBe('https://example.com/path/audio.m3u8');
138
+ });
116
139
  it('resolves EXT-X-DEFINE:QUERYPARAM from the playlist URL query string', async () => {
117
140
  mockRequester.request.and.callFake(() => Promise.resolve(new Response([
118
141
  '#EXTM3U',