solid-js 1.4.5 → 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);
@@ -809,10 +801,8 @@ function runUpdates(fn, init) {
809
801
  completeUpdates(wait);
810
802
  return res;
811
803
  } catch (err) {
804
+ if (!Updates) Effects = null;
812
805
  handleError(err);
813
- } finally {
814
- Updates = null;
815
- if (!wait) Effects = null;
816
806
  }
817
807
  }
818
808
  function completeUpdates(wait) {
@@ -838,7 +828,7 @@ function completeUpdates(wait) {
838
828
  delete e.tState;
839
829
  }
840
830
  Transition = null;
841
- batch(() => {
831
+ runUpdates(() => {
842
832
  for (const d of disposed) cleanNode(d);
843
833
  for (const v of sources) {
844
834
  v.value = v.tValue;
@@ -851,15 +841,11 @@ function completeUpdates(wait) {
851
841
  v.tState = 0;
852
842
  }
853
843
  setTransPending(false);
854
- });
855
- }
856
- if (Effects.length) batch(() => {
857
- runEffects(Effects);
858
- Effects = null;
859
- });else {
860
- Effects = null;
861
- globalThis._$afterUpdate && globalThis._$afterUpdate();
844
+ }, false);
862
845
  }
846
+ const e = Effects;
847
+ Effects = null;
848
+ if (e.length) runUpdates(() => runEffects(e), false);else globalThis._$afterUpdate && globalThis._$afterUpdate();
863
849
  if (res) res();
864
850
  }
865
851
  function runQueue(queue) {
@@ -894,9 +880,9 @@ function runUserEffects(queue) {
894
880
  if (!e.user) runTop(e);else queue[userLength++] = e;
895
881
  }
896
882
  if (sharedConfig.context) setHydrateContext();
897
- const resume = queue.length;
883
+ Effects = [];
898
884
  for (i = 0; i < userLength; i++) runTop(queue[i]);
899
- for (i = resume; i < queue.length; i++) runTop(queue[i]);
885
+ if (Effects.length) runUserEffects(Effects);
900
886
  }
901
887
  function lookUpstream(node, ignore) {
902
888
  const runningTransition = Transition && Transition.running;
@@ -966,7 +952,12 @@ function reset(node, top) {
966
952
  for (let i = 0; i < node.owned.length; i++) reset(node.owned[i]);
967
953
  }
968
954
  }
955
+ function castError(err) {
956
+ if (err instanceof Error || typeof err === "string") return err;
957
+ return new Error("Unknown error");
958
+ }
969
959
  function handleError(err) {
960
+ err = castError(err);
970
961
  const fns = ERROR && lookup(Owner, ERROR);
971
962
  if (!fns) throw err;
972
963
  for (const f of fns) f(err);
@@ -1022,31 +1013,33 @@ function serializeChildren(root) {
1022
1013
  return result;
1023
1014
  }
1024
1015
 
1025
- function getSymbol() {
1026
- const SymbolCopy = Symbol;
1027
- return SymbolCopy.observable || "@@observable";
1028
- }
1029
1016
  function observable(input) {
1030
- const $$observable = getSymbol();
1031
1017
  return {
1032
1018
  subscribe(observer) {
1033
1019
  if (!(observer instanceof Object) || observer == null) {
1034
1020
  throw new TypeError("Expected the observer to be an object.");
1035
1021
  }
1036
- const handler = "next" in observer ? observer.next.bind(observer) : observer;
1037
- let complete = false;
1038
- createComputed(() => {
1039
- if (complete) return;
1040
- const v = input();
1041
- 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;
1042
1034
  });
1035
+ if (getOwner()) onCleanup(dispose);
1043
1036
  return {
1044
1037
  unsubscribe() {
1045
- complete = true;
1038
+ dispose();
1046
1039
  }
1047
1040
  };
1048
1041
  },
1049
- [$$observable]() {
1042
+ [Symbol.observable || "@@observable"]() {
1050
1043
  return this;
1051
1044
  }
1052
1045
  };
@@ -1425,25 +1418,23 @@ function Match(props) {
1425
1418
  return props;
1426
1419
  }
1427
1420
  let Errors;
1428
- const NoErrors = {};
1429
1421
  function resetErrorBoundaries() {
1430
- Errors && [...Errors].forEach(fn => fn(NoErrors));
1422
+ Errors && [...Errors].forEach(fn => fn());
1431
1423
  }
1432
1424
  function ErrorBoundary(props) {
1433
- let err = NoErrors;
1434
- if (sharedConfig.context && sharedConfig.load) {
1435
- err = sharedConfig.load(sharedConfig.context.id + sharedConfig.context.count) || NoErrors;
1436
- }
1425
+ let err;
1426
+ let v;
1427
+ if (sharedConfig.context && sharedConfig.load && (v = sharedConfig.load(sharedConfig.context.id + sharedConfig.context.count))) err = v[0];
1437
1428
  const [errored, setErrored] = createSignal(err);
1438
1429
  Errors || (Errors = new Set());
1439
1430
  Errors.add(setErrored);
1440
1431
  onCleanup(() => Errors.delete(setErrored));
1441
1432
  return createMemo(() => {
1442
1433
  let e;
1443
- if ((e = errored()) !== NoErrors) {
1434
+ if (e = errored()) {
1444
1435
  const f = props.fallback;
1445
1436
  if ((typeof f !== "function" || f.length == 0)) console.error(e);
1446
- return typeof f === "function" && f.length ? untrack(() => f(e, () => setErrored(NoErrors))) : f;
1437
+ return typeof f === "function" && f.length ? untrack(() => f(e, setErrored)) : f;
1447
1438
  }
1448
1439
  onError(setErrored);
1449
1440
  return props.children;
@@ -1538,20 +1529,26 @@ function Suspense(props) {
1538
1529
  owner = getOwner();
1539
1530
  if (sharedConfig.context && sharedConfig.load) {
1540
1531
  const key = sharedConfig.context.id + sharedConfig.context.count;
1541
- p = sharedConfig.load(key);
1542
- if (p) {
1543
- if (typeof p !== "object" || !("then" in p)) p = Promise.resolve(p);
1544
- const [s, set] = createSignal(undefined, {
1545
- equals: false
1546
- });
1547
- flicker = s;
1548
- p.then(err => {
1549
- if ((error = err) || sharedConfig.done) return set();
1550
- sharedConfig.gather(key);
1551
- setHydrateContext(ctx);
1552
- set();
1553
- setHydrateContext();
1554
- });
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
+ }
1555
1552
  }
1556
1553
  }
1557
1554
  const listContext = useContext(SuspenseListContext);
@@ -1568,14 +1565,14 @@ function Suspense(props) {
1568
1565
  flicker();
1569
1566
  return flicker = undefined;
1570
1567
  }
1571
- if (ctx && p === undefined) setHydrateContext();
1568
+ if (ctx && !p) setHydrateContext();
1572
1569
  const rendered = createMemo(() => props.children);
1573
1570
  return createMemo(() => {
1574
1571
  const inFallback = store.inFallback(),
1575
1572
  visibleContent = showContent ? showContent() : true,
1576
1573
  visibleFallback = showFallback ? showFallback() : true;
1577
1574
  dispose && dispose();
1578
- if ((!inFallback || p !== undefined) && visibleContent) {
1575
+ if ((!inFallback || p) && visibleContent) {
1579
1576
  store.resolved = true;
1580
1577
  ctx = p = undefined;
1581
1578
  resumeEffects(store.effects);