rx-player 3.28.0-dev.2022061700 → 3.28.0-dev.2022062700

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 (49) hide show
  1. package/CHANGELOG.md +5 -3
  2. package/VERSION +1 -1
  3. package/appveyor.yml +1 -1
  4. package/dist/_esm5.processed/core/adaptive/adaptive_representation_selector.d.ts +32 -11
  5. package/dist/_esm5.processed/core/adaptive/adaptive_representation_selector.js +19 -26
  6. package/dist/_esm5.processed/core/api/playback_observer.d.ts +47 -35
  7. package/dist/_esm5.processed/core/api/playback_observer.js +120 -117
  8. package/dist/_esm5.processed/core/api/public_api.d.ts +4 -6
  9. package/dist/_esm5.processed/core/api/public_api.js +18 -18
  10. package/dist/_esm5.processed/core/decrypt/content_decryptor.js +60 -31
  11. package/dist/_esm5.processed/core/init/content_time_boundaries_observer.js +1 -1
  12. package/dist/_esm5.processed/core/init/create_stream_playback_observer.d.ts +1 -1
  13. package/dist/_esm5.processed/core/init/create_stream_playback_observer.js +23 -6
  14. package/dist/_esm5.processed/core/init/initial_seek_and_play.js +3 -3
  15. package/dist/_esm5.processed/core/init/initialize_directfile.js +1 -1
  16. package/dist/_esm5.processed/core/init/load_on_media_source.js +1 -1
  17. package/dist/_esm5.processed/core/init/stall_avoider.js +12 -8
  18. package/dist/_esm5.processed/core/stream/adaptation/create_representation_estimator.js +1 -1
  19. package/dist/_esm5.processed/core/stream/orchestrator/stream_orchestrator.js +5 -4
  20. package/dist/_esm5.processed/core/stream/period/create_empty_adaptation_stream.js +1 -1
  21. package/dist/_esm5.processed/core/stream/period/period_stream.js +21 -5
  22. package/dist/_esm5.processed/core/stream/reload_after_switch.js +1 -1
  23. package/dist/_esm5.processed/core/stream/representation/append_segment_to_buffer.js +1 -1
  24. package/dist/_esm5.processed/core/stream/representation/representation_stream.js +1 -1
  25. package/dist/_esm5.processed/utils/reference.d.ts +29 -19
  26. package/dist/_esm5.processed/utils/reference.js +21 -5
  27. package/dist/rx-player.js +366 -257
  28. package/dist/rx-player.min.js +1 -1
  29. package/package.json +2 -2
  30. package/sonar-project.properties +1 -1
  31. package/src/README.md +84 -68
  32. package/src/core/adaptive/adaptive_representation_selector.ts +47 -40
  33. package/src/core/api/playback_observer.ts +185 -173
  34. package/src/core/api/public_api.ts +23 -21
  35. package/src/core/decrypt/content_decryptor.ts +57 -23
  36. package/src/core/init/content_time_boundaries_observer.ts +1 -1
  37. package/src/core/init/create_stream_playback_observer.ts +69 -47
  38. package/src/core/init/initial_seek_and_play.ts +3 -3
  39. package/src/core/init/initialize_directfile.ts +1 -1
  40. package/src/core/init/load_on_media_source.ts +1 -1
  41. package/src/core/init/stall_avoider.ts +12 -9
  42. package/src/core/stream/adaptation/create_representation_estimator.ts +6 -6
  43. package/src/core/stream/orchestrator/stream_orchestrator.ts +5 -4
  44. package/src/core/stream/period/create_empty_adaptation_stream.ts +1 -1
  45. package/src/core/stream/period/period_stream.ts +33 -14
  46. package/src/core/stream/reload_after_switch.ts +1 -1
  47. package/src/core/stream/representation/append_segment_to_buffer.ts +1 -1
  48. package/src/core/stream/representation/representation_stream.ts +1 -1
  49. package/src/utils/reference.ts +40 -28
@@ -13,19 +13,33 @@
13
13
  * See the License for the specific language governing permissions and
14
14
  * limitations under the License.
15
15
  */
16
- import { combineLatest as observableCombineLatest, map, } from "rxjs";
16
+ import createSharedReference from "../../utils/reference";
17
17
  /**
18
18
  * Create PlaybackObserver for the `Stream` part of the code.
19
19
  * @param {Object} manifest
20
20
  * @param {Object} playbackObserver
21
21
  * @param {Object} args
22
- * @returns {Observable}
22
+ * @returns {Object}
23
23
  */
24
24
  export default function createStreamPlaybackObserver(manifest, playbackObserver, _a) {
25
25
  var autoPlay = _a.autoPlay, initialPlayPerformed = _a.initialPlayPerformed, initialSeekPerformed = _a.initialSeekPerformed, speed = _a.speed, startTime = _a.startTime;
26
- return playbackObserver.deriveReadOnlyObserver(function mapObservable(observation$) {
27
- return observableCombineLatest([observation$, speed.asObservable()]).pipe(map(function (_a) {
28
- var observation = _a[0], lastSpeed = _a[1];
26
+ return playbackObserver.deriveReadOnlyObserver(function transform(observationRef, cancellationSignal) {
27
+ var newRef = createSharedReference(constructStreamPlaybackObservation());
28
+ speed.onUpdate(emitStreamPlaybackObservation, {
29
+ clearSignal: cancellationSignal,
30
+ emitCurrentValue: false,
31
+ });
32
+ observationRef.onUpdate(emitStreamPlaybackObservation, {
33
+ clearSignal: cancellationSignal,
34
+ emitCurrentValue: false,
35
+ });
36
+ cancellationSignal.register(function () {
37
+ newRef.finish();
38
+ });
39
+ return newRef;
40
+ function constructStreamPlaybackObservation() {
41
+ var observation = observationRef.getValue();
42
+ var lastSpeed = speed.getValue();
29
43
  var pendingPosition;
30
44
  if (!initialSeekPerformed.getValue()) {
31
45
  pendingPosition = startTime;
@@ -61,6 +75,9 @@ export default function createStreamPlaybackObserver(manifest, playbackObserver,
61
75
  readyState: observation.readyState,
62
76
  speed: lastSpeed,
63
77
  };
64
- }));
78
+ }
79
+ function emitStreamPlaybackObservation() {
80
+ newRef.setValue(constructStreamPlaybackObservation());
81
+ }
65
82
  });
66
83
  }
@@ -39,7 +39,7 @@ export function waitUntilPlayable(observation$) {
39
39
  }
40
40
  /**
41
41
  * Try to play content then handle autoplay errors.
42
- * @param {HTMLMediaElement} - mediaElement
42
+ * @param {HTMLMediaElement} mediaElement
43
43
  * @returns {Observable}
44
44
  */
45
45
  function autoPlay(mediaElement) {
@@ -75,12 +75,12 @@ export default function initialSeekAndPlay(_a) {
75
75
  }), shareReplay({ refCount: true }));
76
76
  var seekAndPlay$ = seek$.pipe(mergeMap(function () {
77
77
  if (!shouldValidateMetadata() || mediaElement.duration > 0) {
78
- return waitUntilPlayable(playbackObserver.observe(true));
78
+ return waitUntilPlayable(playbackObserver.getReference().asObservable());
79
79
  }
80
80
  else {
81
81
  var error = new MediaError("MEDIA_ERR_NOT_LOADED_METADATA", "Cannot load automatically: your browser " +
82
82
  "falsely announced having loaded the content.");
83
- return waitUntilPlayable(playbackObserver.observe(true))
83
+ return waitUntilPlayable(playbackObserver.getReference().asObservable())
84
84
  .pipe(startWith(EVENTS.warning(error)));
85
85
  }
86
86
  }), mergeMap(function (evt) {
@@ -99,7 +99,7 @@ export default function initializeDirectfileContent(_a) {
99
99
  // Translate errors coming from the media element into RxPlayer errors
100
100
  // through a throwing Observable.
101
101
  var mediaError$ = throwOnMediaError(mediaElement);
102
- var observation$ = playbackObserver.observe(true);
102
+ var observation$ = playbackObserver.getReference().asObservable();
103
103
  // Set the speed set by the user on the media element while pausing a
104
104
  // little longer while the buffer is empty.
105
105
  var playbackRate$ = updatePlaybackRate(mediaElement, speed, observation$)
@@ -54,7 +54,7 @@ export default function createMediaSourceLoader(_a) {
54
54
  var segmentBuffersStore = new SegmentBuffersStore(mediaElement, mediaSource);
55
55
  var _b = initialSeekAndPlay({ mediaElement: mediaElement, playbackObserver: playbackObserver, startTime: initialTime,
56
56
  mustAutoPlay: autoPlay }), seekAndPlay$ = _b.seekAndPlay$, initialPlayPerformed = _b.initialPlayPerformed, initialSeekPerformed = _b.initialSeekPerformed;
57
- var observation$ = playbackObserver.observe(true);
57
+ var observation$ = playbackObserver.getReference().asObservable();
58
58
  var streamEvents$ = initialPlayPerformed.asObservable().pipe(filter(function (hasPlayed) { return hasPlayed; }), mergeMap(function () { return streamEventsEmitter(manifest, mediaElement, observation$); }));
59
59
  var streamObserver = createStreamPlaybackObserver(manifest, playbackObserver, { autoPlay: autoPlay, initialPlayPerformed: initialPlayPerformed, initialSeekPerformed: initialSeekPerformed, speed: speed, startTime: initialTime });
60
60
  /** Cancel endOfStream calls when streams become active again. */
@@ -42,7 +42,7 @@ export default function StallAvoider(playbackObserver, manifest, lockedStream$,
42
42
  * Emit every known audio and video buffer discontinuities in chronological
43
43
  * order (first ordered by Period's start, then by bufferType in any order.
44
44
  */
45
- var discontinuitiesStore$ = discontinuityUpdate$.pipe(withLatestFrom(playbackObserver.observe(true)), scan(function (discontinuitiesStore, _a) {
45
+ var discontinuitiesStore$ = discontinuityUpdate$.pipe(withLatestFrom(playbackObserver.getReference().asObservable()), scan(function (discontinuitiesStore, _a) {
46
46
  var evt = _a[0], observation = _a[1];
47
47
  return updateDiscontinuitiesStore(discontinuitiesStore, evt, observation);
48
48
  }, initialDiscontinuitiesStore));
@@ -76,7 +76,7 @@ export default function StallAvoider(playbackObserver, manifest, lockedStream$,
76
76
  * If we're rebuffering waiting on data of a "locked stream", seek into the
77
77
  * Period handled by that stream to unlock the situation.
78
78
  */
79
- var unlock$ = lockedStream$.pipe(withLatestFrom(playbackObserver.observe(true)), tap(function (_a) {
79
+ var unlock$ = lockedStream$.pipe(withLatestFrom(playbackObserver.getReference().asObservable()), tap(function (_a) {
80
80
  var _b;
81
81
  var lockedStreamEvt = _a[0], observation = _a[1];
82
82
  // TODO(PaulB) also skip when the user's wanted speed is set to `0`, as we
@@ -102,7 +102,7 @@ export default function StallAvoider(playbackObserver, manifest, lockedStream$,
102
102
  // This is why we're disabling the eslint rule.
103
103
  /* eslint-disable-next-line @typescript-eslint/no-unsafe-argument */
104
104
  ignoreElements());
105
- var stall$ = playbackObserver.observe(true).pipe(withLatestFrom(discontinuitiesStore$), map(function (_a) {
105
+ var stall$ = playbackObserver.getReference().asObservable().pipe(withLatestFrom(discontinuitiesStore$), map(function (_a) {
106
106
  var observation = _a[0], discontinuitiesStore = _a[1];
107
107
  var buffered = observation.buffered, position = observation.position, readyState = observation.readyState, rebuffering = observation.rebuffering, freezing = observation.freezing;
108
108
  var _b = config.getCurrent(), BUFFER_DISCONTINUITY_THRESHOLD = _b.BUFFER_DISCONTINUITY_THRESHOLD, FORCE_DISCONTINUITY_SEEK_DELAY = _b.FORCE_DISCONTINUITY_SEEK_DELAY, FREEZING_STALLED_DELAY = _b.FREEZING_STALLED_DELAY, UNFREEZING_SEEK_DELAY = _b.UNFREEZING_SEEK_DELAY, UNFREEZING_DELTA_POSITION = _b.UNFREEZING_DELTA_POSITION;
@@ -155,11 +155,15 @@ export default function StallAvoider(playbackObserver, manifest, lockedStream$,
155
155
  if (ignoredStallTimeStamp === null) {
156
156
  ignoredStallTimeStamp = now;
157
157
  }
158
- if (isSeekingApproximate &&
159
- observation.position < lastSeekingPosition &&
160
- now - ignoredStallTimeStamp < FORCE_DISCONTINUITY_SEEK_DELAY) {
161
- return { type: "stalled",
162
- value: stalledReason };
158
+ if (isSeekingApproximate && observation.position < lastSeekingPosition) {
159
+ log.debug("Init: the device appeared to have seeked back by itself.");
160
+ if (now - ignoredStallTimeStamp < FORCE_DISCONTINUITY_SEEK_DELAY) {
161
+ return { type: "stalled",
162
+ value: stalledReason };
163
+ }
164
+ else {
165
+ log.warn("Init: ignored stall for too long, checking discontinuity", now - ignoredStallTimeStamp);
166
+ }
163
167
  }
164
168
  lastSeekingPosition = null;
165
169
  }
@@ -39,7 +39,7 @@ export default function getRepresentationEstimate(content, representationEstimat
39
39
  updateRepresentationsReference();
40
40
  manifest.addEventListener("decipherabilityUpdate", updateRepresentationsReference);
41
41
  var unregisterCleanUp = cancellationSignal.register(cleanUp);
42
- var _a = representationEstimator(content, currentRepresentation, representations, playbackObserver, cancellationSignal), estimateRef = _a[0], abrCallbacks = _a[1];
42
+ var _a = representationEstimator(content, currentRepresentation, representations, playbackObserver, cancellationSignal), estimateRef = _a.estimates, abrCallbacks = _a.callbacks;
43
43
  return { abrCallbacks: abrCallbacks, estimateRef: estimateRef };
44
44
  function updateRepresentationsReference() {
45
45
  /** Representations for which a `RepresentationStream` can be created. */
@@ -79,7 +79,7 @@ export default function StreamOrchestrator(content, playbackObserver, representa
79
79
  Infinity;
80
80
  return BufferGarbageCollector({
81
81
  segmentBuffer: segmentBuffer,
82
- currentTime$: playbackObserver.observe(true)
82
+ currentTime$: playbackObserver.getReference().asObservable()
83
83
  .pipe(map(function (o) { var _a; return (_a = o.position.pending) !== null && _a !== void 0 ? _a : o.position.last; })),
84
84
  maxBufferBehind$: maxBufferBehind.asObservable().pipe(map(function (val) { return Math.min(val, defaultMaxBehind); })),
85
85
  maxBufferAhead$: maxBufferAhead.asObservable().pipe(map(function (val) { return Math.min(val, defaultMaxAhead); })),
@@ -175,7 +175,8 @@ export default function StreamOrchestrator(content, playbackObserver, representa
175
175
  }
176
176
  // Restart the current Stream when the wanted time is in another period
177
177
  // than the ones already considered
178
- var restartStreamsWhenOutOfBounds$ = playbackObserver.observe(true).pipe(filterMap(function (_a) {
178
+ var observation$ = playbackObserver.getReference().asObservable();
179
+ var restartStreamsWhenOutOfBounds$ = observation$.pipe(filterMap(function (_a) {
179
180
  var _b, _c;
180
181
  var position = _a.position;
181
182
  var time = (_b = position.pending) !== null && _b !== void 0 ? _b : position.last;
@@ -228,7 +229,7 @@ export default function StreamOrchestrator(content, playbackObserver, representa
228
229
  // to reduce the risk of race conditions where the next observation
229
230
  // was going to be emitted synchronously.
230
231
  nextTickObs().pipe(ignoreElements()),
231
- playbackObserver.observe(true).pipe(take(1), mergeMap(function (observation) {
232
+ playbackObserver.getReference().asObservable().pipe(take(1), mergeMap(function (observation) {
232
233
  var _a;
233
234
  var shouldAutoPlay = !((_a = observation.paused.pending) !== null && _a !== void 0 ? _a : playbackObserver.getIsPaused());
234
235
  return observableConcat(observableOf(EVENTS.needsDecipherabilityFlush(observation.position.last, shouldAutoPlay, observation.duration)), observableDefer(function () {
@@ -279,7 +280,7 @@ export default function StreamOrchestrator(content, playbackObserver, representa
279
280
  // created.
280
281
  var destroyNextStreams$ = new Subject();
281
282
  // Emits when the current position goes over the end of the current Stream.
282
- var endOfCurrentStream$ = playbackObserver.observe(true)
283
+ var endOfCurrentStream$ = playbackObserver.getReference().asObservable()
283
284
  .pipe(filter(function (_a) {
284
285
  var _b;
285
286
  var position = _a.position;
@@ -30,7 +30,7 @@ export default function createEmptyAdaptationStream(playbackObserver, wantedBuff
30
30
  var period = content.period;
31
31
  var hasFinishedLoading = false;
32
32
  var wantedBufferAhead$ = wantedBufferAhead.asObservable();
33
- var observation$ = playbackObserver.observe(true);
33
+ var observation$ = playbackObserver.getReference().asObservable();
34
34
  return observableCombineLatest([observation$,
35
35
  wantedBufferAhead$]).pipe(mergeMap(function (_a) {
36
36
  var observation = _a[0], wba = _a[1];
@@ -19,6 +19,7 @@ import { formatError, MediaError, } from "../../../errors";
19
19
  import log from "../../../log";
20
20
  import objectAssign from "../../../utils/object_assign";
21
21
  import { getLeftSizeOfRange } from "../../../utils/ranges";
22
+ import createSharedReference from "../../../utils/reference";
22
23
  import SegmentBuffersStore from "../../segment_buffers";
23
24
  import AdaptationStream from "../adaptation";
24
25
  import EVENTS from "../events_generators";
@@ -181,9 +182,24 @@ function getFirstDeclaredMimeType(adaptation) {
181
182
  * @returns {Object}
182
183
  */
183
184
  function createAdaptationStreamPlaybackObserver(initialPlaybackObserver, segmentBuffer) {
184
- return initialPlaybackObserver.deriveReadOnlyObserver(function (observation$) { return observation$.pipe(map(mapObservation)); }, mapObservation);
185
- function mapObservation(baseObservation) {
186
- var buffered = segmentBuffer.getBufferedRanges();
187
- return objectAssign({}, baseObservation, { bufferGap: getLeftSizeOfRange(buffered, baseObservation.position.last) });
188
- }
185
+ return initialPlaybackObserver.deriveReadOnlyObserver(function transform(observationRef, cancellationSignal) {
186
+ var newRef = createSharedReference(constructAdaptationStreamPlaybackObservation());
187
+ observationRef.onUpdate(emitAdaptationStreamPlaybackObservation, {
188
+ clearSignal: cancellationSignal,
189
+ emitCurrentValue: false,
190
+ });
191
+ cancellationSignal.register(function () {
192
+ newRef.finish();
193
+ });
194
+ return newRef;
195
+ function constructAdaptationStreamPlaybackObservation() {
196
+ var baseObservation = observationRef.getValue();
197
+ var buffered = segmentBuffer.getBufferedRanges();
198
+ var bufferGap = getLeftSizeOfRange(buffered, baseObservation.position.last);
199
+ return objectAssign({}, baseObservation, { bufferGap: bufferGap });
200
+ }
201
+ function emitAdaptationStreamPlaybackObservation() {
202
+ newRef.setValue(constructAdaptationStreamPlaybackObservation());
203
+ }
204
+ });
189
205
  }
@@ -44,7 +44,7 @@ export default function reloadAfterSwitch(period, bufferType, playbackObserver,
44
44
  // is actually received.
45
45
  // It can happen when `reloadAfterSwitch` is called as a side-effect of the
46
46
  // same event that triggers the playback observation to be emitted.
47
- return nextTickObs().pipe(mergeMap(function () { return playbackObserver.observe(true); }), map(function (observation) {
47
+ return nextTickObs().pipe(mergeMap(function () { return playbackObserver.getReference().asObservable(); }), map(function (observation) {
48
48
  var _a, _b;
49
49
  var currentTime = playbackObserver.getCurrentTime();
50
50
  var pos = currentTime + deltaPos;
@@ -38,7 +38,7 @@ export default function appendSegmentToBuffer(playbackObserver, segmentBuffer, d
38
38
  "An unknown error happened when pushing content";
39
39
  throw new MediaError("BUFFER_APPEND_ERROR", reason);
40
40
  }
41
- return playbackObserver.observe(true).pipe(take(1), mergeMap(function (observation) {
41
+ return playbackObserver.getReference().asObservable().pipe(take(1), mergeMap(function (observation) {
42
42
  var _a;
43
43
  var currentPos = (_a = observation.position.pending) !== null && _a !== void 0 ? _a : observation.position.last;
44
44
  return observableConcat(forceGarbageCollection(currentPos, segmentBuffer).pipe(ignoreElements()), append$).pipe(catchError(function (forcedGCError) {
@@ -97,7 +97,7 @@ export default function RepresentationStream(_a) {
97
97
  .pipe(mergeMap(onQueueEvent));
98
98
  /** Observable emitting the stream "status" and filling `lastSegmentQueue`. */
99
99
  var status$ = observableCombineLatest([
100
- playbackObserver.observe(true),
100
+ playbackObserver.getReference().asObservable(),
101
101
  bufferGoal$,
102
102
  maxBufferSize$,
103
103
  terminate$.pipe(take(1), startWith(null)),
@@ -52,10 +52,24 @@ import { CancellationSignal } from "./task_canceller";
52
52
  * those use cases makes the intent of the corresponding code clearer.
53
53
  */
54
54
  export interface ISharedReference<T> {
55
- /** Get the last set value for this shared reference. */
55
+ /**
56
+ * Get the last set value for this shared reference.
57
+ * @returns {*}
58
+ */
56
59
  getValue(): T;
57
- /** Update the value of this shared reference. */
60
+ /**
61
+ * Update the value of this shared reference.
62
+ * @param {*} newVal
63
+ */
58
64
  setValue(newVal: T): void;
65
+ /**
66
+ * Update the value of this shared reference only if the value changed.
67
+ *
68
+ * Note that this function only performs a strict equality reference through
69
+ * the "===" operator. Different objects that are structurally the same will
70
+ * thus be considered different.
71
+ * @param {*} newVal
72
+ */
59
73
  setValueIfChanged(newVal: T): void;
60
74
  /**
61
75
  * Returns an Observable which synchronously emits the current value (unless
@@ -65,21 +79,6 @@ export interface ISharedReference<T> {
65
79
  * @returns {Observable}
66
80
  */
67
81
  asObservable(skipCurrentValue?: boolean): Observable<T>;
68
- /**
69
- * Triggers a callback each time this reference's value is updated.
70
- *
71
- * Can be given several options as argument:
72
- * - clearSignal: When the attach `CancellationSignal` emits, the given
73
- * callback will not be called anymore on reference updates.
74
- * - emitCurrentValue: If `true`, the callback will be called directly and
75
- * synchronously on this call with its current value.
76
- * @param {Function} cb
77
- * @param {Object} [options]
78
- */
79
- onUpdate(cb: (val: T) => void, options?: {
80
- clearSignal?: CancellationSignal;
81
- emitCurrentValue?: boolean;
82
- }): void;
83
82
  /**
84
83
  * Allows to register a callback to be called each time the value inside the
85
84
  * reference is updated.
@@ -92,8 +91,8 @@ export interface ISharedReference<T> {
92
91
  * also be immediately called with the current value.
93
92
  */
94
93
  onUpdate(cb: (val: T) => void, options?: {
95
- clearSignal?: CancellationSignal;
96
- emitCurrentValue?: boolean;
94
+ clearSignal?: CancellationSignal | undefined;
95
+ emitCurrentValue?: boolean | undefined;
97
96
  }): void;
98
97
  /**
99
98
  * Indicate that no new values will be emitted.
@@ -160,5 +159,16 @@ export interface IReadOnlySharedReference<T> {
160
159
  * @returns {Observable}
161
160
  */
162
161
  export declare function createSharedReference<T>(initialValue: T): ISharedReference<T>;
162
+ /**
163
+ * Create a new `ISharedReference` based on another one by mapping over its
164
+ * referenced value each time it is updated.
165
+ * @param {Object} originalRef - The Original `ISharedReference` you wish to map
166
+ * over.
167
+ * @param {Function} mappingFn - The mapping function which will receives
168
+ * `originalRef`'s value and outputs this new reference's value.
169
+ * @param {Object | undefined} [cancellationSignal] - Optionally, a
170
+ * `CancellationSignal` which will finish that reference when it emits.
171
+ * @returns {Object} - The new, mapped, reference.
172
+ */
163
173
  export declare function createMappedReference<T, U>(originalRef: IReadOnlySharedReference<T>, mappingFn: (x: T) => U, cancellationSignal?: CancellationSignal): IReadOnlySharedReference<U>;
164
174
  export default createSharedReference;
@@ -53,16 +53,15 @@ export function createSharedReference(initialValue) {
53
53
  },
54
54
  /**
55
55
  * Update the value of this shared reference.
56
- * @param {*}
56
+ * @param {*} newVal
57
57
  */
58
58
  setValue: function (newVal) {
59
59
  if (isFinished) {
60
60
  if (0 /* __ENVIRONMENT__.CURRENT_ENV */ === 1 /* __ENVIRONMENT__.DEV */) {
61
- throw new Error("Finished shared references cannot be updated");
62
- }
63
- else {
64
- return;
61
+ /* eslint-disable-next-line no-console */
62
+ console.error("Finished shared references cannot be updated");
65
63
  }
64
+ return;
66
65
  }
67
66
  value = newVal;
68
67
  if (cbs.length === 0) {
@@ -81,6 +80,10 @@ export function createSharedReference(initialValue) {
81
80
  }
82
81
  }
83
82
  },
83
+ /**
84
+ * Update the value of this shared reference only if it changed.
85
+ * @param {*} newVal
86
+ */
84
87
  setValueIfChanged: function (newVal) {
85
88
  if (newVal !== value) {
86
89
  this.setValue(newVal);
@@ -173,14 +176,27 @@ export function createSharedReference(initialValue) {
173
176
  if (!cbObj.hasBeenCleared) {
174
177
  cbObj.complete();
175
178
  }
179
+ cbObj.hasBeenCleared = true;
176
180
  }
177
181
  catch (_) {
178
182
  /* nothing */
179
183
  }
180
184
  }
185
+ cbs.length = 0;
181
186
  },
182
187
  };
183
188
  }
189
+ /**
190
+ * Create a new `ISharedReference` based on another one by mapping over its
191
+ * referenced value each time it is updated.
192
+ * @param {Object} originalRef - The Original `ISharedReference` you wish to map
193
+ * over.
194
+ * @param {Function} mappingFn - The mapping function which will receives
195
+ * `originalRef`'s value and outputs this new reference's value.
196
+ * @param {Object | undefined} [cancellationSignal] - Optionally, a
197
+ * `CancellationSignal` which will finish that reference when it emits.
198
+ * @returns {Object} - The new, mapped, reference.
199
+ */
184
200
  export function createMappedReference(originalRef, mappingFn, cancellationSignal) {
185
201
  var newRef = createSharedReference(mappingFn(originalRef.getValue()));
186
202
  originalRef.onUpdate(function mapOriginalReference(x) {