@pyreon/runtime-dom 0.13.0 → 0.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +23 -0
- package/lib/analysis/index.js.html +1 -1
- package/lib/analysis/keep-alive-entry.js.html +5406 -0
- package/lib/analysis/transition-entry.js.html +5406 -0
- package/lib/index.js +98 -47
- package/lib/index.js.map +1 -1
- package/lib/keep-alive-entry.js +1341 -0
- package/lib/keep-alive-entry.js.map +1 -0
- package/lib/transition-entry.js +167 -0
- package/lib/transition-entry.js.map +1 -0
- package/lib/types/index.d.ts.map +1 -1
- package/lib/types/keep-alive-entry.d.ts +41 -0
- package/lib/types/keep-alive-entry.d.ts.map +1 -0
- package/lib/types/transition-entry.d.ts +59 -0
- package/lib/types/transition-entry.d.ts.map +1 -0
- package/package.json +17 -7
- package/src/hydrate.ts +14 -12
- package/src/index.ts +19 -3
- package/src/keep-alive-entry.ts +3 -0
- package/src/mount.ts +159 -54
- package/src/nodes.ts +61 -11
- package/src/template.ts +13 -2
- package/src/tests/coverage-gaps.test.ts +709 -0
- package/src/tests/lis-prepend.browser.test.ts +99 -0
- package/src/tests/runtime-dom.browser.test.ts +63 -1
- package/src/tests/template.test.ts +64 -0
- package/src/transition-entry.ts +7 -0
package/lib/index.js
CHANGED
|
@@ -303,7 +303,8 @@ function installDevTools() {
|
|
|
303
303
|
|
|
304
304
|
//#endregion
|
|
305
305
|
//#region src/nodes.ts
|
|
306
|
-
const __DEV__$
|
|
306
|
+
const __DEV__$5 = import.meta.env?.DEV === true;
|
|
307
|
+
const _countSink$3 = globalThis;
|
|
307
308
|
/**
|
|
308
309
|
* Move all nodes strictly between `start` and `end` into a throwaway
|
|
309
310
|
* DocumentFragment, detaching them from the live DOM in O(n) top-level moves.
|
|
@@ -367,6 +368,7 @@ function growLisArrays(lis, n) {
|
|
|
367
368
|
function computeKeyedLis(lis, n, newKeyOrder, curPos) {
|
|
368
369
|
const { tails, tailIdx, pred } = lis;
|
|
369
370
|
let lisLen = 0;
|
|
371
|
+
let ops = 0;
|
|
370
372
|
for (let i = 0; i < n; i++) {
|
|
371
373
|
const key = newKeyOrder[i];
|
|
372
374
|
if (key === void 0) continue;
|
|
@@ -376,6 +378,7 @@ function computeKeyedLis(lis, n, newKeyOrder, curPos) {
|
|
|
376
378
|
let hi = lisLen;
|
|
377
379
|
while (lo < hi) {
|
|
378
380
|
const mid = lo + hi >> 1;
|
|
381
|
+
ops++;
|
|
379
382
|
if (tails[mid] < v) lo = mid + 1;
|
|
380
383
|
else hi = mid;
|
|
381
384
|
}
|
|
@@ -384,6 +387,7 @@ function computeKeyedLis(lis, n, newKeyOrder, curPos) {
|
|
|
384
387
|
if (lo > 0) pred[i] = tailIdx[lo - 1];
|
|
385
388
|
if (lo === lisLen) lisLen++;
|
|
386
389
|
}
|
|
390
|
+
if (__DEV__$5 && ops > 0) _countSink$3.__pyreon_count__?.("runtime.mountFor.lisOps", ops);
|
|
387
391
|
return lisLen;
|
|
388
392
|
}
|
|
389
393
|
function markStayingEntries(lis, lisLen) {
|
|
@@ -521,21 +525,36 @@ function trySmallKReorder(n, newKeys, currentKeys, cache, liveParent, tailMarker
|
|
|
521
525
|
function computeForLis(lis, n, newKeys, cache) {
|
|
522
526
|
const { tails, tailIdx, pred } = lis;
|
|
523
527
|
let lisLen = 0;
|
|
528
|
+
let ops = 0;
|
|
529
|
+
let lastV = -1;
|
|
524
530
|
for (let i = 0; i < n; i++) {
|
|
525
531
|
const key = newKeys[i];
|
|
526
532
|
const v = cache.get(key)?.pos ?? 0;
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
+
if (v > lastV) {
|
|
534
|
+
tails[lisLen] = v;
|
|
535
|
+
tailIdx[lisLen] = i;
|
|
536
|
+
if (lisLen > 0) pred[i] = tailIdx[lisLen - 1];
|
|
537
|
+
lisLen++;
|
|
538
|
+
lastV = v;
|
|
539
|
+
continue;
|
|
540
|
+
}
|
|
541
|
+
let lo;
|
|
542
|
+
if (v < lisLen && tails[v] === v) lo = v;
|
|
543
|
+
else {
|
|
544
|
+
lo = 0;
|
|
545
|
+
let hi = lisLen;
|
|
546
|
+
while (lo < hi) {
|
|
547
|
+
const mid = lo + hi >> 1;
|
|
548
|
+
ops++;
|
|
549
|
+
if (tails[mid] < v) lo = mid + 1;
|
|
550
|
+
else hi = mid;
|
|
551
|
+
}
|
|
533
552
|
}
|
|
534
553
|
tails[lo] = v;
|
|
535
554
|
tailIdx[lo] = i;
|
|
536
555
|
if (lo > 0) pred[i] = tailIdx[lo - 1];
|
|
537
|
-
if (lo === lisLen) lisLen++;
|
|
538
556
|
}
|
|
557
|
+
if (__DEV__$5 && ops > 0) _countSink$3.__pyreon_count__?.("runtime.mountFor.lisOps", ops);
|
|
539
558
|
return lisLen;
|
|
540
559
|
}
|
|
541
560
|
function applyForMoves(n, newKeys, stay, cache, liveParent, tailMarker) {
|
|
@@ -576,6 +595,7 @@ function mountFor(source, getKey, renderItem, parent, anchor, mountChild) {
|
|
|
576
595
|
parent.insertBefore(tailMarker, anchor);
|
|
577
596
|
let cache = /* @__PURE__ */ new Map();
|
|
578
597
|
let currentKeys = [];
|
|
598
|
+
const _reusableKeySet = /* @__PURE__ */ new Set();
|
|
579
599
|
let cleanupCount = 0;
|
|
580
600
|
let anchorsRegistered = false;
|
|
581
601
|
let lis = {
|
|
@@ -586,9 +606,9 @@ function mountFor(source, getKey, renderItem, parent, anchor, mountChild) {
|
|
|
586
606
|
};
|
|
587
607
|
const warnForKey = (seen, key) => {
|
|
588
608
|
if (!seen) return;
|
|
589
|
-
if (__DEV__$
|
|
609
|
+
if (__DEV__$5 && key == null) console.warn("[Pyreon] <For> `by` function returned null/undefined. Keys must be strings or numbers. Check your `by` prop.");
|
|
590
610
|
if (seen.has(key)) {
|
|
591
|
-
if (__DEV__$
|
|
611
|
+
if (__DEV__$5) console.warn(`[Pyreon] Duplicate key "${String(key)}" in <For> list. Keys must be unique.`);
|
|
592
612
|
return true;
|
|
593
613
|
}
|
|
594
614
|
seen.add(key);
|
|
@@ -714,7 +734,9 @@ function mountFor(source, getKey, renderItem, parent, anchor, mountChild) {
|
|
|
714
734
|
return false;
|
|
715
735
|
};
|
|
716
736
|
const handleIncrementalUpdate = (items, n, newKeys, liveParent) => {
|
|
717
|
-
|
|
737
|
+
_reusableKeySet.clear();
|
|
738
|
+
for (let i = 0; i < newKeys.length; i++) _reusableKeySet.add(newKeys[i]);
|
|
739
|
+
removeStaleForEntries(_reusableKeySet);
|
|
718
740
|
mountNewForEntries(items, n, newKeys, liveParent);
|
|
719
741
|
if (!anchorsRegistered) {
|
|
720
742
|
for (const entry of cache.values()) _forAnchors.add(entry.anchor);
|
|
@@ -813,7 +835,7 @@ function moveEntryBefore(parent, startNode, before) {
|
|
|
813
835
|
|
|
814
836
|
//#endregion
|
|
815
837
|
//#region src/props.ts
|
|
816
|
-
const __DEV__$
|
|
838
|
+
const __DEV__$4 = import.meta.env?.DEV === true;
|
|
817
839
|
let _customSanitizer = null;
|
|
818
840
|
/**
|
|
819
841
|
* Set a custom HTML sanitizer used by `innerHTML` and `sanitizeHtml()`.
|
|
@@ -978,7 +1000,7 @@ function applyProps(el, props) {
|
|
|
978
1000
|
*/
|
|
979
1001
|
function applyEventProp(el, key, value) {
|
|
980
1002
|
if (typeof value !== "function") {
|
|
981
|
-
if (__DEV__$
|
|
1003
|
+
if (__DEV__$4 && value != null) console.warn(`[Pyreon] Event handler "${key}" received a non-function value (${typeof value}). Expected a function. Did you mean ${key}={() => ...}?`);
|
|
982
1004
|
return null;
|
|
983
1005
|
}
|
|
984
1006
|
const eventName = (key[2]?.toLowerCase() + key.slice(3)).toLowerCase();
|
|
@@ -1009,7 +1031,7 @@ function applyEventProp(el, key, value) {
|
|
|
1009
1031
|
* dispatch) eliminates the entire bug class.
|
|
1010
1032
|
*/
|
|
1011
1033
|
function applyStaticProp(el, key, value) {
|
|
1012
|
-
if (__DEV__$
|
|
1034
|
+
if (__DEV__$4 && typeof value === "function") console.warn(`[Pyreon] applyStaticProp received a function for "${key}". This likely means a new special-cased prop sink in applyProp() bypassed the reactive-wrap path. The closure would be stringified and set as a literal value. Verify the dispatch in applyProp().`);
|
|
1013
1035
|
if (key === "innerHTML") {
|
|
1014
1036
|
const html = String(value ?? "");
|
|
1015
1037
|
if (typeof el.setHTML === "function") el.setHTML(html);
|
|
@@ -1076,7 +1098,7 @@ function applyClassProp(el, value) {
|
|
|
1076
1098
|
}
|
|
1077
1099
|
function setStaticProp(el, key, value) {
|
|
1078
1100
|
if (URL_ATTRS.has(key) && typeof value === "string" && UNSAFE_URL_RE.test(value)) {
|
|
1079
|
-
if (__DEV__$
|
|
1101
|
+
if (__DEV__$4) console.warn(`[Pyreon] Blocked unsafe URL in "${key}" attribute: ${value}`);
|
|
1080
1102
|
return;
|
|
1081
1103
|
}
|
|
1082
1104
|
if (key === "class" || key === "className") {
|
|
@@ -1113,10 +1135,12 @@ function setStaticProp(el, key, value) {
|
|
|
1113
1135
|
|
|
1114
1136
|
//#endregion
|
|
1115
1137
|
//#region src/mount.ts
|
|
1116
|
-
const __DEV__$
|
|
1138
|
+
const __DEV__$3 = import.meta.env?.DEV === true;
|
|
1139
|
+
const _countSink$2 = globalThis;
|
|
1117
1140
|
const noop$1 = () => {};
|
|
1118
1141
|
let _elementDepth = 0;
|
|
1119
|
-
|
|
1142
|
+
let _mountingStack;
|
|
1143
|
+
if (__DEV__$3) _mountingStack = [];
|
|
1120
1144
|
/**
|
|
1121
1145
|
* Mount a single child into `parent`, inserting before `anchor` (null = append).
|
|
1122
1146
|
* Returns a cleanup that removes the node(s) and disposes all reactive effects.
|
|
@@ -1125,6 +1149,7 @@ const _mountingStack = [];
|
|
|
1125
1149
|
* function call overhead in tight render loops (1000+ calls per list render).
|
|
1126
1150
|
*/
|
|
1127
1151
|
function mountChild(child, parent, anchor = null) {
|
|
1152
|
+
if (__DEV__$3) _countSink$2.__pyreon_count__?.("runtime.mountChild");
|
|
1128
1153
|
if (typeof child === "function") {
|
|
1129
1154
|
const sample = runUntracked(() => child());
|
|
1130
1155
|
if (isKeyedArray(sample)) {
|
|
@@ -1139,7 +1164,8 @@ function mountChild(child, parent, anchor = null) {
|
|
|
1139
1164
|
parent.insertBefore(text, anchor);
|
|
1140
1165
|
const dispose = renderEffect(() => {
|
|
1141
1166
|
const v = child();
|
|
1142
|
-
|
|
1167
|
+
const next = v == null || v === false ? "" : String(v);
|
|
1168
|
+
if (next !== text.data) text.data = next;
|
|
1143
1169
|
});
|
|
1144
1170
|
if (_elementDepth > 0) return dispose;
|
|
1145
1171
|
return () => {
|
|
@@ -1180,24 +1206,26 @@ function mountChild(child, parent, anchor = null) {
|
|
|
1180
1206
|
const vnode = child;
|
|
1181
1207
|
if (vnode.type === Fragment) return mountChildren(vnode.children ?? [], parent, anchor);
|
|
1182
1208
|
if (vnode.type === ForSymbol) {
|
|
1183
|
-
const
|
|
1209
|
+
const props = vnode.props;
|
|
1210
|
+
const initialEach = props.each;
|
|
1211
|
+
const source = typeof initialEach === "function" ? initialEach : (() => props.each);
|
|
1184
1212
|
const prevDepth = _elementDepth;
|
|
1185
1213
|
_elementDepth = 0;
|
|
1186
|
-
const cleanup = mountFor(
|
|
1214
|
+
const cleanup = mountFor(source, props.by, props.children, parent, anchor, mountChild);
|
|
1187
1215
|
_elementDepth = prevDepth;
|
|
1188
1216
|
return cleanup;
|
|
1189
1217
|
}
|
|
1190
1218
|
if (vnode.type === PortalSymbol) {
|
|
1191
1219
|
const { target, children } = vnode.props;
|
|
1192
|
-
if (__DEV__$
|
|
1220
|
+
if (__DEV__$3 && !target) {
|
|
1193
1221
|
console.warn("[Pyreon] <Portal> received a falsy `target`. Provide a valid DOM element.");
|
|
1194
1222
|
return noop$1;
|
|
1195
1223
|
}
|
|
1196
|
-
if (__DEV__$
|
|
1224
|
+
if (__DEV__$3 && !(target instanceof Node)) console.warn(`[Pyreon] <Portal> target must be a DOM node. Received ${typeof target}. Use document.getElementById() or a ref to get the target element.`);
|
|
1197
1225
|
return mountChild(children, target, null);
|
|
1198
1226
|
}
|
|
1199
1227
|
if (typeof vnode.type === "function") return mountComponent(vnode, parent, anchor);
|
|
1200
|
-
if (__DEV__$
|
|
1228
|
+
if (__DEV__$3 && typeof vnode.type !== "string") {
|
|
1201
1229
|
console.warn(`[Pyreon] Invalid VNode type: expected a string tag or component function, received ${typeof vnode.type} (${String(vnode.type)}). This usually means you passed an object or class instead of a component function.`);
|
|
1202
1230
|
return noop$1;
|
|
1203
1231
|
}
|
|
@@ -1312,7 +1340,7 @@ function mountElement(vnode, parent, anchor) {
|
|
|
1312
1340
|
const isMathml = tag === "math";
|
|
1313
1341
|
if (isSvg) _svgDepth++;
|
|
1314
1342
|
if (isMathml) _mathmlDepth++;
|
|
1315
|
-
if (__DEV__$
|
|
1343
|
+
if (__DEV__$3 && (vnode.children?.length ?? 0) > 0 && VOID_ELEMENTS.has(vnode.type)) console.warn(`[Pyreon] <${vnode.type}> is a void element and cannot have children. Children passed to void elements will be ignored by the browser.`);
|
|
1316
1344
|
const props = vnode.props;
|
|
1317
1345
|
const propCleanup = props !== EMPTY_PROPS ? applyProps(el, props) : null;
|
|
1318
1346
|
_elementDepth++;
|
|
@@ -1360,9 +1388,13 @@ function mountComponent(vnode, parent, anchor) {
|
|
|
1360
1388
|
let hooks;
|
|
1361
1389
|
let output;
|
|
1362
1390
|
const componentName = vnode.type.name || "Anonymous";
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1391
|
+
let compId;
|
|
1392
|
+
let devParentId;
|
|
1393
|
+
if (__DEV__$3) {
|
|
1394
|
+
compId = `${componentName}-${Math.random().toString(36).slice(2, 9)}`;
|
|
1395
|
+
devParentId = _mountingStack[_mountingStack.length - 1] ?? null;
|
|
1396
|
+
_mountingStack.push(compId);
|
|
1397
|
+
}
|
|
1366
1398
|
const children = vnode.children ?? [];
|
|
1367
1399
|
const rawProps = children.length > 0 && vnode.props.children === void 0 ? {
|
|
1368
1400
|
...vnode.props,
|
|
@@ -1374,7 +1406,7 @@ function mountComponent(vnode, parent, anchor) {
|
|
|
1374
1406
|
hooks = result.hooks;
|
|
1375
1407
|
output = result.vnode;
|
|
1376
1408
|
} catch (err) {
|
|
1377
|
-
_mountingStack.pop();
|
|
1409
|
+
if (__DEV__$3) _mountingStack.pop();
|
|
1378
1410
|
setCurrentScope(null);
|
|
1379
1411
|
scope.stop();
|
|
1380
1412
|
reportError({
|
|
@@ -1386,7 +1418,7 @@ function mountComponent(vnode, parent, anchor) {
|
|
|
1386
1418
|
});
|
|
1387
1419
|
const handled = dispatchToErrorBoundary(err);
|
|
1388
1420
|
if (!handled) console.error(`[Pyreon] <${componentName}> threw during setup:`, err);
|
|
1389
|
-
if (__DEV__$
|
|
1421
|
+
if (__DEV__$3 && !handled) {
|
|
1390
1422
|
const overlay = document.createElement("pre");
|
|
1391
1423
|
overlay.style.cssText = "color:#e53e3e;background:#fff5f5;padding:12px;border:2px solid #e53e3e;border-radius:6px;font-size:12px;margin:4px;font-family:monospace;white-space:pre-wrap;word-break:break-word";
|
|
1392
1424
|
const e = err;
|
|
@@ -1398,16 +1430,16 @@ function mountComponent(vnode, parent, anchor) {
|
|
|
1398
1430
|
} finally {
|
|
1399
1431
|
setCurrentScope(null);
|
|
1400
1432
|
}
|
|
1401
|
-
if (__DEV__$
|
|
1433
|
+
if (__DEV__$3 && output != null && typeof output === "object") {
|
|
1402
1434
|
if (output instanceof Promise) console.warn(`[Pyreon] Component <${componentName}> returned a Promise. Components must be synchronous — use lazy() + Suspense for async loading, or fetch data in onMount and store it in a signal.`);
|
|
1403
1435
|
else if (!("type" in output) && !Array.isArray(output) && !output.__isNative) console.warn(`[Pyreon] Component <${componentName}> returned an invalid value. Components must return a VNode, string, null, function, or array.`);
|
|
1404
1436
|
}
|
|
1405
|
-
for (const fn of hooks.update) scope.addUpdateHook(fn);
|
|
1437
|
+
if (hooks.update) for (const fn of hooks.update) scope.addUpdateHook(fn);
|
|
1406
1438
|
let subtreeCleanup = noop$1;
|
|
1407
1439
|
try {
|
|
1408
1440
|
subtreeCleanup = output != null ? mountChild(output, parent, anchor) : noop$1;
|
|
1409
1441
|
} catch (err) {
|
|
1410
|
-
_mountingStack.pop();
|
|
1442
|
+
if (__DEV__$3) _mountingStack.pop();
|
|
1411
1443
|
scope.stop();
|
|
1412
1444
|
if (!(propagateError(err, hooks) || dispatchToErrorBoundary(err))) {
|
|
1413
1445
|
reportError({
|
|
@@ -1421,15 +1453,21 @@ function mountComponent(vnode, parent, anchor) {
|
|
|
1421
1453
|
}
|
|
1422
1454
|
return noop$1;
|
|
1423
1455
|
}
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1456
|
+
if (__DEV__$3) {
|
|
1457
|
+
_mountingStack.pop();
|
|
1458
|
+
const firstEl = parent instanceof Element ? parent.firstElementChild : null;
|
|
1459
|
+
registerComponent(compId, componentName, firstEl, devParentId);
|
|
1460
|
+
}
|
|
1461
|
+
let mountCleanups = null;
|
|
1462
|
+
if (hooks.mount) for (const fn of hooks.mount) try {
|
|
1428
1463
|
let cleanup;
|
|
1429
1464
|
scope.runInScope(() => {
|
|
1430
1465
|
cleanup = fn();
|
|
1431
1466
|
});
|
|
1432
|
-
if (cleanup)
|
|
1467
|
+
if (cleanup) {
|
|
1468
|
+
if (mountCleanups === null) mountCleanups = [];
|
|
1469
|
+
mountCleanups.push(cleanup);
|
|
1470
|
+
}
|
|
1433
1471
|
} catch (err) {
|
|
1434
1472
|
console.error(`[Pyreon] Error in onMount hook of <${componentName}>:`, err);
|
|
1435
1473
|
reportError({
|
|
@@ -1440,10 +1478,10 @@ function mountComponent(vnode, parent, anchor) {
|
|
|
1440
1478
|
});
|
|
1441
1479
|
}
|
|
1442
1480
|
return () => {
|
|
1443
|
-
unregisterComponent(compId);
|
|
1481
|
+
if (__DEV__$3) unregisterComponent(compId);
|
|
1444
1482
|
scope.stop();
|
|
1445
1483
|
subtreeCleanup();
|
|
1446
|
-
for (const fn of hooks.unmount) try {
|
|
1484
|
+
if (hooks.unmount) for (const fn of hooks.unmount) try {
|
|
1447
1485
|
fn();
|
|
1448
1486
|
} catch (err) {
|
|
1449
1487
|
console.error(`[Pyreon] Error in onUnmount hook of <${componentName}>:`, err);
|
|
@@ -1454,7 +1492,7 @@ function mountComponent(vnode, parent, anchor) {
|
|
|
1454
1492
|
timestamp: Date.now()
|
|
1455
1493
|
});
|
|
1456
1494
|
}
|
|
1457
|
-
for (const fn of mountCleanups) fn();
|
|
1495
|
+
if (mountCleanups) for (const fn of mountCleanups) fn();
|
|
1458
1496
|
};
|
|
1459
1497
|
}
|
|
1460
1498
|
function mountChildren(children, parent, anchor) {
|
|
@@ -1670,13 +1708,13 @@ function hydrateComponent(vnode, domNode, parent, anchor, path = "root") {
|
|
|
1670
1708
|
}
|
|
1671
1709
|
setCurrentScope(null);
|
|
1672
1710
|
const { vnode: output, hooks } = result;
|
|
1673
|
-
for (const fn of hooks.update) scope.addUpdateHook(fn);
|
|
1711
|
+
if (hooks.update) for (const fn of hooks.update) scope.addUpdateHook(fn);
|
|
1674
1712
|
if (output != null) {
|
|
1675
1713
|
const [childCleanup, next] = hydrateChild(output, domNode, parent, anchor, path);
|
|
1676
1714
|
subtreeCleanup = childCleanup;
|
|
1677
1715
|
nextDom = next;
|
|
1678
1716
|
}
|
|
1679
|
-
for (const fn of hooks.mount) try {
|
|
1717
|
+
if (hooks.mount) for (const fn of hooks.mount) try {
|
|
1680
1718
|
let c;
|
|
1681
1719
|
scope.runInScope(() => {
|
|
1682
1720
|
c = fn();
|
|
@@ -1693,7 +1731,7 @@ function hydrateComponent(vnode, domNode, parent, anchor, path = "root") {
|
|
|
1693
1731
|
const cleanup = () => {
|
|
1694
1732
|
scope.stop();
|
|
1695
1733
|
subtreeCleanup();
|
|
1696
|
-
for (const fn of hooks.unmount) fn();
|
|
1734
|
+
if (hooks.unmount) for (const fn of hooks.unmount) fn();
|
|
1697
1735
|
for (const fn of mountCleanups) fn();
|
|
1698
1736
|
};
|
|
1699
1737
|
return [cleanup, nextDom];
|
|
@@ -1772,6 +1810,8 @@ function KeepAlive(props) {
|
|
|
1772
1810
|
|
|
1773
1811
|
//#endregion
|
|
1774
1812
|
//#region src/template.ts
|
|
1813
|
+
const __DEV__$2 = import.meta.env?.DEV === true;
|
|
1814
|
+
const _countSink$1 = globalThis;
|
|
1775
1815
|
/**
|
|
1776
1816
|
* Creates a row/item factory backed by HTML template cloning.
|
|
1777
1817
|
*
|
|
@@ -1830,7 +1870,8 @@ function _bindText(source, node) {
|
|
|
1830
1870
|
if (source.direct) {
|
|
1831
1871
|
const textUpdate = () => {
|
|
1832
1872
|
const v = source._v;
|
|
1833
|
-
|
|
1873
|
+
const next = v == null || v === false ? "" : String(v);
|
|
1874
|
+
if (next !== node.data) node.data = next;
|
|
1834
1875
|
};
|
|
1835
1876
|
textUpdate();
|
|
1836
1877
|
return source.direct(textUpdate);
|
|
@@ -1838,7 +1879,8 @@ function _bindText(source, node) {
|
|
|
1838
1879
|
const fn = source;
|
|
1839
1880
|
return renderEffect(() => {
|
|
1840
1881
|
const v = fn();
|
|
1841
|
-
|
|
1882
|
+
const next = v == null || v === false ? "" : String(v);
|
|
1883
|
+
if (next !== node.data) node.data = next;
|
|
1842
1884
|
});
|
|
1843
1885
|
}
|
|
1844
1886
|
/**
|
|
@@ -1890,6 +1932,7 @@ const _tplCache = /* @__PURE__ */ new Map();
|
|
|
1890
1932
|
* })
|
|
1891
1933
|
*/
|
|
1892
1934
|
function _tpl(html, bind) {
|
|
1935
|
+
if (__DEV__$2) _countSink$1.__pyreon_count__?.("runtime.tpl");
|
|
1893
1936
|
let tpl = _tplCache.get(html);
|
|
1894
1937
|
if (!tpl) {
|
|
1895
1938
|
tpl = document.createElement("template");
|
|
@@ -2344,6 +2387,7 @@ function TransitionGroup(props) {
|
|
|
2344
2387
|
//#endregion
|
|
2345
2388
|
//#region src/index.ts
|
|
2346
2389
|
const __DEV__ = import.meta.env?.DEV === true;
|
|
2390
|
+
const _countSink = globalThis;
|
|
2347
2391
|
/**
|
|
2348
2392
|
* Mount a VNode tree into a container element.
|
|
2349
2393
|
* Clears the container first, then mounts the given child.
|
|
@@ -2354,10 +2398,17 @@ const __DEV__ = import.meta.env?.DEV === true;
|
|
|
2354
2398
|
*/
|
|
2355
2399
|
function mount(root, container) {
|
|
2356
2400
|
if (__DEV__ && container == null) throw new Error("[pyreon] mount() called with a null/undefined container. Make sure the element exists in the DOM, e.g. document.getElementById(\"app\")");
|
|
2357
|
-
|
|
2401
|
+
if (__DEV__) {
|
|
2402
|
+
_countSink.__pyreon_count__?.("runtime.mount");
|
|
2403
|
+
installDevTools();
|
|
2404
|
+
}
|
|
2358
2405
|
setupDelegation(container);
|
|
2359
2406
|
container.innerHTML = "";
|
|
2360
|
-
|
|
2407
|
+
const unmount = mountChild(root, container, null);
|
|
2408
|
+
return () => {
|
|
2409
|
+
if (__DEV__) _countSink.__pyreon_count__?.("runtime.unmount");
|
|
2410
|
+
unmount();
|
|
2411
|
+
};
|
|
2361
2412
|
}
|
|
2362
2413
|
/** Alias for `mount` */
|
|
2363
2414
|
const render = mount;
|