fix: synchronize forwarded component props
Quality / quality (ubuntu-latest) (push) Failing after 10m57s
Quality / quality (windows-latest) (push) Canceled after 0s

This commit is contained in:
2026-08-23 20:20:43 +05:30
parent f13e83fd74
commit 1a94179b5f
4 changed files with 28 additions and 6 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/csr",
"version": "0.8.32",
"version": "0.8.33",
"type": "module",
"main": "src/index.ts",
"exports": {
+10 -4
View File
@@ -2775,9 +2775,15 @@ export const REACTIVE_RUNTIME = String.raw`
// server forwards these markers onto the rendered child root; evaluate
// them here and write changes into the child's prop signals.
toArray(el.querySelectorAll("*"))
.filter(isScopeRoot)
.filter(function (node) {
return toArray(node.attributes).some(function (attr) {
return attr.name.indexOf("data-wrn-prop-bind-") === 0;
});
})
.forEach(function (node) {
if (!node.parentNode || ownerScope(node.parentNode) !== el) return;
var targetScope = isScopeRoot(node) ? node : ownerScope(node);
if (!targetScope || targetScope === el) return;
if (!targetScope.parentNode || ownerScope(targetScope.parentNode) !== el) return;
toArray(node.attributes).forEach(function (attr) {
if (attr.name.indexOf("data-wrn-prop-bind-") !== 0) return;
var binding = pairBinding(attr.value);
@@ -2796,9 +2802,9 @@ export const REACTIVE_RUNTIME = String.raw`
});
} catch (_) { return; }
var apply = function () {
if (node.__wrnexusScopeApi) node.__wrnexusScopeApi.set(propName, value);
if (targetScope.__wrnexusScopeApi) targetScope.__wrnexusScopeApi.set(propName, value);
};
if (node.__wrnexusScopeApi) apply();
if (targetScope.__wrnexusScopeApi) apply();
else queueMicrotask(apply);
});
});
+16
View File
@@ -454,6 +454,22 @@ test("parent state updates a mounted child's reactive prop", async () => {
expect(win.document.querySelector("#child-value")?.textContent).toBe("2");
});
test("a prop marker forwarded onto a child control still updates the child scope", async () => {
const win = mount(
`<div data-scope="enabled: false">` +
`<button data-on-click="enabled = true">enable</button>` +
`<div data-scope="disabled: true">` +
`<button id="child" disabled data-wrn-bind-0='["disabled","{disabled}"]' ` +
`data-wrn-prop-bind-0='["disabled","{!enabled}"]'>child</button>` +
`</div></div>`,
);
await Promise.resolve();
const buttons = win.document.querySelectorAll("button");
expect((buttons[1] as unknown as HTMLButtonElement).disabled).toBe(true);
(buttons[0] as unknown as HTMLElement).click();
expect((buttons[1] as unknown as HTMLButtonElement).disabled).toBe(false);
});
test("independent signals in one scope update correctly (dependency tracking)", () => {
const win = mount(
`<div data-scope="a: 0, b: 100">