@solidjs/signals 2.0.0-beta.11 → 2.0.0-beta.13

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 CHANGED
@@ -107,8 +107,9 @@ const data = createMemo(async () => {
107
107
  return response.json();
108
108
  });
109
109
 
110
- // Check async state
111
- isPending(data); // true while loading
110
+ // Check async state during revalidation
111
+ isPending(data); // true while stale data is visible and newer data is pending
112
+ isPending(data, true); // follows the Loading path for render guards
112
113
  latest(data); // last resolved value
113
114
  ```
114
115
 
@@ -183,7 +184,7 @@ import { createErrorBoundary, createLoadingBoundary } from "@solidjs/signals";
183
184
 
184
185
  createErrorBoundary(
185
186
  () => riskyComputation(),
186
- (error, reset) => handleError(error)
187
+ (error, reset) => handleError(error())
187
188
  );
188
189
 
189
190
  createLoadingBoundary(
@@ -223,7 +224,7 @@ createRoot(dispose => {
223
224
  | ------------------------ | ------------------------------------------------------------------ |
224
225
  | `flush()` | Process all pending updates |
225
226
  | `untrack(fn)` | Run `fn` without tracking dependencies |
226
- | `isPending(accessor)` | Check if an async accessor is loading |
227
+ | `isPending(accessor)` | Check if an async accessor is revalidating stale data |
227
228
  | `latest(accessor)` | Get the last resolved value of an async accessor |
228
229
  | `refresh(accessor)` | Re-trigger an async computation |
229
230
  | `isRefreshing(accessor)` | Check if an async accessor is refreshing |
package/dist/dev.js CHANGED
@@ -1469,6 +1469,7 @@ let foundPending = false;
1469
1469
  let latestReadActive = false;
1470
1470
  let context = null;
1471
1471
  let currentOptimisticLane = null;
1472
+ let pendingCheckLoadingPath = false;
1472
1473
  let snapshotCaptureActive = false;
1473
1474
  let snapshotSources = null;
1474
1475
  function ownerInSnapshotScope(owner) {
@@ -1930,6 +1931,18 @@ function read(el) {
1930
1931
  const firewall = el._firewall;
1931
1932
  const prevCheck = pendingCheckActive;
1932
1933
  pendingCheckActive = false;
1934
+ const owner = firewall || el;
1935
+ if (
1936
+ pendingCheckLoadingPath &&
1937
+ owner._statusFlags & STATUS_PENDING &&
1938
+ owner._statusFlags & STATUS_UNINITIALIZED
1939
+ ) {
1940
+ let c = context;
1941
+ if (c?._root) c = c._parentComputed;
1942
+ if (c && tracking) link(el, c);
1943
+ pendingCheckActive = prevCheck;
1944
+ throw owner._error;
1945
+ }
1933
1946
  if (firewall && el._overrideValue !== undefined) {
1934
1947
  if (
1935
1948
  el._overrideValue !== NOT_PENDING &&
@@ -2296,18 +2309,23 @@ function latest(fn) {
2296
2309
  latestReadActive = prevLatest;
2297
2310
  }
2298
2311
  }
2299
- function isPending(fn) {
2312
+ function isPending(fn, loading) {
2300
2313
  const prevPendingCheck = pendingCheckActive;
2314
+ const prevPendingCheckLoadingPath = pendingCheckLoadingPath;
2301
2315
  const prevFoundPending = foundPending;
2316
+ const checkLoading = loading === true;
2302
2317
  pendingCheckActive = true;
2318
+ pendingCheckLoadingPath = checkLoading;
2303
2319
  foundPending = false;
2304
2320
  try {
2305
2321
  fn();
2306
2322
  return foundPending;
2307
- } catch {
2323
+ } catch (e) {
2324
+ if (checkLoading && e instanceof NotReadyError) throw e;
2308
2325
  return foundPending;
2309
2326
  } finally {
2310
2327
  pendingCheckActive = prevPendingCheck;
2328
+ pendingCheckLoadingPath = prevPendingCheckLoadingPath;
2311
2329
  foundPending = prevFoundPending;
2312
2330
  }
2313
2331
  }
@@ -3967,7 +3985,8 @@ function mapArray(list, map, options) {
3967
3985
  _nodes: [],
3968
3986
  _key: keyFn,
3969
3987
  _rows: keyFn || options?.keyed === false ? [] : undefined,
3970
- _indexes: indexes ? [] : undefined,
3988
+ _indexes: indexes && options?.keyed !== false ? [] : undefined,
3989
+ _byIndex: options?.keyed === false,
3971
3990
  _fallback: options?.fallback
3972
3991
  };
3973
3992
  const node = computed(updateKeyedMap.bind(data));
@@ -3984,23 +4003,28 @@ function updateKeyedMap() {
3984
4003
  let i,
3985
4004
  j,
3986
4005
  mapper = this._rows
3987
- ? () => {
3988
- this._rows[j] = signal(newItems[j], pureOptions);
3989
- this._indexes && (this._indexes[j] = signal(j, pureOptions));
3990
- return this._map(
3991
- accessor(this._rows[j]),
3992
- this._indexes ? accessor(this._indexes[j]) : undefined
3993
- );
3994
- }
4006
+ ? this._byIndex
4007
+ ? () => {
4008
+ this._rows[j] = signal(newItems[j], pureOptions);
4009
+ return this._map(accessor(this._rows[j]), j);
4010
+ }
4011
+ : () => {
4012
+ this._rows[j] = signal(newItems[j], pureOptions);
4013
+ this._indexes && (this._indexes[j] = signal(j, pureOptions));
4014
+ return this._map(
4015
+ accessor(this._rows[j]),
4016
+ this._indexes ? accessor(this._indexes[j]) : undefined
4017
+ );
4018
+ }
3995
4019
  : this._indexes
3996
4020
  ? () => {
3997
4021
  const item = newItems[j];
3998
4022
  this._indexes[j] = signal(j, pureOptions);
3999
- return this._map(() => item, accessor(this._indexes[j]));
4023
+ return this._map(item, accessor(this._indexes[j]));
4000
4024
  }
4001
4025
  : () => {
4002
4026
  const item = newItems[j];
4003
- return this._map(() => item);
4027
+ return this._map(item);
4004
4028
  };
4005
4029
  if (newLen === 0) {
4006
4030
  if (this._len !== 0) {
@@ -4350,6 +4374,7 @@ class CollectionQueue extends Queue {
4350
4374
  _tree;
4351
4375
  _pending = true;
4352
4376
  _disabled = signal(false, { ownedWrite: true, _noSnapshot: true });
4377
+ _error;
4353
4378
  _collapsed = signal(false, { ownedWrite: true, _noSnapshot: true });
4354
4379
  _revealController;
4355
4380
  _initialized = false;
@@ -4391,6 +4416,9 @@ class CollectionQueue extends Queue {
4391
4416
  const wasEmpty = this._sources.size === 0;
4392
4417
  this._sources.add(source);
4393
4418
  if (wasEmpty) setSignal(this._disabled, true);
4419
+ if (this._collectionType & STATUS_ERROR) {
4420
+ setSignal(this._error, source._error?.cause ?? source._error);
4421
+ }
4394
4422
  }
4395
4423
  }
4396
4424
  type &= ~this._collectionType;
@@ -4444,6 +4472,8 @@ function createCollectionBoundary(type, fn, fallback, onFn) {
4444
4472
  const owner = createOwner();
4445
4473
  if (_revealUsed) setContext(RevealControllerContext, null, owner);
4446
4474
  const queue = new CollectionQueue(type);
4475
+ if (type === STATUS_ERROR)
4476
+ queue._error = signal(undefined, { ownedWrite: true, _noSnapshot: true });
4447
4477
  if (onFn) queue._onFn = onFn;
4448
4478
  const tree = (queue._tree = createBoundChildren(owner, fn, queue, type));
4449
4479
  untrack(() => {
@@ -4479,14 +4509,12 @@ function createLoadingBoundary(fn, fallback, options) {
4479
4509
  return createCollectionBoundary(STATUS_PENDING, fn, () => fallback(), options?.on);
4480
4510
  }
4481
4511
  function createErrorBoundary(fn, fallback) {
4482
- return createCollectionBoundary(STATUS_ERROR, fn, queue => {
4483
- let source = queue._sources.values().next().value;
4484
- const error = source._error?.cause ?? source._error;
4485
- return fallback(error, () => {
4512
+ return createCollectionBoundary(STATUS_ERROR, fn, queue =>
4513
+ fallback(accessor(queue._error), () => {
4486
4514
  for (const source of queue._sources) recompute(source);
4487
4515
  schedule();
4488
- });
4489
- });
4516
+ })
4517
+ );
4490
4518
  }
4491
4519
  function createRevealOrder(fn, options) {
4492
4520
  _revealUsed = true;