@rlabs-inc/signals 1.3.0 → 1.4.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 (48) hide show
  1. package/README.md +114 -0
  2. package/dist/core/constants.d.ts +6 -0
  3. package/dist/core/constants.d.ts.map +1 -1
  4. package/dist/deep/proxy.d.ts.map +1 -1
  5. package/dist/index.d.ts +7 -1
  6. package/dist/index.d.ts.map +1 -1
  7. package/dist/index.js +430 -56
  8. package/dist/index.mjs +430 -56
  9. package/dist/primitives/bind.d.ts.map +1 -1
  10. package/dist/primitives/effect.d.ts.map +1 -1
  11. package/dist/primitives/linked.d.ts +73 -0
  12. package/dist/primitives/linked.d.ts.map +1 -0
  13. package/dist/primitives/scope.d.ts +96 -0
  14. package/dist/primitives/scope.d.ts.map +1 -0
  15. package/dist/primitives/selector.d.ts +46 -0
  16. package/dist/primitives/selector.d.ts.map +1 -0
  17. package/dist/reactivity/scheduling.d.ts.map +1 -1
  18. package/dist/reactivity/tracking.d.ts +5 -0
  19. package/dist/reactivity/tracking.d.ts.map +1 -1
  20. package/dist/v2/bench-compare.d.ts +2 -0
  21. package/dist/v2/bench-compare.d.ts.map +1 -0
  22. package/dist/v2/bench.d.ts +5 -0
  23. package/dist/v2/bench.d.ts.map +1 -0
  24. package/dist/v2/bind.d.ts +94 -0
  25. package/dist/v2/bind.d.ts.map +1 -0
  26. package/dist/v2/collections.d.ts +133 -0
  27. package/dist/v2/collections.d.ts.map +1 -0
  28. package/dist/v2/compat-test.d.ts +2 -0
  29. package/dist/v2/compat-test.d.ts.map +1 -0
  30. package/dist/v2/debug-array.d.ts +2 -0
  31. package/dist/v2/debug-array.d.ts.map +1 -0
  32. package/dist/v2/debug-diamond.d.ts +2 -0
  33. package/dist/v2/debug-diamond.d.ts.map +1 -0
  34. package/dist/v2/index.d.ts +7 -0
  35. package/dist/v2/index.d.ts.map +1 -0
  36. package/dist/v2/primitives.d.ts +120 -0
  37. package/dist/v2/primitives.d.ts.map +1 -0
  38. package/dist/v2/proxy.d.ts +10 -0
  39. package/dist/v2/proxy.d.ts.map +1 -0
  40. package/dist/v2/registry.d.ts +35 -0
  41. package/dist/v2/registry.d.ts.map +1 -0
  42. package/dist/v2/stress.d.ts +7 -0
  43. package/dist/v2/stress.d.ts.map +1 -0
  44. package/dist/v2/test-suite.d.ts +2 -0
  45. package/dist/v2/test-suite.d.ts.map +1 -0
  46. package/dist/v2/test-v1.d.ts +2 -0
  47. package/dist/v2/test-v1.d.ts.map +1 -0
  48. package/package.json +7 -1
package/dist/index.mjs CHANGED
@@ -63,6 +63,9 @@ var UNINITIALIZED = Symbol.for("rlabs.signals.uninitialized");
63
63
  var STALE_REACTION = Symbol.for("rlabs.signals.stale_reaction");
64
64
  var STATE_SYMBOL = Symbol.for("rlabs.signals.state");
65
65
  var REACTIVE_MARKER = Symbol.for("rlabs.signals.reactive");
66
+ var BINDING_SYMBOL = Symbol.for("rlabs.signals.binding");
67
+ var LINKED_SYMBOL = Symbol.for("rlabs.signals.linked");
68
+ var SOURCE = 1 << 0;
66
69
  var STATUS_MASK = ~(DIRTY | MAYBE_DIRTY | CLEAN);
67
70
 
68
71
  // src/core/globals.ts
@@ -187,6 +190,9 @@ function setUpdateEffectImpl(impl) {
187
190
  function flushEffects() {
188
191
  const roots = clearQueuedRootEffects();
189
192
  for (const root of roots) {
193
+ if ((root.f & INERT) !== 0) {
194
+ continue;
195
+ }
190
196
  if (isDirty(root)) {
191
197
  updateEffectImpl(root);
192
198
  }
@@ -197,7 +203,7 @@ function processEffectTree(effect) {
197
203
  let child = effect.first;
198
204
  while (child !== null) {
199
205
  const next = child.next;
200
- if (isDirty(child)) {
206
+ if ((child.f & INERT) === 0 && isDirty(child)) {
201
207
  updateEffectImpl(child);
202
208
  }
203
209
  if (child.first !== null) {
@@ -210,6 +216,9 @@ function flushPendingReactions() {
210
216
  const reactions = [...pendingReactions];
211
217
  clearPendingReactions();
212
218
  for (const reaction of reactions) {
219
+ if ((reaction.f & INERT) !== 0) {
220
+ continue;
221
+ }
213
222
  if (isDirty(reaction)) {
214
223
  if ("parent" in reaction) {
215
224
  updateEffectImpl(reaction);
@@ -241,6 +250,9 @@ function flushSync(fn) {
241
250
  continue;
242
251
  }
243
252
  for (const root of roots) {
253
+ if ((root.f & INERT) !== 0) {
254
+ continue;
255
+ }
244
256
  if (isDirty(root)) {
245
257
  updateEffectImpl(root);
246
258
  }
@@ -287,13 +299,63 @@ function get(signal) {
287
299
  }
288
300
  }
289
301
  if ((signal.f & DERIVED) !== 0) {
290
- const derived = signal;
291
- if (isDirty(derived)) {
292
- updateDerived(derived);
293
- }
302
+ updateDerivedChain(signal);
294
303
  }
295
304
  return signal.v;
296
305
  }
306
+ var updateCycleId = 0;
307
+ var processedInCycle = new WeakMap;
308
+ function updateDerivedChain(target) {
309
+ if ((target.f & (DIRTY | MAYBE_DIRTY)) === 0) {
310
+ return;
311
+ }
312
+ const cycleId = ++updateCycleId;
313
+ const chain = [target];
314
+ processedInCycle.set(target, cycleId);
315
+ let idx = 0;
316
+ while (idx < chain.length) {
317
+ const current = chain[idx];
318
+ idx++;
319
+ if ((current.f & (DIRTY | MAYBE_DIRTY)) === 0) {
320
+ continue;
321
+ }
322
+ const deps = current.deps;
323
+ if (deps !== null) {
324
+ for (let i = 0;i < deps.length; i++) {
325
+ const dep = deps[i];
326
+ if ((dep.f & DERIVED) !== 0 && (dep.f & (DIRTY | MAYBE_DIRTY)) !== 0 && processedInCycle.get(dep) !== cycleId) {
327
+ chain.push(dep);
328
+ processedInCycle.set(dep, cycleId);
329
+ }
330
+ }
331
+ }
332
+ }
333
+ for (let i = chain.length - 1;i >= 0; i--) {
334
+ const current = chain[i];
335
+ if ((current.f & (DIRTY | MAYBE_DIRTY)) === 0) {
336
+ continue;
337
+ }
338
+ if ((current.f & DIRTY) !== 0) {
339
+ updateDerived(current);
340
+ } else {
341
+ const deps = current.deps;
342
+ let needsUpdate = false;
343
+ if (deps !== null) {
344
+ for (let j = 0;j < deps.length; j++) {
345
+ if (deps[j].wv > current.wv) {
346
+ needsUpdate = true;
347
+ break;
348
+ }
349
+ }
350
+ }
351
+ if (needsUpdate) {
352
+ updateDerived(current);
353
+ } else {
354
+ setSignalStatus(current, CLEAN);
355
+ }
356
+ }
357
+ }
358
+ }
297
359
  function set(signal, value) {
298
360
  if (activeReaction !== null && (activeReaction.f & DERIVED) !== 0) {
299
361
  throw new Error("Cannot write to signals inside a derived. " + "Deriveds should be pure computations with no side effects.");
@@ -309,20 +371,24 @@ function set(signal, value) {
309
371
  return value;
310
372
  }
311
373
  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);
321
- }
322
- if ((flags & DERIVED) !== 0) {
323
- markReactions(reaction, MAYBE_DIRTY);
324
- } else if (notDirty) {
325
- scheduleEffect(reaction);
374
+ const stack = [{ signal, status }];
375
+ while (stack.length > 0) {
376
+ const { signal: currentSignal, status: currentStatus } = stack.pop();
377
+ const reactions = currentSignal.reactions;
378
+ if (reactions === null)
379
+ continue;
380
+ for (let i = 0;i < reactions.length; i++) {
381
+ const reaction = reactions[i];
382
+ const flags = reaction.f;
383
+ const notDirty = (flags & DIRTY) === 0;
384
+ if (notDirty) {
385
+ setSignalStatus(reaction, currentStatus);
386
+ }
387
+ if ((flags & DERIVED) !== 0) {
388
+ stack.push({ signal: reaction, status: MAYBE_DIRTY });
389
+ } else if (notDirty) {
390
+ scheduleEffect(reaction);
391
+ }
326
392
  }
327
393
  }
328
394
  }
@@ -333,22 +399,66 @@ function isDirty(reaction) {
333
399
  if ((reaction.f & DIRTY) !== 0) {
334
400
  return true;
335
401
  }
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
- }
402
+ if ((reaction.f & MAYBE_DIRTY) === 0) {
403
+ return false;
404
+ }
405
+ const toCheck = [reaction];
406
+ const toUpdate = [];
407
+ let idx = 0;
408
+ while (idx < toCheck.length) {
409
+ const current = toCheck[idx];
410
+ idx++;
411
+ if ((current.f & DIRTY) !== 0) {
412
+ continue;
413
+ }
414
+ if ((current.f & MAYBE_DIRTY) === 0) {
415
+ continue;
416
+ }
417
+ const deps2 = current.deps;
418
+ if (deps2 !== null) {
419
+ for (let i = 0;i < deps2.length; i++) {
420
+ const dep = deps2[i];
421
+ if ((dep.f & DERIVED) !== 0 && (dep.f & (DIRTY | MAYBE_DIRTY)) !== 0) {
422
+ toCheck.push(dep);
345
423
  }
346
- if (dep.wv > reaction.wv) {
347
- return true;
424
+ }
425
+ }
426
+ }
427
+ for (let i = toCheck.length - 1;i >= 0; i--) {
428
+ const current = toCheck[i];
429
+ if ((current.f & DERIVED) === 0) {
430
+ continue;
431
+ }
432
+ if ((current.f & DIRTY) !== 0) {
433
+ updateDerived(current);
434
+ } else if ((current.f & MAYBE_DIRTY) !== 0) {
435
+ const deps2 = current.deps;
436
+ let needsUpdate = false;
437
+ if (deps2 !== null) {
438
+ for (let j = 0;j < deps2.length; j++) {
439
+ if (deps2[j].wv > current.wv) {
440
+ needsUpdate = true;
441
+ break;
442
+ }
348
443
  }
349
444
  }
445
+ if (needsUpdate) {
446
+ updateDerived(current);
447
+ } else {
448
+ setSignalStatus(current, CLEAN);
449
+ }
450
+ }
451
+ }
452
+ if ((reaction.f & DIRTY) !== 0) {
453
+ return true;
454
+ }
455
+ const deps = reaction.deps;
456
+ if (deps !== null) {
457
+ for (let i = 0;i < deps.length; i++) {
458
+ if (deps[i].wv > reaction.wv) {
459
+ return true;
460
+ }
350
461
  }
351
- setSignalStatus(reaction, CLEAN);
352
462
  }
353
463
  return false;
354
464
  }
@@ -501,6 +611,7 @@ function stateRaw(initialValue) {
501
611
  }
502
612
 
503
613
  // src/deep/proxy.ts
614
+ var proxyCache = new WeakMap;
504
615
  var proxyCleanup = new FinalizationRegistry((data) => {
505
616
  data.version.reactions = null;
506
617
  for (const src of data.sources.values()) {
@@ -512,6 +623,9 @@ function shouldProxy(value) {
512
623
  if (value === null || typeof value !== "object") {
513
624
  return false;
514
625
  }
626
+ if (BINDING_SYMBOL in value) {
627
+ return false;
628
+ }
515
629
  const proto = Object.getPrototypeOf(value);
516
630
  return proto === Object.prototype || proto === Array.prototype || proto === null;
517
631
  }
@@ -526,6 +640,10 @@ function proxy(value) {
526
640
  if (!shouldProxy(value) || isProxy(value)) {
527
641
  return value;
528
642
  }
643
+ const cached = proxyCache.get(value);
644
+ if (cached) {
645
+ return cached;
646
+ }
529
647
  const sources = new Map;
530
648
  const version = source(0);
531
649
  const isArray = Array.isArray(value);
@@ -577,7 +695,7 @@ function proxy(value) {
577
695
  }
578
696
  return currentValue;
579
697
  },
580
- set(target, prop, newValue, receiver) {
698
+ set(target, prop, newValue) {
581
699
  const exists = prop in target;
582
700
  let s = sources.get(prop);
583
701
  if (s === undefined) {
@@ -587,29 +705,35 @@ function proxy(value) {
587
705
  s = withParent(() => source(undefined));
588
706
  sources.set(prop, s);
589
707
  }
590
- const proxied = withParent(() => shouldProxy(newValue) ? proxy(newValue) : newValue);
708
+ let proxied;
709
+ if (shouldProxy(newValue)) {
710
+ proxied = withParent(() => proxy(newValue));
711
+ } else {
712
+ proxied = newValue;
713
+ }
591
714
  set(s, proxied);
592
- Reflect.set(target, prop, newValue, receiver);
593
- if (isArray && prop === "length") {
594
- const oldLength = s.v;
595
- const newLength = newValue;
596
- for (let i = newLength;i < oldLength; i++) {
597
- const indexKey = String(i);
598
- const indexSource = sources.get(indexKey);
599
- if (indexSource !== undefined) {
600
- set(indexSource, UNINITIALIZED);
601
- } else if (i in target) {
602
- const deletedSource = withParent(() => source(UNINITIALIZED));
603
- sources.set(indexKey, deletedSource);
715
+ target[prop] = newValue;
716
+ if (isArray) {
717
+ if (prop === "length") {
718
+ const oldLength = s.v;
719
+ const newLength = newValue;
720
+ for (let i = newLength;i < oldLength; i++) {
721
+ const indexKey = String(i);
722
+ const indexSource = sources.get(indexKey);
723
+ if (indexSource !== undefined) {
724
+ set(indexSource, UNINITIALIZED);
725
+ } else if (i in target) {
726
+ const deletedSource = withParent(() => source(UNINITIALIZED));
727
+ sources.set(indexKey, deletedSource);
728
+ }
604
729
  }
605
- }
606
- }
607
- if (isArray && typeof prop === "string") {
608
- const index = Number(prop);
609
- if (Number.isInteger(index) && index >= 0) {
610
- const lengthSource = sources.get("length");
611
- if (lengthSource !== undefined && index >= lengthSource.v) {
612
- set(lengthSource, index + 1);
730
+ } else if (typeof prop === "string") {
731
+ const index = Number(prop);
732
+ if (Number.isInteger(index) && index >= 0) {
733
+ const lengthSource = sources.get("length");
734
+ if (lengthSource !== undefined && index >= lengthSource.v) {
735
+ set(lengthSource, index + 1);
736
+ }
613
737
  }
614
738
  }
615
739
  }
@@ -630,7 +754,7 @@ function proxy(value) {
630
754
  }
631
755
  set(version, get(version) + 1);
632
756
  }
633
- return Reflect.deleteProperty(target, prop);
757
+ return delete target[prop];
634
758
  },
635
759
  has(target, prop) {
636
760
  if (prop === STATE_SYMBOL) {
@@ -669,6 +793,7 @@ function proxy(value) {
669
793
  }
670
794
  });
671
795
  proxyCleanup.register(proxyObj, { sources, version });
796
+ proxyCache.set(value, proxyObj);
672
797
  return proxyObj;
673
798
  }
674
799
  function toRaw(value) {
@@ -758,6 +883,123 @@ function disconnectDerived(derived2) {
758
883
  derived2.reactions = null;
759
884
  destroyDerivedEffects(derived2);
760
885
  }
886
+ // src/primitives/scope.ts
887
+ var activeScope = null;
888
+ function getCurrentScope() {
889
+ return activeScope;
890
+ }
891
+ function setActiveScope(scope) {
892
+ const prev = activeScope;
893
+ activeScope = scope;
894
+ return prev;
895
+ }
896
+
897
+ class EffectScopeImpl {
898
+ _active = true;
899
+ _paused = false;
900
+ effects = [];
901
+ cleanups = [];
902
+ parent = null;
903
+ scopes = null;
904
+ constructor(detached = false) {
905
+ this.parent = activeScope;
906
+ if (!detached && this.parent) {
907
+ if (this.parent.scopes === null) {
908
+ this.parent.scopes = [];
909
+ }
910
+ this.parent.scopes.push(this);
911
+ }
912
+ }
913
+ get active() {
914
+ return this._active;
915
+ }
916
+ get paused() {
917
+ return this._paused;
918
+ }
919
+ run(fn) {
920
+ if (!this._active) {
921
+ return;
922
+ }
923
+ const prevScope = setActiveScope(this);
924
+ try {
925
+ return fn();
926
+ } finally {
927
+ setActiveScope(prevScope);
928
+ }
929
+ }
930
+ stop() {
931
+ if (!this._active)
932
+ return;
933
+ for (const effect of [...this.effects]) {
934
+ destroyEffect(effect);
935
+ }
936
+ this.effects.length = 0;
937
+ for (const cleanup of this.cleanups) {
938
+ try {
939
+ cleanup();
940
+ } catch {}
941
+ }
942
+ this.cleanups.length = 0;
943
+ if (this.scopes) {
944
+ for (const scope of this.scopes) {
945
+ scope.stop();
946
+ }
947
+ this.scopes.length = 0;
948
+ }
949
+ if (this.parent?.scopes) {
950
+ const idx = this.parent.scopes.indexOf(this);
951
+ if (idx !== -1) {
952
+ this.parent.scopes.splice(idx, 1);
953
+ }
954
+ }
955
+ this._active = false;
956
+ }
957
+ pause() {
958
+ if (!this._active || this._paused)
959
+ return;
960
+ this._paused = true;
961
+ for (const effect of this.effects) {
962
+ effect.f |= INERT;
963
+ }
964
+ if (this.scopes) {
965
+ for (const scope of this.scopes) {
966
+ scope.pause();
967
+ }
968
+ }
969
+ }
970
+ resume() {
971
+ if (!this._active || !this._paused)
972
+ return;
973
+ this._paused = false;
974
+ for (const effect of this.effects) {
975
+ effect.f &= ~INERT;
976
+ if ((effect.f & DIRTY) !== 0) {
977
+ scheduleEffect(effect);
978
+ }
979
+ }
980
+ if (this.scopes) {
981
+ for (const scope of this.scopes) {
982
+ scope.resume();
983
+ }
984
+ }
985
+ }
986
+ }
987
+ function effectScope(detached) {
988
+ return new EffectScopeImpl(detached);
989
+ }
990
+ function onScopeDispose(fn) {
991
+ if (activeScope) {
992
+ activeScope.cleanups.push(fn);
993
+ } else {
994
+ console.warn("onScopeDispose() called outside of scope context");
995
+ }
996
+ }
997
+ function registerEffectWithScope(effect) {
998
+ if (activeScope) {
999
+ activeScope.effects.push(effect);
1000
+ }
1001
+ }
1002
+
761
1003
  // src/primitives/effect.ts
762
1004
  function createEffect(type, fn, sync, push = true) {
763
1005
  const parent = activeEffect;
@@ -773,6 +1015,7 @@ function createEffect(type, fn, sync, push = true) {
773
1015
  next: null,
774
1016
  wv: 0
775
1017
  };
1018
+ registerEffectWithScope(effect);
776
1019
  if (sync) {
777
1020
  updateEffect(effect);
778
1021
  effect.f |= EFFECT_RAN;
@@ -885,7 +1128,6 @@ effect.tracking = function effectTracking() {
885
1128
  var bindingCleanup = new FinalizationRegistry((internalSource) => {
886
1129
  internalSource.reactions = null;
887
1130
  });
888
- var BINDING_SYMBOL = Symbol("binding");
889
1131
  function isBinding(value) {
890
1132
  return value !== null && typeof value === "object" && BINDING_SYMBOL in value;
891
1133
  }
@@ -971,6 +1213,130 @@ function untrack(fn) {
971
1213
  }
972
1214
  }
973
1215
  var peek = untrack;
1216
+
1217
+ // src/primitives/linked.ts
1218
+ function linkedSignal(config) {
1219
+ let sourceFn;
1220
+ let computation;
1221
+ let equalsFn = Object.is;
1222
+ if (typeof config === "function") {
1223
+ const fn = config;
1224
+ sourceFn = fn;
1225
+ computation = (s) => s;
1226
+ } else {
1227
+ sourceFn = config.source;
1228
+ computation = config.computation;
1229
+ if (config.equal) {
1230
+ equalsFn = config.equal;
1231
+ }
1232
+ }
1233
+ let prevSource = undefined;
1234
+ let prevValue = undefined;
1235
+ let initialized = false;
1236
+ const valueSignal = signal(undefined, { equals: equalsFn });
1237
+ const sourceTracker = derived(() => {
1238
+ const newSource = sourceFn();
1239
+ return newSource;
1240
+ });
1241
+ let manualOverride = false;
1242
+ let lastKnownSource = undefined;
1243
+ const dispose = effect.pre(() => {
1244
+ const currentSource = sourceTracker.value;
1245
+ const sourceChanged = initialized && !Object.is(lastKnownSource, currentSource);
1246
+ if (!initialized || sourceChanged) {
1247
+ const previous = initialized ? { source: prevSource, value: prevValue } : undefined;
1248
+ const newValue = computation(currentSource, previous);
1249
+ prevSource = currentSource;
1250
+ prevValue = newValue;
1251
+ lastKnownSource = currentSource;
1252
+ initialized = true;
1253
+ manualOverride = false;
1254
+ untrack(() => {
1255
+ valueSignal.value = newValue;
1256
+ });
1257
+ }
1258
+ });
1259
+ const accessor = {
1260
+ [LINKED_SYMBOL]: true,
1261
+ get value() {
1262
+ sourceTracker.value;
1263
+ const currentSource = untrack(() => sourceTracker.value);
1264
+ if (initialized && !Object.is(lastKnownSource, currentSource)) {
1265
+ flushSync();
1266
+ }
1267
+ return valueSignal.value;
1268
+ },
1269
+ set value(newValue) {
1270
+ manualOverride = true;
1271
+ prevValue = newValue;
1272
+ valueSignal.value = newValue;
1273
+ },
1274
+ get peek() {
1275
+ return untrack(() => valueSignal.value);
1276
+ }
1277
+ };
1278
+ return accessor;
1279
+ }
1280
+ function isLinkedSignal(value) {
1281
+ return value !== null && typeof value === "object" && LINKED_SYMBOL in value;
1282
+ }
1283
+ // src/primitives/selector.ts
1284
+ function createSelector(source2, fn = (k, v) => k === v) {
1285
+ const subscribers = new Map;
1286
+ const reactionKeys = new WeakMap;
1287
+ let prevValue;
1288
+ let initialized = false;
1289
+ effect.pre(() => {
1290
+ const value = source2();
1291
+ if (initialized && !Object.is(prevValue, value)) {
1292
+ for (const [key, reactions] of subscribers) {
1293
+ const wasSelected = fn(key, prevValue);
1294
+ const isSelected = fn(key, value);
1295
+ if (wasSelected !== isSelected) {
1296
+ const toRemove = [];
1297
+ for (const reaction of reactions) {
1298
+ if ((reaction.f & DESTROYED) !== 0) {
1299
+ toRemove.push(reaction);
1300
+ continue;
1301
+ }
1302
+ setSignalStatus(reaction, DIRTY);
1303
+ if ((reaction.f & EFFECT) !== 0 && (reaction.f & DERIVED) === 0) {
1304
+ scheduleEffect(reaction);
1305
+ }
1306
+ }
1307
+ for (const r of toRemove) {
1308
+ reactions.delete(r);
1309
+ }
1310
+ }
1311
+ }
1312
+ }
1313
+ prevValue = value;
1314
+ initialized = true;
1315
+ });
1316
+ return (key) => {
1317
+ const currentValue = prevValue;
1318
+ if (activeReaction !== null) {
1319
+ const reaction = activeReaction;
1320
+ if ((reaction.f & DESTROYED) === 0) {
1321
+ let keySubscribers = subscribers.get(key);
1322
+ if (!keySubscribers) {
1323
+ keySubscribers = new Set;
1324
+ subscribers.set(key, keySubscribers);
1325
+ }
1326
+ if (!keySubscribers.has(reaction)) {
1327
+ keySubscribers.add(reaction);
1328
+ let keys = reactionKeys.get(reaction);
1329
+ if (!keys) {
1330
+ keys = new Set;
1331
+ reactionKeys.set(reaction, keys);
1332
+ }
1333
+ keys.add(key);
1334
+ }
1335
+ }
1336
+ }
1337
+ return fn(key, currentValue);
1338
+ };
1339
+ }
974
1340
  // src/collections/map.ts
975
1341
  var mapCleanup = new FinalizationRegistry((data) => {
976
1342
  data.version.reactions = null;
@@ -1481,10 +1847,13 @@ export {
1481
1847
  readVersion,
1482
1848
  proxy,
1483
1849
  peek,
1850
+ onScopeDispose,
1484
1851
  neverEquals,
1485
1852
  mutableSource,
1486
1853
  markReactions,
1854
+ linkedSignal,
1487
1855
  isReactive,
1856
+ isLinkedSignal,
1488
1857
  isDirty,
1489
1858
  isBinding,
1490
1859
  incrementWriteVersion,
@@ -1492,15 +1861,18 @@ export {
1492
1861
  incrementBatchDepth,
1493
1862
  getWriteVersion,
1494
1863
  getReadVersion,
1864
+ getCurrentScope,
1495
1865
  getBatchDepth,
1496
1866
  get,
1497
1867
  flushSync,
1498
1868
  equals,
1869
+ effectScope,
1499
1870
  effect,
1500
1871
  disconnectDerived,
1501
1872
  destroyEffect,
1502
1873
  derived,
1503
1874
  decrementBatchDepth,
1875
+ createSelector,
1504
1876
  createEquals,
1505
1877
  createEffect,
1506
1878
  createDerived,
@@ -1524,6 +1896,7 @@ export {
1524
1896
  REACTIVE_MARKER,
1525
1897
  REACTION_IS_UPDATING,
1526
1898
  MAYBE_DIRTY,
1899
+ LINKED_SYMBOL,
1527
1900
  INERT,
1528
1901
  EFFECT_RAN,
1529
1902
  EFFECT_PRESERVED,
@@ -1534,5 +1907,6 @@ export {
1534
1907
  DERIVED,
1535
1908
  CLEAN,
1536
1909
  BRANCH_EFFECT,
1537
- BLOCK_EFFECT
1910
+ BLOCK_EFFECT,
1911
+ BINDING_SYMBOL
1538
1912
  };
@@ -1 +1 @@
1
- {"version":3,"file":"bind.d.ts","sourceRoot":"","sources":["../../src/primitives/bind.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAU,MAAM,kBAAkB,CAAA;AAqB9E;;;GAGG;AACH,MAAM,WAAW,OAAO,CAAC,CAAC;IACxB,IAAI,KAAK,IAAI,CAAC,CAAA;IACd,IAAI,KAAK,CAAC,CAAC,EAAE,CAAC,EAAC;CAChB;AAED;;;GAGG;AACH,MAAM,WAAW,eAAe,CAAC,CAAC;IAChC,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAA;CAClB;AAQD;;GAEG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,OAAO,CAAC,OAAO,CAAC,CAEnE;AA0DD,wBAAgB,IAAI,CAAC,CAAC,EAAE,MAAM,EAAE,cAAc,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAA;AAC9D,wBAAgB,IAAI,CAAC,CAAC,EAAE,MAAM,EAAE,cAAc,CAAC,CAAC,CAAC,GAAG,eAAe,CAAC,CAAC,CAAC,CAAA;AACtE,wBAAgB,IAAI,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAA;AACvD,wBAAgB,IAAI,CAAC,CAAC,EAAE,MAAM,EAAE,eAAe,CAAC,CAAC,CAAC,GAAG,eAAe,CAAC,CAAC,CAAC,CAAA;AACvE,wBAAgB,IAAI,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,GAAG,eAAe,CAAC,CAAC,CAAC,CAAA;AAC5D,wBAAgB,IAAI,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAA;AA2D9C;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,YAAY,CAAC,CAAC,EAAE,MAAM,EAAE,cAAc,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,GAAG,eAAe,CAAC,CAAC,CAAC,CAQ1F;AAMD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,MAAM,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,GAAG,eAAe,CAAC,CAAC,CAAC,GAAG,CAAC,CAKvE;AAMD;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,OAAO,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACvD,OAAO,EAAE,CAAC,GACT;KAAG,CAAC,IAAI,MAAM,CAAC,GAAG,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;CAAE,CAU1C"}
1
+ {"version":3,"file":"bind.d.ts","sourceRoot":"","sources":["../../src/primitives/bind.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAU,MAAM,kBAAkB,CAAA;AAsB9E;;;GAGG;AACH,MAAM,WAAW,OAAO,CAAC,CAAC;IACxB,IAAI,KAAK,IAAI,CAAC,CAAA;IACd,IAAI,KAAK,CAAC,CAAC,EAAE,CAAC,EAAC;CAChB;AAED;;;GAGG;AACH,MAAM,WAAW,eAAe,CAAC,CAAC;IAChC,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAA;CAClB;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,OAAO,CAAC,OAAO,CAAC,CAEnE;AA0DD,wBAAgB,IAAI,CAAC,CAAC,EAAE,MAAM,EAAE,cAAc,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAA;AAC9D,wBAAgB,IAAI,CAAC,CAAC,EAAE,MAAM,EAAE,cAAc,CAAC,CAAC,CAAC,GAAG,eAAe,CAAC,CAAC,CAAC,CAAA;AACtE,wBAAgB,IAAI,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAA;AACvD,wBAAgB,IAAI,CAAC,CAAC,EAAE,MAAM,EAAE,eAAe,CAAC,CAAC,CAAC,GAAG,eAAe,CAAC,CAAC,CAAC,CAAA;AACvE,wBAAgB,IAAI,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,GAAG,eAAe,CAAC,CAAC,CAAC,CAAA;AAC5D,wBAAgB,IAAI,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAA;AA2D9C;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,YAAY,CAAC,CAAC,EAAE,MAAM,EAAE,cAAc,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,GAAG,eAAe,CAAC,CAAC,CAAC,CAQ1F;AAMD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,MAAM,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,GAAG,eAAe,CAAC,CAAC,CAAC,GAAG,CAAC,CAKvE;AAMD;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,OAAO,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACvD,OAAO,EAAE,CAAC,GACT;KAAG,CAAC,IAAI,MAAM,CAAC,GAAG,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;CAAE,CAU1C"}
@@ -1 +1 @@
1
- {"version":3,"file":"effect.d.ts","sourceRoot":"","sources":["../../src/primitives/effect.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAa,SAAS,EAAE,MAAM,kBAAkB,CAAA;AA8B9E;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAC1B,IAAI,EAAE,MAAM,EACZ,EAAE,EAAE,QAAQ,GAAG,IAAI,EACnB,IAAI,EAAE,OAAO,EACb,IAAI,UAAO,GACV,MAAM,CA8BR;AAyBD;;GAEG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CA4BjD;AASD;;GAEG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,gBAAgB,UAAO,GAAG,IAAI,CA0B3E;AA8ED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,MAAM,CAAC,EAAE,EAAE,QAAQ,GAAG,SAAS,CAI9C;yBAJe,MAAM;kBAUc,QAAQ,KAAG,SAAS;mBAqBlB,MAAM,IAAI,KAAG,SAAS;wBAUf,OAAO"}
1
+ {"version":3,"file":"effect.d.ts","sourceRoot":"","sources":["../../src/primitives/effect.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAa,SAAS,EAAE,MAAM,kBAAkB,CAAA;AA+B9E;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAC1B,IAAI,EAAE,MAAM,EACZ,EAAE,EAAE,QAAQ,GAAG,IAAI,EACnB,IAAI,EAAE,OAAO,EACb,IAAI,UAAO,GACV,MAAM,CAiCR;AAyBD;;GAEG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CA4BjD;AASD;;GAEG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,gBAAgB,UAAO,GAAG,IAAI,CA0B3E;AA8ED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,MAAM,CAAC,EAAE,EAAE,QAAQ,GAAG,SAAS,CAI9C;yBAJe,MAAM;kBAUc,QAAQ,KAAG,SAAS;mBAqBlB,MAAM,IAAI,KAAG,SAAS;wBAUf,OAAO"}