synstate 6.1.1 → 6.2.1
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.
- package/README.md +2 -2
- package/dist/core/authoring.d.mts +3 -3
- package/dist/core/class/child-observable-class.d.mts +24 -25
- package/dist/core/class/child-observable-class.d.mts.map +1 -1
- package/dist/core/class/child-observable-class.mjs +41 -42
- package/dist/core/class/child-observable-class.mjs.map +1 -1
- package/dist/core/class/create-child-observable.d.mts +27 -29
- package/dist/core/class/create-child-observable.d.mts.map +1 -1
- package/dist/core/class/create-child-observable.mjs.map +1 -1
- package/dist/core/class/create-root-observable.d.mts +11 -11
- package/dist/core/class/manager-observable-class.d.mts +6 -6
- package/dist/core/class/manager-observable-class.mjs.map +1 -1
- package/dist/core/class/observable-base-class.d.mts +29 -31
- package/dist/core/class/observable-base-class.d.mts.map +1 -1
- package/dist/core/class/observable-base-class.mjs +0 -2
- package/dist/core/class/observable-base-class.mjs.map +1 -1
- package/dist/core/class/observable-node.d.mts +3 -4
- package/dist/core/class/observable-node.d.mts.map +1 -1
- package/dist/core/class/observable-node.mjs +0 -1
- package/dist/core/class/observable-node.mjs.map +1 -1
- package/dist/core/class/propagation-state.d.mts +6 -8
- package/dist/core/class/propagation-state.d.mts.map +1 -1
- package/dist/core/class/propagation-state.mjs +0 -2
- package/dist/core/class/propagation-state.mjs.map +1 -1
- package/dist/core/class/root-observable-class.d.mts +4 -4
- package/dist/core/combine/derive.d.mts +7 -8
- package/dist/core/combine/derive.d.mts.map +1 -1
- package/dist/core/combine/derive.mjs +0 -1
- package/dist/core/combine/derive.mjs.map +1 -1
- package/dist/core/combine/merge.mjs.map +1 -1
- package/dist/core/combine/zip.d.mts +3 -3
- package/dist/core/combine/zip.mjs.map +1 -1
- package/dist/core/create/counter.d.mts +3 -3
- package/dist/core/create/counter.mjs.map +1 -1
- package/dist/core/create/from-abortable-promise.mjs.map +1 -1
- package/dist/core/create/from-promise.mjs.map +1 -1
- package/dist/core/create/from-subscribable.mjs.map +1 -1
- package/dist/core/create/source.mjs.map +1 -1
- package/dist/core/create/timer.mjs.map +1 -1
- package/dist/core/operators/audit.mjs.map +1 -1
- package/dist/core/operators/debounce.mjs.map +1 -1
- package/dist/core/operators/filter.mjs.map +1 -1
- package/dist/core/operators/keep-equal-parts.d.mts +14 -15
- package/dist/core/operators/keep-equal-parts.d.mts.map +1 -1
- package/dist/core/operators/keep-equal-parts.mjs +0 -1
- package/dist/core/operators/keep-equal-parts.mjs.map +1 -1
- package/dist/core/operators/map.mjs.map +1 -1
- package/dist/core/operators/merge-map.d.mts +3 -3
- package/dist/core/operators/merge-map.mjs.map +1 -1
- package/dist/core/operators/pairwise.mjs.map +1 -1
- package/dist/core/operators/scan.mjs.map +1 -1
- package/dist/core/operators/skip-if-no-change.mjs.map +1 -1
- package/dist/core/operators/skip-until.mjs.map +1 -1
- package/dist/core/operators/skip-while.mjs.map +1 -1
- package/dist/core/operators/switch-map.mjs.map +1 -1
- package/dist/core/operators/take-until.mjs.map +1 -1
- package/dist/core/operators/take-while.mjs.map +1 -1
- package/dist/core/operators/take.mjs.map +1 -1
- package/dist/core/operators/throttle.mjs.map +1 -1
- package/dist/core/operators/with-buffered-from.mjs.map +1 -1
- package/dist/core/operators/with-current-value-from.mjs.map +1 -1
- package/dist/core/operators/with-initial-value.mjs.map +1 -1
- package/dist/core/predefined/operators/attach-index.mjs.map +1 -1
- package/dist/core/predefined/operators/map-to.d.mts +3 -4
- package/dist/core/predefined/operators/map-to.d.mts.map +1 -1
- package/dist/core/predefined/operators/map-to.mjs +0 -1
- package/dist/core/predefined/operators/map-to.mjs.map +1 -1
- package/dist/core/scope/scope.d.mts +4 -4
- package/dist/core/types/observable-family.d.mts.map +1 -1
- package/dist/core/types/observable-family.mjs.map +1 -1
- package/dist/core/types/observable.d.mts +5 -5
- package/dist/core/types/observable.mjs.map +1 -1
- package/dist/core/utils/current-scope.d.mts +6 -6
- package/dist/core/utils/id-maker.d.mts +2 -2
- package/dist/core/utils/observable-brand.d.mts +5 -5
- package/dist/utils/create-boolean-state.d.mts +2 -2
- package/dist/utils/create-reducer.d.mts +18 -18
- package/dist/utils/create-state.d.mts +2 -2
- package/dist/utils/create-state.mjs.map +1 -1
- package/dist/utils/state-source.d.mts +3 -3
- package/package.json +9 -9
- package/src/core/authoring.mts +3 -3
- package/src/core/class/child-observable-class.mts +86 -87
- package/src/core/class/circular-dependency-comparison.test.mts +2 -2
- package/src/core/class/create-child-observable.mts +27 -29
- package/src/core/class/create-root-observable.mts +11 -11
- package/src/core/class/manager-observable-class.mts +12 -12
- package/src/core/class/observable-base-class.mts +33 -35
- package/src/core/class/observable-node.mts +3 -4
- package/src/core/class/propagation-state.mts +26 -28
- package/src/core/class/remove-completed.test.mts +2 -2
- package/src/core/class/root-observable-class.mts +9 -9
- package/src/core/class/unobserved-write.test.mts +4 -4
- package/src/core/combine/derive.mts +10 -11
- package/src/core/combine/merge.mts +2 -2
- package/src/core/combine/zip.mts +7 -7
- package/src/core/create/counter.mts +5 -5
- package/src/core/create/from-abortable-promise.mts +2 -2
- package/src/core/create/from-promise.mts +2 -2
- package/src/core/create/from-subscribable.mts +2 -2
- package/src/core/create/source.mts +5 -5
- package/src/core/create/timer.mts +2 -2
- package/src/core/operators/audit.mts +2 -2
- package/src/core/operators/debounce.mts +2 -2
- package/src/core/operators/filter.mts +4 -4
- package/src/core/operators/keep-equal-parts.mts +16 -17
- package/src/core/operators/map.mts +2 -2
- package/src/core/operators/merge-map.mts +5 -5
- package/src/core/operators/pairwise.mts +4 -4
- package/src/core/operators/scan.mts +2 -2
- package/src/core/operators/skip-if-no-change.mts +4 -4
- package/src/core/operators/skip-until.mts +4 -4
- package/src/core/operators/skip-while.mts +2 -2
- package/src/core/operators/switch-map.mts +5 -5
- package/src/core/operators/take-until.mts +2 -2
- package/src/core/operators/take-while.mts +2 -2
- package/src/core/operators/take.mts +2 -2
- package/src/core/operators/throttle.mts +2 -2
- package/src/core/operators/with-buffered-from.mts +2 -2
- package/src/core/operators/with-current-value-from.mts +2 -2
- package/src/core/operators/with-initial-value.mts +2 -2
- package/src/core/predefined/operators/attach-index.mts +2 -2
- package/src/core/predefined/operators/map-to.mts +3 -4
- package/src/core/scope/scope.mts +6 -6
- package/src/core/types/observable-family.mts +4 -5
- package/src/core/types/observable.mts +7 -7
- package/src/core/utils/current-scope.mts +8 -8
- package/src/core/utils/id-maker.mts +2 -2
- package/src/core/utils/observable-brand.mts +5 -5
- package/src/utils/create-boolean-state.mts +2 -2
- package/src/utils/create-reducer.mts +18 -18
- package/src/utils/create-state.mts +4 -4
- package/src/utils/create-state.test.mts +2 -2
- package/src/utils/state-source.mts +3 -3
|
@@ -18,8 +18,8 @@ import type { UpdateToken } from '../types/index.mjs';
|
|
|
18
18
|
import type { ChildNode } from './observable-node.mjs';
|
|
19
19
|
|
|
20
20
|
/**
|
|
21
|
-
* How many updates are propagating, across every observable, and the token
|
|
22
|
-
*
|
|
21
|
+
* How many updates are propagating, across every observable, and the token of
|
|
22
|
+
* the outermost one. A write nothing observes opens none
|
|
23
23
|
* (`setNextIfUnobserved`).
|
|
24
24
|
*/
|
|
25
25
|
const mut_propagation: {
|
|
@@ -28,15 +28,14 @@ const mut_propagation: {
|
|
|
28
28
|
} = { depth: 0, outermostToken: undefined };
|
|
29
29
|
|
|
30
30
|
/**
|
|
31
|
-
* Work deferred by {@link runAfterPropagation}, run once the outermost
|
|
32
|
-
*
|
|
31
|
+
* Work deferred by {@link runAfterPropagation}, run once the outermost update
|
|
32
|
+
* has reached every descendant.
|
|
33
33
|
*/
|
|
34
34
|
const mut_afterPropagation: (() => void)[] = [];
|
|
35
35
|
|
|
36
36
|
/**
|
|
37
|
-
* Whether some observable's update is propagating right now. A root written
|
|
38
|
-
*
|
|
39
|
-
* (#2336).
|
|
37
|
+
* Whether some observable's update is propagating right now. A root written to
|
|
38
|
+
* while one is, is written to from inside a subscriber or a projection (#2336).
|
|
40
39
|
*/
|
|
41
40
|
export const isPropagating = (): boolean => mut_propagation.depth > 0;
|
|
42
41
|
|
|
@@ -71,8 +70,7 @@ export const beginPropagation = (updateToken: UpdateToken): void => {
|
|
|
71
70
|
};
|
|
72
71
|
|
|
73
72
|
/**
|
|
74
|
-
* Ends one update, and runs the deferred work once the outermost one has
|
|
75
|
-
* ended.
|
|
73
|
+
* Ends one update, and runs the deferred work once the outermost one has ended.
|
|
76
74
|
*/
|
|
77
75
|
export const endPropagation = (): void => {
|
|
78
76
|
mut_propagation.depth -= 1;
|
|
@@ -91,11 +89,11 @@ export const endPropagation = (): void => {
|
|
|
91
89
|
};
|
|
92
90
|
|
|
93
91
|
/**
|
|
94
|
-
* The buckets of this copy's open updates, one set per nesting level: a
|
|
95
|
-
*
|
|
96
|
-
*
|
|
97
|
-
* update
|
|
98
|
-
*
|
|
92
|
+
* The buckets of this copy's open updates, one set per nesting level: a bucket
|
|
93
|
+
* per depth below the node that started the update, holding the queued nodes
|
|
94
|
+
* and how many of its slots are in use. Kept from update to update, so that an
|
|
95
|
+
* update allocates nothing but its token; emptying a bucket is setting its
|
|
96
|
+
* length to 0.
|
|
99
97
|
*/
|
|
100
98
|
const mut_bucketSets: Bucket[][] = [];
|
|
101
99
|
|
|
@@ -125,9 +123,9 @@ export const openUpdate = (depth: number): UpdateToken => {
|
|
|
125
123
|
|
|
126
124
|
/**
|
|
127
125
|
* How many updates of one copy may be open at once, one inside another. An
|
|
128
|
-
* update opens inside another only when a subscriber or projection writes to
|
|
129
|
-
*
|
|
130
|
-
*
|
|
126
|
+
* update opens inside another only when a subscriber or projection writes to a
|
|
127
|
+
* root while the outer one is propagating; a chain of such writes this deep is
|
|
128
|
+
* a loop that would otherwise run until the stack overflows.
|
|
131
129
|
*/
|
|
132
130
|
export const maxUpdateNesting = 100;
|
|
133
131
|
|
|
@@ -173,10 +171,10 @@ type Bucket = {
|
|
|
173
171
|
*
|
|
174
172
|
* A queued node is marked with the token of the update that queued it
|
|
175
173
|
* (`queuedFor`), which is how an update queues a node once. The mark is not
|
|
176
|
-
* cleared after the visit: a later update has another token. An update does
|
|
177
|
-
*
|
|
178
|
-
*
|
|
179
|
-
*
|
|
174
|
+
* cleared after the visit: a later update has another token. An update does not
|
|
175
|
+
* overwrite the mark of an update that is still open — one it is nested in, or
|
|
176
|
+
* one of another copy of synstate — and remembers the nodes it queues despite
|
|
177
|
+
* such a mark in a set of its own instead.
|
|
180
178
|
*/
|
|
181
179
|
class UpdateQueue {
|
|
182
180
|
readonly #base: number;
|
|
@@ -252,8 +250,8 @@ class UpdateQueue {
|
|
|
252
250
|
}
|
|
253
251
|
|
|
254
252
|
if (mark !== undefined && toQueue(mark).isOpen) {
|
|
255
|
-
// Another open update has queued `child` and may not have visited
|
|
256
|
-
//
|
|
253
|
+
// Another open update has queued `child` and may not have visited it
|
|
254
|
+
// yet: leave its mark alone.
|
|
257
255
|
if (this.#mut_queuedDespiteMark === undefined) {
|
|
258
256
|
this.#mut_queuedDespiteMark = new Set<ChildNode>();
|
|
259
257
|
} else if (this.#mut_queuedDespiteMark.has(child)) {
|
|
@@ -274,8 +272,8 @@ class UpdateQueue {
|
|
|
274
272
|
|
|
275
273
|
const mut_buckets = this.#mut_buckets;
|
|
276
274
|
|
|
277
|
-
// `size` grows while the buckets are visited, always past `index`, which
|
|
278
|
-
//
|
|
275
|
+
// `size` grows while the buckets are visited, always past `index`, which a
|
|
276
|
+
// `range` built at the start would miss.
|
|
279
277
|
// eslint-disable-next-line ts-data-forge/prefer-range-for-loop
|
|
280
278
|
for (let mut_index = 0; mut_index < this.#mut_size; mut_index += 1) {
|
|
281
279
|
const mut_bucket = mut_buckets[mut_index];
|
|
@@ -284,9 +282,9 @@ class UpdateQueue {
|
|
|
284
282
|
continue;
|
|
285
283
|
}
|
|
286
284
|
|
|
287
|
-
// A node visited here queues only deeper nodes, so this bucket does
|
|
288
|
-
//
|
|
289
|
-
//
|
|
285
|
+
// A node visited here queues only deeper nodes, so this bucket does not
|
|
286
|
+
// grow while it is visited. Its length is kept until the end, so that
|
|
287
|
+
// `close` can clear what an exception leaves.
|
|
290
288
|
const { nodes: mut_nodes, length } = mut_bucket;
|
|
291
289
|
|
|
292
290
|
// eslint-disable-next-line ts-data-forge/prefer-range-for-loop
|
|
@@ -202,8 +202,8 @@ describe('a completed observable leaves the propagation graph', () => {
|
|
|
202
202
|
|
|
203
203
|
const mut_got: number[] = [];
|
|
204
204
|
|
|
205
|
-
// Subscribed on a child, so the node is created while the update of `s`
|
|
206
|
-
//
|
|
205
|
+
// Subscribed on a child, so the node is created while the update of `s` is
|
|
206
|
+
// under way.
|
|
207
207
|
s.pipe(map((x) => x)).subscribe((x) => {
|
|
208
208
|
if (x === 1) {
|
|
209
209
|
s.pipe(
|
|
@@ -16,11 +16,11 @@ export class RootObservableClass<A>
|
|
|
16
16
|
implements RootObservable<A>
|
|
17
17
|
{
|
|
18
18
|
/**
|
|
19
|
-
* The outermost update propagating when this root was created. A root
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
19
|
+
* The outermost update propagating when this root was created. A root created
|
|
20
|
+
* while an update propagates (inside a `switchMap` projection, say) may emit
|
|
21
|
+
* while it is created, as `fromSubscribable` does for a synchronous source.
|
|
22
|
+
* Nothing is derived from it yet, so that is its initial value rather than a
|
|
23
|
+
* write (#2336).
|
|
24
24
|
*/
|
|
25
25
|
readonly #createdDuring: UpdateToken | undefined;
|
|
26
26
|
#mut_hasWarned: boolean;
|
|
@@ -64,10 +64,10 @@ export class RootObservableClass<A>
|
|
|
64
64
|
|
|
65
65
|
/**
|
|
66
66
|
* Shown once per root observable, the first time it is written to (`next`,
|
|
67
|
-
* `setState`, `dispatch`, …) while another update is still propagating —
|
|
68
|
-
*
|
|
69
|
-
*
|
|
70
|
-
*
|
|
67
|
+
* `setState`, `dispatch`, …) while another update is still propagating — from a
|
|
68
|
+
* subscriber or a projection. The write still propagates immediately, as it
|
|
69
|
+
* always has; the warning is there because the pattern is wrong, not because
|
|
70
|
+
* anything was refused.
|
|
71
71
|
*/
|
|
72
72
|
export const writeDuringPropagationWarning =
|
|
73
73
|
'synstate: an observable was written to (next / setState / dispatch) while an update was propagating, so subscribers can see intermediate states. Derive the value with map / combine instead of writing from a subscriber or a projection.';
|
|
@@ -6,8 +6,8 @@ import { debounce, map, switchMap } from '../operators/index.mjs';
|
|
|
6
6
|
import { writeDuringPropagationWarning } from './root-observable-class.mjs';
|
|
7
7
|
|
|
8
8
|
// A write to an observable with no child and no subscriber stores the value
|
|
9
|
-
// without opening an update (`ManagerObservableClass.startUpdate`). These
|
|
10
|
-
//
|
|
9
|
+
// without opening an update (`ManagerObservableClass.startUpdate`). These pin
|
|
10
|
+
// what that must not change.
|
|
11
11
|
describe('a write nothing observes', () => {
|
|
12
12
|
test('is held, and a later subscriber receives the last one', () => {
|
|
13
13
|
const s$ = source<number>(0);
|
|
@@ -98,8 +98,8 @@ describe('a write nothing observes', () => {
|
|
|
98
98
|
|
|
99
99
|
a$.next(6);
|
|
100
100
|
|
|
101
|
-
// merge passes on the parents that emitted in an update: only b$, then
|
|
102
|
-
//
|
|
101
|
+
// merge passes on the parents that emitted in an update: only b$, then only
|
|
102
|
+
// a$, never the value a$ was given while nothing observed it.
|
|
103
103
|
assert.deepStrictEqual(mut_merged, [1, 6]);
|
|
104
104
|
|
|
105
105
|
assert.deepStrictEqual(mut_derived, [
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Sumi bans classes, `this`, method syntax and writes to `this` outside a
|
|
2
|
-
// `mut_` binding; an observable is a class (`ObservableBaseClass` says why),
|
|
3
|
-
//
|
|
2
|
+
// `mut_` binding; an observable is a class (`ObservableBaseClass` says why), so
|
|
3
|
+
// those rules are waived here (D-63).
|
|
4
4
|
// @sumi-expect-error-file classes/no-class
|
|
5
5
|
// @sumi-expect-error-file banned-syntax/no-this
|
|
6
6
|
// @sumi-expect-error-file functions/prefer-arrow-function
|
|
@@ -20,14 +20,13 @@ import type {
|
|
|
20
20
|
|
|
21
21
|
/**
|
|
22
22
|
* Derives one value from the latest values of several observables: one
|
|
23
|
-
* observable that calls `project` with them, as arguments, and emits the
|
|
24
|
-
*
|
|
23
|
+
* observable that calls `project` with them, as arguments, and emits the result
|
|
24
|
+
* unless it equals the one already held.
|
|
25
25
|
*
|
|
26
|
-
* It emits once every parent has a value, and then whenever any of them
|
|
27
|
-
*
|
|
28
|
-
* observables and a tuple per update, `derive` is one, and passes the values
|
|
29
|
-
*
|
|
30
|
-
* again).
|
|
26
|
+
* It emits once every parent has a value, and then whenever any of them emits,
|
|
27
|
+
* as `combine` does; but where `combine(parents).pipe(map(fn))` is two
|
|
28
|
+
* observables and a tuple per update, `derive` is one, and passes the values as
|
|
29
|
+
* arguments (a rest parameter in `project` collects them into an array again).
|
|
31
30
|
* The comparison is `Object.is` unless `equals` says otherwise.
|
|
32
31
|
*
|
|
33
32
|
* @template OS - Tuple type of the parent observables
|
|
@@ -83,8 +82,8 @@ export const derive = <const OS extends NonEmptyTuple<Observable<unknown>>, B>(
|
|
|
83
82
|
// @sumi-expect-error banned-syntax/no-unsafe-type-assertion
|
|
84
83
|
new DeriveObservableClass(
|
|
85
84
|
parents,
|
|
86
|
-
// `project` is called with the values of `parents`, position by
|
|
87
|
-
//
|
|
85
|
+
// `project` is called with the values of `parents`, position by position,
|
|
86
|
+
// which the checker cannot follow through an index.
|
|
88
87
|
// @sumi-expect-error banned-syntax/no-unsafe-type-assertion
|
|
89
88
|
project as (...values: readonly unknown[]) => B,
|
|
90
89
|
options?.equals ?? Object.is,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Sumi bans classes, `this`, method syntax and writes to `this` outside a
|
|
2
|
-
// `mut_` binding; an observable is a class (`ObservableBaseClass` says why),
|
|
3
|
-
//
|
|
2
|
+
// `mut_` binding; an observable is a class (`ObservableBaseClass` says why), so
|
|
3
|
+
// those rules are waived here (D-63).
|
|
4
4
|
// @sumi-expect-error-file classes/no-class
|
|
5
5
|
// @sumi-expect-error-file banned-syntax/no-this
|
|
6
6
|
// @sumi-expect-error-file functions/prefer-arrow-function
|
package/src/core/combine/zip.mts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Sumi bans classes, `this`, method syntax and writes to `this` outside a
|
|
2
|
-
// `mut_` binding; an observable is a class (`ObservableBaseClass` says why),
|
|
3
|
-
//
|
|
2
|
+
// `mut_` binding; an observable is a class (`ObservableBaseClass` says why), so
|
|
3
|
+
// those rules are waived here (D-63).
|
|
4
4
|
// @sumi-expect-error-file classes/no-class
|
|
5
5
|
// @sumi-expect-error-file banned-syntax/no-this
|
|
6
6
|
// @sumi-expect-error-file functions/prefer-arrow-function
|
|
@@ -26,9 +26,9 @@ import type {
|
|
|
26
26
|
/**
|
|
27
27
|
* Combines multiple observables by pairing their emissions by index.
|
|
28
28
|
* Waits for all sources to emit their nth value before emitting the nth tuple.
|
|
29
|
-
* Completes once a completed source has no value left to pair, as RxJS's
|
|
30
|
-
*
|
|
31
|
-
*
|
|
29
|
+
* Completes once a completed source has no value left to pair, as RxJS's `zip`
|
|
30
|
+
* does: at once if it completes with nothing queued, otherwise after the tuple
|
|
31
|
+
* that takes its last queued value.
|
|
32
32
|
*
|
|
33
33
|
* @template OS - Tuple type of source observables
|
|
34
34
|
* @param parents - Array of observables to zip
|
|
@@ -156,8 +156,8 @@ class ZipObservableClass<const A extends NonEmptyUnknownList>
|
|
|
156
156
|
}
|
|
157
157
|
|
|
158
158
|
/**
|
|
159
|
-
* No tuple can be completed any more once a completed source has nothing
|
|
160
|
-
*
|
|
159
|
+
* No tuple can be completed any more once a completed source has nothing left
|
|
160
|
+
* to pair (#2343).
|
|
161
161
|
*/
|
|
162
162
|
override canEmitNoMore(): boolean {
|
|
163
163
|
return this.parents.some(
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Sumi bans classes, `this`, method syntax and writes to `this` outside a
|
|
2
|
-
// `mut_` binding; an observable is a class (`ObservableBaseClass` says why),
|
|
3
|
-
//
|
|
2
|
+
// `mut_` binding; an observable is a class (`ObservableBaseClass` says why), so
|
|
3
|
+
// those rules are waived here (D-63).
|
|
4
4
|
// @sumi-expect-error-file classes/no-class
|
|
5
5
|
// @sumi-expect-error-file banned-syntax/no-this
|
|
6
6
|
// @sumi-expect-error-file functions/prefer-arrow-function
|
|
@@ -12,9 +12,9 @@ import type { CounterObservable, TimerId } from '../types/index.mjs';
|
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
14
|
* Creates an observable that emits incremental numbers at a specified interval.
|
|
15
|
-
* Emits 0 in the macrotask right after `start()` (which runs at creation
|
|
16
|
-
*
|
|
17
|
-
*
|
|
15
|
+
* Emits 0 in the macrotask right after `start()` (which runs at creation unless
|
|
16
|
+
* `startManually` is set), then 1, 2, 3, ... every interval. A subscriber added
|
|
17
|
+
* after that 0 has been emitted does not receive it.
|
|
18
18
|
*
|
|
19
19
|
* @param intervalMilliSeconds - The interval duration in milliseconds
|
|
20
20
|
* @param options - Optional settings
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Sumi bans classes, `this`, method syntax and writes to `this` outside a
|
|
2
|
-
// `mut_` binding; an observable is a class (`ObservableBaseClass` says why),
|
|
3
|
-
//
|
|
2
|
+
// `mut_` binding; an observable is a class (`ObservableBaseClass` says why), so
|
|
3
|
+
// those rules are waived here (D-63).
|
|
4
4
|
// @sumi-expect-error-file classes/no-class
|
|
5
5
|
// @sumi-expect-error-file banned-syntax/no-this
|
|
6
6
|
// @sumi-expect-error-file functions/prefer-arrow-function
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Sumi bans classes, `this`, method syntax and writes to `this` outside a
|
|
2
|
-
// `mut_` binding; an observable is a class (`ObservableBaseClass` says why),
|
|
3
|
-
//
|
|
2
|
+
// `mut_` binding; an observable is a class (`ObservableBaseClass` says why), so
|
|
3
|
+
// those rules are waived here (D-63).
|
|
4
4
|
// @sumi-expect-error-file classes/no-class
|
|
5
5
|
// @sumi-expect-error-file banned-syntax/no-this
|
|
6
6
|
// @sumi-expect-error-file functions/prefer-arrow-function
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Sumi bans classes, `this`, method syntax and writes to `this` outside a
|
|
2
|
-
// `mut_` binding; an observable is a class (`ObservableBaseClass` says why),
|
|
3
|
-
//
|
|
2
|
+
// `mut_` binding; an observable is a class (`ObservableBaseClass` says why), so
|
|
3
|
+
// those rules are waived here (D-63).
|
|
4
4
|
// @sumi-expect-error-file classes/no-class
|
|
5
5
|
// @sumi-expect-error-file banned-syntax/no-this
|
|
6
6
|
// @sumi-expect-error-file functions/prefer-arrow-function
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Sumi bans classes, `this`, method syntax and writes to `this` outside a
|
|
2
|
-
// `mut_` binding; an observable is a class (`ObservableBaseClass` says why),
|
|
3
|
-
//
|
|
2
|
+
// `mut_` binding; an observable is a class (`ObservableBaseClass` says why), so
|
|
3
|
+
// those rules are waived here (D-63).
|
|
4
4
|
// @sumi-expect-error-file classes/no-class
|
|
5
5
|
// @sumi-expect-error-file banned-syntax/no-this
|
|
6
6
|
// @sumi-expect-error-file functions/prefer-arrow-function
|
|
@@ -79,9 +79,9 @@ class SourceObservableClass<A>
|
|
|
79
79
|
});
|
|
80
80
|
}
|
|
81
81
|
|
|
82
|
-
// Returns the value held after the call: `nextValue`, or, once completed,
|
|
83
|
-
//
|
|
84
|
-
//
|
|
82
|
+
// Returns the value held after the call: `nextValue`, or, once completed, the
|
|
83
|
+
// value already there — `undefined` only on a source that never had one,
|
|
84
|
+
// whose `next` is typed `void`.
|
|
85
85
|
next(nextValue: A): A | undefined {
|
|
86
86
|
if (this.isCompleted) {
|
|
87
87
|
return Optional.unwrap(this.getSnapshot());
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Sumi bans classes, `this`, method syntax and writes to `this` outside a
|
|
2
|
-
// `mut_` binding; an observable is a class (`ObservableBaseClass` says why),
|
|
3
|
-
//
|
|
2
|
+
// `mut_` binding; an observable is a class (`ObservableBaseClass` says why), so
|
|
3
|
+
// those rules are waived here (D-63).
|
|
4
4
|
// @sumi-expect-error-file classes/no-class
|
|
5
5
|
// @sumi-expect-error-file banned-syntax/no-this
|
|
6
6
|
// @sumi-expect-error-file functions/prefer-arrow-function
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Sumi bans classes, `this`, method syntax and writes to `this` outside a
|
|
2
|
-
// `mut_` binding; an observable is a class (`ObservableBaseClass` says why),
|
|
3
|
-
//
|
|
2
|
+
// `mut_` binding; an observable is a class (`ObservableBaseClass` says why), so
|
|
3
|
+
// those rules are waived here (D-63).
|
|
4
4
|
// @sumi-expect-error-file classes/no-class
|
|
5
5
|
// @sumi-expect-error-file banned-syntax/no-this
|
|
6
6
|
// @sumi-expect-error-file functions/prefer-arrow-function
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Sumi bans classes, `this`, method syntax and writes to `this` outside a
|
|
2
|
-
// `mut_` binding; an observable is a class (`ObservableBaseClass` says why),
|
|
3
|
-
//
|
|
2
|
+
// `mut_` binding; an observable is a class (`ObservableBaseClass` says why), so
|
|
3
|
+
// those rules are waived here (D-63).
|
|
4
4
|
// @sumi-expect-error-file classes/no-class
|
|
5
5
|
// @sumi-expect-error-file banned-syntax/no-this
|
|
6
6
|
// @sumi-expect-error-file functions/prefer-arrow-function
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Sumi bans classes, `this`, method syntax and writes to `this` outside a
|
|
2
|
-
// `mut_` binding; an observable is a class (`ObservableBaseClass` says why),
|
|
3
|
-
//
|
|
2
|
+
// `mut_` binding; an observable is a class (`ObservableBaseClass` says why), so
|
|
3
|
+
// those rules are waived here (D-63).
|
|
4
4
|
// @sumi-expect-error-file classes/no-class
|
|
5
5
|
// @sumi-expect-error-file banned-syntax/no-this
|
|
6
6
|
// @sumi-expect-error-file functions/prefer-arrow-function
|
|
@@ -175,8 +175,8 @@ if (import.meta.vitest !== undefined) {
|
|
|
175
175
|
|
|
176
176
|
expectType<typeof _inferred, Observable<number>>('=');
|
|
177
177
|
|
|
178
|
-
// A generic guard is what a single signature with a union parameter
|
|
179
|
-
//
|
|
178
|
+
// A generic guard is what a single signature with a union parameter loses
|
|
179
|
+
// (it infers `unknown`), and why this set stays overloaded.
|
|
180
180
|
const _generic = s.pipe(filter(isNotUndefined));
|
|
181
181
|
|
|
182
182
|
expectType<typeof _generic, Observable<number>>('=');
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Sumi bans classes, `this`, method syntax and writes to `this` outside a
|
|
2
|
-
// `mut_` binding; an observable is a class (`ObservableBaseClass` says why),
|
|
3
|
-
//
|
|
2
|
+
// `mut_` binding; an observable is a class (`ObservableBaseClass` says why), so
|
|
3
|
+
// those rules are waived here (D-63).
|
|
4
4
|
// @sumi-expect-error-file classes/no-class
|
|
5
5
|
// @sumi-expect-error-file banned-syntax/no-this
|
|
6
6
|
// @sumi-expect-error-file functions/prefer-arrow-function
|
|
@@ -20,19 +20,19 @@ import type {
|
|
|
20
20
|
|
|
21
21
|
/**
|
|
22
22
|
* Passes on each value with every part deeply equal to the same part of the
|
|
23
|
-
* value passed on before replaced by that part, and skips a value deeply
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
23
|
+
* value passed on before replaced by that part, and skips a value deeply equal
|
|
24
|
+
* to it altogether (structural sharing). A reader of a part that did not change
|
|
25
|
+
* keeps the object it has, so `skipIfNoChange()` with `Object.is` stops it.
|
|
26
|
+
* Superset of `skipIfNoChange(fastDeepEqual)`.
|
|
27
27
|
*
|
|
28
28
|
* **Prefer keeping references where the value is written** — compare before
|
|
29
|
-
* `setState`, and skip it when nothing changed — so that nothing downstream
|
|
30
|
-
*
|
|
31
|
-
* `createReducer` does it for a state written whole, and `replaceEqualDeep`
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
29
|
+
* `setState`, and skip it when nothing changed — so that nothing downstream has
|
|
30
|
+
* anything to undo. The `keepEqualParts` option of `createState` and
|
|
31
|
+
* `createReducer` does it for a state written whole, and `replaceEqualDeep` of
|
|
32
|
+
* ts-data-forge does it for any other write. This operator lets every update
|
|
33
|
+
* that changes nothing reach the source and everything up to it, and walks the
|
|
34
|
+
* whole value again on each one; reach for it when the source is not yours to
|
|
35
|
+
* change (a stream that arrives whole from outside).
|
|
36
36
|
*
|
|
37
37
|
* Array items are matched by index; pass `{ key }` to match them by key, an
|
|
38
38
|
* item for which `key` returns `undefined` being matched by index. Only plain
|
|
@@ -51,10 +51,9 @@ import type {
|
|
|
51
51
|
* cards: { id: number; text: string }[];
|
|
52
52
|
* }>;
|
|
53
53
|
*
|
|
54
|
-
* // A stream that arrives whole from outside (a WebSocket, say), each
|
|
55
|
-
* //
|
|
56
|
-
* //
|
|
57
|
-
* // instead.
|
|
54
|
+
* // A stream that arrives whole from outside (a WebSocket, say), each message
|
|
55
|
+
* // a new object even when nothing changed. A state you write yourself takes
|
|
56
|
+
* // `createState(initial, { keepEqualParts: true })` instead.
|
|
58
57
|
* const message$ = source<Board>();
|
|
59
58
|
*
|
|
60
59
|
* const board$ = message$.pipe(keepEqualParts());
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Sumi bans classes, `this`, method syntax and writes to `this` outside a
|
|
2
|
-
// `mut_` binding; an observable is a class (`ObservableBaseClass` says why),
|
|
3
|
-
//
|
|
2
|
+
// `mut_` binding; an observable is a class (`ObservableBaseClass` says why), so
|
|
3
|
+
// those rules are waived here (D-63).
|
|
4
4
|
// @sumi-expect-error-file classes/no-class
|
|
5
5
|
// @sumi-expect-error-file banned-syntax/no-this
|
|
6
6
|
// @sumi-expect-error-file functions/prefer-arrow-function
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Sumi bans classes, `this`, method syntax and writes to `this` outside a
|
|
2
|
-
// `mut_` binding; an observable is a class (`ObservableBaseClass` says why),
|
|
3
|
-
//
|
|
2
|
+
// `mut_` binding; an observable is a class (`ObservableBaseClass` says why), so
|
|
3
|
+
// those rules are waived here (D-63).
|
|
4
4
|
// @sumi-expect-error-file classes/no-class
|
|
5
5
|
// @sumi-expect-error-file banned-syntax/no-this
|
|
6
6
|
// @sumi-expect-error-file functions/prefer-arrow-function
|
|
@@ -22,9 +22,9 @@ import type {
|
|
|
22
22
|
* Unlike `switchMap`, does not cancel previous inner observables.
|
|
23
23
|
*
|
|
24
24
|
* Each projection runs in a scope of its own (see `createScope`): what it
|
|
25
|
-
* creates is disposed when `mergeMap` completes. An observable it only
|
|
26
|
-
*
|
|
27
|
-
*
|
|
25
|
+
* creates is disposed when `mergeMap` completes. An observable it only returns
|
|
26
|
+
* — one created outside the projection and shared with others — is unsubscribed
|
|
27
|
+
* and left running.
|
|
28
28
|
*
|
|
29
29
|
* @template A - The type of values from the source
|
|
30
30
|
* @template B - The type of values from the projected observable
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Sumi bans classes, `this`, method syntax and writes to `this` outside a
|
|
2
|
-
// `mut_` binding; an observable is a class (`ObservableBaseClass` says why),
|
|
3
|
-
//
|
|
2
|
+
// `mut_` binding; an observable is a class (`ObservableBaseClass` says why), so
|
|
3
|
+
// those rules are waived here (D-63).
|
|
4
4
|
// @sumi-expect-error-file classes/no-class
|
|
5
5
|
// @sumi-expect-error-file banned-syntax/no-this
|
|
6
6
|
// @sumi-expect-error-file functions/prefer-arrow-function
|
|
@@ -90,8 +90,8 @@ class PairwiseObservableClass<A>
|
|
|
90
90
|
initialValue: Optional.none,
|
|
91
91
|
});
|
|
92
92
|
|
|
93
|
-
// parentObservable.snapshot has value
|
|
94
|
-
//
|
|
93
|
+
// parentObservable.snapshot has value if parentObservable is
|
|
94
|
+
// InitializedObservable
|
|
95
95
|
this.#mut_previousValue = parentObservable.getSnapshot();
|
|
96
96
|
|
|
97
97
|
this.attach();
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Sumi bans classes, `this`, method syntax and writes to `this` outside a
|
|
2
|
-
// `mut_` binding; an observable is a class (`ObservableBaseClass` says why),
|
|
3
|
-
//
|
|
2
|
+
// `mut_` binding; an observable is a class (`ObservableBaseClass` says why), so
|
|
3
|
+
// those rules are waived here (D-63).
|
|
4
4
|
// @sumi-expect-error-file classes/no-class
|
|
5
5
|
// @sumi-expect-error-file banned-syntax/no-this
|
|
6
6
|
// @sumi-expect-error-file functions/prefer-arrow-function
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Sumi bans classes, `this`, method syntax and writes to `this` outside a
|
|
2
|
-
// `mut_` binding; an observable is a class (`ObservableBaseClass` says why),
|
|
3
|
-
//
|
|
2
|
+
// `mut_` binding; an observable is a class (`ObservableBaseClass` says why), so
|
|
3
|
+
// those rules are waived here (D-63).
|
|
4
4
|
// @sumi-expect-error-file classes/no-class
|
|
5
5
|
// @sumi-expect-error-file banned-syntax/no-this
|
|
6
6
|
// @sumi-expect-error-file functions/prefer-arrow-function
|
|
@@ -104,8 +104,8 @@ class SkipIfNoChangeObservableClass<A>
|
|
|
104
104
|
initialValue: parentObservable.getSnapshot(),
|
|
105
105
|
});
|
|
106
106
|
|
|
107
|
-
// parentObservable.snapshot has value
|
|
108
|
-
//
|
|
107
|
+
// parentObservable.snapshot has value if parentObservable is
|
|
108
|
+
// InitializedObservable
|
|
109
109
|
this.#mut_previousValue = parentObservable.getSnapshot();
|
|
110
110
|
|
|
111
111
|
this.#eq = eq;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Sumi bans classes, `this`, method syntax and writes to `this` outside a
|
|
2
|
-
// `mut_` binding; an observable is a class (`ObservableBaseClass` says why),
|
|
3
|
-
//
|
|
2
|
+
// `mut_` binding; an observable is a class (`ObservableBaseClass` says why), so
|
|
3
|
+
// those rules are waived here (D-63).
|
|
4
4
|
// @sumi-expect-error-file classes/no-class
|
|
5
5
|
// @sumi-expect-error-file banned-syntax/no-this
|
|
6
6
|
// @sumi-expect-error-file functions/prefer-arrow-function
|
|
@@ -83,8 +83,8 @@ class SkipUntilObservableClass<A>
|
|
|
83
83
|
initialValue: Optional.none,
|
|
84
84
|
});
|
|
85
85
|
|
|
86
|
-
// A notifier that already holds a value, or has completed, would stop
|
|
87
|
-
//
|
|
86
|
+
// A notifier that already holds a value, or has completed, would stop the
|
|
87
|
+
// skipping inside `subscribe`, before the subscription is stored.
|
|
88
88
|
this.#mut_isSkipping =
|
|
89
89
|
Optional.isNone(notifier.getSnapshot()) && !notifier.isCompleted;
|
|
90
90
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Sumi bans classes, `this`, method syntax and writes to `this` outside a
|
|
2
|
-
// `mut_` binding; an observable is a class (`ObservableBaseClass` says why),
|
|
3
|
-
//
|
|
2
|
+
// `mut_` binding; an observable is a class (`ObservableBaseClass` says why), so
|
|
3
|
+
// those rules are waived here (D-63).
|
|
4
4
|
// @sumi-expect-error-file classes/no-class
|
|
5
5
|
// @sumi-expect-error-file banned-syntax/no-this
|
|
6
6
|
// @sumi-expect-error-file functions/prefer-arrow-function
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Sumi bans classes, `this`, method syntax and writes to `this` outside a
|
|
2
|
-
// `mut_` binding; an observable is a class (`ObservableBaseClass` says why),
|
|
3
|
-
//
|
|
2
|
+
// `mut_` binding; an observable is a class (`ObservableBaseClass` says why), so
|
|
3
|
+
// those rules are waived here (D-63).
|
|
4
4
|
// @sumi-expect-error-file classes/no-class
|
|
5
5
|
// @sumi-expect-error-file banned-syntax/no-this
|
|
6
6
|
// @sumi-expect-error-file functions/prefer-arrow-function
|
|
@@ -126,9 +126,9 @@ class SwitchMapObservableClass<A, B>
|
|
|
126
126
|
readonly #mapToObservable: (curr: A) => Observable<B>;
|
|
127
127
|
|
|
128
128
|
/**
|
|
129
|
-
* The scope the operator was created in, so that each inner scope is
|
|
130
|
-
*
|
|
131
|
-
*
|
|
129
|
+
* The scope the operator was created in, so that each inner scope is disposed
|
|
130
|
+
* with it; the projection itself runs during propagation, when the current
|
|
131
|
+
* scope is whatever happens to be running.
|
|
132
132
|
*/
|
|
133
133
|
readonly #ownerScope: Scope | undefined;
|
|
134
134
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Sumi bans classes, `this`, method syntax and writes to `this` outside a
|
|
2
|
-
// `mut_` binding; an observable is a class (`ObservableBaseClass` says why),
|
|
3
|
-
//
|
|
2
|
+
// `mut_` binding; an observable is a class (`ObservableBaseClass` says why), so
|
|
3
|
+
// those rules are waived here (D-63).
|
|
4
4
|
// @sumi-expect-error-file classes/no-class
|
|
5
5
|
// @sumi-expect-error-file banned-syntax/no-this
|
|
6
6
|
// @sumi-expect-error-file functions/prefer-arrow-function
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Sumi bans classes, `this`, method syntax and writes to `this` outside a
|
|
2
|
-
// `mut_` binding; an observable is a class (`ObservableBaseClass` says why),
|
|
3
|
-
//
|
|
2
|
+
// `mut_` binding; an observable is a class (`ObservableBaseClass` says why), so
|
|
3
|
+
// those rules are waived here (D-63).
|
|
4
4
|
// @sumi-expect-error-file classes/no-class
|
|
5
5
|
// @sumi-expect-error-file banned-syntax/no-this
|
|
6
6
|
// @sumi-expect-error-file functions/prefer-arrow-function
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Sumi bans classes, `this`, method syntax and writes to `this` outside a
|
|
2
|
-
// `mut_` binding; an observable is a class (`ObservableBaseClass` says why),
|
|
3
|
-
//
|
|
2
|
+
// `mut_` binding; an observable is a class (`ObservableBaseClass` says why), so
|
|
3
|
+
// those rules are waived here (D-63).
|
|
4
4
|
// @sumi-expect-error-file classes/no-class
|
|
5
5
|
// @sumi-expect-error-file banned-syntax/no-this
|
|
6
6
|
// @sumi-expect-error-file functions/prefer-arrow-function
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Sumi bans classes, `this`, method syntax and writes to `this` outside a
|
|
2
|
-
// `mut_` binding; an observable is a class (`ObservableBaseClass` says why),
|
|
3
|
-
//
|
|
2
|
+
// `mut_` binding; an observable is a class (`ObservableBaseClass` says why), so
|
|
3
|
+
// those rules are waived here (D-63).
|
|
4
4
|
// @sumi-expect-error-file classes/no-class
|
|
5
5
|
// @sumi-expect-error-file banned-syntax/no-this
|
|
6
6
|
// @sumi-expect-error-file functions/prefer-arrow-function
|