@solidjs/signals 0.8.7 → 0.9.1

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
@@ -217,7 +217,7 @@ class GlobalQueue extends Queue {
217
217
  this.stashQueues(activeTransition.queueStash);
218
218
  clock++;
219
219
  scheduled = false;
220
- runPending(activeTransition.pendingNodes, true);
220
+ runTransitionPending(activeTransition.pendingNodes, true);
221
221
  activeTransition = null;
222
222
  return;
223
223
  }
@@ -225,18 +225,14 @@ class GlobalQueue extends Queue {
225
225
  this.restoreQueues(activeTransition.queueStash);
226
226
  transitions.delete(activeTransition);
227
227
  activeTransition = null;
228
- if (runPending(this._pendingNodes, false)) runHeap(dirtyQueue, GlobalQueue._update);
228
+ runTransitionPending(this._pendingNodes, false);
229
+ dirtyQueue._max >= dirtyQueue._min && runHeap(dirtyQueue, GlobalQueue._update);
229
230
  } else if (transitions.size) runHeap(zombieQueue, GlobalQueue._update);
230
- for (let i = 0; i < this._pendingNodes.length; i++) {
231
- const n = this._pendingNodes[i];
232
- if (n._pendingValue !== NOT_PENDING) {
233
- n._value = n._pendingValue;
234
- n._pendingValue = NOT_PENDING;
235
- if (n._type) n._modified = true;
236
- }
237
- if (n._fn) GlobalQueue._dispose(n, false, true);
231
+ runPending(this._pendingNodes);
232
+ while (dirtyQueue._max >= dirtyQueue._min) {
233
+ runHeap(dirtyQueue, GlobalQueue._update);
234
+ runPending(this._pendingNodes);
238
235
  }
239
- this._pendingNodes.length = 0;
240
236
  clock++;
241
237
  scheduled = false;
242
238
  this.run(EFFECT_RENDER);
@@ -277,23 +273,31 @@ class GlobalQueue extends Queue {
277
273
  this._pendingNodes = activeTransition.pendingNodes;
278
274
  }
279
275
  }
280
- function runPending(pendingNodes, value) {
281
- let needsReset = false;
276
+ function runPending(pendingNodes) {
277
+ for (let i = 0; i < pendingNodes.length; i++) {
278
+ const n = pendingNodes[i];
279
+ if (n._pendingValue !== NOT_PENDING) {
280
+ n._value = n._pendingValue;
281
+ n._pendingValue = NOT_PENDING;
282
+ if (n._type) n._modified = true;
283
+ }
284
+ if (n._pendingSignal && n._pendingSignal._pendingValue !== NOT_PENDING)
285
+ n._pendingSignal._set(n._pendingSignal._pendingValue);
286
+ if (n._fn) GlobalQueue._dispose(n, false, true);
287
+ }
288
+ pendingNodes.length = 0;
289
+ }
290
+ function runTransitionPending(pendingNodes, value) {
282
291
  const p = pendingNodes.slice();
283
292
  for (let i = 0; i < p.length; i++) {
284
293
  const n = p[i];
285
294
  n._transition = activeTransition;
286
- if (n._pendingCheck) {
287
- n._pendingCheck._set(value);
288
- needsReset = true;
289
- }
295
+ if (n._pendingCheck) n._pendingCheck._set(value);
290
296
  if (n._pendingSignal && n._pendingSignal._pendingValue !== NOT_PENDING) {
291
297
  n._pendingSignal._set(n._pendingSignal._pendingValue);
292
298
  n._pendingSignal._pendingValue = NOT_PENDING;
293
- needsReset = true;
294
299
  }
295
300
  }
296
- return needsReset;
297
301
  }
298
302
  const globalQueue = new GlobalQueue();
299
303
  function flush() {
@@ -328,6 +332,7 @@ let tracking = false;
328
332
  let stale = false;
329
333
  let pendingValueCheck = false;
330
334
  let pendingCheck = null;
335
+ let refreshing = false;
331
336
  let context = null;
332
337
  function notifySubs(node) {
333
338
  for (let s = node._subs; s !== null; s = s._nextSub) {
@@ -364,7 +369,7 @@ function recompute(el, create = false) {
364
369
  setStatusFlags(el, STATUS_NONE | (prevStatusFlags & STATUS_UNINITIALIZED));
365
370
  tracking = true;
366
371
  try {
367
- value = el._fn(value);
372
+ value = handleAsync(el, el._fn(value));
368
373
  el._statusFlags &= ~STATUS_UNINITIALIZED;
369
374
  } catch (e) {
370
375
  if (e instanceof NotReadyError) {
@@ -417,6 +422,55 @@ function recompute(el, create = false) {
417
422
  globalQueue._pendingNodes.push(el);
418
423
  if (el._transition && honoraryOptimistic) runInTransition(el, recompute);
419
424
  }
425
+ function handleAsync(el, result, setter) {
426
+ const isObject = typeof result === "object" && result !== null;
427
+ const isPromise = isObject && result instanceof Promise;
428
+ const iterator = isObject && untrack(() => result[Symbol.asyncIterator]);
429
+ if (!isPromise && !iterator) {
430
+ el._inFlight = null;
431
+ return result;
432
+ }
433
+ el._inFlight = result;
434
+ if (isPromise) {
435
+ result
436
+ .then(value => {
437
+ if (el._inFlight !== result) return;
438
+ globalQueue.initTransition(el);
439
+ setter?.(value) ?? setSignal(el, () => value);
440
+ flush();
441
+ })
442
+ .catch(e => {
443
+ if (el._inFlight !== result) return;
444
+ globalQueue.initTransition(el);
445
+ setStatusFlags(el, STATUS_ERROR, e);
446
+ el._time = clock;
447
+ notifySubs(el);
448
+ schedule();
449
+ flush();
450
+ });
451
+ } else {
452
+ (async () => {
453
+ try {
454
+ for await (let value of result) {
455
+ if (el._inFlight !== result) return;
456
+ globalQueue.initTransition(el);
457
+ setter?.(value) ?? setSignal(el, () => value);
458
+ flush();
459
+ }
460
+ } catch (error) {
461
+ if (el._inFlight !== result) return;
462
+ globalQueue.initTransition(el);
463
+ setStatusFlags(el, STATUS_ERROR, error);
464
+ el._time = clock;
465
+ notifySubs(el);
466
+ schedule();
467
+ flush();
468
+ }
469
+ })();
470
+ }
471
+ globalQueue.initTransition(el);
472
+ throw new NotReadyError(context);
473
+ }
420
474
  function updateIfNecessary(el) {
421
475
  if (el._flags & REACTIVE_CHECK) {
422
476
  for (let d = el._deps; d; d = d._nextDep) {
@@ -600,6 +654,7 @@ function computed(fn, initialValue, options) {
600
654
  _pendingValue: NOT_PENDING,
601
655
  _pendingDisposal: null,
602
656
  _pendingFirstChild: null,
657
+ _inFlight: null,
603
658
  _transition: null
604
659
  };
605
660
  if (options?._internal) Object.assign(self, options._internal);
@@ -619,67 +674,6 @@ function computed(fn, initialValue, options) {
619
674
  recompute(self, true);
620
675
  return self;
621
676
  }
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
677
  function signal(v, options, firewall = null) {
684
678
  const s = {
685
679
  id: options?.id ?? (context?.id != null ? getNextChildId(context) : undefined),
@@ -714,6 +708,7 @@ function untrack(fn) {
714
708
  function read(el) {
715
709
  let c = context;
716
710
  if (c?._root) c = c._parentComputed;
711
+ if (refreshing && el._fn) recompute(el);
717
712
  if (c && tracking && !pendingCheck && !pendingValueCheck) {
718
713
  if (el._fn && el._flags & REACTIVE_DISPOSED) recompute(el);
719
714
  link(el, c);
@@ -895,6 +890,22 @@ function isPending(fn) {
895
890
  pendingCheck = current;
896
891
  }
897
892
  }
893
+ function refresh(fn) {
894
+ let prevRefreshing = refreshing;
895
+ refreshing = true;
896
+ try {
897
+ return untrack(fn);
898
+ } finally {
899
+ refreshing = prevRefreshing;
900
+ if (!prevRefreshing) {
901
+ schedule();
902
+ flush();
903
+ }
904
+ }
905
+ }
906
+ function isRefreshing() {
907
+ return refreshing;
908
+ }
898
909
  function createContext(defaultValue, description) {
899
910
  return { id: Symbol(description), defaultValue: defaultValue };
900
911
  }
@@ -1004,12 +1015,6 @@ function createMemo(compute, value, options) {
1004
1015
  let node = computed(compute, value, options);
1005
1016
  return read.bind(null, node);
1006
1017
  }
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
1018
  function createEffect(compute, effectFn, value, options) {
1014
1019
  void effect(compute, effectFn.effect || effectFn, effectFn.error, value, {
1015
1020
  ...options,
@@ -1232,11 +1237,14 @@ function createProjectionInternal(fn, initialValue = {}, options) {
1232
1237
  };
1233
1238
  const wrappedStore = wrapProjection(initialValue);
1234
1239
  node = computed(() => {
1240
+ const owner = node || getOwner();
1235
1241
  storeSetter(wrappedStore, s => {
1236
- const value = fn(s);
1237
- if (value !== s && value !== undefined) {
1238
- reconcile(value, options?.key || "id", options?.all)(s);
1239
- }
1242
+ const value = handleAsync(owner, fn(s), value => {
1243
+ value !== s &&
1244
+ value !== undefined &&
1245
+ storeSetter(wrappedStore, reconcile(value, options?.key || "id", options?.all));
1246
+ });
1247
+ value !== s && value !== undefined && reconcile(value, options?.key || "id", options?.all)(s);
1240
1248
  });
1241
1249
  });
1242
1250
  return { store: wrappedStore, node: node };
@@ -2149,7 +2157,6 @@ export {
2149
2157
  NoOwnerError,
2150
2158
  NotReadyError,
2151
2159
  SUPPORTS_PROXY,
2152
- createAsync,
2153
2160
  createBoundary,
2154
2161
  createContext,
2155
2162
  createEffect,
@@ -2174,6 +2181,7 @@ export {
2174
2181
  getOwner,
2175
2182
  isEqual,
2176
2183
  isPending,
2184
+ isRefreshing,
2177
2185
  isWrappable,
2178
2186
  mapArray,
2179
2187
  merge,
@@ -2182,6 +2190,7 @@ export {
2182
2190
  onSettled,
2183
2191
  pending,
2184
2192
  reconcile,
2193
+ refresh,
2185
2194
  repeat,
2186
2195
  resolve,
2187
2196
  runWithOwner,