@fictjs/runtime 0.0.9 → 0.0.11
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 +398 -204
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.dev.js +400 -204
- package/dist/index.dev.js.map +1 -1
- package/dist/index.js +398 -204
- package/dist/index.js.map +1 -1
- package/dist/slim.cjs +398 -204
- package/dist/slim.cjs.map +1 -1
- package/dist/slim.d.cts +1 -0
- package/dist/slim.d.ts +1 -0
- package/dist/slim.js +398 -204
- package/dist/slim.js.map +1 -1
- package/package.json +1 -1
- package/src/binding.ts +41 -13
- package/src/dom.ts +16 -6
- package/src/effect.ts +18 -6
- package/src/hooks.ts +14 -1
- package/src/list-helpers.ts +125 -47
- package/src/signal.ts +102 -4
package/dist/slim.js
CHANGED
|
@@ -305,6 +305,7 @@ var lowPriorityQueue = [];
|
|
|
305
305
|
var enqueueMicrotask = typeof queueMicrotask === "function" ? queueMicrotask : (fn) => {
|
|
306
306
|
Promise.resolve().then(fn);
|
|
307
307
|
};
|
|
308
|
+
var inCleanup = false;
|
|
308
309
|
function link(dep, sub, version) {
|
|
309
310
|
const prevDep = sub.depsTail;
|
|
310
311
|
if (prevDep !== void 0 && prevDep.dep === dep) return;
|
|
@@ -550,7 +551,15 @@ function updateComputed(c) {
|
|
|
550
551
|
}
|
|
551
552
|
function runEffect(e) {
|
|
552
553
|
const flags = e.flags;
|
|
553
|
-
if (flags & Dirty
|
|
554
|
+
if (flags & Dirty) {
|
|
555
|
+
if (e.runCleanup) {
|
|
556
|
+
inCleanup = true;
|
|
557
|
+
try {
|
|
558
|
+
e.runCleanup();
|
|
559
|
+
} finally {
|
|
560
|
+
inCleanup = false;
|
|
561
|
+
}
|
|
562
|
+
}
|
|
554
563
|
++cycle;
|
|
555
564
|
effectRunDevtools(e);
|
|
556
565
|
e.depsTail = void 0;
|
|
@@ -567,6 +576,35 @@ function runEffect(e) {
|
|
|
567
576
|
e.flags = Watching;
|
|
568
577
|
throw err;
|
|
569
578
|
}
|
|
579
|
+
} else if (flags & Pending && e.deps) {
|
|
580
|
+
if (e.runCleanup) {
|
|
581
|
+
inCleanup = true;
|
|
582
|
+
try {
|
|
583
|
+
e.runCleanup();
|
|
584
|
+
} finally {
|
|
585
|
+
inCleanup = false;
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
if (checkDirty(e.deps, e)) {
|
|
589
|
+
++cycle;
|
|
590
|
+
effectRunDevtools(e);
|
|
591
|
+
e.depsTail = void 0;
|
|
592
|
+
e.flags = WatchingRunning;
|
|
593
|
+
const prevSub = activeSub;
|
|
594
|
+
activeSub = e;
|
|
595
|
+
try {
|
|
596
|
+
e.fn();
|
|
597
|
+
activeSub = prevSub;
|
|
598
|
+
e.flags = Watching;
|
|
599
|
+
purgeDeps(e);
|
|
600
|
+
} catch (err) {
|
|
601
|
+
activeSub = prevSub;
|
|
602
|
+
e.flags = Watching;
|
|
603
|
+
throw err;
|
|
604
|
+
}
|
|
605
|
+
} else {
|
|
606
|
+
e.flags = Watching;
|
|
607
|
+
}
|
|
570
608
|
} else {
|
|
571
609
|
e.flags = Watching;
|
|
572
610
|
}
|
|
@@ -662,7 +700,7 @@ function signalOper(value) {
|
|
|
662
700
|
return;
|
|
663
701
|
}
|
|
664
702
|
const flags = this.flags;
|
|
665
|
-
if (flags & Dirty) {
|
|
703
|
+
if (flags & Dirty && !inCleanup) {
|
|
666
704
|
if (updateSignal(this)) {
|
|
667
705
|
const subs = this.subs;
|
|
668
706
|
if (subs !== void 0) shallowPropagate(subs);
|
|
@@ -744,6 +782,30 @@ function effect(fn) {
|
|
|
744
782
|
}
|
|
745
783
|
return effectOper.bind(e);
|
|
746
784
|
}
|
|
785
|
+
function effectWithCleanup(fn, cleanupRunner) {
|
|
786
|
+
const e = {
|
|
787
|
+
fn,
|
|
788
|
+
subs: void 0,
|
|
789
|
+
subsTail: void 0,
|
|
790
|
+
deps: void 0,
|
|
791
|
+
depsTail: void 0,
|
|
792
|
+
flags: WatchingRunning,
|
|
793
|
+
runCleanup: cleanupRunner,
|
|
794
|
+
__id: void 0
|
|
795
|
+
};
|
|
796
|
+
registerEffectDevtools(e);
|
|
797
|
+
const prevSub = activeSub;
|
|
798
|
+
if (prevSub !== void 0) link(e, prevSub, 0);
|
|
799
|
+
activeSub = e;
|
|
800
|
+
try {
|
|
801
|
+
effectRunDevtools(e);
|
|
802
|
+
fn();
|
|
803
|
+
} finally {
|
|
804
|
+
activeSub = prevSub;
|
|
805
|
+
e.flags &= ~Running;
|
|
806
|
+
}
|
|
807
|
+
return effectOper.bind(e);
|
|
808
|
+
}
|
|
747
809
|
function effectOper() {
|
|
748
810
|
disposeNode(this);
|
|
749
811
|
}
|
|
@@ -764,10 +826,17 @@ function effectScopeOper() {
|
|
|
764
826
|
}
|
|
765
827
|
function batch(fn) {
|
|
766
828
|
++batchDepth;
|
|
829
|
+
let hasError = false;
|
|
767
830
|
try {
|
|
768
831
|
return fn();
|
|
832
|
+
} catch (e) {
|
|
833
|
+
hasError = true;
|
|
834
|
+
throw e;
|
|
769
835
|
} finally {
|
|
770
|
-
|
|
836
|
+
--batchDepth;
|
|
837
|
+
if (!hasError && batchDepth === 0) {
|
|
838
|
+
flush();
|
|
839
|
+
}
|
|
771
840
|
}
|
|
772
841
|
}
|
|
773
842
|
function setActiveSub(sub) {
|
|
@@ -818,7 +887,7 @@ function effectRunDevtools(node) {
|
|
|
818
887
|
function createSelector(source, equalityFn = (a, b) => a === b) {
|
|
819
888
|
let current = source();
|
|
820
889
|
const observers = /* @__PURE__ */ new Map();
|
|
821
|
-
effect(() => {
|
|
890
|
+
const dispose = effect(() => {
|
|
822
891
|
const next = source();
|
|
823
892
|
if (equalityFn(current, next)) return;
|
|
824
893
|
const prevSig = observers.get(current);
|
|
@@ -827,6 +896,10 @@ function createSelector(source, equalityFn = (a, b) => a === b) {
|
|
|
827
896
|
if (nextSig) nextSig(true);
|
|
828
897
|
current = next;
|
|
829
898
|
});
|
|
899
|
+
registerRootCleanup(() => {
|
|
900
|
+
dispose();
|
|
901
|
+
observers.clear();
|
|
902
|
+
});
|
|
830
903
|
return (key) => {
|
|
831
904
|
let sig = observers.get(key);
|
|
832
905
|
if (!sig) {
|
|
@@ -847,8 +920,11 @@ function createMemo(fn) {
|
|
|
847
920
|
function createEffect(fn) {
|
|
848
921
|
let cleanups = [];
|
|
849
922
|
const rootForError = getCurrentRoot();
|
|
850
|
-
const
|
|
923
|
+
const doCleanup = () => {
|
|
851
924
|
runCleanupList(cleanups);
|
|
925
|
+
cleanups = [];
|
|
926
|
+
};
|
|
927
|
+
const run = () => {
|
|
852
928
|
const bucket = [];
|
|
853
929
|
withEffectCleanups(bucket, () => {
|
|
854
930
|
try {
|
|
@@ -865,7 +941,7 @@ function createEffect(fn) {
|
|
|
865
941
|
});
|
|
866
942
|
cleanups = bucket;
|
|
867
943
|
};
|
|
868
|
-
const disposeEffect =
|
|
944
|
+
const disposeEffect = effectWithCleanup(run, doCleanup);
|
|
869
945
|
const teardown = () => {
|
|
870
946
|
runCleanupList(cleanups);
|
|
871
947
|
disposeEffect();
|
|
@@ -876,24 +952,27 @@ function createEffect(fn) {
|
|
|
876
952
|
function createRenderEffect(fn) {
|
|
877
953
|
let cleanup;
|
|
878
954
|
const rootForError = getCurrentRoot();
|
|
879
|
-
const
|
|
955
|
+
const doCleanup = () => {
|
|
880
956
|
if (cleanup) {
|
|
881
957
|
cleanup();
|
|
882
958
|
cleanup = void 0;
|
|
883
959
|
}
|
|
960
|
+
};
|
|
961
|
+
const run = () => {
|
|
884
962
|
try {
|
|
885
963
|
const maybeCleanup = fn();
|
|
886
964
|
if (typeof maybeCleanup === "function") {
|
|
887
965
|
cleanup = maybeCleanup;
|
|
888
966
|
}
|
|
889
967
|
} catch (err) {
|
|
890
|
-
|
|
968
|
+
const handled = handleError(err, { source: "effect" }, rootForError);
|
|
969
|
+
if (handled) {
|
|
891
970
|
return;
|
|
892
971
|
}
|
|
893
972
|
throw err;
|
|
894
973
|
}
|
|
895
974
|
};
|
|
896
|
-
const disposeEffect =
|
|
975
|
+
const disposeEffect = effectWithCleanup(run, doCleanup);
|
|
897
976
|
const teardown = () => {
|
|
898
977
|
if (cleanup) {
|
|
899
978
|
cleanup();
|
|
@@ -1279,159 +1358,22 @@ var UnitlessStyles = /* @__PURE__ */ new Set([
|
|
|
1279
1358
|
// src/jsx.ts
|
|
1280
1359
|
var Fragment = Symbol("Fragment");
|
|
1281
1360
|
|
|
1282
|
-
// src/node-ops.ts
|
|
1283
|
-
function toNodeArray(node) {
|
|
1284
|
-
try {
|
|
1285
|
-
if (Array.isArray(node)) {
|
|
1286
|
-
let allNodes = true;
|
|
1287
|
-
for (const item of node) {
|
|
1288
|
-
let isItemNode = false;
|
|
1289
|
-
try {
|
|
1290
|
-
isItemNode = item instanceof Node;
|
|
1291
|
-
} catch {
|
|
1292
|
-
isItemNode = false;
|
|
1293
|
-
}
|
|
1294
|
-
if (!isItemNode) {
|
|
1295
|
-
allNodes = false;
|
|
1296
|
-
break;
|
|
1297
|
-
}
|
|
1298
|
-
}
|
|
1299
|
-
if (allNodes) {
|
|
1300
|
-
return node;
|
|
1301
|
-
}
|
|
1302
|
-
const result = [];
|
|
1303
|
-
for (const item of node) {
|
|
1304
|
-
result.push(...toNodeArray(item));
|
|
1305
|
-
}
|
|
1306
|
-
return result;
|
|
1307
|
-
}
|
|
1308
|
-
if (node === null || node === void 0 || node === false) {
|
|
1309
|
-
return [];
|
|
1310
|
-
}
|
|
1311
|
-
} catch {
|
|
1312
|
-
return [];
|
|
1313
|
-
}
|
|
1314
|
-
let isNode = false;
|
|
1315
|
-
try {
|
|
1316
|
-
isNode = node instanceof Node;
|
|
1317
|
-
} catch {
|
|
1318
|
-
isNode = false;
|
|
1319
|
-
}
|
|
1320
|
-
if (isNode) {
|
|
1321
|
-
try {
|
|
1322
|
-
if (node instanceof DocumentFragment) {
|
|
1323
|
-
return Array.from(node.childNodes);
|
|
1324
|
-
}
|
|
1325
|
-
} catch {
|
|
1326
|
-
}
|
|
1327
|
-
return [node];
|
|
1328
|
-
}
|
|
1329
|
-
try {
|
|
1330
|
-
if (typeof node === "object" && node !== null && "marker" in node) {
|
|
1331
|
-
return toNodeArray(node.marker);
|
|
1332
|
-
}
|
|
1333
|
-
} catch {
|
|
1334
|
-
}
|
|
1335
|
-
try {
|
|
1336
|
-
return [document.createTextNode(String(node))];
|
|
1337
|
-
} catch {
|
|
1338
|
-
return [document.createTextNode("")];
|
|
1339
|
-
}
|
|
1340
|
-
}
|
|
1341
|
-
function insertNodesBefore(parent, nodes, anchor) {
|
|
1342
|
-
if (nodes.length === 0) return;
|
|
1343
|
-
if (nodes.length === 1) {
|
|
1344
|
-
const node = nodes[0];
|
|
1345
|
-
if (node === void 0 || node === null) return;
|
|
1346
|
-
if (node.ownerDocument !== parent.ownerDocument && parent.ownerDocument) {
|
|
1347
|
-
parent.ownerDocument.adoptNode(node);
|
|
1348
|
-
}
|
|
1349
|
-
try {
|
|
1350
|
-
parent.insertBefore(node, anchor);
|
|
1351
|
-
} catch (e) {
|
|
1352
|
-
if (parent.ownerDocument) {
|
|
1353
|
-
try {
|
|
1354
|
-
const clone = parent.ownerDocument.importNode(node, true);
|
|
1355
|
-
parent.insertBefore(clone, anchor);
|
|
1356
|
-
return;
|
|
1357
|
-
} catch {
|
|
1358
|
-
}
|
|
1359
|
-
}
|
|
1360
|
-
throw e;
|
|
1361
|
-
}
|
|
1362
|
-
return;
|
|
1363
|
-
}
|
|
1364
|
-
const doc = parent.ownerDocument;
|
|
1365
|
-
if (doc) {
|
|
1366
|
-
const frag = doc.createDocumentFragment();
|
|
1367
|
-
for (let i = 0; i < nodes.length; i++) {
|
|
1368
|
-
const node = nodes[i];
|
|
1369
|
-
if (node === void 0 || node === null) continue;
|
|
1370
|
-
if (node.nodeType === 11) {
|
|
1371
|
-
const childrenArr = Array.from(node.childNodes);
|
|
1372
|
-
for (let j = 0; j < childrenArr.length; j++) {
|
|
1373
|
-
frag.appendChild(childrenArr[j]);
|
|
1374
|
-
}
|
|
1375
|
-
} else {
|
|
1376
|
-
if (node.ownerDocument !== doc) {
|
|
1377
|
-
doc.adoptNode(node);
|
|
1378
|
-
}
|
|
1379
|
-
frag.appendChild(node);
|
|
1380
|
-
}
|
|
1381
|
-
}
|
|
1382
|
-
parent.insertBefore(frag, anchor);
|
|
1383
|
-
return;
|
|
1384
|
-
}
|
|
1385
|
-
const insertSingle = (nodeToInsert, anchorNode) => {
|
|
1386
|
-
if (nodeToInsert.ownerDocument !== parent.ownerDocument && parent.ownerDocument) {
|
|
1387
|
-
parent.ownerDocument.adoptNode(nodeToInsert);
|
|
1388
|
-
}
|
|
1389
|
-
try {
|
|
1390
|
-
parent.insertBefore(nodeToInsert, anchorNode);
|
|
1391
|
-
return nodeToInsert;
|
|
1392
|
-
} catch (e) {
|
|
1393
|
-
if (parent.ownerDocument) {
|
|
1394
|
-
try {
|
|
1395
|
-
const clone = parent.ownerDocument.importNode(nodeToInsert, true);
|
|
1396
|
-
parent.insertBefore(clone, anchorNode);
|
|
1397
|
-
return clone;
|
|
1398
|
-
} catch {
|
|
1399
|
-
}
|
|
1400
|
-
}
|
|
1401
|
-
throw e;
|
|
1402
|
-
}
|
|
1403
|
-
};
|
|
1404
|
-
for (let i = nodes.length - 1; i >= 0; i--) {
|
|
1405
|
-
const node = nodes[i];
|
|
1406
|
-
if (node === void 0 || node === null) continue;
|
|
1407
|
-
const isFrag = node.nodeType === 11;
|
|
1408
|
-
if (isFrag) {
|
|
1409
|
-
const childrenArr = Array.from(node.childNodes);
|
|
1410
|
-
for (let j = childrenArr.length - 1; j >= 0; j--) {
|
|
1411
|
-
const child = childrenArr[j];
|
|
1412
|
-
anchor = insertSingle(child, anchor);
|
|
1413
|
-
}
|
|
1414
|
-
} else {
|
|
1415
|
-
anchor = insertSingle(node, anchor);
|
|
1416
|
-
}
|
|
1417
|
-
}
|
|
1418
|
-
}
|
|
1419
|
-
function removeNodes(nodes) {
|
|
1420
|
-
for (const node of nodes) {
|
|
1421
|
-
node.parentNode?.removeChild(node);
|
|
1422
|
-
}
|
|
1423
|
-
}
|
|
1424
|
-
|
|
1425
1361
|
// src/hooks.ts
|
|
1426
1362
|
var ctxStack = [];
|
|
1363
|
+
function assertRenderContext(ctx, hookName) {
|
|
1364
|
+
if (!ctx.rendering) {
|
|
1365
|
+
throw new Error(`${hookName} can only be used during render execution`);
|
|
1366
|
+
}
|
|
1367
|
+
}
|
|
1427
1368
|
function __fictUseContext() {
|
|
1428
1369
|
if (ctxStack.length === 0) {
|
|
1429
|
-
const ctx2 = { slots: [], cursor: 0 };
|
|
1370
|
+
const ctx2 = { slots: [], cursor: 0, rendering: true };
|
|
1430
1371
|
ctxStack.push(ctx2);
|
|
1431
1372
|
return ctx2;
|
|
1432
1373
|
}
|
|
1433
1374
|
const ctx = ctxStack[ctxStack.length - 1];
|
|
1434
1375
|
ctx.cursor = 0;
|
|
1376
|
+
ctx.rendering = true;
|
|
1435
1377
|
return ctx;
|
|
1436
1378
|
}
|
|
1437
1379
|
function __fictPushContext() {
|
|
@@ -1446,6 +1388,7 @@ function __fictResetContext() {
|
|
|
1446
1388
|
ctxStack.length = 0;
|
|
1447
1389
|
}
|
|
1448
1390
|
function __fictUseSignal(ctx, initial, slot) {
|
|
1391
|
+
assertRenderContext(ctx, "__fictUseSignal");
|
|
1449
1392
|
const index = slot ?? ctx.cursor++;
|
|
1450
1393
|
if (!ctx.slots[index]) {
|
|
1451
1394
|
ctx.slots[index] = signal(initial);
|
|
@@ -1453,6 +1396,7 @@ function __fictUseSignal(ctx, initial, slot) {
|
|
|
1453
1396
|
return ctx.slots[index];
|
|
1454
1397
|
}
|
|
1455
1398
|
function __fictUseMemo(ctx, fn, slot) {
|
|
1399
|
+
assertRenderContext(ctx, "__fictUseMemo");
|
|
1456
1400
|
const index = slot ?? ctx.cursor++;
|
|
1457
1401
|
if (!ctx.slots[index]) {
|
|
1458
1402
|
ctx.slots[index] = createMemo(fn);
|
|
@@ -1460,6 +1404,7 @@ function __fictUseMemo(ctx, fn, slot) {
|
|
|
1460
1404
|
return ctx.slots[index];
|
|
1461
1405
|
}
|
|
1462
1406
|
function __fictUseEffect(ctx, fn, slot) {
|
|
1407
|
+
assertRenderContext(ctx, "__fictUseEffect");
|
|
1463
1408
|
const index = slot ?? ctx.cursor++;
|
|
1464
1409
|
if (!ctx.slots[index]) {
|
|
1465
1410
|
ctx.slots[index] = createEffect(fn);
|
|
@@ -1468,9 +1413,11 @@ function __fictUseEffect(ctx, fn, slot) {
|
|
|
1468
1413
|
function __fictRender(ctx, fn) {
|
|
1469
1414
|
ctxStack.push(ctx);
|
|
1470
1415
|
ctx.cursor = 0;
|
|
1416
|
+
ctx.rendering = true;
|
|
1471
1417
|
try {
|
|
1472
1418
|
return fn();
|
|
1473
1419
|
} finally {
|
|
1420
|
+
ctx.rendering = false;
|
|
1474
1421
|
ctxStack.pop();
|
|
1475
1422
|
}
|
|
1476
1423
|
}
|
|
@@ -1673,6 +1620,14 @@ function createElementWithContext(node, namespace) {
|
|
|
1673
1620
|
if (typeof handle.dispose === "function") {
|
|
1674
1621
|
registerRootCleanup(handle.dispose);
|
|
1675
1622
|
}
|
|
1623
|
+
if (typeof handle.flush === "function") {
|
|
1624
|
+
const runFlush = () => handle.flush && handle.flush();
|
|
1625
|
+
if (typeof queueMicrotask === "function") {
|
|
1626
|
+
queueMicrotask(runFlush);
|
|
1627
|
+
} else {
|
|
1628
|
+
Promise.resolve().then(runFlush).catch(() => void 0);
|
|
1629
|
+
}
|
|
1630
|
+
}
|
|
1676
1631
|
return createElement(handle.marker);
|
|
1677
1632
|
}
|
|
1678
1633
|
const nodeRecord = node;
|
|
@@ -1720,18 +1675,18 @@ function createElementWithContext(node, namespace) {
|
|
|
1720
1675
|
}
|
|
1721
1676
|
});
|
|
1722
1677
|
const props = createPropsProxy(baseProps);
|
|
1678
|
+
__fictPushContext();
|
|
1723
1679
|
try {
|
|
1724
|
-
__fictPushContext();
|
|
1725
1680
|
const rendered = vnode.type(props);
|
|
1726
|
-
__fictPopContext();
|
|
1727
1681
|
return createElementWithContext(rendered, namespace);
|
|
1728
1682
|
} catch (err) {
|
|
1729
|
-
__fictPopContext();
|
|
1730
1683
|
if (handleSuspend(err)) {
|
|
1731
1684
|
return document.createComment("fict:suspend");
|
|
1732
1685
|
}
|
|
1733
1686
|
handleError(err, { source: "render", componentName: vnode.type.name });
|
|
1734
1687
|
throw err;
|
|
1688
|
+
} finally {
|
|
1689
|
+
__fictPopContext();
|
|
1735
1690
|
}
|
|
1736
1691
|
}
|
|
1737
1692
|
if (vnode.type === Fragment) {
|
|
@@ -2023,6 +1978,149 @@ function eventNameFromProp(key) {
|
|
|
2023
1978
|
return key.slice(2).toLowerCase();
|
|
2024
1979
|
}
|
|
2025
1980
|
|
|
1981
|
+
// src/node-ops.ts
|
|
1982
|
+
function toNodeArray(node) {
|
|
1983
|
+
try {
|
|
1984
|
+
if (Array.isArray(node)) {
|
|
1985
|
+
let allNodes = true;
|
|
1986
|
+
for (const item of node) {
|
|
1987
|
+
let isItemNode = false;
|
|
1988
|
+
try {
|
|
1989
|
+
isItemNode = item instanceof Node;
|
|
1990
|
+
} catch {
|
|
1991
|
+
isItemNode = false;
|
|
1992
|
+
}
|
|
1993
|
+
if (!isItemNode) {
|
|
1994
|
+
allNodes = false;
|
|
1995
|
+
break;
|
|
1996
|
+
}
|
|
1997
|
+
}
|
|
1998
|
+
if (allNodes) {
|
|
1999
|
+
return node;
|
|
2000
|
+
}
|
|
2001
|
+
const result = [];
|
|
2002
|
+
for (const item of node) {
|
|
2003
|
+
result.push(...toNodeArray(item));
|
|
2004
|
+
}
|
|
2005
|
+
return result;
|
|
2006
|
+
}
|
|
2007
|
+
if (node === null || node === void 0 || node === false) {
|
|
2008
|
+
return [];
|
|
2009
|
+
}
|
|
2010
|
+
} catch {
|
|
2011
|
+
return [];
|
|
2012
|
+
}
|
|
2013
|
+
let isNode = false;
|
|
2014
|
+
try {
|
|
2015
|
+
isNode = node instanceof Node;
|
|
2016
|
+
} catch {
|
|
2017
|
+
isNode = false;
|
|
2018
|
+
}
|
|
2019
|
+
if (isNode) {
|
|
2020
|
+
try {
|
|
2021
|
+
if (node instanceof DocumentFragment) {
|
|
2022
|
+
return Array.from(node.childNodes);
|
|
2023
|
+
}
|
|
2024
|
+
} catch {
|
|
2025
|
+
}
|
|
2026
|
+
return [node];
|
|
2027
|
+
}
|
|
2028
|
+
try {
|
|
2029
|
+
if (typeof node === "object" && node !== null && "marker" in node) {
|
|
2030
|
+
return toNodeArray(node.marker);
|
|
2031
|
+
}
|
|
2032
|
+
} catch {
|
|
2033
|
+
}
|
|
2034
|
+
try {
|
|
2035
|
+
return [document.createTextNode(String(node))];
|
|
2036
|
+
} catch {
|
|
2037
|
+
return [document.createTextNode("")];
|
|
2038
|
+
}
|
|
2039
|
+
}
|
|
2040
|
+
function insertNodesBefore(parent, nodes, anchor) {
|
|
2041
|
+
if (nodes.length === 0) return;
|
|
2042
|
+
if (nodes.length === 1) {
|
|
2043
|
+
const node = nodes[0];
|
|
2044
|
+
if (node === void 0 || node === null) return;
|
|
2045
|
+
if (node.ownerDocument !== parent.ownerDocument && parent.ownerDocument) {
|
|
2046
|
+
parent.ownerDocument.adoptNode(node);
|
|
2047
|
+
}
|
|
2048
|
+
try {
|
|
2049
|
+
parent.insertBefore(node, anchor);
|
|
2050
|
+
} catch (e) {
|
|
2051
|
+
if (parent.ownerDocument) {
|
|
2052
|
+
try {
|
|
2053
|
+
const clone = parent.ownerDocument.importNode(node, true);
|
|
2054
|
+
parent.insertBefore(clone, anchor);
|
|
2055
|
+
return;
|
|
2056
|
+
} catch {
|
|
2057
|
+
}
|
|
2058
|
+
}
|
|
2059
|
+
throw e;
|
|
2060
|
+
}
|
|
2061
|
+
return;
|
|
2062
|
+
}
|
|
2063
|
+
const doc = parent.ownerDocument;
|
|
2064
|
+
if (doc) {
|
|
2065
|
+
const frag = doc.createDocumentFragment();
|
|
2066
|
+
for (let i = 0; i < nodes.length; i++) {
|
|
2067
|
+
const node = nodes[i];
|
|
2068
|
+
if (node === void 0 || node === null) continue;
|
|
2069
|
+
if (node.nodeType === 11) {
|
|
2070
|
+
const childrenArr = Array.from(node.childNodes);
|
|
2071
|
+
for (let j = 0; j < childrenArr.length; j++) {
|
|
2072
|
+
frag.appendChild(childrenArr[j]);
|
|
2073
|
+
}
|
|
2074
|
+
} else {
|
|
2075
|
+
if (node.ownerDocument !== doc) {
|
|
2076
|
+
doc.adoptNode(node);
|
|
2077
|
+
}
|
|
2078
|
+
frag.appendChild(node);
|
|
2079
|
+
}
|
|
2080
|
+
}
|
|
2081
|
+
parent.insertBefore(frag, anchor);
|
|
2082
|
+
return;
|
|
2083
|
+
}
|
|
2084
|
+
const insertSingle = (nodeToInsert, anchorNode) => {
|
|
2085
|
+
if (nodeToInsert.ownerDocument !== parent.ownerDocument && parent.ownerDocument) {
|
|
2086
|
+
parent.ownerDocument.adoptNode(nodeToInsert);
|
|
2087
|
+
}
|
|
2088
|
+
try {
|
|
2089
|
+
parent.insertBefore(nodeToInsert, anchorNode);
|
|
2090
|
+
return nodeToInsert;
|
|
2091
|
+
} catch (e) {
|
|
2092
|
+
if (parent.ownerDocument) {
|
|
2093
|
+
try {
|
|
2094
|
+
const clone = parent.ownerDocument.importNode(nodeToInsert, true);
|
|
2095
|
+
parent.insertBefore(clone, anchorNode);
|
|
2096
|
+
return clone;
|
|
2097
|
+
} catch {
|
|
2098
|
+
}
|
|
2099
|
+
}
|
|
2100
|
+
throw e;
|
|
2101
|
+
}
|
|
2102
|
+
};
|
|
2103
|
+
for (let i = nodes.length - 1; i >= 0; i--) {
|
|
2104
|
+
const node = nodes[i];
|
|
2105
|
+
if (node === void 0 || node === null) continue;
|
|
2106
|
+
const isFrag = node.nodeType === 11;
|
|
2107
|
+
if (isFrag) {
|
|
2108
|
+
const childrenArr = Array.from(node.childNodes);
|
|
2109
|
+
for (let j = childrenArr.length - 1; j >= 0; j--) {
|
|
2110
|
+
const child = childrenArr[j];
|
|
2111
|
+
anchor = insertSingle(child, anchor);
|
|
2112
|
+
}
|
|
2113
|
+
} else {
|
|
2114
|
+
anchor = insertSingle(node, anchor);
|
|
2115
|
+
}
|
|
2116
|
+
}
|
|
2117
|
+
}
|
|
2118
|
+
function removeNodes(nodes) {
|
|
2119
|
+
for (const node of nodes) {
|
|
2120
|
+
node.parentNode?.removeChild(node);
|
|
2121
|
+
}
|
|
2122
|
+
}
|
|
2123
|
+
|
|
2026
2124
|
// src/reconcile.ts
|
|
2027
2125
|
function reconcileArrays(parentNode, a, b) {
|
|
2028
2126
|
const bLength = b.length;
|
|
@@ -2250,7 +2348,6 @@ function createKeyedBlock(key, item, index, render2, needsIndex = true, hostRoot
|
|
|
2250
2348
|
} finally {
|
|
2251
2349
|
setActiveSub(prevSub);
|
|
2252
2350
|
popRoot(prevRoot);
|
|
2253
|
-
flushOnMount(root);
|
|
2254
2351
|
}
|
|
2255
2352
|
return {
|
|
2256
2353
|
key,
|
|
@@ -2274,13 +2371,24 @@ function createFineGrainedKeyedList(getItems, keyFn, renderItem, needsIndex) {
|
|
|
2274
2371
|
const hostRoot = getCurrentRoot();
|
|
2275
2372
|
const fragment = document.createDocumentFragment();
|
|
2276
2373
|
fragment.append(container.startMarker, container.endMarker);
|
|
2277
|
-
let pendingItems = null;
|
|
2278
2374
|
let disposed = false;
|
|
2375
|
+
let effectDispose;
|
|
2376
|
+
let connectObserver = null;
|
|
2377
|
+
let effectStarted = false;
|
|
2378
|
+
let startScheduled = false;
|
|
2379
|
+
const getConnectedParent = () => {
|
|
2380
|
+
const endParent = container.endMarker.parentNode;
|
|
2381
|
+
const startParent = container.startMarker.parentNode;
|
|
2382
|
+
if (endParent && startParent && endParent === startParent && endParent.nodeType !== 11) {
|
|
2383
|
+
return endParent;
|
|
2384
|
+
}
|
|
2385
|
+
return null;
|
|
2386
|
+
};
|
|
2279
2387
|
const performDiff = () => {
|
|
2280
2388
|
if (disposed) return;
|
|
2389
|
+
const parent = getConnectedParent();
|
|
2390
|
+
if (!parent) return;
|
|
2281
2391
|
batch2(() => {
|
|
2282
|
-
const newItems = pendingItems || getItems();
|
|
2283
|
-
pendingItems = null;
|
|
2284
2392
|
const oldBlocks = container.blocks;
|
|
2285
2393
|
const newBlocks = container.nextBlocks;
|
|
2286
2394
|
const prevOrderedBlocks = container.orderedBlocks;
|
|
@@ -2289,20 +2397,17 @@ function createFineGrainedKeyedList(getItems, keyFn, renderItem, needsIndex) {
|
|
|
2289
2397
|
newBlocks.clear();
|
|
2290
2398
|
nextOrderedBlocks.length = 0;
|
|
2291
2399
|
orderedIndexByKey.clear();
|
|
2292
|
-
const
|
|
2293
|
-
const
|
|
2294
|
-
const parent = endParent && startParent && endParent === startParent && endParent.isConnected ? endParent : null;
|
|
2295
|
-
if (!parent) {
|
|
2296
|
-
pendingItems = newItems;
|
|
2297
|
-
queueMicrotask(performDiff);
|
|
2298
|
-
return;
|
|
2299
|
-
}
|
|
2400
|
+
const createdBlocks = [];
|
|
2401
|
+
const newItems = getItems();
|
|
2300
2402
|
if (newItems.length === 0) {
|
|
2301
2403
|
if (oldBlocks.size > 0) {
|
|
2302
2404
|
for (const block of oldBlocks.values()) {
|
|
2303
2405
|
destroyRoot(block.root);
|
|
2304
|
-
removeNodes(block.nodes);
|
|
2305
2406
|
}
|
|
2407
|
+
const range = document.createRange();
|
|
2408
|
+
range.setStartAfter(container.startMarker);
|
|
2409
|
+
range.setEndBefore(container.endMarker);
|
|
2410
|
+
range.deleteContents();
|
|
2306
2411
|
}
|
|
2307
2412
|
oldBlocks.clear();
|
|
2308
2413
|
newBlocks.clear();
|
|
@@ -2319,8 +2424,8 @@ function createFineGrainedKeyedList(getItems, keyFn, renderItem, needsIndex) {
|
|
|
2319
2424
|
const appendedBlocks = [];
|
|
2320
2425
|
newItems.forEach((item, index) => {
|
|
2321
2426
|
const key = keyFn(item, index);
|
|
2322
|
-
const existed = oldBlocks.has(key);
|
|
2323
2427
|
let block = oldBlocks.get(key);
|
|
2428
|
+
const existed = block !== void 0;
|
|
2324
2429
|
if (block) {
|
|
2325
2430
|
if (block.rawItem !== item) {
|
|
2326
2431
|
block.rawItem = item;
|
|
@@ -2331,38 +2436,23 @@ function createFineGrainedKeyedList(getItems, keyFn, renderItem, needsIndex) {
|
|
|
2331
2436
|
block.index(index);
|
|
2332
2437
|
}
|
|
2333
2438
|
}
|
|
2334
|
-
const existingBlock = newBlocks.get(key);
|
|
2335
|
-
if (existingBlock && existingBlock !== block) {
|
|
2336
|
-
destroyRoot(existingBlock.root);
|
|
2337
|
-
removeNodes(existingBlock.nodes);
|
|
2338
|
-
}
|
|
2339
2439
|
if (block) {
|
|
2340
2440
|
newBlocks.set(key, block);
|
|
2341
2441
|
oldBlocks.delete(key);
|
|
2342
2442
|
} else {
|
|
2343
|
-
const
|
|
2344
|
-
if (
|
|
2345
|
-
destroyRoot(
|
|
2346
|
-
removeNodes(
|
|
2443
|
+
const existingBlock = newBlocks.get(key);
|
|
2444
|
+
if (existingBlock) {
|
|
2445
|
+
destroyRoot(existingBlock.root);
|
|
2446
|
+
removeNodes(existingBlock.nodes);
|
|
2347
2447
|
}
|
|
2348
2448
|
block = createKeyedBlock(key, item, index, renderItem, needsIndex, hostRoot);
|
|
2449
|
+
createdBlocks.push(block);
|
|
2349
2450
|
}
|
|
2350
2451
|
const resolvedBlock = block;
|
|
2351
2452
|
newBlocks.set(key, resolvedBlock);
|
|
2352
2453
|
const position = orderedIndexByKey.get(key);
|
|
2353
2454
|
if (position !== void 0) {
|
|
2354
2455
|
appendCandidate = false;
|
|
2355
|
-
}
|
|
2356
|
-
if (appendCandidate) {
|
|
2357
|
-
if (index < prevCount) {
|
|
2358
|
-
if (!prevOrderedBlocks[index] || prevOrderedBlocks[index].key !== key) {
|
|
2359
|
-
appendCandidate = false;
|
|
2360
|
-
}
|
|
2361
|
-
} else if (existed) {
|
|
2362
|
-
appendCandidate = false;
|
|
2363
|
-
}
|
|
2364
|
-
}
|
|
2365
|
-
if (position !== void 0) {
|
|
2366
2456
|
const prior = nextOrderedBlocks[position];
|
|
2367
2457
|
if (prior && prior !== resolvedBlock) {
|
|
2368
2458
|
destroyRoot(prior.root);
|
|
@@ -2370,6 +2460,15 @@ function createFineGrainedKeyedList(getItems, keyFn, renderItem, needsIndex) {
|
|
|
2370
2460
|
}
|
|
2371
2461
|
nextOrderedBlocks[position] = resolvedBlock;
|
|
2372
2462
|
} else {
|
|
2463
|
+
if (appendCandidate) {
|
|
2464
|
+
if (index < prevCount) {
|
|
2465
|
+
if (!prevOrderedBlocks[index] || prevOrderedBlocks[index].key !== key) {
|
|
2466
|
+
appendCandidate = false;
|
|
2467
|
+
}
|
|
2468
|
+
} else if (existed) {
|
|
2469
|
+
appendCandidate = false;
|
|
2470
|
+
}
|
|
2471
|
+
}
|
|
2373
2472
|
orderedIndexByKey.set(key, nextOrderedBlocks.length);
|
|
2374
2473
|
nextOrderedBlocks.push(resolvedBlock);
|
|
2375
2474
|
}
|
|
@@ -2398,6 +2497,11 @@ function createFineGrainedKeyedList(getItems, keyFn, renderItem, needsIndex) {
|
|
|
2398
2497
|
container.nextBlocks = oldBlocks;
|
|
2399
2498
|
container.orderedBlocks = nextOrderedBlocks;
|
|
2400
2499
|
container.nextOrderedBlocks = prevOrderedBlocks;
|
|
2500
|
+
for (const block of createdBlocks) {
|
|
2501
|
+
if (newBlocks.get(block.key) === block) {
|
|
2502
|
+
flushOnMount(block.root);
|
|
2503
|
+
}
|
|
2504
|
+
}
|
|
2401
2505
|
return;
|
|
2402
2506
|
}
|
|
2403
2507
|
if (oldBlocks.size > 0) {
|
|
@@ -2427,22 +2531,87 @@ function createFineGrainedKeyedList(getItems, keyFn, renderItem, needsIndex) {
|
|
|
2427
2531
|
container.nextBlocks = oldBlocks;
|
|
2428
2532
|
container.orderedBlocks = nextOrderedBlocks;
|
|
2429
2533
|
container.nextOrderedBlocks = prevOrderedBlocks;
|
|
2534
|
+
for (const block of createdBlocks) {
|
|
2535
|
+
if (newBlocks.get(block.key) === block) {
|
|
2536
|
+
flushOnMount(block.root);
|
|
2537
|
+
}
|
|
2538
|
+
}
|
|
2539
|
+
});
|
|
2540
|
+
};
|
|
2541
|
+
const disconnectObserver = () => {
|
|
2542
|
+
connectObserver?.disconnect();
|
|
2543
|
+
connectObserver = null;
|
|
2544
|
+
};
|
|
2545
|
+
const ensureEffectStarted = () => {
|
|
2546
|
+
if (disposed || effectStarted) return effectStarted;
|
|
2547
|
+
const parent = getConnectedParent();
|
|
2548
|
+
if (!parent) return false;
|
|
2549
|
+
const start = () => {
|
|
2550
|
+
effectDispose = createRenderEffect(performDiff);
|
|
2551
|
+
effectStarted = true;
|
|
2552
|
+
};
|
|
2553
|
+
if (hostRoot) {
|
|
2554
|
+
const prev = pushRoot(hostRoot);
|
|
2555
|
+
try {
|
|
2556
|
+
start();
|
|
2557
|
+
} finally {
|
|
2558
|
+
popRoot(prev);
|
|
2559
|
+
}
|
|
2560
|
+
} else {
|
|
2561
|
+
start();
|
|
2562
|
+
}
|
|
2563
|
+
return true;
|
|
2564
|
+
};
|
|
2565
|
+
const waitForConnection = () => {
|
|
2566
|
+
if (connectObserver || typeof MutationObserver === "undefined") return;
|
|
2567
|
+
connectObserver = new MutationObserver(() => {
|
|
2568
|
+
if (disposed) return;
|
|
2569
|
+
if (getConnectedParent()) {
|
|
2570
|
+
disconnectObserver();
|
|
2571
|
+
if (ensureEffectStarted()) {
|
|
2572
|
+
flush();
|
|
2573
|
+
}
|
|
2574
|
+
}
|
|
2430
2575
|
});
|
|
2576
|
+
connectObserver.observe(document, { childList: true, subtree: true });
|
|
2577
|
+
};
|
|
2578
|
+
const scheduleStart = () => {
|
|
2579
|
+
if (startScheduled || disposed || effectStarted) return;
|
|
2580
|
+
startScheduled = true;
|
|
2581
|
+
const run = () => {
|
|
2582
|
+
startScheduled = false;
|
|
2583
|
+
if (!ensureEffectStarted()) {
|
|
2584
|
+
waitForConnection();
|
|
2585
|
+
}
|
|
2586
|
+
};
|
|
2587
|
+
if (typeof queueMicrotask === "function") {
|
|
2588
|
+
queueMicrotask(run);
|
|
2589
|
+
} else {
|
|
2590
|
+
Promise.resolve().then(run).catch(() => void 0);
|
|
2591
|
+
}
|
|
2431
2592
|
};
|
|
2432
|
-
|
|
2593
|
+
scheduleStart();
|
|
2433
2594
|
return {
|
|
2434
|
-
marker
|
|
2595
|
+
get marker() {
|
|
2596
|
+
scheduleStart();
|
|
2597
|
+
return fragment;
|
|
2598
|
+
},
|
|
2435
2599
|
startMarker: container.startMarker,
|
|
2436
2600
|
endMarker: container.endMarker,
|
|
2437
2601
|
// Flush pending items - call after markers are inserted into DOM
|
|
2438
2602
|
flush: () => {
|
|
2439
|
-
if (
|
|
2440
|
-
|
|
2603
|
+
if (disposed) return;
|
|
2604
|
+
scheduleStart();
|
|
2605
|
+
if (ensureEffectStarted()) {
|
|
2606
|
+
flush();
|
|
2607
|
+
} else {
|
|
2608
|
+
waitForConnection();
|
|
2441
2609
|
}
|
|
2442
2610
|
},
|
|
2443
2611
|
dispose: () => {
|
|
2444
2612
|
disposed = true;
|
|
2445
2613
|
effectDispose?.();
|
|
2614
|
+
disconnectObserver();
|
|
2446
2615
|
container.dispose();
|
|
2447
2616
|
}
|
|
2448
2617
|
};
|
|
@@ -2614,8 +2783,17 @@ function createClassBinding(el, value) {
|
|
|
2614
2783
|
}
|
|
2615
2784
|
function bindClass(el, getValue) {
|
|
2616
2785
|
let prev = {};
|
|
2786
|
+
let prevString;
|
|
2617
2787
|
return createRenderEffect(() => {
|
|
2618
2788
|
const next = getValue();
|
|
2789
|
+
if (typeof next === "string") {
|
|
2790
|
+
if (next === prevString) return;
|
|
2791
|
+
prevString = next;
|
|
2792
|
+
el.className = next;
|
|
2793
|
+
prev = {};
|
|
2794
|
+
return;
|
|
2795
|
+
}
|
|
2796
|
+
prevString = void 0;
|
|
2619
2797
|
prev = applyClass(el, next, prev);
|
|
2620
2798
|
});
|
|
2621
2799
|
}
|
|
@@ -2841,11 +3019,19 @@ function clearDelegatedEvents(doc = window.document) {
|
|
|
2841
3019
|
}
|
|
2842
3020
|
}
|
|
2843
3021
|
function globalEventHandler(e) {
|
|
2844
|
-
|
|
3022
|
+
const asNode = (value) => value && typeof value.nodeType === "number" ? value : null;
|
|
3023
|
+
const asElement = (value) => {
|
|
3024
|
+
const n = asNode(value);
|
|
3025
|
+
if (!n) return null;
|
|
3026
|
+
if (n.nodeType === 1) return n;
|
|
3027
|
+
return n.parentElement;
|
|
3028
|
+
};
|
|
3029
|
+
let node = asElement(e.target);
|
|
2845
3030
|
const key = `$$${e.type}`;
|
|
2846
3031
|
const dataKey = `${key}Data`;
|
|
2847
3032
|
const oriTarget = e.target;
|
|
2848
3033
|
const oriCurrentTarget = e.currentTarget;
|
|
3034
|
+
let lastHandled = null;
|
|
2849
3035
|
const retarget = (value) => Object.defineProperty(e, "target", {
|
|
2850
3036
|
configurable: true,
|
|
2851
3037
|
value
|
|
@@ -2868,23 +3054,28 @@ function globalEventHandler(e) {
|
|
|
2868
3054
|
const rawData = node[dataKey];
|
|
2869
3055
|
const hasData = rawData !== void 0;
|
|
2870
3056
|
const resolvedNodeData = hasData ? resolveData(rawData) : void 0;
|
|
2871
|
-
|
|
2872
|
-
|
|
2873
|
-
|
|
2874
|
-
|
|
2875
|
-
|
|
2876
|
-
|
|
3057
|
+
batch2(() => {
|
|
3058
|
+
if (typeof handler === "function") {
|
|
3059
|
+
callEventHandler(handler, e, node, hasData ? resolvedNodeData : void 0);
|
|
3060
|
+
} else if (Array.isArray(handler)) {
|
|
3061
|
+
const tupleData = resolveData(handler[1]);
|
|
3062
|
+
callEventHandler(handler[0], e, node, tupleData);
|
|
3063
|
+
}
|
|
3064
|
+
});
|
|
2877
3065
|
if (e.cancelBubble) return false;
|
|
2878
3066
|
}
|
|
2879
3067
|
const shadowHost = node.host;
|
|
2880
|
-
if (shadowHost && typeof shadowHost !== "string" && !shadowHost._$host &&
|
|
3068
|
+
if (shadowHost && typeof shadowHost !== "string" && !shadowHost._$host && (() => {
|
|
3069
|
+
const targetNode = asNode(e.target);
|
|
3070
|
+
return targetNode ? node.contains(targetNode) : false;
|
|
3071
|
+
})()) {
|
|
2881
3072
|
retarget(shadowHost);
|
|
2882
3073
|
}
|
|
2883
3074
|
return true;
|
|
2884
3075
|
};
|
|
2885
3076
|
const walkUpTree = () => {
|
|
2886
3077
|
while (handleNode() && node) {
|
|
2887
|
-
node = node._$host || node.parentNode || node.host;
|
|
3078
|
+
node = asElement(node._$host || node.parentNode || node.host);
|
|
2888
3079
|
}
|
|
2889
3080
|
};
|
|
2890
3081
|
Object.defineProperty(e, "currentTarget", {
|
|
@@ -2897,8 +3088,11 @@ function globalEventHandler(e) {
|
|
|
2897
3088
|
const path = e.composedPath();
|
|
2898
3089
|
retarget(path[0]);
|
|
2899
3090
|
for (let i = 0; i < path.length - 2; i++) {
|
|
2900
|
-
|
|
3091
|
+
const nextNode = asElement(path[i]);
|
|
3092
|
+
if (!nextNode || nextNode === lastHandled) continue;
|
|
3093
|
+
node = nextNode;
|
|
2901
3094
|
if (!handleNode()) break;
|
|
3095
|
+
lastHandled = node;
|
|
2902
3096
|
if (node._$host) {
|
|
2903
3097
|
node = node._$host;
|
|
2904
3098
|
walkUpTree();
|