rx-player 4.5.0-dev.2026012302 → 4.5.0-dev.2026021900

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 (108) hide show
  1. package/CHANGELOG.md +9 -1
  2. package/VERSION +1 -1
  3. package/dist/commonjs/__GENERATED_CODE/embedded_dash_wasm.d.ts.map +1 -1
  4. package/dist/commonjs/__GENERATED_CODE/embedded_dash_wasm.js +1 -1
  5. package/dist/commonjs/__GENERATED_CODE/embedded_worker.d.ts.map +1 -1
  6. package/dist/commonjs/__GENERATED_CODE/embedded_worker.js +1 -1
  7. package/dist/commonjs/compat/should_seek_at_zero.d.ts +12 -0
  8. package/dist/commonjs/compat/should_seek_at_zero.d.ts.map +1 -0
  9. package/dist/commonjs/compat/should_seek_at_zero.js +23 -0
  10. package/dist/commonjs/core/entry/FreezeResolver.js +2 -2
  11. package/dist/commonjs/core/entry/content_time_boundaries_observer.d.ts.map +1 -1
  12. package/dist/commonjs/core/entry/content_time_boundaries_observer.js +8 -0
  13. package/dist/commonjs/core/stream/representation/encryption_data_notifier.d.ts +70 -0
  14. package/dist/commonjs/core/stream/representation/encryption_data_notifier.d.ts.map +1 -0
  15. package/dist/commonjs/core/stream/representation/encryption_data_notifier.js +107 -0
  16. package/dist/commonjs/core/stream/representation/representation_stream.d.ts.map +1 -1
  17. package/dist/commonjs/core/stream/representation/representation_stream.js +12 -60
  18. package/dist/commonjs/core/stream/representation/utils/get_needed_segments.js +1 -1
  19. package/dist/commonjs/default_config.d.ts +5 -0
  20. package/dist/commonjs/default_config.d.ts.map +1 -1
  21. package/dist/commonjs/default_config.js +5 -0
  22. package/dist/commonjs/main_thread/api/public_api.d.ts.map +1 -1
  23. package/dist/commonjs/main_thread/api/public_api.js +27 -3
  24. package/dist/commonjs/main_thread/init/directfile_content_initializer.d.ts.map +1 -1
  25. package/dist/commonjs/main_thread/init/directfile_content_initializer.js +23 -1
  26. package/dist/commonjs/main_thread/init/utils/initial_seek_and_play.d.ts.map +1 -1
  27. package/dist/commonjs/main_thread/init/utils/initial_seek_and_play.js +3 -1
  28. package/dist/commonjs/manifest/classes/index.d.ts +2 -1
  29. package/dist/commonjs/manifest/classes/index.d.ts.map +1 -1
  30. package/dist/commonjs/manifest/classes/representation.d.ts +1 -1
  31. package/dist/commonjs/manifest/classes/representation.d.ts.map +1 -1
  32. package/dist/commonjs/manifest/classes/representation.js +2 -2
  33. package/dist/commonjs/manifest/classes/representation_index/types.d.ts +2 -2
  34. package/dist/commonjs/utils/base64.d.ts +15 -1
  35. package/dist/commonjs/utils/base64.d.ts.map +1 -1
  36. package/dist/commonjs/utils/base64.js +6 -0
  37. package/dist/commonjs/utils/ranges.d.ts +1 -1
  38. package/dist/commonjs/utils/ranges.js +1 -1
  39. package/dist/es2017/__GENERATED_CODE/embedded_dash_wasm.d.ts.map +1 -1
  40. package/dist/es2017/__GENERATED_CODE/embedded_dash_wasm.js +1 -1
  41. package/dist/es2017/__GENERATED_CODE/embedded_worker.d.ts.map +1 -1
  42. package/dist/es2017/__GENERATED_CODE/embedded_worker.js +1 -1
  43. package/dist/es2017/compat/should_seek_at_zero.d.ts +12 -0
  44. package/dist/es2017/compat/should_seek_at_zero.d.ts.map +1 -0
  45. package/dist/es2017/compat/should_seek_at_zero.js +20 -0
  46. package/dist/es2017/core/entry/FreezeResolver.js +1 -1
  47. package/dist/es2017/core/entry/content_time_boundaries_observer.d.ts.map +1 -1
  48. package/dist/es2017/core/entry/content_time_boundaries_observer.js +8 -0
  49. package/dist/es2017/core/stream/representation/encryption_data_notifier.d.ts +70 -0
  50. package/dist/es2017/core/stream/representation/encryption_data_notifier.d.ts.map +1 -0
  51. package/dist/es2017/core/stream/representation/encryption_data_notifier.js +80 -0
  52. package/dist/es2017/core/stream/representation/representation_stream.d.ts.map +1 -1
  53. package/dist/es2017/core/stream/representation/representation_stream.js +10 -38
  54. package/dist/es2017/core/stream/representation/utils/get_needed_segments.js +1 -1
  55. package/dist/es2017/default_config.d.ts +5 -0
  56. package/dist/es2017/default_config.d.ts.map +1 -1
  57. package/dist/es2017/default_config.js +5 -0
  58. package/dist/es2017/main_thread/api/public_api.d.ts.map +1 -1
  59. package/dist/es2017/main_thread/api/public_api.js +27 -3
  60. package/dist/es2017/main_thread/init/directfile_content_initializer.d.ts.map +1 -1
  61. package/dist/es2017/main_thread/init/directfile_content_initializer.js +23 -1
  62. package/dist/es2017/main_thread/init/utils/initial_seek_and_play.d.ts.map +1 -1
  63. package/dist/es2017/main_thread/init/utils/initial_seek_and_play.js +3 -1
  64. package/dist/es2017/manifest/classes/index.d.ts +2 -1
  65. package/dist/es2017/manifest/classes/index.d.ts.map +1 -1
  66. package/dist/es2017/manifest/classes/representation.d.ts +1 -1
  67. package/dist/es2017/manifest/classes/representation.d.ts.map +1 -1
  68. package/dist/es2017/manifest/classes/representation.js +1 -1
  69. package/dist/es2017/manifest/classes/representation_index/types.d.ts +2 -2
  70. package/dist/es2017/utils/base64.d.ts +15 -1
  71. package/dist/es2017/utils/base64.d.ts.map +1 -1
  72. package/dist/es2017/utils/base64.js +6 -0
  73. package/dist/es2017/utils/ranges.d.ts +1 -1
  74. package/dist/es2017/utils/ranges.js +1 -1
  75. package/dist/mpd-parser.wasm +0 -0
  76. package/dist/worker.js +6 -6
  77. package/package.json +9 -3
  78. package/src/__GENERATED_CODE/embedded_dash_wasm.ts +1 -1
  79. package/src/__GENERATED_CODE/embedded_worker.ts +1 -1
  80. package/src/compat/should_seek_at_zero.ts +23 -0
  81. package/src/core/adaptive/__tests__/guess_based_chooser.test.ts +790 -0
  82. package/src/core/adaptive/__tests__/network_analyzer.test.ts +514 -0
  83. package/src/core/adaptive/utils/__tests__/pending_requests_store.test.ts +285 -0
  84. package/src/core/adaptive/utils/__tests__/representation_score_calculator.test.ts +247 -0
  85. package/src/core/entry/FreezeResolver.ts +1 -1
  86. package/src/core/entry/__tests__/FreezeResolver.test.ts +542 -0
  87. package/src/core/entry/__tests__/content_time_boundaries_observer.test.ts +868 -0
  88. package/src/core/entry/content_time_boundaries_observer.ts +10 -0
  89. package/src/core/stream/adaptation/__tests__/get_representations_switch_strategy.test.ts +592 -0
  90. package/src/core/stream/period/utils/__tests__/get_adaptation_switch_strategy.test.ts +646 -0
  91. package/src/core/stream/representation/__tests__/encryption_data_notifier.test.ts +531 -0
  92. package/src/core/stream/representation/encryption_data_notifier.ts +122 -0
  93. package/src/core/stream/representation/representation_stream.ts +11 -49
  94. package/src/core/stream/representation/utils/__tests__/append_segment_to_buffer.test.ts +321 -0
  95. package/src/core/stream/representation/utils/__tests__/check_for_discontinuity.test.ts +513 -0
  96. package/src/core/stream/representation/utils/__tests__/get_segment_priority.test.ts +132 -0
  97. package/src/core/stream/representation/utils/__tests__/push_init_segment.test.ts +209 -0
  98. package/src/core/stream/representation/utils/__tests__/push_media_segment.test.ts +343 -0
  99. package/src/core/stream/representation/utils/get_needed_segments.ts +1 -1
  100. package/src/default_config.ts +6 -0
  101. package/src/main_thread/api/public_api.ts +32 -3
  102. package/src/main_thread/init/directfile_content_initializer.ts +26 -1
  103. package/src/main_thread/init/utils/initial_seek_and_play.ts +5 -1
  104. package/src/manifest/classes/index.ts +2 -0
  105. package/src/manifest/classes/representation.ts +2 -1
  106. package/src/manifest/classes/representation_index/types.ts +2 -2
  107. package/src/utils/base64.ts +30 -1
  108. package/src/utils/ranges.ts +1 -1
@@ -33,6 +33,7 @@ import type {
33
33
  IParsedInitSegmentPayload,
34
34
  IParsedSegmentPayload,
35
35
  } from "../../fetchers/segment/segment_queue";
36
+ import EncryptionDataNotifier from "./encryption_data_notifier";
36
37
  import type {
37
38
  IQueuedSegment,
38
39
  IRepresentationStreamArguments,
@@ -125,33 +126,16 @@ export default function RepresentationStream<TSegmentDataType>(
125
126
  initSegmentState.isLoaded = true;
126
127
  }
127
128
 
128
- /**
129
- * `true` if the event notifying about encryption data has already been
130
- * constructed.
131
- * Allows to avoid sending multiple times protection events.
132
- */
133
- let hasSentEncryptionData = false;
134
-
135
- // If the DRM system id is already known, and if we already have encryption data
136
- // for it, we may not need to wait until the initialization segment is loaded to
137
- // signal required protection data, thus performing License negotiations sooner
138
- if (drmSystemId !== undefined) {
139
- const encryptionData = representation.getEncryptionData(drmSystemId);
140
-
141
- // If some key ids are not known yet, it may be safer to wait for this initialization
142
- // segment to be loaded first
143
- if (
144
- encryptionData.length > 0 &&
145
- encryptionData.every((e) => e.keyIds !== undefined)
146
- ) {
147
- hasSentEncryptionData = true;
129
+ const drmNotifier = new EncryptionDataNotifier({
130
+ drmSystemId,
131
+ representation,
132
+ notify: (encryptionData) =>
148
133
  callbacks.encryptionDataEncountered(
149
134
  encryptionData.map((d) => objectAssign({ content }, d)),
150
- );
151
- if (canceller.isUsed()) {
152
- return; // previous callback has stopped everything by side-effect
153
- }
154
- }
135
+ ),
136
+ });
137
+ if (canceller.isUsed()) {
138
+ return;
155
139
  }
156
140
 
157
141
  segmentQueue.addEventListener(
@@ -260,7 +244,7 @@ export default function RepresentationStream<TSegmentDataType>(
260
244
  } else if (initSegmentState.isLoaded) {
261
245
  log.warn(
262
246
  "Stream",
263
- "Uninitialized index with an already loaded " + "initialization segment",
247
+ "Uninitialized index with an already loaded initialization segment",
264
248
  {
265
249
  bufferType,
266
250
  representationBitrate: content.representation.bitrate,
@@ -369,29 +353,7 @@ export default function RepresentationStream<TSegmentDataType>(
369
353
  | IParsedInitSegmentPayload<TSegmentDataType>
370
354
  | IParsedSegmentPayload<TSegmentDataType>,
371
355
  ): void {
372
- // Supplementary encryption information might have been parsed.
373
- for (const protInfo of evt.protectionData) {
374
- // TODO better handle use cases like key rotation by not always grouping
375
- // every protection data together? To check.
376
- representation.addProtectionData(
377
- protInfo.initDataType,
378
- protInfo.keyId,
379
- protInfo.initData,
380
- );
381
- }
382
-
383
- // Now that the initialization segment has been parsed - which may have
384
- // included encryption information - take care of the encryption event
385
- // if not already done.
386
- if (!hasSentEncryptionData) {
387
- const allEncryptionData = representation.getAllEncryptionData();
388
- if (allEncryptionData.length > 0) {
389
- callbacks.encryptionDataEncountered(
390
- allEncryptionData.map((p) => objectAssign({ content }, p)),
391
- );
392
- hasSentEncryptionData = true;
393
- }
394
- }
356
+ drmNotifier.onNewProtectionData(evt.protectionData);
395
357
 
396
358
  if (evt.segmentType === "init") {
397
359
  if (!representation.index.isInitialized() && evt.segmentList !== undefined) {
@@ -0,0 +1,321 @@
1
+ import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
2
+ import { MediaError, SourceBufferError } from "../../../../../errors";
3
+ import SharedReference from "../../../../../utils/reference";
4
+ import TaskCanceller, { CancellationError } from "../../../../../utils/task_canceller";
5
+ import appendSegmentToBuffer from "../append_segment_to_buffer";
6
+
7
+ /* eslint-disable @typescript-eslint/no-explicit-any */
8
+ /* eslint-disable @typescript-eslint/no-unsafe-member-access */
9
+ /* eslint-disable @typescript-eslint/no-unsafe-argument */
10
+
11
+ vi.mock("../../../../../log", () => ({
12
+ default: {
13
+ debug: vi.fn(),
14
+ warn: vi.fn(),
15
+ },
16
+ }));
17
+ vi.mock("../../../../../utils/sleep", () => ({
18
+ default: vi.fn(() => Promise.resolve()),
19
+ }));
20
+
21
+ describe("appendSegmentToBuffer", () => {
22
+ let mockPlaybackObserver: any;
23
+ let mockSegmentSink: any;
24
+ let mockDataInfos: any;
25
+ let mockBufferGoal: SharedReference<number>;
26
+ let mockTaskCanceller = new TaskCanceller("test canceller");
27
+
28
+ beforeEach(() => {
29
+ mockPlaybackObserver = {
30
+ getReference: vi.fn(
31
+ () =>
32
+ new SharedReference({
33
+ position: {
34
+ getWanted: () => 10,
35
+ },
36
+ }),
37
+ ),
38
+ };
39
+ mockSegmentSink = {
40
+ pushChunk: vi.fn(() => Promise.resolve([{ start: 0, end: 10 }])),
41
+ removeBuffer: vi.fn(() => Promise.resolve(undefined)),
42
+ };
43
+ mockDataInfos = {
44
+ inventoryInfos: {
45
+ adaptation: { id: "test-adaptation", type: "video", representations: [] },
46
+ },
47
+ };
48
+ mockBufferGoal = new SharedReference(30);
49
+ mockTaskCanceller.cancel("test end");
50
+ mockTaskCanceller = new TaskCanceller("test canceller");
51
+ });
52
+
53
+ afterEach(() => {
54
+ vi.clearAllMocks();
55
+ });
56
+
57
+ describe("successful append", () => {
58
+ it("should push chunk successfully on first try", async () => {
59
+ const result = await appendSegmentToBuffer(
60
+ mockPlaybackObserver,
61
+ mockSegmentSink,
62
+ mockDataInfos,
63
+ mockBufferGoal,
64
+ mockTaskCanceller.signal,
65
+ );
66
+
67
+ expect(mockSegmentSink.pushChunk).toHaveBeenCalledTimes(1);
68
+ expect(mockSegmentSink.pushChunk).toHaveBeenCalledWith(mockDataInfos);
69
+ expect(result).toEqual([{ start: 0, end: 10 }]);
70
+ });
71
+ });
72
+
73
+ describe("buffer full error handling", () => {
74
+ it("should run garbage collector and retry on buffer full error", async () => {
75
+ const bufferFullError = new SourceBufferError(
76
+ "BUFFER_FULL",
77
+ "Buffer is full",
78
+ true,
79
+ );
80
+
81
+ mockSegmentSink.pushChunk
82
+ .mockRejectedValueOnce(bufferFullError)
83
+ .mockResolvedValueOnce([{ start: 0, end: 10 }]);
84
+
85
+ const result = await appendSegmentToBuffer(
86
+ mockPlaybackObserver,
87
+ mockSegmentSink,
88
+ mockDataInfos,
89
+ mockBufferGoal,
90
+ mockTaskCanceller.signal,
91
+ );
92
+
93
+ expect(mockSegmentSink.pushChunk).toHaveBeenCalledTimes(2);
94
+ expect(mockSegmentSink.removeBuffer).toHaveBeenCalledTimes(2);
95
+ expect(result).toEqual([{ start: 0, end: 10 }]);
96
+ });
97
+
98
+ it("should remove buffer before current position (start)", async () => {
99
+ const bufferFullError = new SourceBufferError(
100
+ "BUFFER_FULL",
101
+ "Buffer is full",
102
+ true,
103
+ );
104
+
105
+ mockSegmentSink.pushChunk
106
+ .mockRejectedValueOnce(bufferFullError)
107
+ .mockResolvedValueOnce([{ start: 0, end: 10 }]);
108
+
109
+ await appendSegmentToBuffer(
110
+ mockPlaybackObserver,
111
+ mockSegmentSink,
112
+ mockDataInfos,
113
+ mockBufferGoal,
114
+ mockTaskCanceller.signal,
115
+ );
116
+
117
+ // Should remove from 0 to (currentPos - 5) = 5
118
+ expect(mockSegmentSink.removeBuffer).toHaveBeenCalledWith(0, 5);
119
+ });
120
+
121
+ it("should remove buffer after buffer goal (end)", async () => {
122
+ const bufferFullError = new SourceBufferError(
123
+ "BUFFER_FULL",
124
+ "Buffer is full",
125
+ true,
126
+ );
127
+
128
+ mockSegmentSink.pushChunk
129
+ .mockRejectedValueOnce(bufferFullError)
130
+ .mockResolvedValueOnce([{ start: 0, end: 10 }]);
131
+
132
+ mockBufferGoal.setValue(30);
133
+
134
+ await appendSegmentToBuffer(
135
+ mockPlaybackObserver,
136
+ mockSegmentSink,
137
+ mockDataInfos,
138
+ mockBufferGoal,
139
+ mockTaskCanceller.signal,
140
+ );
141
+
142
+ // Should remove from (currentPos + bufferGoal + 12) = 52 to MAX_VALUE
143
+ expect(mockSegmentSink.removeBuffer).toHaveBeenCalledWith(52, Number.MAX_VALUE);
144
+ });
145
+
146
+ it("should not remove start buffer when position is < 5", async () => {
147
+ const bufferFullError = new SourceBufferError(
148
+ "BUFFER_FULL",
149
+ "Buffer is full",
150
+ true,
151
+ );
152
+
153
+ mockSegmentSink.pushChunk
154
+ .mockRejectedValueOnce(bufferFullError)
155
+ .mockResolvedValueOnce([{ start: 0, end: 10 }]);
156
+
157
+ mockPlaybackObserver.getReference.mockReturnValue(
158
+ new SharedReference({
159
+ position: {
160
+ getWanted: vi.fn(() => 3),
161
+ },
162
+ }),
163
+ );
164
+ await appendSegmentToBuffer(
165
+ mockPlaybackObserver,
166
+ mockSegmentSink,
167
+ mockDataInfos,
168
+ mockBufferGoal,
169
+ mockTaskCanceller.signal,
170
+ );
171
+ expect(mockSegmentSink.removeBuffer).toHaveBeenCalledWith(45, Number.MAX_VALUE);
172
+
173
+ // Should only be called once for the end buffer
174
+ expect(mockSegmentSink.removeBuffer).toHaveBeenCalledTimes(1);
175
+ });
176
+
177
+ it("should throw BUFFER_FULL_ERROR if retry fails", async () => {
178
+ const bufferFullError = new SourceBufferError(
179
+ "BUFFER_FULL",
180
+ "Buffer is full",
181
+ true,
182
+ );
183
+
184
+ const retryError = new Error("Retry failed");
185
+
186
+ mockSegmentSink.pushChunk
187
+ .mockRejectedValueOnce(bufferFullError)
188
+ .mockRejectedValueOnce(retryError);
189
+
190
+ await expect(
191
+ appendSegmentToBuffer(
192
+ mockPlaybackObserver,
193
+ mockSegmentSink,
194
+ mockDataInfos,
195
+ mockBufferGoal,
196
+ mockTaskCanceller.signal,
197
+ ),
198
+ ).rejects.toThrow("BUFFER_FULL_ERROR");
199
+ });
200
+ });
201
+
202
+ describe("non-buffer-full errors", () => {
203
+ it("should throw BUFFER_APPEND_ERROR for non-buffer-full SourceBufferError", async () => {
204
+ const error = new SourceBufferError("SOME_ERROR", "Some error", false);
205
+ mockSegmentSink.pushChunk.mockRejectedValueOnce(error);
206
+ await expect(
207
+ appendSegmentToBuffer(
208
+ mockPlaybackObserver,
209
+ mockSegmentSink,
210
+ mockDataInfos,
211
+ mockBufferGoal,
212
+ mockTaskCanceller.signal,
213
+ ),
214
+ ).rejects.toThrow(
215
+ new MediaError("BUFFER_APPEND_ERROR", "SOME_ERROR: Some error", {
216
+ tracks: [
217
+ {
218
+ type: "video",
219
+ track: {
220
+ id: "test-adaptation",
221
+ representations: [],
222
+ },
223
+ },
224
+ ],
225
+ }),
226
+ );
227
+ });
228
+
229
+ it("should throw BUFFER_APPEND_ERROR for generic Error", async () => {
230
+ const error = new Error("Generic error");
231
+ mockSegmentSink.pushChunk.mockRejectedValueOnce(error);
232
+
233
+ await expect(
234
+ appendSegmentToBuffer(
235
+ mockPlaybackObserver,
236
+ mockSegmentSink,
237
+ mockDataInfos,
238
+ mockBufferGoal,
239
+ mockTaskCanceller.signal,
240
+ ),
241
+ ).rejects.toThrow(MediaError);
242
+ });
243
+
244
+ it("should throw BUFFER_APPEND_ERROR for unknown error type", async () => {
245
+ mockSegmentSink.pushChunk.mockRejectedValueOnce("string error");
246
+
247
+ await expect(
248
+ appendSegmentToBuffer(
249
+ mockPlaybackObserver,
250
+ mockSegmentSink,
251
+ mockDataInfos,
252
+ mockBufferGoal,
253
+ mockTaskCanceller.signal,
254
+ ),
255
+ ).rejects.toThrow(MediaError);
256
+ });
257
+ });
258
+
259
+ describe("cancellation handling", () => {
260
+ it("should throw CancellationError on initial pushChunk if cancelled", async () => {
261
+ const cancellationError = new CancellationError("Test", "test");
262
+ mockTaskCanceller.cancel("test cancellation");
263
+ mockSegmentSink.pushChunk.mockRejectedValueOnce(cancellationError);
264
+
265
+ await expect(
266
+ appendSegmentToBuffer(
267
+ mockPlaybackObserver,
268
+ mockSegmentSink,
269
+ mockDataInfos,
270
+ mockBufferGoal,
271
+ mockTaskCanceller.signal,
272
+ ),
273
+ ).rejects.toThrow(CancellationError);
274
+ });
275
+
276
+ it("should throw CancellationError during retry if cancelled", async () => {
277
+ const bufferFullError = new SourceBufferError(
278
+ "BUFFER_FULL",
279
+ "Buffer is full",
280
+ true,
281
+ );
282
+
283
+ mockSegmentSink.pushChunk.mockRejectedValueOnce(bufferFullError);
284
+ mockTaskCanceller.cancel("test 523");
285
+
286
+ await expect(
287
+ appendSegmentToBuffer(
288
+ mockPlaybackObserver,
289
+ mockSegmentSink,
290
+ mockDataInfos,
291
+ mockBufferGoal,
292
+ mockTaskCanceller.signal,
293
+ ),
294
+ ).rejects.toThrow(CancellationError);
295
+ });
296
+
297
+ it("should throw CancellationError if retry pushChunk is cancelled", async () => {
298
+ const bufferFullError = new SourceBufferError(
299
+ "BUFFER_FULL",
300
+ "Buffer is full",
301
+ true,
302
+ );
303
+
304
+ const cancellationError = new CancellationError("Test", "test");
305
+
306
+ mockSegmentSink.pushChunk
307
+ .mockRejectedValueOnce(bufferFullError)
308
+ .mockRejectedValueOnce(cancellationError);
309
+
310
+ await expect(
311
+ appendSegmentToBuffer(
312
+ mockPlaybackObserver,
313
+ mockSegmentSink,
314
+ mockDataInfos,
315
+ mockBufferGoal,
316
+ mockTaskCanceller.signal,
317
+ ),
318
+ ).rejects.toThrow(CancellationError);
319
+ });
320
+ });
321
+ });