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/solid.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;
@@ -179,12 +179,11 @@ function createSignal(value, options) {
179
179
  value,
180
180
  observers: null,
181
181
  observerSlots: null,
182
- pending: NOTPENDING,
183
182
  comparator: options.equals || undefined
184
183
  };
185
184
  const setter = value => {
186
185
  if (typeof value === "function") {
187
- 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);
186
+ if (Transition && Transition.running && Transition.sources.has(s)) value = value(s.tValue);else value = value(s.value);
188
187
  }
189
188
  return writeSignal(s, value);
190
189
  };
@@ -223,7 +222,6 @@ function createReaction(onInvalidate, options) {
223
222
  function createMemo(fn, value, options) {
224
223
  options = options ? Object.assign({}, signalOptions, options) : signalOptions;
225
224
  const c = createComputation(fn, value, true, 0);
226
- c.pending = NOTPENDING;
227
225
  c.observers = null;
228
226
  c.observerSlots = null;
229
227
  c.comparator = options.equals || undefined;
@@ -245,34 +243,33 @@ function createResource(source, fetcher, options) {
245
243
  source = true;
246
244
  }
247
245
  options || (options = {});
248
- const contexts = new Set(),
249
- [value, setValue] = createSignal(options.initialValue),
250
- [track, trigger] = createSignal(undefined, {
251
- equals: false
252
- }),
253
- [loading, setLoading] = createSignal(false),
254
- [error, setError] = createSignal();
255
246
  let err = undefined,
256
247
  pr = null,
257
- initP = null,
248
+ initP = NO_INIT,
258
249
  id = null,
259
250
  loadedUnderTransition = false,
260
251
  scheduled = false,
261
252
  resolved = ("initialValue" in options),
262
253
  dynamic = typeof source === "function" && createMemo(source);
254
+ const contexts = new Set(),
255
+ [value, setValue] = options.store ? options.store(options.initialValue) : createSignal(options.initialValue),
256
+ [track, trigger] = createSignal(undefined, {
257
+ equals: false
258
+ }),
259
+ [state, setState] = createSignal(resolved ? "ready" : "unresolved");
263
260
  if (sharedConfig.context) {
264
261
  id = `${sharedConfig.context.id}${sharedConfig.context.count++}`;
265
- if (sharedConfig.load) initP = sharedConfig.load(id);
262
+ let v;
263
+ if (sharedConfig.load && (v = sharedConfig.load(id))) initP = v[0];
266
264
  }
267
- function loadEnd(p, v, e, key) {
265
+ function loadEnd(p, v, success, key) {
268
266
  if (pr === p) {
269
267
  pr = null;
270
268
  resolved = true;
271
- if (initP && (p === initP || v === initP) && options.onHydrated) queueMicrotask(() => options.onHydrated(key, {
269
+ if ((p === initP || v === initP) && options.onHydrated) queueMicrotask(() => options.onHydrated(key, {
272
270
  value: v
273
271
  }));
274
- initP = null;
275
- setError(err = e);
272
+ initP = NO_INIT;
276
273
  if (Transition && p && loadedUnderTransition) {
277
274
  Transition.promises.delete(p);
278
275
  loadedUnderTransition = false;
@@ -282,19 +279,20 @@ function createResource(source, fetcher, options) {
282
279
  Effects.push.apply(Effects, Transition.effects);
283
280
  Transition.effects = [];
284
281
  }
285
- completeLoad(v);
282
+ completeLoad(v, success);
286
283
  }, false);
287
- } else completeLoad(v);
284
+ } else completeLoad(v, success);
288
285
  }
289
286
  return v;
290
287
  }
291
- function completeLoad(v) {
292
- batch(() => {
293
- setValue(() => v);
294
- setLoading(false);
288
+ function completeLoad(v, success) {
289
+ !success && (err = castError(v));
290
+ runUpdates(() => {
291
+ setValue(() => success ? v : undefined);
292
+ setState(success ? "ready" : "error");
295
293
  for (const c of contexts.keys()) c.decrement();
296
294
  contexts.clear();
297
- });
295
+ }, false);
298
296
  }
299
297
  function read() {
300
298
  const c = SuspenseContext && lookup(Owner, SuspenseContext.id),
@@ -316,46 +314,52 @@ function createResource(source, fetcher, options) {
316
314
  function load(refetching = true) {
317
315
  if (refetching && scheduled) return;
318
316
  scheduled = false;
319
- setError(err = undefined);
317
+ err = undefined;
320
318
  const lookup = dynamic ? dynamic() : source;
321
319
  loadedUnderTransition = Transition && Transition.running;
322
320
  if (lookup == null || lookup === false) {
323
- loadEnd(pr, untrack(value));
321
+ loadEnd(pr, untrack(value), true);
324
322
  return;
325
323
  }
326
324
  if (Transition && pr) Transition.promises.delete(pr);
327
- const p = initP || untrack(() => fetcher(lookup, {
325
+ const p = initP !== NO_INIT ? initP : untrack(() => fetcher(lookup, {
328
326
  value: value(),
329
327
  refetching
330
328
  }));
331
329
  if (typeof p !== "object" || !("then" in p)) {
332
- loadEnd(pr, p);
330
+ loadEnd(pr, p, true);
333
331
  return p;
334
332
  }
335
333
  pr = p;
336
334
  scheduled = true;
337
335
  queueMicrotask(() => scheduled = false);
338
- batch(() => {
339
- setLoading(true);
336
+ runUpdates(() => {
337
+ setState(resolved ? "refreshing" : "pending");
340
338
  trigger();
341
- });
342
- return p.then(v => loadEnd(p, v, undefined, lookup), e => loadEnd(p, e, e));
339
+ }, false);
340
+ return p.then(v => loadEnd(p, v, true, lookup), e => loadEnd(p, e, false));
343
341
  }
344
342
  Object.defineProperties(read, {
343
+ state: {
344
+ get() {
345
+ return state();
346
+ }
347
+ },
345
348
  loading: {
346
349
  get() {
347
- return loading();
350
+ const s = state();
351
+ return s === "pending" || s === "refreshing";
348
352
  }
349
353
  },
350
354
  error: {
351
355
  get() {
352
- return error();
356
+ return state() === "error" ? err : undefined;
353
357
  }
354
358
  },
355
359
  latest: {
356
360
  get() {
357
361
  if (!resolved) return read();
358
- if (err) throw err;
362
+ if (state() === "error") throw err;
359
363
  return value();
360
364
  }
361
365
  }
@@ -417,14 +421,7 @@ function batch(fn) {
417
421
  Pending = null;
418
422
  }
419
423
  runUpdates(() => {
420
- for (let i = 0; i < q.length; i += 1) {
421
- const data = q[i];
422
- if (data.pending !== NOTPENDING) {
423
- const pending = data.pending;
424
- data.pending = NOTPENDING;
425
- writeSignal(data, pending);
426
- }
427
- }
424
+ for (let i = 0; i < q.length; i += 1) notifySignal(q[i]);
428
425
  }, false);
429
426
  return result;
430
427
  }
@@ -509,7 +506,7 @@ function startTransition(fn) {
509
506
  t.done || (t.done = new Promise(res => t.resolve = res));
510
507
  t.running = true;
511
508
  }
512
- batch(fn);
509
+ runUpdates(fn, false);
513
510
  Listener = Owner = null;
514
511
  return t ? t.done : undefined;
515
512
  });
@@ -588,29 +585,26 @@ function readSignal() {
588
585
  return this.value;
589
586
  }
590
587
  function writeSignal(node, value, isComp) {
591
- if (Pending) {
592
- if (node.pending === NOTPENDING) Pending.push(node);
593
- node.pending = value;
594
- return value;
595
- }
596
- if (node.comparator) {
597
- if (Transition && Transition.running && Transition.sources.has(node)) {
598
- if (node.comparator(node.tValue, value)) return value;
599
- } else if (node.comparator(node.value, value)) return value;
588
+ let current = Transition && Transition.running && Transition.sources.has(node) ? node.tValue : node.value;
589
+ if (!node.comparator || !node.comparator(current, value)) {
590
+ if (Transition) {
591
+ const TransitionRunning = Transition.running;
592
+ if (TransitionRunning || !isComp && Transition.sources.has(node)) {
593
+ Transition.sources.add(node);
594
+ node.tValue = value;
595
+ }
596
+ if (!TransitionRunning) node.value = value;
597
+ } else node.value = value;
598
+ if (Pending) Pending.push(node);else notifySignal(node);
600
599
  }
601
- let TransitionRunning = false;
602
- if (Transition) {
603
- TransitionRunning = Transition.running;
604
- if (TransitionRunning || !isComp && Transition.sources.has(node)) {
605
- Transition.sources.add(node);
606
- node.tValue = value;
607
- }
608
- if (!TransitionRunning) node.value = value;
609
- } else node.value = value;
600
+ return value;
601
+ }
602
+ function notifySignal(node) {
610
603
  if (node.observers && node.observers.length) {
611
604
  runUpdates(() => {
612
605
  for (let i = 0; i < node.observers.length; i += 1) {
613
606
  const o = node.observers[i];
607
+ const TransitionRunning = Transition && Transition.running;
614
608
  if (TransitionRunning && Transition.disposed.has(o)) continue;
615
609
  if (TransitionRunning && !o.tState || !TransitionRunning && !o.state) {
616
610
  if (o.pure) Updates.push(o);else Effects.push(o);
@@ -625,7 +619,6 @@ function writeSignal(node, value, isComp) {
625
619
  }
626
620
  }, false);
627
621
  }
628
- return value;
629
622
  }
630
623
  function updateComputation(node) {
631
624
  if (!node.fn) return;
@@ -654,7 +647,7 @@ function runComputation(node, value, time) {
654
647
  handleError(err);
655
648
  }
656
649
  if (!node.updatedAt || node.updatedAt <= time) {
657
- if (node.observers && node.observers.length) {
650
+ if (node.updatedAt && "observers" in node) {
658
651
  writeSignal(node, nextValue, true);
659
652
  } else if (Transition && Transition.running && node.pure) {
660
653
  Transition.sources.add(node);
@@ -743,10 +736,8 @@ function runUpdates(fn, init) {
743
736
  completeUpdates(wait);
744
737
  return res;
745
738
  } catch (err) {
739
+ if (!Updates) Effects = null;
746
740
  handleError(err);
747
- } finally {
748
- Updates = null;
749
- if (!wait) Effects = null;
750
741
  }
751
742
  }
752
743
  function completeUpdates(wait) {
@@ -772,7 +763,7 @@ function completeUpdates(wait) {
772
763
  delete e.tState;
773
764
  }
774
765
  Transition = null;
775
- batch(() => {
766
+ runUpdates(() => {
776
767
  for (const d of disposed) cleanNode(d);
777
768
  for (const v of sources) {
778
769
  v.value = v.tValue;
@@ -785,14 +776,11 @@ function completeUpdates(wait) {
785
776
  v.tState = 0;
786
777
  }
787
778
  setTransPending(false);
788
- });
789
- }
790
- if (Effects.length) batch(() => {
791
- runEffects(Effects);
792
- Effects = null;
793
- });else {
794
- Effects = null;
779
+ }, false);
795
780
  }
781
+ const e = Effects;
782
+ Effects = null;
783
+ if (e.length) runUpdates(() => runEffects(e), false);
796
784
  if (res) res();
797
785
  }
798
786
  function runQueue(queue) {
@@ -827,9 +815,9 @@ function runUserEffects(queue) {
827
815
  if (!e.user) runTop(e);else queue[userLength++] = e;
828
816
  }
829
817
  if (sharedConfig.context) setHydrateContext();
830
- const resume = queue.length;
818
+ Effects = [];
831
819
  for (i = 0; i < userLength; i++) runTop(queue[i]);
832
- for (i = resume; i < queue.length; i++) runTop(queue[i]);
820
+ if (Effects.length) runUserEffects(Effects);
833
821
  }
834
822
  function lookUpstream(node, ignore) {
835
823
  const runningTransition = Transition && Transition.running;
@@ -898,7 +886,12 @@ function reset(node, top) {
898
886
  for (let i = 0; i < node.owned.length; i++) reset(node.owned[i]);
899
887
  }
900
888
  }
889
+ function castError(err) {
890
+ if (err instanceof Error || typeof err === "string") return err;
891
+ return new Error("Unknown error");
892
+ }
901
893
  function handleError(err) {
894
+ err = castError(err);
902
895
  const fns = ERROR && lookup(Owner, ERROR);
903
896
  if (!fns) throw err;
904
897
  for (const f of fns) f(err);
@@ -931,31 +924,33 @@ function createProvider(id) {
931
924
  };
932
925
  }
933
926
 
934
- function getSymbol() {
935
- const SymbolCopy = Symbol;
936
- return SymbolCopy.observable || "@@observable";
937
- }
938
927
  function observable(input) {
939
- const $$observable = getSymbol();
940
928
  return {
941
929
  subscribe(observer) {
942
930
  if (!(observer instanceof Object) || observer == null) {
943
931
  throw new TypeError("Expected the observer to be an object.");
944
932
  }
945
- const handler = "next" in observer ? observer.next.bind(observer) : observer;
946
- let complete = false;
947
- createComputed(() => {
948
- if (complete) return;
949
- const v = input();
950
- untrack(() => handler(v));
933
+ const handler = typeof observer === 'function' ? observer : observer.next && observer.next.bind(observer);
934
+ if (!handler) {
935
+ return {
936
+ unsubscribe() {}
937
+ };
938
+ }
939
+ const dispose = createRoot(disposer => {
940
+ createComputed(() => {
941
+ const v = input();
942
+ untrack(() => handler(v));
943
+ });
944
+ return disposer;
951
945
  });
946
+ if (getOwner()) onCleanup(dispose);
952
947
  return {
953
948
  unsubscribe() {
954
- complete = true;
949
+ dispose();
955
950
  }
956
951
  };
957
952
  },
958
- [$$observable]() {
953
+ [Symbol.observable || "@@observable"]() {
959
954
  return this;
960
955
  }
961
956
  };
@@ -1331,24 +1326,22 @@ function Match(props) {
1331
1326
  return props;
1332
1327
  }
1333
1328
  let Errors;
1334
- const NoErrors = {};
1335
1329
  function resetErrorBoundaries() {
1336
- Errors && [...Errors].forEach(fn => fn(NoErrors));
1330
+ Errors && [...Errors].forEach(fn => fn());
1337
1331
  }
1338
1332
  function ErrorBoundary(props) {
1339
- let err = NoErrors;
1340
- if (sharedConfig.context && sharedConfig.load) {
1341
- err = sharedConfig.load(sharedConfig.context.id + sharedConfig.context.count) || NoErrors;
1342
- }
1333
+ let err;
1334
+ let v;
1335
+ if (sharedConfig.context && sharedConfig.load && (v = sharedConfig.load(sharedConfig.context.id + sharedConfig.context.count))) err = v[0];
1343
1336
  const [errored, setErrored] = createSignal(err);
1344
1337
  Errors || (Errors = new Set());
1345
1338
  Errors.add(setErrored);
1346
1339
  onCleanup(() => Errors.delete(setErrored));
1347
1340
  return createMemo(() => {
1348
1341
  let e;
1349
- if ((e = errored()) !== NoErrors) {
1342
+ if (e = errored()) {
1350
1343
  const f = props.fallback;
1351
- return typeof f === "function" && f.length ? untrack(() => f(e, () => setErrored(NoErrors))) : f;
1344
+ return typeof f === "function" && f.length ? untrack(() => f(e, setErrored)) : f;
1352
1345
  }
1353
1346
  onError(setErrored);
1354
1347
  return props.children;
@@ -1443,20 +1436,26 @@ function Suspense(props) {
1443
1436
  owner = getOwner();
1444
1437
  if (sharedConfig.context && sharedConfig.load) {
1445
1438
  const key = sharedConfig.context.id + sharedConfig.context.count;
1446
- p = sharedConfig.load(key);
1447
- if (p) {
1448
- if (typeof p !== "object" || !("then" in p)) p = Promise.resolve(p);
1449
- const [s, set] = createSignal(undefined, {
1450
- equals: false
1451
- });
1452
- flicker = s;
1453
- p.then(err => {
1454
- if ((error = err) || sharedConfig.done) return set();
1455
- sharedConfig.gather(key);
1456
- setHydrateContext(ctx);
1457
- set();
1458
- setHydrateContext();
1459
- });
1439
+ let ref = sharedConfig.load(key);
1440
+ if (ref) {
1441
+ p = ref[0];
1442
+ if (p === "$$$") sharedConfig.gather(key);else {
1443
+ if (typeof p !== "object" || !("then" in p)) p = Promise.resolve(p);
1444
+ const [s, set] = createSignal(undefined, {
1445
+ equals: false
1446
+ });
1447
+ flicker = s;
1448
+ p.then(err => {
1449
+ if (err !== "$$$" || sharedConfig.done) {
1450
+ err !== "$$$" && (error = err);
1451
+ return set();
1452
+ }
1453
+ sharedConfig.gather(key);
1454
+ setHydrateContext(ctx);
1455
+ set();
1456
+ setHydrateContext();
1457
+ });
1458
+ }
1460
1459
  }
1461
1460
  }
1462
1461
  const listContext = useContext(SuspenseListContext);
@@ -1473,14 +1472,14 @@ function Suspense(props) {
1473
1472
  flicker();
1474
1473
  return flicker = undefined;
1475
1474
  }
1476
- if (ctx && p === undefined) setHydrateContext();
1475
+ if (ctx && !p) setHydrateContext();
1477
1476
  const rendered = createMemo(() => props.children);
1478
1477
  return createMemo(() => {
1479
1478
  const inFallback = store.inFallback(),
1480
1479
  visibleContent = showContent ? showContent() : true,
1481
1480
  visibleFallback = showFallback ? showFallback() : true;
1482
1481
  dispose && dispose();
1483
- if ((!inFallback || p !== undefined) && visibleContent) {
1482
+ if ((!inFallback || p) && visibleContent) {
1484
1483
  store.resolved = true;
1485
1484
  ctx = p = undefined;
1486
1485
  resumeEffects(store.effects);