rx-player 3.30.0-dev.2023020100 → 3.30.0-dev.2023030200

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 (183) hide show
  1. package/.eslintrc.js +8 -0
  2. package/CHANGELOG.md +5 -1
  3. package/VERSION +1 -1
  4. package/dist/_esm5.processed/compat/browser_detection.d.ts +23 -12
  5. package/dist/_esm5.processed/compat/browser_detection.js +80 -38
  6. package/dist/_esm5.processed/compat/can_reuse_media_keys.js +2 -2
  7. package/dist/_esm5.processed/compat/eme/close_session.js +2 -2
  8. package/dist/_esm5.processed/compat/event_listeners.js +1 -1
  9. package/dist/_esm5.processed/config.d.ts +2 -0
  10. package/dist/_esm5.processed/core/adaptive/adaptive_representation_selector.js +4 -2
  11. package/dist/_esm5.processed/core/api/debug/buffer_graph.d.ts +28 -0
  12. package/dist/_esm5.processed/core/api/debug/buffer_graph.js +175 -0
  13. package/dist/_esm5.processed/core/api/debug/buffer_size_graph.d.ts +10 -0
  14. package/dist/_esm5.processed/core/api/debug/buffer_size_graph.js +104 -0
  15. package/dist/_esm5.processed/core/api/debug/constants.d.ts +2 -0
  16. package/dist/_esm5.processed/core/api/debug/constants.js +2 -0
  17. package/dist/_esm5.processed/core/api/debug/index.d.ts +2 -0
  18. package/dist/_esm5.processed/core/api/debug/index.js +2 -0
  19. package/dist/_esm5.processed/core/api/debug/modules/general_info.d.ts +3 -0
  20. package/dist/_esm5.processed/core/api/debug/modules/general_info.js +199 -0
  21. package/dist/_esm5.processed/core/api/debug/modules/segment_buffer_content.d.ts +4 -0
  22. package/dist/_esm5.processed/core/api/debug/modules/segment_buffer_content.js +121 -0
  23. package/dist/_esm5.processed/core/api/debug/modules/segment_buffer_size.d.ts +3 -0
  24. package/dist/_esm5.processed/core/api/debug/modules/segment_buffer_size.js +35 -0
  25. package/dist/_esm5.processed/core/api/debug/render.d.ts +3 -0
  26. package/dist/_esm5.processed/core/api/debug/render.js +32 -0
  27. package/dist/_esm5.processed/core/api/debug/utils.d.ts +39 -0
  28. package/dist/_esm5.processed/core/api/debug/utils.js +57 -0
  29. package/dist/_esm5.processed/core/api/playback_observer.js +3 -2
  30. package/dist/_esm5.processed/core/api/public_api.d.ts +3 -0
  31. package/dist/_esm5.processed/core/api/public_api.js +25 -14
  32. package/dist/_esm5.processed/core/api/utils.js +3 -3
  33. package/dist/_esm5.processed/core/decrypt/__tests__/__global__/utils.d.ts +32 -13
  34. package/dist/_esm5.processed/core/decrypt/__tests__/__global__/utils.js +28 -7
  35. package/dist/_esm5.processed/core/decrypt/attach_media_keys.js +1 -1
  36. package/dist/_esm5.processed/core/decrypt/content_decryptor.js +1 -1
  37. package/dist/_esm5.processed/core/decrypt/find_key_system.js +33 -24
  38. package/dist/_esm5.processed/core/decrypt/session_events_listener.js +54 -50
  39. package/dist/_esm5.processed/core/decrypt/utils/check_key_statuses.js +4 -0
  40. package/dist/_esm5.processed/core/fetchers/cdn_prioritizer.d.ts +17 -8
  41. package/dist/_esm5.processed/core/fetchers/cdn_prioritizer.js +10 -6
  42. package/dist/_esm5.processed/core/fetchers/manifest/manifest_fetcher.js +5 -4
  43. package/dist/_esm5.processed/core/fetchers/segment/segment_fetcher.d.ts +22 -5
  44. package/dist/_esm5.processed/core/fetchers/segment/segment_fetcher.js +37 -21
  45. package/dist/_esm5.processed/core/fetchers/segment/task_prioritizer.js +21 -23
  46. package/dist/_esm5.processed/core/fetchers/utils/schedule_request.js +17 -7
  47. package/dist/_esm5.processed/core/init/directfile_content_initializer.js +1 -1
  48. package/dist/_esm5.processed/core/init/media_source_content_initializer.js +27 -31
  49. package/dist/_esm5.processed/core/init/utils/content_time_boundaries_observer.js +2 -2
  50. package/dist/_esm5.processed/core/init/utils/create_media_source.js +3 -12
  51. package/dist/_esm5.processed/core/init/utils/end_of_stream.js +6 -3
  52. package/dist/_esm5.processed/core/init/utils/get_loaded_reference.js +2 -1
  53. package/dist/_esm5.processed/core/init/utils/initial_seek_and_play.js +9 -5
  54. package/dist/_esm5.processed/core/init/utils/initialize_content_decryption.js +2 -1
  55. package/dist/_esm5.processed/core/init/utils/media_duration_updater.js +23 -19
  56. package/dist/_esm5.processed/core/init/utils/rebuffering_controller.js +1 -1
  57. package/dist/_esm5.processed/core/init/utils/stream_events_emitter/stream_events_emitter.js +6 -4
  58. package/dist/_esm5.processed/core/init/utils/throw_on_media_error.js +1 -1
  59. package/dist/_esm5.processed/core/segment_buffers/implementations/audio_video/audio_video_segment_buffer.js +7 -10
  60. package/dist/_esm5.processed/core/segment_buffers/implementations/text/html/html_text_segment_buffer.js +4 -2
  61. package/dist/_esm5.processed/core/segment_buffers/segment_buffers_store.js +13 -9
  62. package/dist/_esm5.processed/core/stream/adaptation/adaptation_stream.js +25 -16
  63. package/dist/_esm5.processed/core/stream/orchestrator/stream_orchestrator.js +26 -12
  64. package/dist/_esm5.processed/core/stream/period/period_stream.js +11 -10
  65. package/dist/_esm5.processed/core/stream/representation/representation_stream.js +15 -15
  66. package/dist/_esm5.processed/core/stream/representation/utils/append_segment_to_buffer.js +1 -1
  67. package/dist/_esm5.processed/core/stream/representation/utils/downloading_queue.js +16 -6
  68. package/dist/_esm5.processed/default_config.d.ts +16 -0
  69. package/dist/_esm5.processed/default_config.js +19 -0
  70. package/dist/_esm5.processed/experimental/features/debug_element.d.ts +8 -0
  71. package/dist/_esm5.processed/experimental/features/debug_element.js +10 -0
  72. package/dist/_esm5.processed/experimental/features/index.d.ts +1 -0
  73. package/dist/_esm5.processed/experimental/features/index.js +1 -0
  74. package/dist/_esm5.processed/experimental/tools/VideoThumbnailLoader/prepare_source_buffer.js +7 -4
  75. package/dist/_esm5.processed/experimental/tools/VideoThumbnailLoader/video_thumbnail_loader.js +8 -4
  76. package/dist/_esm5.processed/features/features_object.js +1 -0
  77. package/dist/_esm5.processed/features/initialize_features.js +13 -10
  78. package/dist/_esm5.processed/features/types.d.ts +3 -0
  79. package/dist/_esm5.processed/manifest/adaptation.js +4 -0
  80. package/dist/_esm5.processed/manifest/manifest.js +2 -0
  81. package/dist/_esm5.processed/manifest/representation.js +11 -4
  82. package/dist/_esm5.processed/parsers/manifest/dash/common/parse_adaptation_sets.js +105 -137
  83. package/dist/_esm5.processed/parsers/manifest/dash/common/parse_representations.js +25 -5
  84. package/dist/_esm5.processed/public_types.d.ts +1 -0
  85. package/dist/_esm5.processed/transports/dash/add_segment_integrity_checks_to_loader.js +15 -11
  86. package/dist/_esm5.processed/transports/dash/low_latency_segment_loader.js +2 -2
  87. package/dist/_esm5.processed/transports/dash/manifest_parser.js +1 -1
  88. package/dist/_esm5.processed/transports/dash/segment_loader.js +4 -4
  89. package/dist/_esm5.processed/transports/local/segment_loader.js +13 -26
  90. package/dist/_esm5.processed/transports/smooth/segment_loader.js +4 -4
  91. package/dist/_esm5.processed/transports/utils/call_custom_manifest_loader.js +3 -3
  92. package/dist/_esm5.processed/utils/cancellable_sleep.js +4 -10
  93. package/dist/_esm5.processed/utils/create_cancellable_promise.d.ts +26 -0
  94. package/dist/_esm5.processed/utils/create_cancellable_promise.js +52 -0
  95. package/dist/_esm5.processed/utils/reference.js +6 -0
  96. package/dist/_esm5.processed/utils/request/xhr.js +1 -1
  97. package/dist/_esm5.processed/utils/task_canceller.d.ts +34 -15
  98. package/dist/_esm5.processed/utils/task_canceller.js +55 -22
  99. package/dist/rx-player.js +880 -677
  100. package/dist/rx-player.min.js +1 -1
  101. package/jest.config.js +1 -0
  102. package/package.json +19 -18
  103. package/scripts/build/constants.d.ts +1 -0
  104. package/scripts/report_build_sizes +4 -0
  105. package/sonar-project.properties +1 -1
  106. package/src/compat/browser_detection.ts +99 -52
  107. package/src/compat/can_reuse_media_keys.ts +5 -2
  108. package/src/compat/eme/close_session.ts +2 -2
  109. package/src/compat/event_listeners.ts +1 -1
  110. package/src/core/adaptive/adaptive_representation_selector.ts +4 -2
  111. package/src/core/api/debug/buffer_graph.ts +247 -0
  112. package/src/core/api/debug/buffer_size_graph.ts +130 -0
  113. package/src/core/api/debug/constants.ts +2 -0
  114. package/src/core/api/debug/index.ts +3 -0
  115. package/src/core/api/debug/modules/general_info.ts +204 -0
  116. package/src/core/api/debug/modules/segment_buffer_content.ts +155 -0
  117. package/src/core/api/debug/modules/segment_buffer_size.ts +48 -0
  118. package/src/core/api/debug/render.ts +40 -0
  119. package/src/core/api/debug/utils.ts +103 -0
  120. package/src/core/api/playback_observer.ts +4 -2
  121. package/src/core/api/public_api.ts +28 -14
  122. package/src/core/api/utils.ts +3 -3
  123. package/src/core/decrypt/__tests__/__global__/utils.ts +61 -40
  124. package/src/core/decrypt/attach_media_keys.ts +1 -1
  125. package/src/core/decrypt/content_decryptor.ts +1 -1
  126. package/src/core/decrypt/find_key_system.ts +36 -35
  127. package/src/core/decrypt/session_events_listener.ts +57 -56
  128. package/src/core/decrypt/utils/check_key_statuses.ts +6 -0
  129. package/src/core/fetchers/cdn_prioritizer.ts +18 -9
  130. package/src/core/fetchers/manifest/manifest_fetcher.ts +5 -4
  131. package/src/core/fetchers/segment/segment_fetcher.ts +36 -14
  132. package/src/core/fetchers/segment/task_prioritizer.ts +25 -30
  133. package/src/core/fetchers/utils/schedule_request.ts +18 -7
  134. package/src/core/init/directfile_content_initializer.ts +1 -1
  135. package/src/core/init/media_source_content_initializer.ts +37 -41
  136. package/src/core/init/utils/content_time_boundaries_observer.ts +2 -2
  137. package/src/core/init/utils/create_media_source.ts +4 -16
  138. package/src/core/init/utils/end_of_stream.ts +6 -3
  139. package/src/core/init/utils/get_loaded_reference.ts +2 -1
  140. package/src/core/init/utils/initial_seek_and_play.ts +9 -5
  141. package/src/core/init/utils/initialize_content_decryption.ts +2 -1
  142. package/src/core/init/utils/media_duration_updater.ts +25 -20
  143. package/src/core/init/utils/rebuffering_controller.ts +1 -1
  144. package/src/core/init/utils/stream_events_emitter/stream_events_emitter.ts +6 -4
  145. package/src/core/init/utils/throw_on_media_error.ts +1 -1
  146. package/src/core/segment_buffers/implementations/audio_video/audio_video_segment_buffer.ts +7 -11
  147. package/src/core/segment_buffers/implementations/text/html/html_text_segment_buffer.ts +4 -2
  148. package/src/core/segment_buffers/segment_buffers_store.ts +16 -13
  149. package/src/core/stream/adaptation/adaptation_stream.ts +28 -19
  150. package/src/core/stream/orchestrator/stream_orchestrator.ts +26 -12
  151. package/src/core/stream/period/period_stream.ts +11 -10
  152. package/src/core/stream/representation/representation_stream.ts +15 -15
  153. package/src/core/stream/representation/utils/append_segment_to_buffer.ts +1 -1
  154. package/src/core/stream/representation/utils/downloading_queue.ts +16 -4
  155. package/src/default_config.ts +30 -9
  156. package/src/experimental/features/__tests__/debug_element.test.ts +26 -0
  157. package/src/experimental/features/debug_element.ts +13 -0
  158. package/src/experimental/features/index.ts +1 -0
  159. package/src/experimental/tools/VideoThumbnailLoader/prepare_source_buffer.ts +7 -4
  160. package/src/experimental/tools/VideoThumbnailLoader/video_thumbnail_loader.ts +8 -4
  161. package/src/features/__tests__/initialize_features.test.ts +11 -0
  162. package/src/features/features_object.ts +1 -0
  163. package/src/features/initialize_features.ts +15 -10
  164. package/src/features/types.ts +9 -0
  165. package/src/manifest/adaptation.ts +7 -0
  166. package/src/manifest/manifest.ts +4 -0
  167. package/src/manifest/representation.ts +10 -4
  168. package/src/parsers/manifest/dash/common/parse_adaptation_sets.ts +116 -151
  169. package/src/parsers/manifest/dash/common/parse_representations.ts +21 -4
  170. package/src/public_types.ts +1 -0
  171. package/src/transports/dash/add_segment_integrity_checks_to_loader.ts +31 -22
  172. package/src/transports/dash/low_latency_segment_loader.ts +2 -2
  173. package/src/transports/dash/manifest_parser.ts +1 -1
  174. package/src/transports/dash/segment_loader.ts +4 -4
  175. package/src/transports/local/segment_loader.ts +14 -30
  176. package/src/transports/smooth/segment_loader.ts +4 -4
  177. package/src/transports/utils/call_custom_manifest_loader.ts +3 -3
  178. package/src/typings/globals.d.ts +2 -0
  179. package/src/utils/cancellable_sleep.ts +5 -14
  180. package/src/utils/create_cancellable_promise.ts +69 -0
  181. package/src/utils/reference.ts +6 -0
  182. package/src/utils/request/xhr.ts +1 -1
  183. package/src/utils/task_canceller.ts +63 -34
@@ -62,7 +62,7 @@ export default function callCustomManifestLoader(
62
62
  receivingTime? : number | undefined;
63
63
  sendingTime? : number | undefined; }) =>
64
64
  {
65
- if (hasFinished || cancelSignal.isCancelled) {
65
+ if (hasFinished || cancelSignal.isCancelled()) {
66
66
  return;
67
67
  }
68
68
  hasFinished = true;
@@ -87,7 +87,7 @@ export default function callCustomManifestLoader(
87
87
  * @param {*} err - The corresponding error encountered
88
88
  */
89
89
  const reject = (err : unknown) : void => {
90
- if (hasFinished || cancelSignal.isCancelled) {
90
+ if (hasFinished || cancelSignal.isCancelled()) {
91
91
  return;
92
92
  }
93
93
  hasFinished = true;
@@ -113,7 +113,7 @@ export default function callCustomManifestLoader(
113
113
  * the "regular" implementation
114
114
  */
115
115
  const fallback = () => {
116
- if (hasFinished || cancelSignal.isCancelled) {
116
+ if (hasFinished || cancelSignal.isCancelled()) {
117
117
  return;
118
118
  }
119
119
  hasFinished = true;
@@ -33,6 +33,7 @@ declare const __FEATURES__ : {
33
33
  HTML_VTT : number;
34
34
  LOCAL_MANIFEST : number;
35
35
  METAPLAYLIST : number;
36
+ DEBUG_ELEMENT : number;
36
37
  NATIVE_SAMI : number;
37
38
  NATIVE_SRT : number;
38
39
  NATIVE_TTML : number;
@@ -54,6 +55,7 @@ declare const enum FEATURES_ENUM {
54
55
  HTML_VTT,
55
56
  LOCAL_MANIFEST,
56
57
  METAPLAYLIST,
58
+ DEBUG_ELEMENT,
57
59
  NATIVE_SAMI,
58
60
  NATIVE_SRT,
59
61
  NATIVE_TTML,
@@ -14,10 +14,8 @@
14
14
  * limitations under the License.
15
15
  */
16
16
 
17
- import {
18
- CancellationError,
19
- CancellationSignal,
20
- } from "./task_canceller";
17
+ import createCancellablePromise from "./create_cancellable_promise";
18
+ import { CancellationSignal } from "./task_canceller";
21
19
 
22
20
  /**
23
21
  * Wait the given `delay`, resolving the Promise when finished.
@@ -36,15 +34,8 @@ export default function cancellableSleep(
36
34
  delay: number,
37
35
  cancellationSignal: CancellationSignal
38
36
  ) : Promise<void> {
39
- return new Promise((res, rej) => {
40
- const timeout = setTimeout(() => {
41
- unregisterCancelSignal();
42
- res();
43
- }, delay);
44
- const unregisterCancelSignal = cancellationSignal
45
- .register(function onCancel(cancellationError : CancellationError) {
46
- clearTimeout(timeout);
47
- rej(cancellationError);
48
- });
37
+ return createCancellablePromise(cancellationSignal, (res) => {
38
+ const timeout = setTimeout(() => res(), delay);
39
+ return () => clearTimeout(timeout);
49
40
  });
50
41
  }
@@ -0,0 +1,69 @@
1
+ import {
2
+ CancellationError,
3
+ CancellationSignal,
4
+ } from "./task_canceller";
5
+
6
+ /**
7
+ * Returns a Promise linked to a `CancellationSignal`, which will reject the
8
+ * corresponding `CancellationError` if that signal emits before the wanted
9
+ * task finishes (either on success or on error).
10
+ *
11
+ * The given callback mimicks the Promise interface with the added possibility
12
+ * of returning a callback which will be called when and if the task is
13
+ * cancelled before being either resolved or rejected.
14
+ * In that case, that logic will be called just before the Promise is rejected
15
+ * with the corresponding `CancellationError`.
16
+ * The point of this callback is to implement aborting logic, such as for
17
+ * example aborting a request.
18
+ *
19
+ * @param {Object} cancellationSignal - The `CancellationSignal` the returned
20
+ * Promise will be linked to.
21
+ * @param {Function} cb - The function implementing the cancellable Promise. Its
22
+ * arguments follow Promise's semantics but it can also return a function which
23
+ * will be called when and if `cancellationSignal` emits before either arguments
24
+ * are called.
25
+ * @returns {Promise} - The created Promise, which will resolve when and if the
26
+ * first argument to `cb` is called first and reject either if the second
27
+ * argument to `cb` is called first or if the given `CancellationSignal` emits
28
+ * before either of the two previous conditions.
29
+ */
30
+ export default function createCancellablePromise<T>(
31
+ cancellationSignal : CancellationSignal,
32
+ cb : (
33
+ resolve : (val : T) => void,
34
+ reject : (err : unknown) => void,
35
+ ) => (() => void) | void
36
+ ) : Promise<T> {
37
+ let abortingLogic : (() => void) | void;
38
+ return new Promise((res, rej) => {
39
+ if (cancellationSignal.cancellationError !== null) {
40
+ // If the signal was already triggered before, do not even call `cb`
41
+ return rej(cancellationSignal.cancellationError);
42
+ }
43
+
44
+ let hasUnregistered = false;
45
+ abortingLogic = cb(
46
+ function onCancellablePromiseSuccess(val : T) {
47
+ cancellationSignal.deregister(onCancellablePromiseCancellation);
48
+ hasUnregistered = true;
49
+ res(val);
50
+ },
51
+ function onCancellablePromiseFailure(err : unknown) {
52
+ cancellationSignal.deregister(onCancellablePromiseCancellation);
53
+ hasUnregistered = true;
54
+ rej(err);
55
+ }
56
+ );
57
+
58
+ if (!hasUnregistered) {
59
+ cancellationSignal.register(onCancellablePromiseCancellation);
60
+ }
61
+
62
+ function onCancellablePromiseCancellation(error : CancellationError) {
63
+ if (abortingLogic !== undefined) {
64
+ abortingLogic();
65
+ }
66
+ rej(error);
67
+ }
68
+ });
69
+ }
@@ -294,6 +294,9 @@ export default function createSharedReference<T>(
294
294
  options.clearSignal.register(unlisten);
295
295
 
296
296
  function unlisten() : void {
297
+ if (options?.clearSignal !== undefined) {
298
+ options.clearSignal.deregister(unlisten);
299
+ }
297
300
  if (cbObj.hasBeenCleared) {
298
301
  return;
299
302
  }
@@ -339,6 +342,9 @@ export default function createSharedReference<T>(
339
342
  finish,
340
343
  };
341
344
  function finish() {
345
+ if (cancelSignal !== undefined) {
346
+ cancelSignal.deregister(finish);
347
+ }
342
348
  isFinished = true;
343
349
  const clonedCbs = cbs.slice();
344
350
  for (const cbObj of clonedCbs) {
@@ -125,7 +125,7 @@ export default function request<T>(
125
125
  reject(err);
126
126
  });
127
127
 
128
- if (cancelSignal.isCancelled) {
128
+ if (cancelSignal.isCancelled()) {
129
129
  return;
130
130
  }
131
131
  }
@@ -14,6 +14,7 @@
14
14
  * limitations under the License.
15
15
  */
16
16
 
17
+ import log from "../log";
17
18
  import assert from "./assert";
18
19
  import noop from "./noop";
19
20
 
@@ -120,12 +121,12 @@ export default class TaskCanceller {
120
121
  * notified that it should be aborted when this `TaskCanceller` is triggered
121
122
  * (through its `cancel` method).
122
123
  */
123
- public signal : CancellationSignal;
124
+ public readonly signal : CancellationSignal;
124
125
  /**
125
126
  * `true` if this `TaskCanceller` has already been triggered.
126
127
  * `false` otherwise.
127
128
  */
128
- public isUsed : boolean;
129
+ private _isUsed : boolean;
129
130
  /**
130
131
  * @private
131
132
  * Internal function called when the `TaskCanceller` is triggered`.
@@ -136,28 +137,43 @@ export default class TaskCanceller {
136
137
  * Creates a new `TaskCanceller`, with its own `CancellationSignal` created
137
138
  * as its `signal` provide.
138
139
  * You can then pass this property to async task you wish to be cancellable.
139
- * @param {Object|undefined} options
140
140
  */
141
- constructor(options? : {
142
- /**
143
- * If set the TaskCanceller created here will automatically be triggered
144
- * when that signal emits.
145
- */
146
- cancelOn? : CancellationSignal | undefined;
147
- } | undefined) {
141
+ constructor() {
148
142
  const [trigger, register] = createCancellationFunctions();
149
- this.isUsed = false;
143
+ this._isUsed = false;
150
144
  this._trigger = trigger;
151
145
  this.signal = new CancellationSignal(register);
146
+ }
152
147
 
153
- if (options?.cancelOn !== undefined) {
154
- const unregisterParent = options.cancelOn.register(() => {
155
- this.cancel();
156
- });
157
- this.signal.register(unregisterParent);
158
- }
148
+ /**
149
+ * Returns `true` if this `TaskCanceller` has already been triggered.
150
+ * `false` otherwise.
151
+ */
152
+ public isUsed() : boolean {
153
+ return this._isUsed;
159
154
  }
160
155
 
156
+ /**
157
+ * Bind this `TaskCanceller` to a `CancellationSignal`, so the former
158
+ * is automatically cancelled when the latter is triggered.
159
+ *
160
+ * Note that this call registers a callback on the given signal, until either
161
+ * the current `TaskCanceller` is cancelled or until this given
162
+ * `CancellationSignal` is triggered.
163
+ * To avoid leaking memory, the returned callback allow to undo this link.
164
+ * It should be called if/when that link is not needed anymore, such as when
165
+ * there is no need for this `TaskCanceller` anymore.
166
+ *
167
+ * @param {Object} signal
168
+ * @returns {Function}
169
+ */
170
+ public linkToSignal(signal : CancellationSignal) : () => void {
171
+ const unregister = signal.register(() => {
172
+ this.cancel();
173
+ });
174
+ this.signal.register(unregister);
175
+ return unregister;
176
+ }
161
177
 
162
178
  /**
163
179
  * "Trigger" the `TaskCanceller`, notify through its associated
@@ -171,10 +187,10 @@ export default class TaskCanceller {
171
187
  * @param {Error} [srcError]
172
188
  */
173
189
  public cancel(srcError? : CancellationError) : void {
174
- if (this.isUsed) {
190
+ if (this._isUsed) {
175
191
  return ;
176
192
  }
177
- this.isUsed = true;
193
+ this._isUsed = true;
178
194
  const cancellationError = srcError ?? new CancellationError();
179
195
  this._trigger(cancellationError);
180
196
  }
@@ -196,11 +212,6 @@ export default class TaskCanceller {
196
212
  * @class
197
213
  */
198
214
  export class CancellationSignal {
199
- /**
200
- * True when the cancellation order was already triggered, meaning that the
201
- * linked task needs to be aborted.
202
- */
203
- public isCancelled : boolean;
204
215
  /**
205
216
  * Error associated to the cancellation, only set if the `CancellationSignal`
206
217
  * has been used (which means that the task has been cancelled).
@@ -220,6 +231,12 @@ export class CancellationSignal {
220
231
  */
221
232
  private _listeners : Array<(error : CancellationError) => void>;
222
233
 
234
+ /**
235
+ * True when the cancellation order was already triggered, meaning that the
236
+ * linked task needs to be aborted.
237
+ */
238
+ private _isCancelled : boolean;
239
+
223
240
  /**
224
241
  * Creates a new CancellationSignal.
225
242
  * /!\ Note: Only a `TaskCanceller` is supposed to be able to create one.
@@ -227,20 +244,35 @@ export class CancellationSignal {
227
244
  * cancelled.
228
245
  */
229
246
  constructor(registerToSource : (listener: ICancellationListener) => void) {
230
- this.isCancelled = false;
247
+ this._isCancelled = false;
231
248
  this.cancellationError = null;
232
249
  this._listeners = [];
233
250
 
234
251
  registerToSource((cancellationError : CancellationError) : void => {
235
252
  this.cancellationError = cancellationError;
236
- this.isCancelled = true;
253
+ this._isCancelled = true;
237
254
  while (this._listeners.length > 0) {
238
- const listener = this._listeners.splice(this._listeners.length - 1, 1)[0];
239
- listener(cancellationError);
255
+ try {
256
+ const listener = this._listeners.pop();
257
+ listener?.(cancellationError);
258
+ } catch (err) {
259
+ log.error("Error while calling clean up listener",
260
+ err instanceof Error ? err.toString() :
261
+ "Unknown error");
262
+ }
240
263
  }
241
264
  });
242
265
  }
243
266
 
267
+ /**
268
+ * Returns `true` when the cancellation order was already triggered, meaning
269
+ * that the linked task needs to be aborted.
270
+ * @returns boolean
271
+ */
272
+ public isCancelled() : boolean {
273
+ return this._isCancelled;
274
+ }
275
+
244
276
  /**
245
277
  * Registers a function that will be called when/if the current task is
246
278
  * cancelled.
@@ -263,9 +295,10 @@ export class CancellationSignal {
263
295
  * performed.
264
296
  */
265
297
  public register(fn : ICancellationListener) : () => void {
266
- if (this.isCancelled) {
298
+ if (this._isCancelled) {
267
299
  assert(this.cancellationError !== null);
268
300
  fn(this.cancellationError);
301
+ return noop;
269
302
  }
270
303
  this._listeners.push(fn);
271
304
  return () => this.deregister(fn);
@@ -280,13 +313,9 @@ export class CancellationSignal {
280
313
  * @param {Function} fn
281
314
  */
282
315
  public deregister(fn : ICancellationListener) : void {
283
- if (this.isCancelled) {
284
- return;
285
- }
286
- for (let i = 0; i < this._listeners.length; i++) {
316
+ for (let i = this._listeners.length - 1; i >= 0; i--) {
287
317
  if (this._listeners[i] === fn) {
288
318
  this._listeners.splice(i, 1);
289
- return;
290
319
  }
291
320
  }
292
321
  }