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