@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.cjs
CHANGED
|
@@ -302,7 +302,7 @@ function handleError(err, info, startRoot) {
|
|
|
302
302
|
}
|
|
303
303
|
}
|
|
304
304
|
}
|
|
305
|
-
|
|
305
|
+
return false;
|
|
306
306
|
}
|
|
307
307
|
function handleSuspend(token, startRoot) {
|
|
308
308
|
let root = startRoot ?? currentRoot;
|
|
@@ -348,6 +348,11 @@ var isInTransition = false;
|
|
|
348
348
|
var enqueueMicrotask = typeof queueMicrotask === "function" ? queueMicrotask : (fn) => {
|
|
349
349
|
Promise.resolve().then(fn);
|
|
350
350
|
};
|
|
351
|
+
var inCleanup = false;
|
|
352
|
+
var SIGNAL_MARKER = Symbol.for("fict:signal");
|
|
353
|
+
var COMPUTED_MARKER = Symbol.for("fict:computed");
|
|
354
|
+
var EFFECT_MARKER = Symbol.for("fict:effect");
|
|
355
|
+
var EFFECT_SCOPE_MARKER = Symbol.for("fict:effectScope");
|
|
351
356
|
function link(dep, sub, version) {
|
|
352
357
|
const prevDep = sub.depsTail;
|
|
353
358
|
if (prevDep !== void 0 && prevDep.dep === dep) return;
|
|
@@ -471,13 +476,21 @@ function checkDirty(firstLink, sub) {
|
|
|
471
476
|
dirty = true;
|
|
472
477
|
}
|
|
473
478
|
} else if ((depFlags & MutablePending) === MutablePending) {
|
|
474
|
-
if (
|
|
475
|
-
|
|
479
|
+
if (!dep.deps) {
|
|
480
|
+
const nextDep = link2.nextDep;
|
|
481
|
+
if (nextDep !== void 0) {
|
|
482
|
+
link2 = nextDep;
|
|
483
|
+
continue;
|
|
484
|
+
}
|
|
485
|
+
} else {
|
|
486
|
+
if (link2.nextSub !== void 0 || link2.prevSub !== void 0) {
|
|
487
|
+
stack = { value: link2, prev: stack };
|
|
488
|
+
}
|
|
489
|
+
link2 = dep.deps;
|
|
490
|
+
sub = dep;
|
|
491
|
+
++checkDepth;
|
|
492
|
+
continue;
|
|
476
493
|
}
|
|
477
|
-
link2 = dep.deps;
|
|
478
|
-
sub = dep;
|
|
479
|
-
++checkDepth;
|
|
480
|
-
continue;
|
|
481
494
|
}
|
|
482
495
|
if (!dirty) {
|
|
483
496
|
const nextDep = link2.nextDep;
|
|
@@ -555,8 +568,12 @@ function disposeNode(node) {
|
|
|
555
568
|
node.depsTail = void 0;
|
|
556
569
|
node.flags = 0;
|
|
557
570
|
purgeDeps(node);
|
|
558
|
-
|
|
559
|
-
|
|
571
|
+
let sub = node.subs;
|
|
572
|
+
while (sub !== void 0) {
|
|
573
|
+
const next = sub.nextSub;
|
|
574
|
+
unlink(sub);
|
|
575
|
+
sub = next;
|
|
576
|
+
}
|
|
560
577
|
}
|
|
561
578
|
function updateSignal(s) {
|
|
562
579
|
s.flags = Mutable;
|
|
@@ -593,7 +610,15 @@ function updateComputed(c) {
|
|
|
593
610
|
}
|
|
594
611
|
function runEffect(e) {
|
|
595
612
|
const flags = e.flags;
|
|
596
|
-
if (flags & Dirty
|
|
613
|
+
if (flags & Dirty) {
|
|
614
|
+
if (e.runCleanup) {
|
|
615
|
+
inCleanup = true;
|
|
616
|
+
try {
|
|
617
|
+
e.runCleanup();
|
|
618
|
+
} finally {
|
|
619
|
+
inCleanup = false;
|
|
620
|
+
}
|
|
621
|
+
}
|
|
597
622
|
++cycle;
|
|
598
623
|
effectRunDevtools(e);
|
|
599
624
|
e.depsTail = void 0;
|
|
@@ -610,6 +635,35 @@ function runEffect(e) {
|
|
|
610
635
|
e.flags = Watching;
|
|
611
636
|
throw err;
|
|
612
637
|
}
|
|
638
|
+
} else if (flags & Pending && e.deps) {
|
|
639
|
+
if (e.runCleanup) {
|
|
640
|
+
inCleanup = true;
|
|
641
|
+
try {
|
|
642
|
+
e.runCleanup();
|
|
643
|
+
} finally {
|
|
644
|
+
inCleanup = false;
|
|
645
|
+
}
|
|
646
|
+
}
|
|
647
|
+
if (checkDirty(e.deps, e)) {
|
|
648
|
+
++cycle;
|
|
649
|
+
effectRunDevtools(e);
|
|
650
|
+
e.depsTail = void 0;
|
|
651
|
+
e.flags = WatchingRunning;
|
|
652
|
+
const prevSub = activeSub;
|
|
653
|
+
activeSub = e;
|
|
654
|
+
try {
|
|
655
|
+
e.fn();
|
|
656
|
+
activeSub = prevSub;
|
|
657
|
+
e.flags = Watching;
|
|
658
|
+
purgeDeps(e);
|
|
659
|
+
} catch (err) {
|
|
660
|
+
activeSub = prevSub;
|
|
661
|
+
e.flags = Watching;
|
|
662
|
+
throw err;
|
|
663
|
+
}
|
|
664
|
+
} else {
|
|
665
|
+
e.flags = Watching;
|
|
666
|
+
}
|
|
613
667
|
} else {
|
|
614
668
|
e.flags = Watching;
|
|
615
669
|
}
|
|
@@ -688,7 +742,9 @@ function signal(initialValue) {
|
|
|
688
742
|
__id: void 0
|
|
689
743
|
};
|
|
690
744
|
registerSignalDevtools(initialValue, s);
|
|
691
|
-
|
|
745
|
+
const accessor = signalOper.bind(s);
|
|
746
|
+
accessor[SIGNAL_MARKER] = true;
|
|
747
|
+
return accessor;
|
|
692
748
|
}
|
|
693
749
|
function signalOper(value) {
|
|
694
750
|
if (arguments.length > 0) {
|
|
@@ -705,7 +761,7 @@ function signalOper(value) {
|
|
|
705
761
|
return;
|
|
706
762
|
}
|
|
707
763
|
const flags = this.flags;
|
|
708
|
-
if (flags & Dirty) {
|
|
764
|
+
if (flags & Dirty && !inCleanup) {
|
|
709
765
|
if (updateSignal(this)) {
|
|
710
766
|
const subs = this.subs;
|
|
711
767
|
if (subs !== void 0) shallowPropagate(subs);
|
|
@@ -733,6 +789,7 @@ function computed(getter) {
|
|
|
733
789
|
getter
|
|
734
790
|
};
|
|
735
791
|
const bound = computedOper.bind(c);
|
|
792
|
+
bound[COMPUTED_MARKER] = true;
|
|
736
793
|
return bound;
|
|
737
794
|
}
|
|
738
795
|
function computedOper() {
|
|
@@ -785,7 +842,35 @@ function effect(fn) {
|
|
|
785
842
|
activeSub = prevSub;
|
|
786
843
|
e.flags &= ~Running;
|
|
787
844
|
}
|
|
788
|
-
|
|
845
|
+
const disposer = effectOper.bind(e);
|
|
846
|
+
disposer[EFFECT_MARKER] = true;
|
|
847
|
+
return disposer;
|
|
848
|
+
}
|
|
849
|
+
function effectWithCleanup(fn, cleanupRunner) {
|
|
850
|
+
const e = {
|
|
851
|
+
fn,
|
|
852
|
+
subs: void 0,
|
|
853
|
+
subsTail: void 0,
|
|
854
|
+
deps: void 0,
|
|
855
|
+
depsTail: void 0,
|
|
856
|
+
flags: WatchingRunning,
|
|
857
|
+
runCleanup: cleanupRunner,
|
|
858
|
+
__id: void 0
|
|
859
|
+
};
|
|
860
|
+
registerEffectDevtools(e);
|
|
861
|
+
const prevSub = activeSub;
|
|
862
|
+
if (prevSub !== void 0) link(e, prevSub, 0);
|
|
863
|
+
activeSub = e;
|
|
864
|
+
try {
|
|
865
|
+
effectRunDevtools(e);
|
|
866
|
+
fn();
|
|
867
|
+
} finally {
|
|
868
|
+
activeSub = prevSub;
|
|
869
|
+
e.flags &= ~Running;
|
|
870
|
+
}
|
|
871
|
+
const disposer = effectOper.bind(e);
|
|
872
|
+
disposer[EFFECT_MARKER] = true;
|
|
873
|
+
return disposer;
|
|
789
874
|
}
|
|
790
875
|
function effectOper() {
|
|
791
876
|
disposeNode(this);
|
|
@@ -800,7 +885,9 @@ function effectScope(fn) {
|
|
|
800
885
|
} finally {
|
|
801
886
|
activeSub = prevSub;
|
|
802
887
|
}
|
|
803
|
-
|
|
888
|
+
const disposer = effectScopeOper.bind(e);
|
|
889
|
+
disposer[EFFECT_SCOPE_MARKER] = true;
|
|
890
|
+
return disposer;
|
|
804
891
|
}
|
|
805
892
|
function effectScopeOper() {
|
|
806
893
|
disposeNode(this);
|
|
@@ -1032,8 +1119,11 @@ var $memo = createMemo;
|
|
|
1032
1119
|
function createEffect(fn) {
|
|
1033
1120
|
let cleanups = [];
|
|
1034
1121
|
const rootForError = getCurrentRoot();
|
|
1035
|
-
const
|
|
1122
|
+
const doCleanup = () => {
|
|
1036
1123
|
runCleanupList(cleanups);
|
|
1124
|
+
cleanups = [];
|
|
1125
|
+
};
|
|
1126
|
+
const run = () => {
|
|
1037
1127
|
const bucket = [];
|
|
1038
1128
|
withEffectCleanups(bucket, () => {
|
|
1039
1129
|
try {
|
|
@@ -1050,7 +1140,7 @@ function createEffect(fn) {
|
|
|
1050
1140
|
});
|
|
1051
1141
|
cleanups = bucket;
|
|
1052
1142
|
};
|
|
1053
|
-
const disposeEffect =
|
|
1143
|
+
const disposeEffect = effectWithCleanup(run, doCleanup);
|
|
1054
1144
|
const teardown = () => {
|
|
1055
1145
|
runCleanupList(cleanups);
|
|
1056
1146
|
disposeEffect();
|
|
@@ -1062,11 +1152,13 @@ var $effect = createEffect;
|
|
|
1062
1152
|
function createRenderEffect(fn) {
|
|
1063
1153
|
let cleanup;
|
|
1064
1154
|
const rootForError = getCurrentRoot();
|
|
1065
|
-
const
|
|
1155
|
+
const doCleanup = () => {
|
|
1066
1156
|
if (cleanup) {
|
|
1067
1157
|
cleanup();
|
|
1068
1158
|
cleanup = void 0;
|
|
1069
1159
|
}
|
|
1160
|
+
};
|
|
1161
|
+
const run = () => {
|
|
1070
1162
|
try {
|
|
1071
1163
|
const maybeCleanup = fn();
|
|
1072
1164
|
if (typeof maybeCleanup === "function") {
|
|
@@ -1080,7 +1172,7 @@ function createRenderEffect(fn) {
|
|
|
1080
1172
|
throw err;
|
|
1081
1173
|
}
|
|
1082
1174
|
};
|
|
1083
|
-
const disposeEffect =
|
|
1175
|
+
const disposeEffect = effectWithCleanup(run, doCleanup);
|
|
1084
1176
|
const teardown = () => {
|
|
1085
1177
|
if (cleanup) {
|
|
1086
1178
|
cleanup();
|
|
@@ -1612,9 +1704,6 @@ function mergeProps(...sources) {
|
|
|
1612
1704
|
};
|
|
1613
1705
|
return new Proxy({}, {
|
|
1614
1706
|
get(_, prop) {
|
|
1615
|
-
if (typeof prop === "symbol") {
|
|
1616
|
-
return void 0;
|
|
1617
|
-
}
|
|
1618
1707
|
for (let i = validSources.length - 1; i >= 0; i--) {
|
|
1619
1708
|
const src = validSources[i];
|
|
1620
1709
|
const raw = resolveSource(src);
|
|
@@ -1687,8 +1776,8 @@ function startTransition(fn) {
|
|
|
1687
1776
|
function useTransition() {
|
|
1688
1777
|
const pending = signal(false);
|
|
1689
1778
|
const start = (fn) => {
|
|
1690
|
-
pending(true);
|
|
1691
1779
|
startTransition(() => {
|
|
1780
|
+
pending(true);
|
|
1692
1781
|
try {
|
|
1693
1782
|
fn();
|
|
1694
1783
|
} finally {
|
|
@@ -1933,7 +2022,8 @@ function applyRef(el, value) {
|
|
|
1933
2022
|
if (typeof value === "function") {
|
|
1934
2023
|
const refFn = value;
|
|
1935
2024
|
refFn(el);
|
|
1936
|
-
|
|
2025
|
+
const root = getCurrentRoot();
|
|
2026
|
+
if (root) {
|
|
1937
2027
|
registerRootCleanup(() => {
|
|
1938
2028
|
refFn(null);
|
|
1939
2029
|
});
|
|
@@ -1941,7 +2031,8 @@ function applyRef(el, value) {
|
|
|
1941
2031
|
} else if (value && typeof value === "object" && "current" in value) {
|
|
1942
2032
|
const refObj = value;
|
|
1943
2033
|
refObj.current = el;
|
|
1944
|
-
|
|
2034
|
+
const root = getCurrentRoot();
|
|
2035
|
+
if (root) {
|
|
1945
2036
|
registerRootCleanup(() => {
|
|
1946
2037
|
refObj.current = null;
|
|
1947
2038
|
});
|
|
@@ -2352,8 +2443,6 @@ function reconcileArrays(parentNode, a, b) {
|
|
|
2352
2443
|
}
|
|
2353
2444
|
}
|
|
2354
2445
|
}
|
|
2355
|
-
|
|
2356
|
-
// src/list-helpers.ts
|
|
2357
2446
|
function moveNodesBefore(parent, nodes, anchor) {
|
|
2358
2447
|
for (let i = nodes.length - 1; i >= 0; i--) {
|
|
2359
2448
|
const node = nodes[i];
|
|
@@ -2415,6 +2504,7 @@ function removeBlockRange(block) {
|
|
|
2415
2504
|
cursor = next;
|
|
2416
2505
|
}
|
|
2417
2506
|
}
|
|
2507
|
+
var MAX_SAFE_VERSION = 9007199254740991;
|
|
2418
2508
|
function createVersionedSignalAccessor(initialValue) {
|
|
2419
2509
|
let current = initialValue;
|
|
2420
2510
|
let version = 0;
|
|
@@ -2425,7 +2515,7 @@ function createVersionedSignalAccessor(initialValue) {
|
|
|
2425
2515
|
return current;
|
|
2426
2516
|
}
|
|
2427
2517
|
current = value;
|
|
2428
|
-
version
|
|
2518
|
+
version = version >= MAX_SAFE_VERSION ? 1 : version + 1;
|
|
2429
2519
|
track2(version);
|
|
2430
2520
|
}
|
|
2431
2521
|
return accessor;
|
|
@@ -2481,15 +2571,21 @@ function createKeyedBlock(key, item, index, render2, needsIndex = true, hostRoot
|
|
|
2481
2571
|
});
|
|
2482
2572
|
const root = createRootContext(hostRoot);
|
|
2483
2573
|
const prevRoot = pushRoot(root);
|
|
2484
|
-
const prevSub = setActiveSub(void 0);
|
|
2485
2574
|
let nodes = [];
|
|
2575
|
+
let scopeDispose;
|
|
2576
|
+
const prevSub = setActiveSub(void 0);
|
|
2486
2577
|
try {
|
|
2487
|
-
|
|
2488
|
-
|
|
2489
|
-
|
|
2490
|
-
|
|
2491
|
-
|
|
2492
|
-
|
|
2578
|
+
scopeDispose = effectScope(() => {
|
|
2579
|
+
const rendered = render2(itemSig, indexSig, key);
|
|
2580
|
+
if (rendered instanceof Node || Array.isArray(rendered) && rendered.every((n) => n instanceof Node)) {
|
|
2581
|
+
nodes = toNodeArray(rendered);
|
|
2582
|
+
} else {
|
|
2583
|
+
const element = createElement(rendered);
|
|
2584
|
+
nodes = toNodeArray(element);
|
|
2585
|
+
}
|
|
2586
|
+
});
|
|
2587
|
+
if (scopeDispose) {
|
|
2588
|
+
root.cleanups.push(scopeDispose);
|
|
2493
2589
|
}
|
|
2494
2590
|
} finally {
|
|
2495
2591
|
setActiveSub(prevSub);
|
|
@@ -2516,6 +2612,86 @@ function isNodeBetweenMarkers(node, startMarker, endMarker) {
|
|
|
2516
2612
|
}
|
|
2517
2613
|
return false;
|
|
2518
2614
|
}
|
|
2615
|
+
function reorderBySwap(parent, first, second) {
|
|
2616
|
+
if (first === second) return false;
|
|
2617
|
+
const firstNodes = first.nodes;
|
|
2618
|
+
const secondNodes = second.nodes;
|
|
2619
|
+
if (firstNodes.length === 0 || secondNodes.length === 0) return false;
|
|
2620
|
+
const lastFirst = firstNodes[firstNodes.length - 1];
|
|
2621
|
+
const lastSecond = secondNodes[secondNodes.length - 1];
|
|
2622
|
+
const afterFirst = lastFirst.nextSibling;
|
|
2623
|
+
const afterSecond = lastSecond.nextSibling;
|
|
2624
|
+
moveNodesBefore(parent, firstNodes, afterSecond);
|
|
2625
|
+
moveNodesBefore(parent, secondNodes, afterFirst);
|
|
2626
|
+
return true;
|
|
2627
|
+
}
|
|
2628
|
+
function getLISIndices(sequence) {
|
|
2629
|
+
const predecessors = new Array(sequence.length);
|
|
2630
|
+
const result = [];
|
|
2631
|
+
for (let i = 0; i < sequence.length; i++) {
|
|
2632
|
+
const value = sequence[i];
|
|
2633
|
+
if (value < 0) {
|
|
2634
|
+
predecessors[i] = -1;
|
|
2635
|
+
continue;
|
|
2636
|
+
}
|
|
2637
|
+
let low = 0;
|
|
2638
|
+
let high = result.length;
|
|
2639
|
+
while (low < high) {
|
|
2640
|
+
const mid = low + high >> 1;
|
|
2641
|
+
if (sequence[result[mid]] < value) {
|
|
2642
|
+
low = mid + 1;
|
|
2643
|
+
} else {
|
|
2644
|
+
high = mid;
|
|
2645
|
+
}
|
|
2646
|
+
}
|
|
2647
|
+
predecessors[i] = low > 0 ? result[low - 1] : -1;
|
|
2648
|
+
if (low === result.length) {
|
|
2649
|
+
result.push(i);
|
|
2650
|
+
} else {
|
|
2651
|
+
result[low] = i;
|
|
2652
|
+
}
|
|
2653
|
+
}
|
|
2654
|
+
const lis = new Array(result.length);
|
|
2655
|
+
let k = result.length > 0 ? result[result.length - 1] : -1;
|
|
2656
|
+
for (let i = result.length - 1; i >= 0; i--) {
|
|
2657
|
+
lis[i] = k;
|
|
2658
|
+
k = predecessors[k];
|
|
2659
|
+
}
|
|
2660
|
+
return lis;
|
|
2661
|
+
}
|
|
2662
|
+
function reorderByLIS(parent, endMarker, prev, next) {
|
|
2663
|
+
const positions = /* @__PURE__ */ new Map();
|
|
2664
|
+
for (let i = 0; i < prev.length; i++) {
|
|
2665
|
+
positions.set(prev[i], i);
|
|
2666
|
+
}
|
|
2667
|
+
const sequence = new Array(next.length);
|
|
2668
|
+
for (let i = 0; i < next.length; i++) {
|
|
2669
|
+
const position = positions.get(next[i]);
|
|
2670
|
+
if (position === void 0) return false;
|
|
2671
|
+
sequence[i] = position;
|
|
2672
|
+
}
|
|
2673
|
+
const lisIndices = getLISIndices(sequence);
|
|
2674
|
+
if (lisIndices.length === sequence.length) return true;
|
|
2675
|
+
const inLIS = new Array(sequence.length).fill(false);
|
|
2676
|
+
for (let i = 0; i < lisIndices.length; i++) {
|
|
2677
|
+
inLIS[lisIndices[i]] = true;
|
|
2678
|
+
}
|
|
2679
|
+
let anchor = endMarker;
|
|
2680
|
+
let moved = false;
|
|
2681
|
+
for (let i = next.length - 1; i >= 0; i--) {
|
|
2682
|
+
const block = next[i];
|
|
2683
|
+
const nodes = block.nodes;
|
|
2684
|
+
if (nodes.length === 0) continue;
|
|
2685
|
+
if (inLIS[i]) {
|
|
2686
|
+
anchor = nodes[0];
|
|
2687
|
+
continue;
|
|
2688
|
+
}
|
|
2689
|
+
moveNodesBefore(parent, nodes, anchor);
|
|
2690
|
+
anchor = nodes[0];
|
|
2691
|
+
moved = true;
|
|
2692
|
+
}
|
|
2693
|
+
return moved;
|
|
2694
|
+
}
|
|
2519
2695
|
function createKeyedList(getItems, keyFn, renderItem, needsIndex) {
|
|
2520
2696
|
const resolvedNeedsIndex = arguments.length >= 4 ? !!needsIndex : renderItem.length > 1;
|
|
2521
2697
|
return createFineGrainedKeyedList(getItems, keyFn, renderItem, resolvedNeedsIndex);
|
|
@@ -2548,10 +2724,6 @@ function createFineGrainedKeyedList(getItems, keyFn, renderItem, needsIndex) {
|
|
|
2548
2724
|
const prevOrderedBlocks = container.orderedBlocks;
|
|
2549
2725
|
const nextOrderedBlocks = container.nextOrderedBlocks;
|
|
2550
2726
|
const orderedIndexByKey = container.orderedIndexByKey;
|
|
2551
|
-
newBlocks.clear();
|
|
2552
|
-
nextOrderedBlocks.length = 0;
|
|
2553
|
-
orderedIndexByKey.clear();
|
|
2554
|
-
const createdBlocks = [];
|
|
2555
2727
|
const newItems = getItems();
|
|
2556
2728
|
if (newItems.length === 0) {
|
|
2557
2729
|
if (oldBlocks.size > 0) {
|
|
@@ -2574,8 +2746,44 @@ function createFineGrainedKeyedList(getItems, keyFn, renderItem, needsIndex) {
|
|
|
2574
2746
|
return;
|
|
2575
2747
|
}
|
|
2576
2748
|
const prevCount = prevOrderedBlocks.length;
|
|
2749
|
+
if (prevCount > 0 && newItems.length === prevCount && orderedIndexByKey.size === prevCount) {
|
|
2750
|
+
let stableOrder = true;
|
|
2751
|
+
const seen = /* @__PURE__ */ new Set();
|
|
2752
|
+
for (let i = 0; i < prevCount; i++) {
|
|
2753
|
+
const item = newItems[i];
|
|
2754
|
+
const key = keyFn(item, i);
|
|
2755
|
+
if (seen.has(key) || prevOrderedBlocks[i].key !== key) {
|
|
2756
|
+
stableOrder = false;
|
|
2757
|
+
break;
|
|
2758
|
+
}
|
|
2759
|
+
seen.add(key);
|
|
2760
|
+
}
|
|
2761
|
+
if (stableOrder) {
|
|
2762
|
+
for (let i = 0; i < prevCount; i++) {
|
|
2763
|
+
const item = newItems[i];
|
|
2764
|
+
const block = prevOrderedBlocks[i];
|
|
2765
|
+
if (block.rawItem !== item) {
|
|
2766
|
+
block.rawItem = item;
|
|
2767
|
+
block.item(item);
|
|
2768
|
+
}
|
|
2769
|
+
if (needsIndex && block.rawIndex !== i) {
|
|
2770
|
+
block.rawIndex = i;
|
|
2771
|
+
block.index(i);
|
|
2772
|
+
}
|
|
2773
|
+
}
|
|
2774
|
+
return;
|
|
2775
|
+
}
|
|
2776
|
+
}
|
|
2777
|
+
newBlocks.clear();
|
|
2778
|
+
nextOrderedBlocks.length = 0;
|
|
2779
|
+
orderedIndexByKey.clear();
|
|
2780
|
+
const createdBlocks = [];
|
|
2577
2781
|
let appendCandidate = prevCount > 0 && newItems.length >= prevCount;
|
|
2578
2782
|
const appendedBlocks = [];
|
|
2783
|
+
let mismatchCount = 0;
|
|
2784
|
+
let mismatchFirst = -1;
|
|
2785
|
+
let mismatchSecond = -1;
|
|
2786
|
+
let hasDuplicateKey = false;
|
|
2579
2787
|
newItems.forEach((item, index) => {
|
|
2580
2788
|
const key = keyFn(item, index);
|
|
2581
2789
|
let block = oldBlocks.get(key);
|
|
@@ -2607,6 +2815,7 @@ function createFineGrainedKeyedList(getItems, keyFn, renderItem, needsIndex) {
|
|
|
2607
2815
|
const position = orderedIndexByKey.get(key);
|
|
2608
2816
|
if (position !== void 0) {
|
|
2609
2817
|
appendCandidate = false;
|
|
2818
|
+
hasDuplicateKey = true;
|
|
2610
2819
|
const prior = nextOrderedBlocks[position];
|
|
2611
2820
|
if (prior && prior !== resolvedBlock) {
|
|
2612
2821
|
destroyRoot(prior.root);
|
|
@@ -2623,8 +2832,17 @@ function createFineGrainedKeyedList(getItems, keyFn, renderItem, needsIndex) {
|
|
|
2623
2832
|
appendCandidate = false;
|
|
2624
2833
|
}
|
|
2625
2834
|
}
|
|
2626
|
-
|
|
2835
|
+
const nextIndex = nextOrderedBlocks.length;
|
|
2836
|
+
orderedIndexByKey.set(key, nextIndex);
|
|
2627
2837
|
nextOrderedBlocks.push(resolvedBlock);
|
|
2838
|
+
if (mismatchCount < 3 && (nextIndex >= prevCount || prevOrderedBlocks[nextIndex] !== resolvedBlock)) {
|
|
2839
|
+
if (mismatchCount === 0) {
|
|
2840
|
+
mismatchFirst = nextIndex;
|
|
2841
|
+
} else if (mismatchCount === 1) {
|
|
2842
|
+
mismatchSecond = nextIndex;
|
|
2843
|
+
}
|
|
2844
|
+
mismatchCount++;
|
|
2845
|
+
}
|
|
2628
2846
|
}
|
|
2629
2847
|
if (appendCandidate && index >= prevCount) {
|
|
2630
2848
|
appendedBlocks.push(resolvedBlock);
|
|
@@ -2665,7 +2883,26 @@ function createFineGrainedKeyedList(getItems, keyFn, renderItem, needsIndex) {
|
|
|
2665
2883
|
}
|
|
2666
2884
|
oldBlocks.clear();
|
|
2667
2885
|
}
|
|
2668
|
-
|
|
2886
|
+
const canReorderInPlace = createdBlocks.length === 0 && oldBlocks.size === 0 && nextOrderedBlocks.length === prevOrderedBlocks.length;
|
|
2887
|
+
let skipReconcile = false;
|
|
2888
|
+
let updateNodeBuffer = true;
|
|
2889
|
+
if (canReorderInPlace && nextOrderedBlocks.length > 0 && !hasDuplicateKey) {
|
|
2890
|
+
if (mismatchCount === 0) {
|
|
2891
|
+
skipReconcile = true;
|
|
2892
|
+
updateNodeBuffer = false;
|
|
2893
|
+
} else if (mismatchCount === 2 && prevOrderedBlocks[mismatchFirst] === nextOrderedBlocks[mismatchSecond] && prevOrderedBlocks[mismatchSecond] === nextOrderedBlocks[mismatchFirst]) {
|
|
2894
|
+
if (reorderBySwap(
|
|
2895
|
+
parent,
|
|
2896
|
+
prevOrderedBlocks[mismatchFirst],
|
|
2897
|
+
prevOrderedBlocks[mismatchSecond]
|
|
2898
|
+
)) {
|
|
2899
|
+
skipReconcile = true;
|
|
2900
|
+
}
|
|
2901
|
+
} else if (reorderByLIS(parent, container.endMarker, prevOrderedBlocks, nextOrderedBlocks)) {
|
|
2902
|
+
skipReconcile = true;
|
|
2903
|
+
}
|
|
2904
|
+
}
|
|
2905
|
+
if (!skipReconcile && (newBlocks.size > 0 || container.currentNodes.length > 0)) {
|
|
2669
2906
|
const prevNodes = container.currentNodes;
|
|
2670
2907
|
const nextNodes = container.nextNodes;
|
|
2671
2908
|
nextNodes.length = 0;
|
|
@@ -2680,6 +2917,20 @@ function createFineGrainedKeyedList(getItems, keyFn, renderItem, needsIndex) {
|
|
|
2680
2917
|
reconcileArrays(parent, prevNodes, nextNodes);
|
|
2681
2918
|
container.currentNodes = nextNodes;
|
|
2682
2919
|
container.nextNodes = prevNodes;
|
|
2920
|
+
} else if (skipReconcile && updateNodeBuffer) {
|
|
2921
|
+
const prevNodes = container.currentNodes;
|
|
2922
|
+
const nextNodes = container.nextNodes;
|
|
2923
|
+
nextNodes.length = 0;
|
|
2924
|
+
nextNodes.push(container.startMarker);
|
|
2925
|
+
for (let i = 0; i < nextOrderedBlocks.length; i++) {
|
|
2926
|
+
const nodes = nextOrderedBlocks[i].nodes;
|
|
2927
|
+
for (let j = 0; j < nodes.length; j++) {
|
|
2928
|
+
nextNodes.push(nodes[j]);
|
|
2929
|
+
}
|
|
2930
|
+
}
|
|
2931
|
+
nextNodes.push(container.endMarker);
|
|
2932
|
+
container.currentNodes = nextNodes;
|
|
2933
|
+
container.nextNodes = prevNodes;
|
|
2683
2934
|
}
|
|
2684
2935
|
container.blocks = newBlocks;
|
|
2685
2936
|
container.nextBlocks = oldBlocks;
|
|
@@ -3321,7 +3572,9 @@ function bindEvent(el, eventName, handler, options2) {
|
|
|
3321
3572
|
const fn = resolveHandler();
|
|
3322
3573
|
callEventHandler(fn, args[0], el);
|
|
3323
3574
|
} catch (err) {
|
|
3324
|
-
handleError(err, { source: "event", eventName }, rootRef)
|
|
3575
|
+
if (!handleError(err, { source: "event", eventName }, rootRef)) {
|
|
3576
|
+
throw err;
|
|
3577
|
+
}
|
|
3325
3578
|
}
|
|
3326
3579
|
};
|
|
3327
3580
|
return () => {
|
|
@@ -4099,10 +4352,12 @@ function ErrorBoundary(props) {
|
|
|
4099
4352
|
renderingFallback = true;
|
|
4100
4353
|
try {
|
|
4101
4354
|
renderValue(toView(err));
|
|
4102
|
-
} finally {
|
|
4103
4355
|
renderingFallback = false;
|
|
4356
|
+
props.onError?.(err);
|
|
4357
|
+
} catch (fallbackErr) {
|
|
4358
|
+
props.onError?.(err);
|
|
4359
|
+
throw fallbackErr;
|
|
4104
4360
|
}
|
|
4105
|
-
props.onError?.(err);
|
|
4106
4361
|
return;
|
|
4107
4362
|
}
|
|
4108
4363
|
popRoot(prev);
|
|
@@ -4197,7 +4452,9 @@ function Suspense(props) {
|
|
|
4197
4452
|
popRoot(prev);
|
|
4198
4453
|
flushOnMount(root);
|
|
4199
4454
|
destroyRoot(root);
|
|
4200
|
-
handleError(err, { source: "render" })
|
|
4455
|
+
if (!handleError(err, { source: "render" }, hostRoot)) {
|
|
4456
|
+
throw err;
|
|
4457
|
+
}
|
|
4201
4458
|
return;
|
|
4202
4459
|
}
|
|
4203
4460
|
popRoot(prev);
|
|
@@ -4227,18 +4484,26 @@ function Suspense(props) {
|
|
|
4227
4484
|
if (thenable) {
|
|
4228
4485
|
thenable.then(
|
|
4229
4486
|
() => {
|
|
4230
|
-
if (epoch !== tokenEpoch)
|
|
4231
|
-
|
|
4232
|
-
|
|
4487
|
+
if (epoch !== tokenEpoch) {
|
|
4488
|
+
return;
|
|
4489
|
+
}
|
|
4490
|
+
const newPending = Math.max(0, pending() - 1);
|
|
4491
|
+
pending(newPending);
|
|
4492
|
+
if (newPending === 0) {
|
|
4233
4493
|
switchView(props.children ?? null);
|
|
4234
4494
|
onResolveMaybe();
|
|
4235
4495
|
}
|
|
4236
4496
|
},
|
|
4237
4497
|
(err) => {
|
|
4238
|
-
if (epoch !== tokenEpoch)
|
|
4239
|
-
|
|
4498
|
+
if (epoch !== tokenEpoch) {
|
|
4499
|
+
return;
|
|
4500
|
+
}
|
|
4501
|
+
const newPending = Math.max(0, pending() - 1);
|
|
4502
|
+
pending(newPending);
|
|
4240
4503
|
props.onReject?.(err);
|
|
4241
|
-
handleError(err, { source: "render" }, hostRoot)
|
|
4504
|
+
if (!handleError(err, { source: "render" }, hostRoot)) {
|
|
4505
|
+
throw err;
|
|
4506
|
+
}
|
|
4242
4507
|
}
|
|
4243
4508
|
);
|
|
4244
4509
|
return true;
|