@fictjs/runtime 0.0.10 → 0.0.12
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/index.cjs +315 -50
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +4 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.dev.js +330 -48
- package/dist/index.dev.js.map +1 -1
- package/dist/index.js +315 -50
- package/dist/index.js.map +1 -1
- package/dist/slim.cjs +293 -40
- package/dist/slim.cjs.map +1 -1
- package/dist/slim.js +293 -40
- package/dist/slim.js.map +1 -1
- package/package.json +1 -1
- package/src/binding.ts +3 -1
- package/src/dev.d.ts +5 -0
- package/src/dom.ts +20 -2
- package/src/effect.ts +16 -5
- package/src/error-boundary.ts +11 -2
- package/src/lifecycle.ts +4 -1
- package/src/list-helpers.ts +243 -22
- package/src/props.ts +2 -4
- package/src/reconcile.ts +4 -0
- package/src/signal.ts +154 -25
- package/src/suspense.ts +24 -7
- package/src/transition.ts +4 -1
package/dist/index.js
CHANGED
|
@@ -300,7 +300,7 @@ function handleError(err, info, startRoot) {
|
|
|
300
300
|
}
|
|
301
301
|
}
|
|
302
302
|
}
|
|
303
|
-
|
|
303
|
+
return false;
|
|
304
304
|
}
|
|
305
305
|
function handleSuspend(token, startRoot) {
|
|
306
306
|
let root = startRoot ?? currentRoot;
|
|
@@ -346,6 +346,11 @@ var isInTransition = false;
|
|
|
346
346
|
var enqueueMicrotask = typeof queueMicrotask === "function" ? queueMicrotask : (fn) => {
|
|
347
347
|
Promise.resolve().then(fn);
|
|
348
348
|
};
|
|
349
|
+
var inCleanup = false;
|
|
350
|
+
var SIGNAL_MARKER = Symbol.for("fict:signal");
|
|
351
|
+
var COMPUTED_MARKER = Symbol.for("fict:computed");
|
|
352
|
+
var EFFECT_MARKER = Symbol.for("fict:effect");
|
|
353
|
+
var EFFECT_SCOPE_MARKER = Symbol.for("fict:effectScope");
|
|
349
354
|
function link(dep, sub, version) {
|
|
350
355
|
const prevDep = sub.depsTail;
|
|
351
356
|
if (prevDep !== void 0 && prevDep.dep === dep) return;
|
|
@@ -469,13 +474,21 @@ function checkDirty(firstLink, sub) {
|
|
|
469
474
|
dirty = true;
|
|
470
475
|
}
|
|
471
476
|
} else if ((depFlags & MutablePending) === MutablePending) {
|
|
472
|
-
if (
|
|
473
|
-
|
|
477
|
+
if (!dep.deps) {
|
|
478
|
+
const nextDep = link2.nextDep;
|
|
479
|
+
if (nextDep !== void 0) {
|
|
480
|
+
link2 = nextDep;
|
|
481
|
+
continue;
|
|
482
|
+
}
|
|
483
|
+
} else {
|
|
484
|
+
if (link2.nextSub !== void 0 || link2.prevSub !== void 0) {
|
|
485
|
+
stack = { value: link2, prev: stack };
|
|
486
|
+
}
|
|
487
|
+
link2 = dep.deps;
|
|
488
|
+
sub = dep;
|
|
489
|
+
++checkDepth;
|
|
490
|
+
continue;
|
|
474
491
|
}
|
|
475
|
-
link2 = dep.deps;
|
|
476
|
-
sub = dep;
|
|
477
|
-
++checkDepth;
|
|
478
|
-
continue;
|
|
479
492
|
}
|
|
480
493
|
if (!dirty) {
|
|
481
494
|
const nextDep = link2.nextDep;
|
|
@@ -553,8 +566,12 @@ function disposeNode(node) {
|
|
|
553
566
|
node.depsTail = void 0;
|
|
554
567
|
node.flags = 0;
|
|
555
568
|
purgeDeps(node);
|
|
556
|
-
|
|
557
|
-
|
|
569
|
+
let sub = node.subs;
|
|
570
|
+
while (sub !== void 0) {
|
|
571
|
+
const next = sub.nextSub;
|
|
572
|
+
unlink(sub);
|
|
573
|
+
sub = next;
|
|
574
|
+
}
|
|
558
575
|
}
|
|
559
576
|
function updateSignal(s) {
|
|
560
577
|
s.flags = Mutable;
|
|
@@ -591,7 +608,15 @@ function updateComputed(c) {
|
|
|
591
608
|
}
|
|
592
609
|
function runEffect(e) {
|
|
593
610
|
const flags = e.flags;
|
|
594
|
-
if (flags & Dirty
|
|
611
|
+
if (flags & Dirty) {
|
|
612
|
+
if (e.runCleanup) {
|
|
613
|
+
inCleanup = true;
|
|
614
|
+
try {
|
|
615
|
+
e.runCleanup();
|
|
616
|
+
} finally {
|
|
617
|
+
inCleanup = false;
|
|
618
|
+
}
|
|
619
|
+
}
|
|
595
620
|
++cycle;
|
|
596
621
|
effectRunDevtools(e);
|
|
597
622
|
e.depsTail = void 0;
|
|
@@ -608,6 +633,35 @@ function runEffect(e) {
|
|
|
608
633
|
e.flags = Watching;
|
|
609
634
|
throw err;
|
|
610
635
|
}
|
|
636
|
+
} else if (flags & Pending && e.deps) {
|
|
637
|
+
if (e.runCleanup) {
|
|
638
|
+
inCleanup = true;
|
|
639
|
+
try {
|
|
640
|
+
e.runCleanup();
|
|
641
|
+
} finally {
|
|
642
|
+
inCleanup = false;
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
if (checkDirty(e.deps, e)) {
|
|
646
|
+
++cycle;
|
|
647
|
+
effectRunDevtools(e);
|
|
648
|
+
e.depsTail = void 0;
|
|
649
|
+
e.flags = WatchingRunning;
|
|
650
|
+
const prevSub = activeSub;
|
|
651
|
+
activeSub = e;
|
|
652
|
+
try {
|
|
653
|
+
e.fn();
|
|
654
|
+
activeSub = prevSub;
|
|
655
|
+
e.flags = Watching;
|
|
656
|
+
purgeDeps(e);
|
|
657
|
+
} catch (err) {
|
|
658
|
+
activeSub = prevSub;
|
|
659
|
+
e.flags = Watching;
|
|
660
|
+
throw err;
|
|
661
|
+
}
|
|
662
|
+
} else {
|
|
663
|
+
e.flags = Watching;
|
|
664
|
+
}
|
|
611
665
|
} else {
|
|
612
666
|
e.flags = Watching;
|
|
613
667
|
}
|
|
@@ -686,7 +740,9 @@ function signal(initialValue) {
|
|
|
686
740
|
__id: void 0
|
|
687
741
|
};
|
|
688
742
|
registerSignalDevtools(initialValue, s);
|
|
689
|
-
|
|
743
|
+
const accessor = signalOper.bind(s);
|
|
744
|
+
accessor[SIGNAL_MARKER] = true;
|
|
745
|
+
return accessor;
|
|
690
746
|
}
|
|
691
747
|
function signalOper(value) {
|
|
692
748
|
if (arguments.length > 0) {
|
|
@@ -703,7 +759,7 @@ function signalOper(value) {
|
|
|
703
759
|
return;
|
|
704
760
|
}
|
|
705
761
|
const flags = this.flags;
|
|
706
|
-
if (flags & Dirty) {
|
|
762
|
+
if (flags & Dirty && !inCleanup) {
|
|
707
763
|
if (updateSignal(this)) {
|
|
708
764
|
const subs = this.subs;
|
|
709
765
|
if (subs !== void 0) shallowPropagate(subs);
|
|
@@ -731,6 +787,7 @@ function computed(getter) {
|
|
|
731
787
|
getter
|
|
732
788
|
};
|
|
733
789
|
const bound = computedOper.bind(c);
|
|
790
|
+
bound[COMPUTED_MARKER] = true;
|
|
734
791
|
return bound;
|
|
735
792
|
}
|
|
736
793
|
function computedOper() {
|
|
@@ -783,7 +840,35 @@ function effect(fn) {
|
|
|
783
840
|
activeSub = prevSub;
|
|
784
841
|
e.flags &= ~Running;
|
|
785
842
|
}
|
|
786
|
-
|
|
843
|
+
const disposer = effectOper.bind(e);
|
|
844
|
+
disposer[EFFECT_MARKER] = true;
|
|
845
|
+
return disposer;
|
|
846
|
+
}
|
|
847
|
+
function effectWithCleanup(fn, cleanupRunner) {
|
|
848
|
+
const e = {
|
|
849
|
+
fn,
|
|
850
|
+
subs: void 0,
|
|
851
|
+
subsTail: void 0,
|
|
852
|
+
deps: void 0,
|
|
853
|
+
depsTail: void 0,
|
|
854
|
+
flags: WatchingRunning,
|
|
855
|
+
runCleanup: cleanupRunner,
|
|
856
|
+
__id: void 0
|
|
857
|
+
};
|
|
858
|
+
registerEffectDevtools(e);
|
|
859
|
+
const prevSub = activeSub;
|
|
860
|
+
if (prevSub !== void 0) link(e, prevSub, 0);
|
|
861
|
+
activeSub = e;
|
|
862
|
+
try {
|
|
863
|
+
effectRunDevtools(e);
|
|
864
|
+
fn();
|
|
865
|
+
} finally {
|
|
866
|
+
activeSub = prevSub;
|
|
867
|
+
e.flags &= ~Running;
|
|
868
|
+
}
|
|
869
|
+
const disposer = effectOper.bind(e);
|
|
870
|
+
disposer[EFFECT_MARKER] = true;
|
|
871
|
+
return disposer;
|
|
787
872
|
}
|
|
788
873
|
function effectOper() {
|
|
789
874
|
disposeNode(this);
|
|
@@ -798,7 +883,9 @@ function effectScope(fn) {
|
|
|
798
883
|
} finally {
|
|
799
884
|
activeSub = prevSub;
|
|
800
885
|
}
|
|
801
|
-
|
|
886
|
+
const disposer = effectScopeOper.bind(e);
|
|
887
|
+
disposer[EFFECT_SCOPE_MARKER] = true;
|
|
888
|
+
return disposer;
|
|
802
889
|
}
|
|
803
890
|
function effectScopeOper() {
|
|
804
891
|
disposeNode(this);
|
|
@@ -1030,8 +1117,11 @@ var $memo = createMemo;
|
|
|
1030
1117
|
function createEffect(fn) {
|
|
1031
1118
|
let cleanups = [];
|
|
1032
1119
|
const rootForError = getCurrentRoot();
|
|
1033
|
-
const
|
|
1120
|
+
const doCleanup = () => {
|
|
1034
1121
|
runCleanupList(cleanups);
|
|
1122
|
+
cleanups = [];
|
|
1123
|
+
};
|
|
1124
|
+
const run = () => {
|
|
1035
1125
|
const bucket = [];
|
|
1036
1126
|
withEffectCleanups(bucket, () => {
|
|
1037
1127
|
try {
|
|
@@ -1048,7 +1138,7 @@ function createEffect(fn) {
|
|
|
1048
1138
|
});
|
|
1049
1139
|
cleanups = bucket;
|
|
1050
1140
|
};
|
|
1051
|
-
const disposeEffect =
|
|
1141
|
+
const disposeEffect = effectWithCleanup(run, doCleanup);
|
|
1052
1142
|
const teardown = () => {
|
|
1053
1143
|
runCleanupList(cleanups);
|
|
1054
1144
|
disposeEffect();
|
|
@@ -1060,11 +1150,13 @@ var $effect = createEffect;
|
|
|
1060
1150
|
function createRenderEffect(fn) {
|
|
1061
1151
|
let cleanup;
|
|
1062
1152
|
const rootForError = getCurrentRoot();
|
|
1063
|
-
const
|
|
1153
|
+
const doCleanup = () => {
|
|
1064
1154
|
if (cleanup) {
|
|
1065
1155
|
cleanup();
|
|
1066
1156
|
cleanup = void 0;
|
|
1067
1157
|
}
|
|
1158
|
+
};
|
|
1159
|
+
const run = () => {
|
|
1068
1160
|
try {
|
|
1069
1161
|
const maybeCleanup = fn();
|
|
1070
1162
|
if (typeof maybeCleanup === "function") {
|
|
@@ -1078,7 +1170,7 @@ function createRenderEffect(fn) {
|
|
|
1078
1170
|
throw err;
|
|
1079
1171
|
}
|
|
1080
1172
|
};
|
|
1081
|
-
const disposeEffect =
|
|
1173
|
+
const disposeEffect = effectWithCleanup(run, doCleanup);
|
|
1082
1174
|
const teardown = () => {
|
|
1083
1175
|
if (cleanup) {
|
|
1084
1176
|
cleanup();
|
|
@@ -1610,9 +1702,6 @@ function mergeProps(...sources) {
|
|
|
1610
1702
|
};
|
|
1611
1703
|
return new Proxy({}, {
|
|
1612
1704
|
get(_, prop) {
|
|
1613
|
-
if (typeof prop === "symbol") {
|
|
1614
|
-
return void 0;
|
|
1615
|
-
}
|
|
1616
1705
|
for (let i = validSources.length - 1; i >= 0; i--) {
|
|
1617
1706
|
const src = validSources[i];
|
|
1618
1707
|
const raw = resolveSource(src);
|
|
@@ -1685,8 +1774,8 @@ function startTransition(fn) {
|
|
|
1685
1774
|
function useTransition() {
|
|
1686
1775
|
const pending = signal(false);
|
|
1687
1776
|
const start = (fn) => {
|
|
1688
|
-
pending(true);
|
|
1689
1777
|
startTransition(() => {
|
|
1778
|
+
pending(true);
|
|
1690
1779
|
try {
|
|
1691
1780
|
fn();
|
|
1692
1781
|
} finally {
|
|
@@ -1931,7 +2020,8 @@ function applyRef(el, value) {
|
|
|
1931
2020
|
if (typeof value === "function") {
|
|
1932
2021
|
const refFn = value;
|
|
1933
2022
|
refFn(el);
|
|
1934
|
-
|
|
2023
|
+
const root = getCurrentRoot();
|
|
2024
|
+
if (root) {
|
|
1935
2025
|
registerRootCleanup(() => {
|
|
1936
2026
|
refFn(null);
|
|
1937
2027
|
});
|
|
@@ -1939,7 +2029,8 @@ function applyRef(el, value) {
|
|
|
1939
2029
|
} else if (value && typeof value === "object" && "current" in value) {
|
|
1940
2030
|
const refObj = value;
|
|
1941
2031
|
refObj.current = el;
|
|
1942
|
-
|
|
2032
|
+
const root = getCurrentRoot();
|
|
2033
|
+
if (root) {
|
|
1943
2034
|
registerRootCleanup(() => {
|
|
1944
2035
|
refObj.current = null;
|
|
1945
2036
|
});
|
|
@@ -2350,8 +2441,6 @@ function reconcileArrays(parentNode, a, b) {
|
|
|
2350
2441
|
}
|
|
2351
2442
|
}
|
|
2352
2443
|
}
|
|
2353
|
-
|
|
2354
|
-
// src/list-helpers.ts
|
|
2355
2444
|
function moveNodesBefore(parent, nodes, anchor) {
|
|
2356
2445
|
for (let i = nodes.length - 1; i >= 0; i--) {
|
|
2357
2446
|
const node = nodes[i];
|
|
@@ -2413,6 +2502,7 @@ function removeBlockRange(block) {
|
|
|
2413
2502
|
cursor = next;
|
|
2414
2503
|
}
|
|
2415
2504
|
}
|
|
2505
|
+
var MAX_SAFE_VERSION = 9007199254740991;
|
|
2416
2506
|
function createVersionedSignalAccessor(initialValue) {
|
|
2417
2507
|
let current = initialValue;
|
|
2418
2508
|
let version = 0;
|
|
@@ -2423,7 +2513,7 @@ function createVersionedSignalAccessor(initialValue) {
|
|
|
2423
2513
|
return current;
|
|
2424
2514
|
}
|
|
2425
2515
|
current = value;
|
|
2426
|
-
version
|
|
2516
|
+
version = version >= MAX_SAFE_VERSION ? 1 : version + 1;
|
|
2427
2517
|
track2(version);
|
|
2428
2518
|
}
|
|
2429
2519
|
return accessor;
|
|
@@ -2479,15 +2569,21 @@ function createKeyedBlock(key, item, index, render2, needsIndex = true, hostRoot
|
|
|
2479
2569
|
});
|
|
2480
2570
|
const root = createRootContext(hostRoot);
|
|
2481
2571
|
const prevRoot = pushRoot(root);
|
|
2482
|
-
const prevSub = setActiveSub(void 0);
|
|
2483
2572
|
let nodes = [];
|
|
2573
|
+
let scopeDispose;
|
|
2574
|
+
const prevSub = setActiveSub(void 0);
|
|
2484
2575
|
try {
|
|
2485
|
-
|
|
2486
|
-
|
|
2487
|
-
|
|
2488
|
-
|
|
2489
|
-
|
|
2490
|
-
|
|
2576
|
+
scopeDispose = effectScope(() => {
|
|
2577
|
+
const rendered = render2(itemSig, indexSig, key);
|
|
2578
|
+
if (rendered instanceof Node || Array.isArray(rendered) && rendered.every((n) => n instanceof Node)) {
|
|
2579
|
+
nodes = toNodeArray(rendered);
|
|
2580
|
+
} else {
|
|
2581
|
+
const element = createElement(rendered);
|
|
2582
|
+
nodes = toNodeArray(element);
|
|
2583
|
+
}
|
|
2584
|
+
});
|
|
2585
|
+
if (scopeDispose) {
|
|
2586
|
+
root.cleanups.push(scopeDispose);
|
|
2491
2587
|
}
|
|
2492
2588
|
} finally {
|
|
2493
2589
|
setActiveSub(prevSub);
|
|
@@ -2514,6 +2610,86 @@ function isNodeBetweenMarkers(node, startMarker, endMarker) {
|
|
|
2514
2610
|
}
|
|
2515
2611
|
return false;
|
|
2516
2612
|
}
|
|
2613
|
+
function reorderBySwap(parent, first, second) {
|
|
2614
|
+
if (first === second) return false;
|
|
2615
|
+
const firstNodes = first.nodes;
|
|
2616
|
+
const secondNodes = second.nodes;
|
|
2617
|
+
if (firstNodes.length === 0 || secondNodes.length === 0) return false;
|
|
2618
|
+
const lastFirst = firstNodes[firstNodes.length - 1];
|
|
2619
|
+
const lastSecond = secondNodes[secondNodes.length - 1];
|
|
2620
|
+
const afterFirst = lastFirst.nextSibling;
|
|
2621
|
+
const afterSecond = lastSecond.nextSibling;
|
|
2622
|
+
moveNodesBefore(parent, firstNodes, afterSecond);
|
|
2623
|
+
moveNodesBefore(parent, secondNodes, afterFirst);
|
|
2624
|
+
return true;
|
|
2625
|
+
}
|
|
2626
|
+
function getLISIndices(sequence) {
|
|
2627
|
+
const predecessors = new Array(sequence.length);
|
|
2628
|
+
const result = [];
|
|
2629
|
+
for (let i = 0; i < sequence.length; i++) {
|
|
2630
|
+
const value = sequence[i];
|
|
2631
|
+
if (value < 0) {
|
|
2632
|
+
predecessors[i] = -1;
|
|
2633
|
+
continue;
|
|
2634
|
+
}
|
|
2635
|
+
let low = 0;
|
|
2636
|
+
let high = result.length;
|
|
2637
|
+
while (low < high) {
|
|
2638
|
+
const mid = low + high >> 1;
|
|
2639
|
+
if (sequence[result[mid]] < value) {
|
|
2640
|
+
low = mid + 1;
|
|
2641
|
+
} else {
|
|
2642
|
+
high = mid;
|
|
2643
|
+
}
|
|
2644
|
+
}
|
|
2645
|
+
predecessors[i] = low > 0 ? result[low - 1] : -1;
|
|
2646
|
+
if (low === result.length) {
|
|
2647
|
+
result.push(i);
|
|
2648
|
+
} else {
|
|
2649
|
+
result[low] = i;
|
|
2650
|
+
}
|
|
2651
|
+
}
|
|
2652
|
+
const lis = new Array(result.length);
|
|
2653
|
+
let k = result.length > 0 ? result[result.length - 1] : -1;
|
|
2654
|
+
for (let i = result.length - 1; i >= 0; i--) {
|
|
2655
|
+
lis[i] = k;
|
|
2656
|
+
k = predecessors[k];
|
|
2657
|
+
}
|
|
2658
|
+
return lis;
|
|
2659
|
+
}
|
|
2660
|
+
function reorderByLIS(parent, endMarker, prev, next) {
|
|
2661
|
+
const positions = /* @__PURE__ */ new Map();
|
|
2662
|
+
for (let i = 0; i < prev.length; i++) {
|
|
2663
|
+
positions.set(prev[i], i);
|
|
2664
|
+
}
|
|
2665
|
+
const sequence = new Array(next.length);
|
|
2666
|
+
for (let i = 0; i < next.length; i++) {
|
|
2667
|
+
const position = positions.get(next[i]);
|
|
2668
|
+
if (position === void 0) return false;
|
|
2669
|
+
sequence[i] = position;
|
|
2670
|
+
}
|
|
2671
|
+
const lisIndices = getLISIndices(sequence);
|
|
2672
|
+
if (lisIndices.length === sequence.length) return true;
|
|
2673
|
+
const inLIS = new Array(sequence.length).fill(false);
|
|
2674
|
+
for (let i = 0; i < lisIndices.length; i++) {
|
|
2675
|
+
inLIS[lisIndices[i]] = true;
|
|
2676
|
+
}
|
|
2677
|
+
let anchor = endMarker;
|
|
2678
|
+
let moved = false;
|
|
2679
|
+
for (let i = next.length - 1; i >= 0; i--) {
|
|
2680
|
+
const block = next[i];
|
|
2681
|
+
const nodes = block.nodes;
|
|
2682
|
+
if (nodes.length === 0) continue;
|
|
2683
|
+
if (inLIS[i]) {
|
|
2684
|
+
anchor = nodes[0];
|
|
2685
|
+
continue;
|
|
2686
|
+
}
|
|
2687
|
+
moveNodesBefore(parent, nodes, anchor);
|
|
2688
|
+
anchor = nodes[0];
|
|
2689
|
+
moved = true;
|
|
2690
|
+
}
|
|
2691
|
+
return moved;
|
|
2692
|
+
}
|
|
2517
2693
|
function createKeyedList(getItems, keyFn, renderItem, needsIndex) {
|
|
2518
2694
|
const resolvedNeedsIndex = arguments.length >= 4 ? !!needsIndex : renderItem.length > 1;
|
|
2519
2695
|
return createFineGrainedKeyedList(getItems, keyFn, renderItem, resolvedNeedsIndex);
|
|
@@ -2546,10 +2722,6 @@ function createFineGrainedKeyedList(getItems, keyFn, renderItem, needsIndex) {
|
|
|
2546
2722
|
const prevOrderedBlocks = container.orderedBlocks;
|
|
2547
2723
|
const nextOrderedBlocks = container.nextOrderedBlocks;
|
|
2548
2724
|
const orderedIndexByKey = container.orderedIndexByKey;
|
|
2549
|
-
newBlocks.clear();
|
|
2550
|
-
nextOrderedBlocks.length = 0;
|
|
2551
|
-
orderedIndexByKey.clear();
|
|
2552
|
-
const createdBlocks = [];
|
|
2553
2725
|
const newItems = getItems();
|
|
2554
2726
|
if (newItems.length === 0) {
|
|
2555
2727
|
if (oldBlocks.size > 0) {
|
|
@@ -2572,8 +2744,44 @@ function createFineGrainedKeyedList(getItems, keyFn, renderItem, needsIndex) {
|
|
|
2572
2744
|
return;
|
|
2573
2745
|
}
|
|
2574
2746
|
const prevCount = prevOrderedBlocks.length;
|
|
2747
|
+
if (prevCount > 0 && newItems.length === prevCount && orderedIndexByKey.size === prevCount) {
|
|
2748
|
+
let stableOrder = true;
|
|
2749
|
+
const seen = /* @__PURE__ */ new Set();
|
|
2750
|
+
for (let i = 0; i < prevCount; i++) {
|
|
2751
|
+
const item = newItems[i];
|
|
2752
|
+
const key = keyFn(item, i);
|
|
2753
|
+
if (seen.has(key) || prevOrderedBlocks[i].key !== key) {
|
|
2754
|
+
stableOrder = false;
|
|
2755
|
+
break;
|
|
2756
|
+
}
|
|
2757
|
+
seen.add(key);
|
|
2758
|
+
}
|
|
2759
|
+
if (stableOrder) {
|
|
2760
|
+
for (let i = 0; i < prevCount; i++) {
|
|
2761
|
+
const item = newItems[i];
|
|
2762
|
+
const block = prevOrderedBlocks[i];
|
|
2763
|
+
if (block.rawItem !== item) {
|
|
2764
|
+
block.rawItem = item;
|
|
2765
|
+
block.item(item);
|
|
2766
|
+
}
|
|
2767
|
+
if (needsIndex && block.rawIndex !== i) {
|
|
2768
|
+
block.rawIndex = i;
|
|
2769
|
+
block.index(i);
|
|
2770
|
+
}
|
|
2771
|
+
}
|
|
2772
|
+
return;
|
|
2773
|
+
}
|
|
2774
|
+
}
|
|
2775
|
+
newBlocks.clear();
|
|
2776
|
+
nextOrderedBlocks.length = 0;
|
|
2777
|
+
orderedIndexByKey.clear();
|
|
2778
|
+
const createdBlocks = [];
|
|
2575
2779
|
let appendCandidate = prevCount > 0 && newItems.length >= prevCount;
|
|
2576
2780
|
const appendedBlocks = [];
|
|
2781
|
+
let mismatchCount = 0;
|
|
2782
|
+
let mismatchFirst = -1;
|
|
2783
|
+
let mismatchSecond = -1;
|
|
2784
|
+
let hasDuplicateKey = false;
|
|
2577
2785
|
newItems.forEach((item, index) => {
|
|
2578
2786
|
const key = keyFn(item, index);
|
|
2579
2787
|
let block = oldBlocks.get(key);
|
|
@@ -2605,6 +2813,7 @@ function createFineGrainedKeyedList(getItems, keyFn, renderItem, needsIndex) {
|
|
|
2605
2813
|
const position = orderedIndexByKey.get(key);
|
|
2606
2814
|
if (position !== void 0) {
|
|
2607
2815
|
appendCandidate = false;
|
|
2816
|
+
hasDuplicateKey = true;
|
|
2608
2817
|
const prior = nextOrderedBlocks[position];
|
|
2609
2818
|
if (prior && prior !== resolvedBlock) {
|
|
2610
2819
|
destroyRoot(prior.root);
|
|
@@ -2621,8 +2830,17 @@ function createFineGrainedKeyedList(getItems, keyFn, renderItem, needsIndex) {
|
|
|
2621
2830
|
appendCandidate = false;
|
|
2622
2831
|
}
|
|
2623
2832
|
}
|
|
2624
|
-
|
|
2833
|
+
const nextIndex = nextOrderedBlocks.length;
|
|
2834
|
+
orderedIndexByKey.set(key, nextIndex);
|
|
2625
2835
|
nextOrderedBlocks.push(resolvedBlock);
|
|
2836
|
+
if (mismatchCount < 3 && (nextIndex >= prevCount || prevOrderedBlocks[nextIndex] !== resolvedBlock)) {
|
|
2837
|
+
if (mismatchCount === 0) {
|
|
2838
|
+
mismatchFirst = nextIndex;
|
|
2839
|
+
} else if (mismatchCount === 1) {
|
|
2840
|
+
mismatchSecond = nextIndex;
|
|
2841
|
+
}
|
|
2842
|
+
mismatchCount++;
|
|
2843
|
+
}
|
|
2626
2844
|
}
|
|
2627
2845
|
if (appendCandidate && index >= prevCount) {
|
|
2628
2846
|
appendedBlocks.push(resolvedBlock);
|
|
@@ -2663,7 +2881,26 @@ function createFineGrainedKeyedList(getItems, keyFn, renderItem, needsIndex) {
|
|
|
2663
2881
|
}
|
|
2664
2882
|
oldBlocks.clear();
|
|
2665
2883
|
}
|
|
2666
|
-
|
|
2884
|
+
const canReorderInPlace = createdBlocks.length === 0 && oldBlocks.size === 0 && nextOrderedBlocks.length === prevOrderedBlocks.length;
|
|
2885
|
+
let skipReconcile = false;
|
|
2886
|
+
let updateNodeBuffer = true;
|
|
2887
|
+
if (canReorderInPlace && nextOrderedBlocks.length > 0 && !hasDuplicateKey) {
|
|
2888
|
+
if (mismatchCount === 0) {
|
|
2889
|
+
skipReconcile = true;
|
|
2890
|
+
updateNodeBuffer = false;
|
|
2891
|
+
} else if (mismatchCount === 2 && prevOrderedBlocks[mismatchFirst] === nextOrderedBlocks[mismatchSecond] && prevOrderedBlocks[mismatchSecond] === nextOrderedBlocks[mismatchFirst]) {
|
|
2892
|
+
if (reorderBySwap(
|
|
2893
|
+
parent,
|
|
2894
|
+
prevOrderedBlocks[mismatchFirst],
|
|
2895
|
+
prevOrderedBlocks[mismatchSecond]
|
|
2896
|
+
)) {
|
|
2897
|
+
skipReconcile = true;
|
|
2898
|
+
}
|
|
2899
|
+
} else if (reorderByLIS(parent, container.endMarker, prevOrderedBlocks, nextOrderedBlocks)) {
|
|
2900
|
+
skipReconcile = true;
|
|
2901
|
+
}
|
|
2902
|
+
}
|
|
2903
|
+
if (!skipReconcile && (newBlocks.size > 0 || container.currentNodes.length > 0)) {
|
|
2667
2904
|
const prevNodes = container.currentNodes;
|
|
2668
2905
|
const nextNodes = container.nextNodes;
|
|
2669
2906
|
nextNodes.length = 0;
|
|
@@ -2678,6 +2915,20 @@ function createFineGrainedKeyedList(getItems, keyFn, renderItem, needsIndex) {
|
|
|
2678
2915
|
reconcileArrays(parent, prevNodes, nextNodes);
|
|
2679
2916
|
container.currentNodes = nextNodes;
|
|
2680
2917
|
container.nextNodes = prevNodes;
|
|
2918
|
+
} else if (skipReconcile && updateNodeBuffer) {
|
|
2919
|
+
const prevNodes = container.currentNodes;
|
|
2920
|
+
const nextNodes = container.nextNodes;
|
|
2921
|
+
nextNodes.length = 0;
|
|
2922
|
+
nextNodes.push(container.startMarker);
|
|
2923
|
+
for (let i = 0; i < nextOrderedBlocks.length; i++) {
|
|
2924
|
+
const nodes = nextOrderedBlocks[i].nodes;
|
|
2925
|
+
for (let j = 0; j < nodes.length; j++) {
|
|
2926
|
+
nextNodes.push(nodes[j]);
|
|
2927
|
+
}
|
|
2928
|
+
}
|
|
2929
|
+
nextNodes.push(container.endMarker);
|
|
2930
|
+
container.currentNodes = nextNodes;
|
|
2931
|
+
container.nextNodes = prevNodes;
|
|
2681
2932
|
}
|
|
2682
2933
|
container.blocks = newBlocks;
|
|
2683
2934
|
container.nextBlocks = oldBlocks;
|
|
@@ -3319,7 +3570,9 @@ function bindEvent(el, eventName, handler, options2) {
|
|
|
3319
3570
|
const fn = resolveHandler();
|
|
3320
3571
|
callEventHandler(fn, args[0], el);
|
|
3321
3572
|
} catch (err) {
|
|
3322
|
-
handleError(err, { source: "event", eventName }, rootRef)
|
|
3573
|
+
if (!handleError(err, { source: "event", eventName }, rootRef)) {
|
|
3574
|
+
throw err;
|
|
3575
|
+
}
|
|
3323
3576
|
}
|
|
3324
3577
|
};
|
|
3325
3578
|
return () => {
|
|
@@ -4097,10 +4350,12 @@ function ErrorBoundary(props) {
|
|
|
4097
4350
|
renderingFallback = true;
|
|
4098
4351
|
try {
|
|
4099
4352
|
renderValue(toView(err));
|
|
4100
|
-
} finally {
|
|
4101
4353
|
renderingFallback = false;
|
|
4354
|
+
props.onError?.(err);
|
|
4355
|
+
} catch (fallbackErr) {
|
|
4356
|
+
props.onError?.(err);
|
|
4357
|
+
throw fallbackErr;
|
|
4102
4358
|
}
|
|
4103
|
-
props.onError?.(err);
|
|
4104
4359
|
return;
|
|
4105
4360
|
}
|
|
4106
4361
|
popRoot(prev);
|
|
@@ -4195,7 +4450,9 @@ function Suspense(props) {
|
|
|
4195
4450
|
popRoot(prev);
|
|
4196
4451
|
flushOnMount(root);
|
|
4197
4452
|
destroyRoot(root);
|
|
4198
|
-
handleError(err, { source: "render" })
|
|
4453
|
+
if (!handleError(err, { source: "render" }, hostRoot)) {
|
|
4454
|
+
throw err;
|
|
4455
|
+
}
|
|
4199
4456
|
return;
|
|
4200
4457
|
}
|
|
4201
4458
|
popRoot(prev);
|
|
@@ -4225,18 +4482,26 @@ function Suspense(props) {
|
|
|
4225
4482
|
if (thenable) {
|
|
4226
4483
|
thenable.then(
|
|
4227
4484
|
() => {
|
|
4228
|
-
if (epoch !== tokenEpoch)
|
|
4229
|
-
|
|
4230
|
-
|
|
4485
|
+
if (epoch !== tokenEpoch) {
|
|
4486
|
+
return;
|
|
4487
|
+
}
|
|
4488
|
+
const newPending = Math.max(0, pending() - 1);
|
|
4489
|
+
pending(newPending);
|
|
4490
|
+
if (newPending === 0) {
|
|
4231
4491
|
switchView(props.children ?? null);
|
|
4232
4492
|
onResolveMaybe();
|
|
4233
4493
|
}
|
|
4234
4494
|
},
|
|
4235
4495
|
(err) => {
|
|
4236
|
-
if (epoch !== tokenEpoch)
|
|
4237
|
-
|
|
4496
|
+
if (epoch !== tokenEpoch) {
|
|
4497
|
+
return;
|
|
4498
|
+
}
|
|
4499
|
+
const newPending = Math.max(0, pending() - 1);
|
|
4500
|
+
pending(newPending);
|
|
4238
4501
|
props.onReject?.(err);
|
|
4239
|
-
handleError(err, { source: "render" }, hostRoot)
|
|
4502
|
+
if (!handleError(err, { source: "render" }, hostRoot)) {
|
|
4503
|
+
throw err;
|
|
4504
|
+
}
|
|
4240
4505
|
}
|
|
4241
4506
|
);
|
|
4242
4507
|
return true;
|