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/server.js CHANGED
@@ -3,6 +3,16 @@ const $PROXY = Symbol("solid-proxy");
3
3
  const $DEVCOMP = Symbol("solid-dev-component");
4
4
  const DEV = {};
5
5
  const ERROR = Symbol("error");
6
+ function castError(err) {
7
+ if (err instanceof Error || typeof err === "string") return err;
8
+ return new Error("Unknown error");
9
+ }
10
+ function handleError(err) {
11
+ err = castError(err);
12
+ const fns = lookup(Owner, ERROR);
13
+ if (!fns) throw err;
14
+ for (const f of fns) f(err);
15
+ }
6
16
  const UNOWNED = {
7
17
  context: null,
8
18
  owner: null
@@ -20,9 +30,7 @@ function createRoot(fn, detachedOwner) {
20
30
  try {
21
31
  result = fn(() => {});
22
32
  } catch (err) {
23
- const fns = lookup(Owner, ERROR);
24
- if (!fns) throw err;
25
- fns.forEach(f => f(err));
33
+ handleError(err);
26
34
  } finally {
27
35
  Owner = owner;
28
36
  }
@@ -41,9 +49,7 @@ function createComputed(fn, value) {
41
49
  try {
42
50
  fn(value);
43
51
  } catch (err) {
44
- const fns = lookup(Owner, ERROR);
45
- if (!fns) throw err;
46
- fns.forEach(f => f(err));
52
+ handleError(err);
47
53
  } finally {
48
54
  Owner = Owner.owner;
49
55
  }
@@ -64,9 +70,7 @@ function createMemo(fn, value) {
64
70
  try {
65
71
  v = fn(value);
66
72
  } catch (err) {
67
- const fns = lookup(Owner, ERROR);
68
- if (!fns) throw err;
69
- fns.forEach(f => f(err));
73
+ handleError(err);
70
74
  } finally {
71
75
  Owner = Owner.owner;
72
76
  }
@@ -311,16 +315,14 @@ function Switch(props) {
311
315
  function Match(props) {
312
316
  return props;
313
317
  }
314
- const NoErrors = {};
315
318
  function resetErrorBoundaries() {}
316
319
  function ErrorBoundary(props) {
317
- let error = NoErrors,
318
- res;
320
+ let error, res;
319
321
  const ctx = sharedConfig.context;
320
322
  const id = ctx.id + ctx.count;
321
323
  onError(err => error = err);
322
324
  createMemo(() => res = props.children);
323
- if (error !== NoErrors) {
325
+ if (error) {
324
326
  ctx.writeResource(id, error, true);
325
327
  setHydrateContext({ ...ctx,
326
328
  count: 0
@@ -408,7 +410,7 @@ function createResource(source, fetcher, options = {}) {
408
410
  return res;
409
411
  }).catch(err => {
410
412
  read.loading = false;
411
- read.error = error = err;
413
+ read.error = error = castError(err);
412
414
  p = null;
413
415
  notifySuspense(contexts);
414
416
  });
@@ -426,10 +428,17 @@ function createResource(source, fetcher, options = {}) {
426
428
  }
427
429
  function lazy(fn) {
428
430
  let resolved;
429
- const p = fn();
431
+ let p;
432
+ let load = () => {
433
+ if (!p) {
434
+ p = fn();
435
+ p.then(mod => resolved = mod.default);
436
+ }
437
+ return p;
438
+ };
430
439
  const contexts = new Set();
431
- p.then(mod => resolved = mod.default);
432
440
  const wrap = props => {
441
+ load();
433
442
  const id = sharedConfig.context.id.slice(0, -1);
434
443
  if (resolved) return resolved(props);
435
444
  const ctx = useContext(SuspenseContext);
@@ -447,7 +456,7 @@ function lazy(fn) {
447
456
  });
448
457
  return "";
449
458
  };
450
- wrap.preload = () => p;
459
+ wrap.preload = load;
451
460
  return wrap;
452
461
  }
453
462
  function suspenseComplete(c) {
@@ -504,24 +513,20 @@ function Suspense(props) {
504
513
  }
505
514
  const res = runSuspense();
506
515
  if (suspenseComplete(value)) {
507
- ctx.writeResource(id, null);
516
+ ctx.writeResource(id, "$$$");
508
517
  return res;
509
518
  }
510
519
  onError(err => {
511
520
  if (!done || !done(undefined, err)) throw err;
512
521
  });
513
522
  done = ctx.async ? ctx.registerFragment(id) : undefined;
514
- if (ctx.streaming) {
523
+ if (ctx.async) {
515
524
  setHydrateContext(undefined);
516
525
  const res = {
517
526
  t: `<span id="pl-${id}">${resolveSSRNode(props.fallback)}</span>`
518
527
  };
519
528
  setHydrateContext(ctx);
520
529
  return res;
521
- } else if (ctx.async) {
522
- return {
523
- t: `<![${id}]>`
524
- };
525
530
  }
526
531
  setHydrateContext({ ...ctx,
527
532
  count: 0,
package/dist/solid.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;
@@ -183,12 +183,11 @@ function createSignal(value, options) {
183
183
  value,
184
184
  observers: null,
185
185
  observerSlots: null,
186
- pending: NOTPENDING,
187
186
  comparator: options.equals || undefined
188
187
  };
189
188
  const setter = value => {
190
189
  if (typeof value === "function") {
191
- 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);
190
+ if (Transition && Transition.running && Transition.sources.has(s)) value = value(s.tValue);else value = value(s.value);
192
191
  }
193
192
  return writeSignal(s, value);
194
193
  };
@@ -227,7 +226,6 @@ function createReaction(onInvalidate, options) {
227
226
  function createMemo(fn, value, options) {
228
227
  options = options ? Object.assign({}, signalOptions, options) : signalOptions;
229
228
  const c = createComputation(fn, value, true, 0);
230
- c.pending = NOTPENDING;
231
229
  c.observers = null;
232
230
  c.observerSlots = null;
233
231
  c.comparator = options.equals || undefined;
@@ -249,34 +247,33 @@ function createResource(source, fetcher, options) {
249
247
  source = true;
250
248
  }
251
249
  options || (options = {});
252
- const contexts = new Set(),
253
- [value, setValue] = createSignal(options.initialValue),
254
- [track, trigger] = createSignal(undefined, {
255
- equals: false
256
- }),
257
- [loading, setLoading] = createSignal(false),
258
- [error, setError] = createSignal();
259
250
  let err = undefined,
260
251
  pr = null,
261
- initP = null,
252
+ initP = NO_INIT,
262
253
  id = null,
263
254
  loadedUnderTransition = false,
264
255
  scheduled = false,
265
256
  resolved = ("initialValue" in options),
266
257
  dynamic = typeof source === "function" && createMemo(source);
258
+ const contexts = new Set(),
259
+ [value, setValue] = options.store ? options.store(options.initialValue) : createSignal(options.initialValue),
260
+ [track, trigger] = createSignal(undefined, {
261
+ equals: false
262
+ }),
263
+ [state, setState] = createSignal(resolved ? "ready" : "unresolved");
267
264
  if (sharedConfig.context) {
268
265
  id = `${sharedConfig.context.id}${sharedConfig.context.count++}`;
269
- if (sharedConfig.load) initP = sharedConfig.load(id);
266
+ let v;
267
+ if (sharedConfig.load && (v = sharedConfig.load(id))) initP = v[0];
270
268
  }
271
- function loadEnd(p, v, e, key) {
269
+ function loadEnd(p, v, success, key) {
272
270
  if (pr === p) {
273
271
  pr = null;
274
272
  resolved = true;
275
- if (initP && (p === initP || v === initP) && options.onHydrated) queueMicrotask(() => options.onHydrated(key, {
273
+ if ((p === initP || v === initP) && options.onHydrated) queueMicrotask(() => options.onHydrated(key, {
276
274
  value: v
277
275
  }));
278
- initP = null;
279
- setError(err = e);
276
+ initP = NO_INIT;
280
277
  if (Transition && p && loadedUnderTransition) {
281
278
  Transition.promises.delete(p);
282
279
  loadedUnderTransition = false;
@@ -286,19 +283,20 @@ function createResource(source, fetcher, options) {
286
283
  Effects.push.apply(Effects, Transition.effects);
287
284
  Transition.effects = [];
288
285
  }
289
- completeLoad(v);
286
+ completeLoad(v, success);
290
287
  }, false);
291
- } else completeLoad(v);
288
+ } else completeLoad(v, success);
292
289
  }
293
290
  return v;
294
291
  }
295
- function completeLoad(v) {
296
- batch(() => {
297
- setValue(() => v);
298
- setLoading(false);
292
+ function completeLoad(v, success) {
293
+ !success && (err = castError(v));
294
+ runUpdates(() => {
295
+ setValue(() => success ? v : undefined);
296
+ setState(success ? "ready" : "error");
299
297
  for (const c of contexts.keys()) c.decrement();
300
298
  contexts.clear();
301
- });
299
+ }, false);
302
300
  }
303
301
  function read() {
304
302
  const c = SuspenseContext && lookup(Owner, SuspenseContext.id),
@@ -320,46 +318,52 @@ function createResource(source, fetcher, options) {
320
318
  function load(refetching = true) {
321
319
  if (refetching && scheduled) return;
322
320
  scheduled = false;
323
- setError(err = undefined);
321
+ err = undefined;
324
322
  const lookup = dynamic ? dynamic() : source;
325
323
  loadedUnderTransition = Transition && Transition.running;
326
324
  if (lookup == null || lookup === false) {
327
- loadEnd(pr, untrack(value));
325
+ loadEnd(pr, untrack(value), true);
328
326
  return;
329
327
  }
330
328
  if (Transition && pr) Transition.promises.delete(pr);
331
- const p = initP || untrack(() => fetcher(lookup, {
329
+ const p = initP !== NO_INIT ? initP : untrack(() => fetcher(lookup, {
332
330
  value: value(),
333
331
  refetching
334
332
  }));
335
333
  if (typeof p !== "object" || !("then" in p)) {
336
- loadEnd(pr, p);
334
+ loadEnd(pr, p, true);
337
335
  return p;
338
336
  }
339
337
  pr = p;
340
338
  scheduled = true;
341
339
  queueMicrotask(() => scheduled = false);
342
- batch(() => {
343
- setLoading(true);
340
+ runUpdates(() => {
341
+ setState(resolved ? "refreshing" : "pending");
344
342
  trigger();
345
- });
346
- return p.then(v => loadEnd(p, v, undefined, lookup), e => loadEnd(p, e, e));
343
+ }, false);
344
+ return p.then(v => loadEnd(p, v, true, lookup), e => loadEnd(p, e, false));
347
345
  }
348
346
  Object.defineProperties(read, {
347
+ state: {
348
+ get() {
349
+ return state();
350
+ }
351
+ },
349
352
  loading: {
350
353
  get() {
351
- return loading();
354
+ const s = state();
355
+ return s === "pending" || s === "refreshing";
352
356
  }
353
357
  },
354
358
  error: {
355
359
  get() {
356
- return error();
360
+ return state() === "error" ? err : undefined;
357
361
  }
358
362
  },
359
363
  latest: {
360
364
  get() {
361
365
  if (!resolved) return read();
362
- if (err) throw err;
366
+ if (state() === "error") throw err;
363
367
  return value();
364
368
  }
365
369
  }
@@ -421,14 +425,7 @@ function batch(fn) {
421
425
  Pending = null;
422
426
  }
423
427
  runUpdates(() => {
424
- for (let i = 0; i < q.length; i += 1) {
425
- const data = q[i];
426
- if (data.pending !== NOTPENDING) {
427
- const pending = data.pending;
428
- data.pending = NOTPENDING;
429
- writeSignal(data, pending);
430
- }
431
- }
428
+ for (let i = 0; i < q.length; i += 1) notifySignal(q[i]);
432
429
  }, false);
433
430
  return result;
434
431
  }
@@ -513,7 +510,7 @@ function startTransition(fn) {
513
510
  t.done || (t.done = new Promise(res => t.resolve = res));
514
511
  t.running = true;
515
512
  }
516
- batch(fn);
513
+ runUpdates(fn, false);
517
514
  Listener = Owner = null;
518
515
  return t ? t.done : undefined;
519
516
  });
@@ -592,29 +589,26 @@ function readSignal() {
592
589
  return this.value;
593
590
  }
594
591
  function writeSignal(node, value, isComp) {
595
- if (Pending) {
596
- if (node.pending === NOTPENDING) Pending.push(node);
597
- node.pending = value;
598
- return value;
599
- }
600
- if (node.comparator) {
601
- if (Transition && Transition.running && Transition.sources.has(node)) {
602
- if (node.comparator(node.tValue, value)) return value;
603
- } else if (node.comparator(node.value, value)) return value;
592
+ let current = Transition && Transition.running && Transition.sources.has(node) ? node.tValue : node.value;
593
+ if (!node.comparator || !node.comparator(current, value)) {
594
+ if (Transition) {
595
+ const TransitionRunning = Transition.running;
596
+ if (TransitionRunning || !isComp && Transition.sources.has(node)) {
597
+ Transition.sources.add(node);
598
+ node.tValue = value;
599
+ }
600
+ if (!TransitionRunning) node.value = value;
601
+ } else node.value = value;
602
+ if (Pending) Pending.push(node);else notifySignal(node);
604
603
  }
605
- let TransitionRunning = false;
606
- if (Transition) {
607
- TransitionRunning = Transition.running;
608
- if (TransitionRunning || !isComp && Transition.sources.has(node)) {
609
- Transition.sources.add(node);
610
- node.tValue = value;
611
- }
612
- if (!TransitionRunning) node.value = value;
613
- } else node.value = value;
604
+ return value;
605
+ }
606
+ function notifySignal(node) {
614
607
  if (node.observers && node.observers.length) {
615
608
  runUpdates(() => {
616
609
  for (let i = 0; i < node.observers.length; i += 1) {
617
610
  const o = node.observers[i];
611
+ const TransitionRunning = Transition && Transition.running;
618
612
  if (TransitionRunning && Transition.disposed.has(o)) continue;
619
613
  if (TransitionRunning && !o.tState || !TransitionRunning && !o.state) {
620
614
  if (o.pure) Updates.push(o);else Effects.push(o);
@@ -629,7 +623,6 @@ function writeSignal(node, value, isComp) {
629
623
  }
630
624
  }, false);
631
625
  }
632
- return value;
633
626
  }
634
627
  function updateComputation(node) {
635
628
  if (!node.fn) return;
@@ -658,7 +651,7 @@ function runComputation(node, value, time) {
658
651
  handleError(err);
659
652
  }
660
653
  if (!node.updatedAt || node.updatedAt <= time) {
661
- if (node.observers && node.observers.length) {
654
+ if (node.updatedAt && "observers" in node) {
662
655
  writeSignal(node, nextValue, true);
663
656
  } else if (Transition && Transition.running && node.pure) {
664
657
  Transition.sources.add(node);
@@ -747,10 +740,8 @@ function runUpdates(fn, init) {
747
740
  completeUpdates(wait);
748
741
  return res;
749
742
  } catch (err) {
743
+ if (!Updates) Effects = null;
750
744
  handleError(err);
751
- } finally {
752
- Updates = null;
753
- if (!wait) Effects = null;
754
745
  }
755
746
  }
756
747
  function completeUpdates(wait) {
@@ -776,7 +767,7 @@ function completeUpdates(wait) {
776
767
  delete e.tState;
777
768
  }
778
769
  Transition = null;
779
- batch(() => {
770
+ runUpdates(() => {
780
771
  for (const d of disposed) cleanNode(d);
781
772
  for (const v of sources) {
782
773
  v.value = v.tValue;
@@ -789,14 +780,11 @@ function completeUpdates(wait) {
789
780
  v.tState = 0;
790
781
  }
791
782
  setTransPending(false);
792
- });
793
- }
794
- if (Effects.length) batch(() => {
795
- runEffects(Effects);
796
- Effects = null;
797
- });else {
798
- Effects = null;
783
+ }, false);
799
784
  }
785
+ const e = Effects;
786
+ Effects = null;
787
+ if (e.length) runUpdates(() => runEffects(e), false);
800
788
  if (res) res();
801
789
  }
802
790
  function runQueue(queue) {
@@ -831,9 +819,9 @@ function runUserEffects(queue) {
831
819
  if (!e.user) runTop(e);else queue[userLength++] = e;
832
820
  }
833
821
  if (sharedConfig.context) setHydrateContext();
834
- const resume = queue.length;
822
+ Effects = [];
835
823
  for (i = 0; i < userLength; i++) runTop(queue[i]);
836
- for (i = resume; i < queue.length; i++) runTop(queue[i]);
824
+ if (Effects.length) runUserEffects(Effects);
837
825
  }
838
826
  function lookUpstream(node, ignore) {
839
827
  const runningTransition = Transition && Transition.running;
@@ -902,7 +890,12 @@ function reset(node, top) {
902
890
  for (let i = 0; i < node.owned.length; i++) reset(node.owned[i]);
903
891
  }
904
892
  }
893
+ function castError(err) {
894
+ if (err instanceof Error || typeof err === "string") return err;
895
+ return new Error("Unknown error");
896
+ }
905
897
  function handleError(err) {
898
+ err = castError(err);
906
899
  const fns = ERROR && lookup(Owner, ERROR);
907
900
  if (!fns) throw err;
908
901
  for (const f of fns) f(err);
@@ -935,31 +928,33 @@ function createProvider(id) {
935
928
  };
936
929
  }
937
930
 
938
- function getSymbol() {
939
- const SymbolCopy = Symbol;
940
- return SymbolCopy.observable || "@@observable";
941
- }
942
931
  function observable(input) {
943
- const $$observable = getSymbol();
944
932
  return {
945
933
  subscribe(observer) {
946
934
  if (!(observer instanceof Object) || observer == null) {
947
935
  throw new TypeError("Expected the observer to be an object.");
948
936
  }
949
- const handler = "next" in observer ? observer.next.bind(observer) : observer;
950
- let complete = false;
951
- createComputed(() => {
952
- if (complete) return;
953
- const v = input();
954
- untrack(() => handler(v));
937
+ const handler = typeof observer === 'function' ? observer : observer.next && observer.next.bind(observer);
938
+ if (!handler) {
939
+ return {
940
+ unsubscribe() {}
941
+ };
942
+ }
943
+ const dispose = createRoot(disposer => {
944
+ createComputed(() => {
945
+ const v = input();
946
+ untrack(() => handler(v));
947
+ });
948
+ return disposer;
955
949
  });
950
+ if (getOwner()) onCleanup(dispose);
956
951
  return {
957
952
  unsubscribe() {
958
- complete = true;
953
+ dispose();
959
954
  }
960
955
  };
961
956
  },
962
- [$$observable]() {
957
+ [Symbol.observable || "@@observable"]() {
963
958
  return this;
964
959
  }
965
960
  };
@@ -1335,24 +1330,22 @@ function Match(props) {
1335
1330
  return props;
1336
1331
  }
1337
1332
  let Errors;
1338
- const NoErrors = {};
1339
1333
  function resetErrorBoundaries() {
1340
- Errors && [...Errors].forEach(fn => fn(NoErrors));
1334
+ Errors && [...Errors].forEach(fn => fn());
1341
1335
  }
1342
1336
  function ErrorBoundary(props) {
1343
- let err = NoErrors;
1344
- if (sharedConfig.context && sharedConfig.load) {
1345
- err = sharedConfig.load(sharedConfig.context.id + sharedConfig.context.count) || NoErrors;
1346
- }
1337
+ let err;
1338
+ let v;
1339
+ if (sharedConfig.context && sharedConfig.load && (v = sharedConfig.load(sharedConfig.context.id + sharedConfig.context.count))) err = v[0];
1347
1340
  const [errored, setErrored] = createSignal(err);
1348
1341
  Errors || (Errors = new Set());
1349
1342
  Errors.add(setErrored);
1350
1343
  onCleanup(() => Errors.delete(setErrored));
1351
1344
  return createMemo(() => {
1352
1345
  let e;
1353
- if ((e = errored()) !== NoErrors) {
1346
+ if (e = errored()) {
1354
1347
  const f = props.fallback;
1355
- return typeof f === "function" && f.length ? untrack(() => f(e, () => setErrored(NoErrors))) : f;
1348
+ return typeof f === "function" && f.length ? untrack(() => f(e, setErrored)) : f;
1356
1349
  }
1357
1350
  onError(setErrored);
1358
1351
  return props.children;
@@ -1447,20 +1440,26 @@ function Suspense(props) {
1447
1440
  owner = getOwner();
1448
1441
  if (sharedConfig.context && sharedConfig.load) {
1449
1442
  const key = sharedConfig.context.id + sharedConfig.context.count;
1450
- p = sharedConfig.load(key);
1451
- if (p) {
1452
- if (typeof p !== "object" || !("then" in p)) p = Promise.resolve(p);
1453
- const [s, set] = createSignal(undefined, {
1454
- equals: false
1455
- });
1456
- flicker = s;
1457
- p.then(err => {
1458
- if ((error = err) || sharedConfig.done) return set();
1459
- sharedConfig.gather(key);
1460
- setHydrateContext(ctx);
1461
- set();
1462
- setHydrateContext();
1463
- });
1443
+ let ref = sharedConfig.load(key);
1444
+ if (ref) {
1445
+ p = ref[0];
1446
+ if (p === "$$$") sharedConfig.gather(key);else {
1447
+ if (typeof p !== "object" || !("then" in p)) p = Promise.resolve(p);
1448
+ const [s, set] = createSignal(undefined, {
1449
+ equals: false
1450
+ });
1451
+ flicker = s;
1452
+ p.then(err => {
1453
+ if (err !== "$$$" || sharedConfig.done) {
1454
+ err !== "$$$" && (error = err);
1455
+ return set();
1456
+ }
1457
+ sharedConfig.gather(key);
1458
+ setHydrateContext(ctx);
1459
+ set();
1460
+ setHydrateContext();
1461
+ });
1462
+ }
1464
1463
  }
1465
1464
  }
1466
1465
  const listContext = useContext(SuspenseListContext);
@@ -1477,14 +1476,14 @@ function Suspense(props) {
1477
1476
  flicker();
1478
1477
  return flicker = undefined;
1479
1478
  }
1480
- if (ctx && p === undefined) setHydrateContext();
1479
+ if (ctx && !p) setHydrateContext();
1481
1480
  const rendered = createMemo(() => props.children);
1482
1481
  return createMemo(() => {
1483
1482
  const inFallback = store.inFallback(),
1484
1483
  visibleContent = showContent ? showContent() : true,
1485
1484
  visibleFallback = showFallback ? showFallback() : true;
1486
1485
  dispose && dispose();
1487
- if ((!inFallback || p !== undefined) && visibleContent) {
1486
+ if ((!inFallback || p) && visibleContent) {
1488
1487
  store.resolved = true;
1489
1488
  ctx = p = undefined;
1490
1489
  resumeEffects(store.effects);