@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.
- package/README.md +114 -0
- package/dist/core/constants.d.ts +6 -0
- package/dist/core/constants.d.ts.map +1 -1
- package/dist/deep/proxy.d.ts.map +1 -1
- package/dist/index.d.ts +7 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +430 -56
- package/dist/index.mjs +430 -56
- package/dist/primitives/bind.d.ts.map +1 -1
- package/dist/primitives/effect.d.ts.map +1 -1
- package/dist/primitives/linked.d.ts +73 -0
- package/dist/primitives/linked.d.ts.map +1 -0
- package/dist/primitives/scope.d.ts +96 -0
- package/dist/primitives/scope.d.ts.map +1 -0
- package/dist/primitives/selector.d.ts +46 -0
- package/dist/primitives/selector.d.ts.map +1 -0
- package/dist/reactivity/scheduling.d.ts.map +1 -1
- package/dist/reactivity/tracking.d.ts +5 -0
- package/dist/reactivity/tracking.d.ts.map +1 -1
- package/dist/v2/bench-compare.d.ts +2 -0
- package/dist/v2/bench-compare.d.ts.map +1 -0
- package/dist/v2/bench.d.ts +5 -0
- package/dist/v2/bench.d.ts.map +1 -0
- package/dist/v2/bind.d.ts +94 -0
- package/dist/v2/bind.d.ts.map +1 -0
- package/dist/v2/collections.d.ts +133 -0
- package/dist/v2/collections.d.ts.map +1 -0
- package/dist/v2/compat-test.d.ts +2 -0
- package/dist/v2/compat-test.d.ts.map +1 -0
- package/dist/v2/debug-array.d.ts +2 -0
- package/dist/v2/debug-array.d.ts.map +1 -0
- package/dist/v2/debug-diamond.d.ts +2 -0
- package/dist/v2/debug-diamond.d.ts.map +1 -0
- package/dist/v2/index.d.ts +7 -0
- package/dist/v2/index.d.ts.map +1 -0
- package/dist/v2/primitives.d.ts +120 -0
- package/dist/v2/primitives.d.ts.map +1 -0
- package/dist/v2/proxy.d.ts +10 -0
- package/dist/v2/proxy.d.ts.map +1 -0
- package/dist/v2/registry.d.ts +35 -0
- package/dist/v2/registry.d.ts.map +1 -0
- package/dist/v2/stress.d.ts +7 -0
- package/dist/v2/stress.d.ts.map +1 -0
- package/dist/v2/test-suite.d.ts +2 -0
- package/dist/v2/test-suite.d.ts.map +1 -0
- package/dist/v2/test-v1.d.ts +2 -0
- package/dist/v2/test-v1.d.ts.map +1 -0
- 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
|
-
|
|
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
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
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)
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
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
|
-
|
|
347
|
-
|
|
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
|
|
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
|
-
|
|
708
|
+
let proxied;
|
|
709
|
+
if (shouldProxy(newValue)) {
|
|
710
|
+
proxied = withParent(() => proxy(newValue));
|
|
711
|
+
} else {
|
|
712
|
+
proxied = newValue;
|
|
713
|
+
}
|
|
591
714
|
set(s, proxied);
|
|
592
|
-
|
|
593
|
-
if (isArray
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
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
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
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
|
|
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;
|
|
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;
|
|
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"}
|