--- a/packages/compiler/src/codegen.ts +++ b/packages/compiler/src/codegen.ts @@ -859,7 +859,11 @@ out.push(`export async function __wrnexusLoad(ctx: any) {\n${serverLoads.map((entry) => entry.body).join("\n")}\n}`); } if (clientLoads.length > 0) { - out.push(`export const __wrnexusClientLoad = ${JSON.stringify(clientLoads.map((entry) => entry.body))};`); + out.push( + `export async function __wrnexusClientLoad(ctx: any) { +${clientLoads.map((entry) => entry.body).join("\n")} +}`, + ); } } --- a/packages/csr/src/reactive-runtime.ts +++ b/packages/csr/src/reactive-runtime.ts @@ -480,18 +480,39 @@ // signal.subscribe dedupes, so re-subscribing each run is cheap and bounded. var currentRenderer = null; var pendingRenderers = new Set(); - var renderScheduled = false; + var batchDepth = 0; + var flushingRenderers = false; + + function flushRenderers() { + if (flushingRenderers || batchDepth > 0) return; + + flushingRenderers = true; + + try { + while (pendingRenderers.size > 0) { + var queue = Array.from(pendingRenderers); + pendingRenderers.clear(); + queue.forEach(function (run) { run(); }); + } + } finally { + flushingRenderers = false; + } + } function scheduleRenderer(renderer) { pendingRenderers.add(renderer); - if (renderScheduled) return; - renderScheduled = true; - queueMicrotask(function () { - renderScheduled = false; - var queue = Array.from(pendingRenderers); - pendingRenderers.clear(); - queue.forEach(function (run) { run(); }); - }); + flushRenderers(); + } + + function batchUpdates(callback) { + batchDepth++; + + try { + return callback(); + } finally { + batchDepth--; + flushRenderers(); + } } function reactive(fn) { @@ -723,68 +744,70 @@ source, locals, ) { - var statements = - splitStatements(source); + return batchUpdates(function () { + var statements = + splitStatements(source); - for ( - var statementIndex = 0; - statementIndex < - statements.length; - statementIndex++ - ) { - var result = runStatement( - statements[statementIndex], - function (expression) { - return evalExpr( - expression, - locals, - ); - }, - function (name) { - if ( - locals && - Object.prototype - .hasOwnProperty.call( - locals, - name, - ) - ) { - return locals[name]; - } - - return peekScope(name); - }, - function (name, value) { - if ( - locals && - Object.prototype - .hasOwnProperty.call( - locals, - name, - ) - ) { - locals[name] = value; - } else { - writeScope(name, value); - } - }, - function (body) { - return runStmt( - body, - locals, - ); - }, - ); + for ( + var statementIndex = 0; + statementIndex < + statements.length; + statementIndex++ + ) { + var result = runStatement( + statements[statementIndex], + function (expression) { + return evalExpr( + expression, + locals, + ); + }, + function (name) { + if ( + locals && + Object.prototype + .hasOwnProperty.call( + locals, + name, + ) + ) { + return locals[name]; + } + + return peekScope(name); + }, + function (name, value) { + if ( + locals && + Object.prototype + .hasOwnProperty.call( + locals, + name, + ) + ) { + locals[name] = value; + } else { + writeScope(name, value); + } + }, + function (body) { + return runStmt( + body, + locals, + ); + }, + ); - if (result.returned) { - return result; + if (result.returned) { + return result; + } } - } - return { - returned: false, - value: undefined, - }; + return { + returned: false, + value: undefined, + }; + }); } function installBehaviorFunctions(source) {