async-reactivity 2.2.1 → 2.2.3

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
@@ -29,23 +29,28 @@ export default class Computed extends Effect {
29
29
  if (this.state === EffectState.Initial || this.state === EffectState.Scheduled) {
30
30
  this.oldValue = this._value;
31
31
  const newValue = this.run();
32
- if (newValue === InSyncSymbol) {
33
- this.validateDependents();
32
+ if (newValue instanceof Promise) {
33
+ // @ts-expect-error
34
+ this._value = Promise.allSettled([newValue, this.oldValue])
35
+ .then(([newValueResult, oldValueResult]) => {
36
+ const newValue = newValueResult.status === 'fulfilled' ? newValueResult.value : newValueResult.reason;
37
+ const oldValue = oldValueResult.status === 'fulfilled' ? oldValueResult.value : oldValueResult.reason;
38
+ if (newValue === InSyncSymbol) {
39
+ this.validateDependents();
40
+ return oldValue;
41
+ }
42
+ if (this.dependents.size > 0 && newValueResult.status === oldValueResult.status && this.isEqual(newValue, oldValue)) {
43
+ this.validateDependents();
44
+ }
45
+ if (this.state === EffectState.Waiting) {
46
+ this.oldValue = undefined;
47
+ }
48
+ return newValueResult.status === 'fulfilled' ? newValue : Promise.reject(newValue);
49
+ });
34
50
  }
35
51
  else {
36
- if (newValue instanceof Promise) {
37
- // @ts-expect-error
38
- this._value = Promise.all([newValue, this.oldValue])
39
- .then(([newValue, oldValue]) => {
40
- if (newValue === InSyncSymbol) {
41
- this.validateDependents();
42
- return oldValue;
43
- }
44
- if (this.dependents.size > 0 && this.isEqual(newValue, oldValue)) {
45
- this.validateDependents();
46
- }
47
- return newValue;
48
- });
52
+ if (newValue === InSyncSymbol) {
53
+ this.validateDependents();
49
54
  }
50
55
  else {
51
56
  this._value = newValue;
@@ -53,6 +58,7 @@ export default class Computed extends Effect {
53
58
  this.validateDependents();
54
59
  }
55
60
  }
61
+ this.oldValue = undefined;
56
62
  }
57
63
  }
58
64
  return this._value;
@@ -70,6 +70,18 @@ describe('computed', function () {
70
70
  });
71
71
  assert.throws(() => a.value);
72
72
  });
73
+ it('recompute after error', function () {
74
+ const a = new Ref(5);
75
+ const b = new Computed((value) => {
76
+ if (value(a) === 5) {
77
+ throw new Error();
78
+ }
79
+ return value(a);
80
+ });
81
+ assert.throws(() => b.value);
82
+ a.value = 6;
83
+ assert.strictEqual(b.value, 6);
84
+ });
73
85
  it('ignore same ref value', function () {
74
86
  let gate = 0;
75
87
  const a = new Ref(5);
@@ -208,6 +220,22 @@ describe('computed', function () {
208
220
  a.value;
209
221
  assert.strictEqual(await a.value, 5);
210
222
  });
223
+ it('recompute after error', async function () {
224
+ const a = new Ref(5);
225
+ const b = new Computed(async (value) => {
226
+ if (value(a) === 5) {
227
+ throw new Error();
228
+ }
229
+ return value(a);
230
+ });
231
+ try {
232
+ await b.value;
233
+ }
234
+ catch { }
235
+ a.value = 6;
236
+ console.log('invalidate');
237
+ assert.strictEqual(await b.value, 6);
238
+ });
211
239
  it('detect circular dependency', async function () {
212
240
  // @ts-expect-error
213
241
  const a = new Computed(async (value) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "async-reactivity",
3
- "version": "2.2.1",
3
+ "version": "2.2.3",
4
4
  "description": "",
5
5
  "main": "lib/index.js",
6
6
  "types": "types/index.d.ts",
@@ -24,11 +24,11 @@
24
24
  "devDependencies": {
25
25
  "@types/lodash-es": "^4.17.12",
26
26
  "@types/mocha": "^10.0.10",
27
- "@types/node": "^24.11.0",
28
- "mocha": "^11.7.5",
27
+ "@types/node": "^24.13.2",
28
+ "mocha": "^11.7.6",
29
29
  "typescript": "^5.9.3"
30
30
  },
31
31
  "dependencies": {
32
- "lodash-es": "^4.17.23"
32
+ "lodash-es": "^4.18.1"
33
33
  }
34
34
  }
@@ -83,6 +83,20 @@ describe('computed', function () {
83
83
  assert.throws(() => a.value);
84
84
  });
85
85
 
86
+ it('recompute after error', function () {
87
+ const a = new Ref(5);
88
+ const b = new Computed((value) => {
89
+ if (value(a) === 5) {
90
+ throw new Error();
91
+ }
92
+ return value(a);
93
+ });
94
+
95
+ assert.throws(() => b.value);
96
+ a.value = 6;
97
+ assert.strictEqual(b.value, 6);
98
+ });
99
+
86
100
  it('ignore same ref value', function () {
87
101
  let gate = 0;
88
102
  const a = new Ref(5);
@@ -137,7 +151,7 @@ describe('computed', function () {
137
151
  assert.strictEqual(gate, 1);
138
152
  });
139
153
 
140
- it('ignore in sync dependencies', function() {
154
+ it('ignore in sync dependencies', function () {
141
155
  let gate = 0;
142
156
  const a = new Ref(5);
143
157
  const b = new Computed((value) => {
@@ -248,6 +262,23 @@ describe('computed', function () {
248
262
  assert.strictEqual(await a.value, 5);
249
263
  });
250
264
 
265
+ it('recompute after error', async function () {
266
+ const a = new Ref(5);
267
+ const b = new Computed(async (value) => {
268
+ if (value(a) === 5) {
269
+ throw new Error();
270
+ }
271
+ return value(a);
272
+ });
273
+
274
+ try {
275
+ await b.value;
276
+ } catch { }
277
+ a.value = 6;
278
+ console.log('invalidate');
279
+ assert.strictEqual(await b.value, 6);
280
+ });
281
+
251
282
  it('detect circular dependency', async function () {
252
283
  // @ts-expect-error
253
284
  const a = new Computed(async (value) => {
@@ -391,7 +422,7 @@ describe('computed', function () {
391
422
  assert.strictEqual(gate, 1);
392
423
  });
393
424
 
394
- it('ignore in sync dependencies', async function() {
425
+ it('ignore in sync dependencies', async function () {
395
426
  let gate = 0;
396
427
  const a = new Ref(5);
397
428
  const b = new Computed(async (value) => {
package/src/computed.ts CHANGED
@@ -41,28 +41,34 @@ export default class Computed<T> extends Effect implements Dependent, Dependency
41
41
  if (this.state === EffectState.Initial || this.state === EffectState.Scheduled) {
42
42
  this.oldValue = this._value!;
43
43
  const newValue = this.run() as T;
44
- if (newValue === InSyncSymbol) {
45
- this.validateDependents();
44
+ if (newValue instanceof Promise) {
45
+ // @ts-expect-error
46
+ this._value = Promise.allSettled([newValue, this.oldValue])
47
+ .then(([newValueResult, oldValueResult]) => {
48
+ const newValue = newValueResult.status === 'fulfilled' ? newValueResult.value : newValueResult.reason;
49
+ const oldValue = oldValueResult.status === 'fulfilled' ? oldValueResult.value : oldValueResult.reason;
50
+ if (newValue === InSyncSymbol) {
51
+ this.validateDependents();
52
+ return oldValue;
53
+ }
54
+ if (this.dependents.size > 0 && newValueResult.status === oldValueResult.status && this.isEqual(newValue, oldValue)) {
55
+ this.validateDependents();
56
+ }
57
+ if (this.state === EffectState.Waiting) {
58
+ this.oldValue = undefined;
59
+ }
60
+ return newValueResult.status === 'fulfilled' ? newValue : Promise.reject(newValue);
61
+ });
46
62
  } else {
47
- if (newValue instanceof Promise) {
48
- // @ts-expect-error
49
- this._value = Promise.all([newValue, this.oldValue])
50
- .then(([newValue, oldValue]) => {
51
- if (newValue === InSyncSymbol) {
52
- this.validateDependents();
53
- return oldValue;
54
- }
55
- if (this.dependents.size > 0 && this.isEqual(newValue, oldValue)) {
56
- this.validateDependents();
57
- }
58
- return newValue;
59
- });
63
+ if (newValue === InSyncSymbol) {
64
+ this.validateDependents();
60
65
  } else {
61
66
  this._value = newValue;
62
67
  if (this.dependents.size > 0 && this.isEqual(newValue, this.oldValue)) {
63
68
  this.validateDependents();
64
69
  }
65
70
  }
71
+ this.oldValue = undefined;
66
72
  }
67
73
  }
68
74
 
@@ -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,cAAc,MAAM,qBAAqB,CAAC;AAGjD,OAAO,MAAqC,MAAM,aAAa,CAAC;AAEhE,MAAM,CAAC,OAAO,MAAM,UAAU,GAAG,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,UAAU,CAAC,CAAC,CAAC,GAAG,SAAS,KAAK,CAAC,GAAG,SAAS,CAAC,CAAC;AACvI,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;AAI9I,MAAM,CAAC,OAAO,OAAO,QAAQ,CAAC,CAAC,CAAE,SAAQ,MAAO,YAAW,SAAS,EAAE,UAAU,CAAC,CAAC,CAAC;IAC/E,OAAO,CAAC,QAAQ,CAAC,CAAI;IACrB,OAAO,CAAC,MAAM,CAAC,CAAI;IACnB,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC;IACvB,OAAO,EAAE,OAAO,cAAc,CAAC,CAAC,CAAC,CAAC;IAClC,OAAO,CAAC,UAAU,CAAwB;IAC1C,OAAO,CAAC,QAAQ,CAAC,CAAW;gBAEhB,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,EAAE,OAAO,4BAAoB,EAAE,UAAU,CAAC,EAAE,MAAM;IAkBpF,IAAW,KAAK,IAAI,CAAC,CA8BpB;IAED,OAAO,CAAC,kBAAkB;IAMnB,YAAY,CAAC,SAAS,EAAE,SAAS;IAOjC,eAAe,CAAC,SAAS,EAAE,SAAS,EAAE,OAAO,gBAAoB,GAAG,IAAI;IAKxE,UAAU,CAAC,UAAU,CAAC,EAAE,UAAU,CAAC,OAAO,CAAC;IAW3C,eAAe;IAaf,KAAK;IAKL,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,cAAc,MAAM,qBAAqB,CAAC;AAGjD,OAAO,MAAqC,MAAM,aAAa,CAAC;AAEhE,MAAM,CAAC,OAAO,MAAM,UAAU,GAAG,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,UAAU,CAAC,CAAC,CAAC,GAAG,SAAS,KAAK,CAAC,GAAG,SAAS,CAAC,CAAC;AACvI,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;AAI9I,MAAM,CAAC,OAAO,OAAO,QAAQ,CAAC,CAAC,CAAE,SAAQ,MAAO,YAAW,SAAS,EAAE,UAAU,CAAC,CAAC,CAAC;IAC/E,OAAO,CAAC,QAAQ,CAAC,CAAI;IACrB,OAAO,CAAC,MAAM,CAAC,CAAI;IACnB,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC;IACvB,OAAO,EAAE,OAAO,cAAc,CAAC,CAAC,CAAC,CAAC;IAClC,OAAO,CAAC,UAAU,CAAwB;IAC1C,OAAO,CAAC,QAAQ,CAAC,CAAW;gBAEhB,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,EAAE,OAAO,4BAAoB,EAAE,UAAU,CAAC,EAAE,MAAM;IAkBpF,IAAW,KAAK,IAAI,CAAC,CAoCpB;IAED,OAAO,CAAC,kBAAkB;IAMnB,YAAY,CAAC,SAAS,EAAE,SAAS;IAOjC,eAAe,CAAC,SAAS,EAAE,SAAS,EAAE,OAAO,gBAAoB,GAAG,IAAI;IAKxE,UAAU,CAAC,UAAU,CAAC,EAAE,UAAU,CAAC,OAAO,CAAC;IAW3C,eAAe;IAaf,KAAK;IAKL,OAAO;CAGjB"}