@solidjs/signals 0.8.7 → 0.9.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/dist/dev.js CHANGED
@@ -328,6 +328,7 @@ let tracking = false;
328
328
  let stale = false;
329
329
  let pendingValueCheck = false;
330
330
  let pendingCheck = null;
331
+ let refreshing = false;
331
332
  let context = null;
332
333
  function notifySubs(node) {
333
334
  for (let s = node._subs; s !== null; s = s._nextSub) {
@@ -364,7 +365,7 @@ function recompute(el, create = false) {
364
365
  setStatusFlags(el, STATUS_NONE | (prevStatusFlags & STATUS_UNINITIALIZED));
365
366
  tracking = true;
366
367
  try {
367
- value = el._fn(value);
368
+ value = handleAsync(el, el._fn(value));
368
369
  el._statusFlags &= ~STATUS_UNINITIALIZED;
369
370
  } catch (e) {
370
371
  if (e instanceof NotReadyError) {
@@ -417,6 +418,55 @@ function recompute(el, create = false) {
417
418
  globalQueue._pendingNodes.push(el);
418
419
  if (el._transition && honoraryOptimistic) runInTransition(el, recompute);
419
420
  }
421
+ function handleAsync(el, result, setter) {
422
+ const isObject = typeof result === "object" && result !== null;
423
+ const isPromise = isObject && result instanceof Promise;
424
+ const iterator = isObject && untrack(() => result[Symbol.asyncIterator]);
425
+ if (!isPromise && !iterator) {
426
+ el._inFlight = null;
427
+ return result;
428
+ }
429
+ el._inFlight = result;
430
+ if (isPromise) {
431
+ result
432
+ .then(value => {
433
+ if (el._inFlight !== result) return;
434
+ globalQueue.initTransition(el);
435
+ setter?.(value) ?? setSignal(el, () => value);
436
+ flush();
437
+ })
438
+ .catch(e => {
439
+ if (el._inFlight !== result) return;
440
+ globalQueue.initTransition(el);
441
+ setStatusFlags(el, STATUS_ERROR, e);
442
+ el._time = clock;
443
+ notifySubs(el);
444
+ schedule();
445
+ flush();
446
+ });
447
+ } else {
448
+ (async () => {
449
+ try {
450
+ for await (let value of result) {
451
+ if (el._inFlight !== result) return;
452
+ globalQueue.initTransition(el);
453
+ setter?.(value) ?? setSignal(el, () => value);
454
+ flush();
455
+ }
456
+ } catch (error) {
457
+ if (el._inFlight !== result) return;
458
+ globalQueue.initTransition(el);
459
+ setStatusFlags(el, STATUS_ERROR, error);
460
+ el._time = clock;
461
+ notifySubs(el);
462
+ schedule();
463
+ flush();
464
+ }
465
+ })();
466
+ }
467
+ globalQueue.initTransition(el);
468
+ throw new NotReadyError(context);
469
+ }
420
470
  function updateIfNecessary(el) {
421
471
  if (el._flags & REACTIVE_CHECK) {
422
472
  for (let d = el._deps; d; d = d._nextDep) {
@@ -600,6 +650,7 @@ function computed(fn, initialValue, options) {
600
650
  _pendingValue: NOT_PENDING,
601
651
  _pendingDisposal: null,
602
652
  _pendingFirstChild: null,
653
+ _inFlight: null,
603
654
  _transition: null
604
655
  };
605
656
  if (options?._internal) Object.assign(self, options._internal);
@@ -619,67 +670,6 @@ function computed(fn, initialValue, options) {
619
670
  recompute(self, true);
620
671
  return self;
621
672
  }
622
- function asyncComputed(asyncFn, initialValue, options) {
623
- let lastResult = undefined;
624
- let refreshing = false;
625
- const fn = prev => {
626
- const result = asyncFn(prev, refreshing);
627
- refreshing = false;
628
- lastResult = result;
629
- const isPromise = result instanceof Promise;
630
- const iterator = result[Symbol.asyncIterator];
631
- if (!isPromise && !iterator) {
632
- return result;
633
- }
634
- if (isPromise) {
635
- result
636
- .then(v => {
637
- if (lastResult !== result) return;
638
- globalQueue.initTransition(self);
639
- setSignal(self, () => v);
640
- flush();
641
- })
642
- .catch(e => {
643
- if (lastResult !== result) return;
644
- globalQueue.initTransition(self);
645
- setStatusFlags(self, STATUS_ERROR, e);
646
- self._time = clock;
647
- notifySubs(self);
648
- schedule();
649
- flush();
650
- });
651
- } else {
652
- (async () => {
653
- try {
654
- for await (let value of result) {
655
- if (lastResult !== result) return;
656
- globalQueue.initTransition(self);
657
- setSignal(self, () => value);
658
- flush();
659
- }
660
- } catch (error) {
661
- if (lastResult !== result) return;
662
- globalQueue.initTransition(self);
663
- setStatusFlags(self, STATUS_ERROR, error);
664
- self._time = clock;
665
- notifySubs(self);
666
- schedule();
667
- flush();
668
- }
669
- })();
670
- }
671
- globalQueue.initTransition(context);
672
- throw new NotReadyError(context);
673
- };
674
- const self = computed(fn, initialValue, options);
675
- self._refresh = () => {
676
- refreshing = true;
677
- recompute(self);
678
- schedule();
679
- flush();
680
- };
681
- return self;
682
- }
683
673
  function signal(v, options, firewall = null) {
684
674
  const s = {
685
675
  id: options?.id ?? (context?.id != null ? getNextChildId(context) : undefined),
@@ -714,6 +704,7 @@ function untrack(fn) {
714
704
  function read(el) {
715
705
  let c = context;
716
706
  if (c?._root) c = c._parentComputed;
707
+ if (refreshing && el._fn) recompute(el);
717
708
  if (c && tracking && !pendingCheck && !pendingValueCheck) {
718
709
  if (el._fn && el._flags & REACTIVE_DISPOSED) recompute(el);
719
710
  link(el, c);
@@ -895,6 +886,22 @@ function isPending(fn) {
895
886
  pendingCheck = current;
896
887
  }
897
888
  }
889
+ function refresh(fn) {
890
+ let prevRefreshing = refreshing;
891
+ refreshing = true;
892
+ try {
893
+ return untrack(fn);
894
+ } finally {
895
+ refreshing = prevRefreshing;
896
+ if (!prevRefreshing) {
897
+ schedule();
898
+ flush();
899
+ }
900
+ }
901
+ }
902
+ function isRefreshing() {
903
+ return refreshing;
904
+ }
898
905
  function createContext(defaultValue, description) {
899
906
  return { id: Symbol(description), defaultValue: defaultValue };
900
907
  }
@@ -1004,12 +1011,6 @@ function createMemo(compute, value, options) {
1004
1011
  let node = computed(compute, value, options);
1005
1012
  return read.bind(null, node);
1006
1013
  }
1007
- function createAsync(compute, value, options) {
1008
- const node = asyncComputed(compute, value, options);
1009
- const ret = read.bind(null, node);
1010
- ret.refresh = node._refresh;
1011
- return ret;
1012
- }
1013
1014
  function createEffect(compute, effectFn, value, options) {
1014
1015
  void effect(compute, effectFn.effect || effectFn, effectFn.error, value, {
1015
1016
  ...options,
@@ -1232,11 +1233,14 @@ function createProjectionInternal(fn, initialValue = {}, options) {
1232
1233
  };
1233
1234
  const wrappedStore = wrapProjection(initialValue);
1234
1235
  node = computed(() => {
1236
+ const owner = node || getOwner();
1235
1237
  storeSetter(wrappedStore, s => {
1236
- const value = fn(s);
1237
- if (value !== s && value !== undefined) {
1238
- reconcile(value, options?.key || "id", options?.all)(s);
1239
- }
1238
+ const value = handleAsync(owner, fn(s), value => {
1239
+ value !== s &&
1240
+ value !== undefined &&
1241
+ storeSetter(wrappedStore, reconcile(value, options?.key || "id", options?.all));
1242
+ });
1243
+ value !== s && value !== undefined && reconcile(value, options?.key || "id", options?.all)(s);
1240
1244
  });
1241
1245
  });
1242
1246
  return { store: wrappedStore, node: node };
@@ -2149,7 +2153,6 @@ export {
2149
2153
  NoOwnerError,
2150
2154
  NotReadyError,
2151
2155
  SUPPORTS_PROXY,
2152
- createAsync,
2153
2156
  createBoundary,
2154
2157
  createContext,
2155
2158
  createEffect,
@@ -2174,6 +2177,7 @@ export {
2174
2177
  getOwner,
2175
2178
  isEqual,
2176
2179
  isPending,
2180
+ isRefreshing,
2177
2181
  isWrappable,
2178
2182
  mapArray,
2179
2183
  merge,
@@ -2182,6 +2186,7 @@ export {
2182
2186
  onSettled,
2183
2187
  pending,
2184
2188
  reconcile,
2189
+ refresh,
2185
2190
  repeat,
2186
2191
  resolve,
2187
2192
  runWithOwner,