@praxisjs/core 1.0.0 → 1.2.0

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 (65) hide show
  1. package/CHANGELOG.md +41 -0
  2. package/dist/__tests__/batch.test.js +47 -0
  3. package/dist/__tests__/batch.test.js.map +1 -1
  4. package/dist/__tests__/computed.test.js +48 -0
  5. package/dist/__tests__/computed.test.js.map +1 -1
  6. package/dist/__tests__/effect.test.js +39 -1
  7. package/dist/__tests__/effect.test.js.map +1 -1
  8. package/dist/__tests__/persisted-signal.test.js +34 -0
  9. package/dist/__tests__/persisted-signal.test.js.map +1 -1
  10. package/dist/__tests__/reactive.test.js +51 -0
  11. package/dist/__tests__/reactive.test.js.map +1 -1
  12. package/dist/__tests__/resource.test.js +43 -0
  13. package/dist/__tests__/resource.test.js.map +1 -1
  14. package/dist/__tests__/signal.test.js +29 -0
  15. package/dist/__tests__/signal.test.js.map +1 -1
  16. package/dist/async/resource.d.ts.map +1 -1
  17. package/dist/async/resource.js +15 -2
  18. package/dist/async/resource.js.map +1 -1
  19. package/dist/index.d.ts +1 -0
  20. package/dist/index.d.ts.map +1 -1
  21. package/dist/index.js +1 -0
  22. package/dist/index.js.map +1 -1
  23. package/dist/internal.d.ts +1 -1
  24. package/dist/internal.d.ts.map +1 -1
  25. package/dist/internal.js +1 -1
  26. package/dist/internal.js.map +1 -1
  27. package/dist/reactive/reactive.d.ts +3 -1
  28. package/dist/reactive/reactive.d.ts.map +1 -1
  29. package/dist/reactive/reactive.js +10 -2
  30. package/dist/reactive/reactive.js.map +1 -1
  31. package/dist/signal/batch.d.ts +3 -0
  32. package/dist/signal/batch.d.ts.map +1 -1
  33. package/dist/signal/batch.js +15 -4
  34. package/dist/signal/batch.js.map +1 -1
  35. package/dist/signal/computed.d.ts.map +1 -1
  36. package/dist/signal/computed.js +7 -3
  37. package/dist/signal/computed.js.map +1 -1
  38. package/dist/signal/effect.d.ts +1 -0
  39. package/dist/signal/effect.d.ts.map +1 -1
  40. package/dist/signal/effect.js +10 -0
  41. package/dist/signal/effect.js.map +1 -1
  42. package/dist/signal/index.d.ts +1 -1
  43. package/dist/signal/index.d.ts.map +1 -1
  44. package/dist/signal/index.js +1 -1
  45. package/dist/signal/index.js.map +1 -1
  46. package/dist/signal/signal.d.ts.map +1 -1
  47. package/dist/signal/signal.js +14 -1
  48. package/dist/signal/signal.js.map +1 -1
  49. package/package.json +1 -1
  50. package/src/__tests__/batch.test.ts +59 -1
  51. package/src/__tests__/computed.test.ts +50 -0
  52. package/src/__tests__/effect.test.ts +43 -1
  53. package/src/__tests__/persisted-signal.test.ts +43 -0
  54. package/src/__tests__/reactive.test.ts +59 -0
  55. package/src/__tests__/resource.test.ts +55 -0
  56. package/src/__tests__/signal.test.ts +31 -0
  57. package/src/async/resource.ts +13 -2
  58. package/src/index.ts +1 -0
  59. package/src/internal.ts +1 -0
  60. package/src/reactive/reactive.ts +11 -2
  61. package/src/signal/batch.ts +17 -4
  62. package/src/signal/computed.ts +6 -3
  63. package/src/signal/effect.ts +10 -0
  64. package/src/signal/index.ts +1 -1
  65. package/src/signal/signal.ts +12 -1
@@ -27,11 +27,24 @@ export function resource(fetcher, options = {}) {
27
27
  });
28
28
  }
29
29
  function execute() {
30
- _execute(fetcher());
30
+ try {
31
+ _execute(fetcher());
32
+ }
33
+ catch (err) {
34
+ _runId++;
35
+ _error.set(err instanceof Error ? err : new Error(String(err)));
36
+ _status.set("error");
37
+ }
31
38
  }
32
39
  if (immediate) {
33
40
  effect(() => {
34
- _execute(fetcher());
41
+ try {
42
+ _execute(fetcher());
43
+ }
44
+ catch (err) {
45
+ _error.set(err instanceof Error ? err : new Error(String(err)));
46
+ _status.set("error");
47
+ }
35
48
  });
36
49
  }
37
50
  return {
@@ -1 +1 @@
1
- {"version":3,"file":"resource.js","sourceRoot":"","sources":["../../src/async/resource.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"resource.js","sourceRoot":"","sources":["../../src/async/resource.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1,2 +1,3 @@
1
1
  export { StatefulComponent, StatelessComponent, Composable } from "./component";
2
+ export { peek, untrack } from "./signal";
2
3
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAChF,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC"}
package/dist/index.js CHANGED
@@ -1,2 +1,3 @@
1
1
  export { StatefulComponent, StatelessComponent, Composable } from "./component";
2
+ export { peek, untrack } from "./signal";
2
3
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAChF,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC"}
@@ -1,5 +1,5 @@
1
1
  export { debounced, until, when, history, type HistoryElement, } from "./reactive";
2
- export { signal, persistedSignal, peek, computed, batch, effect, type PersistedSignalOptions, } from "./signal";
2
+ export { signal, persistedSignal, peek, computed, batch, effect, untrack, type PersistedSignalOptions, } from "./signal";
3
3
  export { RootComponent } from "./component";
4
4
  export { resource, createResource, type ResourceStatus, type Resource, type ResourceOptions, } from "./async/resource";
5
5
  //# sourceMappingURL=internal.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"internal.d.ts","sourceRoot":"","sources":["../src/internal.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,SAAS,EACT,KAAK,EACL,IAAI,EACJ,OAAO,EACP,KAAK,cAAc,GACpB,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,MAAM,EACN,eAAe,EACf,IAAI,EACJ,QAAQ,EACR,KAAK,EACL,MAAM,EACN,KAAK,sBAAsB,GAC5B,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EACL,QAAQ,EACR,cAAc,EACd,KAAK,cAAc,EACnB,KAAK,QAAQ,EACb,KAAK,eAAe,GACrB,MAAM,kBAAkB,CAAC"}
1
+ {"version":3,"file":"internal.d.ts","sourceRoot":"","sources":["../src/internal.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,SAAS,EACT,KAAK,EACL,IAAI,EACJ,OAAO,EACP,KAAK,cAAc,GACpB,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,MAAM,EACN,eAAe,EACf,IAAI,EACJ,QAAQ,EACR,KAAK,EACL,MAAM,EACN,OAAO,EACP,KAAK,sBAAsB,GAC5B,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EACL,QAAQ,EACR,cAAc,EACd,KAAK,cAAc,EACnB,KAAK,QAAQ,EACb,KAAK,eAAe,GACrB,MAAM,kBAAkB,CAAC"}
package/dist/internal.js CHANGED
@@ -1,5 +1,5 @@
1
1
  export { debounced, until, when, history, } from "./reactive";
2
- export { signal, persistedSignal, peek, computed, batch, effect, } from "./signal";
2
+ export { signal, persistedSignal, peek, computed, batch, effect, untrack, } from "./signal";
3
3
  export { RootComponent } from "./component";
4
4
  export { resource, createResource, } from "./async/resource";
5
5
  //# sourceMappingURL=internal.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"internal.js","sourceRoot":"","sources":["../src/internal.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,SAAS,EACT,KAAK,EACL,IAAI,EACJ,OAAO,GAER,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,MAAM,EACN,eAAe,EACf,IAAI,EACJ,QAAQ,EACR,KAAK,EACL,MAAM,GAEP,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EACL,QAAQ,EACR,cAAc,GAIf,MAAM,kBAAkB,CAAC"}
1
+ {"version":3,"file":"internal.js","sourceRoot":"","sources":["../src/internal.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,SAAS,EACT,KAAK,EACL,IAAI,EACJ,OAAO,GAER,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,MAAM,EACN,eAAe,EACf,IAAI,EACJ,QAAQ,EACR,KAAK,EACL,MAAM,EACN,OAAO,GAER,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EACL,QAAQ,EACR,cAAc,GAIf,MAAM,kBAAkB,CAAC"}
@@ -1,5 +1,7 @@
1
1
  import type { Computed, Signal } from "@praxisjs/shared";
2
2
  export declare function when<T>(source: Signal<T> | Computed<T>, fn: (value: NonNullable<T>) => void): () => void;
3
3
  export declare function until<T>(source: Signal<T> | Computed<T>): Promise<NonNullable<T>>;
4
- export declare function debounced<T>(source: Signal<T> | Computed<T>, ms: number): Signal<T>;
4
+ export declare function debounced<T>(source: Signal<T> | Computed<T>, ms: number): Signal<T> & {
5
+ stop: () => void;
6
+ };
5
7
  //# sourceMappingURL=reactive.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"reactive.d.ts","sourceRoot":"","sources":["../../src/reactive/reactive.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAKzD,wBAAgB,IAAI,CAAC,CAAC,EACpB,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,EAC/B,EAAE,EAAE,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC,CAAC,KAAK,IAAI,cAsBpC;AAED,wBAAgB,KAAK,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,2BAQvD;AAED,wBAAgB,SAAS,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,aAcvE"}
1
+ {"version":3,"file":"reactive.d.ts","sourceRoot":"","sources":["../../src/reactive/reactive.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAKzD,wBAAgB,IAAI,CAAC,CAAC,EACpB,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,EAC/B,EAAE,EAAE,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC,CAAC,KAAK,IAAI,cAsBpC;AAED,wBAAgB,KAAK,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,2BAQvD;AAED,wBAAgB,SAAS,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM;UAmBf,MAAM,IAAI;EAIlE"}
@@ -30,7 +30,7 @@ export function until(source) {
30
30
  export function debounced(source, ms) {
31
31
  const current = signal(source());
32
32
  let timeout;
33
- effect(() => {
33
+ const stop = effect(() => {
34
34
  const value = source();
35
35
  if (timeout)
36
36
  clearTimeout(timeout);
@@ -38,7 +38,15 @@ export function debounced(source, ms) {
38
38
  current.set(value);
39
39
  timeout = undefined;
40
40
  }, ms);
41
+ return () => {
42
+ if (timeout) {
43
+ clearTimeout(timeout);
44
+ timeout = undefined;
45
+ }
46
+ };
41
47
  });
42
- return current;
48
+ const debouncedSignal = current;
49
+ debouncedSignal.stop = stop;
50
+ return debouncedSignal;
43
51
  }
44
52
  //# sourceMappingURL=reactive.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"reactive.js","sourceRoot":"","sources":["../../src/reactive/reactive.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AACnC,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAE1C,MAAM,UAAU,IAAI,CAClB,MAA+B,EAC/B,EAAmC;IAEnC,IAAI,QAAQ,GAAG,KAAK,CAAC;IACrB,MAAM,GAAG,GAAG,EAAE,MAAM,EAAE,SAAqC,EAAE,CAAC;IAE9D,MAAM,IAAI,GAAG,MAAM,CAAC,GAAG,EAAE;QACvB,MAAM,KAAK,GAAG,MAAM,EAAE,CAAC;QACvB,IAAI,CAAC,KAAK,IAAI,QAAQ;YAAE,OAAO;QAE/B,QAAQ,GAAG,IAAI,CAAC;QAChB,GAAG,CAAC,MAAM,EAAE,EAAE,CAAC;QACf,EAAE,CAAC,KAAK,CAAC,CAAC;IACZ,CAAC,CAAC,CAAC;IAEH,GAAG,CAAC,MAAM,GAAG,IAAI,CAAC;IAElB,0EAA0E;IAC1E,0EAA0E;IAC1E,uEAAuE;IACvE,IAAI,QAAQ;QAAE,IAAI,EAAE,CAAC;IAErB,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,KAAK,CAAI,MAA+B;IACtD,OAAO,IAAI,OAAO,CAAiB,CAAC,OAAO,EAAE,EAAE;QAC7C,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE;YAClC,OAAO,CAAC,KAAK,CAAC,CAAC;QACjB,CAAC,CAAC,CAAC;QAEH,KAAK,IAAI,CAAC;IACZ,CAAC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,SAAS,CAAI,MAA+B,EAAE,EAAU;IACtE,MAAM,OAAO,GAAG,MAAM,CAAI,MAAM,EAAE,CAAC,CAAC;IACpC,IAAI,OAAkD,CAAC;IAEvD,MAAM,CAAC,GAAG,EAAE;QACV,MAAM,KAAK,GAAG,MAAM,EAAE,CAAC;QACvB,IAAI,OAAO;YAAE,YAAY,CAAC,OAAO,CAAC,CAAC;QACnC,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE;YACxB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;YACnB,OAAO,GAAG,SAAS,CAAC;QACtB,CAAC,EAAE,EAAE,CAAC,CAAC;IACT,CAAC,CAAC,CAAC;IAEH,OAAO,OAAO,CAAC;AACjB,CAAC"}
1
+ {"version":3,"file":"reactive.js","sourceRoot":"","sources":["../../src/reactive/reactive.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AACnC,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAE1C,MAAM,UAAU,IAAI,CAClB,MAA+B,EAC/B,EAAmC;IAEnC,IAAI,QAAQ,GAAG,KAAK,CAAC;IACrB,MAAM,GAAG,GAAG,EAAE,MAAM,EAAE,SAAqC,EAAE,CAAC;IAE9D,MAAM,IAAI,GAAG,MAAM,CAAC,GAAG,EAAE;QACvB,MAAM,KAAK,GAAG,MAAM,EAAE,CAAC;QACvB,IAAI,CAAC,KAAK,IAAI,QAAQ;YAAE,OAAO;QAE/B,QAAQ,GAAG,IAAI,CAAC;QAChB,GAAG,CAAC,MAAM,EAAE,EAAE,CAAC;QACf,EAAE,CAAC,KAAK,CAAC,CAAC;IACZ,CAAC,CAAC,CAAC;IAEH,GAAG,CAAC,MAAM,GAAG,IAAI,CAAC;IAElB,0EAA0E;IAC1E,0EAA0E;IAC1E,uEAAuE;IACvE,IAAI,QAAQ;QAAE,IAAI,EAAE,CAAC;IAErB,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,KAAK,CAAI,MAA+B;IACtD,OAAO,IAAI,OAAO,CAAiB,CAAC,OAAO,EAAE,EAAE;QAC7C,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE;YAClC,OAAO,CAAC,KAAK,CAAC,CAAC;QACjB,CAAC,CAAC,CAAC;QAEH,KAAK,IAAI,CAAC;IACZ,CAAC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,SAAS,CAAI,MAA+B,EAAE,EAAU;IACtE,MAAM,OAAO,GAAG,MAAM,CAAI,MAAM,EAAE,CAAC,CAAC;IACpC,IAAI,OAAkD,CAAC;IAEvD,MAAM,IAAI,GAAG,MAAM,CAAC,GAAG,EAAE;QACvB,MAAM,KAAK,GAAG,MAAM,EAAE,CAAC;QACvB,IAAI,OAAO;YAAE,YAAY,CAAC,OAAO,CAAC,CAAC;QACnC,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE;YACxB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;YACnB,OAAO,GAAG,SAAS,CAAC;QACtB,CAAC,EAAE,EAAE,CAAC,CAAC;QACP,OAAO,GAAG,EAAE;YACV,IAAI,OAAO,EAAE,CAAC;gBACZ,YAAY,CAAC,OAAO,CAAC,CAAC;gBACtB,OAAO,GAAG,SAAS,CAAC;YACtB,CAAC;QACH,CAAC,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,MAAM,eAAe,GAAG,OAA2C,CAAC;IACpE,eAAe,CAAC,IAAI,GAAG,IAAI,CAAC;IAE5B,OAAO,eAAe,CAAC;AACzB,CAAC"}
@@ -1,2 +1,5 @@
1
+ import type { Effect } from "./effect";
2
+ export declare function isBatching(): boolean;
3
+ export declare function enqueueEffect(effect: Effect): void;
1
4
  export declare function batch(fn: () => void): void;
2
5
  //# sourceMappingURL=batch.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"batch.d.ts","sourceRoot":"","sources":["../../src/signal/batch.ts"],"names":[],"mappings":"AAIA,wBAAgB,KAAK,CAAC,EAAE,EAAE,MAAM,IAAI,QASnC"}
1
+ {"version":3,"file":"batch.d.ts","sourceRoot":"","sources":["../../src/signal/batch.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAIvC,wBAAgB,UAAU,IAAI,OAAO,CAEpC;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAElD;AAED,wBAAgB,KAAK,CAAC,EAAE,EAAE,MAAM,IAAI,QAcnC"}
@@ -1,13 +1,24 @@
1
1
  let batchQueue = null;
2
+ export function isBatching() {
3
+ return batchQueue !== null;
4
+ }
5
+ export function enqueueEffect(effect) {
6
+ batchQueue?.add(effect);
7
+ }
2
8
  export function batch(fn) {
3
- batchQueue = new Set();
9
+ const isOuter = batchQueue === null;
10
+ if (isOuter) {
11
+ batchQueue = new Set();
12
+ }
4
13
  try {
5
14
  fn();
6
15
  }
7
16
  finally {
8
- const effectsToRun = batchQueue;
9
- batchQueue = null;
10
- effectsToRun.forEach((eff) => { eff(); });
17
+ if (isOuter) {
18
+ const effectsToRun = batchQueue ?? new Set();
19
+ batchQueue = null;
20
+ effectsToRun.forEach((eff) => { eff(); });
21
+ }
11
22
  }
12
23
  }
13
24
  //# sourceMappingURL=batch.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"batch.js","sourceRoot":"","sources":["../../src/signal/batch.ts"],"names":[],"mappings":"AAEA,IAAI,UAAU,GAAuB,IAAI,CAAC;AAE1C,MAAM,UAAU,KAAK,CAAC,EAAc;IAClC,UAAU,GAAG,IAAI,GAAG,EAAE,CAAC;IACvB,IAAI,CAAC;QACH,EAAE,EAAE,CAAC;IACP,CAAC;YAAS,CAAC;QACT,MAAM,YAAY,GAAG,UAAU,CAAC;QAChC,UAAU,GAAG,IAAI,CAAC;QAClB,YAAY,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,EAAE,GAAG,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IAC5C,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"batch.js","sourceRoot":"","sources":["../../src/signal/batch.ts"],"names":[],"mappings":"AAEA,IAAI,UAAU,GAAuB,IAAI,CAAC;AAE1C,MAAM,UAAU,UAAU;IACxB,OAAO,UAAU,KAAK,IAAI,CAAC;AAC7B,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,MAAc;IAC1C,UAAU,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;AAC1B,CAAC;AAED,MAAM,UAAU,KAAK,CAAC,EAAc;IAClC,MAAM,OAAO,GAAG,UAAU,KAAK,IAAI,CAAC;IACpC,IAAI,OAAO,EAAE,CAAC;QACZ,UAAU,GAAG,IAAI,GAAG,EAAE,CAAC;IACzB,CAAC;IACD,IAAI,CAAC;QACH,EAAE,EAAE,CAAC;IACP,CAAC;YAAS,CAAC;QACT,IAAI,OAAO,EAAE,CAAC;YACZ,MAAM,YAAY,GAAG,UAAU,IAAI,IAAI,GAAG,EAAU,CAAC;YACrD,UAAU,GAAG,IAAI,CAAC;YAClB,YAAY,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,EAAE,GAAG,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QAC5C,CAAC;IACH,CAAC;AACH,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"computed.d.ts","sourceRoot":"","sources":["../../src/signal/computed.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAIjD,wBAAgB,QAAQ,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CA0C3D"}
1
+ {"version":3,"file":"computed.d.ts","sourceRoot":"","sources":["../../src/signal/computed.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAIjD,wBAAgB,QAAQ,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CA6C3D"}
@@ -16,9 +16,13 @@ export function computed(computeFn) {
16
16
  if (dirty) {
17
17
  const prevEffect = activeEffect;
18
18
  runEffect(recompute);
19
- cachedValue = computeFn();
20
- dirty = false;
21
- runEffect(prevEffect);
19
+ try {
20
+ cachedValue = computeFn();
21
+ dirty = false;
22
+ }
23
+ finally {
24
+ runEffect(prevEffect);
25
+ }
22
26
  }
23
27
  return cachedValue;
24
28
  }
@@ -1 +1 @@
1
- {"version":3,"file":"computed.js","sourceRoot":"","sources":["../../src/signal/computed.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,SAAS,EAAe,MAAM,UAAU,CAAC;AAEhE,MAAM,UAAU,QAAQ,CAAI,SAAkB;IAC5C,IAAI,WAAc,CAAC;IACnB,IAAI,KAAK,GAAG,IAAI,CAAC;IACjB,MAAM,WAAW,GAAG,IAAI,GAAG,EAAU,CAAC;IAEtC,MAAM,SAAS,GAAG,GAAG,EAAE;QACrB,KAAK,GAAG,IAAI,CAAC;QACb,CAAC,GAAG,WAAW,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,EAAE;YAC/B,GAAG,EAAE,CAAC;QACR,CAAC,CAAC,CAAC;IACL,CAAC,CAAC;IAEF,SAAS,IAAI;QACX,IAAI,YAAY,EAAE,CAAC;YACjB,WAAW,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;QAChC,CAAC;QAED,IAAI,KAAK,EAAE,CAAC;YACV,MAAM,UAAU,GAAG,YAAY,CAAC;YAChC,SAAS,CAAC,SAAS,CAAC,CAAC;YACrB,WAAW,GAAG,SAAS,EAAE,CAAC;YAC1B,KAAK,GAAG,KAAK,CAAC;YACd,SAAS,CAAC,UAAU,CAAC,CAAC;QACxB,CAAC;QAED,OAAO,WAAW,CAAC;IACrB,CAAC;IAED,SAAS,SAAS,CAAC,EAAsB;QACvC,MAAM,aAAa,GAAG,GAAG,EAAE;YACzB,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC;QACb,CAAC,CAAC;QACF,WAAW,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;QAC/B,aAAa,EAAE,CAAC;QAChB,OAAO,GAAG,EAAE,CAAC,WAAW,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;IACjD,CAAC;IAED,MAAM,cAAc,GAAG,IAAmB,CAAC;IAC3C,cAAc,CAAC,SAAS,GAAG,SAAS,CAAC;IACrC,cAAc,CAAC,YAAY,GAAG,IAAI,CAAC;IAEnC,OAAO,cAAc,CAAC;AACxB,CAAC"}
1
+ {"version":3,"file":"computed.js","sourceRoot":"","sources":["../../src/signal/computed.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,SAAS,EAAe,MAAM,UAAU,CAAC;AAEhE,MAAM,UAAU,QAAQ,CAAI,SAAkB;IAC5C,IAAI,WAAc,CAAC;IACnB,IAAI,KAAK,GAAG,IAAI,CAAC;IACjB,MAAM,WAAW,GAAG,IAAI,GAAG,EAAU,CAAC;IAEtC,MAAM,SAAS,GAAG,GAAG,EAAE;QACrB,KAAK,GAAG,IAAI,CAAC;QACb,CAAC,GAAG,WAAW,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,EAAE;YAC/B,GAAG,EAAE,CAAC;QACR,CAAC,CAAC,CAAC;IACL,CAAC,CAAC;IAEF,SAAS,IAAI;QACX,IAAI,YAAY,EAAE,CAAC;YACjB,WAAW,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;QAChC,CAAC;QAED,IAAI,KAAK,EAAE,CAAC;YACV,MAAM,UAAU,GAAG,YAAY,CAAC;YAChC,SAAS,CAAC,SAAS,CAAC,CAAC;YACrB,IAAI,CAAC;gBACH,WAAW,GAAG,SAAS,EAAE,CAAC;gBAC1B,KAAK,GAAG,KAAK,CAAC;YAChB,CAAC;oBAAS,CAAC;gBACT,SAAS,CAAC,UAAU,CAAC,CAAC;YACxB,CAAC;QACH,CAAC;QAED,OAAO,WAAW,CAAC;IACrB,CAAC;IAED,SAAS,SAAS,CAAC,EAAsB;QACvC,MAAM,aAAa,GAAG,GAAG,EAAE;YACzB,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC;QACb,CAAC,CAAC;QACF,WAAW,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;QAC/B,aAAa,EAAE,CAAC;QAChB,OAAO,GAAG,EAAE,CAAC,WAAW,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;IACjD,CAAC;IAED,MAAM,cAAc,GAAG,IAAmB,CAAC;IAC3C,cAAc,CAAC,SAAS,GAAG,SAAS,CAAC;IACrC,cAAc,CAAC,YAAY,GAAG,IAAI,CAAC;IAEnC,OAAO,cAAc,CAAC;AACxB,CAAC"}
@@ -2,6 +2,7 @@ export type Effect = () => void;
2
2
  export declare let activeEffect: Effect | null;
3
3
  export declare function track(effect: Effect): void;
4
4
  export declare function runEffect(effect: Effect | null): void;
5
+ export declare function untrack<T>(fn: () => T): T;
5
6
  type Cleanup = (() => void) | void;
6
7
  export declare function effect(fn: () => Cleanup): () => void;
7
8
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"effect.d.ts","sourceRoot":"","sources":["../../src/signal/effect.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC;AAEhC,eAAO,IAAI,YAAY,EAAE,MAAM,GAAG,IAAW,CAAC;AAG9C,wBAAgB,KAAK,CAAC,MAAM,EAAE,MAAM,QAUnC;AAED,wBAAgB,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,QAE9C;AAGD,KAAK,OAAO,GAAG,CAAC,MAAM,IAAI,CAAC,GAAG,IAAI,CAAC;AAEnC,wBAAgB,MAAM,CAAC,EAAE,EAAE,MAAM,OAAO,cAuBvC"}
1
+ {"version":3,"file":"effect.d.ts","sourceRoot":"","sources":["../../src/signal/effect.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC;AAEhC,eAAO,IAAI,YAAY,EAAE,MAAM,GAAG,IAAW,CAAC;AAG9C,wBAAgB,KAAK,CAAC,MAAM,EAAE,MAAM,QAUnC;AAED,wBAAgB,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,QAE9C;AAED,wBAAgB,OAAO,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,CAQzC;AAGD,KAAK,OAAO,GAAG,CAAC,MAAM,IAAI,CAAC,GAAG,IAAI,CAAC;AAEnC,wBAAgB,MAAM,CAAC,EAAE,EAAE,MAAM,OAAO,cAuBvC"}
@@ -15,6 +15,16 @@ export function track(effect) {
15
15
  export function runEffect(effect) {
16
16
  activeEffect = effect;
17
17
  }
18
+ export function untrack(fn) {
19
+ const prev = activeEffect;
20
+ activeEffect = null;
21
+ try {
22
+ return fn();
23
+ }
24
+ finally {
25
+ activeEffect = prev;
26
+ }
27
+ }
18
28
  export function effect(fn) {
19
29
  let cleanup;
20
30
  let stopped = false;
@@ -1 +1 @@
1
- {"version":3,"file":"effect.js","sourceRoot":"","sources":["../../src/signal/effect.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,IAAI,YAAY,GAAkB,IAAI,CAAC;AAC9C,MAAM,WAAW,GAAa,EAAE,CAAC;AAEjC,MAAM,UAAU,KAAK,CAAC,MAAc;IAClC,MAAM,UAAU,GAAG,MAAM,CAAC;IAC1B,WAAW,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAC7B,YAAY,GAAG,UAAU,CAAC;IAC1B,IAAI,CAAC;QACH,UAAU,EAAE,CAAC;IACf,CAAC;YAAS,CAAC;QACT,WAAW,CAAC,GAAG,EAAE,CAAC;QAClB,YAAY,GAAG,WAAW,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC,CAAC,IAAI,IAAI,CAAC;IAC7D,CAAC;AACH,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,MAAqB;IAC7C,YAAY,GAAG,MAAM,CAAC;AACxB,CAAC;AAKD,MAAM,UAAU,MAAM,CAAC,EAAiB;IACtC,IAAI,OAAgB,CAAC;IACrB,IAAI,OAAO,GAAG,KAAK,CAAC;IAEpB,MAAM,aAAa,GAAG,GAAG,EAAE;QACzB,IAAI,OAAO;YAAE,OAAO;QACpB,OAAO,EAAE,EAAE,CAAC;QACZ,MAAM,UAAU,GAAG,YAAY,CAAC;QAChC,YAAY,GAAG,aAAa,CAAC;QAC7B,IAAI,CAAC;YACH,OAAO,GAAG,EAAE,EAAE,CAAC;QACjB,CAAC;gBAAS,CAAC;YACT,YAAY,GAAG,UAAU,CAAC;QAC5B,CAAC;IACH,CAAC,CAAC;IAEF,aAAa,EAAE,CAAC;IAEhB,OAAO,GAAG,EAAE;QACV,OAAO,GAAG,IAAI,CAAC;QACf,OAAO,EAAE,EAAE,CAAC;QACZ,OAAO,GAAG,SAAS,CAAC;IACtB,CAAC,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"effect.js","sourceRoot":"","sources":["../../src/signal/effect.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,IAAI,YAAY,GAAkB,IAAI,CAAC;AAC9C,MAAM,WAAW,GAAa,EAAE,CAAC;AAEjC,MAAM,UAAU,KAAK,CAAC,MAAc;IAClC,MAAM,UAAU,GAAG,MAAM,CAAC;IAC1B,WAAW,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAC7B,YAAY,GAAG,UAAU,CAAC;IAC1B,IAAI,CAAC;QACH,UAAU,EAAE,CAAC;IACf,CAAC;YAAS,CAAC;QACT,WAAW,CAAC,GAAG,EAAE,CAAC;QAClB,YAAY,GAAG,WAAW,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC,CAAC,IAAI,IAAI,CAAC;IAC7D,CAAC;AACH,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,MAAqB;IAC7C,YAAY,GAAG,MAAM,CAAC;AACxB,CAAC;AAED,MAAM,UAAU,OAAO,CAAI,EAAW;IACpC,MAAM,IAAI,GAAG,YAAY,CAAC;IAC1B,YAAY,GAAG,IAAI,CAAC;IACpB,IAAI,CAAC;QACH,OAAO,EAAE,EAAE,CAAC;IACd,CAAC;YAAS,CAAC;QACT,YAAY,GAAG,IAAI,CAAC;IACtB,CAAC;AACH,CAAC;AAKD,MAAM,UAAU,MAAM,CAAC,EAAiB;IACtC,IAAI,OAAgB,CAAC;IACrB,IAAI,OAAO,GAAG,KAAK,CAAC;IAEpB,MAAM,aAAa,GAAG,GAAG,EAAE;QACzB,IAAI,OAAO;YAAE,OAAO;QACpB,OAAO,EAAE,EAAE,CAAC;QACZ,MAAM,UAAU,GAAG,YAAY,CAAC;QAChC,YAAY,GAAG,aAAa,CAAC;QAC7B,IAAI,CAAC;YACH,OAAO,GAAG,EAAE,EAAE,CAAC;QACjB,CAAC;gBAAS,CAAC;YACT,YAAY,GAAG,UAAU,CAAC;QAC5B,CAAC;IACH,CAAC,CAAC;IAEF,aAAa,EAAE,CAAC;IAEhB,OAAO,GAAG,EAAE;QACV,OAAO,GAAG,IAAI,CAAC;QACf,OAAO,EAAE,EAAE,CAAC;QACZ,OAAO,GAAG,SAAS,CAAC;IACtB,CAAC,CAAC;AACJ,CAAC"}
@@ -3,5 +3,5 @@ export { peek } from "./peek";
3
3
  export { signal } from "./signal";
4
4
  export { computed } from "./computed";
5
5
  export { type PersistedSignalOptions, persistedSignal } from "./persisted";
6
- export { effect } from "./effect";
6
+ export { effect, untrack } from "./effect";
7
7
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/signal/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAChC,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAC9B,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,KAAK,sBAAsB,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC3E,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/signal/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAChC,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAC9B,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,KAAK,sBAAsB,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC3E,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC"}
@@ -3,5 +3,5 @@ export { peek } from "./peek";
3
3
  export { signal } from "./signal";
4
4
  export { computed } from "./computed";
5
5
  export { persistedSignal } from "./persisted";
6
- export { effect } from "./effect";
6
+ export { effect, untrack } from "./effect";
7
7
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/signal/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAChC,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAC9B,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAA+B,eAAe,EAAE,MAAM,aAAa,CAAC;AAC3E,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/signal/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAChC,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAC9B,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAA+B,eAAe,EAAE,MAAM,aAAa,CAAC;AAC3E,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"signal.d.ts","sourceRoot":"","sources":["../../src/signal/signal.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAI/C,wBAAgB,MAAM,CAAC,CAAC,EAAE,YAAY,EAAE,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAuCpD"}
1
+ {"version":3,"file":"signal.d.ts","sourceRoot":"","sources":["../../src/signal/signal.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAK/C,wBAAgB,MAAM,CAAC,CAAC,EAAE,YAAY,EAAE,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAiDpD"}
@@ -1,3 +1,4 @@
1
+ import { isBatching, enqueueEffect } from "./batch";
1
2
  import { activeEffect } from "./effect";
2
3
  export function signal(initialValue) {
3
4
  let value = initialValue;
@@ -12,9 +13,21 @@ export function signal(initialValue) {
12
13
  if (Object.is(value, newValue))
13
14
  return;
14
15
  value = newValue;
16
+ if (isBatching()) {
17
+ [...subscribers].forEach((sub) => { enqueueEffect(sub); });
18
+ return;
19
+ }
20
+ const errors = [];
15
21
  [...subscribers].forEach((sub) => {
16
- sub();
22
+ try {
23
+ sub();
24
+ }
25
+ catch (e) {
26
+ errors.push(e);
27
+ }
17
28
  });
29
+ if (errors.length > 0)
30
+ throw errors[errors.length - 1];
18
31
  }
19
32
  function update(fn) {
20
33
  set(fn(value));
@@ -1 +1 @@
1
- {"version":3,"file":"signal.js","sourceRoot":"","sources":["../../src/signal/signal.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAe,MAAM,UAAU,CAAC;AAErD,MAAM,UAAU,MAAM,CAAI,YAAe;IACvC,IAAI,KAAK,GAAG,YAAY,CAAC;IACzB,MAAM,WAAW,GAAG,IAAI,GAAG,EAAU,CAAC;IAEtC,SAAS,IAAI;QACX,IAAI,YAAY,EAAE,CAAC;YACjB,WAAW,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;QAChC,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,SAAS,GAAG,CAAC,QAAW;QACtB,IAAI,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,QAAQ,CAAC;YAAE,OAAO;QACvC,KAAK,GAAG,QAAQ,CAAC;QACjB,CAAC,GAAG,WAAW,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,EAAE;YAC/B,GAAG,EAAE,CAAC;QACR,CAAC,CAAC,CAAC;IACL,CAAC;IAED,SAAS,MAAM,CAAC,EAAkB;QAChC,GAAG,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC;IACjB,CAAC;IAED,SAAS,SAAS,CAAC,EAAsB;QACvC,MAAM,OAAO,GAAG,GAAG,EAAE;YACnB,EAAE,CAAC,KAAK,CAAC,CAAC;QACZ,CAAC,CAAC;QACF,WAAW,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QACzB,OAAO,EAAE,CAAC;QACV,OAAO,GAAG,EAAE,CAAC,WAAW,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAC3C,CAAC;IAED,MAAM,MAAM,GAAG,IAAiB,CAAC;IACjC,MAAM,CAAC,GAAG,GAAG,GAAG,CAAC;IACjB,MAAM,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,MAAM,CAAC,SAAS,GAAG,SAAS,CAAC;IAC7B,MAAM,CAAC,UAAU,GAAG,IAAI,CAAC;IAEzB,OAAO,MAAM,CAAC;AAChB,CAAC"}
1
+ {"version":3,"file":"signal.js","sourceRoot":"","sources":["../../src/signal/signal.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACpD,OAAO,EAAE,YAAY,EAAe,MAAM,UAAU,CAAC;AAErD,MAAM,UAAU,MAAM,CAAI,YAAe;IACvC,IAAI,KAAK,GAAG,YAAY,CAAC;IACzB,MAAM,WAAW,GAAG,IAAI,GAAG,EAAU,CAAC;IAEtC,SAAS,IAAI;QACX,IAAI,YAAY,EAAE,CAAC;YACjB,WAAW,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;QAChC,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,SAAS,GAAG,CAAC,QAAW;QACtB,IAAI,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,QAAQ,CAAC;YAAE,OAAO;QACvC,KAAK,GAAG,QAAQ,CAAC;QACjB,IAAI,UAAU,EAAE,EAAE,CAAC;YACjB,CAAC,GAAG,WAAW,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,EAAE,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YAC3D,OAAO;QACT,CAAC;QACD,MAAM,MAAM,GAAc,EAAE,CAAC;QAC7B,CAAC,GAAG,WAAW,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,EAAE;YAC/B,IAAI,CAAC;gBACH,GAAG,EAAE,CAAC;YACR,CAAC;YAAC,OAAO,CAAC,EAAE,CAAC;gBACX,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YACjB,CAAC;QACH,CAAC,CAAC,CAAC;QACH,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC;YAAE,MAAM,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IACzD,CAAC;IAED,SAAS,MAAM,CAAC,EAAkB;QAChC,GAAG,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC;IACjB,CAAC;IAED,SAAS,SAAS,CAAC,EAAsB;QACvC,MAAM,OAAO,GAAG,GAAG,EAAE;YACnB,EAAE,CAAC,KAAK,CAAC,CAAC;QACZ,CAAC,CAAC;QACF,WAAW,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QACzB,OAAO,EAAE,CAAC;QACV,OAAO,GAAG,EAAE,CAAC,WAAW,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAC3C,CAAC;IAED,MAAM,MAAM,GAAG,IAAiB,CAAC;IACjC,MAAM,CAAC,GAAG,GAAG,GAAG,CAAC;IACjB,MAAM,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,MAAM,CAAC,SAAS,GAAG,SAAS,CAAC;IAC7B,MAAM,CAAC,UAAU,GAAG,IAAI,CAAC;IAEzB,OAAO,MAAM,CAAC;AAChB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@praxisjs/core",
3
- "version": "1.0.0",
3
+ "version": "1.2.0",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -1,6 +1,7 @@
1
- import { describe, it, expect } from "vitest";
1
+ import { describe, it, expect, vi } from "vitest";
2
2
 
3
3
  import { batch } from "../signal/batch";
4
+ import { effect } from "../signal/effect";
4
5
  import { signal } from "../signal/signal";
5
6
 
6
7
  describe("batch", () => {
@@ -26,4 +27,61 @@ describe("batch", () => {
26
27
  }); },
27
28
  ).toThrow("inside batch");
28
29
  });
30
+
31
+ it("nested batch() — effects run exactly once after outer batch completes", () => {
32
+ const s = signal(0);
33
+ const runs: number[] = [];
34
+ effect(() => { runs.push(s()); });
35
+ // initial run captured
36
+ const before = runs.length;
37
+
38
+ batch(() => {
39
+ batch(() => {
40
+ s.set(1);
41
+ s.set(2);
42
+ });
43
+ s.set(3);
44
+ });
45
+
46
+ // effect should have run exactly once for the final value
47
+ expect(runs.length).toBe(before + 1);
48
+ expect(runs[runs.length - 1]).toBe(3);
49
+ });
50
+
51
+ it("batch() that throws still cleans up state (no stuck batchQueue)", () => {
52
+ const s = signal(0);
53
+ const runs: number[] = [];
54
+ effect(() => { runs.push(s()); });
55
+
56
+ expect(() =>
57
+ batch(() => {
58
+ s.set(1);
59
+ throw new Error("batch boom");
60
+ }),
61
+ ).toThrow("batch boom");
62
+
63
+ // After the failed batch, the queue must be cleared so subsequent
64
+ // signal changes work normally (not deferred indefinitely).
65
+ const countBefore = runs.length;
66
+ s.set(99);
67
+ expect(runs.length).toBe(countBefore + 1);
68
+ expect(runs[runs.length - 1]).toBe(99);
69
+ });
70
+
71
+ it("effect added inside a running batch is included in the drain", () => {
72
+ const s = signal(0);
73
+ const seen: number[] = [];
74
+
75
+ batch(() => {
76
+ // Create an effect inside the batch — it runs immediately (initial run)
77
+ // and registers itself as a subscriber. Then we set the signal so it
78
+ // gets enqueued into the batch queue.
79
+ effect(() => { seen.push(s()); });
80
+ s.set(5);
81
+ });
82
+
83
+ // The effect should have captured both the initial value and the batched value
84
+ expect(seen).toContain(0);
85
+ expect(seen).toContain(5);
86
+ });
29
87
  });
@@ -125,4 +125,54 @@ describe("computed", () => {
125
125
  s.set(2);
126
126
  expect(received).toContain(6);
127
127
  });
128
+
129
+ it("dirty remains true after computeFn throws — next read recomputes instead of returning stale cache", () => {
130
+ const s = signal(true);
131
+ const fn = vi.fn(() => {
132
+ if (s()) throw new Error("compute error");
133
+ return 42;
134
+ });
135
+ const c = computed(fn);
136
+ // First read — throws, dirty stays true
137
+ expect(() => c()).toThrow("compute error");
138
+ expect(fn).toHaveBeenCalledTimes(1);
139
+ // Second read while still throwing — must recompute, not return stale
140
+ expect(() => c()).toThrow("compute error");
141
+ expect(fn).toHaveBeenCalledTimes(2);
142
+ // Fix the source and read — should now succeed
143
+ s.set(false);
144
+ expect(c()).toBe(42);
145
+ expect(fn).toHaveBeenCalledTimes(3);
146
+ });
147
+
148
+ it("circular dependency between two computed values throws or does not hang", () => {
149
+ // This test documents behavior: circular deps must not cause infinite loops
150
+ // We use a signal to break potential infinite recursion via dirty flag
151
+ const s = signal(0);
152
+ let aVal = 0;
153
+ let bVal = 0;
154
+ const a: ReturnType<typeof computed<number>> = computed(() => {
155
+ s(); // track signal to make dirty
156
+ return bVal + 1;
157
+ });
158
+ const b: ReturnType<typeof computed<number>> = computed(() => {
159
+ s(); // track signal to make dirty
160
+ return aVal + 1;
161
+ });
162
+ // Manually reading without cross-dependency reads to avoid true circularity
163
+ aVal = a();
164
+ bVal = b();
165
+ expect(aVal).toBeGreaterThanOrEqual(1);
166
+ expect(bVal).toBeGreaterThanOrEqual(1);
167
+ });
168
+
169
+ it("double unsubscribe on computed does not crash", () => {
170
+ const s = signal(1);
171
+ const c = computed(() => s() + 1);
172
+ const unsub = c.subscribe(() => {});
173
+ expect(() => {
174
+ unsub();
175
+ unsub();
176
+ }).not.toThrow();
177
+ });
128
178
  });
@@ -1,6 +1,6 @@
1
1
  import { describe, it, expect, vi } from "vitest";
2
2
 
3
- import { effect } from "../signal/effect";
3
+ import { effect, track, activeEffect } from "../signal/effect";
4
4
  import { signal } from "../signal/signal";
5
5
 
6
6
  describe("effect", () => {
@@ -90,4 +90,46 @@ describe("effect", () => {
90
90
  // cleanup called once before second run, once before third run
91
91
  expect(cleanupCount.n).toBe(2);
92
92
  });
93
+
94
+ it("stop() called multiple times does not crash or double-clean", () => {
95
+ const cleanupFn = vi.fn();
96
+ const stop = effect(() => cleanupFn);
97
+ expect(() => {
98
+ stop();
99
+ stop();
100
+ stop();
101
+ }).not.toThrow();
102
+ // cleanup is only called once (on first stop)
103
+ expect(cleanupFn).toHaveBeenCalledTimes(1);
104
+ });
105
+
106
+ it("exception inside nested track() restores outer activeEffect", () => {
107
+ const s = signal(0);
108
+ const outer = vi.fn();
109
+ let outerEffectRef: unknown;
110
+
111
+ effect(() => {
112
+ outer();
113
+ s(); // track
114
+ outerEffectRef = activeEffect;
115
+ });
116
+
117
+ // Now do a track that throws — outer activeEffect must be restored
118
+ try {
119
+ track(() => { throw new Error("inner throws"); });
120
+ } catch {
121
+ // expected
122
+ }
123
+
124
+ expect(activeEffect).toBeNull();
125
+ });
126
+
127
+ it("activeEffect is null after a track() that throws", () => {
128
+ try {
129
+ track(() => { throw new Error("boom"); });
130
+ } catch {
131
+ // expected
132
+ }
133
+ expect(activeEffect).toBeNull();
134
+ });
93
135
  });
@@ -148,4 +148,47 @@ describe("persistedSignal", () => {
148
148
  s.set(undefined);
149
149
  expect(localStorage.getItem("key15")).toBeNull();
150
150
  });
151
+
152
+ it("localStorage.setItem throws QuotaExceededError — signal state is updated but no crash", () => {
153
+ const warn = vi.spyOn(console, "warn").mockImplementation(() => {});
154
+ const setItemSpy = vi.spyOn(Storage.prototype, "setItem").mockImplementation(() => {
155
+ const err = new DOMException("QuotaExceededError", "QuotaExceededError");
156
+ throw err;
157
+ });
158
+
159
+ const s = persistedSignal("key16", 0);
160
+ expect(() => s.set(42)).not.toThrow();
161
+ // The in-memory signal value is still updated despite storage failure
162
+ expect(s()).toBe(42);
163
+
164
+ setItemSpy.mockRestore();
165
+ warn.mockRestore();
166
+ });
167
+
168
+ it("syncTabs=true — storage event with empty string newValue is handled", () => {
169
+ const s = persistedSignal("key17", 99);
170
+ window.dispatchEvent(
171
+ new StorageEvent("storage", {
172
+ key: "key17",
173
+ newValue: "",
174
+ storageArea: localStorage,
175
+ }),
176
+ );
177
+ // Empty string is falsy, so falls back to initialValue
178
+ expect(s()).toBe(99);
179
+ });
180
+
181
+ it("syncTabs=true — storage event from sessionStorage is ignored", () => {
182
+ const s = persistedSignal("key18", 10);
183
+ s.set(20);
184
+ window.dispatchEvent(
185
+ new StorageEvent("storage", {
186
+ key: "key18",
187
+ newValue: "999",
188
+ storageArea: sessionStorage,
189
+ }),
190
+ );
191
+ // Should stay at 20 since the event is from sessionStorage, not localStorage
192
+ expect(s()).toBe(20);
193
+ });
151
194
  });