Fix streaming resolve: color dict keys + defer resolveSuspense until after boot

stream-colors dict had green/blue keys but data used emerald/violet — all three
slots now render with correct Tailwind color classes. Platform: resolveSuspense
must not exist on Sx until boot completes, otherwise bootstrap __sxResolve calls
it before web stack loads and resolves silently fail. Moved to post-boot setup
so all pre-boot resolves queue in __sxPending and drain correctly.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-12 09:58:18 +00:00
parent 6e27442d57
commit 56855eee7f
3 changed files with 131 additions and 93 deletions

View File

@@ -103,6 +103,23 @@
});
} else if (opName === "io-navigate") {
// navigation — don't resume
} else if (opName === "text-measure") {
// Pretext: measure text using offscreen canvas
var font = arg;
var size = items && items[2];
var text = items && items[3];
var canvas = document.createElement("canvas");
var ctx = canvas.getContext("2d");
ctx.font = (size || 16) + "px " + (font || "serif");
var m = ctx.measureText(text || "");
try {
driveAsync(result.resume({
width: m.width,
height: m.actualBoundingBoxAscent + m.actualBoundingBoxDescent,
ascent: m.actualBoundingBoxAscent,
descent: m.actualBoundingBoxDescent
}));
} catch(e) { console.error("[sx] driveAsync:", e.message); }
} else {
console.warn("[sx] unhandled IO:", opName);
}
@@ -635,13 +652,6 @@
renderToHtml: function(expr) { return K.renderToHtml(expr); },
callFn: function(fn, args) { return K.callFn(fn, args); },
engine: function() { return K.engine(); },
resolveSuspense: function(id, sx) {
try {
K.eval('(resolve-suspense ' + JSON.stringify(id) + ' ' + JSON.stringify(sx) + ')');
} catch (e) {
console.error("[sx] resolveSuspense error for id=" + id, e);
}
},
// Boot entry point (called by auto-init or manually)
init: function() {
if (typeof K.eval === "function") {
@@ -697,26 +707,15 @@
};
// ================================================================
// Auto-init: load web stack eagerly, boot on DOMContentLoaded
// Auto-init: load web stack and boot on DOMContentLoaded
// ================================================================
if (typeof document !== "undefined") {
loadWebStack();
// Pre-process component scripts eagerly so resolve-suspense doesn't
// hit the 'Undefined symbol: default' error on first call.
// The error occurs during component loading but is non-fatal.
try { K.eval("(process-sx-scripts nil)"); } catch(e) {}
var _doInit = function() {
loadWebStack();
Sx.init();
// Drain streaming resolves that arrived before boot or were deferred on error
if (window.__sxPending) {
for (var pi = 0; pi < window.__sxPending.length; pi++) {
Sx.resolveSuspense(window.__sxPending[pi].id, window.__sxPending[pi].sx);
}
window.__sxPending = null;
}
window.__sxResolve = function(id, sx) { Sx.resolveSuspense(id, sx); };
// Enable JIT after all boot code has run.
// Lazy-load the compiler first — JIT needs it to compile functions.
setTimeout(function() {
if (K.beginModuleLoad) K.beginModuleLoad();
loadLibrary("sx compiler", {});