({ src, entryDir = '', baseUrl = null, onLine, incremental = false })
| 81 | } |
| 82 | |
| 83 | export async function run({ src, entryDir = '', baseUrl = null, onLine, incremental = false }) { |
| 84 | if (!wasmModule) throw new Error('engine.load() must be called before run()'); |
| 85 | |
| 86 | const srcBytes = TE.encode(src); |
| 87 | if (srcBytes.length > SOURCE_LIMIT) throw new Error(`source exceeds ${SOURCE_LIMIT} bytes`); |
| 88 | |
| 89 | let lockfile = new Map(); |
| 90 | if (integrityActive) { |
| 91 | try { lockfile = await cache.loadLockfile(); } |
| 92 | catch { /* lockfile load failure is non-fatal; treat as empty */ } |
| 93 | } |
| 94 | |
| 95 | /* rt built first (lazy getter) so makeCompilerEnv can decode handles during deferred host calls. */ |
| 96 | const rt = makeRt(() => compilerExports); |
| 97 | |
| 98 | /* Incremental mode reuses the existing wasm instance so module-level state (imports, defs) persists across runs. `onLine` lives in worker.js and is stable, so old env closures still post correctly. */ |
| 99 | let exports; |
| 100 | if (incremental && compilerExports) { |
| 101 | exports = compilerExports; |
| 102 | } else { |
| 103 | const env = makeCompilerEnv({ |
| 104 | getExports: () => compilerExports, |
| 105 | onLine: onLine ?? (() => {}), |
| 106 | fetchedSources, |
| 107 | lockfile, |
| 108 | integrityActive, |
| 109 | rt, |
| 110 | captureHostCall: (id, call) => { pendingHostCalls.set(id, call); }, |
| 111 | }); |
| 112 | ({ exports } = await WebAssembly.instantiate(wasmModule, { env })); |
| 113 | compilerExports = exports; |
| 114 | exports.reset_modules(); |
| 115 | resetNativeTable(); |
| 116 | } |
| 117 | |
| 118 | const writeBytes = (bytes) => { |
| 119 | const ptr = exports.wasm_alloc(Math.max(1, bytes.length)); |
| 120 | new Uint8Array(exports.memory.buffer, ptr, bytes.length).set(bytes); |
| 121 | return ptr; |
| 122 | }; |
| 123 | |
| 124 | /* Register a main-thread module at `mt:<name>`: push a stub per export (the real call defers to the page) and tell the compiler its export names. */ |
| 125 | const registerHost = (name, exportNames) => { |
| 126 | const baseId = nativeTable.length; |
| 127 | for (const fnName of exportNames) { |
| 128 | const stub = () => {}; |
| 129 | stub.__edge_kind = 'capability'; |
| 130 | stub.__edge_main_thread = true; |
| 131 | stub.__edge_name = fnName; |
| 132 | stub.__edge_module = name; |
| 133 | nativeTable.push(stub); |
| 134 | } |
| 135 | const specBytes = TE.encode(`mt:${name}`); |
| 136 | const namesBytes = TE.encode(exportNames.join('\n')); |
| 137 | exports.register_native_module( |
| 138 | writeBytes(specBytes), specBytes.length, |
| 139 | writeBytes(namesBytes), namesBytes.length, |
| 140 | baseId, |
nothing calls this directly
no test coverage detected