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.js CHANGED
@@ -134,7 +134,6 @@ const signalOptions = {
134
134
  };
135
135
  let ERROR = null;
136
136
  let runEffects = runQueue;
137
- const NOTPENDING = {};
138
137
  const STALE = 1;
139
138
  const PENDING = 2;
140
139
  const UNOWNED = {
@@ -143,6 +142,7 @@ const UNOWNED = {
143
142
  context: null,
144
143
  owner: null
145
144
  };
145
+ const NO_INIT = {};
146
146
  const [transPending, setTransPending] = /*@__PURE__*/createSignal(false);
147
147
  var Owner = null;
148
148
  let Transition = null;
@@ -186,13 +186,12 @@ function createSignal(value, options) {
186
186
  value,
187
187
  observers: null,
188
188
  observerSlots: null,
189
- pending: NOTPENDING,
190
189
  comparator: options.equals || undefined
191
190
  };
192
191
  if (!options.internal) s.name = registerGraph(options.name || hashValue(value), s);
193
192
  const setter = value => {
194
193
  if (typeof value === "function") {
195
- 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);
194
+ if (Transition && Transition.running && Transition.sources.has(s)) value = value(s.tValue);else value = value(s.value);
196
195
  }
197
196
  return writeSignal(s, value);
198
197
  };
@@ -231,7 +230,6 @@ function createReaction(onInvalidate, options) {
231
230
  function createMemo(fn, value, options) {
232
231
  options = options ? Object.assign({}, signalOptions, options) : signalOptions;
233
232
  const c = createComputation(fn, value, true, 0, options );
234
- c.pending = NOTPENDING;
235
233
  c.observers = null;
236
234
  c.observerSlots = null;
237
235
  c.comparator = options.equals || undefined;
@@ -253,34 +251,33 @@ function createResource(source, fetcher, options) {
253
251
  source = true;
254
252
  }
255
253
  options || (options = {});
256
- const contexts = new Set(),
257
- [value, setValue] = createSignal(options.initialValue),
258
- [track, trigger] = createSignal(undefined, {
259
- equals: false
260
- }),
261
- [loading, setLoading] = createSignal(false),
262
- [error, setError] = createSignal();
263
254
  let err = undefined,
264
255
  pr = null,
265
- initP = null,
256
+ initP = NO_INIT,
266
257
  id = null,
267
258
  loadedUnderTransition = false,
268
259
  scheduled = false,
269
260
  resolved = ("initialValue" in options),
270
261
  dynamic = typeof source === "function" && createMemo(source);
262
+ const contexts = new Set(),
263
+ [value, setValue] = options.store ? options.store(options.initialValue) : createSignal(options.initialValue),
264
+ [track, trigger] = createSignal(undefined, {
265
+ equals: false
266
+ }),
267
+ [state, setState] = createSignal(resolved ? "ready" : "unresolved");
271
268
  if (sharedConfig.context) {
272
269
  id = `${sharedConfig.context.id}${sharedConfig.context.count++}`;
273
- if (sharedConfig.load) initP = sharedConfig.load(id);
270
+ let v;
271
+ if (sharedConfig.load && (v = sharedConfig.load(id))) initP = v[0];
274
272
  }
275
- function loadEnd(p, v, e, key) {
273
+ function loadEnd(p, v, success, key) {
276
274
  if (pr === p) {
277
275
  pr = null;
278
276
  resolved = true;
279
- if (initP && (p === initP || v === initP) && options.onHydrated) queueMicrotask(() => options.onHydrated(key, {
277
+ if ((p === initP || v === initP) && options.onHydrated) queueMicrotask(() => options.onHydrated(key, {
280
278
  value: v
281
279
  }));
282
- initP = null;
283
- setError(err = e);
280
+ initP = NO_INIT;
284
281
  if (Transition && p && loadedUnderTransition) {
285
282
  Transition.promises.delete(p);
286
283
  loadedUnderTransition = false;
@@ -290,19 +287,20 @@ function createResource(source, fetcher, options) {
290
287
  Effects.push.apply(Effects, Transition.effects);
291
288
  Transition.effects = [];
292
289
  }
293
- completeLoad(v);
290
+ completeLoad(v, success);
294
291
  }, false);
295
- } else completeLoad(v);
292
+ } else completeLoad(v, success);
296
293
  }
297
294
  return v;
298
295
  }
299
- function completeLoad(v) {
300
- batch(() => {
301
- setValue(() => v);
302
- setLoading(false);
296
+ function completeLoad(v, success) {
297
+ !success && (err = castError(v));
298
+ runUpdates(() => {
299
+ setValue(() => success ? v : undefined);
300
+ setState(success ? "ready" : "error");
303
301
  for (const c of contexts.keys()) c.decrement();
304
302
  contexts.clear();
305
- });
303
+ }, false);
306
304
  }
307
305
  function read() {
308
306
  const c = SuspenseContext && lookup(Owner, SuspenseContext.id),
@@ -324,46 +322,52 @@ function createResource(source, fetcher, options) {
324
322
  function load(refetching = true) {
325
323
  if (refetching && scheduled) return;
326
324
  scheduled = false;
327
- setError(err = undefined);
325
+ err = undefined;
328
326
  const lookup = dynamic ? dynamic() : source;
329
327
  loadedUnderTransition = Transition && Transition.running;
330
328
  if (lookup == null || lookup === false) {
331
- loadEnd(pr, untrack(value));
329
+ loadEnd(pr, untrack(value), true);
332
330
  return;
333
331
  }
334
332
  if (Transition && pr) Transition.promises.delete(pr);
335
- const p = initP || untrack(() => fetcher(lookup, {
333
+ const p = initP !== NO_INIT ? initP : untrack(() => fetcher(lookup, {
336
334
  value: value(),
337
335
  refetching
338
336
  }));
339
337
  if (typeof p !== "object" || !("then" in p)) {
340
- loadEnd(pr, p);
338
+ loadEnd(pr, p, true);
341
339
  return p;
342
340
  }
343
341
  pr = p;
344
342
  scheduled = true;
345
343
  queueMicrotask(() => scheduled = false);
346
- batch(() => {
347
- setLoading(true);
344
+ runUpdates(() => {
345
+ setState(resolved ? "refreshing" : "pending");
348
346
  trigger();
349
- });
350
- return p.then(v => loadEnd(p, v, undefined, lookup), e => loadEnd(p, e, e));
347
+ }, false);
348
+ return p.then(v => loadEnd(p, v, true, lookup), e => loadEnd(p, e, false));
351
349
  }
352
350
  Object.defineProperties(read, {
351
+ state: {
352
+ get() {
353
+ return state();
354
+ }
355
+ },
353
356
  loading: {
354
357
  get() {
355
- return loading();
358
+ const s = state();
359
+ return s === "pending" || s === "refreshing";
356
360
  }
357
361
  },
358
362
  error: {
359
363
  get() {
360
- return error();
364
+ return state() === "error" ? err : undefined;
361
365
  }
362
366
  },
363
367
  latest: {
364
368
  get() {
365
369
  if (!resolved) return read();
366
- if (err) throw err;
370
+ if (state() === "error") throw err;
367
371
  return value();
368
372
  }
369
373
  }
@@ -425,14 +429,7 @@ function batch(fn) {
425
429
  Pending = null;
426
430
  }
427
431
  runUpdates(() => {
428
- for (let i = 0; i < q.length; i += 1) {
429
- const data = q[i];
430
- if (data.pending !== NOTPENDING) {
431
- const pending = data.pending;
432
- data.pending = NOTPENDING;
433
- writeSignal(data, pending);
434
- }
435
- }
432
+ for (let i = 0; i < q.length; i += 1) notifySignal(q[i]);
436
433
  }, false);
437
434
  return result;
438
435
  }
@@ -517,7 +514,7 @@ function startTransition(fn) {
517
514
  t.done || (t.done = new Promise(res => t.resolve = res));
518
515
  t.running = true;
519
516
  }
520
- batch(fn);
517
+ runUpdates(fn, false);
521
518
  Listener = Owner = null;
522
519
  return t ? t.done : undefined;
523
520
  });
@@ -536,7 +533,6 @@ function devComponent(Comp, props) {
536
533
  });
537
534
  return Comp(props);
538
535
  }), undefined, true);
539
- c.pending = NOTPENDING;
540
536
  c.observers = null;
541
537
  c.observerSlots = null;
542
538
  c.state = 0;
@@ -649,29 +645,26 @@ function readSignal() {
649
645
  return this.value;
650
646
  }
651
647
  function writeSignal(node, value, isComp) {
652
- if (Pending) {
653
- if (node.pending === NOTPENDING) Pending.push(node);
654
- node.pending = value;
655
- return value;
656
- }
657
- if (node.comparator) {
658
- if (Transition && Transition.running && Transition.sources.has(node)) {
659
- if (node.comparator(node.tValue, value)) return value;
660
- } else if (node.comparator(node.value, value)) return value;
648
+ let current = Transition && Transition.running && Transition.sources.has(node) ? node.tValue : node.value;
649
+ if (!node.comparator || !node.comparator(current, value)) {
650
+ if (Transition) {
651
+ const TransitionRunning = Transition.running;
652
+ if (TransitionRunning || !isComp && Transition.sources.has(node)) {
653
+ Transition.sources.add(node);
654
+ node.tValue = value;
655
+ }
656
+ if (!TransitionRunning) node.value = value;
657
+ } else node.value = value;
658
+ if (Pending) Pending.push(node);else notifySignal(node);
661
659
  }
662
- let TransitionRunning = false;
663
- if (Transition) {
664
- TransitionRunning = Transition.running;
665
- if (TransitionRunning || !isComp && Transition.sources.has(node)) {
666
- Transition.sources.add(node);
667
- node.tValue = value;
668
- }
669
- if (!TransitionRunning) node.value = value;
670
- } else node.value = value;
660
+ return value;
661
+ }
662
+ function notifySignal(node) {
671
663
  if (node.observers && node.observers.length) {
672
664
  runUpdates(() => {
673
665
  for (let i = 0; i < node.observers.length; i += 1) {
674
666
  const o = node.observers[i];
667
+ const TransitionRunning = Transition && Transition.running;
675
668
  if (TransitionRunning && Transition.disposed.has(o)) continue;
676
669
  if (TransitionRunning && !o.tState || !TransitionRunning && !o.state) {
677
670
  if (o.pure) Updates.push(o);else Effects.push(o);
@@ -686,7 +679,6 @@ function writeSignal(node, value, isComp) {
686
679
  }
687
680
  }, false);
688
681
  }
689
- return value;
690
682
  }
691
683
  function updateComputation(node) {
692
684
  if (!node.fn) return;
@@ -715,7 +707,7 @@ function runComputation(node, value, time) {
715
707
  handleError(err);
716
708
  }
717
709
  if (!node.updatedAt || node.updatedAt <= time) {
718
- if (node.observers && node.observers.length) {
710
+ if (node.updatedAt && "observers" in node) {
719
711
  writeSignal(node, nextValue, true);
720
712
  } else if (Transition && Transition.running && node.pure) {
721
713
  Transition.sources.add(node);
@@ -832,7 +824,7 @@ function completeUpdates(wait) {
832
824
  delete e.tState;
833
825
  }
834
826
  Transition = null;
835
- batch(() => {
827
+ runUpdates(() => {
836
828
  for (const d of disposed) cleanNode(d);
837
829
  for (const v of sources) {
838
830
  v.value = v.tValue;
@@ -845,15 +837,11 @@ function completeUpdates(wait) {
845
837
  v.tState = 0;
846
838
  }
847
839
  setTransPending(false);
848
- });
849
- }
850
- if (Effects.length) batch(() => {
851
- runEffects(Effects);
852
- Effects = null;
853
- });else {
854
- Effects = null;
855
- globalThis._$afterUpdate && globalThis._$afterUpdate();
840
+ }, false);
856
841
  }
842
+ const e = Effects;
843
+ Effects = null;
844
+ if (e.length) runUpdates(() => runEffects(e), false);else globalThis._$afterUpdate && globalThis._$afterUpdate();
857
845
  if (res) res();
858
846
  }
859
847
  function runQueue(queue) {
@@ -888,9 +876,9 @@ function runUserEffects(queue) {
888
876
  if (!e.user) runTop(e);else queue[userLength++] = e;
889
877
  }
890
878
  if (sharedConfig.context) setHydrateContext();
891
- const resume = queue.length;
879
+ Effects = [];
892
880
  for (i = 0; i < userLength; i++) runTop(queue[i]);
893
- for (i = resume; i < queue.length; i++) runTop(queue[i]);
881
+ if (Effects.length) runUserEffects(Effects);
894
882
  }
895
883
  function lookUpstream(node, ignore) {
896
884
  const runningTransition = Transition && Transition.running;
@@ -960,7 +948,12 @@ function reset(node, top) {
960
948
  for (let i = 0; i < node.owned.length; i++) reset(node.owned[i]);
961
949
  }
962
950
  }
951
+ function castError(err) {
952
+ if (err instanceof Error || typeof err === "string") return err;
953
+ return new Error("Unknown error");
954
+ }
963
955
  function handleError(err) {
956
+ err = castError(err);
964
957
  const fns = ERROR && lookup(Owner, ERROR);
965
958
  if (!fns) throw err;
966
959
  for (const f of fns) f(err);
@@ -1016,31 +1009,33 @@ function serializeChildren(root) {
1016
1009
  return result;
1017
1010
  }
1018
1011
 
1019
- function getSymbol() {
1020
- const SymbolCopy = Symbol;
1021
- return SymbolCopy.observable || "@@observable";
1022
- }
1023
1012
  function observable(input) {
1024
- const $$observable = getSymbol();
1025
1013
  return {
1026
1014
  subscribe(observer) {
1027
1015
  if (!(observer instanceof Object) || observer == null) {
1028
1016
  throw new TypeError("Expected the observer to be an object.");
1029
1017
  }
1030
- const handler = "next" in observer ? observer.next.bind(observer) : observer;
1031
- let complete = false;
1032
- createComputed(() => {
1033
- if (complete) return;
1034
- const v = input();
1035
- untrack(() => handler(v));
1018
+ const handler = typeof observer === 'function' ? observer : observer.next && observer.next.bind(observer);
1019
+ if (!handler) {
1020
+ return {
1021
+ unsubscribe() {}
1022
+ };
1023
+ }
1024
+ const dispose = createRoot(disposer => {
1025
+ createComputed(() => {
1026
+ const v = input();
1027
+ untrack(() => handler(v));
1028
+ });
1029
+ return disposer;
1036
1030
  });
1031
+ if (getOwner()) onCleanup(dispose);
1037
1032
  return {
1038
1033
  unsubscribe() {
1039
- complete = true;
1034
+ dispose();
1040
1035
  }
1041
1036
  };
1042
1037
  },
1043
- [$$observable]() {
1038
+ [Symbol.observable || "@@observable"]() {
1044
1039
  return this;
1045
1040
  }
1046
1041
  };
@@ -1419,25 +1414,23 @@ function Match(props) {
1419
1414
  return props;
1420
1415
  }
1421
1416
  let Errors;
1422
- const NoErrors = {};
1423
1417
  function resetErrorBoundaries() {
1424
- Errors && [...Errors].forEach(fn => fn(NoErrors));
1418
+ Errors && [...Errors].forEach(fn => fn());
1425
1419
  }
1426
1420
  function ErrorBoundary(props) {
1427
- let err = NoErrors;
1428
- if (sharedConfig.context && sharedConfig.load) {
1429
- err = sharedConfig.load(sharedConfig.context.id + sharedConfig.context.count) || NoErrors;
1430
- }
1421
+ let err;
1422
+ let v;
1423
+ if (sharedConfig.context && sharedConfig.load && (v = sharedConfig.load(sharedConfig.context.id + sharedConfig.context.count))) err = v[0];
1431
1424
  const [errored, setErrored] = createSignal(err);
1432
1425
  Errors || (Errors = new Set());
1433
1426
  Errors.add(setErrored);
1434
1427
  onCleanup(() => Errors.delete(setErrored));
1435
1428
  return createMemo(() => {
1436
1429
  let e;
1437
- if ((e = errored()) !== NoErrors) {
1430
+ if (e = errored()) {
1438
1431
  const f = props.fallback;
1439
1432
  if ((typeof f !== "function" || f.length == 0)) console.error(e);
1440
- return typeof f === "function" && f.length ? untrack(() => f(e, () => setErrored(NoErrors))) : f;
1433
+ return typeof f === "function" && f.length ? untrack(() => f(e, setErrored)) : f;
1441
1434
  }
1442
1435
  onError(setErrored);
1443
1436
  return props.children;
@@ -1532,21 +1525,27 @@ function Suspense(props) {
1532
1525
  owner = getOwner();
1533
1526
  if (sharedConfig.context && sharedConfig.load) {
1534
1527
  const key = sharedConfig.context.id + sharedConfig.context.count;
1535
- p = sharedConfig.load(key);
1536
- if (p) {
1537
- if (typeof p !== "object" || !("then" in p)) p = Promise.resolve(p);
1538
- const [s, set] = createSignal(undefined, {
1539
- equals: false
1540
- });
1541
- flicker = s;
1542
- p.then(err => {
1543
- if ((error = err) || sharedConfig.done) return set();
1544
- sharedConfig.gather(key);
1545
- setHydrateContext(ctx);
1546
- set();
1547
- setHydrateContext();
1548
- });
1549
- } else if (p === null) sharedConfig.gather(key);
1528
+ let ref = sharedConfig.load(key);
1529
+ if (ref) {
1530
+ p = ref[0];
1531
+ if (p === "$$$") sharedConfig.gather(key);else {
1532
+ if (typeof p !== "object" || !("then" in p)) p = Promise.resolve(p);
1533
+ const [s, set] = createSignal(undefined, {
1534
+ equals: false
1535
+ });
1536
+ flicker = s;
1537
+ p.then(err => {
1538
+ if (err !== "$$$" || sharedConfig.done) {
1539
+ err !== "$$$" && (error = err);
1540
+ return set();
1541
+ }
1542
+ sharedConfig.gather(key);
1543
+ setHydrateContext(ctx);
1544
+ set();
1545
+ setHydrateContext();
1546
+ });
1547
+ }
1548
+ }
1550
1549
  }
1551
1550
  const listContext = useContext(SuspenseListContext);
1552
1551
  if (listContext) [showContent, showFallback] = listContext.register(store.inFallback);
@@ -1562,14 +1561,14 @@ function Suspense(props) {
1562
1561
  flicker();
1563
1562
  return flicker = undefined;
1564
1563
  }
1565
- if (ctx && p === undefined) setHydrateContext();
1564
+ if (ctx && !p) setHydrateContext();
1566
1565
  const rendered = createMemo(() => props.children);
1567
1566
  return createMemo(() => {
1568
1567
  const inFallback = store.inFallback(),
1569
1568
  visibleContent = showContent ? showContent() : true,
1570
1569
  visibleFallback = showFallback ? showFallback() : true;
1571
1570
  dispose && dispose();
1572
- if ((!inFallback || p !== undefined) && visibleContent) {
1571
+ if ((!inFallback || p) && visibleContent) {
1573
1572
  store.resolved = true;
1574
1573
  ctx = p = undefined;
1575
1574
  resumeEffects(store.effects);
package/dist/server.cjs CHANGED
@@ -7,6 +7,16 @@ const $PROXY = Symbol("solid-proxy");
7
7
  const $DEVCOMP = Symbol("solid-dev-component");
8
8
  const DEV = {};
9
9
  const ERROR = Symbol("error");
10
+ function castError(err) {
11
+ if (err instanceof Error || typeof err === "string") return err;
12
+ return new Error("Unknown error");
13
+ }
14
+ function handleError(err) {
15
+ err = castError(err);
16
+ const fns = lookup(Owner, ERROR);
17
+ if (!fns) throw err;
18
+ for (const f of fns) f(err);
19
+ }
10
20
  const UNOWNED = {
11
21
  context: null,
12
22
  owner: null
@@ -24,9 +34,7 @@ function createRoot(fn, detachedOwner) {
24
34
  try {
25
35
  result = fn(() => {});
26
36
  } catch (err) {
27
- const fns = lookup(Owner, ERROR);
28
- if (!fns) throw err;
29
- fns.forEach(f => f(err));
37
+ handleError(err);
30
38
  } finally {
31
39
  Owner = owner;
32
40
  }
@@ -45,9 +53,7 @@ function createComputed(fn, value) {
45
53
  try {
46
54
  fn(value);
47
55
  } catch (err) {
48
- const fns = lookup(Owner, ERROR);
49
- if (!fns) throw err;
50
- fns.forEach(f => f(err));
56
+ handleError(err);
51
57
  } finally {
52
58
  Owner = Owner.owner;
53
59
  }
@@ -68,9 +74,7 @@ function createMemo(fn, value) {
68
74
  try {
69
75
  v = fn(value);
70
76
  } catch (err) {
71
- const fns = lookup(Owner, ERROR);
72
- if (!fns) throw err;
73
- fns.forEach(f => f(err));
77
+ handleError(err);
74
78
  } finally {
75
79
  Owner = Owner.owner;
76
80
  }
@@ -315,16 +319,14 @@ function Switch(props) {
315
319
  function Match(props) {
316
320
  return props;
317
321
  }
318
- const NoErrors = {};
319
322
  function resetErrorBoundaries() {}
320
323
  function ErrorBoundary(props) {
321
- let error = NoErrors,
322
- res;
324
+ let error, res;
323
325
  const ctx = sharedConfig.context;
324
326
  const id = ctx.id + ctx.count;
325
327
  onError(err => error = err);
326
328
  createMemo(() => res = props.children);
327
- if (error !== NoErrors) {
329
+ if (error) {
328
330
  ctx.writeResource(id, error, true);
329
331
  setHydrateContext({ ...ctx,
330
332
  count: 0
@@ -412,7 +414,7 @@ function createResource(source, fetcher, options = {}) {
412
414
  return res;
413
415
  }).catch(err => {
414
416
  read.loading = false;
415
- read.error = error = err;
417
+ read.error = error = castError(err);
416
418
  p = null;
417
419
  notifySuspense(contexts);
418
420
  });
@@ -430,10 +432,17 @@ function createResource(source, fetcher, options = {}) {
430
432
  }
431
433
  function lazy(fn) {
432
434
  let resolved;
433
- const p = fn();
435
+ let p;
436
+ let load = () => {
437
+ if (!p) {
438
+ p = fn();
439
+ p.then(mod => resolved = mod.default);
440
+ }
441
+ return p;
442
+ };
434
443
  const contexts = new Set();
435
- p.then(mod => resolved = mod.default);
436
444
  const wrap = props => {
445
+ load();
437
446
  const id = sharedConfig.context.id.slice(0, -1);
438
447
  if (resolved) return resolved(props);
439
448
  const ctx = useContext(SuspenseContext);
@@ -451,7 +460,7 @@ function lazy(fn) {
451
460
  });
452
461
  return "";
453
462
  };
454
- wrap.preload = () => p;
463
+ wrap.preload = load;
455
464
  return wrap;
456
465
  }
457
466
  function suspenseComplete(c) {
@@ -508,24 +517,20 @@ function Suspense(props) {
508
517
  }
509
518
  const res = runSuspense();
510
519
  if (suspenseComplete(value)) {
511
- ctx.writeResource(id, null);
520
+ ctx.writeResource(id, "$$$");
512
521
  return res;
513
522
  }
514
523
  onError(err => {
515
524
  if (!done || !done(undefined, err)) throw err;
516
525
  });
517
526
  done = ctx.async ? ctx.registerFragment(id) : undefined;
518
- if (ctx.streaming) {
527
+ if (ctx.async) {
519
528
  setHydrateContext(undefined);
520
529
  const res = {
521
530
  t: `<span id="pl-${id}">${resolveSSRNode(props.fallback)}</span>`
522
531
  };
523
532
  setHydrateContext(ctx);
524
533
  return res;
525
- } else if (ctx.async) {
526
- return {
527
- t: `<![${id}]>`
528
- };
529
534
  }
530
535
  setHydrateContext({ ...ctx,
531
536
  count: 0,