solid-js 1.4.7 → 1.5.0-beta.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.cjs CHANGED
@@ -138,7 +138,6 @@ const signalOptions = {
138
138
  };
139
139
  let ERROR = null;
140
140
  let runEffects = runQueue;
141
- const NOTPENDING = {};
142
141
  const STALE = 1;
143
142
  const PENDING = 2;
144
143
  const UNOWNED = {
@@ -147,6 +146,7 @@ const UNOWNED = {
147
146
  context: null,
148
147
  owner: null
149
148
  };
149
+ const NO_INIT = {};
150
150
  const [transPending, setTransPending] = /*@__PURE__*/createSignal(false);
151
151
  var Owner = null;
152
152
  let Transition = null;
@@ -190,13 +190,12 @@ function createSignal(value, options) {
190
190
  value,
191
191
  observers: null,
192
192
  observerSlots: null,
193
- pending: NOTPENDING,
194
193
  comparator: options.equals || undefined
195
194
  };
196
195
  if (!options.internal) s.name = registerGraph(options.name || hashValue(value), s);
197
196
  const setter = value => {
198
197
  if (typeof value === "function") {
199
- if (Transition && Transition.running && Transition.sources.has(s)) value = value(s.pending !== NOTPENDING ? s.pending : s.tValue);else value = value(s.pending !== NOTPENDING ? s.pending : s.value);
198
+ if (Transition && Transition.running && Transition.sources.has(s)) value = value(s.tValue);else value = value(s.value);
200
199
  }
201
200
  return writeSignal(s, value);
202
201
  };
@@ -235,7 +234,6 @@ function createReaction(onInvalidate, options) {
235
234
  function createMemo(fn, value, options) {
236
235
  options = options ? Object.assign({}, signalOptions, options) : signalOptions;
237
236
  const c = createComputation(fn, value, true, 0, options );
238
- c.pending = NOTPENDING;
239
237
  c.observers = null;
240
238
  c.observerSlots = null;
241
239
  c.comparator = options.equals || undefined;
@@ -257,34 +255,33 @@ function createResource(source, fetcher, options) {
257
255
  source = true;
258
256
  }
259
257
  options || (options = {});
260
- const contexts = new Set(),
261
- [value, setValue] = createSignal(options.initialValue),
262
- [track, trigger] = createSignal(undefined, {
263
- equals: false
264
- }),
265
- [loading, setLoading] = createSignal(false),
266
- [error, setError] = createSignal();
267
258
  let err = undefined,
268
259
  pr = null,
269
- initP = null,
260
+ initP = NO_INIT,
270
261
  id = null,
271
262
  loadedUnderTransition = false,
272
263
  scheduled = false,
273
264
  resolved = ("initialValue" in options),
274
265
  dynamic = typeof source === "function" && createMemo(source);
266
+ const contexts = new Set(),
267
+ [value, setValue] = options.store ? options.store(options.initialValue) : createSignal(options.initialValue),
268
+ [track, trigger] = createSignal(undefined, {
269
+ equals: false
270
+ }),
271
+ [state, setState] = createSignal(resolved ? "ready" : "unresolved");
275
272
  if (sharedConfig.context) {
276
273
  id = `${sharedConfig.context.id}${sharedConfig.context.count++}`;
277
- if (sharedConfig.load) initP = sharedConfig.load(id);
274
+ let v;
275
+ if (sharedConfig.load && (v = sharedConfig.load(id))) initP = v[0];
278
276
  }
279
- function loadEnd(p, v, e, key) {
277
+ function loadEnd(p, v, success, key) {
280
278
  if (pr === p) {
281
279
  pr = null;
282
280
  resolved = true;
283
- if (initP && (p === initP || v === initP) && options.onHydrated) queueMicrotask(() => options.onHydrated(key, {
281
+ if ((p === initP || v === initP) && options.onHydrated) queueMicrotask(() => options.onHydrated(key, {
284
282
  value: v
285
283
  }));
286
- initP = null;
287
- setError(err = e);
284
+ initP = NO_INIT;
288
285
  if (Transition && p && loadedUnderTransition) {
289
286
  Transition.promises.delete(p);
290
287
  loadedUnderTransition = false;
@@ -294,19 +291,20 @@ function createResource(source, fetcher, options) {
294
291
  Effects.push.apply(Effects, Transition.effects);
295
292
  Transition.effects = [];
296
293
  }
297
- completeLoad(v);
294
+ completeLoad(v, success);
298
295
  }, false);
299
- } else completeLoad(v);
296
+ } else completeLoad(v, success);
300
297
  }
301
298
  return v;
302
299
  }
303
- function completeLoad(v) {
304
- batch(() => {
305
- setValue(() => v);
306
- setLoading(false);
300
+ function completeLoad(v, success) {
301
+ !success && (err = castError(v));
302
+ runUpdates(() => {
303
+ setValue(() => success ? v : undefined);
304
+ setState(success ? "ready" : "error");
307
305
  for (const c of contexts.keys()) c.decrement();
308
306
  contexts.clear();
309
- });
307
+ }, false);
310
308
  }
311
309
  function read() {
312
310
  const c = SuspenseContext && lookup(Owner, SuspenseContext.id),
@@ -328,46 +326,52 @@ function createResource(source, fetcher, options) {
328
326
  function load(refetching = true) {
329
327
  if (refetching && scheduled) return;
330
328
  scheduled = false;
331
- setError(err = undefined);
329
+ err = undefined;
332
330
  const lookup = dynamic ? dynamic() : source;
333
331
  loadedUnderTransition = Transition && Transition.running;
334
332
  if (lookup == null || lookup === false) {
335
- loadEnd(pr, untrack(value));
333
+ loadEnd(pr, untrack(value), true);
336
334
  return;
337
335
  }
338
336
  if (Transition && pr) Transition.promises.delete(pr);
339
- const p = initP || untrack(() => fetcher(lookup, {
337
+ const p = initP !== NO_INIT ? initP : untrack(() => fetcher(lookup, {
340
338
  value: value(),
341
339
  refetching
342
340
  }));
343
341
  if (typeof p !== "object" || !("then" in p)) {
344
- loadEnd(pr, p);
342
+ loadEnd(pr, p, true);
345
343
  return p;
346
344
  }
347
345
  pr = p;
348
346
  scheduled = true;
349
347
  queueMicrotask(() => scheduled = false);
350
- batch(() => {
351
- setLoading(true);
348
+ runUpdates(() => {
349
+ setState(resolved ? "refreshing" : "pending");
352
350
  trigger();
353
- });
354
- return p.then(v => loadEnd(p, v, undefined, lookup), e => loadEnd(p, e, e));
351
+ }, false);
352
+ return p.then(v => loadEnd(p, v, true, lookup), e => loadEnd(p, e, false));
355
353
  }
356
354
  Object.defineProperties(read, {
355
+ state: {
356
+ get() {
357
+ return state();
358
+ }
359
+ },
357
360
  loading: {
358
361
  get() {
359
- return loading();
362
+ const s = state();
363
+ return s === "pending" || s === "refreshing";
360
364
  }
361
365
  },
362
366
  error: {
363
367
  get() {
364
- return error();
368
+ return state() === "error" ? err : undefined;
365
369
  }
366
370
  },
367
371
  latest: {
368
372
  get() {
369
373
  if (!resolved) return read();
370
- if (err) throw err;
374
+ if (state() === "error") throw err;
371
375
  return value();
372
376
  }
373
377
  }
@@ -429,14 +433,7 @@ function batch(fn) {
429
433
  Pending = null;
430
434
  }
431
435
  runUpdates(() => {
432
- for (let i = 0; i < q.length; i += 1) {
433
- const data = q[i];
434
- if (data.pending !== NOTPENDING) {
435
- const pending = data.pending;
436
- data.pending = NOTPENDING;
437
- writeSignal(data, pending);
438
- }
439
- }
436
+ for (let i = 0; i < q.length; i += 1) notifySignal(q[i]);
440
437
  }, false);
441
438
  return result;
442
439
  }
@@ -521,7 +518,7 @@ function startTransition(fn) {
521
518
  t.done || (t.done = new Promise(res => t.resolve = res));
522
519
  t.running = true;
523
520
  }
524
- batch(fn);
521
+ runUpdates(fn, false);
525
522
  Listener = Owner = null;
526
523
  return t ? t.done : undefined;
527
524
  });
@@ -540,7 +537,6 @@ function devComponent(Comp, props) {
540
537
  });
541
538
  return Comp(props);
542
539
  }), undefined, true);
543
- c.pending = NOTPENDING;
544
540
  c.observers = null;
545
541
  c.observerSlots = null;
546
542
  c.state = 0;
@@ -653,29 +649,26 @@ function readSignal() {
653
649
  return this.value;
654
650
  }
655
651
  function writeSignal(node, value, isComp) {
656
- if (Pending) {
657
- if (node.pending === NOTPENDING) Pending.push(node);
658
- node.pending = value;
659
- return value;
660
- }
661
- if (node.comparator) {
662
- if (Transition && Transition.running && Transition.sources.has(node)) {
663
- if (node.comparator(node.tValue, value)) return value;
664
- } else if (node.comparator(node.value, value)) return value;
652
+ let current = Transition && Transition.running && Transition.sources.has(node) ? node.tValue : node.value;
653
+ if (!node.comparator || !node.comparator(current, value)) {
654
+ if (Transition) {
655
+ const TransitionRunning = Transition.running;
656
+ if (TransitionRunning || !isComp && Transition.sources.has(node)) {
657
+ Transition.sources.add(node);
658
+ node.tValue = value;
659
+ }
660
+ if (!TransitionRunning) node.value = value;
661
+ } else node.value = value;
662
+ if (Pending) Pending.push(node);else notifySignal(node);
665
663
  }
666
- let TransitionRunning = false;
667
- if (Transition) {
668
- TransitionRunning = Transition.running;
669
- if (TransitionRunning || !isComp && Transition.sources.has(node)) {
670
- Transition.sources.add(node);
671
- node.tValue = value;
672
- }
673
- if (!TransitionRunning) node.value = value;
674
- } else node.value = value;
664
+ return value;
665
+ }
666
+ function notifySignal(node) {
675
667
  if (node.observers && node.observers.length) {
676
668
  runUpdates(() => {
677
669
  for (let i = 0; i < node.observers.length; i += 1) {
678
670
  const o = node.observers[i];
671
+ const TransitionRunning = Transition && Transition.running;
679
672
  if (TransitionRunning && Transition.disposed.has(o)) continue;
680
673
  if (TransitionRunning && !o.tState || !TransitionRunning && !o.state) {
681
674
  if (o.pure) Updates.push(o);else Effects.push(o);
@@ -690,7 +683,6 @@ function writeSignal(node, value, isComp) {
690
683
  }
691
684
  }, false);
692
685
  }
693
- return value;
694
686
  }
695
687
  function updateComputation(node) {
696
688
  if (!node.fn) return;
@@ -719,7 +711,7 @@ function runComputation(node, value, time) {
719
711
  handleError(err);
720
712
  }
721
713
  if (!node.updatedAt || node.updatedAt <= time) {
722
- if (node.observers && node.observers.length) {
714
+ if (node.updatedAt && "observers" in node) {
723
715
  writeSignal(node, nextValue, true);
724
716
  } else if (Transition && Transition.running && node.pure) {
725
717
  Transition.sources.add(node);
@@ -836,7 +828,7 @@ function completeUpdates(wait) {
836
828
  delete e.tState;
837
829
  }
838
830
  Transition = null;
839
- batch(() => {
831
+ runUpdates(() => {
840
832
  for (const d of disposed) cleanNode(d);
841
833
  for (const v of sources) {
842
834
  v.value = v.tValue;
@@ -849,15 +841,11 @@ function completeUpdates(wait) {
849
841
  v.tState = 0;
850
842
  }
851
843
  setTransPending(false);
852
- });
853
- }
854
- if (Effects.length) batch(() => {
855
- runEffects(Effects);
856
- Effects = null;
857
- });else {
858
- Effects = null;
859
- globalThis._$afterUpdate && globalThis._$afterUpdate();
844
+ }, false);
860
845
  }
846
+ const e = Effects;
847
+ Effects = null;
848
+ if (e.length) runUpdates(() => runEffects(e), false);else globalThis._$afterUpdate && globalThis._$afterUpdate();
861
849
  if (res) res();
862
850
  }
863
851
  function runQueue(queue) {
@@ -892,9 +880,9 @@ function runUserEffects(queue) {
892
880
  if (!e.user) runTop(e);else queue[userLength++] = e;
893
881
  }
894
882
  if (sharedConfig.context) setHydrateContext();
895
- const resume = queue.length;
883
+ Effects = [];
896
884
  for (i = 0; i < userLength; i++) runTop(queue[i]);
897
- for (i = resume; i < queue.length; i++) runTop(queue[i]);
885
+ if (Effects.length) runUserEffects(Effects);
898
886
  }
899
887
  function lookUpstream(node, ignore) {
900
888
  const runningTransition = Transition && Transition.running;
@@ -964,7 +952,12 @@ function reset(node, top) {
964
952
  for (let i = 0; i < node.owned.length; i++) reset(node.owned[i]);
965
953
  }
966
954
  }
955
+ function castError(err) {
956
+ if (err instanceof Error || typeof err === "string") return err;
957
+ return new Error("Unknown error");
958
+ }
967
959
  function handleError(err) {
960
+ err = castError(err);
968
961
  const fns = ERROR && lookup(Owner, ERROR);
969
962
  if (!fns) throw err;
970
963
  for (const f of fns) f(err);
@@ -1020,31 +1013,33 @@ function serializeChildren(root) {
1020
1013
  return result;
1021
1014
  }
1022
1015
 
1023
- function getSymbol() {
1024
- const SymbolCopy = Symbol;
1025
- return SymbolCopy.observable || "@@observable";
1026
- }
1027
1016
  function observable(input) {
1028
- const $$observable = getSymbol();
1029
1017
  return {
1030
1018
  subscribe(observer) {
1031
1019
  if (!(observer instanceof Object) || observer == null) {
1032
1020
  throw new TypeError("Expected the observer to be an object.");
1033
1021
  }
1034
- const handler = "next" in observer ? observer.next.bind(observer) : observer;
1035
- let complete = false;
1036
- createComputed(() => {
1037
- if (complete) return;
1038
- const v = input();
1039
- untrack(() => handler(v));
1022
+ const handler = typeof observer === 'function' ? observer : observer.next && observer.next.bind(observer);
1023
+ if (!handler) {
1024
+ return {
1025
+ unsubscribe() {}
1026
+ };
1027
+ }
1028
+ const dispose = createRoot(disposer => {
1029
+ createComputed(() => {
1030
+ const v = input();
1031
+ untrack(() => handler(v));
1032
+ });
1033
+ return disposer;
1040
1034
  });
1035
+ if (getOwner()) onCleanup(dispose);
1041
1036
  return {
1042
1037
  unsubscribe() {
1043
- complete = true;
1038
+ dispose();
1044
1039
  }
1045
1040
  };
1046
1041
  },
1047
- [$$observable]() {
1042
+ [Symbol.observable || "@@observable"]() {
1048
1043
  return this;
1049
1044
  }
1050
1045
  };
@@ -1423,25 +1418,23 @@ function Match(props) {
1423
1418
  return props;
1424
1419
  }
1425
1420
  let Errors;
1426
- const NoErrors = {};
1427
1421
  function resetErrorBoundaries() {
1428
- Errors && [...Errors].forEach(fn => fn(NoErrors));
1422
+ Errors && [...Errors].forEach(fn => fn());
1429
1423
  }
1430
1424
  function ErrorBoundary(props) {
1431
- let err = NoErrors;
1432
- if (sharedConfig.context && sharedConfig.load) {
1433
- err = sharedConfig.load(sharedConfig.context.id + sharedConfig.context.count) || NoErrors;
1434
- }
1425
+ let err;
1426
+ let v;
1427
+ if (sharedConfig.context && sharedConfig.load && (v = sharedConfig.load(sharedConfig.context.id + sharedConfig.context.count))) err = v[0];
1435
1428
  const [errored, setErrored] = createSignal(err);
1436
1429
  Errors || (Errors = new Set());
1437
1430
  Errors.add(setErrored);
1438
1431
  onCleanup(() => Errors.delete(setErrored));
1439
1432
  return createMemo(() => {
1440
1433
  let e;
1441
- if ((e = errored()) !== NoErrors) {
1434
+ if (e = errored()) {
1442
1435
  const f = props.fallback;
1443
1436
  if ((typeof f !== "function" || f.length == 0)) console.error(e);
1444
- return typeof f === "function" && f.length ? untrack(() => f(e, () => setErrored(NoErrors))) : f;
1437
+ return typeof f === "function" && f.length ? untrack(() => f(e, setErrored)) : f;
1445
1438
  }
1446
1439
  onError(setErrored);
1447
1440
  return props.children;
@@ -1536,21 +1529,27 @@ function Suspense(props) {
1536
1529
  owner = getOwner();
1537
1530
  if (sharedConfig.context && sharedConfig.load) {
1538
1531
  const key = sharedConfig.context.id + sharedConfig.context.count;
1539
- p = sharedConfig.load(key);
1540
- if (p) {
1541
- if (typeof p !== "object" || !("then" in p)) p = Promise.resolve(p);
1542
- const [s, set] = createSignal(undefined, {
1543
- equals: false
1544
- });
1545
- flicker = s;
1546
- p.then(err => {
1547
- if ((error = err) || sharedConfig.done) return set();
1548
- sharedConfig.gather(key);
1549
- setHydrateContext(ctx);
1550
- set();
1551
- setHydrateContext();
1552
- });
1553
- } else if (p === null) sharedConfig.gather(key);
1532
+ let ref = sharedConfig.load(key);
1533
+ if (ref) {
1534
+ p = ref[0];
1535
+ if (p === "$$$") sharedConfig.gather(key);else {
1536
+ if (typeof p !== "object" || !("then" in p)) p = Promise.resolve(p);
1537
+ const [s, set] = createSignal(undefined, {
1538
+ equals: false
1539
+ });
1540
+ flicker = s;
1541
+ p.then(err => {
1542
+ if (err !== "$$$" || sharedConfig.done) {
1543
+ err !== "$$$" && (error = err);
1544
+ return set();
1545
+ }
1546
+ sharedConfig.gather(key);
1547
+ setHydrateContext(ctx);
1548
+ set();
1549
+ setHydrateContext();
1550
+ });
1551
+ }
1552
+ }
1554
1553
  }
1555
1554
  const listContext = useContext(SuspenseListContext);
1556
1555
  if (listContext) [showContent, showFallback] = listContext.register(store.inFallback);
@@ -1566,14 +1565,14 @@ function Suspense(props) {
1566
1565
  flicker();
1567
1566
  return flicker = undefined;
1568
1567
  }
1569
- if (ctx && p === undefined) setHydrateContext();
1568
+ if (ctx && !p) setHydrateContext();
1570
1569
  const rendered = createMemo(() => props.children);
1571
1570
  return createMemo(() => {
1572
1571
  const inFallback = store.inFallback(),
1573
1572
  visibleContent = showContent ? showContent() : true,
1574
1573
  visibleFallback = showFallback ? showFallback() : true;
1575
1574
  dispose && dispose();
1576
- if ((!inFallback || p !== undefined) && visibleContent) {
1575
+ if ((!inFallback || p) && visibleContent) {
1577
1576
  store.resolved = true;
1578
1577
  ctx = p = undefined;
1579
1578
  resumeEffects(store.effects);