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