solid-js 1.1.2 → 1.1.6-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/dev.cjs CHANGED
@@ -145,7 +145,6 @@ const UNOWNED = {
145
145
  context: null,
146
146
  owner: null
147
147
  };
148
- const [transPending, setTransPending] = /*@__PURE__*/createSignal(false);
149
148
  var Owner = null;
150
149
  let Transition = null;
151
150
  let Scheduler = null;
@@ -155,6 +154,7 @@ let Updates = null;
155
154
  let Effects = null;
156
155
  let ExecCount = 0;
157
156
  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,12 +186,24 @@ 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);
189
190
  if (!options.internal) s.name = registerGraph(options.name || hashValue(value), s);
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);
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
+ }
193
205
  }
194
- return writeSignal(s, value);
206
+ return writeSignal(sig, value);
195
207
  }];
196
208
  }
197
209
  function createComputed(fn, value, options) {
@@ -216,9 +228,20 @@ function createMemo(fn, value, options) {
216
228
  c.observerSlots = null;
217
229
  c.comparator = options.equals || undefined;
218
230
  updateComputation(c);
219
- return readSignal.bind(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
+ };
220
243
  }
221
- function createResource(source, fetcher, options = {}) {
244
+ function createResource(source, fetcher, options) {
222
245
  if (arguments.length === 2) {
223
246
  if (typeof fetcher === "object") {
224
247
  options = fetcher;
@@ -230,7 +253,7 @@ function createResource(source, fetcher, options = {}) {
230
253
  source = true;
231
254
  }
232
255
  const contexts = new Set(),
233
- [s, set] = createSignal(options.initialValue),
256
+ [s, set] = createSignal(options?.initialValue),
234
257
  [track, trigger] = createSignal(undefined, {
235
258
  equals: false
236
259
  }),
@@ -351,8 +374,9 @@ function createDeferred(source, options) {
351
374
  }
352
375
  function createSelector(source, fn = equalFn, options) {
353
376
  const subs = new Map();
377
+ let current;
354
378
  const node = createComputation(p => {
355
- const v = source();
379
+ const v = current = source();
356
380
  for (const key of subs.keys()) if (fn(key, v) || p !== undefined && fn(key, p)) {
357
381
  const l = subs.get(key);
358
382
  for (const c of l.values()) {
@@ -368,11 +392,9 @@ function createSelector(source, fn = equalFn, options) {
368
392
  if (listener = Listener) {
369
393
  let l;
370
394
  if (l = subs.get(key)) l.add(listener);else subs.set(key, l = new Set([listener]));
371
- onCleanup(() => {
372
- l.size > 1 ? l.delete(listener) : subs.delete(key);
373
- });
395
+ onCleanup(() => l.size > 1 ? l.delete(listener) : subs.delete(key));
374
396
  }
375
- return fn(key, Transition && Transition.running && Transition.sources.has(node) ? node.tValue : node.value);
397
+ return fn(key, current);
376
398
  };
377
399
  }
378
400
  function batch(fn) {
@@ -385,12 +407,12 @@ function batch(fn) {
385
407
  Pending = null;
386
408
  }
387
409
  runUpdates(() => {
388
- for (let i = 0; i < q.length; i += 1) {
410
+ for (let i = 0; i < q.length; i++) {
389
411
  const data = q[i];
390
412
  if (data.pending !== NOTPENDING) {
391
413
  const pending = data.pending;
392
414
  data.pending = NOTPENDING;
393
- writeSignal(data, pending);
415
+ writeSource(data, pending);
394
416
  }
395
417
  }
396
418
  }, false);
@@ -455,27 +477,29 @@ function enableScheduling(scheduler = requestCallback) {
455
477
  Scheduler = scheduler;
456
478
  }
457
479
  function startTransition(fn, cb) {
458
- if (Scheduler || SuspenseContext) {
459
- Transition || (Transition = {
460
- sources: new Set(),
461
- effects: [],
462
- promises: new Set(),
463
- disposed: new Set(),
464
- queue: new Set(),
465
- running: true,
466
- cb: []
467
- });
468
- cb && Transition.cb.push(cb);
469
- Transition.running = true;
470
- }
471
- batch(fn);
472
- if (!Scheduler && !SuspenseContext && cb) cb();
480
+ queueMicrotask(() => {
481
+ if (Scheduler || SuspenseContext) {
482
+ Transition || (Transition = {
483
+ sources: new Set(),
484
+ lookup: new Map(),
485
+ updated: new Set(),
486
+ effects: [],
487
+ promises: new Set(),
488
+ queue: new Set(),
489
+ running: true,
490
+ cb: []
491
+ });
492
+ cb && Transition.cb.push(cb);
493
+ Transition.running = true;
494
+ }
495
+ batch(fn);
496
+ if (!Scheduler && !SuspenseContext && cb) cb();
497
+ });
473
498
  }
474
499
  function useTransition() {
475
500
  return [transPending, startTransition];
476
501
  }
477
502
  function resumeEffects(e) {
478
- Transition && (Transition.running = true);
479
503
  Effects.push.apply(Effects, e);
480
504
  e.length = 0;
481
505
  }
@@ -487,7 +511,7 @@ function devComponent(Comp, props) {
487
511
  c.state = 0;
488
512
  c.componentName = Comp.name;
489
513
  updateComputation(c);
490
- return c.tValue !== undefined ? c.tValue : c.value;
514
+ return c.value;
491
515
  }
492
516
  function hashValue(v) {
493
517
  const s = new Set();
@@ -495,6 +519,14 @@ function hashValue(v) {
495
519
  if (typeof v === "object" && v != null) {
496
520
  if (s.has(v)) return;
497
521
  s.add(v);
522
+ const keys = Object.keys(v);
523
+ const desc = Object.getOwnPropertyDescriptors(v);
524
+ const newDesc = keys.reduce((memo, key) => {
525
+ const value = desc[key];
526
+ if (!value.get) memo[key] = value;
527
+ return memo;
528
+ }, {});
529
+ v = Object.create({}, newDesc);
498
530
  }
499
531
  if (typeof v === "bigint") {
500
532
  return `${v.toString()}n`;
@@ -538,61 +570,44 @@ let SuspenseContext;
538
570
  function getSuspenseContext() {
539
571
  return SuspenseContext || (SuspenseContext = createContext({}));
540
572
  }
541
- function readSignal() {
542
- if (this.state && this.sources) {
543
- const updates = Updates;
544
- Updates = null;
545
- this.state === STALE || Transition && Transition.running && this.tState ? updateComputation(this) : lookDownstream(this);
546
- Updates = updates;
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);
547
581
  }
548
- if (Listener) {
549
- const sSlot = this.observers ? this.observers.length : 0;
550
- if (!Listener.sources) {
551
- Listener.sources = [this];
552
- Listener.sourceSlots = [sSlot];
553
- } else {
554
- Listener.sources.push(this);
555
- Listener.sourceSlots.push(sSlot);
556
- }
557
- if (!this.observers) {
558
- this.observers = [Listener];
559
- this.observerSlots = [Listener.sources.length - 1];
560
- } else {
561
- this.observers.push(Listener);
562
- this.observerSlots.push(Listener.sources.length - 1);
563
- }
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);
564
588
  }
565
- if (Transition && Transition.running && Transition.sources.has(this)) return this.tValue;
566
- return this.value;
567
- }
568
- function writeSignal(node, value, isComp) {
569
- if (node.comparator) {
570
- if (Transition && Transition.running && Transition.sources.has(node)) {
571
- if (node.comparator(node.tValue, value)) return value;
572
- } else if (node.comparator(node.value, value)) return value;
589
+ }
590
+ function writeSignal(node, value) {
591
+ if (typeof value === "function") {
592
+ value = value(node.pending !== NOTPENDING ? node.pending : node.value);
573
593
  }
594
+ return writeSource(node, value);
595
+ }
596
+ function writeSource(node, value) {
597
+ if (node.comparator && node.comparator(node.value, value)) return value;
574
598
  if (Pending) {
575
599
  if (node.pending === NOTPENDING) Pending.push(node);
576
600
  node.pending = value;
577
601
  return value;
578
602
  }
579
- let TransitionRunning = false;
580
- if (Transition) {
581
- TransitionRunning = Transition.running;
582
- if (TransitionRunning || !isComp && Transition.sources.has(node)) {
583
- Transition.sources.add(node);
584
- node.tValue = value;
585
- }
586
- if (!TransitionRunning) node.value = value;
587
- } else node.value = value;
603
+ node.value = value;
588
604
  if (node.observers && node.observers.length) {
589
605
  runUpdates(() => {
590
- for (let i = 0; i < node.observers.length; i += 1) {
606
+ for (let i = 0; i < node.observers.length; i++) {
591
607
  const o = node.observers[i];
592
- if (TransitionRunning && Transition.disposed.has(o)) continue;
593
608
  if (o.pure) Updates.push(o);else Effects.push(o);
594
- if (o.observers && (TransitionRunning && !o.tState || !TransitionRunning && !o.state)) markUpstream(o);
595
- if (TransitionRunning) o.tState = STALE;else o.state = STALE;
609
+ if (o.observers && !o.state) markUpstream(o);
610
+ o.state = STALE;
596
611
  }
597
612
  if (Updates.length > 10e5) {
598
613
  Updates = [];
@@ -605,17 +620,21 @@ function writeSignal(node, value, isComp) {
605
620
  }
606
621
  function updateComputation(node) {
607
622
  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
+ }
608
632
  cleanNode(node);
609
633
  const owner = Owner,
610
634
  listener = Listener,
611
635
  time = ExecCount;
612
636
  Listener = Owner = node;
613
637
  runComputation(node, node.value, time);
614
- if (Transition && !Transition.running && Transition.sources.has(node)) {
615
- Transition.running = true;
616
- runComputation(node, node.tValue, time);
617
- Transition.running = false;
618
- }
619
638
  Listener = listener;
620
639
  Owner = owner;
621
640
  }
@@ -628,10 +647,7 @@ function runComputation(node, value, time) {
628
647
  }
629
648
  if (!node.updatedAt || node.updatedAt <= time) {
630
649
  if (node.observers && node.observers.length) {
631
- writeSignal(node, nextValue, true);
632
- } else if (Transition && Transition.running && node.pure) {
633
- Transition.sources.add(node);
634
- node.tValue = nextValue;
650
+ writeSource(node, nextValue);
635
651
  } else node.value = nextValue;
636
652
  node.updatedAt = time;
637
653
  }
@@ -640,7 +656,7 @@ function createComputation(fn, init, pure, state = STALE, options) {
640
656
  const c = {
641
657
  fn,
642
658
  state: state,
643
- updatedAt: null,
659
+ updatedAt: 0,
644
660
  owned: null,
645
661
  sources: null,
646
662
  sourceSlots: null,
@@ -650,42 +666,25 @@ function createComputation(fn, init, pure, state = STALE, options) {
650
666
  context: null,
651
667
  pure
652
668
  };
653
- if (Transition && Transition.running) {
654
- c.state = 0;
655
- c.tState = state;
656
- }
657
669
  if (Owner === null) console.warn("computations created outside a `createRoot` or `render` will never be disposed");else if (Owner !== UNOWNED) {
658
- if (Transition && Transition.running && Owner.pure) {
659
- if (!Owner.tOwned) Owner.tOwned = [c];else Owner.tOwned.push(c);
660
- } else {
661
- if (!Owner.owned) Owner.owned = [c];else Owner.owned.push(c);
662
- }
663
- c.name = options && options.name || `${Owner.name || "c"}-${(Owner.owned || Owner.tOwned).length}`;
670
+ if (!Owner.owned) Owner.owned = [c];else Owner.owned.push(c);
671
+ c.name = options && options.name || `${Owner.name || "c"}-${Owner.owned.length}`;
664
672
  }
673
+ if (Transition && Transition.running) Transition.sources.add(c);
665
674
  return c;
666
675
  }
667
676
  function runTop(node) {
668
- const runningTransition = Transition && Transition.running;
669
- if (!runningTransition && node.state !== STALE) return node.state = 0;
670
- if (runningTransition && node.tState !== STALE) return node.tState = 0;
677
+ if (node.state !== STALE) return node.state = 0;
671
678
  if (node.suspense && untrack(node.suspense.inFallback)) return node.suspense.effects.push(node);
672
679
  const ancestors = [node];
673
680
  while ((node = node.owner) && (!node.updatedAt || node.updatedAt < ExecCount)) {
674
- if (runningTransition && Transition.disposed.has(node)) return;
675
- if (node.state || runningTransition && node.tState) ancestors.push(node);
681
+ if (node.state) ancestors.push(node);
676
682
  }
677
683
  for (let i = ancestors.length - 1; i >= 0; i--) {
678
684
  node = ancestors[i];
679
- if (runningTransition) {
680
- let top = node,
681
- prev = ancestors[i + 1];
682
- while ((top = top.owner) && top !== prev) {
683
- if (Transition.disposed.has(top)) return;
684
- }
685
- }
686
- if (node.state === STALE || runningTransition && node.tState === STALE) {
685
+ if (node.state === STALE) {
687
686
  updateComputation(node);
688
- } else if (node.state === PENDING || runningTransition && node.tState === PENDING) {
687
+ } else if (node.state === PENDING) {
689
688
  const updates = Updates;
690
689
  Updates = null;
691
690
  lookDownstream(node);
@@ -722,24 +721,11 @@ function completeUpdates(wait) {
722
721
  setTransPending(true);
723
722
  return;
724
723
  }
725
- const sources = Transition.sources;
724
+ const t = Transition;
726
725
  cbs = Transition.cb;
727
- Effects.forEach(e => {
728
- e.state = STALE;
729
- delete e.tState;
730
- });
731
726
  Transition = null;
732
727
  batch(() => {
733
- sources.forEach(v => {
734
- v.value = v.tValue;
735
- if (v.owned) {
736
- for (let i = 0, len = v.owned.length; i < len; i++) cleanNode(v.owned[i]);
737
- }
738
- if (v.tOwned) v.owned = v.tOwned;
739
- delete v.tValue;
740
- delete v.tOwned;
741
- v.tState = 0;
742
- });
728
+ mergeTransition(t);
743
729
  setTransPending(false);
744
730
  });
745
731
  }
@@ -789,24 +775,75 @@ function runUserEffects(queue) {
789
775
  }
790
776
  function lookDownstream(node) {
791
777
  node.state = 0;
792
- for (let i = 0; i < node.sources.length; i += 1) {
778
+ for (let i = 0; i < node.sources.length; i++) {
793
779
  const source = node.sources[i];
794
780
  if (source.sources) {
795
- if (source.state === STALE || Transition && Transition.running && source.tState) runTop(source);else if (source.state === PENDING) lookDownstream(source);
781
+ if (source.state === STALE) runTop(source);else if (source.state === PENDING) lookDownstream(source);
796
782
  }
797
783
  }
798
784
  }
799
785
  function markUpstream(node) {
800
- const runningTransition = Transition && Transition.running;
801
- for (let i = 0; i < node.observers.length; i += 1) {
786
+ for (let i = 0; i < node.observers.length; i++) {
802
787
  const o = node.observers[i];
803
- if (!o.state || runningTransition && !o.tState) {
804
- if (runningTransition) o.tState = PENDING;else o.state = PENDING;
788
+ if (!o.state) {
789
+ o.state = PENDING;
805
790
  if (o.pure) Updates.push(o);else Effects.push(o);
806
791
  o.observers && markUpstream(o);
807
792
  }
808
793
  }
809
794
  }
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
+ }
810
847
  function cleanNode(node) {
811
848
  let i;
812
849
  if (node.sources) {
@@ -825,13 +862,7 @@ function cleanNode(node) {
825
862
  }
826
863
  }
827
864
  }
828
- if (Transition && Transition.running && node.pure) {
829
- if (node.tOwned) {
830
- for (i = 0; i < node.tOwned.length; i++) cleanNode(node.tOwned[i]);
831
- delete node.tOwned;
832
- }
833
- reset(node, true);
834
- } else if (node.owned) {
865
+ if (node.owned) {
835
866
  for (i = 0; i < node.owned.length; i++) cleanNode(node.owned[i]);
836
867
  node.owned = null;
837
868
  }
@@ -839,18 +870,9 @@ function cleanNode(node) {
839
870
  for (i = 0; i < node.cleanups.length; i++) node.cleanups[i]();
840
871
  node.cleanups = null;
841
872
  }
842
- if (Transition && Transition.running) node.tState = 0;else node.state = 0;
873
+ node.state = 0;
843
874
  node.context = null;
844
875
  }
845
- function reset(node, top) {
846
- if (!top) {
847
- node.tState = 0;
848
- Transition.disposed.add(node);
849
- }
850
- if (node.owned) {
851
- for (let i = 0; i < node.owned.length; i++) reset(node.owned[i]);
852
- }
853
- }
854
876
  function handleError(err) {
855
877
  const fns = ERROR && lookup(Owner, ERROR);
856
878
  if (!fns) throw err;