solid-js 2.0.0-beta.4 → 2.0.0-beta.5

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/server.cjs CHANGED
@@ -64,7 +64,7 @@ function createMemo(compute, value, options) {
64
64
  processResult(comp, result, owner, ctx, options?.deferStream, options?.ssrSource);
65
65
  } catch (err) {
66
66
  if (err instanceof signals.NotReadyError) {
67
- err.source?.then(() => update());
67
+ err.source?.then(() => update(), () => update());
68
68
  }
69
69
  comp.error = err;
70
70
  comp.computed = true;
@@ -149,20 +149,31 @@ function createDeepProxy(target, patches, basePath = []) {
149
149
  function processResult(comp, result, owner, ctx, deferStream, ssrSource) {
150
150
  if (comp.disposed) return;
151
151
  const id = owner.id;
152
- const uninitialized = comp.value === undefined;
153
152
  const noHydrate = signals.getContext(NoHydrateContext, owner);
154
153
  if (result instanceof Promise) {
154
+ if (result.s === 1) {
155
+ comp.value = result.v;
156
+ comp.error = undefined;
157
+ return;
158
+ }
159
+ if (result.s === 2) {
160
+ comp.error = result.v;
161
+ return;
162
+ }
155
163
  result.then(v => {
156
164
  result.s = 1;
157
165
  result.v = v;
158
166
  if (comp.disposed) return;
159
167
  comp.value = v;
160
168
  comp.error = undefined;
161
- }, () => {});
169
+ }, err => {
170
+ result.s = 2;
171
+ result.v = err;
172
+ if (comp.disposed) return;
173
+ comp.error = err;
174
+ });
162
175
  if (ctx?.async && ctx.serialize && id && !noHydrate) ctx.serialize(id, result, deferStream);
163
- if (uninitialized) {
164
- comp.error = new signals.NotReadyError(result);
165
- }
176
+ comp.error = new signals.NotReadyError(result);
166
177
  return;
167
178
  }
168
179
  const iterator = result?.[Symbol.asyncIterator];
@@ -172,6 +183,7 @@ function processResult(comp, result, owner, ctx, deferStream, ssrSource) {
172
183
  const promise = iter.next().then(v => {
173
184
  promise.s = 1;
174
185
  promise.v = v.value;
186
+ if (!v.done) closeAsyncIterator(iter);
175
187
  if (comp.disposed) return v.value;
176
188
  comp.value = v.value;
177
189
  comp.error = undefined;
@@ -199,6 +211,9 @@ function processResult(comp, result, owner, ctx, deferStream, ssrSource) {
199
211
  return firstNext.then(r => r);
200
212
  }
201
213
  return iter.next().then(r => r);
214
+ },
215
+ return(value) {
216
+ return iter.return?.(value);
202
217
  }
203
218
  })
204
219
  };
@@ -210,6 +225,12 @@ function processResult(comp, result, owner, ctx, deferStream, ssrSource) {
210
225
  }
211
226
  comp.value = result;
212
227
  }
228
+ function closeAsyncIterator(iter, value) {
229
+ const returned = iter.return?.(value);
230
+ if (returned && typeof returned.then === "function") {
231
+ returned.then(undefined, () => {});
232
+ }
233
+ }
213
234
  function serverEffect(compute, effectFn, value, options) {
214
235
  const ssrSource = options?.ssrSource;
215
236
  if (ssrSource === "client" || ssrSource === "initial") {
@@ -311,6 +332,7 @@ function createProjection(fn, initialValue = {}, options) {
311
332
  if (ssrSource === "hybrid") {
312
333
  const promise = iter.next().then(r => {
313
334
  promise.s = 1;
335
+ if (!r.done) closeAsyncIterator(iter);
314
336
  if (disposed) {
315
337
  promise.v = state;
316
338
  return state;
@@ -378,6 +400,9 @@ function createProjection(fn, initialValue = {}, options) {
378
400
  value: undefined
379
401
  };
380
402
  });
403
+ },
404
+ return(value) {
405
+ return iter.return?.(value);
381
406
  }
382
407
  })
383
408
  };
@@ -429,7 +454,7 @@ function deep(store) {
429
454
  }
430
455
  function mapArray(list, mapFn, options = {}) {
431
456
  const parent = signals.createOwner();
432
- return () => {
457
+ return createMemo(() => {
433
458
  const items = list();
434
459
  let s = [];
435
460
  if (items && items.length) {
@@ -446,54 +471,93 @@ function mapArray(list, mapFn, options = {}) {
446
471
  })];
447
472
  }
448
473
  return s;
449
- };
474
+ });
450
475
  }
451
476
  function repeat(count, mapFn, options = {}) {
452
477
  const owner = signals.createOwner();
453
- const len = count();
454
- const offset = options.from?.() || 0;
455
- let s = [];
456
- if (len) {
457
- signals.runWithOwner(owner, () => {
458
- for (let i = 0; i < len; i++) {
459
- const itemOwner = signals.createOwner();
460
- s.push(signals.runWithOwner(itemOwner, () => mapFn(i + offset)));
461
- }
462
- });
463
- } else if (options.fallback) {
464
- s = [signals.runWithOwner(owner, () => {
465
- const fo = signals.createOwner();
466
- return signals.runWithOwner(fo, () => options.fallback());
467
- })];
468
- }
469
- return () => s;
478
+ return createMemo(() => {
479
+ const len = count();
480
+ const offset = options.from?.() || 0;
481
+ if (!len) {
482
+ if (!options.fallback) return [];
483
+ return [signals.runWithOwner(owner, () => {
484
+ const fallbackOwner = signals.createOwner();
485
+ return signals.runWithOwner(fallbackOwner, () => options.fallback());
486
+ })];
487
+ }
488
+ return signals.runWithOwner(owner, () => Array.from({
489
+ length: len
490
+ }, (_, i) => {
491
+ const itemOwner = signals.createOwner();
492
+ return signals.runWithOwner(itemOwner, () => mapFn(i + offset));
493
+ }));
494
+ });
470
495
  }
471
496
  const ErrorContext = {
472
497
  id: Symbol("ErrorContext"),
473
498
  defaultValue: null
474
499
  };
500
+ function runWithBoundaryErrorContext(owner, render, onError, context, boundaryId) {
501
+ const prevCtx = sharedConfig.context;
502
+ const prevBoundary = context?._currentBoundaryId;
503
+ if (context) {
504
+ sharedConfig.context = context;
505
+ if (boundaryId !== undefined) context._currentBoundaryId = boundaryId;
506
+ }
507
+ try {
508
+ return signals.runWithOwner(owner, () => {
509
+ const parentHandler = signals.getContext(ErrorContext);
510
+ signals.setContext(ErrorContext, err => onError(err, parentHandler));
511
+ return render();
512
+ });
513
+ } finally {
514
+ if (context) {
515
+ if (boundaryId !== undefined) context._currentBoundaryId = prevBoundary;
516
+ sharedConfig.context = prevCtx;
517
+ }
518
+ }
519
+ }
475
520
  function createErrorBoundary(fn, fallback) {
476
521
  const ctx = sharedConfig.context;
477
- const owner = signals.createOwner();
478
522
  const parent = signals.getOwner();
479
- if (parent?.id != null) signals.getNextChildId(parent);
480
- owner.id = owner.id + "0";
481
- return signals.runWithOwner(owner, () => {
523
+ const owner = signals.createOwner();
524
+ const resolve = () => {
525
+ const resolved = ctx.resolve(signals.runWithOwner(signals.createOwner(), fn));
526
+ if (resolved?.p?.length) throw new signals.NotReadyError(Promise.all(resolved.p));
527
+ return resolved;
528
+ };
529
+ const renderFallback = err => ctx ? signals.runWithOwner(parent, () => {
530
+ const fallbackOwner = signals.createOwner();
531
+ return signals.runWithOwner(fallbackOwner, () => fallback(err, () => {}));
532
+ }) : fallback(err, () => {});
533
+ const serializeError = err => {
534
+ if (ctx && owner.id && !signals.runWithOwner(owner, () => signals.getContext(NoHydrateContext))) {
535
+ ctx.serialize(owner.id, err);
536
+ }
537
+ };
538
+ const handleError = err => {
539
+ serializeError(err);
540
+ return renderFallback(err);
541
+ };
542
+ return () => {
482
543
  let result;
483
- signals.setContext(ErrorContext, err => {
484
- if (ctx && !signals.getContext(NoHydrateContext) && owner.id) ctx.serialize(owner.id, err);
485
- result = fallback(err, () => {});
486
- });
544
+ let handled = false;
545
+ if (ctx) owner.dispose(false);
487
546
  try {
488
- result = fn();
547
+ result = ctx ? runWithBoundaryErrorContext(owner, resolve, err => {
548
+ if (err instanceof signals.NotReadyError) throw err;
549
+ handled = true;
550
+ result = handleError(err);
551
+ throw err;
552
+ }) : signals.runWithOwner(owner, fn);
489
553
  } catch (err) {
490
- if (ctx && !signals.getContext(NoHydrateContext) && owner.id) ctx.serialize(owner.id, err);
491
- result = fallback(err, () => {});
554
+ if (err instanceof signals.NotReadyError) throw err;
555
+ result = handled ? result : handleError(err);
492
556
  }
493
- return () => result;
494
- });
557
+ return result;
558
+ };
495
559
  }
496
- function createLoadingBoundary(fn, fallback, options) {
560
+ function createLoadingBoundary$1(fn, fallback, options) {
497
561
  try {
498
562
  const result = fn();
499
563
  return () => result;
@@ -569,7 +633,9 @@ function children(fn) {
569
633
  return memo;
570
634
  }
571
635
  function ssrRunInScope(fn) {
572
- return fn;
636
+ const owner = signals.getOwner();
637
+ if (!owner) return fn;
638
+ return Array.isArray(fn) ? fn.map(hole => () => signals.runWithOwner(owner, hole)) : () => signals.runWithOwner(owner, fn);
573
639
  }
574
640
 
575
641
  function enableHydration() {}
@@ -626,6 +692,136 @@ function createUniqueId() {
626
692
  return signals.getNextChildId(o);
627
693
  }
628
694
 
695
+ function ssrHandleError(err) {
696
+ if (err instanceof signals.NotReadyError) {
697
+ return err.source;
698
+ }
699
+ const handler = signals.getContext(ErrorContext);
700
+ if (handler) {
701
+ handler(err);
702
+ return;
703
+ }
704
+ throw err;
705
+ }
706
+ class InvalidTopLevelAsyncReadError extends Error {
707
+ constructor() {
708
+ super("Async values must be read within a tracking scope (JSX, a memo, or an effect's compute function).");
709
+ this.name = "InvalidTopLevelAsyncReadError";
710
+ }
711
+ }
712
+ function createLoadingBoundary(fn, fallback, options) {
713
+ const currentCtx = sharedConfig.context;
714
+ if (!currentCtx) {
715
+ return createLoadingBoundary$1(fn, fallback);
716
+ }
717
+ const ctx = currentCtx;
718
+ const parent = signals.getOwner();
719
+ const parentHandler = parent && signals.runWithOwner(parent, () => signals.getContext(ErrorContext));
720
+ const o = signals.createOwner();
721
+ const id = o.id;
722
+ o.id = id + "00";
723
+ let done;
724
+ let handledRenderError;
725
+ let serializeBuffer = [];
726
+ const bufferedCtx = Object.create(ctx);
727
+ bufferedCtx.serialize = (id, value, deferStream) => {
728
+ serializeBuffer.push([id, value, deferStream]);
729
+ };
730
+ bufferedCtx._currentBoundaryId = id;
731
+ function flushSerializeBuffer() {
732
+ for (const args of serializeBuffer) ctx.serialize(args[0], args[1], args[2]);
733
+ serializeBuffer = [];
734
+ }
735
+ function commitBoundaryState() {
736
+ flushSerializeBuffer();
737
+ const modules = ctx.getBoundaryModules?.(id);
738
+ if (modules) ctx.serialize(id + "_assets", modules);
739
+ }
740
+ function runLoadingPhase(render) {
741
+ handledRenderError = undefined;
742
+ return runWithBoundaryErrorContext(o, render, (err, parentHandler) => {
743
+ handledRenderError = err;
744
+ if (done?.(undefined, err)) throw err;
745
+ if (parentHandler) {
746
+ parentHandler(err);
747
+ return;
748
+ }
749
+ throw err;
750
+ }, bufferedCtx, id);
751
+ }
752
+ function finalizeError(err) {
753
+ if (handledRenderError === err) {
754
+ handledRenderError = undefined;
755
+ return;
756
+ }
757
+ if (done?.(undefined, err)) return;
758
+ if (!parentHandler) throw err;
759
+ try {
760
+ signals.runWithOwner(parent, () => parentHandler(err));
761
+ } catch (caught) {
762
+ if (caught !== err) throw caught;
763
+ }
764
+ }
765
+ function runDiscovery() {
766
+ o.dispose(false);
767
+ serializeBuffer = [];
768
+ return runLoadingPhase(() => {
769
+ try {
770
+ return ctx.resolve(fn());
771
+ } catch (err) {
772
+ if (err instanceof signals.NotReadyError) throw new InvalidTopLevelAsyncReadError();
773
+ throw err;
774
+ }
775
+ });
776
+ }
777
+ let ret = runDiscovery();
778
+ if (!ret?.p?.length) {
779
+ commitBoundaryState();
780
+ return () => ret;
781
+ }
782
+ const fallbackOwner = signals.createOwner({
783
+ id
784
+ });
785
+ const fallbackResult = signals.runWithOwner(fallbackOwner, () => ctx.async ? ctx.ssr([`<template id="pl-${id}"></template>`, `<!--pl-${id}-->`], ctx.escape(fallback())) : fallback());
786
+ if (ctx.async) {
787
+ done = ctx.registerFragment(id);
788
+ (async () => {
789
+ try {
790
+ commitBoundaryState();
791
+ while (ret.p.length) {
792
+ await Promise.all(ret.p).catch(() => {});
793
+ ret = runLoadingPhase(() => ctx.ssr(ret.t, ...ret.h));
794
+ }
795
+ flushSerializeBuffer();
796
+ done(ret.t[0]);
797
+ } catch (err) {
798
+ finalizeError(err);
799
+ }
800
+ })();
801
+ return () => fallbackResult;
802
+ }
803
+ commitBoundaryState();
804
+ ctx.serialize(id, "$$f");
805
+ return () => fallbackResult;
806
+ }
807
+ function NoHydration(props) {
808
+ const o = signals.createOwner();
809
+ return signals.runWithOwner(o, () => {
810
+ signals.setContext(NoHydrateContext, true);
811
+ return props.children;
812
+ });
813
+ }
814
+ function Hydration(props) {
815
+ if (!signals.getContext(NoHydrateContext)) return props.children;
816
+ const o = signals.createOwner({
817
+ id: props.id ?? ""
818
+ });
819
+ return signals.runWithOwner(o, () => {
820
+ signals.setContext(NoHydrateContext, false);
821
+ return props.children;
822
+ });
823
+ }
824
+
629
825
  function For(props) {
630
826
  const options = "fallback" in props ? {
631
827
  keyed: props.keyed,
@@ -633,7 +829,7 @@ function For(props) {
633
829
  } : {
634
830
  keyed: props.keyed
635
831
  };
636
- return createMemo(mapArray(() => props.each, props.children, options));
832
+ return mapArray(() => props.each, props.children, options);
637
833
  }
638
834
  function Repeat(props) {
639
835
  const options = "fallback" in props ? {
@@ -686,106 +882,8 @@ function Errored(props) {
686
882
  return typeof f === "function" && f.length ? f(err, reset) : f;
687
883
  });
688
884
  }
689
-
690
- function ssrHandleError(err) {
691
- if (err instanceof signals.NotReadyError) {
692
- return err.source;
693
- }
694
- const handler = signals.getContext(ErrorContext);
695
- if (handler) {
696
- handler(err);
697
- return;
698
- }
699
- throw err;
700
- }
701
885
  function Loading(props) {
702
- const ctx = sharedConfig.context;
703
- if (!ctx) {
704
- return createLoadingBoundary(() => props.children, () => props.fallback);
705
- }
706
- const o = signals.createOwner();
707
- const id = o.id;
708
- o.id = id + "00";
709
- let runPromise;
710
- let serializeBuffer = [];
711
- const origSerialize = ctx.serialize;
712
- function runInitially() {
713
- o.dispose(false);
714
- serializeBuffer = [];
715
- ctx.serialize = (id, p, deferStream) => {
716
- serializeBuffer.push([id, p, deferStream]);
717
- };
718
- const prevBoundary = ctx._currentBoundaryId;
719
- ctx._currentBoundaryId = id;
720
- const result = signals.runWithOwner(o, () => {
721
- try {
722
- return ctx.resolve(props.children);
723
- } catch (err) {
724
- runPromise = ssrHandleError(err);
725
- }
726
- });
727
- ctx._currentBoundaryId = prevBoundary;
728
- ctx.serialize = origSerialize;
729
- return result;
730
- }
731
- let ret = runInitially();
732
- if (!(runPromise || ret?.p?.length)) {
733
- for (const args of serializeBuffer) origSerialize(args[0], args[1], args[2]);
734
- serializeBuffer = [];
735
- const modules = ctx.getBoundaryModules?.(id);
736
- if (modules) ctx.serialize(id + "_assets", modules);
737
- return ret;
738
- }
739
- const fallbackOwner = signals.createOwner({
740
- id
741
- });
742
- signals.getNextChildId(fallbackOwner);
743
- if (ctx.async) {
744
- const done = ctx.registerFragment(id);
745
- (async () => {
746
- try {
747
- while (runPromise) {
748
- o.dispose(false);
749
- await runPromise;
750
- runPromise = undefined;
751
- ret = runInitially();
752
- }
753
- for (const args of serializeBuffer) origSerialize(args[0], args[1], args[2]);
754
- serializeBuffer = [];
755
- while (ret.p.length) {
756
- await Promise.all(ret.p);
757
- ret = signals.runWithOwner(o, () => ctx.ssr(ret.t, ...ret.h));
758
- }
759
- done(ret.t[0]);
760
- } catch (err) {
761
- done(undefined, err);
762
- }
763
- })();
764
- return signals.runWithOwner(fallbackOwner, () => ctx.ssr([`<template id="pl-${id}"></template>`, `<!--pl-${id}-->`], ctx.escape(props.fallback)));
765
- }
766
- for (const args of serializeBuffer) origSerialize(args[0], args[1], args[2]);
767
- serializeBuffer = [];
768
- const modules = ctx.getBoundaryModules?.(id);
769
- if (modules) ctx.serialize(id + "_assets", modules);
770
- ctx.serialize(id, "$$f");
771
- return signals.runWithOwner(fallbackOwner, () => props.fallback);
772
- }
773
- function NoHydration(props) {
774
- const o = signals.createOwner();
775
- return signals.runWithOwner(o, () => {
776
- signals.setContext(NoHydrateContext, true);
777
- return props.children;
778
- });
779
- }
780
- function Hydration(props) {
781
- if (!signals.getContext(NoHydrateContext)) return props.children;
782
- const o = signals.createOwner({
783
- id: props.id ?? ""
784
- });
785
- return signals.runWithOwner(o, () => {
786
- signals.setContext(NoHydrateContext, false);
787
- return props.children;
788
- });
886
+ return createLoadingBoundary(() => props.children, () => props.fallback);
789
887
  }
790
888
 
791
889
  const DEV = undefined;