fix: synchronize mounted component props
Quality / quality (ubuntu-latest) (push) Failing after 9m51s
Quality / quality (windows-latest) (push) Canceled after 0s

This commit is contained in:
2026-08-23 19:42:39 +05:30
parent 56cde5aaf8
commit 53b9947ef9
11 changed files with 159 additions and 10 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/compiler",
"version": "0.8.19",
"version": "0.8.20",
"type": "module",
"main": "src/index.ts",
"exports": {
+13 -3
View File
@@ -834,7 +834,7 @@ function renderPageComponentInvocation(
const attrs = expandBindings(node.attrs)
.filter((attr) => attr.name !== "data-component")
.map((attr) => renderPageComponentAttr(attr, loops))
.map((attr) => renderPageComponentAttr(attr, loops, reactive))
.join("");
const inner = node.children
@@ -3170,7 +3170,11 @@ function __wrnProp(v: unknown): string {
return __wrnAttr(value);
}
function renderPageComponentAttr(attr: Attr, dynamicExpressions: string[]): string {
function renderPageComponentAttr(
attr: Attr,
dynamicExpressions: string[],
reactive: PageReactive | null,
): string {
if (attr.event) {
return ` ${componentEventAttribute(attr.name)}="${attrEscape(attr.value)}"`;
}
@@ -3188,6 +3192,12 @@ function renderPageComponentAttr(attr: Attr, dynamicExpressions: string[]): stri
dynamicExpressions.push(`\${__wrnexusPropAttr(${expression})}`);
const marker = `\x00WRNEACH${dynamicExpressions.length - 1}\x00`;
// The mount disappears during SSR. Preserve every dynamic component prop
// as a parent-owned binding; server-only expressions simply fail closed in
// the browser, while page state can continue driving the mounted child.
const binding = ` data-wrn-prop-bind-${dynamicExpressions.length - 1}="${attrEscape(
JSON.stringify([attr.name, attr.value]),
)}"`;
return ` ${attr.name}="${marker}"`;
return ` ${attr.name}="${marker}"${binding}`;
}
+10
View File
@@ -1151,6 +1151,16 @@ page Home {
expect(output).toContain("__wrnexusPropAttr([");
});
test("page state passed to a component retains a parent-owned prop binding", () => {
const output = generate(
parse(`page Home {
state count = 1
view { <Child value={count} /> }
}`),
);
expect(output).toContain("data-wrn-prop-bind-");
expect(output).toContain("{count}");
});
test("nested component props retain parent-owned reactive bindings", () => {
const output = generate(
parse(`component Parent {