@pyreon/runtime-dom 0.14.0 → 0.15.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/lib/analysis/index.js.html +1 -1
- package/lib/analysis/keep-alive-entry.js.html +1 -1
- package/lib/analysis/transition-entry.js.html +1 -1
- package/lib/index.js +62 -14
- package/lib/keep-alive-entry.js +5 -4
- package/lib/transition-entry.js +3 -2
- package/lib/types/index.d.ts +54 -5
- package/package.json +6 -5
- package/src/delegate.ts +16 -0
- package/src/hydrate.ts +9 -2
- package/src/hydration-debug.ts +99 -14
- package/src/index.ts +11 -3
- package/src/keep-alive.ts +5 -1
- package/src/mount.ts +1 -2
- package/src/nodes.ts +1 -2
- package/src/props.ts +1 -2
- package/src/template.ts +46 -2
- package/src/tests/dev-gate-pattern.test.ts +17 -11
- package/src/tests/dev-gate-treeshake.test.ts +20 -26
- package/src/tests/hydration-integration.test.tsx +166 -1
- package/src/tests/mount.test.ts +91 -0
- package/src/tests/native-markers.test.ts +19 -0
- package/src/tests/runtime-dom.browser.test.ts +58 -6
- package/src/tests/show-context.test.ts +93 -0
- package/src/tests/template.test.ts +71 -1
- package/src/transition-group.ts +6 -1
- package/src/transition.ts +11 -3
- package/lib/index.js.map +0 -1
- package/lib/keep-alive-entry.js.map +0 -1
- package/lib/transition-entry.js.map +0 -1
- package/lib/types/index.d.ts.map +0 -1
- package/lib/types/keep-alive-entry.d.ts.map +0 -1
- package/lib/types/transition-entry.d.ts.map +0 -1
|
@@ -5386,7 +5386,7 @@ var drawChart = (function (exports) {
|
|
|
5386
5386
|
</script>
|
|
5387
5387
|
<script>
|
|
5388
5388
|
/*<!--*/
|
|
5389
|
-
const data = {"version":2,"tree":{"name":"root","children":[{"name":"index.js","children":[{"name":"src","children":[{"uid":"
|
|
5389
|
+
const data = {"version":2,"tree":{"name":"root","children":[{"name":"index.js","children":[{"name":"src","children":[{"uid":"707cac82-1","name":"delegate.ts"},{"uid":"707cac82-3","name":"hydration-debug.ts"},{"uid":"707cac82-5","name":"devtools.ts"},{"uid":"707cac82-7","name":"nodes.ts"},{"uid":"707cac82-9","name":"props.ts"},{"uid":"707cac82-11","name":"mount.ts"},{"uid":"707cac82-13","name":"hydrate.ts"},{"uid":"707cac82-15","name":"keep-alive.ts"},{"uid":"707cac82-17","name":"template.ts"},{"uid":"707cac82-19","name":"transition.ts"},{"uid":"707cac82-21","name":"transition-group.ts"},{"uid":"707cac82-23","name":"index.ts"}]}]}],"isRoot":true},"nodeParts":{"707cac82-1":{"renderedLength":2090,"gzipLength":1029,"brotliLength":0,"metaUid":"707cac82-0"},"707cac82-3":{"renderedLength":1395,"gzipLength":718,"brotliLength":0,"metaUid":"707cac82-2"},"707cac82-5":{"renderedLength":7009,"gzipLength":2149,"brotliLength":0,"metaUid":"707cac82-4"},"707cac82-7":{"renderedLength":16850,"gzipLength":4538,"brotliLength":0,"metaUid":"707cac82-6"},"707cac82-9":{"renderedLength":7955,"gzipLength":3028,"brotliLength":0,"metaUid":"707cac82-8"},"707cac82-11":{"renderedLength":12232,"gzipLength":3882,"brotliLength":0,"metaUid":"707cac82-10"},"707cac82-13":{"renderedLength":8312,"gzipLength":2472,"brotliLength":0,"metaUid":"707cac82-12"},"707cac82-15":{"renderedLength":1498,"gzipLength":713,"brotliLength":0,"metaUid":"707cac82-14"},"707cac82-17":{"renderedLength":5802,"gzipLength":2272,"brotliLength":0,"metaUid":"707cac82-16"},"707cac82-19":{"renderedLength":4929,"gzipLength":1410,"brotliLength":0,"metaUid":"707cac82-18"},"707cac82-21":{"renderedLength":7973,"gzipLength":2085,"brotliLength":0,"metaUid":"707cac82-20"},"707cac82-23":{"renderedLength":985,"gzipLength":549,"brotliLength":0,"metaUid":"707cac82-22"}},"nodeMetas":{"707cac82-0":{"id":"/src/delegate.ts","moduleParts":{"index.js":"707cac82-1"},"imported":[{"uid":"707cac82-24"}],"importedBy":[{"uid":"707cac82-22"},{"uid":"707cac82-12"},{"uid":"707cac82-8"}]},"707cac82-2":{"id":"/src/hydration-debug.ts","moduleParts":{"index.js":"707cac82-3"},"imported":[],"importedBy":[{"uid":"707cac82-22"},{"uid":"707cac82-12"}]},"707cac82-4":{"id":"/src/devtools.ts","moduleParts":{"index.js":"707cac82-5"},"imported":[],"importedBy":[{"uid":"707cac82-22"},{"uid":"707cac82-10"}]},"707cac82-6":{"id":"/src/nodes.ts","moduleParts":{"index.js":"707cac82-7"},"imported":[{"uid":"707cac82-25"},{"uid":"707cac82-24"}],"importedBy":[{"uid":"707cac82-12"},{"uid":"707cac82-10"}]},"707cac82-8":{"id":"/src/props.ts","moduleParts":{"index.js":"707cac82-9"},"imported":[{"uid":"707cac82-25"},{"uid":"707cac82-24"},{"uid":"707cac82-0"}],"importedBy":[{"uid":"707cac82-22"},{"uid":"707cac82-12"},{"uid":"707cac82-10"}]},"707cac82-10":{"id":"/src/mount.ts","moduleParts":{"index.js":"707cac82-11"},"imported":[{"uid":"707cac82-25"},{"uid":"707cac82-24"},{"uid":"707cac82-4"},{"uid":"707cac82-6"},{"uid":"707cac82-8"}],"importedBy":[{"uid":"707cac82-22"},{"uid":"707cac82-12"},{"uid":"707cac82-14"},{"uid":"707cac82-16"},{"uid":"707cac82-20"}]},"707cac82-12":{"id":"/src/hydrate.ts","moduleParts":{"index.js":"707cac82-13"},"imported":[{"uid":"707cac82-25"},{"uid":"707cac82-24"},{"uid":"707cac82-0"},{"uid":"707cac82-2"},{"uid":"707cac82-10"},{"uid":"707cac82-6"},{"uid":"707cac82-8"}],"importedBy":[{"uid":"707cac82-22"}]},"707cac82-14":{"id":"/src/keep-alive.ts","moduleParts":{"index.js":"707cac82-15"},"imported":[{"uid":"707cac82-25"},{"uid":"707cac82-24"},{"uid":"707cac82-10"}],"importedBy":[{"uid":"707cac82-22"}]},"707cac82-16":{"id":"/src/template.ts","moduleParts":{"index.js":"707cac82-17"},"imported":[{"uid":"707cac82-24"},{"uid":"707cac82-10"}],"importedBy":[{"uid":"707cac82-22"}]},"707cac82-18":{"id":"/src/transition.ts","moduleParts":{"index.js":"707cac82-19"},"imported":[{"uid":"707cac82-25"},{"uid":"707cac82-24"}],"importedBy":[{"uid":"707cac82-22"}]},"707cac82-20":{"id":"/src/transition-group.ts","moduleParts":{"index.js":"707cac82-21"},"imported":[{"uid":"707cac82-25"},{"uid":"707cac82-24"},{"uid":"707cac82-10"}],"importedBy":[{"uid":"707cac82-22"}]},"707cac82-22":{"id":"/src/index.ts","moduleParts":{"index.js":"707cac82-23"},"imported":[{"uid":"707cac82-0"},{"uid":"707cac82-12"},{"uid":"707cac82-2"},{"uid":"707cac82-14"},{"uid":"707cac82-10"},{"uid":"707cac82-8"},{"uid":"707cac82-16"},{"uid":"707cac82-18"},{"uid":"707cac82-20"},{"uid":"707cac82-4"}],"importedBy":[],"isEntry":true},"707cac82-24":{"id":"@pyreon/reactivity","moduleParts":{},"imported":[],"importedBy":[{"uid":"707cac82-0"},{"uid":"707cac82-12"},{"uid":"707cac82-14"},{"uid":"707cac82-10"},{"uid":"707cac82-8"},{"uid":"707cac82-16"},{"uid":"707cac82-18"},{"uid":"707cac82-20"},{"uid":"707cac82-6"}]},"707cac82-25":{"id":"@pyreon/core","moduleParts":{},"imported":[],"importedBy":[{"uid":"707cac82-12"},{"uid":"707cac82-14"},{"uid":"707cac82-10"},{"uid":"707cac82-8"},{"uid":"707cac82-18"},{"uid":"707cac82-20"},{"uid":"707cac82-6"}]}},"env":{"rollup":"4.23.0"},"options":{"gzip":true,"brotli":false,"sourcemap":false}};
|
|
5390
5390
|
|
|
5391
5391
|
const run = () => {
|
|
5392
5392
|
const width = window.innerWidth;
|
|
@@ -5386,7 +5386,7 @@ var drawChart = (function (exports) {
|
|
|
5386
5386
|
</script>
|
|
5387
5387
|
<script>
|
|
5388
5388
|
/*<!--*/
|
|
5389
|
-
const data = {"version":2,"tree":{"name":"root","children":[{"name":"keep-alive-entry.js","children":[{"name":"src","children":[{"uid":"
|
|
5389
|
+
const data = {"version":2,"tree":{"name":"root","children":[{"name":"keep-alive-entry.js","children":[{"name":"src","children":[{"uid":"5601753e-1","name":"devtools.ts"},{"uid":"5601753e-3","name":"nodes.ts"},{"uid":"5601753e-5","name":"delegate.ts"},{"uid":"5601753e-7","name":"props.ts"},{"uid":"5601753e-9","name":"mount.ts"},{"uid":"5601753e-11","name":"keep-alive.ts"}]}]}],"isRoot":true},"nodeParts":{"5601753e-1":{"renderedLength":759,"gzipLength":340,"brotliLength":0,"metaUid":"5601753e-0"},"5601753e-3":{"renderedLength":16850,"gzipLength":4538,"brotliLength":0,"metaUid":"5601753e-2"},"5601753e-5":{"renderedLength":790,"gzipLength":436,"brotliLength":0,"metaUid":"5601753e-4"},"5601753e-7":{"renderedLength":7485,"gzipLength":2872,"brotliLength":0,"metaUid":"5601753e-6"},"5601753e-9":{"renderedLength":12162,"gzipLength":3873,"brotliLength":0,"metaUid":"5601753e-8"},"5601753e-11":{"renderedLength":1498,"gzipLength":713,"brotliLength":0,"metaUid":"5601753e-10"}},"nodeMetas":{"5601753e-0":{"id":"/src/devtools.ts","moduleParts":{"keep-alive-entry.js":"5601753e-1"},"imported":[],"importedBy":[{"uid":"5601753e-8"}]},"5601753e-2":{"id":"/src/nodes.ts","moduleParts":{"keep-alive-entry.js":"5601753e-3"},"imported":[{"uid":"5601753e-12"},{"uid":"5601753e-13"}],"importedBy":[{"uid":"5601753e-8"}]},"5601753e-4":{"id":"/src/delegate.ts","moduleParts":{"keep-alive-entry.js":"5601753e-5"},"imported":[{"uid":"5601753e-13"}],"importedBy":[{"uid":"5601753e-6"}]},"5601753e-6":{"id":"/src/props.ts","moduleParts":{"keep-alive-entry.js":"5601753e-7"},"imported":[{"uid":"5601753e-12"},{"uid":"5601753e-13"},{"uid":"5601753e-4"}],"importedBy":[{"uid":"5601753e-8"}]},"5601753e-8":{"id":"/src/mount.ts","moduleParts":{"keep-alive-entry.js":"5601753e-9"},"imported":[{"uid":"5601753e-12"},{"uid":"5601753e-13"},{"uid":"5601753e-0"},{"uid":"5601753e-2"},{"uid":"5601753e-6"}],"importedBy":[{"uid":"5601753e-10"}]},"5601753e-10":{"id":"/src/keep-alive.ts","moduleParts":{"keep-alive-entry.js":"5601753e-11"},"imported":[{"uid":"5601753e-12"},{"uid":"5601753e-13"},{"uid":"5601753e-8"}],"importedBy":[],"isEntry":true},"5601753e-12":{"id":"@pyreon/core","moduleParts":{},"imported":[],"importedBy":[{"uid":"5601753e-10"},{"uid":"5601753e-8"},{"uid":"5601753e-2"},{"uid":"5601753e-6"}]},"5601753e-13":{"id":"@pyreon/reactivity","moduleParts":{},"imported":[],"importedBy":[{"uid":"5601753e-10"},{"uid":"5601753e-8"},{"uid":"5601753e-2"},{"uid":"5601753e-6"},{"uid":"5601753e-4"}]}},"env":{"rollup":"4.23.0"},"options":{"gzip":true,"brotli":false,"sourcemap":false}};
|
|
5390
5390
|
|
|
5391
5391
|
const run = () => {
|
|
5392
5392
|
const width = window.innerWidth;
|
|
@@ -5386,7 +5386,7 @@ var drawChart = (function (exports) {
|
|
|
5386
5386
|
</script>
|
|
5387
5387
|
<script>
|
|
5388
5388
|
/*<!--*/
|
|
5389
|
-
const data = {"version":2,"tree":{"name":"root","children":[{"name":"transition-entry.js","children":[{"name":"src/transition.ts","uid":"
|
|
5389
|
+
const data = {"version":2,"tree":{"name":"root","children":[{"name":"transition-entry.js","children":[{"name":"src/transition.ts","uid":"266bed6c-1"}]}],"isRoot":true},"nodeParts":{"266bed6c-1":{"renderedLength":4925,"gzipLength":1407,"brotliLength":0,"metaUid":"266bed6c-0"}},"nodeMetas":{"266bed6c-0":{"id":"/src/transition.ts","moduleParts":{"transition-entry.js":"266bed6c-1"},"imported":[{"uid":"266bed6c-2"},{"uid":"266bed6c-3"}],"importedBy":[],"isEntry":true},"266bed6c-2":{"id":"@pyreon/core","moduleParts":{},"imported":[],"importedBy":[{"uid":"266bed6c-0"}]},"266bed6c-3":{"id":"@pyreon/reactivity","moduleParts":{},"imported":[],"importedBy":[{"uid":"266bed6c-0"}]}},"env":{"rollup":"4.23.0"},"options":{"gzip":true,"brotli":false,"sourcemap":false}};
|
|
5390
5390
|
|
|
5391
5391
|
const run = () => {
|
|
5392
5392
|
const width = window.innerWidth;
|
package/lib/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { batch, effect, effectScope, renderEffect, runUntracked, setCurrentScope, signal } from "@pyreon/reactivity";
|
|
2
|
-
import { EMPTY_PROPS, ForSymbol, Fragment, PortalSymbol, captureContextStack, createRef, cx, dispatchToErrorBoundary, h, makeReactiveProps, normalizeStyleValue, onMount, onUnmount, propagateError, reportError, restoreContextStack, runWithHooks, toKebabCase } from "@pyreon/core";
|
|
2
|
+
import { EMPTY_PROPS, ForSymbol, Fragment, PortalSymbol, captureContextStack, createRef, cx, dispatchToErrorBoundary, h, makeReactiveProps, nativeCompat, normalizeStyleValue, onMount, onUnmount, propagateError, reportError, restoreContextStack, runWithHooks, toKebabCase } from "@pyreon/core";
|
|
3
3
|
|
|
4
4
|
//#region src/delegate.ts
|
|
5
5
|
/**
|
|
@@ -66,6 +66,10 @@ function setupDelegation(container) {
|
|
|
66
66
|
while (el && el !== container) {
|
|
67
67
|
const handler = el[prop];
|
|
68
68
|
if (typeof handler === "function") {
|
|
69
|
+
Object.defineProperty(e, "currentTarget", {
|
|
70
|
+
value: el,
|
|
71
|
+
configurable: true
|
|
72
|
+
});
|
|
69
73
|
batch(() => handler(e));
|
|
70
74
|
if (e.cancelBubble) break;
|
|
71
75
|
}
|
|
@@ -77,13 +81,29 @@ function setupDelegation(container) {
|
|
|
77
81
|
|
|
78
82
|
//#endregion
|
|
79
83
|
//#region src/hydration-debug.ts
|
|
80
|
-
let _enabled =
|
|
84
|
+
let _enabled = process.env.NODE_ENV !== "production";
|
|
81
85
|
function enableHydrationWarnings() {
|
|
82
86
|
_enabled = true;
|
|
83
87
|
}
|
|
84
88
|
function disableHydrationWarnings() {
|
|
85
89
|
_enabled = false;
|
|
86
90
|
}
|
|
91
|
+
let _handlers = [];
|
|
92
|
+
/**
|
|
93
|
+
* Register a hydration mismatch handler. Called on every mismatch in BOTH
|
|
94
|
+
* development and production, independent of the dev-mode warn toggle.
|
|
95
|
+
*
|
|
96
|
+
* Mirrors `@pyreon/core`'s `registerErrorHandler` pattern — multiple
|
|
97
|
+
* handlers can be registered; each is called in registration order;
|
|
98
|
+
* handler errors are swallowed so they don't propagate into the
|
|
99
|
+
* framework. Returns an unregister function.
|
|
100
|
+
*/
|
|
101
|
+
function onHydrationMismatch(handler) {
|
|
102
|
+
_handlers.push(handler);
|
|
103
|
+
return () => {
|
|
104
|
+
_handlers = _handlers.filter((h) => h !== handler);
|
|
105
|
+
};
|
|
106
|
+
}
|
|
87
107
|
/**
|
|
88
108
|
* Emit a hydration mismatch warning.
|
|
89
109
|
* @param type - Kind of mismatch
|
|
@@ -91,9 +111,20 @@ function disableHydrationWarnings() {
|
|
|
91
111
|
* @param actual - What the DOM had
|
|
92
112
|
* @param path - Human-readable path in the tree, e.g. "root > div > span"
|
|
93
113
|
*/
|
|
94
|
-
function warnHydrationMismatch(
|
|
95
|
-
if (
|
|
96
|
-
|
|
114
|
+
function warnHydrationMismatch(type, expected, actual, path) {
|
|
115
|
+
if (_enabled) console.warn(`[Pyreon] Hydration mismatch (${type}): expected ${String(expected)}, got ${String(actual)} at ${path}`);
|
|
116
|
+
if (_handlers.length > 0) {
|
|
117
|
+
const ctx = {
|
|
118
|
+
type,
|
|
119
|
+
expected,
|
|
120
|
+
actual,
|
|
121
|
+
path,
|
|
122
|
+
timestamp: Date.now()
|
|
123
|
+
};
|
|
124
|
+
for (const h of _handlers) try {
|
|
125
|
+
h(ctx);
|
|
126
|
+
} catch {}
|
|
127
|
+
}
|
|
97
128
|
}
|
|
98
129
|
|
|
99
130
|
//#endregion
|
|
@@ -279,13 +310,18 @@ function installDevTools() {
|
|
|
279
310
|
});
|
|
280
311
|
const win = window;
|
|
281
312
|
win.$p = {
|
|
313
|
+
/** List all mounted components */
|
|
282
314
|
components: () => devtools.getAllComponents(),
|
|
315
|
+
/** Component tree (roots only) */
|
|
283
316
|
tree: () => devtools.getComponentTree(),
|
|
317
|
+
/** Highlight a component by id */
|
|
284
318
|
highlight: (id) => devtools.highlight(id),
|
|
319
|
+
/** Toggle component inspector overlay */
|
|
285
320
|
inspect: () => {
|
|
286
321
|
if (_overlayActive) disableOverlay();
|
|
287
322
|
else enableOverlay();
|
|
288
323
|
},
|
|
324
|
+
/** Print component count */
|
|
289
325
|
stats: () => {
|
|
290
326
|
const all = devtools.getAllComponents();
|
|
291
327
|
const roots = devtools.getComponentTree();
|
|
@@ -295,6 +331,7 @@ function installDevTools() {
|
|
|
295
331
|
roots: roots.length
|
|
296
332
|
};
|
|
297
333
|
},
|
|
334
|
+
/** Quick help */
|
|
298
335
|
help: () => {
|
|
299
336
|
console.log("[Pyreon] $p commands:\n $p.components() — list all mounted components\n $p.tree() — component tree (roots only)\n $p.highlight(id)— outline a component\n $p.inspect() — toggle component inspector\n $p.stats() — print component count\n $p.help() — this message");
|
|
300
337
|
}
|
|
@@ -303,7 +340,7 @@ function installDevTools() {
|
|
|
303
340
|
|
|
304
341
|
//#endregion
|
|
305
342
|
//#region src/nodes.ts
|
|
306
|
-
const __DEV__$5 =
|
|
343
|
+
const __DEV__$5 = process.env.NODE_ENV !== "production";
|
|
307
344
|
const _countSink$3 = globalThis;
|
|
308
345
|
/**
|
|
309
346
|
* Move all nodes strictly between `start` and `end` into a throwaway
|
|
@@ -835,7 +872,7 @@ function moveEntryBefore(parent, startNode, before) {
|
|
|
835
872
|
|
|
836
873
|
//#endregion
|
|
837
874
|
//#region src/props.ts
|
|
838
|
-
const __DEV__$4 =
|
|
875
|
+
const __DEV__$4 = process.env.NODE_ENV !== "production";
|
|
839
876
|
let _customSanitizer = null;
|
|
840
877
|
/**
|
|
841
878
|
* Set a custom HTML sanitizer used by `innerHTML` and `sanitizeHtml()`.
|
|
@@ -1135,7 +1172,7 @@ function setStaticProp(el, key, value) {
|
|
|
1135
1172
|
|
|
1136
1173
|
//#endregion
|
|
1137
1174
|
//#region src/mount.ts
|
|
1138
|
-
const __DEV__$3 =
|
|
1175
|
+
const __DEV__$3 = process.env.NODE_ENV !== "production";
|
|
1139
1176
|
const _countSink$2 = globalThis;
|
|
1140
1177
|
const noop$1 = () => {};
|
|
1141
1178
|
let _elementDepth = 0;
|
|
@@ -1685,10 +1722,10 @@ function hydrateComponent(vnode, domNode, parent, anchor, path = "root") {
|
|
|
1685
1722
|
const mountCleanups = [];
|
|
1686
1723
|
let nextDom = domNode;
|
|
1687
1724
|
const componentName = vnode.type.name || "Anonymous";
|
|
1688
|
-
const mergedProps = (vnode.children ?? []).length > 0 && vnode.props.children === void 0 ? {
|
|
1725
|
+
const mergedProps = makeReactiveProps((vnode.children ?? []).length > 0 && vnode.props.children === void 0 ? {
|
|
1689
1726
|
...vnode.props,
|
|
1690
1727
|
children: (vnode.children ?? []).length === 1 ? (vnode.children ?? [])[0] : vnode.children ?? []
|
|
1691
|
-
} : vnode.props;
|
|
1728
|
+
} : vnode.props);
|
|
1692
1729
|
let result;
|
|
1693
1730
|
try {
|
|
1694
1731
|
result = runWithHooks(vnode.type, mergedProps);
|
|
@@ -1807,10 +1844,11 @@ function KeepAlive(props) {
|
|
|
1807
1844
|
style: "display: contents"
|
|
1808
1845
|
});
|
|
1809
1846
|
}
|
|
1847
|
+
nativeCompat(KeepAlive);
|
|
1810
1848
|
|
|
1811
1849
|
//#endregion
|
|
1812
1850
|
//#region src/template.ts
|
|
1813
|
-
const __DEV__$2 =
|
|
1851
|
+
const __DEV__$2 = process.env.NODE_ENV !== "production";
|
|
1814
1852
|
const _countSink$1 = globalThis;
|
|
1815
1853
|
/**
|
|
1816
1854
|
* Creates a row/item factory backed by HTML template cloning.
|
|
@@ -1907,6 +1945,7 @@ function _bindDirect(source, updater) {
|
|
|
1907
1945
|
const fn = source;
|
|
1908
1946
|
return renderEffect(() => updater(fn()));
|
|
1909
1947
|
}
|
|
1948
|
+
const TPL_CACHE_MAX = 1024;
|
|
1910
1949
|
const _tplCache = /* @__PURE__ */ new Map();
|
|
1911
1950
|
/**
|
|
1912
1951
|
* Compiler-emitted template instantiation.
|
|
@@ -1937,6 +1976,13 @@ function _tpl(html, bind) {
|
|
|
1937
1976
|
if (!tpl) {
|
|
1938
1977
|
tpl = document.createElement("template");
|
|
1939
1978
|
tpl.innerHTML = html;
|
|
1979
|
+
if (_tplCache.size >= TPL_CACHE_MAX) {
|
|
1980
|
+
const oldest = _tplCache.keys().next().value;
|
|
1981
|
+
if (oldest !== void 0) _tplCache.delete(oldest);
|
|
1982
|
+
}
|
|
1983
|
+
_tplCache.set(html, tpl);
|
|
1984
|
+
} else {
|
|
1985
|
+
_tplCache.delete(html);
|
|
1940
1986
|
_tplCache.set(html, tpl);
|
|
1941
1987
|
}
|
|
1942
1988
|
const el = tpl.content.firstElementChild?.cloneNode(true);
|
|
@@ -1971,7 +2017,7 @@ function _mountSlot(children, parent, placeholder) {
|
|
|
1971
2017
|
|
|
1972
2018
|
//#endregion
|
|
1973
2019
|
//#region src/transition.ts
|
|
1974
|
-
const __DEV__$1 =
|
|
2020
|
+
const __DEV__$1 = process.env.NODE_ENV !== "production";
|
|
1975
2021
|
/**
|
|
1976
2022
|
* Transition — adds CSS enter/leave animation classes to a single child element,
|
|
1977
2023
|
* controlled by the reactive `show` prop.
|
|
@@ -2130,6 +2176,7 @@ function Transition(props) {
|
|
|
2130
2176
|
};
|
|
2131
2177
|
});
|
|
2132
2178
|
}
|
|
2179
|
+
nativeCompat(Transition);
|
|
2133
2180
|
|
|
2134
2181
|
//#endregion
|
|
2135
2182
|
//#region src/transition-group.ts
|
|
@@ -2383,10 +2430,11 @@ function TransitionGroup(props) {
|
|
|
2383
2430
|
});
|
|
2384
2431
|
return h(tag, { ref: containerRef });
|
|
2385
2432
|
}
|
|
2433
|
+
nativeCompat(TransitionGroup);
|
|
2386
2434
|
|
|
2387
2435
|
//#endregion
|
|
2388
2436
|
//#region src/index.ts
|
|
2389
|
-
const __DEV__ =
|
|
2437
|
+
const __DEV__ = process.env.NODE_ENV !== "production";
|
|
2390
2438
|
const _countSink = globalThis;
|
|
2391
2439
|
/**
|
|
2392
2440
|
* Mount a VNode tree into a container element.
|
|
@@ -2414,5 +2462,5 @@ function mount(root, container) {
|
|
|
2414
2462
|
const render = mount;
|
|
2415
2463
|
|
|
2416
2464
|
//#endregion
|
|
2417
|
-
export { DELEGATED_EVENTS, KeepAlive, Transition, TransitionGroup, applyProps as _applyProps, applyProps, _bindDirect, _bindText, _mountSlot, _tpl, applyProp, createTemplate, delegatedPropName, disableHydrationWarnings, enableHydrationWarnings, hydrateRoot, mount, mountChild, render, sanitizeHtml, setSanitizer, setupDelegation };
|
|
2465
|
+
export { DELEGATED_EVENTS, KeepAlive, Transition, TransitionGroup, applyProps as _applyProps, applyProps, _bindDirect, _bindText, _mountSlot, _tpl, applyProp, createTemplate, delegatedPropName, disableHydrationWarnings, enableHydrationWarnings, hydrateRoot, mount, mountChild, onHydrationMismatch, render, sanitizeHtml, setSanitizer, setupDelegation };
|
|
2418
2466
|
//# sourceMappingURL=index.js.map
|
package/lib/keep-alive-entry.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { EMPTY_PROPS, ForSymbol, Fragment, PortalSymbol, captureContextStack, createRef, cx, dispatchToErrorBoundary, h, makeReactiveProps, normalizeStyleValue, onMount, propagateError, reportError, restoreContextStack, runWithHooks, toKebabCase } from "@pyreon/core";
|
|
1
|
+
import { EMPTY_PROPS, ForSymbol, Fragment, PortalSymbol, captureContextStack, createRef, cx, dispatchToErrorBoundary, h, makeReactiveProps, nativeCompat, normalizeStyleValue, onMount, propagateError, reportError, restoreContextStack, runWithHooks, toKebabCase } from "@pyreon/core";
|
|
2
2
|
import { batch, effect, effectScope, renderEffect, runUntracked, setCurrentScope } from "@pyreon/reactivity";
|
|
3
3
|
|
|
4
4
|
//#region src/devtools.ts
|
|
@@ -33,7 +33,7 @@ function unregisterComponent(id) {
|
|
|
33
33
|
|
|
34
34
|
//#endregion
|
|
35
35
|
//#region src/nodes.ts
|
|
36
|
-
const __DEV__$2 =
|
|
36
|
+
const __DEV__$2 = process.env.NODE_ENV !== "production";
|
|
37
37
|
const _countSink$1 = globalThis;
|
|
38
38
|
/**
|
|
39
39
|
* Move all nodes strictly between `start` and `end` into a throwaway
|
|
@@ -605,7 +605,7 @@ function delegatedPropName(eventName) {
|
|
|
605
605
|
|
|
606
606
|
//#endregion
|
|
607
607
|
//#region src/props.ts
|
|
608
|
-
const __DEV__$1 =
|
|
608
|
+
const __DEV__$1 = process.env.NODE_ENV !== "production";
|
|
609
609
|
let _customSanitizer = null;
|
|
610
610
|
const SAFE_TAGS = new Set([
|
|
611
611
|
"a",
|
|
@@ -886,7 +886,7 @@ function setStaticProp(el, key, value) {
|
|
|
886
886
|
|
|
887
887
|
//#endregion
|
|
888
888
|
//#region src/mount.ts
|
|
889
|
-
const __DEV__ =
|
|
889
|
+
const __DEV__ = process.env.NODE_ENV !== "production";
|
|
890
890
|
const _countSink = globalThis;
|
|
891
891
|
const noop = () => {};
|
|
892
892
|
let _elementDepth = 0;
|
|
@@ -1335,6 +1335,7 @@ function KeepAlive(props) {
|
|
|
1335
1335
|
style: "display: contents"
|
|
1336
1336
|
});
|
|
1337
1337
|
}
|
|
1338
|
+
nativeCompat(KeepAlive);
|
|
1338
1339
|
|
|
1339
1340
|
//#endregion
|
|
1340
1341
|
export { KeepAlive };
|
package/lib/transition-entry.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { Fragment, createRef, h, onUnmount } from "@pyreon/core";
|
|
1
|
+
import { Fragment, createRef, h, nativeCompat, onUnmount } from "@pyreon/core";
|
|
2
2
|
import { effect, runUntracked, signal } from "@pyreon/reactivity";
|
|
3
3
|
|
|
4
4
|
//#region src/transition.ts
|
|
5
|
-
const __DEV__ =
|
|
5
|
+
const __DEV__ = process.env.NODE_ENV !== "production";
|
|
6
6
|
/**
|
|
7
7
|
* Transition — adds CSS enter/leave animation classes to a single child element,
|
|
8
8
|
* controlled by the reactive `show` prop.
|
|
@@ -161,6 +161,7 @@ function Transition(props) {
|
|
|
161
161
|
};
|
|
162
162
|
});
|
|
163
163
|
}
|
|
164
|
+
nativeCompat(Transition);
|
|
164
165
|
|
|
165
166
|
//#endregion
|
|
166
167
|
export { Transition };
|
package/lib/types/index.d.ts
CHANGED
|
@@ -85,17 +85,66 @@ declare function hydrateRoot(container: Element, vnode: VNodeChild): () => void;
|
|
|
85
85
|
//#endregion
|
|
86
86
|
//#region src/hydration-debug.d.ts
|
|
87
87
|
/**
|
|
88
|
-
* Hydration mismatch warnings.
|
|
88
|
+
* Hydration mismatch warnings + telemetry hook.
|
|
89
89
|
*
|
|
90
|
-
*
|
|
91
|
-
* Can be toggled manually for testing or verbose production debugging.
|
|
90
|
+
* Two complementary surfaces:
|
|
92
91
|
*
|
|
93
|
-
*
|
|
92
|
+
* 1. **Dev-mode console.warn** — enabled automatically when
|
|
93
|
+
* `NODE_ENV !== "production"` (and silent otherwise, matching React /
|
|
94
|
+
* Vue / Solid). Toggle manually with `enableHydrationWarnings()` /
|
|
95
|
+
* `disableHydrationWarnings()` if you need verbose production debugging.
|
|
96
|
+
*
|
|
97
|
+
* 2. **Telemetry callback** — register a handler with
|
|
98
|
+
* `onHydrationMismatch(handler)` to forward every mismatch into your
|
|
99
|
+
* error-tracking pipeline (Sentry, Datadog, etc.). Fires on EVERY
|
|
100
|
+
* mismatch, in development AND production, regardless of the warn
|
|
101
|
+
* toggle. Returns an unregister function.
|
|
102
|
+
*
|
|
103
|
+
* The dev warn and the telemetry callback are independent: a production
|
|
104
|
+
* deployment can install Sentry forwarding via `onHydrationMismatch`
|
|
105
|
+
* WITHOUT enabling the noisy console output.
|
|
106
|
+
*
|
|
107
|
+
* @example — dev console
|
|
94
108
|
* import { enableHydrationWarnings } from "@pyreon/runtime-dom"
|
|
95
109
|
* enableHydrationWarnings()
|
|
110
|
+
*
|
|
111
|
+
* @example — production telemetry
|
|
112
|
+
* import { onHydrationMismatch } from "@pyreon/runtime-dom"
|
|
113
|
+
* import * as Sentry from "@sentry/browser"
|
|
114
|
+
*
|
|
115
|
+
* onHydrationMismatch(ctx => {
|
|
116
|
+
* Sentry.captureMessage(`Hydration mismatch (${ctx.type})`, {
|
|
117
|
+
* extra: { expected: ctx.expected, actual: ctx.actual, path: ctx.path },
|
|
118
|
+
* level: 'warning',
|
|
119
|
+
* })
|
|
120
|
+
* })
|
|
96
121
|
*/
|
|
97
122
|
declare function enableHydrationWarnings(): void;
|
|
98
123
|
declare function disableHydrationWarnings(): void;
|
|
124
|
+
type HydrationMismatchType = 'tag' | 'text' | 'missing';
|
|
125
|
+
interface HydrationMismatchContext {
|
|
126
|
+
/** Kind of mismatch */
|
|
127
|
+
type: HydrationMismatchType;
|
|
128
|
+
/** What the VNode expected */
|
|
129
|
+
expected: unknown;
|
|
130
|
+
/** What the DOM had */
|
|
131
|
+
actual: unknown;
|
|
132
|
+
/** Human-readable path in the tree, e.g. "root > div > span" */
|
|
133
|
+
path: string;
|
|
134
|
+
/** Unix timestamp (ms) */
|
|
135
|
+
timestamp: number;
|
|
136
|
+
}
|
|
137
|
+
type HydrationMismatchHandler = (ctx: HydrationMismatchContext) => void;
|
|
138
|
+
/**
|
|
139
|
+
* Register a hydration mismatch handler. Called on every mismatch in BOTH
|
|
140
|
+
* development and production, independent of the dev-mode warn toggle.
|
|
141
|
+
*
|
|
142
|
+
* Mirrors `@pyreon/core`'s `registerErrorHandler` pattern — multiple
|
|
143
|
+
* handlers can be registered; each is called in registration order;
|
|
144
|
+
* handler errors are swallowed so they don't propagate into the
|
|
145
|
+
* framework. Returns an unregister function.
|
|
146
|
+
*/
|
|
147
|
+
declare function onHydrationMismatch(handler: HydrationMismatchHandler): () => void;
|
|
99
148
|
//#endregion
|
|
100
149
|
//#region src/keep-alive.d.ts
|
|
101
150
|
interface KeepAliveProps extends Props {
|
|
@@ -410,5 +459,5 @@ declare function mount(root: VNodeChild, container: Element): () => void;
|
|
|
410
459
|
/** Alias for `mount` */
|
|
411
460
|
declare const render: typeof mount;
|
|
412
461
|
//#endregion
|
|
413
|
-
export { DELEGATED_EVENTS, type DevtoolsComponentEntry, KeepAlive, type KeepAliveProps, type PyreonDevtools, type SanitizeFn, Transition, TransitionGroup, type TransitionGroupProps, type TransitionProps, applyProps as _applyProps, applyProps, _bindDirect, _bindText, _mountSlot, _tpl, applyProp, createTemplate, delegatedPropName, disableHydrationWarnings, enableHydrationWarnings, hydrateRoot, mount, mountChild, render, sanitizeHtml, setSanitizer, setupDelegation };
|
|
462
|
+
export { DELEGATED_EVENTS, type DevtoolsComponentEntry, type HydrationMismatchContext, type HydrationMismatchHandler, type HydrationMismatchType, KeepAlive, type KeepAliveProps, type PyreonDevtools, type SanitizeFn, Transition, TransitionGroup, type TransitionGroupProps, type TransitionProps, applyProps as _applyProps, applyProps, _bindDirect, _bindText, _mountSlot, _tpl, applyProp, createTemplate, delegatedPropName, disableHydrationWarnings, enableHydrationWarnings, hydrateRoot, mount, mountChild, onHydrationMismatch, render, sanitizeHtml, setSanitizer, setupDelegation };
|
|
414
463
|
//# sourceMappingURL=index2.d.ts.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pyreon/runtime-dom",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.15.0",
|
|
4
4
|
"description": "DOM renderer for Pyreon",
|
|
5
5
|
"homepage": "https://github.com/pyreon/pyreon/tree/main/packages/runtime-dom#readme",
|
|
6
6
|
"bugs": {
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
},
|
|
15
15
|
"files": [
|
|
16
16
|
"lib",
|
|
17
|
+
"!lib/**/*.map",
|
|
17
18
|
"src",
|
|
18
19
|
"README.md",
|
|
19
20
|
"LICENSE"
|
|
@@ -53,14 +54,14 @@
|
|
|
53
54
|
"prepublishOnly": "bun run build"
|
|
54
55
|
},
|
|
55
56
|
"dependencies": {
|
|
56
|
-
"@pyreon/core": "^0.
|
|
57
|
-
"@pyreon/reactivity": "^0.
|
|
57
|
+
"@pyreon/core": "^0.15.0",
|
|
58
|
+
"@pyreon/reactivity": "^0.15.0"
|
|
58
59
|
},
|
|
59
60
|
"devDependencies": {
|
|
60
61
|
"@happy-dom/global-registrator": "^20.8.9",
|
|
61
|
-
"@pyreon/compiler": "^0.
|
|
62
|
+
"@pyreon/compiler": "^0.15.0",
|
|
62
63
|
"@pyreon/manifest": "0.13.1",
|
|
63
|
-
"@pyreon/runtime-server": "^0.
|
|
64
|
+
"@pyreon/runtime-server": "^0.15.0",
|
|
64
65
|
"@pyreon/test-utils": "^0.13.2",
|
|
65
66
|
"@vitest/browser-playwright": "^4.1.4",
|
|
66
67
|
"esbuild": "^0.28.0",
|
package/src/delegate.ts
CHANGED
|
@@ -70,6 +70,22 @@ export function setupDelegation(container: Element): void {
|
|
|
70
70
|
while (el && el !== container) {
|
|
71
71
|
const handler = el[prop]
|
|
72
72
|
if (typeof handler === 'function') {
|
|
73
|
+
// Per-handler `currentTarget` patch: native event delegation leaves
|
|
74
|
+
// `e.currentTarget` as the container (the listener root). Without
|
|
75
|
+
// this override, `ev.currentTarget.value` in user code reads from
|
|
76
|
+
// the container — silently `undefined` for inputs, the wrong tag
|
|
77
|
+
// type, etc. Pyreon's `TargetedEvent<E>` type *promises* the
|
|
78
|
+
// matched element; this override makes the runtime keep that
|
|
79
|
+
// promise, matching what React, Vue, and Solid all do for
|
|
80
|
+
// delegated events.
|
|
81
|
+
//
|
|
82
|
+
// `currentTarget` is a read-only accessor on native Event types,
|
|
83
|
+
// so direct assignment is silently ignored — `Object.defineProperty`
|
|
84
|
+
// with `configurable: true` is the only portable override.
|
|
85
|
+
Object.defineProperty(e, 'currentTarget', {
|
|
86
|
+
value: el,
|
|
87
|
+
configurable: true,
|
|
88
|
+
})
|
|
73
89
|
batch(() => handler(e))
|
|
74
90
|
// Don't break — allow ancestor handlers too (consistent with addEventListener)
|
|
75
91
|
// But if stopPropagation was called, stop walking
|
package/src/hydrate.ts
CHANGED
|
@@ -21,6 +21,7 @@ import {
|
|
|
21
21
|
dispatchToErrorBoundary,
|
|
22
22
|
ForSymbol,
|
|
23
23
|
Fragment,
|
|
24
|
+
makeReactiveProps,
|
|
24
25
|
PortalSymbol,
|
|
25
26
|
reportError,
|
|
26
27
|
runWithHooks,
|
|
@@ -349,7 +350,7 @@ function hydrateComponent(
|
|
|
349
350
|
|
|
350
351
|
// Function.name is always a string per spec; || handles empty string, avoids uncoverable ?? branch
|
|
351
352
|
const componentName = ((vnode.type as ComponentFn).name || 'Anonymous') as string
|
|
352
|
-
const
|
|
353
|
+
const rawProps =
|
|
353
354
|
(vnode.children ?? []).length > 0 &&
|
|
354
355
|
(vnode.props as Record<string, unknown>).children === undefined
|
|
355
356
|
? {
|
|
@@ -359,7 +360,13 @@ function hydrateComponent(
|
|
|
359
360
|
? (vnode.children ?? [])[0]
|
|
360
361
|
: (vnode.children ?? []),
|
|
361
362
|
}
|
|
362
|
-
: vnode.props
|
|
363
|
+
: (vnode.props as Record<string, unknown>)
|
|
364
|
+
// Convert compiler-emitted `_rp(() => expr)` wrappers into getter properties —
|
|
365
|
+
// mirrors mount.ts so component code can read `props.x` and get the resolved
|
|
366
|
+
// value (not the raw `_rp` function). Without this, hydration set up reactive
|
|
367
|
+
// bindings against the wrong values and any signal-driven re-render would
|
|
368
|
+
// diverge from the SSR HTML.
|
|
369
|
+
const mergedProps = makeReactiveProps(rawProps as Record<string, unknown>)
|
|
363
370
|
|
|
364
371
|
let result: ReturnType<typeof runWithHooks>
|
|
365
372
|
try {
|