@solidjs/signals 0.13.8 → 0.13.10

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/dist/dev.js CHANGED
@@ -144,6 +144,59 @@ function adjustHeight(el, heap) {
144
144
  }
145
145
  }
146
146
  }
147
+ const hooks = {};
148
+ const DEV = {
149
+ hooks: hooks,
150
+ getChildren: getChildren,
151
+ getSignals: getSignals,
152
+ getParent: getParent,
153
+ getSources: getSources,
154
+ getObservers: getObservers
155
+ };
156
+ function registerGraph(value, owner) {
157
+ value._owner = owner;
158
+ if (owner) {
159
+ if (!owner._signals) owner._signals = [];
160
+ owner._signals.push(value);
161
+ }
162
+ DEV.hooks.onGraph?.(value, owner);
163
+ }
164
+ function clearSignals(node) {
165
+ node._signals = undefined;
166
+ }
167
+ function getChildren(owner) {
168
+ const children = [];
169
+ let child = owner._firstChild;
170
+ while (child) {
171
+ children.push(child);
172
+ child = child._nextSibling;
173
+ }
174
+ return children;
175
+ }
176
+ function getSignals(owner) {
177
+ return owner._signals ? [...owner._signals] : [];
178
+ }
179
+ function getParent(owner) {
180
+ return owner._parent;
181
+ }
182
+ function getSources(computation) {
183
+ const sources = [];
184
+ let link = computation._deps;
185
+ while (link) {
186
+ sources.push(link._dep);
187
+ link = link._nextDep;
188
+ }
189
+ return sources;
190
+ }
191
+ function getObservers(node) {
192
+ const observers = [];
193
+ let link = node._subs;
194
+ while (link) {
195
+ observers.push(link._sub);
196
+ link = link._nextSub;
197
+ }
198
+ return observers;
199
+ }
147
200
  const transitions = new Set();
148
201
  const dirtyQueue = { _heap: new Array(2e3).fill(undefined), _marked: false, _min: 0, _max: 0 };
149
202
  const zombieQueue = { _heap: new Array(2e3).fill(undefined), _marked: false, _min: 0, _max: 0 };
@@ -371,6 +424,7 @@ class GlobalQueue extends Queue {
371
424
  this.run(EFFECT_RENDER);
372
425
  runLaneEffects(EFFECT_USER);
373
426
  this.run(EFFECT_USER);
427
+ if (true) DEV.hooks.onUpdate?.();
374
428
  } finally {
375
429
  this._running = false;
376
430
  }
@@ -742,6 +796,7 @@ function dispose(node) {
742
796
  function disposeChildren(node, self = false, zombie) {
743
797
  if (node._flags & REACTIVE_DISPOSED) return;
744
798
  if (self) node._flags = REACTIVE_DISPOSED;
799
+ if (self && true) clearSignals(node);
745
800
  if (self && node._fn) node._inFlight = null;
746
801
  let child = zombie ? node._pendingFirstChild : node._firstChild;
747
802
  while (child) {
@@ -852,6 +907,7 @@ function createOwner(options) {
852
907
  parent._firstChild = owner;
853
908
  }
854
909
  }
910
+ DEV.hooks.onOwner?.(owner);
855
911
  return owner;
856
912
  }
857
913
  function createRoot(init, options) {
@@ -1240,6 +1296,7 @@ function recompute(el, create = false) {
1240
1296
  el._disposal = null;
1241
1297
  el._firstChild = null;
1242
1298
  el._childCount = 0;
1299
+ clearSignals(el);
1243
1300
  }
1244
1301
  }
1245
1302
  const isOptimisticDirty = !!(el._flags & REACTIVE_OPTIMISTIC_DIRTY);
@@ -1361,7 +1418,7 @@ function updateIfNecessary(el) {
1361
1418
  ) {
1362
1419
  recompute(el);
1363
1420
  }
1364
- el._flags = REACTIVE_NONE | (el._flags & REACTIVE_SNAPSHOT_STALE);
1421
+ el._flags = el._flags & (REACTIVE_SNAPSHOT_STALE | REACTIVE_IN_HEAP | REACTIVE_IN_HEAP_HEIGHT);
1365
1422
  }
1366
1423
  function computed(fn, initialValue, options) {
1367
1424
  const transparent = options?.transparent ?? false;
@@ -1416,6 +1473,7 @@ function computed(fn, initialValue, options) {
1416
1473
  context._firstChild = self;
1417
1474
  }
1418
1475
  }
1476
+ DEV.hooks.onOwner?.(self);
1419
1477
  if (parent) self._height = parent._height + 1;
1420
1478
  if (snapshotCaptureActive && ownerInSnapshotScope(context)) self._inSnapshotScope = true;
1421
1479
  if (externalSourceConfig) {
@@ -1452,7 +1510,10 @@ function signal(v, options, firewall = null) {
1452
1510
  _nextChild: firewall?._child || null,
1453
1511
  _pendingValue: NOT_PENDING
1454
1512
  };
1455
- s._name = options?.name ?? "signal";
1513
+ {
1514
+ s._name = options?.name ?? "signal";
1515
+ s._internal = !!firewall;
1516
+ }
1456
1517
  firewall && (firewall._child = s);
1457
1518
  if (
1458
1519
  snapshotCaptureActive &&
@@ -1606,7 +1667,7 @@ function read(el) {
1606
1667
  }
1607
1668
  if (el._fn && el._statusFlags & STATUS_ERROR) {
1608
1669
  if (el._time < clock) {
1609
- recompute(el, true);
1670
+ recompute(el);
1610
1671
  return read(el);
1611
1672
  } else throw el._error;
1612
1673
  }
@@ -2042,6 +2103,7 @@ function createSignal(first, second, third) {
2042
2103
  return [accessor(node), setSignal.bind(null, node)];
2043
2104
  }
2044
2105
  const node = signal(first, second);
2106
+ registerGraph(node, getOwner());
2045
2107
  return [accessor(node), setSignal.bind(null, node)];
2046
2108
  }
2047
2109
  function createMemo(compute, value, options) {
@@ -2110,10 +2172,12 @@ function resolve(fn) {
2110
2172
  });
2111
2173
  }
2112
2174
  function createOptimistic(first, second, third) {
2113
- const node =
2114
- typeof first === "function"
2115
- ? optimisticComputed(first, second, third)
2116
- : optimisticSignal(first, second);
2175
+ if (typeof first === "function") {
2176
+ const node = optimisticComputed(first, second, third);
2177
+ return [accessor(node), setSignal.bind(null, node)];
2178
+ }
2179
+ const node = optimisticSignal(first, second);
2180
+ registerGraph(node, getOwner());
2117
2181
  return [accessor(node), setSignal.bind(null, node)];
2118
2182
  }
2119
2183
  function onSettled(callback) {
@@ -2639,6 +2703,7 @@ const storeTraps = {
2639
2703
  lengthValue !== undefined && nodes.length && setSignal(nodes.length, lengthValue);
2640
2704
  }
2641
2705
  nodes[$TRACK] && setSignal(nodes[$TRACK], undefined);
2706
+ if (true) DEV.hooks.onStoreNodeUpdate?.(target[$PROXY], property, value, prev);
2642
2707
  });
2643
2708
  }
2644
2709
  return true;
@@ -2733,6 +2798,7 @@ function storeSetter(store, fn) {
2733
2798
  function createStore(first, second, options) {
2734
2799
  const derived = typeof first === "function",
2735
2800
  wrappedStore = derived ? createProjectionInternal(first, second, options).store : wrap(first);
2801
+ registerGraph(wrappedStore, getOwner());
2736
2802
  return [wrappedStore, fn => storeSetter(wrappedStore, fn)];
2737
2803
  }
2738
2804
  function createOptimisticStore(first, second, options) {
@@ -3340,10 +3406,100 @@ function createBoundChildren(owner, fn, queue, mask) {
3340
3406
  });
3341
3407
  }
3342
3408
  const ON_INIT = Symbol();
3409
+ const RevealControllerContext = createContext(null);
3410
+ let _revealUsed = false;
3411
+ const FALSE_ACCESSOR = () => false;
3412
+ function isRevealController(slot) {
3413
+ return slot instanceof RevealController;
3414
+ }
3415
+ function isSlotReady(slot) {
3416
+ return isRevealController(slot) ? slot.isReady() : slot._sources.size === 0 && !slot._pending;
3417
+ }
3418
+ function setSlotState(slot, controller, disabled, collapsed) {
3419
+ setSignal(slot._disabled, disabled);
3420
+ setSignal(slot._collapsed, collapsed);
3421
+ if (isRevealController(slot)) {
3422
+ if (!disabled && slot._parentController === controller) slot._parentController = undefined;
3423
+ return slot.evaluate(disabled, collapsed);
3424
+ }
3425
+ if (!disabled && slot._revealController === controller && slot._initialized)
3426
+ slot._revealController = undefined;
3427
+ }
3428
+ class RevealController {
3429
+ _togetherAccessor;
3430
+ _collapsedAccessor;
3431
+ _slots = [];
3432
+ _parentController;
3433
+ _disabled = signal(false, { pureWrite: true, _noSnapshot: true });
3434
+ _collapsed = signal(false, { pureWrite: true, _noSnapshot: true });
3435
+ _ready = true;
3436
+ _evaluating = false;
3437
+ constructor(together, collapsed) {
3438
+ this._togetherAccessor = together;
3439
+ this._collapsedAccessor = collapsed;
3440
+ }
3441
+ _forEachOwnedSlot(fn) {
3442
+ for (let i = 0; i < this._slots.length; i++) {
3443
+ const slot = this._slots[i];
3444
+ if ((isRevealController(slot) ? slot._parentController : slot._revealController) !== this)
3445
+ continue;
3446
+ if (fn(slot) === false) return false;
3447
+ }
3448
+ return true;
3449
+ }
3450
+ isReady() {
3451
+ return this._forEachOwnedSlot(isSlotReady);
3452
+ }
3453
+ register(slot) {
3454
+ if (this._slots.includes(slot)) return;
3455
+ this._slots.push(slot);
3456
+ const together = !!untrack(this._togetherAccessor);
3457
+ setSignal(slot._disabled, true),
3458
+ setSignal(slot._collapsed, together ? false : !!untrack(this._collapsedAccessor));
3459
+ untrack(() => this.evaluate());
3460
+ }
3461
+ unregister(slot) {
3462
+ const index = this._slots.indexOf(slot);
3463
+ if (index >= 0) this._slots.splice(index, 1);
3464
+ untrack(() => this.evaluate());
3465
+ }
3466
+ evaluate(disabledOverride, collapsedOverride) {
3467
+ if (this._evaluating) return;
3468
+ this._evaluating = true;
3469
+ const wasReady = this._ready;
3470
+ try {
3471
+ const disabled = disabledOverride ?? read(this._disabled),
3472
+ collapseTail = !!untrack(this._collapsedAccessor),
3473
+ collapsed = collapsedOverride ?? collapseTail;
3474
+ if (disabled && collapsed)
3475
+ this._forEachOwnedSlot(slot => setSlotState(slot, this, true, true));
3476
+ else if (!!untrack(this._togetherAccessor)) {
3477
+ const ready = this.isReady();
3478
+ this._forEachOwnedSlot(slot => setSlotState(slot, this, !ready, false));
3479
+ } else {
3480
+ let pendingSeen = false;
3481
+ this._forEachOwnedSlot(slot => {
3482
+ if (pendingSeen) return setSlotState(slot, this, true, collapseTail);
3483
+ if (isSlotReady(slot)) return setSlotState(slot, this, false, false);
3484
+ pendingSeen = true;
3485
+ setSlotState(slot, this, true, false);
3486
+ });
3487
+ }
3488
+ } finally {
3489
+ this._ready = this.isReady();
3490
+ this._evaluating = false;
3491
+ }
3492
+ if (this._parentController && wasReady !== this._ready) this._parentController.evaluate();
3493
+ }
3494
+ }
3343
3495
  class CollectionQueue extends Queue {
3344
3496
  _collectionType;
3345
3497
  _sources = new Set();
3498
+ _tree;
3499
+ _pending = true;
3346
3500
  _disabled = signal(false, { pureWrite: true, _noSnapshot: true });
3501
+ _collapsed = signal(false, { pureWrite: true, _noSnapshot: true });
3502
+ _revealController;
3347
3503
  _initialized = false;
3348
3504
  _onFn;
3349
3505
  _prevOn = ON_INIT;
@@ -3352,7 +3508,7 @@ class CollectionQueue extends Queue {
3352
3508
  this._collectionType = type;
3353
3509
  }
3354
3510
  run(type) {
3355
- if (!type || read(this._disabled)) return;
3511
+ if (!type || (read(this._disabled) && (!_revealUsed || read(this._collapsed)))) return;
3356
3512
  return super.run(type);
3357
3513
  }
3358
3514
  notify(node, type, flags, error) {
@@ -3377,6 +3533,7 @@ class CollectionQueue extends Queue {
3377
3533
  return super.notify(node, STATUS_ERROR, flags, error);
3378
3534
  }
3379
3535
  if (flags & this._collectionType) {
3536
+ this._pending = true;
3380
3537
  const source = error?.source || node._error?.source;
3381
3538
  if (source) {
3382
3539
  const wasEmpty = this._sources.size === 0;
@@ -3397,30 +3554,60 @@ class CollectionQueue extends Queue {
3397
3554
  this._sources.delete(source);
3398
3555
  }
3399
3556
  if (!this._sources.size) {
3400
- setSignal(this._disabled, false);
3401
- if (this._onFn) {
3402
- try {
3403
- this._prevOn = untrack(() => this._onFn());
3404
- } catch {}
3557
+ if (
3558
+ this._collectionType & STATUS_PENDING &&
3559
+ this._pending &&
3560
+ !this._initialized &&
3561
+ this._tree
3562
+ ) {
3563
+ this._pending = !!(this._tree._statusFlags & this._collectionType);
3564
+ } else {
3565
+ this._pending = false;
3566
+ }
3567
+ if (!this._pending) {
3568
+ setSignal(this._disabled, false);
3569
+ if (this._onFn) {
3570
+ try {
3571
+ this._prevOn = untrack(() => this._onFn());
3572
+ } catch {}
3573
+ }
3405
3574
  }
3406
3575
  }
3576
+ if (_revealUsed) this._revealController?.evaluate();
3407
3577
  }
3408
3578
  }
3409
3579
  function createCollectionBoundary(type, fn, fallback, onFn) {
3410
3580
  if (!getOwner())
3411
3581
  console.warn("Boundaries created outside a reactive context will never be disposed.");
3412
3582
  const owner = createOwner();
3583
+ if (_revealUsed) setContext(RevealControllerContext, null, owner);
3413
3584
  const queue = new CollectionQueue(type);
3414
3585
  if (onFn) queue._onFn = onFn;
3415
- const tree = createBoundChildren(owner, fn, queue, type);
3586
+ const tree = (queue._tree = createBoundChildren(owner, fn, queue, type));
3587
+ untrack(() => {
3588
+ let pending = false;
3589
+ try {
3590
+ read(tree);
3591
+ } catch (e) {
3592
+ if (e instanceof NotReadyError) pending = true;
3593
+ else throw e;
3594
+ }
3595
+ queue._pending =
3596
+ pending || !!(tree._statusFlags & type) || tree._error instanceof NotReadyError;
3597
+ });
3598
+ const controller =
3599
+ _revealUsed && type === STATUS_PENDING ? getContext(RevealControllerContext) : null;
3600
+ if (controller) {
3601
+ queue._revealController = controller;
3602
+ controller.register(queue);
3603
+ cleanup(() => controller.unregister(queue));
3604
+ }
3416
3605
  const decision = computed(() => {
3417
3606
  if (!read(queue._disabled)) {
3418
3607
  const resolved = read(tree);
3419
- if (!untrack(() => read(queue._disabled))) {
3420
- queue._initialized = true;
3421
- return resolved;
3422
- }
3608
+ if (!untrack(() => read(queue._disabled))) return (queue._initialized = true), resolved;
3423
3609
  }
3610
+ if (_revealUsed && read(queue._collapsed)) return undefined;
3424
3611
  return fallback(queue);
3425
3612
  });
3426
3613
  return accessor(decision);
@@ -3438,6 +3625,29 @@ function createErrorBoundary(fn, fallback) {
3438
3625
  });
3439
3626
  });
3440
3627
  }
3628
+ function createRevealOrder(fn, options) {
3629
+ _revealUsed = true;
3630
+ const owner = createOwner();
3631
+ const parentController = getContext(RevealControllerContext);
3632
+ const together = options?.together || FALSE_ACCESSOR,
3633
+ collapsed = options?.collapsed || FALSE_ACCESSOR;
3634
+ const controller = new RevealController(together, collapsed);
3635
+ setContext(RevealControllerContext, controller, owner);
3636
+ return runWithOwner(owner, () => {
3637
+ const value = fn();
3638
+ computed(() => {
3639
+ together();
3640
+ collapsed();
3641
+ controller.evaluate();
3642
+ });
3643
+ if (parentController) {
3644
+ controller._parentController = parentController;
3645
+ parentController.register(controller);
3646
+ cleanup(() => parentController.unregister(controller));
3647
+ }
3648
+ return value;
3649
+ });
3650
+ }
3441
3651
  function flatten(children, options) {
3442
3652
  if (typeof children === "function" && !children.length) {
3443
3653
  if (options?.doNotUnwrap) return children;
@@ -3500,6 +3710,7 @@ export {
3500
3710
  $TARGET,
3501
3711
  $TRACK,
3502
3712
  ContextNotFoundError,
3713
+ DEV,
3503
3714
  NoOwnerError,
3504
3715
  NotReadyError,
3505
3716
  SUPPORTS_PROXY,
@@ -3516,6 +3727,7 @@ export {
3516
3727
  createProjection,
3517
3728
  createReaction,
3518
3729
  createRenderEffect,
3730
+ createRevealOrder,
3519
3731
  createRoot,
3520
3732
  createSignal,
3521
3733
  createStore,