fix(code): Workers 實部署修正 —— wasmfile+Module 載入 + tick-budget timeout(CF 實測)

leo21c 實部署發現兩個 CF 限制並修正:
1. CF 禁 runtime 從 bytes 編譯 wasm(WebAssembly.instantiate(bytes) 被 embedder 擋)
   → singlefile(base64) 內嵌不可用。改 wasmfile variant + `import wasm from './vendor/quickjs.wasm'`
   (wrangler CompiledWasm rule 綁成預編 WebAssembly.Module),newVariant({wasmModule}) 注入。
   sandbox 改 variant 注入制(setVariant):Worker 注 wrangler Module、Node 由 bytes 建 Module,
   同一 production 路徑受測。vendor/quickjs.wasm 由 postinstall 自 node_modules 複製(gitignored)。
2. CF 凍結同步執行期 Date.now → wall-clock deadline 對純同步迴圈失效(撞 CF CPU 回 1102)。
   改指令計數 interrupt(max_ticks,CF-safe),wall-clock 留 Node 保護。校準:cadence≈5000
   指令/tick、真實 card 解析≈4 ticks、CF 門檻≈1000+ ticks → 預設 max_ticks=500。
   有 body 的迴圈(含 100M 迴圈)皆乾淨回 TimeoutError;空體 while(true){} 仍由 CF CPU guard 容納。

Worker live: arcrun-code.leo21c.workers.dev(cypher-executor 以此 workers.dev 慣例位址呼叫)。
Node 單測 12/12 綠(wasmfile variant + 注入 Module,同 production 路徑)。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HJiLCRUU2o3aSpPEzVCt2o
This commit is contained in:
Leo
2026-07-06 05:15:50 +00:00
parent 1a7b4639c3
commit 08a79229a5
6 changed files with 1057 additions and 70 deletions
+14 -3
View File
@@ -5,8 +5,11 @@
* → QuickJS-wasm 沙箱(./sandbox.mjs 的 runCode
* → { success:true, data } | { success:false, error, error_type }
*
* 封裝=Aquickjs-emscripten singlefile variantwasm 內嵌為 base64、同步載入,
* bundler 友善、無需 [[wasm_modules]] 綁定、無需 nodejs_compatsandbox 用 TextEncoder 計 bytes
* 封裝=Aquickjs-emscripten wasmfile variant。關鍵:CF Workers 禁止 runtime 從 bytes
* 編譯 wasmWebAssembly.instantiate(bytes) 被 embedder 擋),故不能用 singlefile(base64) 內嵌
* 改為 `import wasm from '.../wasm'` 讓 wrangler 在 build 時把 .wasm 綁成一個「已編好的
* WebAssembly.Module」,再以 newVariant({ wasmModule }) 注入沙箱 → 執行期只 instantiate 既有
* Module、不編譯,合 Workers 規則。無需 nodejs_compatsandbox 用 TextEncoder 計 bytes)。
*
* 與其他 logic 零件不同:`code` 是自足 Worker(自帶 index.ts + sandbox.mjs + quickjs variant),
* 不走 component-worker-template 的 TinyGo-wasm bundling 流程。部署見 DEPLOY.md。
@@ -14,8 +17,16 @@
import { Hono } from 'hono';
import { cors } from 'hono/cors';
import { newVariant } from 'quickjs-emscripten-core';
import baseVariant from '@jitl/quickjs-wasmfile-release-sync';
// wrangler 把相對路徑 .wasm import 綁成 WebAssembly.Modulebuild 時編好,執行期不重編)。
// wasm 從 quickjs-wasmfile-release-sync vendored 進 vendor/(見 DEPLOY.md「vendor 步驟」)。
import wasmModule from './vendor/quickjs.wasm';
// @ts-expect-error —— sandbox.mjs 為 runtime-agnostic JS 核心(Node 測試與 Worker 共用同一份)
import { runCode } from './sandbox.mjs';
import { runCode, setVariant } from './sandbox.mjs';
// 注入預編 Module(模組載入時一次)。之後 runCode 只 instantiate、不編譯。
setVariant(newVariant(baseVariant, { wasmModule: wasmModule as WebAssembly.Module }));
const app = new Hono();
app.use('*', cors());