solid-js 1.4.6 → 1.5.0-beta.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.
Files changed (45) hide show
  1. package/dist/dev.cjs +112 -113
  2. package/dist/dev.js +112 -113
  3. package/dist/server.cjs +65 -31
  4. package/dist/server.js +65 -31
  5. package/dist/solid.cjs +112 -111
  6. package/dist/solid.js +112 -111
  7. package/h/jsx-runtime/types/jsx.d.ts +6 -1401
  8. package/h/types/hyperscript.d.ts +17 -0
  9. package/html/dist/html.cjs +34 -59
  10. package/html/dist/html.js +34 -59
  11. package/html/types/lit.d.ts +37 -0
  12. package/package.json +23 -21
  13. package/store/dist/dev.cjs +40 -22
  14. package/store/dist/dev.js +41 -23
  15. package/store/dist/store.cjs +40 -22
  16. package/store/dist/store.js +40 -22
  17. package/store/types/store.d.ts +1 -1
  18. package/types/jsx.d.ts +194 -1580
  19. package/types/reactive/observable.d.ts +7 -2
  20. package/types/reactive/signal.d.ts +42 -13
  21. package/types/render/component.d.ts +21 -6
  22. package/types/server/reactive.d.ts +6 -1
  23. package/types/server/rendering.d.ts +3 -2
  24. package/universal/types/universal.d.ts +3 -3
  25. package/web/dist/dev.cjs +3 -3
  26. package/web/dist/dev.js +3 -3
  27. package/web/dist/server.cjs +35 -69
  28. package/web/dist/server.js +35 -69
  29. package/web/dist/web.cjs +3 -3
  30. package/web/dist/web.js +3 -3
  31. package/web/types/core.d.ts +2 -2
  32. package/web/types/index.d.ts +5 -6
  33. package/web/types/server-mock.d.ts +4 -2
  34. package/web/types/server.d.ts +70 -0
  35. package/h/README.md +0 -99
  36. package/h/jsx-runtime/package.json +0 -8
  37. package/h/package.json +0 -8
  38. package/html/README.md +0 -84
  39. package/html/package.json +0 -8
  40. package/store/README.md +0 -23
  41. package/store/package.json +0 -35
  42. package/universal/README.md +0 -102
  43. package/universal/package.json +0 -18
  44. package/web/README.md +0 -7
  45. package/web/package.json +0 -35
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,20 +1525,26 @@ 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
- });
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
+ }
1549
1548
  }
1550
1549
  }
1551
1550
  const listContext = useContext(SuspenseListContext);
@@ -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,17 @@ const $PROXY = Symbol("solid-proxy");
7
7
  const $DEVCOMP = Symbol("solid-dev-component");
8
8
  const DEV = {};
9
9
  const ERROR = Symbol("error");
10
+ const BRANCH = Symbol("branch");
11
+ function castError(err) {
12
+ if (err instanceof Error || typeof err === "string") return err;
13
+ return new Error("Unknown error");
14
+ }
15
+ function handleError(err) {
16
+ err = castError(err);
17
+ const fns = lookup(Owner, ERROR);
18
+ if (!fns) throw err;
19
+ for (const f of fns) f(err);
20
+ }
10
21
  const UNOWNED = {
11
22
  context: null,
12
23
  owner: null
@@ -24,9 +35,7 @@ function createRoot(fn, detachedOwner) {
24
35
  try {
25
36
  result = fn(() => {});
26
37
  } catch (err) {
27
- const fns = lookup(Owner, ERROR);
28
- if (!fns) throw err;
29
- fns.forEach(f => f(err));
38
+ handleError(err);
30
39
  } finally {
31
40
  Owner = owner;
32
41
  }
@@ -45,9 +54,7 @@ function createComputed(fn, value) {
45
54
  try {
46
55
  fn(value);
47
56
  } catch (err) {
48
- const fns = lookup(Owner, ERROR);
49
- if (!fns) throw err;
50
- fns.forEach(f => f(err));
57
+ handleError(err);
51
58
  } finally {
52
59
  Owner = Owner.owner;
53
60
  }
@@ -68,9 +75,7 @@ function createMemo(fn, value) {
68
75
  try {
69
76
  v = fn(value);
70
77
  } catch (err) {
71
- const fns = lookup(Owner, ERROR);
72
- if (!fns) throw err;
73
- fns.forEach(f => f(err));
78
+ handleError(err);
74
79
  } finally {
75
80
  Owner = Owner.owner;
76
81
  }
@@ -100,11 +105,25 @@ function on(deps, fn, options = {}) {
100
105
  };
101
106
  }
102
107
  function onMount(fn) {}
103
- function onCleanup(fn) {}
108
+ function onCleanup(fn) {
109
+ let node;
110
+ if (Owner && (node = lookup(Owner, BRANCH))) {
111
+ if (!node.cleanups) node.cleanups = [fn];else node.cleanups.push(fn);
112
+ }
113
+ return fn;
114
+ }
115
+ function cleanNode(node) {
116
+ if (node.cleanups) {
117
+ for (let i = 0; i < node.cleanups.length; i++) node.cleanups[i]();
118
+ node.cleanups = undefined;
119
+ }
120
+ }
104
121
  function onError(fn) {
105
- if (Owner === null) console.warn("error handlers created outside a `createRoot` or `render` will never be run");else if (Owner.context === null) Owner.context = {
106
- [ERROR]: [fn]
107
- };else if (!Owner.context[ERROR]) Owner.context[ERROR] = [fn];else Owner.context[ERROR].push(fn);
122
+ if (Owner) {
123
+ if (Owner.context === null) Owner.context = {
124
+ [ERROR]: [fn]
125
+ };else if (!Owner.context[ERROR]) Owner.context[ERROR] = [fn];else Owner.context[ERROR].push(fn);
126
+ }
108
127
  }
109
128
  function getListener() {
110
129
  return null;
@@ -209,9 +228,11 @@ function observable(input) {
209
228
  function from(producer) {
210
229
  const [s, set] = createSignal(undefined);
211
230
  if ("subscribe" in producer) {
212
- producer.subscribe(v => set(() => v));
231
+ const unsub = producer.subscribe(v => set(() => v));
232
+ onCleanup(() => "unsubscribe" in unsub ? unsub.unsubscribe() : unsub());
213
233
  } else {
214
- producer(set);
234
+ const clean = producer(set);
235
+ onCleanup(clean);
215
236
  }
216
237
  return s;
217
238
  }
@@ -226,7 +247,7 @@ function resolveSSRNode(node) {
226
247
  for (let i = 0, len = node.length; i < len; i++) mapped += resolveSSRNode(node[i]);
227
248
  return mapped;
228
249
  }
229
- if (t === "object") return resolveSSRNode(node.t);
250
+ if (t === "object") return node.t;
230
251
  if (t === "function") return resolveSSRNode(node());
231
252
  return String(node);
232
253
  }
@@ -315,16 +336,21 @@ function Switch(props) {
315
336
  function Match(props) {
316
337
  return props;
317
338
  }
318
- const NoErrors = {};
319
339
  function resetErrorBoundaries() {}
320
340
  function ErrorBoundary(props) {
321
- let error = NoErrors,
322
- res;
341
+ let error, res, clean;
323
342
  const ctx = sharedConfig.context;
324
343
  const id = ctx.id + ctx.count;
325
344
  onError(err => error = err);
326
- createMemo(() => res = props.children);
327
- if (error !== NoErrors) {
345
+ onCleanup(() => cleanNode(clean));
346
+ createMemo(() => {
347
+ Owner.context = {
348
+ [BRANCH]: clean = {}
349
+ };
350
+ return res = props.children;
351
+ });
352
+ if (error) {
353
+ cleanNode(clean);
328
354
  ctx.writeResource(id, error, true);
329
355
  setHydrateContext({ ...ctx,
330
356
  count: 0
@@ -412,7 +438,7 @@ function createResource(source, fetcher, options = {}) {
412
438
  return res;
413
439
  }).catch(err => {
414
440
  read.loading = false;
415
- read.error = error = err;
441
+ read.error = error = castError(err);
416
442
  p = null;
417
443
  notifySuspense(contexts);
418
444
  });
@@ -430,10 +456,17 @@ function createResource(source, fetcher, options = {}) {
430
456
  }
431
457
  function lazy(fn) {
432
458
  let resolved;
433
- const p = fn();
459
+ let p;
460
+ let load = () => {
461
+ if (!p) {
462
+ p = fn();
463
+ p.then(mod => resolved = mod.default);
464
+ }
465
+ return p;
466
+ };
434
467
  const contexts = new Set();
435
- p.then(mod => resolved = mod.default);
436
468
  const wrap = props => {
469
+ load();
437
470
  const id = sharedConfig.context.id.slice(0, -1);
438
471
  if (resolved) return resolved(props);
439
472
  const ctx = useContext(SuspenseContext);
@@ -451,7 +484,7 @@ function lazy(fn) {
451
484
  });
452
485
  return "";
453
486
  };
454
- wrap.preload = () => p;
487
+ wrap.preload = load;
455
488
  return wrap;
456
489
  }
457
490
  function suspenseComplete(c) {
@@ -481,9 +514,13 @@ function SuspenseList(props) {
481
514
  }
482
515
  function Suspense(props) {
483
516
  let done;
517
+ let clean;
484
518
  const ctx = sharedConfig.context;
485
519
  const id = ctx.id + ctx.count;
486
520
  const o = Owner;
521
+ if (o.context) o.context[BRANCH] = clean = {};else o.context = {
522
+ [BRANCH]: clean = {}
523
+ };
487
524
  const value = ctx.suspense[id] || (ctx.suspense[id] = {
488
525
  resources: new Map(),
489
526
  completed: () => {
@@ -501,6 +538,7 @@ function Suspense(props) {
501
538
  return createComponent(SuspenseContext.Provider, {
502
539
  value,
503
540
  get children() {
541
+ cleanNode(clean);
504
542
  return props.children;
505
543
  }
506
544
  });
@@ -508,24 +546,20 @@ function Suspense(props) {
508
546
  }
509
547
  const res = runSuspense();
510
548
  if (suspenseComplete(value)) {
511
- ctx.writeResource(id, null);
549
+ ctx.writeResource(id, "$$$");
512
550
  return res;
513
551
  }
514
552
  onError(err => {
515
553
  if (!done || !done(undefined, err)) throw err;
516
554
  });
517
555
  done = ctx.async ? ctx.registerFragment(id) : undefined;
518
- if (ctx.streaming) {
556
+ if (ctx.async) {
519
557
  setHydrateContext(undefined);
520
558
  const res = {
521
559
  t: `<span id="pl-${id}">${resolveSSRNode(props.fallback)}</span>`
522
560
  };
523
561
  setHydrateContext(ctx);
524
562
  return res;
525
- } else if (ctx.async) {
526
- return {
527
- t: `<![${id}]>`
528
- };
529
563
  }
530
564
  setHydrateContext({ ...ctx,
531
565
  count: 0,