release: WRNexusJS 0.2.49

This commit is contained in:
2026-07-19 12:03:49 +05:30
parent 9ca1cc6b0f
commit 1cda2a01b3
2 changed files with 50 additions and 62 deletions
+10 -8
View File
@@ -881,7 +881,7 @@ component Accordion {
expect(output).not.toContain('${(isOpen(index)) ? " open" : ""}');
});
test("server-rendered each locals work in reactive handlers", () => {
test("server-rendered each locals work in reactive handlers", async () => {
const firstLocals = Buffer.from(
JSON.stringify({
item: {
@@ -903,13 +903,12 @@ test("server-rendered each locals work in reactive handlers", () => {
).toString("base64");
const dom = mountHtml(`
<div
data-scope="openIndex: -1"
>
<div data-scope="openIndex: -1">
<article
data-wrn-loop-locals="${firstLocals}"
>
<button
type="button"
data-on-click="openIndex = index"
>
First
@@ -924,6 +923,7 @@ test("server-rendered each locals work in reactive handlers", () => {
data-wrn-loop-locals="${secondLocals}"
>
<button
type="button"
data-on-click="openIndex = index"
>
Second
@@ -936,13 +936,15 @@ test("server-rendered each locals work in reactive handlers", () => {
</div>
`);
const buttons: any = dom.querySelectorAll("button");
const buttons = dom.querySelectorAll("button") as HTMLButtonElement[];
buttons[1].click();
buttons[1]!.click();
await Promise.resolve();
const articles = dom.querySelectorAll("article");
expect(articles[0].querySelector("span")?.classList.contains("open")).toBe(false);
expect(articles[0]!.querySelector("span")?.classList.contains("open")).toBe(false);
expect(articles[1].querySelector("span")?.classList.contains("open")).toBe(true);
expect(articles[1]!.querySelector("span")?.classList.contains("open")).toBe(true);
});
+40 -54
View File
@@ -214,59 +214,6 @@ export const REACTIVE_RUNTIME = String.raw`
var value = initial;
var subscribers = new Set();
var notifying = false;
var pendingNotification = false;
var pendingPrevious;
function notify(previous) {
if (notifying) {
pendingNotification = true;
if (pendingPrevious === undefined) {
pendingPrevious = previous;
}
return;
}
notifying = true;
try {
/*
* Iterate a snapshot. Reactive renderers may subscribe again while
* running, but that must not mutate the collection currently being
* iterated.
*/
var snapshot =
Array.from(subscribers);
snapshot.forEach(function (
subscriber,
) {
if (
subscribers.has(
subscriber,
)
) {
subscriber(
value,
previous,
);
}
});
} finally {
notifying = false;
}
if (pendingNotification) {
var nextPrevious =
pendingPrevious;
pendingNotification = false;
pendingPrevious = undefined;
notify(nextPrevious);
}
}
return {
get: function () {
@@ -286,7 +233,46 @@ export const REACTIVE_RUNTIME = String.raw`
var previous = value;
value = nextValue;
notify(previous);
/*
* Prevent nested synchronous notification of the
* same signal.
*/
if (notifying) {
return;
}
notifying = true;
try {
/*
* Always iterate a snapshot. A renderer can read
* this signal and subscribe again while it runs.
*/
var snapshot =
Array.from(subscribers);
for (
var index = 0;
index < snapshot.length;
index++
) {
var subscriber =
snapshot[index];
if (
subscribers.has(
subscriber,
)
) {
subscriber(
value,
previous,
);
}
}
} finally {
notifying = false;
}
},
subscribe: function (