solid-js 1.1.6-beta.0 → 1.2.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/README.md CHANGED
@@ -115,11 +115,9 @@ For TypeScript remember to set your TSConfig to handle Solid's JSX by:
115
115
  ## Documentation
116
116
 
117
117
  Check out the [Documentation](https://www.solidjs.com/guide) website.
118
- ### Resources
119
118
 
120
- - [Examples](https://github.com/solidjs/solid/blob/main/documentation/resources/examples.md)
121
- - [Articles](https://github.com/solidjs/solid/blob/main/documentation/resources/articles.md)
122
- - [Projects](https://github.com/solidjs/solid/blob/main/documentation/resources/projects.md)
119
+ [Examples](https://github.com/solidjs/solid/blob/main/documentation/resources/examples.md)
120
+
123
121
  ## Browser Support
124
122
 
125
123
  The last 2 versions of modern evergreen browsers and Node LTS.
package/dist/dev.cjs CHANGED
@@ -145,6 +145,7 @@ const UNOWNED = {
145
145
  context: null,
146
146
  owner: null
147
147
  };
148
+ const [transPending, setTransPending] = /*@__PURE__*/createSignal(false);
148
149
  var Owner = null;
149
150
  let Transition = null;
150
151
  let Scheduler = null;
@@ -154,7 +155,6 @@ let Updates = null;
154
155
  let Effects = null;
155
156
  let ExecCount = 0;
156
157
  let rootCount = 0;
157
- const [transPending, setTransPending] = /*@__PURE__*/createSignal(false);
158
158
  function createRoot(fn, detachedOwner) {
159
159
  detachedOwner && (Owner = detachedOwner);
160
160
  const listener = Listener,
@@ -186,24 +186,12 @@ function createSignal(value, options) {
186
186
  pending: NOTPENDING,
187
187
  comparator: options.equals || undefined
188
188
  };
189
- if (Transition && Transition.running) Transition.sources.add(s);
190
189
  if (!options.internal) s.name = registerGraph(options.name || hashValue(value), s);
191
- return [() => {
192
- let sig = s;
193
- Transition && Transition.running && (sig = Transition.lookup.get(s) || sig);
194
- if (Listener !== null) logRead(sig, Listener);
195
- return sig.value;
196
- }, value => {
197
- let sig = s;
198
- if (Transition) {
199
- if (Transition.running && !(sig = Transition.lookup.get(s))) {
200
- sig = forkSource(s);
201
- } else if (!Transition.running) {
202
- const other = Transition.lookup.get(s);
203
- if (other) writeSignal(other, value);
204
- }
190
+ return [readSignal.bind(s), value => {
191
+ if (typeof value === "function") {
192
+ 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);
205
193
  }
206
- return writeSignal(sig, value);
194
+ return writeSignal(s, value);
207
195
  }];
208
196
  }
209
197
  function createComputed(fn, value, options) {
@@ -228,18 +216,7 @@ function createMemo(fn, value, options) {
228
216
  c.observerSlots = null;
229
217
  c.comparator = options.equals || undefined;
230
218
  updateComputation(c);
231
- return () => {
232
- let sig = c;
233
- Transition && Transition.running && (sig = Transition.lookup.get(c) || sig);
234
- if (c.state && c.sources) {
235
- const updates = Updates;
236
- Updates = null;
237
- c.state === STALE ? updateComputation(c) : lookDownstream(c);
238
- Updates = updates;
239
- }
240
- if (Listener !== null) logRead(sig, Listener);
241
- return sig.value;
242
- };
219
+ return readSignal.bind(c);
243
220
  }
244
221
  function createResource(source, fetcher, options) {
245
222
  if (arguments.length === 2) {
@@ -253,7 +230,7 @@ function createResource(source, fetcher, options) {
253
230
  source = true;
254
231
  }
255
232
  const contexts = new Set(),
256
- [s, set] = createSignal(options?.initialValue),
233
+ [s, set] = createSignal((options || {}).initialValue),
257
234
  [track, trigger] = createSignal(undefined, {
258
235
  equals: false
259
236
  }),
@@ -374,9 +351,8 @@ function createDeferred(source, options) {
374
351
  }
375
352
  function createSelector(source, fn = equalFn, options) {
376
353
  const subs = new Map();
377
- let current;
378
354
  const node = createComputation(p => {
379
- const v = current = source();
355
+ const v = source();
380
356
  for (const key of subs.keys()) if (fn(key, v) || p !== undefined && fn(key, p)) {
381
357
  const l = subs.get(key);
382
358
  for (const c of l.values()) {
@@ -392,9 +368,11 @@ function createSelector(source, fn = equalFn, options) {
392
368
  if (listener = Listener) {
393
369
  let l;
394
370
  if (l = subs.get(key)) l.add(listener);else subs.set(key, l = new Set([listener]));
395
- onCleanup(() => l.size > 1 ? l.delete(listener) : subs.delete(key));
371
+ onCleanup(() => {
372
+ l.size > 1 ? l.delete(listener) : subs.delete(key);
373
+ });
396
374
  }
397
- return fn(key, current);
375
+ return fn(key, Transition && Transition.running && Transition.sources.has(node) ? node.tValue : node.value);
398
376
  };
399
377
  }
400
378
  function batch(fn) {
@@ -407,12 +385,12 @@ function batch(fn) {
407
385
  Pending = null;
408
386
  }
409
387
  runUpdates(() => {
410
- for (let i = 0; i < q.length; i++) {
388
+ for (let i = 0; i < q.length; i += 1) {
411
389
  const data = q[i];
412
390
  if (data.pending !== NOTPENDING) {
413
391
  const pending = data.pending;
414
392
  data.pending = NOTPENDING;
415
- writeSource(data, pending);
393
+ writeSignal(data, pending);
416
394
  }
417
395
  }
418
396
  }, false);
@@ -477,14 +455,18 @@ function enableScheduling(scheduler = requestCallback) {
477
455
  Scheduler = scheduler;
478
456
  }
479
457
  function startTransition(fn, cb) {
458
+ if (Transition && Transition.running) {
459
+ fn();
460
+ cb && Transition.cb.push(cb);
461
+ return;
462
+ }
480
463
  queueMicrotask(() => {
481
464
  if (Scheduler || SuspenseContext) {
482
465
  Transition || (Transition = {
483
466
  sources: new Set(),
484
- lookup: new Map(),
485
- updated: new Set(),
486
467
  effects: [],
487
468
  promises: new Set(),
469
+ disposed: new Set(),
488
470
  queue: new Set(),
489
471
  running: true,
490
472
  cb: []
@@ -511,7 +493,7 @@ function devComponent(Comp, props) {
511
493
  c.state = 0;
512
494
  c.componentName = Comp.name;
513
495
  updateComputation(c);
514
- return c.value;
496
+ return c.tValue !== undefined ? c.tValue : c.value;
515
497
  }
516
498
  function hashValue(v) {
517
499
  const s = new Set();
@@ -570,44 +552,61 @@ let SuspenseContext;
570
552
  function getSuspenseContext() {
571
553
  return SuspenseContext || (SuspenseContext = createContext({}));
572
554
  }
573
- function logRead(node, to) {
574
- const sSlot = node.observers ? node.observers.length : 0;
575
- if (!to.sources) {
576
- to.sources = [node];
577
- to.sourceSlots = [sSlot];
578
- } else {
579
- to.sources.push(node);
580
- to.sourceSlots.push(sSlot);
555
+ function readSignal() {
556
+ if (this.state && this.sources) {
557
+ const updates = Updates;
558
+ Updates = null;
559
+ this.state === STALE || Transition && Transition.running && this.tState ? updateComputation(this) : lookDownstream(this);
560
+ Updates = updates;
581
561
  }
582
- if (!node.observers) {
583
- node.observers = [to];
584
- node.observerSlots = [to.sources.length - 1];
585
- } else {
586
- node.observers.push(to);
587
- node.observerSlots.push(to.sources.length - 1);
562
+ if (Listener) {
563
+ const sSlot = this.observers ? this.observers.length : 0;
564
+ if (!Listener.sources) {
565
+ Listener.sources = [this];
566
+ Listener.sourceSlots = [sSlot];
567
+ } else {
568
+ Listener.sources.push(this);
569
+ Listener.sourceSlots.push(sSlot);
570
+ }
571
+ if (!this.observers) {
572
+ this.observers = [Listener];
573
+ this.observerSlots = [Listener.sources.length - 1];
574
+ } else {
575
+ this.observers.push(Listener);
576
+ this.observerSlots.push(Listener.sources.length - 1);
577
+ }
588
578
  }
589
- }
590
- function writeSignal(node, value) {
591
- if (typeof value === "function") {
592
- value = value(node.pending !== NOTPENDING ? node.pending : node.value);
579
+ if (Transition && Transition.running && Transition.sources.has(this)) return this.tValue;
580
+ return this.value;
581
+ }
582
+ function writeSignal(node, value, isComp) {
583
+ if (node.comparator) {
584
+ if (Transition && Transition.running && Transition.sources.has(node)) {
585
+ if (node.comparator(node.tValue, value)) return value;
586
+ } else if (node.comparator(node.value, value)) return value;
593
587
  }
594
- return writeSource(node, value);
595
- }
596
- function writeSource(node, value) {
597
- if (node.comparator && node.comparator(node.value, value)) return value;
598
588
  if (Pending) {
599
589
  if (node.pending === NOTPENDING) Pending.push(node);
600
590
  node.pending = value;
601
591
  return value;
602
592
  }
603
- node.value = value;
593
+ let TransitionRunning = false;
594
+ if (Transition) {
595
+ 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;
604
602
  if (node.observers && node.observers.length) {
605
603
  runUpdates(() => {
606
- for (let i = 0; i < node.observers.length; i++) {
604
+ for (let i = 0; i < node.observers.length; i += 1) {
607
605
  const o = node.observers[i];
606
+ if (TransitionRunning && Transition.disposed.has(o)) continue;
608
607
  if (o.pure) Updates.push(o);else Effects.push(o);
609
- if (o.observers && !o.state) markUpstream(o);
610
- o.state = STALE;
608
+ if (o.observers && (TransitionRunning && !o.tState || !TransitionRunning && !o.state)) markUpstream(o);
609
+ if (TransitionRunning) o.tState = STALE;else o.state = STALE;
611
610
  }
612
611
  if (Updates.length > 10e5) {
613
612
  Updates = [];
@@ -620,21 +619,20 @@ function writeSource(node, value) {
620
619
  }
621
620
  function updateComputation(node) {
622
621
  if (!node.fn) return;
623
- if (Transition && Transition.sources.has(node)) {
624
- Transition.updated.add(node);
625
- if (!Transition.running) {
626
- return queueMicrotask(() => runUpdates(() => {
627
- Transition.running = true;
628
- updateComputation(node);
629
- }, false));
630
- }
631
- }
632
622
  cleanNode(node);
633
623
  const owner = Owner,
634
624
  listener = Listener,
635
625
  time = ExecCount;
636
626
  Listener = Owner = node;
637
627
  runComputation(node, node.value, time);
628
+ if (Transition && !Transition.running && Transition.sources.has(node)) {
629
+ queueMicrotask(() => {
630
+ runUpdates(() => {
631
+ Transition && (Transition.running = true);
632
+ runComputation(node, node.tValue, time);
633
+ }, false);
634
+ });
635
+ }
638
636
  Listener = listener;
639
637
  Owner = owner;
640
638
  }
@@ -647,7 +645,10 @@ function runComputation(node, value, time) {
647
645
  }
648
646
  if (!node.updatedAt || node.updatedAt <= time) {
649
647
  if (node.observers && node.observers.length) {
650
- writeSource(node, nextValue);
648
+ writeSignal(node, nextValue, true);
649
+ } else if (Transition && Transition.running && node.pure) {
650
+ Transition.sources.add(node);
651
+ node.tValue = nextValue;
651
652
  } else node.value = nextValue;
652
653
  node.updatedAt = time;
653
654
  }
@@ -656,7 +657,7 @@ function createComputation(fn, init, pure, state = STALE, options) {
656
657
  const c = {
657
658
  fn,
658
659
  state: state,
659
- updatedAt: 0,
660
+ updatedAt: null,
660
661
  owned: null,
661
662
  sources: null,
662
663
  sourceSlots: null,
@@ -666,25 +667,42 @@ function createComputation(fn, init, pure, state = STALE, options) {
666
667
  context: null,
667
668
  pure
668
669
  };
670
+ if (Transition && Transition.running) {
671
+ c.state = 0;
672
+ c.tState = state;
673
+ }
669
674
  if (Owner === null) console.warn("computations created outside a `createRoot` or `render` will never be disposed");else if (Owner !== UNOWNED) {
670
- if (!Owner.owned) Owner.owned = [c];else Owner.owned.push(c);
671
- c.name = options && options.name || `${Owner.name || "c"}-${Owner.owned.length}`;
675
+ if (Transition && Transition.running && Owner.pure) {
676
+ if (!Owner.tOwned) Owner.tOwned = [c];else Owner.tOwned.push(c);
677
+ } else {
678
+ if (!Owner.owned) Owner.owned = [c];else Owner.owned.push(c);
679
+ }
680
+ c.name = options && options.name || `${Owner.name || "c"}-${(Owner.owned || Owner.tOwned).length}`;
672
681
  }
673
- if (Transition && Transition.running) Transition.sources.add(c);
674
682
  return c;
675
683
  }
676
684
  function runTop(node) {
677
- if (node.state !== STALE) return node.state = 0;
685
+ const runningTransition = Transition && Transition.running;
686
+ if (!runningTransition && node.state !== STALE) return node.state = 0;
687
+ if (runningTransition && node.tState !== STALE) return node.tState = 0;
678
688
  if (node.suspense && untrack(node.suspense.inFallback)) return node.suspense.effects.push(node);
679
689
  const ancestors = [node];
680
690
  while ((node = node.owner) && (!node.updatedAt || node.updatedAt < ExecCount)) {
681
- if (node.state) ancestors.push(node);
691
+ if (runningTransition && Transition.disposed.has(node)) return;
692
+ if (node.state || runningTransition && node.tState) ancestors.push(node);
682
693
  }
683
694
  for (let i = ancestors.length - 1; i >= 0; i--) {
684
695
  node = ancestors[i];
685
- if (node.state === STALE) {
696
+ if (runningTransition) {
697
+ let top = node,
698
+ prev = ancestors[i + 1];
699
+ while ((top = top.owner) && top !== prev) {
700
+ if (Transition.disposed.has(top)) return;
701
+ }
702
+ }
703
+ if (node.state === STALE || runningTransition && node.tState === STALE) {
686
704
  updateComputation(node);
687
- } else if (node.state === PENDING) {
705
+ } else if (node.state === PENDING || runningTransition && node.tState === PENDING) {
688
706
  const updates = Updates;
689
707
  Updates = null;
690
708
  lookDownstream(node);
@@ -721,11 +739,24 @@ function completeUpdates(wait) {
721
739
  setTransPending(true);
722
740
  return;
723
741
  }
724
- const t = Transition;
742
+ const sources = Transition.sources;
725
743
  cbs = Transition.cb;
744
+ Effects.forEach(e => {
745
+ "tState" in e && (e.state = e.tState);
746
+ delete e.tState;
747
+ });
726
748
  Transition = null;
727
749
  batch(() => {
728
- mergeTransition(t);
750
+ sources.forEach(v => {
751
+ v.value = v.tValue;
752
+ if (v.owned) {
753
+ for (let i = 0, len = v.owned.length; i < len; i++) cleanNode(v.owned[i]);
754
+ }
755
+ if (v.tOwned) v.owned = v.tOwned;
756
+ delete v.tValue;
757
+ delete v.tOwned;
758
+ v.tState = 0;
759
+ });
729
760
  setTransPending(false);
730
761
  });
731
762
  }
@@ -775,75 +806,24 @@ function runUserEffects(queue) {
775
806
  }
776
807
  function lookDownstream(node) {
777
808
  node.state = 0;
778
- for (let i = 0; i < node.sources.length; i++) {
809
+ for (let i = 0; i < node.sources.length; i += 1) {
779
810
  const source = node.sources[i];
780
811
  if (source.sources) {
781
- if (source.state === STALE) runTop(source);else if (source.state === PENDING) lookDownstream(source);
812
+ if (source.state === STALE || Transition && Transition.running && source.tState) runTop(source);else if (source.state === PENDING) lookDownstream(source);
782
813
  }
783
814
  }
784
815
  }
785
816
  function markUpstream(node) {
786
- for (let i = 0; i < node.observers.length; i++) {
817
+ const runningTransition = Transition && Transition.running;
818
+ for (let i = 0; i < node.observers.length; i += 1) {
787
819
  const o = node.observers[i];
788
- if (!o.state) {
789
- o.state = PENDING;
820
+ if (!o.state || runningTransition && !o.tState) {
821
+ if (runningTransition) o.tState = PENDING;else o.state = PENDING;
790
822
  if (o.pure) Updates.push(o);else Effects.push(o);
791
823
  o.observers && markUpstream(o);
792
824
  }
793
825
  }
794
826
  }
795
- function forkSource(s, p, slot) {
796
- let fork;
797
- if (!(fork = Transition.lookup.get(s) || Transition.sources.has(s) && s)) {
798
- Transition.lookup.set(s, fork = { ...s
799
- });
800
- Transition.sources.add(fork);
801
- if (fork.observers) {
802
- fork.observers = [...new Set(fork.observers)];
803
- fork.observerSlots = [];
804
- fork.observers.forEach((o, i) => forkSource(o, fork, i));
805
- }
806
- if (fork.sources) {
807
- fork.sources = [p];
808
- fork.sourceSlots = [slot];
809
- replaceObservers(fork, p, slot, 0);
810
- }
811
- fork.owned && (fork.owned = null);
812
- fork.cleanups && (fork.cleanups = null);
813
- } else if ("sources" in fork) {
814
- fork.sources.push(p);
815
- fork.sourceSlots.push(slot);
816
- replaceObservers(fork, p, slot, fork.sources.length - 1);
817
- }
818
- return fork;
819
- }
820
- function replaceObservers(node, source, slot, sourceSlot) {
821
- source.observers || (source.observers = []);
822
- source.observerSlots || (source.observerSlots = []);
823
- source.observers[slot] = node;
824
- source.observerSlots[slot] = sourceSlot;
825
- }
826
- function mergeTransition(transition) {
827
- const reverse = new Map(Array.from(transition.lookup, entry => [entry[1], entry[0]]));
828
- transition.lookup.forEach((fork, og) => {
829
- if ("sources" in fork && (fork.state || transition.updated.has(fork))) cleanNode(og);
830
- });
831
- transition.lookup.forEach((fork, og) => {
832
- if ("sources" in fork && !fork.state && !transition.updated.has(fork)) return;
833
- transition.updated.delete(fork);
834
- Object.assign(og, fork);
835
- if (og.sources) {
836
- og.sourceSlots.forEach((slot, i) => {
837
- og.sources[i] = reverse.get(og.sources[i]) || og.sources[i];
838
- replaceObservers(og, og.sources[i], slot, i);
839
- });
840
- }
841
- });
842
- Effects.forEach((e, i) => {
843
- const replace = reverse.get(e);
844
- if (replace) Effects[i] = replace;
845
- });
846
- }
847
827
  function cleanNode(node) {
848
828
  let i;
849
829
  if (node.sources) {
@@ -862,7 +842,13 @@ function cleanNode(node) {
862
842
  }
863
843
  }
864
844
  }
865
- if (node.owned) {
845
+ if (Transition && Transition.running && node.pure) {
846
+ if (node.tOwned) {
847
+ for (i = 0; i < node.tOwned.length; i++) cleanNode(node.tOwned[i]);
848
+ delete node.tOwned;
849
+ }
850
+ reset(node, true);
851
+ } else if (node.owned) {
866
852
  for (i = 0; i < node.owned.length; i++) cleanNode(node.owned[i]);
867
853
  node.owned = null;
868
854
  }
@@ -870,9 +856,18 @@ function cleanNode(node) {
870
856
  for (i = 0; i < node.cleanups.length; i++) node.cleanups[i]();
871
857
  node.cleanups = null;
872
858
  }
873
- node.state = 0;
859
+ if (Transition && Transition.running) node.tState = 0;else node.state = 0;
874
860
  node.context = null;
875
861
  }
862
+ function reset(node, top) {
863
+ if (!top) {
864
+ node.tState = 0;
865
+ Transition.disposed.add(node);
866
+ }
867
+ if (node.owned) {
868
+ for (let i = 0; i < node.owned.length; i++) reset(node.owned[i]);
869
+ }
870
+ }
876
871
  function handleError(err) {
877
872
  const fns = ERROR && lookup(Owner, ERROR);
878
873
  if (!fns) throw err;
@@ -1176,23 +1171,26 @@ const propTraps = {
1176
1171
  return _.keys();
1177
1172
  }
1178
1173
  };
1174
+ function resolveSource(s) {
1175
+ return typeof s === "function" ? s() : s;
1176
+ }
1179
1177
  function mergeProps(...sources) {
1180
1178
  return new Proxy({
1181
1179
  get(property) {
1182
1180
  for (let i = sources.length - 1; i >= 0; i--) {
1183
- const v = sources[i][property];
1181
+ const v = resolveSource(sources[i])[property];
1184
1182
  if (v !== undefined) return v;
1185
1183
  }
1186
1184
  },
1187
1185
  has(property) {
1188
1186
  for (let i = sources.length - 1; i >= 0; i--) {
1189
- if (property in sources[i]) return true;
1187
+ if (property in resolveSource(sources[i])) return true;
1190
1188
  }
1191
1189
  return false;
1192
1190
  },
1193
1191
  keys() {
1194
1192
  const keys = [];
1195
- for (let i = 0; i < sources.length; i++) keys.push(...Object.keys(sources[i]));
1193
+ for (let i = 0; i < sources.length; i++) keys.push(...Object.keys(resolveSource(sources[i])));
1196
1194
  return [...new Set(keys)];
1197
1195
  }
1198
1196
  }, propTraps);