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/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);
@@ -774,7 +767,7 @@ function completeUpdates(wait) {
774
767
  delete e.tState;
775
768
  }
776
769
  Transition = null;
777
- batch(() => {
770
+ runUpdates(() => {
778
771
  for (const d of disposed) cleanNode(d);
779
772
  for (const v of sources) {
780
773
  v.value = v.tValue;
@@ -787,14 +780,11 @@ function completeUpdates(wait) {
787
780
  v.tState = 0;
788
781
  }
789
782
  setTransPending(false);
790
- });
791
- }
792
- if (Effects.length) batch(() => {
793
- runEffects(Effects);
794
- Effects = null;
795
- });else {
796
- Effects = null;
783
+ }, false);
797
784
  }
785
+ const e = Effects;
786
+ Effects = null;
787
+ if (e.length) runUpdates(() => runEffects(e), false);
798
788
  if (res) res();
799
789
  }
800
790
  function runQueue(queue) {
@@ -829,9 +819,9 @@ function runUserEffects(queue) {
829
819
  if (!e.user) runTop(e);else queue[userLength++] = e;
830
820
  }
831
821
  if (sharedConfig.context) setHydrateContext();
832
- const resume = queue.length;
822
+ Effects = [];
833
823
  for (i = 0; i < userLength; i++) runTop(queue[i]);
834
- for (i = resume; i < queue.length; i++) runTop(queue[i]);
824
+ if (Effects.length) runUserEffects(Effects);
835
825
  }
836
826
  function lookUpstream(node, ignore) {
837
827
  const runningTransition = Transition && Transition.running;
@@ -900,7 +890,12 @@ function reset(node, top) {
900
890
  for (let i = 0; i < node.owned.length; i++) reset(node.owned[i]);
901
891
  }
902
892
  }
893
+ function castError(err) {
894
+ if (err instanceof Error || typeof err === "string") return err;
895
+ return new Error("Unknown error");
896
+ }
903
897
  function handleError(err) {
898
+ err = castError(err);
904
899
  const fns = ERROR && lookup(Owner, ERROR);
905
900
  if (!fns) throw err;
906
901
  for (const f of fns) f(err);
@@ -933,31 +928,33 @@ function createProvider(id) {
933
928
  };
934
929
  }
935
930
 
936
- function getSymbol() {
937
- const SymbolCopy = Symbol;
938
- return SymbolCopy.observable || "@@observable";
939
- }
940
931
  function observable(input) {
941
- const $$observable = getSymbol();
942
932
  return {
943
933
  subscribe(observer) {
944
934
  if (!(observer instanceof Object) || observer == null) {
945
935
  throw new TypeError("Expected the observer to be an object.");
946
936
  }
947
- const handler = "next" in observer ? observer.next.bind(observer) : observer;
948
- let complete = false;
949
- createComputed(() => {
950
- if (complete) return;
951
- const v = input();
952
- 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;
953
949
  });
950
+ if (getOwner()) onCleanup(dispose);
954
951
  return {
955
952
  unsubscribe() {
956
- complete = true;
953
+ dispose();
957
954
  }
958
955
  };
959
956
  },
960
- [$$observable]() {
957
+ [Symbol.observable || "@@observable"]() {
961
958
  return this;
962
959
  }
963
960
  };
@@ -1333,24 +1330,22 @@ function Match(props) {
1333
1330
  return props;
1334
1331
  }
1335
1332
  let Errors;
1336
- const NoErrors = {};
1337
1333
  function resetErrorBoundaries() {
1338
- Errors && [...Errors].forEach(fn => fn(NoErrors));
1334
+ Errors && [...Errors].forEach(fn => fn());
1339
1335
  }
1340
1336
  function ErrorBoundary(props) {
1341
- let err = NoErrors;
1342
- if (sharedConfig.context && sharedConfig.load) {
1343
- err = sharedConfig.load(sharedConfig.context.id + sharedConfig.context.count) || NoErrors;
1344
- }
1337
+ let err;
1338
+ let v;
1339
+ if (sharedConfig.context && sharedConfig.load && (v = sharedConfig.load(sharedConfig.context.id + sharedConfig.context.count))) err = v[0];
1345
1340
  const [errored, setErrored] = createSignal(err);
1346
1341
  Errors || (Errors = new Set());
1347
1342
  Errors.add(setErrored);
1348
1343
  onCleanup(() => Errors.delete(setErrored));
1349
1344
  return createMemo(() => {
1350
1345
  let e;
1351
- if ((e = errored()) !== NoErrors) {
1346
+ if (e = errored()) {
1352
1347
  const f = props.fallback;
1353
- return typeof f === "function" && f.length ? untrack(() => f(e, () => setErrored(NoErrors))) : f;
1348
+ return typeof f === "function" && f.length ? untrack(() => f(e, setErrored)) : f;
1354
1349
  }
1355
1350
  onError(setErrored);
1356
1351
  return props.children;
@@ -1445,21 +1440,27 @@ function Suspense(props) {
1445
1440
  owner = getOwner();
1446
1441
  if (sharedConfig.context && sharedConfig.load) {
1447
1442
  const key = sharedConfig.context.id + sharedConfig.context.count;
1448
- p = sharedConfig.load(key);
1449
- if (p) {
1450
- if (typeof p !== "object" || !("then" in p)) p = Promise.resolve(p);
1451
- const [s, set] = createSignal(undefined, {
1452
- equals: false
1453
- });
1454
- flicker = s;
1455
- p.then(err => {
1456
- if ((error = err) || sharedConfig.done) return set();
1457
- sharedConfig.gather(key);
1458
- setHydrateContext(ctx);
1459
- set();
1460
- setHydrateContext();
1461
- });
1462
- } else if (p === null) sharedConfig.gather(key);
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
+ }
1463
+ }
1463
1464
  }
1464
1465
  const listContext = useContext(SuspenseListContext);
1465
1466
  if (listContext) [showContent, showFallback] = listContext.register(store.inFallback);
@@ -1475,14 +1476,14 @@ function Suspense(props) {
1475
1476
  flicker();
1476
1477
  return flicker = undefined;
1477
1478
  }
1478
- if (ctx && p === undefined) setHydrateContext();
1479
+ if (ctx && !p) setHydrateContext();
1479
1480
  const rendered = createMemo(() => props.children);
1480
1481
  return createMemo(() => {
1481
1482
  const inFallback = store.inFallback(),
1482
1483
  visibleContent = showContent ? showContent() : true,
1483
1484
  visibleFallback = showFallback ? showFallback() : true;
1484
1485
  dispose && dispose();
1485
- if ((!inFallback || p !== undefined) && visibleContent) {
1486
+ if ((!inFallback || p) && visibleContent) {
1486
1487
  store.resolved = true;
1487
1488
  ctx = p = undefined;
1488
1489
  resumeEffects(store.effects);