Monorepo for Aesthetic.Computer aesthetic.computer
4
fork

Configure Feed

Select the types of activity you want to include in your feed.

kidlisp-bundler: drop query suffixes when rewriting relative imports

disk.mjs imports `./l5.mjs?v=20260330-runtime-support` for cache busting.
After resolvePath, the bundler kept the query suffix, producing bare
`lib/l5.mjs?v=20260330-runtime-support` specifiers in the bundled HTML.
The import map only registers `lib/l5.mjs` (no query), so browsers reject
the import with "Failed to resolve module specifier" and the piece never
renders inside the bundled artifact.

This manifested as keep-prepare-background's oven timing out at 150s when
baking thumbnails for any piece whose code path reaches that import — the
iframe loaded a dead module graph and never produced a frame. The silent
thumbnail-fallback path then reused the previous thumbnail URI, making
the failure invisible to users clicking "Regenerate Media".

Fix: strip the query entirely in rewriteImports (blob: URLs in bundled
output are already unique per bundle, no cache bust needed).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

+15 -8
+15 -8
system/backend/kidlisp-bundler.mjs
··· 122 122 return 'import(\'ac/disks/' + p + '\')'; 123 123 }); 124 124 125 - // Rewrite relative imports (strip query params for resolution, then re-add) 126 - code = code.replace(/from\s*['"](\.\.\/[^'"?]+|\.\/[^'"?]+)(\?[^'"]*)?['"]/g, (match, p, query) => { 125 + // Rewrite relative imports. Drop the query suffix entirely — in bundled 126 + // output the import map maps bare `lib/foo.mjs` specifiers to blob: URLs 127 + // that are already unique per bundle, so cache-busting query params like 128 + // `?v=20260330-runtime-support` are not only unneeded but actively break 129 + // resolution (the map has no versioned entry, browser rejects the import). 130 + // This was the cause of the $rip / l5.mjs "Failed to resolve module 131 + // specifier" error that killed in-browser piece execution and made the 132 + // oven's thumbnail capture hang for its full 150s timeout. 133 + code = code.replace(/from\s*['"](\.\.\/[^'"?]+|\.\/[^'"?]+)(\?[^'"]*)?['"]/g, (match, p) => { 127 134 const resolved = resolvePath(filepath, p); 128 - return 'from"' + resolved + (query || '') + '"'; 135 + return 'from"' + resolved + '"'; 129 136 }); 130 137 131 - // Rewrite dynamic imports (strip query params for resolution, then re-add) 132 - code = code.replace(/import\s*\((['"](\.\.\/[^'"?]+|\.\/[^'"?]+)(\?[^'"]*)?)['"](\))\)/g, (match, fullPath, p, query, closing) => { 138 + // Rewrite dynamic imports (same query-drop logic) 139 + code = code.replace(/import\s*\((['"](\.\.\/[^'"?]+|\.\/[^'"?]+)(\?[^'"]*)?)['"](\))\)/g, (match, fullPath, p) => { 133 140 const resolved = resolvePath(filepath, p); 134 - return 'import("' + resolved + (query || '') + '")'; 141 + return 'import("' + resolved + '")'; 135 142 }); 136 143 137 - code = code.replace(/import\s*\(\`(\.\.\/[^\`?]+)(\?[^\`]*)?\`\)/g, (match, p, query) => { 144 + code = code.replace(/import\s*\(\`(\.\.\/[^\`?]+)(\?[^\`]*)?\`\)/g, (match, p) => { 138 145 const resolved = resolvePath(filepath, p); 139 - return 'import("' + resolved + (query || '') + '")'; 146 + return 'import("' + resolved + '")'; 140 147 }); 141 148 142 149 return code;