@praxisjs/core 2.2.0 → 2.3.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.
Files changed (116) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/dist/component/internals.d.ts +12 -2
  3. package/dist/component/internals.d.ts.map +1 -1
  4. package/dist/component/internals.js +25 -7
  5. package/dist/component/internals.js.map +1 -1
  6. package/dist/internal.d.ts +3 -2
  7. package/dist/internal.d.ts.map +1 -1
  8. package/dist/internal.js +3 -2
  9. package/dist/internal.js.map +1 -1
  10. package/dist/signal/batch.d.ts +1 -3
  11. package/dist/signal/batch.d.ts.map +1 -1
  12. package/dist/signal/batch.js +4 -30
  13. package/dist/signal/batch.js.map +1 -1
  14. package/dist/signal/computed.d.ts.map +1 -1
  15. package/dist/signal/computed.js +13 -66
  16. package/dist/signal/computed.js.map +1 -1
  17. package/dist/signal/effect.d.ts +6 -14
  18. package/dist/signal/effect.d.ts.map +1 -1
  19. package/dist/signal/effect.js +11 -83
  20. package/dist/signal/effect.js.map +1 -1
  21. package/dist/signal/graph.d.ts +111 -0
  22. package/dist/signal/graph.d.ts.map +1 -0
  23. package/dist/signal/graph.js +513 -0
  24. package/dist/signal/graph.js.map +1 -0
  25. package/dist/signal/index.d.ts +1 -0
  26. package/dist/signal/index.d.ts.map +1 -1
  27. package/dist/signal/index.js +1 -0
  28. package/dist/signal/index.js.map +1 -1
  29. package/dist/signal/peek.d.ts.map +1 -1
  30. package/dist/signal/peek.js +2 -9
  31. package/dist/signal/peek.js.map +1 -1
  32. package/dist/signal/selector.d.ts +5 -0
  33. package/dist/signal/selector.d.ts.map +1 -0
  34. package/dist/signal/selector.js +128 -0
  35. package/dist/signal/selector.js.map +1 -0
  36. package/dist/signal/signal.d.ts +0 -5
  37. package/dist/signal/signal.d.ts.map +1 -1
  38. package/dist/signal/signal.js +11 -70
  39. package/dist/signal/signal.js.map +1 -1
  40. package/package.json +13 -4
  41. package/src/component/internals.ts +35 -10
  42. package/src/internal.ts +26 -0
  43. package/src/signal/batch.ts +5 -33
  44. package/src/signal/computed.ts +13 -66
  45. package/src/signal/effect.ts +12 -92
  46. package/src/signal/graph.ts +562 -0
  47. package/src/signal/index.ts +1 -0
  48. package/src/signal/peek.ts +2 -8
  49. package/src/signal/selector.ts +140 -0
  50. package/src/signal/signal.ts +11 -74
  51. package/dist/__tests__/batch.test.d.ts +0 -2
  52. package/dist/__tests__/batch.test.d.ts.map +0 -1
  53. package/dist/__tests__/batch.test.js +0 -124
  54. package/dist/__tests__/batch.test.js.map +0 -1
  55. package/dist/__tests__/component.test.d.ts +0 -2
  56. package/dist/__tests__/component.test.d.ts.map +0 -1
  57. package/dist/__tests__/component.test.js +0 -124
  58. package/dist/__tests__/component.test.js.map +0 -1
  59. package/dist/__tests__/computed.test.d.ts +0 -2
  60. package/dist/__tests__/computed.test.d.ts.map +0 -1
  61. package/dist/__tests__/computed.test.js +0 -289
  62. package/dist/__tests__/computed.test.js.map +0 -1
  63. package/dist/__tests__/effect.test.d.ts +0 -2
  64. package/dist/__tests__/effect.test.d.ts.map +0 -1
  65. package/dist/__tests__/effect.test.js +0 -200
  66. package/dist/__tests__/effect.test.js.map +0 -1
  67. package/dist/__tests__/peek.test.d.ts +0 -2
  68. package/dist/__tests__/peek.test.d.ts.map +0 -1
  69. package/dist/__tests__/peek.test.js +0 -26
  70. package/dist/__tests__/peek.test.js.map +0 -1
  71. package/dist/__tests__/persisted-signal.test.d.ts +0 -2
  72. package/dist/__tests__/persisted-signal.test.d.ts.map +0 -1
  73. package/dist/__tests__/persisted-signal.test.js +0 -252
  74. package/dist/__tests__/persisted-signal.test.js.map +0 -1
  75. package/dist/__tests__/reactive.test.d.ts +0 -2
  76. package/dist/__tests__/reactive.test.d.ts.map +0 -1
  77. package/dist/__tests__/reactive.test.js +0 -299
  78. package/dist/__tests__/reactive.test.js.map +0 -1
  79. package/dist/__tests__/resource-focus.test.d.ts +0 -2
  80. package/dist/__tests__/resource-focus.test.d.ts.map +0 -1
  81. package/dist/__tests__/resource-focus.test.js +0 -50
  82. package/dist/__tests__/resource-focus.test.js.map +0 -1
  83. package/dist/__tests__/resource-server-pass.test.d.ts +0 -2
  84. package/dist/__tests__/resource-server-pass.test.d.ts.map +0 -1
  85. package/dist/__tests__/resource-server-pass.test.js +0 -78
  86. package/dist/__tests__/resource-server-pass.test.js.map +0 -1
  87. package/dist/__tests__/resource.test.d.ts +0 -2
  88. package/dist/__tests__/resource.test.d.ts.map +0 -1
  89. package/dist/__tests__/resource.test.js +0 -336
  90. package/dist/__tests__/resource.test.js.map +0 -1
  91. package/dist/__tests__/signal.test.d.ts +0 -2
  92. package/dist/__tests__/signal.test.d.ts.map +0 -1
  93. package/dist/__tests__/signal.test.js +0 -254
  94. package/dist/__tests__/signal.test.js.map +0 -1
  95. package/dist/__tests__/synced.test.d.ts +0 -2
  96. package/dist/__tests__/synced.test.d.ts.map +0 -1
  97. package/dist/__tests__/synced.test.js +0 -142
  98. package/dist/__tests__/synced.test.js.map +0 -1
  99. package/dist/__tests__/track.test.d.ts +0 -2
  100. package/dist/__tests__/track.test.d.ts.map +0 -1
  101. package/dist/__tests__/track.test.js +0 -54
  102. package/dist/__tests__/track.test.js.map +0 -1
  103. package/src/__tests__/batch.test.ts +0 -138
  104. package/src/__tests__/component.test.ts +0 -165
  105. package/src/__tests__/computed.test.ts +0 -333
  106. package/src/__tests__/effect.test.ts +0 -241
  107. package/src/__tests__/peek.test.ts +0 -31
  108. package/src/__tests__/persisted-signal.test.ts +0 -305
  109. package/src/__tests__/reactive.test.ts +0 -343
  110. package/src/__tests__/resource-focus.test.ts +0 -61
  111. package/src/__tests__/resource-server-pass.test.ts +0 -90
  112. package/src/__tests__/resource.test.ts +0 -421
  113. package/src/__tests__/signal.test.ts +0 -291
  114. package/src/__tests__/synced.test.ts +0 -173
  115. package/src/__tests__/track.test.ts +0 -61
  116. package/tsconfig.json +0 -8
@@ -1,254 +0,0 @@
1
- import { describe, it, expect } from "vitest";
2
- import { batch } from "../signal/batch";
3
- import { SUBS_SET_THRESHOLD } from "../signal/effect";
4
- import { effect } from "../signal/effect";
5
- import { signal, addSub, removeSub } from "../signal/signal";
6
- describe("signal", () => {
7
- it("returns initial value", () => {
8
- const s = signal(42);
9
- expect(s()).toBe(42);
10
- });
11
- it("updates value with set", () => {
12
- const s = signal(0);
13
- s.set(10);
14
- expect(s()).toBe(10);
15
- });
16
- it("updates value with update fn", () => {
17
- const s = signal(5);
18
- s.update((v) => v * 2);
19
- expect(s()).toBe(10);
20
- });
21
- it("skips update when value is identical", () => {
22
- const s = signal(1);
23
- const calls = [];
24
- s.subscribe((v) => calls.push(v));
25
- const before = calls.length;
26
- s.set(1); // same value
27
- expect(calls.length).toBe(before);
28
- });
29
- it("subscribe fires immediately with current value", () => {
30
- const s = signal("hello");
31
- const received = [];
32
- s.subscribe((v) => received.push(v));
33
- expect(received).toEqual(["hello"]);
34
- });
35
- it("subscribe fires on subsequent updates", () => {
36
- const s = signal(0);
37
- const received = [];
38
- s.subscribe((v) => received.push(v));
39
- s.set(1);
40
- s.set(2);
41
- expect(received).toEqual([0, 1, 2]);
42
- });
43
- it("unsubscribe stops receiving updates", () => {
44
- const s = signal(0);
45
- const received = [];
46
- const unsub = s.subscribe((v) => received.push(v));
47
- unsub();
48
- s.set(99);
49
- expect(received).toEqual([0]);
50
- });
51
- it("marks __isSignal = true", () => {
52
- const s = signal(0);
53
- expect(s.__isSignal).toBe(true);
54
- });
55
- it("supports object values", () => {
56
- const s = signal({ name: "Alice" });
57
- s.set({ name: "Bob" });
58
- expect(s().name).toBe("Bob");
59
- });
60
- it("supports null and undefined", () => {
61
- const s = signal(null);
62
- expect(s()).toBeNull();
63
- s.set(5);
64
- expect(s()).toBe(5);
65
- });
66
- it("NaN is considered equal to NaN — no notification", () => {
67
- const s = signal(NaN);
68
- const calls = [];
69
- s.subscribe((v) => calls.push(v));
70
- const before = calls.length;
71
- s.set(NaN);
72
- expect(calls.length).toBe(before);
73
- });
74
- it("-0 and +0 are considered different — notification fires", () => {
75
- const s = signal(-0);
76
- const calls = [];
77
- s.subscribe((v) => calls.push(v));
78
- const before = calls.length;
79
- s.set(+0);
80
- expect(calls.length).toBe(before + 1);
81
- });
82
- it("update() fn that throws does not update the value", () => {
83
- const s = signal(5);
84
- expect(() => s.update(() => { throw new Error("fn error"); })).toThrow("fn error");
85
- expect(s()).toBe(5);
86
- });
87
- it("multiple subscribers all receive the update", () => {
88
- const s = signal(0);
89
- const a = [];
90
- const b = [];
91
- s.subscribe((v) => a.push(v));
92
- s.subscribe((v) => b.push(v));
93
- s.set(7);
94
- expect(a).toContain(7);
95
- expect(b).toContain(7);
96
- });
97
- it("subscriber B still fires when subscriber A throws", () => {
98
- const s = signal(0);
99
- const received = [];
100
- s.subscribe((v) => { if (v !== 0)
101
- throw new Error("sub A throws"); });
102
- s.subscribe((v) => received.push(v));
103
- expect(() => s.set(1)).toThrow("sub A throws");
104
- expect(received).toContain(1);
105
- });
106
- it("unsubscribe during notification does not crash", () => {
107
- const s = signal(0);
108
- let unsub;
109
- unsub = s.subscribe(() => {
110
- unsub?.();
111
- });
112
- expect(() => s.set(1)).not.toThrow();
113
- });
114
- it("unsubscribing one of multiple subscribers removes only that subscriber", () => {
115
- const s = signal(0);
116
- const a = [];
117
- const b = [];
118
- const unsubA = s.subscribe((v) => a.push(v));
119
- s.subscribe((v) => b.push(v));
120
- // subs is now an array — hits removeSub else branch
121
- unsubA();
122
- s.set(1);
123
- expect(a).toEqual([0]); // A stopped after initial fire
124
- expect(b).toEqual([0, 1]); // B still receives
125
- });
126
- it("unsubscribing a non-existent subscriber from array subs is a no-op", () => {
127
- const s = signal(0);
128
- const a = [];
129
- const b = [];
130
- s.subscribe((v) => a.push(v));
131
- const unsubB = s.subscribe((v) => b.push(v));
132
- unsubB(); // remove B, subs becomes array without B
133
- unsubB(); // call again — idx will be -1, splice not called
134
- expect(() => s.set(1)).not.toThrow();
135
- expect(a).toContain(1);
136
- });
137
- it("batch defers notifications for multiple array subscribers", () => {
138
- const s = signal(0);
139
- const a = [];
140
- const b = [];
141
- s.subscribe((v) => a.push(v));
142
- s.subscribe((v) => b.push(v));
143
- // subs is an array; inside batch, notifySubs hits the batching=true array path
144
- batch(() => {
145
- s.set(1);
146
- expect(a).toEqual([0]); // not yet fired
147
- expect(b).toEqual([0]);
148
- });
149
- expect(a).toContain(1);
150
- expect(b).toContain(1);
151
- });
152
- it("removeSub with non-matching single-function subscriber is a no-op", () => {
153
- // When subs is a single function and we try to remove a different function,
154
- // the holder must remain unchanged (subs !== eff → false branch).
155
- const holder = { subs: null };
156
- const fn1 = () => { };
157
- const fn2 = () => { };
158
- addSub(holder, fn1); // subs = fn1 (single function)
159
- removeSub(holder, fn2); // fn2 !== fn1 → no-op
160
- expect(holder.subs).toBe(fn1);
161
- });
162
- it("addSub does not add a duplicate subscriber to an array holder", () => {
163
- const fn1 = () => { };
164
- const fn2 = () => { };
165
- const holder = { subs: [fn1, fn2] };
166
- addSub(holder, fn2);
167
- expect(holder.subs).toEqual([fn1, fn2]);
168
- });
169
- it("removeSub normalizes an emptied array holder back to null", () => {
170
- const fn = () => { };
171
- const holder = { subs: [fn] };
172
- removeSub(holder, fn);
173
- expect(holder.subs).toBeNull();
174
- });
175
- it("set() with mutated object reference (same ref) does NOT notify — Object.is semantics", () => {
176
- const obj = { count: 0 };
177
- const s = signal(obj);
178
- const calls = [];
179
- s.subscribe((v) => calls.push(v));
180
- const before = calls.length;
181
- // Mutate the object in-place and set the same reference
182
- obj.count = 99;
183
- s.set(obj);
184
- // Object.is(obj, obj) === true, so no notification
185
- expect(calls.length).toBe(before);
186
- });
187
- });
188
- describe("large subscriber lists", () => {
189
- function fns(count) {
190
- return Array.from({ length: count }, () => () => { });
191
- }
192
- it("keeps an array up to the threshold and promotes to a Set past it, preserving order", () => {
193
- const holder = { subs: null };
194
- const list = fns(SUBS_SET_THRESHOLD);
195
- for (const fn of list)
196
- addSub(holder, fn);
197
- expect(Array.isArray(holder.subs)).toBe(true);
198
- const extra = () => { };
199
- addSub(holder, extra);
200
- expect(holder.subs).toBeInstanceOf(Set);
201
- expect([...holder.subs]).toEqual([...list, extra]);
202
- });
203
- it("addSub on a Set holder adds new subscribers and ignores duplicates", () => {
204
- const list = fns(SUBS_SET_THRESHOLD + 1);
205
- const holder = { subs: new Set(list) };
206
- addSub(holder, list[0]);
207
- expect(holder.subs.size).toBe(list.length);
208
- const extra = () => { };
209
- addSub(holder, extra);
210
- expect(holder.subs.size).toBe(list.length + 1);
211
- });
212
- it("removeSub on a Set holder removes one subscriber, ignores unknown ones, and normalizes to null when emptied", () => {
213
- const [a, b, stranger] = fns(3);
214
- const holder = { subs: new Set([a, b]) };
215
- removeSub(holder, stranger);
216
- expect(holder.subs.size).toBe(2);
217
- removeSub(holder, a);
218
- expect([...holder.subs]).toEqual([b]);
219
- removeSub(holder, b);
220
- expect(holder.subs).toBeNull();
221
- });
222
- it("many effects on one signal all re-run once per change, in subscription order", () => {
223
- const count = SUBS_SET_THRESHOLD * 3;
224
- const s = signal(0);
225
- const order = [];
226
- const stops = Array.from({ length: count }, (_, i) => effect(() => {
227
- void s();
228
- order.push(i);
229
- }));
230
- order.length = 0;
231
- s.set(1);
232
- expect(order).toEqual(Array.from({ length: count }, (_, i) => i));
233
- order.length = 0;
234
- s.set(2);
235
- expect(order).toEqual(Array.from({ length: count }, (_, i) => i));
236
- stops.forEach((stop) => { stop(); });
237
- order.length = 0;
238
- s.set(3);
239
- expect(order).toEqual([]);
240
- });
241
- it("an effect stopped while the signal holds a Set no longer runs, the others still do", () => {
242
- const s = signal(0);
243
- const runs = new Map();
244
- const stops = Array.from({ length: SUBS_SET_THRESHOLD + 4 }, (_, i) => effect(() => {
245
- void s();
246
- runs.set(i, (runs.get(i) ?? 0) + 1);
247
- }));
248
- stops[2]();
249
- s.set(1);
250
- expect(runs.get(2)).toBe(1);
251
- expect(runs.get(3)).toBe(2);
252
- });
253
- });
254
- //# sourceMappingURL=signal.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"signal.test.js","sourceRoot":"","sources":["../../src/__tests__/signal.test.ts"],"names":[],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=synced.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"synced.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/synced.test.ts"],"names":[],"mappings":""}
@@ -1,142 +0,0 @@
1
- import { describe, it, expect, vi, beforeEach } from "vitest";
2
- import { syncedSignal } from "../signal/synced";
3
- import { effect } from "../signal/effect";
4
- // BroadcastChannel mock
5
- class MockBroadcastChannel {
6
- static instances = [];
7
- static byChannel = new Map();
8
- onmessage = null;
9
- name;
10
- closed = false;
11
- constructor(name) {
12
- this.name = name;
13
- MockBroadcastChannel.instances.push(this);
14
- if (!MockBroadcastChannel.byChannel.has(name)) {
15
- MockBroadcastChannel.byChannel.set(name, []);
16
- }
17
- MockBroadcastChannel.byChannel.get(name).push(this);
18
- }
19
- postMessage(data) {
20
- // Deliver to all OTHER instances on same channel
21
- MockBroadcastChannel.byChannel.get(this.name)?.forEach((ch) => {
22
- if (ch !== this && ch.onmessage) {
23
- ch.onmessage(new MessageEvent("message", { data }));
24
- }
25
- });
26
- }
27
- close() {
28
- this.closed = true;
29
- const list = MockBroadcastChannel.byChannel.get(this.name);
30
- if (list) {
31
- const idx = list.indexOf(this);
32
- if (idx !== -1)
33
- list.splice(idx, 1);
34
- }
35
- MockBroadcastChannel.instances.splice(MockBroadcastChannel.instances.indexOf(this), 1);
36
- }
37
- }
38
- beforeEach(() => {
39
- MockBroadcastChannel.instances = [];
40
- MockBroadcastChannel.byChannel = new Map();
41
- vi.stubGlobal("BroadcastChannel", MockBroadcastChannel);
42
- });
43
- describe("syncedSignal", () => {
44
- it("reads initial value", () => {
45
- const s = syncedSignal("ch", 42);
46
- expect(s()).toBe(42);
47
- s.close();
48
- });
49
- it("set() updates the signal value", () => {
50
- const s = syncedSignal("ch", 0);
51
- s.set(10);
52
- expect(s()).toBe(10);
53
- s.close();
54
- });
55
- it("update() applies a transform", () => {
56
- const s = syncedSignal("ch", 5);
57
- s.update((v) => v * 2);
58
- expect(s()).toBe(10);
59
- s.close();
60
- });
61
- it("set() posts a JSON message to the channel", () => {
62
- const s = syncedSignal("ch", 0);
63
- const postSpy = vi.spyOn(MockBroadcastChannel.instances[0], "postMessage");
64
- s.set(99);
65
- expect(postSpy).toHaveBeenCalledWith(JSON.stringify(99));
66
- s.close();
67
- });
68
- it("receiving a message from another tab updates the signal", () => {
69
- const s = syncedSignal("ch", 0);
70
- const channel = MockBroadcastChannel.instances[0];
71
- channel.onmessage(new MessageEvent("message", { data: JSON.stringify(7) }));
72
- expect(s()).toBe(7);
73
- s.close();
74
- });
75
- it("does not echo own set() back to itself", () => {
76
- const s = syncedSignal("ch", 0);
77
- // Simulate two instances on the same channel
78
- const s2 = syncedSignal("ch", 0);
79
- const received = [];
80
- effect(() => { received.push(s2()); });
81
- s.set(5);
82
- // s2 should receive the message because it came from a different instance
83
- expect(s2()).toBe(5);
84
- // s itself should NOT trigger its own onmessage handler (no echo)
85
- const channel = MockBroadcastChannel.instances[0];
86
- const receivedBySelf = [];
87
- effect(() => { receivedBySelf.push(s()); });
88
- const beforeCount = receivedBySelf.length;
89
- // Manually simulate echo — should be ignored because posting=false after set
90
- channel.onmessage(new MessageEvent("message", { data: JSON.stringify(5) }));
91
- // The value stays 5 (no spurious extra notification tested via subscribe count)
92
- expect(s()).toBe(5);
93
- expect(receivedBySelf.length).toBe(beforeCount); // no extra effect run (Object.is equality)
94
- s.close();
95
- s2.close();
96
- });
97
- it("subscribe fires immediately then on each remote change", () => {
98
- const s = syncedSignal("ch", 0);
99
- const channel = MockBroadcastChannel.instances[0];
100
- const received = [];
101
- s.subscribe((v) => received.push(v));
102
- expect(received).toEqual([0]);
103
- channel.onmessage(new MessageEvent("message", { data: JSON.stringify(3) }));
104
- expect(received).toEqual([0, 3]);
105
- s.close();
106
- });
107
- it("close() shuts down the BroadcastChannel", () => {
108
- const s = syncedSignal("ch", 0);
109
- const channel = MockBroadcastChannel.instances[0];
110
- expect(channel.closed).toBe(false);
111
- s.close();
112
- expect(channel.closed).toBe(true);
113
- });
114
- it("has __isSignal marker", () => {
115
- const s = syncedSignal("ch", 0);
116
- expect(s.__isSignal).toBe(true);
117
- s.close();
118
- });
119
- it("does not update value when onmessage fires while posting (posting guard)", () => {
120
- // Use a self-delivering channel that echoes to itself during postMessage.
121
- // This covers the `if (posting) return;` branch in synced.ts.
122
- class SelfEchoChannel {
123
- onmessage = null;
124
- postMessage(data) {
125
- this.onmessage?.(new MessageEvent("message", { data }));
126
- }
127
- close() { }
128
- }
129
- vi.stubGlobal("BroadcastChannel", SelfEchoChannel);
130
- const s = syncedSignal("echo-ch", 0);
131
- const received = [];
132
- s.subscribe((v) => received.push(v));
133
- // set() triggers postMessage → onmessage fires → posting=true → early return
134
- // Inner value should not be double-set
135
- s.set(42);
136
- expect(s()).toBe(42);
137
- // Only two notifications: initial (0) + the set (42), no echo re-set
138
- expect(received).toEqual([0, 42]);
139
- s.close();
140
- });
141
- });
142
- //# sourceMappingURL=synced.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"synced.test.js","sourceRoot":"","sources":["../../src/__tests__/synced.test.ts"],"names":[],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=track.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"track.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/track.test.ts"],"names":[],"mappings":""}
@@ -1,54 +0,0 @@
1
- import { describe, it, expect, vi } from "vitest";
2
- import { track, runEffect, activeEffect } from "../signal/effect";
3
- import { signal } from "../signal/signal";
4
- describe("track", () => {
5
- it("runs the effect immediately", () => {
6
- const fn = vi.fn();
7
- track(fn);
8
- expect(fn).toHaveBeenCalledOnce();
9
- });
10
- it("sets activeEffect during execution, resets after", () => {
11
- let during = "not-set";
12
- track(() => {
13
- during = activeEffect;
14
- });
15
- expect(during).toBeTypeOf("function");
16
- expect(activeEffect).toBeNull();
17
- });
18
- it("supports nested track calls — restores outer effect", () => {
19
- const outer = vi.fn();
20
- const inner = vi.fn();
21
- let outerActive;
22
- let innerActive;
23
- track(() => {
24
- outer();
25
- outerActive = activeEffect;
26
- track(() => {
27
- inner();
28
- innerActive = activeEffect;
29
- });
30
- // after inner track, activeEffect should be back to outer
31
- expect(activeEffect).toBe(outerActive);
32
- });
33
- expect(outer).toHaveBeenCalledOnce();
34
- expect(inner).toHaveBeenCalledOnce();
35
- expect(innerActive).not.toBe(outerActive);
36
- });
37
- it("subscribes the tracked effect to signals read inside it", () => {
38
- const s = signal(1);
39
- const values = [];
40
- track(() => values.push(s()));
41
- s.set(2);
42
- expect(values).toEqual([1, 2]);
43
- });
44
- });
45
- describe("runEffect", () => {
46
- it("sets activeEffect to the given value", () => {
47
- const fn = () => { };
48
- runEffect(fn);
49
- expect(activeEffect).toBe(fn);
50
- runEffect(null);
51
- expect(activeEffect).toBeNull();
52
- });
53
- });
54
- //# sourceMappingURL=track.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"track.test.js","sourceRoot":"","sources":["../../src/__tests__/track.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAElD,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAClE,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAE1C,QAAQ,CAAC,OAAO,EAAE,GAAG,EAAE;IACrB,EAAE,CAAC,6BAA6B,EAAE,GAAG,EAAE;QACrC,MAAM,EAAE,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;QACnB,KAAK,CAAC,EAAE,CAAC,CAAC;QACV,MAAM,CAAC,EAAE,CAAC,CAAC,oBAAoB,EAAE,CAAC;IACpC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kDAAkD,EAAE,GAAG,EAAE;QAC1D,IAAI,MAAM,GAAY,SAAS,CAAC;QAChC,KAAK,CAAC,GAAG,EAAE;YACT,MAAM,GAAG,YAAY,CAAC;QACxB,CAAC,CAAC,CAAC;QACH,MAAM,CAAC,MAAM,CAAC,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;QACtC,MAAM,CAAC,YAAY,CAAC,CAAC,QAAQ,EAAE,CAAC;IAClC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qDAAqD,EAAE,GAAG,EAAE;QAC7D,MAAM,KAAK,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;QACtB,MAAM,KAAK,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;QACtB,IAAI,WAAoB,CAAC;QACzB,IAAI,WAAoB,CAAC;QAEzB,KAAK,CAAC,GAAG,EAAE;YACT,KAAK,EAAE,CAAC;YACR,WAAW,GAAG,YAAY,CAAC;YAC3B,KAAK,CAAC,GAAG,EAAE;gBACT,KAAK,EAAE,CAAC;gBACR,WAAW,GAAG,YAAY,CAAC;YAC7B,CAAC,CAAC,CAAC;YACH,0DAA0D;YAC1D,MAAM,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QACzC,CAAC,CAAC,CAAC;QAEH,MAAM,CAAC,KAAK,CAAC,CAAC,oBAAoB,EAAE,CAAC;QACrC,MAAM,CAAC,KAAK,CAAC,CAAC,oBAAoB,EAAE,CAAC;QACrC,MAAM,CAAC,WAAW,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IAC5C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yDAAyD,EAAE,GAAG,EAAE;QACjE,MAAM,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;QACpB,MAAM,MAAM,GAAa,EAAE,CAAC;QAC5B,KAAK,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QAC9B,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QACT,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IACjC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,WAAW,EAAE,GAAG,EAAE;IACzB,EAAE,CAAC,sCAAsC,EAAE,GAAG,EAAE;QAC9C,MAAM,EAAE,GAAG,GAAG,EAAE,GAAE,CAAC,CAAC;QACpB,SAAS,CAAC,EAAE,CAAC,CAAC;QACd,MAAM,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAC9B,SAAS,CAAC,IAAI,CAAC,CAAC;QAChB,MAAM,CAAC,YAAY,CAAC,CAAC,QAAQ,EAAE,CAAC;IAClC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -1,138 +0,0 @@
1
- import { describe, it, expect, vi } from "vitest";
2
-
3
- import { batch } from "../signal/batch";
4
- import { effect } from "../signal/effect";
5
- import { signal } from "../signal/signal";
6
-
7
- describe("batch", () => {
8
- it("executes the wrapped function", () => {
9
- const s = signal(0);
10
- batch(() => {
11
- s.set(5);
12
- s.set(10);
13
- });
14
- expect(s()).toBe(10);
15
- });
16
-
17
- it("does not throw when no effects are tracking", () => {
18
- const s = signal(0);
19
- expect(() => { batch(() => { s.set(1); }); }).not.toThrow();
20
- expect(s()).toBe(1);
21
- });
22
-
23
- it("propagates errors thrown inside the batch", () => {
24
- expect(() =>
25
- { batch(() => {
26
- throw new Error("inside batch");
27
- }); },
28
- ).toThrow("inside batch");
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
- });
87
-
88
- it("an effect fed by several signals runs once per batch", () => {
89
- const a = signal(0);
90
- const b = signal(0);
91
- const runs = vi.fn();
92
- effect(() => {
93
- void a();
94
- void b();
95
- runs();
96
- });
97
- runs.mockClear();
98
- batch(() => {
99
- a.set(1);
100
- b.set(1);
101
- a.set(2);
102
- });
103
- expect(runs).toHaveBeenCalledOnce();
104
- });
105
-
106
- it("a throwing effect does not stop the others and the error is rethrown after the flush", () => {
107
- const s = signal(0);
108
- const after = vi.fn();
109
- let armed = false;
110
- effect(() => {
111
- void s();
112
- if (armed) throw new Error("effect boom");
113
- });
114
- effect(() => {
115
- void s();
116
- if (armed) after();
117
- });
118
- armed = true;
119
- expect(() => { batch(() => { s.set(1); }); }).toThrow("effect boom");
120
- expect(after).toHaveBeenCalledOnce();
121
- });
122
-
123
- it("a failed flush leaves no stale entries for the next batch", () => {
124
- const s = signal(0);
125
- const runs = vi.fn();
126
- let throws = true;
127
- effect(() => {
128
- void s();
129
- runs();
130
- if (throws && s() === 1) throw new Error("once");
131
- });
132
- expect(() => { batch(() => { s.set(1); }); }).toThrow("once");
133
- throws = false;
134
- runs.mockClear();
135
- batch(() => { s.set(2); });
136
- expect(runs).toHaveBeenCalledOnce();
137
- });
138
- });