From 1783f4805a8a661e67fc91360e6d3834881950d8 Mon Sep 17 00:00:00 2001 From: giles Date: Sun, 12 Apr 2026 12:35:37 +0000 Subject: [PATCH] Fix streaming resolveSuspense: use callFn instead of eval string interpolation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The previous K.eval() approach double-escaped backslashes in SX source strings, breaking the \/ → / unescaping that the server serializer adds for HTML safety. Using K.callFn() passes strings directly as arguments, bypassing the escaping problem entirely. Co-Authored-By: Claude Opus 4.6 (1M context) --- hosts/ocaml/browser/sx-platform.js | 3 ++- shared/static/wasm/sx-platform.js | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/hosts/ocaml/browser/sx-platform.js b/hosts/ocaml/browser/sx-platform.js index ab8f6330..a43e690a 100644 --- a/hosts/ocaml/browser/sx-platform.js +++ b/hosts/ocaml/browser/sx-platform.js @@ -700,8 +700,9 @@ K.eval("(handle-popstate " + scrollY + ")"); }); // Wire up streaming suspense resolution + var _resolveFn = K.eval("resolve-suspense"); Sx.resolveSuspense = function(id, sx) { - try { K.eval('(resolve-suspense "' + id.replace(/"/g, '\\"') + '" "' + sx.replace(/\\/g, '\\\\').replace(/"/g, '\\"') + '")'); } + try { K.callFn(_resolveFn, [id, sx]); } catch(e) { console.error("[sx] resolveSuspense error:", e); } }; // Drain any pending resolves that arrived before boot diff --git a/shared/static/wasm/sx-platform.js b/shared/static/wasm/sx-platform.js index ab8f6330..a43e690a 100644 --- a/shared/static/wasm/sx-platform.js +++ b/shared/static/wasm/sx-platform.js @@ -700,8 +700,9 @@ K.eval("(handle-popstate " + scrollY + ")"); }); // Wire up streaming suspense resolution + var _resolveFn = K.eval("resolve-suspense"); Sx.resolveSuspense = function(id, sx) { - try { K.eval('(resolve-suspense "' + id.replace(/"/g, '\\"') + '" "' + sx.replace(/\\/g, '\\\\').replace(/"/g, '\\"') + '")'); } + try { K.callFn(_resolveFn, [id, sx]); } catch(e) { console.error("[sx] resolveSuspense error:", e); } }; // Drain any pending resolves that arrived before boot