fix(compiler): preserve server-only loader text and control blocks

This commit is contained in:
Clintchiz committed 2026-08-26 12:25:26 +05:30
1 parent aec1dc6056
commit bfa72d5679
4 files changed
+36 -6

No files matched your search

+18 -3
View File
@@ -417,15 +417,17 @@ function substituteReactiveText(
dynamicExpressions?: string[],
): string {
const text = substituteTMarkers(raw);
if (!reactive || reactive.stateNames.size === 0) return text;
if (!reactive) return text;
return text.replace(/\{([^{}]+)\}/g, (whole, inner: string) => {
const expr = inner.trim();
if (expr.startsWith("t:") || !exprRefsState(expr, reactive.stateNames)) return whole;
const clientReactive = exprRefsState(expr, reactive.stateNames);
if (expr.startsWith("t:")) return whole;
if (exprRefsState(expr, reactive.runtimeStateNames) && dynamicExpressions) {
dynamicExpressions.push(`\${__wrnexusEscapeHtml(${expr})}`);
const sentinel = `\x00WRNEACH${dynamicExpressions.length - 1}\x00`;
return `<span data-text="${attrEscape(expr)}">${sentinel}</span>`;
return clientReactive ? `<span data-text="${attrEscape(expr)}">${sentinel}</span>` : sentinel;
}
if (!clientReactive) return whole;
let value: unknown;
try {
value = new Function("with(this){return (" + expr + ");}").call(reactive.scope);
@@ -660,6 +662,19 @@ function renderNode(
// templateEscape, swapped for its real `${…}` code after escaping.
if (node.type === "each" || node.type === "if") {
loops.push(node.type === "each" ? compileEachExpr(node) : compileIfExpr(node));
const conditions =
node.type === "each"
? [node.list]
: node.branches.flatMap((branch) => (branch.cond ? [branch.cond] : []));
// Server-only loader values are not serialized into browser state. Their
// controls must not be re-evaluated by a surrounding component's hydration.
if (
reactive &&
conditions.some((condition) => exprRefsState(condition, reactive.runtimeStateNames)) &&
!conditions.some((condition) => exprRefsState(condition, reactive.stateNames))
) {
return `\x00WRNEACH${loops.length - 1}\x00`;
}
const definition =
node.type === "each"
? {