async-reactivity 2.0.20 → 2.0.22

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/lib/computed.js CHANGED
@@ -9,7 +9,6 @@ var ComputedState;
9
9
  ComputedState[ComputedState["Uncertain"] = 2] = "Uncertain";
10
10
  ComputedState[ComputedState["Computing"] = 3] = "Computing";
11
11
  })(ComputedState || (ComputedState = {}));
12
- ;
13
12
  class CircularDependencyError extends Error {
14
13
  }
15
14
  export default class Computed extends Tracker {
@@ -21,6 +20,7 @@ export default class Computed extends Tracker {
21
20
  computePromiseActions;
22
21
  lastComputeAttemptPromise;
23
22
  deferrer;
23
+ abortController;
24
24
  constructor(getter, isEqual = (defaultIsEqual), timeToLive) {
25
25
  super();
26
26
  this.getter = getter;
@@ -70,9 +70,13 @@ export default class Computed extends Tracker {
70
70
  return this._value;
71
71
  }
72
72
  }
73
+ else if (this.state === ComputedState.Computing) {
74
+ this.abortController?.abort();
75
+ }
73
76
  this.state = ComputedState.Computing;
74
77
  this.clearDependencies(true);
75
- const newValue = this.getter(this.trackDependency, this._value);
78
+ this.abortController = new AbortController();
79
+ const newValue = this.getter(this.trackDependency, this._value, this.abortController.signal);
76
80
  if (this.isEqual(newValue, this._value)) {
77
81
  this.handlePromiseThen(this.lastComputeAttemptPromise, this._value);
78
82
  this.validateDependents();
@@ -120,6 +124,7 @@ export default class Computed extends Tracker {
120
124
  finalizeComputing() {
121
125
  this.state = ComputedState.Valid;
122
126
  this.lastComputeAttemptPromise = undefined;
127
+ this.abortController = undefined;
123
128
  this.prepareComputePromise();
124
129
  }
125
130
  invalidate() {
@@ -186,6 +186,23 @@ describe('async computed', function () {
186
186
  a.value = 8;
187
187
  assert.strictEqual(await b.value, 13);
188
188
  });
189
+ it('dependency changed while computing - abortSignal', async function () {
190
+ const a = new Ref(5);
191
+ let gate = 0;
192
+ const b = new Computed(async (value, _previousValue, abortSignal) => {
193
+ const dep = value(a);
194
+ await new Promise(resolve => setTimeout(resolve, 10));
195
+ if (abortSignal.aborted) {
196
+ throw new Error();
197
+ }
198
+ gate++;
199
+ return dep + 5;
200
+ });
201
+ b.value; // trigger compute
202
+ a.value = 8;
203
+ await b.value;
204
+ assert.strictEqual(gate, 1);
205
+ });
189
206
  it('old dependency changed while computing', async function () {
190
207
  let gate = 0;
191
208
  const a = new Ref(5);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "async-reactivity",
3
- "version": "2.0.20",
3
+ "version": "2.0.22",
4
4
  "description": "",
5
5
  "main": "lib/index.js",
6
6
  "types": "types/index.d.ts",
@@ -219,6 +219,24 @@ describe('async computed', function () {
219
219
  assert.strictEqual(await b.value, 13);
220
220
  });
221
221
 
222
+ it('dependency changed while computing - abortSignal', async function () {
223
+ const a = new Ref(5);
224
+ let gate = 0;
225
+ const b = new Computed(async (value, _previousValue, abortSignal) => {
226
+ const dep = value(a);
227
+ await new Promise(resolve => setTimeout(resolve, 10));
228
+ if (abortSignal.aborted) {
229
+ throw new Error();
230
+ }
231
+ gate++;
232
+ return dep + 5;
233
+ });
234
+ b.value; // trigger compute
235
+ a.value = 8;
236
+ await b.value;
237
+ assert.strictEqual(gate, 1);
238
+ });
239
+
222
240
  it('old dependency changed while computing', async function () {
223
241
  let gate = 0;
224
242
  const a = new Ref(5);
package/src/computed.ts CHANGED
@@ -6,29 +6,30 @@ import { Deferrer } from "./deferrer.js";
6
6
  import { debounce } from 'lodash-es';
7
7
 
8
8
  export declare type TrackValue = <T>(dependency: Dependency<T>) => T;
9
- export declare type ComputeFunc<T> = (value: TrackValue, previousValue?: T) => T;
10
- export declare type ComputeFuncScoped<T1, T2> = (value: TrackValue, scope: T1, previousValue?: T2) => T2;
9
+ export declare type ComputeFunc<T> = (value: TrackValue, previousValue: T | undefined, abortSignal: AbortSignal) => T;
10
+ export declare type ComputeFuncScoped<T1, T2> = (value: TrackValue, scope: T1, previousValue: T2 | undefined, abortSignal: AbortSignal) => T2;
11
11
 
12
12
  enum ComputedState {
13
13
  Invalid,
14
14
  Valid,
15
15
  Uncertain,
16
16
  Computing
17
- };
17
+ }
18
18
 
19
19
  class CircularDependencyError extends Error { }
20
20
 
21
- export default class Computed<T extends TBase, TBase = T> extends Tracker<T> implements Dependent, Dependency<T> {
21
+ export default class Computed<T> extends Tracker<T> implements Dependent, Dependency<T> {
22
22
  getter: ComputeFunc<T>;
23
- isEqual: typeof defaultIsEqual<TBase>;
23
+ isEqual: typeof defaultIsEqual<T>;
24
24
  private state = ComputedState.Invalid;
25
25
  private dependencies = new Map<Dependency<any>, boolean>();
26
26
  private computePromise?: Promise<any>;
27
27
  private computePromiseActions?: { resolve: Function, reject: Function };
28
28
  private lastComputeAttemptPromise?: Promise<void>;
29
29
  private deferrer?: Deferrer;
30
+ private abortController?: AbortController;
30
31
 
31
- constructor(getter: ComputeFunc<T>, isEqual = defaultIsEqual<TBase>, timeToLive?: number) {
32
+ constructor(getter: ComputeFunc<T>, isEqual = defaultIsEqual<T>, timeToLive?: number) {
32
33
  super();
33
34
  this.getter = getter;
34
35
  this.isEqual = isEqual;
@@ -80,12 +81,15 @@ export default class Computed<T extends TBase, TBase = T> extends Tracker<T> imp
80
81
  this.validateDependents();
81
82
  return this._value!;
82
83
  }
84
+ } else if (this.state === ComputedState.Computing) {
85
+ this.abortController?.abort();
83
86
  }
84
87
 
85
88
  this.state = ComputedState.Computing;
86
89
  this.clearDependencies(true);
90
+ this.abortController = new AbortController();
87
91
 
88
- const newValue: T = this.getter(this.trackDependency, this._value);
92
+ const newValue: T = this.getter(this.trackDependency, this._value, this.abortController.signal);
89
93
  if (this.isEqual(newValue, this._value!)) {
90
94
  this.handlePromiseThen(this.lastComputeAttemptPromise!, this._value);
91
95
  this.validateDependents();
@@ -123,7 +127,7 @@ export default class Computed<T extends TBase, TBase = T> extends Tracker<T> imp
123
127
  }
124
128
  }
125
129
 
126
- private innerTrackDependency(this: Computed<T, TBase>, dependency: Dependency<any>) {
130
+ private innerTrackDependency(this: Computed<T>, dependency: Dependency<any>) {
127
131
  if (this.dependents.has(dependency as any)) {
128
132
  throw new CircularDependencyError();
129
133
  }
@@ -137,6 +141,7 @@ export default class Computed<T extends TBase, TBase = T> extends Tracker<T> imp
137
141
  private finalizeComputing() {
138
142
  this.state = ComputedState.Valid;
139
143
  this.lastComputeAttemptPromise = undefined;
144
+ this.abortController = undefined;
140
145
  this.prepareComputePromise();
141
146
  }
142
147
 
package/src/listener.ts CHANGED
@@ -3,13 +3,13 @@ import Ref from "./ref.js";
3
3
  import defaultIsEqual from "./defaultIsEqual.js";
4
4
  import { Deferrer } from "./deferrer.js";
5
5
 
6
- export default class Listener<T extends TBase, TBase = T> extends Ref<T> {
6
+ export default class Listener<T> extends Ref<T> {
7
7
  private start: () => void;
8
8
  private stop: () => void;
9
9
  private listening = false;
10
10
  private deferrer: Deferrer;
11
11
 
12
- constructor(_value: T, start: () => void, stop: () => void, isEqual = defaultIsEqual<TBase>) {
12
+ constructor(_value: T, start: () => void, stop: () => void, isEqual = defaultIsEqual<T>) {
13
13
  super(_value, isEqual);
14
14
 
15
15
  this.start = start;
package/src/ref.ts CHANGED
@@ -2,10 +2,10 @@ import Dependency from "./dependency.js";
2
2
  import Tracker from "./tracker.js";
3
3
  import defaultIsEqual from "./defaultIsEqual.js";
4
4
 
5
- export default class Ref<T extends TBase, TBase = T> extends Tracker<T> implements Dependency<T> {
6
- private isEqual: typeof defaultIsEqual<TBase>;
5
+ export default class Ref<T> extends Tracker<T> implements Dependency<T> {
6
+ private isEqual: typeof defaultIsEqual<T>;
7
7
 
8
- constructor(_value: T, isEqual = defaultIsEqual<TBase>) {
8
+ constructor(_value: T, isEqual = defaultIsEqual<T>) {
9
9
  super();
10
10
  this._value = _value;
11
11
  this.isEqual = isEqual;
@@ -3,18 +3,19 @@ import Dependent from "./dependent.js";
3
3
  import Tracker from "./tracker.js";
4
4
  import defaultIsEqual from "./defaultIsEqual.js";
5
5
  export declare type TrackValue = <T>(dependency: Dependency<T>) => T;
6
- export declare type ComputeFunc<T> = (value: TrackValue, previousValue?: T) => T;
7
- export declare type ComputeFuncScoped<T1, T2> = (value: TrackValue, scope: T1, previousValue?: T2) => T2;
8
- export default class Computed<T extends TBase, TBase = T> extends Tracker<T> implements Dependent, Dependency<T> {
6
+ export declare type ComputeFunc<T> = (value: TrackValue, previousValue: T | undefined, abortSignal: AbortSignal) => T;
7
+ export declare type ComputeFuncScoped<T1, T2> = (value: TrackValue, scope: T1, previousValue: T2 | undefined, abortSignal: AbortSignal) => T2;
8
+ export default class Computed<T> extends Tracker<T> implements Dependent, Dependency<T> {
9
9
  getter: ComputeFunc<T>;
10
- isEqual: typeof defaultIsEqual<TBase>;
10
+ isEqual: typeof defaultIsEqual<T>;
11
11
  private state;
12
12
  private dependencies;
13
13
  private computePromise?;
14
14
  private computePromiseActions?;
15
15
  private lastComputeAttemptPromise?;
16
16
  private deferrer?;
17
- constructor(getter: ComputeFunc<T>, isEqual?: (v1: TBase, v2: TBase) => boolean, timeToLive?: number);
17
+ private abortController?;
18
+ constructor(getter: ComputeFunc<T>, isEqual?: (v1: T, v2: T) => boolean, timeToLive?: number);
18
19
  private prepareComputePromise;
19
20
  get value(): T;
20
21
  private compute;
@@ -1 +1 @@
1
- {"version":3,"file":"computed.d.ts","sourceRoot":"","sources":["../src/computed.ts"],"names":[],"mappings":"AAAA,OAAO,UAAU,MAAM,iBAAiB,CAAC;AACzC,OAAO,SAAS,MAAM,gBAAgB,CAAC;AACvC,OAAO,OAAO,MAAM,cAAc,CAAC;AACnC,OAAO,cAAc,MAAM,qBAAqB,CAAC;AAIjD,MAAM,CAAC,OAAO,MAAM,UAAU,GAAG,CAAC,CAAC,EAAE,UAAU,EAAE,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;AACrE,MAAM,CAAC,OAAO,MAAM,WAAW,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,UAAU,EAAE,aAAa,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC;AACjF,MAAM,CAAC,OAAO,MAAM,iBAAiB,CAAC,EAAE,EAAE,EAAE,IAAI,CAAC,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,EAAE,EAAE,aAAa,CAAC,EAAE,EAAE,KAAK,EAAE,CAAC;AAWzG,MAAM,CAAC,OAAO,OAAO,QAAQ,CAAC,CAAC,SAAS,KAAK,EAAE,KAAK,GAAG,CAAC,CAAE,SAAQ,OAAO,CAAC,CAAC,CAAE,YAAW,SAAS,EAAE,UAAU,CAAC,CAAC,CAAC;IAC5G,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC;IACvB,OAAO,EAAE,OAAO,cAAc,CAAC,KAAK,CAAC,CAAC;IACtC,OAAO,CAAC,KAAK,CAAyB;IACtC,OAAO,CAAC,YAAY,CAAuC;IAC3D,OAAO,CAAC,cAAc,CAAC,CAAe;IACtC,OAAO,CAAC,qBAAqB,CAAC,CAA0C;IACxE,OAAO,CAAC,yBAAyB,CAAC,CAAgB;IAClD,OAAO,CAAC,QAAQ,CAAC,CAAW;gBAEhB,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,EAAE,OAAO,oCAAwB,EAAE,UAAU,CAAC,EAAE,MAAM;IAexF,OAAO,CAAC,qBAAqB;IAS7B,IAAW,KAAK,IAAI,CAAC,CAMpB;IAED,OAAO,CAAC,OAAO;IA0Cf,OAAO,CAAC,iBAAiB;IAOzB,OAAO,CAAC,iBAAiB;IAOzB,OAAO,CAAC,kBAAkB;IAO1B,OAAO,CAAC,oBAAoB;IAS5B,OAAO,CAAC,eAAe,CAAwC;IAE/D,OAAO,CAAC,iBAAiB;IAMlB,UAAU;IAUV,eAAe;IAKf,QAAQ,CAAC,UAAU,EAAE,UAAU,CAAC,GAAG,CAAC;IAI3C,OAAO,CAAC,kBAAkB;IAMnB,eAAe,CAAC,SAAS,EAAE,SAAS,EAAE,OAAO,gBAAoB,GAAG,IAAI;IAKxE,KAAK;IAQL,OAAO;CAGjB"}
1
+ {"version":3,"file":"computed.d.ts","sourceRoot":"","sources":["../src/computed.ts"],"names":[],"mappings":"AAAA,OAAO,UAAU,MAAM,iBAAiB,CAAC;AACzC,OAAO,SAAS,MAAM,gBAAgB,CAAC;AACvC,OAAO,OAAO,MAAM,cAAc,CAAC;AACnC,OAAO,cAAc,MAAM,qBAAqB,CAAC;AAIjD,MAAM,CAAC,OAAO,MAAM,UAAU,GAAG,CAAC,CAAC,EAAE,UAAU,EAAE,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;AACrE,MAAM,CAAC,OAAO,MAAM,WAAW,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,UAAU,EAAE,aAAa,EAAE,CAAC,GAAG,SAAS,EAAE,WAAW,EAAE,WAAW,KAAK,CAAC,CAAC;AACtH,MAAM,CAAC,OAAO,MAAM,iBAAiB,CAAC,EAAE,EAAE,EAAE,IAAI,CAAC,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,EAAE,EAAE,aAAa,EAAE,EAAE,GAAG,SAAS,EAAE,WAAW,EAAE,WAAW,KAAK,EAAE,CAAC;AAW9I,MAAM,CAAC,OAAO,OAAO,QAAQ,CAAC,CAAC,CAAE,SAAQ,OAAO,CAAC,CAAC,CAAE,YAAW,SAAS,EAAE,UAAU,CAAC,CAAC,CAAC;IACnF,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC;IACvB,OAAO,EAAE,OAAO,cAAc,CAAC,CAAC,CAAC,CAAC;IAClC,OAAO,CAAC,KAAK,CAAyB;IACtC,OAAO,CAAC,YAAY,CAAuC;IAC3D,OAAO,CAAC,cAAc,CAAC,CAAe;IACtC,OAAO,CAAC,qBAAqB,CAAC,CAA0C;IACxE,OAAO,CAAC,yBAAyB,CAAC,CAAgB;IAClD,OAAO,CAAC,QAAQ,CAAC,CAAW;IAC5B,OAAO,CAAC,eAAe,CAAC,CAAkB;gBAE9B,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,EAAE,OAAO,4BAAoB,EAAE,UAAU,CAAC,EAAE,MAAM;IAepF,OAAO,CAAC,qBAAqB;IAS7B,IAAW,KAAK,IAAI,CAAC,CAMpB;IAED,OAAO,CAAC,OAAO;IA6Cf,OAAO,CAAC,iBAAiB;IAOzB,OAAO,CAAC,iBAAiB;IAOzB,OAAO,CAAC,kBAAkB;IAO1B,OAAO,CAAC,oBAAoB;IAS5B,OAAO,CAAC,eAAe,CAAwC;IAE/D,OAAO,CAAC,iBAAiB;IAOlB,UAAU;IAUV,eAAe;IAKf,QAAQ,CAAC,UAAU,EAAE,UAAU,CAAC,GAAG,CAAC;IAI3C,OAAO,CAAC,kBAAkB;IAMnB,eAAe,CAAC,SAAS,EAAE,SAAS,EAAE,OAAO,gBAAoB,GAAG,IAAI;IAKxE,KAAK;IAQL,OAAO;CAGjB"}
@@ -1,11 +1,11 @@
1
1
  import Dependent from "./dependent.js";
2
2
  import Ref from "./ref.js";
3
- export default class Listener<T extends TBase, TBase = T> extends Ref<T> {
3
+ export default class Listener<T> extends Ref<T> {
4
4
  private start;
5
5
  private stop;
6
6
  private listening;
7
7
  private deferrer;
8
- constructor(_value: T, start: () => void, stop: () => void, isEqual?: (v1: TBase, v2: TBase) => boolean);
8
+ constructor(_value: T, start: () => void, stop: () => void, isEqual?: (v1: T, v2: T) => boolean);
9
9
  addDependent(dependent: Dependent): void;
10
10
  removeDependent(dependent: Dependent, promise?: Promise<void>): void;
11
11
  }
@@ -1 +1 @@
1
- {"version":3,"file":"listener.d.ts","sourceRoot":"","sources":["../src/listener.ts"],"names":[],"mappings":"AAAA,OAAO,SAAS,MAAM,gBAAgB,CAAC;AACvC,OAAO,GAAG,MAAM,UAAU,CAAC;AAI3B,MAAM,CAAC,OAAO,OAAO,QAAQ,CAAC,CAAC,SAAS,KAAK,EAAE,KAAK,GAAG,CAAC,CAAE,SAAQ,GAAG,CAAC,CAAC,CAAC;IACpE,OAAO,CAAC,KAAK,CAAa;IAC1B,OAAO,CAAC,IAAI,CAAa;IACzB,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,QAAQ,CAAW;gBAEf,MAAM,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,IAAI,EAAE,IAAI,EAAE,MAAM,IAAI,EAAE,OAAO,oCAAwB;IAcpF,YAAY,CAAC,SAAS,EAAE,SAAS,GAAG,IAAI;IAQxC,eAAe,CAAC,SAAS,EAAE,SAAS,EAAE,OAAO,gBAAoB,GAAG,IAAI;CAIlF"}
1
+ {"version":3,"file":"listener.d.ts","sourceRoot":"","sources":["../src/listener.ts"],"names":[],"mappings":"AAAA,OAAO,SAAS,MAAM,gBAAgB,CAAC;AACvC,OAAO,GAAG,MAAM,UAAU,CAAC;AAI3B,MAAM,CAAC,OAAO,OAAO,QAAQ,CAAC,CAAC,CAAE,SAAQ,GAAG,CAAC,CAAC,CAAC;IAC3C,OAAO,CAAC,KAAK,CAAa;IAC1B,OAAO,CAAC,IAAI,CAAa;IACzB,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,QAAQ,CAAW;gBAEf,MAAM,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,IAAI,EAAE,IAAI,EAAE,MAAM,IAAI,EAAE,OAAO,4BAAoB;IAchF,YAAY,CAAC,SAAS,EAAE,SAAS,GAAG,IAAI;IAQxC,eAAe,CAAC,SAAS,EAAE,SAAS,EAAE,OAAO,gBAAoB,GAAG,IAAI;CAIlF"}
package/types/ref.d.ts CHANGED
@@ -1,8 +1,8 @@
1
1
  import Dependency from "./dependency.js";
2
2
  import Tracker from "./tracker.js";
3
- export default class Ref<T extends TBase, TBase = T> extends Tracker<T> implements Dependency<T> {
3
+ export default class Ref<T> extends Tracker<T> implements Dependency<T> {
4
4
  private isEqual;
5
- constructor(_value: T, isEqual?: (v1: TBase, v2: TBase) => boolean);
5
+ constructor(_value: T, isEqual?: (v1: T, v2: T) => boolean);
6
6
  set value(_value: T);
7
7
  get value(): T;
8
8
  }
@@ -1 +1 @@
1
- {"version":3,"file":"ref.d.ts","sourceRoot":"","sources":["../src/ref.ts"],"names":[],"mappings":"AAAA,OAAO,UAAU,MAAM,iBAAiB,CAAC;AACzC,OAAO,OAAO,MAAM,cAAc,CAAC;AAGnC,MAAM,CAAC,OAAO,OAAO,GAAG,CAAC,CAAC,SAAS,KAAK,EAAE,KAAK,GAAG,CAAC,CAAE,SAAQ,OAAO,CAAC,CAAC,CAAE,YAAW,UAAU,CAAC,CAAC,CAAC;IAC5F,OAAO,CAAC,OAAO,CAA+B;gBAElC,MAAM,EAAE,CAAC,EAAE,OAAO,oCAAwB;IAMtD,IAAW,KAAK,CAAC,MAAM,EAAE,CAAC,EAMzB;IAED,IAAW,KAAK,IAAI,CAAC,CAEpB;CACJ"}
1
+ {"version":3,"file":"ref.d.ts","sourceRoot":"","sources":["../src/ref.ts"],"names":[],"mappings":"AAAA,OAAO,UAAU,MAAM,iBAAiB,CAAC;AACzC,OAAO,OAAO,MAAM,cAAc,CAAC;AAGnC,MAAM,CAAC,OAAO,OAAO,GAAG,CAAC,CAAC,CAAE,SAAQ,OAAO,CAAC,CAAC,CAAE,YAAW,UAAU,CAAC,CAAC,CAAC;IACnE,OAAO,CAAC,OAAO,CAA2B;gBAE9B,MAAM,EAAE,CAAC,EAAE,OAAO,4BAAoB;IAMlD,IAAW,KAAK,CAAC,MAAM,EAAE,CAAC,EAMzB;IAED,IAAW,KAAK,IAAI,CAAC,CAEpB;CACJ"}