@rlabs-inc/signals 0.2.0 → 1.1.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 (36) hide show
  1. package/README.md +238 -198
  2. package/dist/collections/date.d.ts +67 -0
  3. package/dist/collections/date.d.ts.map +1 -0
  4. package/dist/collections/map.d.ts +37 -0
  5. package/dist/collections/map.d.ts.map +1 -0
  6. package/dist/collections/set.d.ts +36 -0
  7. package/dist/collections/set.d.ts.map +1 -0
  8. package/dist/core/constants.d.ts +47 -0
  9. package/dist/core/constants.d.ts.map +1 -0
  10. package/dist/core/globals.d.ts +45 -0
  11. package/dist/core/globals.d.ts.map +1 -0
  12. package/dist/core/types.d.ts +76 -0
  13. package/dist/core/types.d.ts.map +1 -0
  14. package/dist/deep/proxy.d.ts +19 -0
  15. package/dist/deep/proxy.d.ts.map +1 -0
  16. package/dist/index.d.ts +16 -277
  17. package/dist/index.d.ts.map +1 -1
  18. package/dist/index.js +1268 -607
  19. package/dist/index.mjs +1267 -608
  20. package/dist/primitives/bind.d.ts +95 -0
  21. package/dist/primitives/bind.d.ts.map +1 -0
  22. package/dist/primitives/derived.d.ts +45 -0
  23. package/dist/primitives/derived.d.ts.map +1 -0
  24. package/dist/primitives/effect.d.ts +41 -0
  25. package/dist/primitives/effect.d.ts.map +1 -0
  26. package/dist/primitives/signal.d.ts +54 -0
  27. package/dist/primitives/signal.d.ts.map +1 -0
  28. package/dist/reactivity/batching.d.ts +56 -0
  29. package/dist/reactivity/batching.d.ts.map +1 -0
  30. package/dist/reactivity/equality.d.ts +36 -0
  31. package/dist/reactivity/equality.d.ts.map +1 -0
  32. package/dist/reactivity/scheduling.d.ts +26 -0
  33. package/dist/reactivity/scheduling.d.ts.map +1 -0
  34. package/dist/reactivity/tracking.d.ts +47 -0
  35. package/dist/reactivity/tracking.d.ts.map +1 -0
  36. package/package.json +6 -2
package/dist/index.mjs CHANGED
@@ -1,431 +1,957 @@
1
- // src/index.ts
2
- var activeReaction = null;
3
- var reactionStack = [];
4
- var batchDepth = 0;
5
- var pendingReactions = new Set;
6
- var untracking = false;
7
- var proxyToSignal = new WeakMap;
8
- var rawToProxy = new WeakMap;
9
- var defaultEquals = (a, b) => Object.is(a, b);
10
- var shallowEquals = (a, b) => {
11
- if (Object.is(a, b))
1
+ // src/reactivity/equality.ts
2
+ var equals = (oldValue, newValue) => Object.is(oldValue, newValue);
3
+ function safeNotEqual(a, b) {
4
+ return a != a ? b == b : a !== b || a !== null && typeof a === "object" || typeof a === "function";
5
+ }
6
+ var safeEquals = (oldValue, newValue) => !safeNotEqual(oldValue, newValue);
7
+ var shallowEquals = (oldValue, newValue) => {
8
+ if (Object.is(oldValue, newValue)) {
12
9
  return true;
13
- if (typeof a !== "object" || typeof b !== "object")
14
- return false;
15
- if (a === null || b === null)
10
+ }
11
+ if (typeof oldValue !== "object" || oldValue === null || typeof newValue !== "object" || newValue === null) {
16
12
  return false;
17
- const keysA = Object.keys(a);
18
- const keysB = Object.keys(b);
19
- if (keysA.length !== keysB.length)
13
+ }
14
+ if (Array.isArray(oldValue) && Array.isArray(newValue)) {
15
+ if (oldValue.length !== newValue.length) {
16
+ return false;
17
+ }
18
+ for (let i = 0;i < oldValue.length; i++) {
19
+ if (!Object.is(oldValue[i], newValue[i])) {
20
+ return false;
21
+ }
22
+ }
23
+ return true;
24
+ }
25
+ const oldKeys = Object.keys(oldValue);
26
+ const newKeys = Object.keys(newValue);
27
+ if (oldKeys.length !== newKeys.length) {
20
28
  return false;
21
- for (const key of keysA) {
22
- if (!Object.is(a[key], b[key]))
29
+ }
30
+ for (const key of oldKeys) {
31
+ if (!Object.prototype.hasOwnProperty.call(newValue, key) || !Object.is(oldValue[key], newValue[key])) {
23
32
  return false;
33
+ }
24
34
  }
25
35
  return true;
26
36
  };
27
- function signal(initial, options) {
28
- const internal = {
29
- v: initial,
30
- reactions: new Set,
31
- equals: options?.equals ?? defaultEquals
32
- };
33
- let proxyCache = null;
34
- return {
35
- get value() {
36
- track(internal);
37
- if (internal.v !== null && typeof internal.v === "object") {
38
- if (!proxyCache) {
39
- proxyCache = createDeepReactiveForSignal(internal.v, internal);
37
+ function createEquals(fn) {
38
+ return (oldValue, newValue) => fn(oldValue, newValue);
39
+ }
40
+ var neverEquals = () => false;
41
+ var alwaysEquals = () => true;
42
+
43
+ // src/core/constants.ts
44
+ var DERIVED = 1 << 1;
45
+ var EFFECT = 1 << 2;
46
+ var RENDER_EFFECT = 1 << 3;
47
+ var ROOT_EFFECT = 1 << 4;
48
+ var BRANCH_EFFECT = 1 << 5;
49
+ var USER_EFFECT = 1 << 6;
50
+ var BLOCK_EFFECT = 1 << 7;
51
+ var CLEAN = 1 << 10;
52
+ var DIRTY = 1 << 11;
53
+ var MAYBE_DIRTY = 1 << 12;
54
+ var REACTION_IS_UPDATING = 1 << 13;
55
+ var DESTROYED = 1 << 14;
56
+ var INERT = 1 << 15;
57
+ var EFFECT_RAN = 1 << 16;
58
+ var EFFECT_PRESERVED = 1 << 17;
59
+ var UNOWNED = 1 << 8;
60
+ var DISCONNECTED = 1 << 9;
61
+ var INSPECT_EFFECT = 1 << 18;
62
+ var UNINITIALIZED = Symbol.for("rlabs.signals.uninitialized");
63
+ var STALE_REACTION = Symbol.for("rlabs.signals.stale_reaction");
64
+ var STATE_SYMBOL = Symbol.for("rlabs.signals.state");
65
+ var REACTIVE_MARKER = Symbol.for("rlabs.signals.reactive");
66
+ var STATUS_MASK = ~(DIRTY | MAYBE_DIRTY | CLEAN);
67
+
68
+ // src/core/globals.ts
69
+ var activeReaction = null;
70
+ var activeEffect = null;
71
+ var untracking = false;
72
+ var writeVersion = 1;
73
+ var readVersion = 0;
74
+ var newDeps = null;
75
+ var skippedDeps = 0;
76
+ var untrackedWrites = null;
77
+ var batchDepth = 0;
78
+ var pendingReactions = new Set;
79
+ var queuedRootEffects = [];
80
+ var isFlushingSync = false;
81
+ function setActiveReaction(reaction) {
82
+ const prev = activeReaction;
83
+ activeReaction = reaction;
84
+ return prev;
85
+ }
86
+ function setActiveEffect(effect) {
87
+ const prev = activeEffect;
88
+ activeEffect = effect;
89
+ return prev;
90
+ }
91
+ function setUntracking(value) {
92
+ const prev = untracking;
93
+ untracking = value;
94
+ return prev;
95
+ }
96
+ function incrementWriteVersion() {
97
+ return ++writeVersion;
98
+ }
99
+ function incrementReadVersion() {
100
+ return ++readVersion;
101
+ }
102
+ function setNewDeps(deps) {
103
+ const prev = newDeps;
104
+ newDeps = deps;
105
+ return prev;
106
+ }
107
+ function setSkippedDeps(count) {
108
+ const prev = skippedDeps;
109
+ skippedDeps = count;
110
+ return prev;
111
+ }
112
+ function setUntrackedWrites(writes) {
113
+ const prev = untrackedWrites;
114
+ untrackedWrites = writes;
115
+ return prev;
116
+ }
117
+ function addUntrackedWrite(signal) {
118
+ if (untrackedWrites === null) {
119
+ untrackedWrites = [signal];
120
+ } else {
121
+ untrackedWrites.push(signal);
122
+ }
123
+ }
124
+ function incrementBatchDepth() {
125
+ return ++batchDepth;
126
+ }
127
+ function decrementBatchDepth() {
128
+ return --batchDepth;
129
+ }
130
+ function setIsFlushingSync(value) {
131
+ const prev = isFlushingSync;
132
+ isFlushingSync = value;
133
+ return prev;
134
+ }
135
+ function clearPendingReactions() {
136
+ pendingReactions = new Set;
137
+ }
138
+ function addPendingReaction(reaction) {
139
+ pendingReactions.add(reaction);
140
+ }
141
+ function clearQueuedRootEffects() {
142
+ const prev = queuedRootEffects;
143
+ queuedRootEffects = [];
144
+ return prev;
145
+ }
146
+ function addQueuedRootEffect(effect) {
147
+ queuedRootEffects.push(effect);
148
+ }
149
+ function getReadVersion() {
150
+ return readVersion;
151
+ }
152
+ function getWriteVersion() {
153
+ return writeVersion;
154
+ }
155
+ function getBatchDepth() {
156
+ return batchDepth;
157
+ }
158
+
159
+ // src/reactivity/scheduling.ts
160
+ function scheduleEffect(reaction) {
161
+ addPendingReaction(reaction);
162
+ if (batchDepth > 0) {
163
+ return;
164
+ }
165
+ let effect = reaction;
166
+ while (effect.parent !== null) {
167
+ effect = effect.parent;
168
+ const flags = effect.f;
169
+ if ((flags & (ROOT_EFFECT | BRANCH_EFFECT)) !== 0) {
170
+ if ((flags & CLEAN) === 0) {
171
+ return;
172
+ }
173
+ effect.f ^= CLEAN;
174
+ }
175
+ }
176
+ addQueuedRootEffect(effect);
177
+ if (!isFlushingSync) {
178
+ queueMicrotask(flushEffects);
179
+ }
180
+ }
181
+ var updateEffectImpl = () => {
182
+ throw new Error("updateEffect not initialized - import effect.ts first");
183
+ };
184
+ function setUpdateEffectImpl(impl) {
185
+ updateEffectImpl = impl;
186
+ }
187
+ function flushEffects() {
188
+ const roots = clearQueuedRootEffects();
189
+ for (const root of roots) {
190
+ if (isDirty(root)) {
191
+ updateEffectImpl(root);
192
+ }
193
+ processEffectTree(root);
194
+ }
195
+ }
196
+ function processEffectTree(effect) {
197
+ let child = effect.first;
198
+ while (child !== null) {
199
+ const next = child.next;
200
+ if (isDirty(child)) {
201
+ updateEffectImpl(child);
202
+ }
203
+ if (child.first !== null) {
204
+ processEffectTree(child);
205
+ }
206
+ child = next;
207
+ }
208
+ }
209
+ function flushPendingReactions() {
210
+ const reactions = [...pendingReactions];
211
+ clearPendingReactions();
212
+ for (const reaction of reactions) {
213
+ if (isDirty(reaction)) {
214
+ if ("parent" in reaction) {
215
+ updateEffectImpl(reaction);
216
+ }
217
+ }
218
+ }
219
+ }
220
+ var MAX_FLUSH_COUNT = 1000;
221
+ function flushSync(fn) {
222
+ const wasFlushingSync = isFlushingSync;
223
+ setIsFlushingSync(true);
224
+ try {
225
+ let result;
226
+ let flushCount = 0;
227
+ if (fn) {
228
+ flushEffects();
229
+ result = fn();
230
+ }
231
+ while (true) {
232
+ if (++flushCount > MAX_FLUSH_COUNT) {
233
+ throw new Error("Maximum update depth exceeded. This can happen when an effect " + "continuously triggers itself. Check for effects that write to " + "signals they depend on without proper guards.");
234
+ }
235
+ const roots = clearQueuedRootEffects();
236
+ if (roots.length === 0) {
237
+ if (pendingReactions.size === 0) {
238
+ return result;
40
239
  }
41
- return proxyCache;
240
+ flushPendingReactions();
241
+ continue;
42
242
  }
43
- return internal.v;
44
- },
45
- set value(newValue) {
46
- if (!internal.equals(internal.v, newValue)) {
47
- internal.v = newValue;
48
- proxyCache = null;
49
- trigger(internal);
243
+ for (const root of roots) {
244
+ if (isDirty(root)) {
245
+ updateEffectImpl(root);
246
+ }
247
+ processEffectTree(root);
50
248
  }
51
249
  }
52
- };
250
+ } finally {
251
+ setIsFlushingSync(wasFlushingSync);
252
+ }
53
253
  }
54
- function effect(fn) {
55
- const reaction = {
56
- execute: () => {
57
- if (reaction.cleanup) {
58
- reaction.cleanup();
59
- reaction.cleanup = undefined;
60
- }
61
- for (const dep of reaction.deps) {
62
- dep.reactions.delete(reaction);
63
- }
64
- reaction.deps.clear();
65
- reactionStack.push(reaction);
66
- const prevReaction = activeReaction;
67
- activeReaction = reaction;
68
- try {
69
- const cleanup = fn();
70
- if (typeof cleanup === "function") {
71
- reaction.cleanup = cleanup;
254
+ async function tick() {
255
+ await Promise.resolve();
256
+ flushSync();
257
+ }
258
+
259
+ // src/reactivity/tracking.ts
260
+ function get(signal) {
261
+ if (activeReaction !== null && !untracking) {
262
+ if ((activeReaction.f & REACTION_IS_UPDATING) !== 0) {
263
+ if (signal.rv < readVersion) {
264
+ signal.rv = readVersion;
265
+ const deps = activeReaction.deps;
266
+ if (newDeps === null && deps !== null && deps[skippedDeps] === signal) {
267
+ setSkippedDeps(skippedDeps + 1);
268
+ } else {
269
+ if (newDeps === null) {
270
+ setNewDeps([signal]);
271
+ } else {
272
+ newDeps.push(signal);
273
+ }
72
274
  }
73
- } finally {
74
- activeReaction = prevReaction;
75
- reactionStack.pop();
76
275
  }
77
- },
78
- deps: new Set,
79
- active: true
80
- };
81
- reaction.execute();
82
- return () => {
83
- if (!reaction.active)
84
- return;
85
- reaction.active = false;
86
- if (reaction.cleanup) {
87
- reaction.cleanup();
276
+ } else {
277
+ if (activeReaction.deps === null) {
278
+ activeReaction.deps = [signal];
279
+ } else if (!activeReaction.deps.includes(signal)) {
280
+ activeReaction.deps.push(signal);
281
+ }
282
+ if (signal.reactions === null) {
283
+ signal.reactions = [activeReaction];
284
+ } else if (!signal.reactions.includes(activeReaction)) {
285
+ signal.reactions.push(activeReaction);
286
+ }
88
287
  }
89
- for (const dep of reaction.deps) {
90
- dep.reactions.delete(reaction);
288
+ }
289
+ if ((signal.f & DERIVED) !== 0) {
290
+ const derived = signal;
291
+ if (isDirty(derived)) {
292
+ updateDerived(derived);
91
293
  }
92
- reaction.deps.clear();
93
- };
294
+ }
295
+ return signal.v;
94
296
  }
95
- function derived(fn, options) {
96
- const internal = {
97
- v: undefined,
98
- reactions: new Set,
99
- equals: options?.equals ?? defaultEquals,
100
- fn,
101
- dirty: true
102
- };
103
- const deps = new Set;
104
- const markDirty = () => {
105
- if (!internal.dirty) {
106
- internal.dirty = true;
107
- trigger(internal);
297
+ function set(signal, value) {
298
+ if (activeReaction !== null && (activeReaction.f & DERIVED) !== 0) {
299
+ throw new Error("Cannot write to signals inside a derived. " + "Deriveds should be pure computations with no side effects.");
300
+ }
301
+ if (!signal.equals(signal.v, value)) {
302
+ signal.v = value;
303
+ signal.wv = incrementWriteVersion();
304
+ markReactions(signal, DIRTY);
305
+ if (activeEffect !== null && (activeEffect.f & CLEAN) !== 0 && (activeEffect.f & (ROOT_EFFECT | BRANCH_EFFECT)) === 0) {
306
+ addUntrackedWrite(signal);
108
307
  }
109
- };
110
- const recompute = () => {
111
- for (const dep of deps) {
112
- dep.reactions.delete(derivedReaction);
308
+ }
309
+ return value;
310
+ }
311
+ function markReactions(signal, status) {
312
+ const reactions = signal.reactions;
313
+ if (reactions === null)
314
+ return;
315
+ for (let i = 0;i < reactions.length; i++) {
316
+ const reaction = reactions[i];
317
+ const flags = reaction.f;
318
+ const notDirty = (flags & DIRTY) === 0;
319
+ if (notDirty) {
320
+ setSignalStatus(reaction, status);
113
321
  }
114
- deps.clear();
115
- const prevReaction = activeReaction;
116
- activeReaction = derivedReaction;
117
- try {
118
- const newValue = fn();
119
- internal.v = newValue;
120
- } finally {
121
- activeReaction = prevReaction;
322
+ if ((flags & DERIVED) !== 0) {
323
+ markReactions(reaction, MAYBE_DIRTY);
324
+ } else if (notDirty) {
325
+ scheduleEffect(reaction);
122
326
  }
123
- internal.dirty = false;
124
- };
125
- const derivedReaction = {
126
- execute: markDirty,
127
- deps,
128
- active: true
129
- };
130
- return {
131
- get value() {
132
- track(internal);
133
- if (internal.dirty) {
134
- recompute();
135
- }
136
- return internal.v;
137
- }
138
- };
327
+ }
139
328
  }
140
- derived.by = derived;
141
- function batch(fn) {
142
- batchDepth++;
143
- try {
144
- return fn();
145
- } finally {
146
- batchDepth--;
147
- if (batchDepth === 0) {
148
- flushPending();
329
+ function setSignalStatus(signal, status) {
330
+ signal.f = signal.f & STATUS_MASK | status;
331
+ }
332
+ function isDirty(reaction) {
333
+ if ((reaction.f & DIRTY) !== 0) {
334
+ return true;
335
+ }
336
+ if ((reaction.f & MAYBE_DIRTY) !== 0) {
337
+ const deps = reaction.deps;
338
+ if (deps !== null) {
339
+ for (let i = 0;i < deps.length; i++) {
340
+ const dep = deps[i];
341
+ if ((dep.f & DERIVED) !== 0) {
342
+ if (isDirty(dep)) {
343
+ updateDerived(dep);
344
+ }
345
+ }
346
+ if (dep.wv > reaction.wv) {
347
+ return true;
348
+ }
349
+ }
149
350
  }
351
+ setSignalStatus(reaction, CLEAN);
150
352
  }
353
+ return false;
151
354
  }
152
- function untrack(fn) {
153
- const prev = untracking;
154
- untracking = true;
155
- try {
156
- return fn();
157
- } finally {
158
- untracking = prev;
355
+ var updateDerivedImpl = () => {
356
+ throw new Error("updateDerived not initialized - import derived.ts first");
357
+ };
358
+ function updateDerived(derived) {
359
+ updateDerivedImpl(derived);
360
+ }
361
+ function setUpdateDerivedImpl(impl) {
362
+ updateDerivedImpl = impl;
363
+ }
364
+ function removeReactions(reaction, start) {
365
+ const deps = reaction.deps;
366
+ if (deps === null)
367
+ return;
368
+ for (let i = start;i < deps.length; i++) {
369
+ removeReaction(reaction, deps[i]);
159
370
  }
160
371
  }
161
- function track(signal2) {
162
- if (activeReaction && !untracking) {
163
- activeReaction.deps.add(signal2);
164
- signal2.reactions.add(activeReaction);
372
+ function removeReaction(reaction, dep) {
373
+ const reactions = dep.reactions;
374
+ if (reactions === null)
375
+ return;
376
+ const index = reactions.indexOf(reaction);
377
+ if (index !== -1) {
378
+ const last = reactions.length - 1;
379
+ if (index !== last) {
380
+ reactions[index] = reactions[last];
381
+ }
382
+ reactions.pop();
383
+ if (reactions.length === 0) {
384
+ dep.reactions = null;
385
+ }
165
386
  }
166
387
  }
167
- function trigger(signal2) {
168
- const reactions = [...signal2.reactions];
169
- for (const reaction of reactions) {
170
- if (!reaction.active)
171
- continue;
172
- if ("dirty" in reaction) {
173
- reaction.dirty = true;
388
+ function updateReaction(reaction) {
389
+ const prevNewDeps = newDeps;
390
+ const prevSkippedDeps = skippedDeps;
391
+ const prevReaction = activeReaction;
392
+ const prevUntrackedWrites = untrackedWrites;
393
+ setNewDeps(null);
394
+ setSkippedDeps(0);
395
+ setActiveReaction(reaction);
396
+ setUntrackedWrites(null);
397
+ const prevReadVersion = readVersion;
398
+ incrementReadVersion();
399
+ reaction.f |= REACTION_IS_UPDATING;
400
+ try {
401
+ const result = reaction.fn();
402
+ const deps = reaction.deps;
403
+ if (newDeps !== null) {
404
+ removeReactions(reaction, skippedDeps);
405
+ if (deps !== null && skippedDeps > 0) {
406
+ deps.length = skippedDeps + newDeps.length;
407
+ for (let i = 0;i < newDeps.length; i++) {
408
+ deps[skippedDeps + i] = newDeps[i];
409
+ }
410
+ } else {
411
+ reaction.deps = newDeps;
412
+ }
413
+ const finalDeps = reaction.deps;
414
+ for (let i = skippedDeps;i < finalDeps.length; i++) {
415
+ const dep = finalDeps[i];
416
+ if (dep.reactions === null) {
417
+ dep.reactions = [reaction];
418
+ } else {
419
+ dep.reactions.push(reaction);
420
+ }
421
+ }
422
+ } else if (deps !== null && skippedDeps < deps.length) {
423
+ removeReactions(reaction, skippedDeps);
424
+ deps.length = skippedDeps;
425
+ }
426
+ if (untrackedWrites !== null && reaction.deps !== null && (reaction.f & EFFECT) !== 0 && (reaction.f & DERIVED) === 0) {
427
+ for (const signal of untrackedWrites) {
428
+ if (reaction.deps.includes(signal)) {
429
+ setSignalStatus(reaction, DIRTY);
430
+ scheduleEffect(reaction);
431
+ break;
432
+ }
433
+ }
174
434
  }
175
- if (batchDepth > 0) {
176
- pendingReactions.add(reaction);
435
+ return result;
436
+ } finally {
437
+ reaction.f &= ~REACTION_IS_UPDATING;
438
+ setNewDeps(prevNewDeps);
439
+ setSkippedDeps(prevSkippedDeps);
440
+ setActiveReaction(prevReaction);
441
+ if (untrackedWrites !== null) {
442
+ if (prevUntrackedWrites === null) {
443
+ setUntrackedWrites(untrackedWrites);
444
+ } else {
445
+ prevUntrackedWrites.push(...untrackedWrites);
446
+ setUntrackedWrites(prevUntrackedWrites);
447
+ }
177
448
  } else {
178
- reaction.execute();
449
+ setUntrackedWrites(prevUntrackedWrites);
179
450
  }
180
451
  }
181
452
  }
182
- function flushPending() {
183
- const reactions = [...pendingReactions];
184
- pendingReactions.clear();
185
- for (const reaction of reactions) {
186
- if (reaction.active) {
187
- reaction.execute();
453
+
454
+ // src/primitives/signal.ts
455
+ function source(initialValue, options) {
456
+ return {
457
+ f: 0,
458
+ v: initialValue,
459
+ equals: options?.equals ?? equals,
460
+ reactions: null,
461
+ rv: 0,
462
+ wv: 0
463
+ };
464
+ }
465
+ function mutableSource(initialValue) {
466
+ return source(initialValue, { equals: safeEquals });
467
+ }
468
+ function signal(initialValue, options) {
469
+ const src = source(initialValue, options);
470
+ return {
471
+ get value() {
472
+ return get(src);
473
+ },
474
+ set value(newValue) {
475
+ set(src, newValue);
188
476
  }
477
+ };
478
+ }
479
+ var proxyFn = null;
480
+ function setProxyFn(fn) {
481
+ proxyFn = fn;
482
+ }
483
+ function state(initialValue) {
484
+ if (proxyFn === null) {
485
+ throw new Error("state() requires proxy to be initialized. Import from index.ts.");
189
486
  }
487
+ return proxyFn(initialValue);
190
488
  }
191
- var REACTIVE_MARKER = Symbol("reactive");
192
- function state(initial) {
193
- return createDeepReactive(initial);
489
+ function stateRaw(initialValue) {
490
+ return signal(initialValue);
194
491
  }
492
+
493
+ // src/deep/proxy.ts
195
494
  function shouldProxy(value) {
196
- if (value === null || typeof value !== "object")
197
- return false;
198
- if (value[REACTIVE_MARKER])
495
+ if (value === null || typeof value !== "object") {
199
496
  return false;
497
+ }
200
498
  const proto = Object.getPrototypeOf(value);
201
499
  return proto === Object.prototype || proto === Array.prototype || proto === null;
202
500
  }
203
- function createDeepReactive(target) {
204
- const existing = rawToProxy.get(target);
205
- if (existing)
206
- return existing;
207
- const internal = {
208
- v: target,
209
- reactions: new Set,
210
- equals: defaultEquals
501
+ function isProxy(value) {
502
+ return value !== null && typeof value === "object" && STATE_SYMBOL in value;
503
+ }
504
+ function isWritable(target, prop) {
505
+ const descriptor = Object.getOwnPropertyDescriptor(target, prop);
506
+ return descriptor === undefined || descriptor.writable === true;
507
+ }
508
+ function proxy(value) {
509
+ if (!shouldProxy(value) || isProxy(value)) {
510
+ return value;
511
+ }
512
+ const sources = new Map;
513
+ const version = source(0);
514
+ const isArray = Array.isArray(value);
515
+ if (isArray) {
516
+ sources.set("length", source(value.length));
517
+ }
518
+ const parentReadVersion = readVersion;
519
+ const withParent = (fn) => {
520
+ if (readVersion === parentReadVersion) {
521
+ return fn();
522
+ }
523
+ const prevReaction = activeReaction;
524
+ setActiveReaction(null);
525
+ try {
526
+ return fn();
527
+ } finally {
528
+ setActiveReaction(prevReaction);
529
+ }
211
530
  };
212
- const propSignals = new Map;
213
- const getPropSignal = (prop) => {
214
- let sig = propSignals.get(prop);
215
- if (!sig) {
216
- sig = {
217
- v: target[prop],
218
- reactions: new Set,
219
- equals: defaultEquals
220
- };
221
- propSignals.set(prop, sig);
531
+ const getSource = (prop, initialValue) => {
532
+ let s = sources.get(prop);
533
+ if (s === undefined) {
534
+ s = withParent(() => {
535
+ const proxied = shouldProxy(initialValue) ? proxy(initialValue) : initialValue;
536
+ return source(proxied);
537
+ });
538
+ sources.set(prop, s);
222
539
  }
223
- return sig;
540
+ return s;
224
541
  };
225
- const proxy = new Proxy(target, {
226
- get(target2, prop, receiver) {
227
- if (prop === REACTIVE_MARKER)
228
- return true;
229
- const value = Reflect.get(target2, prop, receiver);
230
- if (Array.isArray(target2) && typeof value === "function") {
231
- track(internal);
232
- return value.bind(proxy);
233
- }
234
- const sig = getPropSignal(prop);
235
- track(sig);
236
- if (shouldProxy(value)) {
237
- const existingProxy = rawToProxy.get(value);
238
- if (existingProxy)
239
- return existingProxy;
240
- return createDeepReactive(value);
241
- }
242
- return value;
243
- },
244
- set(target2, prop, value, receiver) {
245
- const oldValue = target2[prop];
246
- const rawValue = value?.[REACTIVE_MARKER] ? proxyToRaw.get(value) ?? value : value;
247
- if (Object.is(oldValue, rawValue))
248
- return true;
249
- const result = Reflect.set(target2, prop, rawValue, receiver);
250
- if (result) {
251
- const sig = getPropSignal(prop);
252
- sig.v = rawValue;
253
- trigger(sig);
254
- if (Array.isArray(target2)) {
255
- internal.v = target2;
256
- trigger(internal);
542
+ const proxyObj = new Proxy(value, {
543
+ get(target, prop, receiver) {
544
+ if (prop === STATE_SYMBOL) {
545
+ return value;
546
+ }
547
+ const exists = prop in target;
548
+ const currentValue = Reflect.get(target, prop, receiver);
549
+ if (isArray && typeof currentValue === "function") {
550
+ get(version);
551
+ return currentValue.bind(proxyObj);
552
+ }
553
+ if (exists || isWritable(target, prop)) {
554
+ const s = getSource(prop, currentValue);
555
+ const val = get(s);
556
+ if (val === UNINITIALIZED) {
557
+ return;
257
558
  }
559
+ return val;
258
560
  }
259
- return result;
561
+ return currentValue;
260
562
  },
261
- deleteProperty(target2, prop) {
262
- const hadKey = prop in target2;
263
- const result = Reflect.deleteProperty(target2, prop);
264
- if (result && hadKey) {
265
- const sig = propSignals.get(prop);
266
- if (sig) {
267
- sig.v = undefined;
268
- trigger(sig);
563
+ set(target, prop, newValue, receiver) {
564
+ const exists = prop in target;
565
+ let s = sources.get(prop);
566
+ if (s === undefined) {
567
+ if (!exists && !isWritable(target, prop)) {
568
+ return false;
269
569
  }
270
- trigger(internal);
570
+ s = withParent(() => source(undefined));
571
+ sources.set(prop, s);
271
572
  }
272
- return result;
273
- },
274
- has(target2, prop) {
275
- if (prop === REACTIVE_MARKER)
276
- return true;
277
- track(internal);
278
- return Reflect.has(target2, prop);
279
- },
280
- ownKeys(target2) {
281
- track(internal);
282
- return Reflect.ownKeys(target2);
283
- }
284
- });
285
- rawToProxy.set(target, proxy);
286
- proxyToRaw.set(proxy, target);
287
- proxyToSignal.set(proxy, internal);
288
- return proxy;
289
- }
290
- var proxyToRaw = new WeakMap;
291
- var signalProxyCache = new WeakMap;
292
- function createDeepReactiveForSignal(target, parentSignal) {
293
- const existingProxy = signalProxyCache.get(target);
294
- if (existingProxy)
295
- return existingProxy;
296
- const propSignals = new Map;
297
- const getPropSignal = (prop) => {
298
- let sig = propSignals.get(prop);
299
- if (!sig) {
300
- sig = {
301
- v: target[prop],
302
- reactions: new Set,
303
- equals: defaultEquals
304
- };
305
- propSignals.set(prop, sig);
306
- }
307
- return sig;
308
- };
309
- const internal = {
310
- v: target,
311
- reactions: new Set,
312
- equals: defaultEquals
313
- };
314
- const proxy = new Proxy(target, {
315
- get(target2, prop, receiver) {
316
- if (prop === REACTIVE_MARKER)
317
- return true;
318
- const value = Reflect.get(target2, prop, receiver);
319
- if (Array.isArray(target2) && typeof value === "function") {
320
- track(internal);
321
- return value.bind(proxy);
322
- }
323
- const sig = getPropSignal(prop);
324
- track(sig);
325
- if (value !== null && typeof value === "object") {
326
- const proto = Object.getPrototypeOf(value);
327
- if (proto === Object.prototype || proto === Array.prototype || proto === null) {
328
- if (!value[REACTIVE_MARKER]) {
329
- return createDeepReactiveForSignal(value, parentSignal);
573
+ const proxied = withParent(() => shouldProxy(newValue) ? proxy(newValue) : newValue);
574
+ set(s, proxied);
575
+ Reflect.set(target, prop, newValue, receiver);
576
+ if (isArray && prop === "length") {
577
+ const oldLength = s.v;
578
+ const newLength = newValue;
579
+ for (let i = newLength;i < oldLength; i++) {
580
+ const indexKey = String(i);
581
+ const indexSource = sources.get(indexKey);
582
+ if (indexSource !== undefined) {
583
+ set(indexSource, UNINITIALIZED);
584
+ } else if (i in target) {
585
+ const deletedSource = withParent(() => source(UNINITIALIZED));
586
+ sources.set(indexKey, deletedSource);
330
587
  }
331
588
  }
332
589
  }
333
- return value;
334
- },
335
- set(target2, prop, value, receiver) {
336
- const oldValue = target2[prop];
337
- const rawValue = value?.[REACTIVE_MARKER] ? proxyToRaw.get(value) ?? value : value;
338
- if (Object.is(oldValue, rawValue))
339
- return true;
340
- const result = Reflect.set(target2, prop, rawValue, receiver);
341
- if (result) {
342
- batch(() => {
343
- const sig = getPropSignal(prop);
344
- sig.v = rawValue;
345
- trigger(sig);
346
- trigger(parentSignal);
347
- if (Array.isArray(target2)) {
348
- internal.v = target2;
349
- trigger(internal);
590
+ if (isArray && typeof prop === "string") {
591
+ const index = Number(prop);
592
+ if (Number.isInteger(index) && index >= 0) {
593
+ const lengthSource = sources.get("length");
594
+ if (lengthSource !== undefined && index >= lengthSource.v) {
595
+ set(lengthSource, index + 1);
350
596
  }
351
- });
597
+ }
598
+ }
599
+ if (!exists) {
600
+ set(version, get(version) + 1);
352
601
  }
353
- return result;
602
+ return true;
354
603
  },
355
- deleteProperty(target2, prop) {
356
- const hadKey = prop in target2;
357
- const result = Reflect.deleteProperty(target2, prop);
358
- if (result && hadKey) {
359
- batch(() => {
360
- const sig = propSignals.get(prop);
361
- if (sig) {
362
- sig.v = undefined;
363
- trigger(sig);
364
- }
365
- trigger(parentSignal);
366
- trigger(internal);
367
- });
604
+ deleteProperty(target, prop) {
605
+ const exists = prop in target;
606
+ if (exists) {
607
+ let s = sources.get(prop);
608
+ if (s === undefined) {
609
+ s = withParent(() => source(UNINITIALIZED));
610
+ sources.set(prop, s);
611
+ } else {
612
+ set(s, UNINITIALIZED);
613
+ }
614
+ set(version, get(version) + 1);
368
615
  }
369
- return result;
616
+ return Reflect.deleteProperty(target, prop);
370
617
  },
371
- has(target2, prop) {
372
- if (prop === REACTIVE_MARKER)
618
+ has(target, prop) {
619
+ if (prop === STATE_SYMBOL) {
373
620
  return true;
374
- track(internal);
375
- return Reflect.has(target2, prop);
621
+ }
622
+ get(version);
623
+ const s = sources.get(prop);
624
+ if (s !== undefined) {
625
+ const val = get(s);
626
+ if (val === UNINITIALIZED) {
627
+ return false;
628
+ }
629
+ }
630
+ return Reflect.has(target, prop);
376
631
  },
377
- ownKeys(target2) {
378
- track(internal);
379
- return Reflect.ownKeys(target2);
632
+ ownKeys(target) {
633
+ get(version);
634
+ const keys = Reflect.ownKeys(target).filter((key) => {
635
+ const s = sources.get(key);
636
+ return s === undefined || s.v !== UNINITIALIZED;
637
+ });
638
+ for (const [key, s] of sources) {
639
+ const k = key;
640
+ if (s.v !== UNINITIALIZED && !(key in target) && !keys.includes(k)) {
641
+ keys.push(k);
642
+ }
643
+ }
644
+ return keys;
645
+ },
646
+ getOwnPropertyDescriptor(target, prop) {
647
+ const s = sources.get(prop);
648
+ if (s !== undefined && s.v === UNINITIALIZED) {
649
+ return;
650
+ }
651
+ return Reflect.getOwnPropertyDescriptor(target, prop);
380
652
  }
381
653
  });
382
- signalProxyCache.set(target, proxy);
383
- proxyToRaw.set(proxy, target);
384
- return proxy;
654
+ return proxyObj;
385
655
  }
386
- function toRaw(proxy) {
387
- if (proxy && typeof proxy === "object" && proxy[REACTIVE_MARKER]) {
388
- return proxyToRaw.get(proxy) ?? proxy;
656
+ function toRaw(value) {
657
+ if (value !== null && typeof value === "object" && STATE_SYMBOL in value) {
658
+ return value[STATE_SYMBOL];
389
659
  }
390
- return proxy;
660
+ return value;
391
661
  }
392
662
  function isReactive(value) {
393
- return value !== null && typeof value === "object" && value[REACTIVE_MARKER] === true;
663
+ return isProxy(value);
394
664
  }
395
-
665
+ // src/primitives/derived.ts
666
+ function createDerived(fn, options) {
667
+ let flags = DERIVED | DIRTY;
668
+ const parentDerived = activeReaction !== null && (activeReaction.f & DERIVED) !== 0 ? activeReaction : null;
669
+ if (activeEffect === null || parentDerived !== null && (parentDerived.f & UNOWNED) !== 0) {
670
+ flags |= UNOWNED;
671
+ }
672
+ const derived = {
673
+ f: flags,
674
+ fn,
675
+ v: UNINITIALIZED,
676
+ equals: options?.equals ?? equals,
677
+ reactions: null,
678
+ deps: null,
679
+ effects: null,
680
+ parent: parentDerived ?? activeEffect,
681
+ rv: 0,
682
+ wv: 0
683
+ };
684
+ return derived;
685
+ }
686
+ function executeDerived(derived) {
687
+ destroyDerivedEffects(derived);
688
+ const value = updateReaction(derived);
689
+ return value;
690
+ }
691
+ function updateDerived2(derived) {
692
+ const value = executeDerived(derived);
693
+ if (!derived.equals(derived.v, value)) {
694
+ derived.v = value;
695
+ derived.wv = incrementWriteVersion();
696
+ }
697
+ const status = (derived.f & UNOWNED) !== 0 && derived.deps !== null ? MAYBE_DIRTY : CLEAN;
698
+ setSignalStatus(derived, status);
699
+ }
700
+ setUpdateDerivedImpl(updateDerived2);
701
+ var destroyEffectImpl = () => {};
702
+ function setDestroyEffectImpl(impl) {
703
+ destroyEffectImpl = impl;
704
+ }
705
+ function destroyDerivedEffects(derived) {
706
+ const effects = derived.effects;
707
+ if (effects !== null) {
708
+ derived.effects = null;
709
+ for (let i = 0;i < effects.length; i++) {
710
+ destroyEffectImpl(effects[i]);
711
+ }
712
+ }
713
+ }
714
+ function derived(fn, options) {
715
+ const d = createDerived(fn, options);
716
+ return {
717
+ get value() {
718
+ return get(d);
719
+ }
720
+ };
721
+ }
722
+ derived.by = derived;
723
+ function disconnectDerived(derived2) {
724
+ removeReactions(derived2, 0);
725
+ derived2.deps = null;
726
+ derived2.reactions = null;
727
+ destroyDerivedEffects(derived2);
728
+ }
729
+ // src/primitives/effect.ts
730
+ function createEffect(type, fn, sync, push = true) {
731
+ const parent = activeEffect;
732
+ const effect = {
733
+ f: type | DIRTY,
734
+ fn,
735
+ deps: null,
736
+ teardown: null,
737
+ parent,
738
+ first: null,
739
+ last: null,
740
+ prev: null,
741
+ next: null,
742
+ wv: 0
743
+ };
744
+ if (sync) {
745
+ updateEffect(effect);
746
+ effect.f |= EFFECT_RAN;
747
+ } else if (fn !== null) {
748
+ scheduleEffect(effect);
749
+ }
750
+ if (push && parent !== null) {
751
+ pushEffect(effect, parent);
752
+ }
753
+ return effect;
754
+ }
755
+ function pushEffect(effect, parent) {
756
+ const parentLast = parent.last;
757
+ if (parentLast === null) {
758
+ parent.first = parent.last = effect;
759
+ } else {
760
+ parentLast.next = effect;
761
+ effect.prev = parentLast;
762
+ parent.last = effect;
763
+ }
764
+ }
765
+ function updateEffect(effect) {
766
+ if ((effect.f & DESTROYED) !== 0)
767
+ return;
768
+ setSignalStatus(effect, CLEAN);
769
+ const prevEffect = activeEffect;
770
+ setActiveEffect(effect);
771
+ try {
772
+ destroyEffectChildren(effect);
773
+ executeTeardown(effect);
774
+ const teardown = updateReaction(effect);
775
+ effect.teardown = typeof teardown === "function" ? teardown : null;
776
+ effect.wv = incrementWriteVersion();
777
+ } finally {
778
+ setActiveEffect(prevEffect);
779
+ }
780
+ }
781
+ setUpdateEffectImpl(updateEffect);
782
+ function destroyEffect(effect, removeFromParent = true) {
783
+ destroyEffectChildren(effect);
784
+ removeReactions(effect, 0);
785
+ setSignalStatus(effect, DESTROYED);
786
+ executeTeardown(effect);
787
+ if (removeFromParent && effect.parent !== null) {
788
+ unlinkEffect(effect);
789
+ }
790
+ effect.fn = null;
791
+ effect.teardown = null;
792
+ effect.deps = null;
793
+ effect.first = null;
794
+ effect.last = null;
795
+ effect.prev = null;
796
+ effect.next = null;
797
+ }
798
+ setDestroyEffectImpl(destroyEffect);
799
+ function destroyEffectChildren(effect) {
800
+ let child = effect.first;
801
+ effect.first = null;
802
+ effect.last = null;
803
+ while (child !== null) {
804
+ const next = child.next;
805
+ if ((child.f & (EFFECT_PRESERVED | ROOT_EFFECT)) === 0) {
806
+ destroyEffect(child, false);
807
+ }
808
+ child = next;
809
+ }
810
+ }
811
+ function executeTeardown(effect) {
812
+ const teardown = effect.teardown;
813
+ if (teardown !== null) {
814
+ effect.teardown = null;
815
+ teardown();
816
+ }
817
+ }
818
+ function unlinkEffect(effect) {
819
+ const { parent, prev, next } = effect;
820
+ if (prev !== null) {
821
+ prev.next = next;
822
+ }
823
+ if (next !== null) {
824
+ next.prev = prev;
825
+ }
826
+ if (parent !== null) {
827
+ if (parent.first === effect) {
828
+ parent.first = next;
829
+ }
830
+ if (parent.last === effect) {
831
+ parent.last = prev;
832
+ }
833
+ }
834
+ effect.prev = null;
835
+ effect.next = null;
836
+ }
837
+ function effect(fn) {
838
+ const eff = createEffect(EFFECT | USER_EFFECT, fn, false);
839
+ return () => destroyEffect(eff);
840
+ }
841
+ effect.pre = function effectPre(fn) {
842
+ const eff = createEffect(RENDER_EFFECT | USER_EFFECT, fn, true);
843
+ return () => destroyEffect(eff);
844
+ };
845
+ effect.root = function effectRoot(fn) {
846
+ const eff = createEffect(ROOT_EFFECT | EFFECT_PRESERVED, fn, true);
847
+ return () => destroyEffect(eff);
848
+ };
849
+ effect.tracking = function effectTracking() {
850
+ return activeEffect !== null;
851
+ };
852
+ // src/primitives/bind.ts
853
+ var BINDING_SYMBOL = Symbol("binding");
854
+ function isBinding(value) {
855
+ return value !== null && typeof value === "object" && BINDING_SYMBOL in value;
856
+ }
857
+ function bind(source2) {
858
+ const binding = {
859
+ [BINDING_SYMBOL]: true,
860
+ get value() {
861
+ return source2.value;
862
+ },
863
+ set value(v) {
864
+ source2.value = v;
865
+ }
866
+ };
867
+ return binding;
868
+ }
869
+ function bindReadonly(source2) {
870
+ return {
871
+ [BINDING_SYMBOL]: true,
872
+ get value() {
873
+ return source2.value;
874
+ }
875
+ };
876
+ }
877
+ function unwrap(value) {
878
+ if (isBinding(value)) {
879
+ return value.value;
880
+ }
881
+ return value;
882
+ }
883
+ // src/reactivity/batching.ts
884
+ function batch(fn) {
885
+ incrementBatchDepth();
886
+ try {
887
+ return fn();
888
+ } finally {
889
+ const depth = decrementBatchDepth();
890
+ if (depth === 0) {
891
+ flushPendingReactions();
892
+ }
893
+ }
894
+ }
895
+ function untrack(fn) {
896
+ const prev = setUntracking(true);
897
+ try {
898
+ return fn();
899
+ } finally {
900
+ setUntracking(prev);
901
+ }
902
+ }
903
+ var peek = untrack;
904
+ // src/collections/map.ts
396
905
  class ReactiveMap extends Map {
397
906
  #keySignals = new Map;
398
- #version = { v: 0, reactions: new Set, equals: defaultEquals };
399
- #size = { v: 0, reactions: new Set, equals: defaultEquals };
907
+ #version = source(0);
908
+ #size;
400
909
  constructor(entries) {
401
- super();
402
- if (entries) {
403
- for (const [key, value] of entries) {
404
- super.set(key, value);
405
- }
406
- this.#size.v = super.size;
407
- }
910
+ super(entries);
911
+ this.#size = source(super.size);
408
912
  }
409
913
  #getKeySignal(key) {
410
914
  let sig = this.#keySignals.get(key);
411
- if (!sig) {
412
- sig = { v: 0, reactions: new Set, equals: defaultEquals };
915
+ if (sig === undefined) {
916
+ sig = source(0);
413
917
  this.#keySignals.set(key, sig);
414
918
  }
415
919
  return sig;
416
920
  }
921
+ #increment(sig) {
922
+ set(sig, sig.v + 1);
923
+ }
417
924
  get size() {
418
- track(this.#size);
925
+ get(this.#size);
419
926
  return super.size;
420
927
  }
421
928
  has(key) {
422
- const sig = this.#getKeySignal(key);
423
- track(sig);
929
+ const sig = this.#keySignals.get(key);
930
+ if (sig === undefined) {
931
+ if (!super.has(key)) {
932
+ get(this.#version);
933
+ return false;
934
+ }
935
+ const newSig = this.#getKeySignal(key);
936
+ get(newSig);
937
+ return true;
938
+ }
939
+ get(sig);
424
940
  return super.has(key);
425
941
  }
426
942
  get(key) {
427
- const sig = this.#getKeySignal(key);
428
- track(sig);
943
+ const sig = this.#keySignals.get(key);
944
+ if (sig === undefined) {
945
+ const val = super.get(key);
946
+ if (val !== undefined) {
947
+ const newSig = this.#getKeySignal(key);
948
+ get(newSig);
949
+ return val;
950
+ }
951
+ get(this.#version);
952
+ return;
953
+ }
954
+ get(sig);
429
955
  return super.get(key);
430
956
  }
431
957
  set(key, value) {
@@ -434,347 +960,480 @@ class ReactiveMap extends Map {
434
960
  super.set(key, value);
435
961
  const sig = this.#getKeySignal(key);
436
962
  if (isNew) {
437
- this.#size.v = super.size;
438
- trigger(this.#size);
439
- this.#version.v++;
440
- trigger(this.#version);
441
- sig.v++;
442
- trigger(sig);
963
+ set(this.#size, super.size);
964
+ this.#increment(this.#version);
965
+ this.#increment(sig);
443
966
  } else if (!Object.is(oldValue, value)) {
444
- sig.v++;
445
- trigger(sig);
967
+ this.#increment(sig);
968
+ const versionReactions = this.#version.reactions;
969
+ const keyReactions = sig.reactions;
970
+ if (keyReactions !== null && (versionReactions === null || !keyReactions.every((r) => versionReactions.includes(r)))) {
971
+ this.#increment(this.#version);
972
+ }
446
973
  }
447
974
  return this;
448
975
  }
449
976
  delete(key) {
450
- const had = super.has(key);
451
- const result = super.delete(key);
452
- if (had) {
977
+ const existed = super.has(key);
978
+ if (existed) {
979
+ super.delete(key);
453
980
  const sig = this.#keySignals.get(key);
454
- if (sig) {
455
- sig.v = -1;
456
- trigger(sig);
981
+ if (sig !== undefined) {
982
+ set(sig, -1);
457
983
  this.#keySignals.delete(key);
458
984
  }
459
- this.#size.v = super.size;
460
- trigger(this.#size);
461
- this.#version.v++;
462
- trigger(this.#version);
985
+ set(this.#size, super.size);
986
+ this.#increment(this.#version);
463
987
  }
464
- return result;
988
+ return existed;
465
989
  }
466
990
  clear() {
467
- if (super.size === 0)
468
- return;
469
- for (const sig of this.#keySignals.values()) {
470
- sig.v = -1;
471
- trigger(sig);
991
+ if (super.size > 0) {
992
+ for (const [key, sig] of this.#keySignals) {
993
+ set(sig, -1);
994
+ }
995
+ this.#keySignals.clear();
996
+ super.clear();
997
+ set(this.#size, 0);
998
+ this.#increment(this.#version);
472
999
  }
473
- super.clear();
474
- this.#keySignals.clear();
475
- this.#size.v = 0;
476
- trigger(this.#size);
477
- this.#version.v++;
478
- trigger(this.#version);
479
- }
480
- forEach(callbackfn, thisArg) {
481
- track(this.#version);
482
- super.forEach(callbackfn, thisArg);
483
1000
  }
484
1001
  keys() {
485
- track(this.#version);
1002
+ get(this.#version);
486
1003
  return super.keys();
487
1004
  }
488
1005
  values() {
489
- track(this.#version);
1006
+ get(this.#version);
490
1007
  return super.values();
491
1008
  }
492
1009
  entries() {
493
- track(this.#version);
1010
+ get(this.#version);
494
1011
  return super.entries();
495
1012
  }
1013
+ forEach(callbackfn, thisArg) {
1014
+ get(this.#version);
1015
+ super.forEach(callbackfn, thisArg);
1016
+ }
496
1017
  [Symbol.iterator]() {
497
1018
  return this.entries();
498
1019
  }
499
1020
  }
500
-
1021
+ // src/collections/set.ts
501
1022
  class ReactiveSet extends Set {
502
1023
  #itemSignals = new Map;
503
- #version = { v: 0, reactions: new Set, equals: defaultEquals };
504
- #size = { v: 0, reactions: new Set, equals: defaultEquals };
1024
+ #version = source(0);
1025
+ #size;
505
1026
  constructor(values) {
506
- super();
507
- if (values) {
508
- for (const value of values) {
509
- super.add(value);
510
- }
511
- this.#size.v = super.size;
512
- }
1027
+ super(values);
1028
+ this.#size = source(super.size);
513
1029
  }
514
1030
  #getItemSignal(item) {
515
1031
  let sig = this.#itemSignals.get(item);
516
- if (!sig) {
517
- sig = { v: super.has(item), reactions: new Set, equals: defaultEquals };
1032
+ if (sig === undefined) {
1033
+ sig = source(super.has(item));
518
1034
  this.#itemSignals.set(item, sig);
519
1035
  }
520
1036
  return sig;
521
1037
  }
1038
+ #incrementVersion() {
1039
+ set(this.#version, this.#version.v + 1);
1040
+ }
522
1041
  get size() {
523
- track(this.#size);
1042
+ get(this.#size);
524
1043
  return super.size;
525
1044
  }
526
- has(value) {
527
- const sig = this.#getItemSignal(value);
528
- track(sig);
529
- return super.has(value);
530
- }
531
- add(value) {
532
- if (!super.has(value)) {
533
- super.add(value);
534
- const sig = this.#getItemSignal(value);
535
- sig.v = true;
536
- trigger(sig);
537
- this.#size.v = super.size;
538
- trigger(this.#size);
539
- this.#version.v++;
540
- trigger(this.#version);
1045
+ has(item) {
1046
+ const sig = this.#itemSignals.get(item);
1047
+ if (sig === undefined) {
1048
+ const exists = super.has(item);
1049
+ if (exists) {
1050
+ const newSig = this.#getItemSignal(item);
1051
+ get(newSig);
1052
+ return true;
1053
+ }
1054
+ get(this.#version);
1055
+ return false;
1056
+ }
1057
+ get(sig);
1058
+ return super.has(item);
1059
+ }
1060
+ add(item) {
1061
+ const isNew = !super.has(item);
1062
+ super.add(item);
1063
+ if (isNew) {
1064
+ const sig = this.#getItemSignal(item);
1065
+ set(sig, true);
1066
+ set(this.#size, super.size);
1067
+ this.#incrementVersion();
541
1068
  }
542
1069
  return this;
543
1070
  }
544
- delete(value) {
545
- const had = super.has(value);
546
- const result = super.delete(value);
547
- if (had) {
548
- const sig = this.#itemSignals.get(value);
549
- if (sig) {
550
- sig.v = false;
551
- trigger(sig);
552
- this.#itemSignals.delete(value);
553
- }
554
- this.#size.v = super.size;
555
- trigger(this.#size);
556
- this.#version.v++;
557
- trigger(this.#version);
1071
+ delete(item) {
1072
+ const existed = super.has(item);
1073
+ if (existed) {
1074
+ super.delete(item);
1075
+ const sig = this.#itemSignals.get(item);
1076
+ if (sig !== undefined) {
1077
+ set(sig, false);
1078
+ this.#itemSignals.delete(item);
1079
+ }
1080
+ set(this.#size, super.size);
1081
+ this.#incrementVersion();
558
1082
  }
559
- return result;
1083
+ return existed;
560
1084
  }
561
1085
  clear() {
562
- if (super.size === 0)
563
- return;
564
- for (const sig of this.#itemSignals.values()) {
565
- sig.v = false;
566
- trigger(sig);
1086
+ if (super.size > 0) {
1087
+ for (const [item, sig] of this.#itemSignals) {
1088
+ set(sig, false);
1089
+ }
1090
+ this.#itemSignals.clear();
1091
+ super.clear();
1092
+ set(this.#size, 0);
1093
+ this.#incrementVersion();
567
1094
  }
568
- super.clear();
569
- this.#itemSignals.clear();
570
- this.#size.v = 0;
571
- trigger(this.#size);
572
- this.#version.v++;
573
- trigger(this.#version);
574
- }
575
- forEach(callbackfn, thisArg) {
576
- track(this.#version);
577
- super.forEach(callbackfn, thisArg);
578
1095
  }
579
1096
  keys() {
580
- track(this.#version);
1097
+ get(this.#version);
581
1098
  return super.keys();
582
1099
  }
583
1100
  values() {
584
- track(this.#version);
1101
+ get(this.#version);
585
1102
  return super.values();
586
1103
  }
587
1104
  entries() {
588
- track(this.#version);
1105
+ get(this.#version);
589
1106
  return super.entries();
590
1107
  }
1108
+ forEach(callbackfn, thisArg) {
1109
+ get(this.#version);
1110
+ super.forEach(callbackfn, thisArg);
1111
+ }
591
1112
  [Symbol.iterator]() {
592
1113
  return this.values();
593
1114
  }
594
1115
  }
595
- function reactiveArray(initial = []) {
596
- const internal = {
597
- v: 0,
598
- reactions: new Set,
599
- equals: defaultEquals
600
- };
601
- const indexSignals = new Map;
602
- const lengthSignal = {
603
- v: initial.length,
604
- reactions: new Set,
605
- equals: defaultEquals
606
- };
607
- const getIndexSignal = (index) => {
608
- let sig = indexSignals.get(index);
609
- if (!sig) {
610
- sig = { v: initial[index], reactions: new Set, equals: defaultEquals };
611
- indexSignals.set(index, sig);
1116
+ // src/collections/date.ts
1117
+ class ReactiveDate extends Date {
1118
+ #time;
1119
+ constructor(...args) {
1120
+ super(...args);
1121
+ this.#time = source(super.getTime());
1122
+ }
1123
+ #update() {
1124
+ const time = super.getTime();
1125
+ set(this.#time, time);
1126
+ return time;
1127
+ }
1128
+ getTime() {
1129
+ get(this.#time);
1130
+ return super.getTime();
1131
+ }
1132
+ getFullYear() {
1133
+ get(this.#time);
1134
+ return super.getFullYear();
1135
+ }
1136
+ getMonth() {
1137
+ get(this.#time);
1138
+ return super.getMonth();
1139
+ }
1140
+ getDate() {
1141
+ get(this.#time);
1142
+ return super.getDate();
1143
+ }
1144
+ getDay() {
1145
+ get(this.#time);
1146
+ return super.getDay();
1147
+ }
1148
+ getHours() {
1149
+ get(this.#time);
1150
+ return super.getHours();
1151
+ }
1152
+ getMinutes() {
1153
+ get(this.#time);
1154
+ return super.getMinutes();
1155
+ }
1156
+ getSeconds() {
1157
+ get(this.#time);
1158
+ return super.getSeconds();
1159
+ }
1160
+ getMilliseconds() {
1161
+ get(this.#time);
1162
+ return super.getMilliseconds();
1163
+ }
1164
+ getUTCFullYear() {
1165
+ get(this.#time);
1166
+ return super.getUTCFullYear();
1167
+ }
1168
+ getUTCMonth() {
1169
+ get(this.#time);
1170
+ return super.getUTCMonth();
1171
+ }
1172
+ getUTCDate() {
1173
+ get(this.#time);
1174
+ return super.getUTCDate();
1175
+ }
1176
+ getUTCDay() {
1177
+ get(this.#time);
1178
+ return super.getUTCDay();
1179
+ }
1180
+ getUTCHours() {
1181
+ get(this.#time);
1182
+ return super.getUTCHours();
1183
+ }
1184
+ getUTCMinutes() {
1185
+ get(this.#time);
1186
+ return super.getUTCMinutes();
1187
+ }
1188
+ getUTCSeconds() {
1189
+ get(this.#time);
1190
+ return super.getUTCSeconds();
1191
+ }
1192
+ getUTCMilliseconds() {
1193
+ get(this.#time);
1194
+ return super.getUTCMilliseconds();
1195
+ }
1196
+ getTimezoneOffset() {
1197
+ get(this.#time);
1198
+ return super.getTimezoneOffset();
1199
+ }
1200
+ setTime(time) {
1201
+ super.setTime(time);
1202
+ return this.#update();
1203
+ }
1204
+ setFullYear(year, month, date) {
1205
+ if (date !== undefined) {
1206
+ super.setFullYear(year, month, date);
1207
+ } else if (month !== undefined) {
1208
+ super.setFullYear(year, month);
1209
+ } else {
1210
+ super.setFullYear(year);
612
1211
  }
613
- return sig;
614
- };
615
- const array = [...initial];
616
- const proxy = new Proxy(array, {
617
- get(target, prop, receiver) {
618
- if (prop === "length") {
619
- track(lengthSignal);
620
- return target.length;
621
- }
622
- const index = typeof prop === "string" ? parseInt(prop, 10) : NaN;
623
- if (!isNaN(index)) {
624
- const sig = getIndexSignal(index);
625
- track(sig);
626
- return target[index];
627
- }
628
- const value = Reflect.get(target, prop, receiver);
629
- if (typeof value === "function") {
630
- return function(...args) {
631
- const method = prop;
632
- if (["indexOf", "includes", "find", "findIndex", "some", "every", "forEach", "map", "filter", "reduce", "reduceRight", "join", "toString"].includes(method)) {
633
- track(internal);
634
- return value.apply(target, args);
635
- }
636
- const prevLength = target.length;
637
- const result = value.apply(target, args);
638
- const newLength = target.length;
639
- if (newLength !== prevLength) {
640
- lengthSignal.v = newLength;
641
- trigger(lengthSignal);
642
- }
643
- if (["push", "pop", "shift", "unshift", "splice", "sort", "reverse", "fill", "copyWithin"].includes(method)) {
644
- internal.v++;
645
- trigger(internal);
646
- for (let i = 0;i < Math.max(prevLength, newLength); i++) {
647
- const sig = indexSignals.get(i);
648
- if (sig && !Object.is(sig.v, target[i])) {
649
- sig.v = target[i];
650
- trigger(sig);
651
- }
652
- }
653
- }
654
- return result;
655
- };
656
- }
657
- return value;
658
- },
659
- set(target, prop, value, receiver) {
660
- if (prop === "length") {
661
- const oldLength = target.length;
662
- target.length = value;
663
- if (oldLength !== value) {
664
- lengthSignal.v = value;
665
- trigger(lengthSignal);
666
- internal.v++;
667
- trigger(internal);
668
- }
669
- return true;
670
- }
671
- const index = typeof prop === "string" ? parseInt(prop, 10) : NaN;
672
- if (!isNaN(index)) {
673
- const oldValue = target[index];
674
- if (!Object.is(oldValue, value)) {
675
- target[index] = value;
676
- const sig = getIndexSignal(index);
677
- sig.v = value;
678
- trigger(sig);
679
- if (index >= lengthSignal.v) {
680
- lengthSignal.v = target.length;
681
- trigger(lengthSignal);
682
- }
683
- internal.v++;
684
- trigger(internal);
685
- }
686
- return true;
687
- }
688
- return Reflect.set(target, prop, value, receiver);
1212
+ return this.#update();
1213
+ }
1214
+ setMonth(month, date) {
1215
+ if (date !== undefined) {
1216
+ super.setMonth(month, date);
1217
+ } else {
1218
+ super.setMonth(month);
689
1219
  }
690
- });
691
- return proxy;
692
- }
693
- function effectScope() {
694
- const disposers = [];
695
- let active = true;
696
- return {
697
- run(fn) {
698
- if (!active)
699
- return;
700
- const originalEffect = effect;
701
- globalThis.__signalEffect = effect;
702
- const wrappedEffect = (effectFn) => {
703
- const dispose = originalEffect(effectFn);
704
- disposers.push(dispose);
705
- return dispose;
706
- };
707
- const prevEffect = globalThis.__effectOverride;
708
- globalThis.__effectOverride = wrappedEffect;
709
- try {
710
- return fn();
711
- } finally {
712
- globalThis.__effectOverride = prevEffect;
713
- }
714
- },
715
- stop() {
716
- if (!active)
717
- return;
718
- active = false;
719
- for (const dispose of disposers) {
720
- dispose();
721
- }
722
- disposers.length = 0;
723
- },
724
- get active() {
725
- return active;
1220
+ return this.#update();
1221
+ }
1222
+ setDate(date) {
1223
+ super.setDate(date);
1224
+ return this.#update();
1225
+ }
1226
+ setHours(hours, min, sec, ms) {
1227
+ if (ms !== undefined) {
1228
+ super.setHours(hours, min, sec, ms);
1229
+ } else if (sec !== undefined) {
1230
+ super.setHours(hours, min, sec);
1231
+ } else if (min !== undefined) {
1232
+ super.setHours(hours, min);
1233
+ } else {
1234
+ super.setHours(hours);
726
1235
  }
727
- };
728
- }
729
- function watch(source, callback, options) {
730
- let oldValue;
731
- let cleanup;
732
- let first = true;
733
- return effect(() => {
734
- const newValue = source();
735
- if (first) {
736
- first = false;
737
- oldValue = newValue;
738
- if (options?.immediate) {
739
- cleanup = callback(newValue, undefined);
740
- }
741
- return;
1236
+ return this.#update();
1237
+ }
1238
+ setMinutes(min, sec, ms) {
1239
+ if (ms !== undefined) {
1240
+ super.setMinutes(min, sec, ms);
1241
+ } else if (sec !== undefined) {
1242
+ super.setMinutes(min, sec);
1243
+ } else {
1244
+ super.setMinutes(min);
742
1245
  }
743
- if (!Object.is(newValue, oldValue)) {
744
- if (typeof cleanup === "function") {
745
- cleanup();
746
- }
747
- cleanup = callback(newValue, oldValue);
748
- oldValue = newValue;
1246
+ return this.#update();
1247
+ }
1248
+ setSeconds(sec, ms) {
1249
+ if (ms !== undefined) {
1250
+ super.setSeconds(sec, ms);
1251
+ } else {
1252
+ super.setSeconds(sec);
749
1253
  }
750
- });
751
- }
752
- function readonly(sig) {
753
- return {
754
- get value() {
755
- return sig.value;
1254
+ return this.#update();
1255
+ }
1256
+ setMilliseconds(ms) {
1257
+ super.setMilliseconds(ms);
1258
+ return this.#update();
1259
+ }
1260
+ setUTCFullYear(year, month, date) {
1261
+ if (date !== undefined) {
1262
+ super.setUTCFullYear(year, month, date);
1263
+ } else if (month !== undefined) {
1264
+ super.setUTCFullYear(year, month);
1265
+ } else {
1266
+ super.setUTCFullYear(year);
756
1267
  }
757
- };
758
- }
759
- function peek(fn) {
760
- return untrack(fn);
1268
+ return this.#update();
1269
+ }
1270
+ setUTCMonth(month, date) {
1271
+ if (date !== undefined) {
1272
+ super.setUTCMonth(month, date);
1273
+ } else {
1274
+ super.setUTCMonth(month);
1275
+ }
1276
+ return this.#update();
1277
+ }
1278
+ setUTCDate(date) {
1279
+ super.setUTCDate(date);
1280
+ return this.#update();
1281
+ }
1282
+ setUTCHours(hours, min, sec, ms) {
1283
+ if (ms !== undefined) {
1284
+ super.setUTCHours(hours, min, sec, ms);
1285
+ } else if (sec !== undefined) {
1286
+ super.setUTCHours(hours, min, sec);
1287
+ } else if (min !== undefined) {
1288
+ super.setUTCHours(hours, min);
1289
+ } else {
1290
+ super.setUTCHours(hours);
1291
+ }
1292
+ return this.#update();
1293
+ }
1294
+ setUTCMinutes(min, sec, ms) {
1295
+ if (ms !== undefined) {
1296
+ super.setUTCMinutes(min, sec, ms);
1297
+ } else if (sec !== undefined) {
1298
+ super.setUTCMinutes(min, sec);
1299
+ } else {
1300
+ super.setUTCMinutes(min);
1301
+ }
1302
+ return this.#update();
1303
+ }
1304
+ setUTCSeconds(sec, ms) {
1305
+ if (ms !== undefined) {
1306
+ super.setUTCSeconds(sec, ms);
1307
+ } else {
1308
+ super.setUTCSeconds(sec);
1309
+ }
1310
+ return this.#update();
1311
+ }
1312
+ setUTCMilliseconds(ms) {
1313
+ super.setUTCMilliseconds(ms);
1314
+ return this.#update();
1315
+ }
1316
+ toString() {
1317
+ get(this.#time);
1318
+ return super.toString();
1319
+ }
1320
+ toDateString() {
1321
+ get(this.#time);
1322
+ return super.toDateString();
1323
+ }
1324
+ toTimeString() {
1325
+ get(this.#time);
1326
+ return super.toTimeString();
1327
+ }
1328
+ toISOString() {
1329
+ get(this.#time);
1330
+ return super.toISOString();
1331
+ }
1332
+ toUTCString() {
1333
+ get(this.#time);
1334
+ return super.toUTCString();
1335
+ }
1336
+ toLocaleString(locales, options) {
1337
+ get(this.#time);
1338
+ return super.toLocaleString(locales, options);
1339
+ }
1340
+ toLocaleDateString(locales, options) {
1341
+ get(this.#time);
1342
+ return super.toLocaleDateString(locales, options);
1343
+ }
1344
+ toLocaleTimeString(locales, options) {
1345
+ get(this.#time);
1346
+ return super.toLocaleTimeString(locales, options);
1347
+ }
1348
+ toJSON() {
1349
+ get(this.#time);
1350
+ return super.toJSON();
1351
+ }
1352
+ valueOf() {
1353
+ get(this.#time);
1354
+ return super.valueOf();
1355
+ }
761
1356
  }
1357
+
1358
+ // src/index.ts
1359
+ setProxyFn(proxy);
762
1360
  export {
763
- watch,
1361
+ writeVersion,
1362
+ updateReaction,
1363
+ updateEffect,
1364
+ unwrap,
1365
+ untracking,
764
1366
  untrack,
765
1367
  toRaw,
1368
+ tick,
1369
+ stateRaw,
766
1370
  state,
1371
+ source,
767
1372
  signal,
768
1373
  shallowEquals,
769
- readonly,
770
- reactiveArray,
1374
+ setUntracking,
1375
+ setSignalStatus,
1376
+ setActiveReaction,
1377
+ setActiveEffect,
1378
+ set,
1379
+ safeNotEqual,
1380
+ safeEquals,
1381
+ removeReactions,
1382
+ readVersion,
1383
+ proxy,
771
1384
  peek,
1385
+ neverEquals,
1386
+ mutableSource,
1387
+ markReactions,
772
1388
  isReactive,
773
- effectScope,
1389
+ isDirty,
1390
+ isBinding,
1391
+ incrementWriteVersion,
1392
+ incrementReadVersion,
1393
+ incrementBatchDepth,
1394
+ getWriteVersion,
1395
+ getReadVersion,
1396
+ getBatchDepth,
1397
+ get,
1398
+ flushSync,
1399
+ equals,
774
1400
  effect,
1401
+ disconnectDerived,
1402
+ destroyEffect,
775
1403
  derived,
776
- defaultEquals,
1404
+ decrementBatchDepth,
1405
+ createEquals,
1406
+ createEffect,
1407
+ createDerived,
1408
+ bindReadonly,
1409
+ bind,
1410
+ batchDepth,
777
1411
  batch,
1412
+ alwaysEquals,
1413
+ activeReaction,
1414
+ activeEffect,
1415
+ USER_EFFECT,
1416
+ UNOWNED,
1417
+ UNINITIALIZED,
1418
+ STATE_SYMBOL,
1419
+ STALE_REACTION,
778
1420
  ReactiveSet,
779
- ReactiveMap
1421
+ ReactiveMap,
1422
+ ReactiveDate,
1423
+ ROOT_EFFECT,
1424
+ RENDER_EFFECT,
1425
+ REACTIVE_MARKER,
1426
+ REACTION_IS_UPDATING,
1427
+ MAYBE_DIRTY,
1428
+ INERT,
1429
+ EFFECT_RAN,
1430
+ EFFECT_PRESERVED,
1431
+ EFFECT,
1432
+ DISCONNECTED,
1433
+ DIRTY,
1434
+ DESTROYED,
1435
+ DERIVED,
1436
+ CLEAN,
1437
+ BRANCH_EFFECT,
1438
+ BLOCK_EFFECT
780
1439
  };