wasm-idle 0.6.1 → 0.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/README.md +77 -11
  2. package/dist/clangd/session.js +1 -1
  3. package/dist/clangd/worker.js +1 -1
  4. package/dist/lsp/cpp/server.js +1 -1
  5. package/dist/lsp/python/server.js +1 -1
  6. package/dist/playground/assets.d.ts +43 -0
  7. package/dist/playground/assets.js +164 -0
  8. package/dist/playground/elixir.d.ts +32 -0
  9. package/dist/playground/elixir.js +173 -0
  10. package/dist/playground/go.d.ts +31 -0
  11. package/dist/playground/go.js +166 -0
  12. package/dist/playground/index.js +36 -1
  13. package/dist/playground/ocaml.d.ts +32 -0
  14. package/dist/playground/ocaml.js +341 -0
  15. package/dist/playground/options.d.ts +4 -0
  16. package/dist/playground/tinygo.d.ts +75 -0
  17. package/dist/playground/tinygo.js +510 -0
  18. package/dist/playground/wasmElixirVersion.d.ts +1 -0
  19. package/dist/playground/wasmElixirVersion.js +1 -0
  20. package/dist/playground/wasmGoVersion.d.ts +1 -0
  21. package/dist/playground/wasmGoVersion.js +1 -0
  22. package/dist/playground/wasmOcamlVersion.d.ts +1 -0
  23. package/dist/playground/wasmOcamlVersion.js +1 -0
  24. package/dist/playground/wasmRustVersion.d.ts +1 -1
  25. package/dist/playground/wasmRustVersion.js +1 -1
  26. package/dist/playground/wasmTinyGoVersion.d.ts +1 -0
  27. package/dist/playground/wasmTinyGoVersion.js +1 -0
  28. package/dist/playground/worker/elixir.d.ts +1 -0
  29. package/dist/playground/worker/elixir.js +591 -0
  30. package/dist/playground/worker/go.d.ts +1 -0
  31. package/dist/playground/worker/go.js +163 -0
  32. package/dist/playground/worker/ocaml.d.ts +1 -0
  33. package/dist/playground/worker/ocaml.js +449 -0
  34. package/dist/playground/worker/tinygo.d.ts +1 -0
  35. package/dist/playground/worker/tinygo.js +140 -0
  36. package/dist/terminal/Terminal.svelte +69 -29
  37. package/dist/utils/vscodeJsonrpcBrowser.d.ts +5 -0
  38. package/dist/utils/vscodeJsonrpcBrowser.js +4 -0
  39. package/package.json +33 -21
@@ -0,0 +1,163 @@
1
+ import { waitForBufferedStdin } from '../stdinBuffer';
2
+ self.document = {
3
+ querySelectorAll() {
4
+ return [];
5
+ }
6
+ };
7
+ let stdinBufferGo = null;
8
+ let compilerUrl = '';
9
+ let loadedCompilerUrl = '';
10
+ let compilerPromise = null;
11
+ let compiledArtifact = null;
12
+ let compiledCacheKey = '';
13
+ async function loadCompiler(url) {
14
+ if (!url) {
15
+ throw new Error('Go runtime is not configured. Set PUBLIC_WASM_GO_COMPILER_URL or runtimeAssets.go.compilerUrl.');
16
+ }
17
+ if (loadedCompilerUrl === url && compilerPromise) {
18
+ return await compilerPromise;
19
+ }
20
+ loadedCompilerUrl = url;
21
+ compiledArtifact = null;
22
+ compiledCacheKey = '';
23
+ compilerPromise = (async () => {
24
+ const module = await import(/* @vite-ignore */ url);
25
+ const factory = typeof module.createGoCompiler === 'function'
26
+ ? module.createGoCompiler
27
+ : typeof module.default === 'function'
28
+ ? module.default
29
+ : null;
30
+ if (!factory) {
31
+ throw new Error('wasm-go module must export createGoCompiler or a default factory');
32
+ }
33
+ if (typeof module.executeBrowserGoArtifact !== 'function') {
34
+ throw new Error('wasm-go module must export executeBrowserGoArtifact');
35
+ }
36
+ return {
37
+ compiler: await factory(),
38
+ executeBrowserGoArtifact: module.executeBrowserGoArtifact
39
+ };
40
+ })();
41
+ return await compilerPromise;
42
+ }
43
+ function normalizeDiagnostic(diagnostic) {
44
+ return {
45
+ fileName: diagnostic?.fileName ?? null,
46
+ lineNumber: Math.max(1, Number(diagnostic?.lineNumber || 1)),
47
+ columnNumber: typeof diagnostic?.columnNumber === 'number'
48
+ ? Math.max(1, diagnostic.columnNumber)
49
+ : undefined,
50
+ severity: diagnostic?.severity === 'warning' || diagnostic?.severity === 'other'
51
+ ? diagnostic.severity
52
+ : 'error',
53
+ message: String(diagnostic?.message || '')
54
+ };
55
+ }
56
+ self.onmessage = async (event) => {
57
+ const { load, compilerUrl: nextCompilerUrl, buffer, code, prepare, args = [], target = 'wasip1/wasm', log } = event.data;
58
+ try {
59
+ if (load) {
60
+ compilerUrl = nextCompilerUrl;
61
+ if (log) {
62
+ console.log(`[wasm-idle:go-worker] load compilerUrl=${compilerUrl}`);
63
+ }
64
+ await loadCompiler(compilerUrl);
65
+ postMessage({ load: true });
66
+ return;
67
+ }
68
+ stdinBufferGo = new Int32Array(buffer);
69
+ const runtime = await loadCompiler(compilerUrl);
70
+ const compileCacheKey = `${target}\n${code}`;
71
+ if (!compiledArtifact || compiledCacheKey !== compileCacheKey) {
72
+ if (log) {
73
+ console.log(`[wasm-idle:go-worker] compile start prepare=${String(prepare)} target=${target} bytes=${code.length}`);
74
+ }
75
+ const result = await runtime.compiler.compile({
76
+ code,
77
+ target,
78
+ prepare,
79
+ log,
80
+ onProgress(progress) {
81
+ postMessage({ progress });
82
+ }
83
+ });
84
+ if (log) {
85
+ console.log(`[wasm-idle:go-worker] compile settled success=${String(result.success)} hasWasm=${String(Boolean(result.artifact?.wasm))} stdout=${String(Boolean(result.stdout))} stderr=${String(Boolean(result.stderr))}`);
86
+ }
87
+ for (const diagnostic of result.diagnostics || []) {
88
+ postMessage({ diagnostic: normalizeDiagnostic(diagnostic) });
89
+ }
90
+ if (result.stdout)
91
+ postMessage({ output: result.stdout });
92
+ if (!result.success) {
93
+ throw new Error(result.stderr ||
94
+ result.diagnostics?.map((diagnostic) => diagnostic.message).join('\n') ||
95
+ 'Go compilation failed');
96
+ }
97
+ if (result.stderr)
98
+ postMessage({ output: result.stderr });
99
+ if (!result.artifact?.wasm) {
100
+ throw new Error('wasm-go did not return a wasm artifact');
101
+ }
102
+ compiledArtifact = result.artifact;
103
+ compiledCacheKey = compileCacheKey;
104
+ if (log) {
105
+ console.log(`[wasm-idle:go-worker] cached artifact target=${compiledArtifact.target} format=${compiledArtifact.format}`);
106
+ }
107
+ }
108
+ if (prepare) {
109
+ if (log) {
110
+ console.log('[wasm-idle:go-worker] prepare complete');
111
+ }
112
+ postMessage({ results: true });
113
+ return;
114
+ }
115
+ if (log) {
116
+ console.log(`[wasm-idle:go-worker] runtime start target=${compiledArtifact.target} format=${compiledArtifact.format}`);
117
+ }
118
+ const execution = await runtime.executeBrowserGoArtifact(compiledArtifact, {
119
+ args,
120
+ env: {
121
+ USER: 'jungol'
122
+ },
123
+ stdin: () => {
124
+ const chunk = waitForBufferedStdin(stdinBufferGo, () => postMessage({ buffer: true }));
125
+ if (chunk == null) {
126
+ if (log) {
127
+ console.log('[wasm-idle:go-stdin] fd_read(bytes=0, eof=true)');
128
+ }
129
+ return null;
130
+ }
131
+ if (log) {
132
+ console.log(`[wasm-idle:go-stdin] fd_fill(bytes=${new TextEncoder().encode(chunk).byteLength}, text=${JSON.stringify(chunk)})`);
133
+ }
134
+ return chunk;
135
+ },
136
+ stdout: (output) => {
137
+ if (output) {
138
+ postMessage({ output });
139
+ }
140
+ },
141
+ stderr: (output) => {
142
+ if (output) {
143
+ postMessage({ output });
144
+ }
145
+ }
146
+ });
147
+ if (log) {
148
+ console.log(`[wasm-idle:go-worker] wasi run complete exitCode=${String(execution.exitCode)}`);
149
+ }
150
+ if (execution.exitCode !== 0) {
151
+ throw new Error(execution.stderr
152
+ ? `Go program exited with code ${execution.exitCode}\n${execution.stderr}`
153
+ : `Go program exited with code ${execution.exitCode}`);
154
+ }
155
+ postMessage({ results: true });
156
+ }
157
+ catch (error) {
158
+ if (log) {
159
+ console.error('[wasm-idle:go-worker] failed', error);
160
+ }
161
+ postMessage({ error: error?.message || String(error) });
162
+ }
163
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,449 @@
1
+ import { waitForBufferedStdin } from '../stdinBuffer';
2
+ let moduleUrl = '';
3
+ let manifestUrl = '';
4
+ let loadedModuleUrl = '';
5
+ let loadedManifestUrl = '';
6
+ let compilerPromise = null;
7
+ let manifestPromise = null;
8
+ let compiledResult = null;
9
+ let compiledCacheKey = '';
10
+ let stdinBufferOcaml = null;
11
+ function appendTrailingNewline(text) {
12
+ return text.endsWith('\n') ? text : `${text}\n`;
13
+ }
14
+ function normalizeAssetLoader(programSource, runtimePromiseKey) {
15
+ let normalizedSource = programSource.includes('($=>async a=>{')
16
+ ? programSource.replace('($=>async a=>{', `globalThis.${runtimePromiseKey}=($=>async a=>{`)
17
+ : programSource;
18
+ const assetLoaderPattern = /function ([A-Za-z$_][\w$]*)\(([A-Za-z$_][\w$]*)\)\{const ([A-Za-z$_][\w$]*)=([A-Za-z$_][\w$]*)\?new URL\(\2,\4\):\2;return fetch\(\3\)\}/;
19
+ const matchedLoader = normalizedSource.match(assetLoaderPattern);
20
+ if (!matchedLoader) {
21
+ return normalizedSource;
22
+ }
23
+ const loaderName = matchedLoader[1] || 'loadAsset';
24
+ const argumentName = matchedLoader[2] || 'assetPath';
25
+ const resolvedName = matchedLoader[3] || 'resolvedUrl';
26
+ const baseName = matchedLoader[4] || 'scriptUrl';
27
+ return normalizedSource.replace(assetLoaderPattern, `function ${loaderName}(${argumentName}){if(globalThis.__wasm_of_js_of_ocaml_resolve_asset){const resolvedAsset=globalThis.__wasm_of_js_of_ocaml_resolve_asset(${argumentName});if(resolvedAsset)return fetch(resolvedAsset)}const ${resolvedName}=${baseName}?new URL(${argumentName},${baseName}):${argumentName};return fetch(${resolvedName})}`);
28
+ }
29
+ function rewriteAbsoluteBundleUrl(url, currentManifestUrl) {
30
+ if (!url || /^[a-z]+:/i.test(url)) {
31
+ return url;
32
+ }
33
+ const manifestLocation = new URL(currentManifestUrl, self.location.href);
34
+ const basePath = manifestLocation.pathname.replace(/\/wasm-of-js-of-ocaml\/browser-native-bundle\/browser-native-manifest\.v1\.json$/, '');
35
+ return new URL(`${basePath}${url}`, manifestLocation.origin).toString();
36
+ }
37
+ function rewriteManifest(manifest, currentManifestUrl) {
38
+ return {
39
+ ...manifest,
40
+ findlibConf: rewriteAbsoluteBundleUrl(manifest.findlibConf, currentManifestUrl),
41
+ tools: {
42
+ ocamlc: rewriteAbsoluteBundleUrl(manifest.tools.ocamlc, currentManifestUrl),
43
+ js_of_ocaml: rewriteAbsoluteBundleUrl(manifest.tools.js_of_ocaml, currentManifestUrl),
44
+ wasm_of_ocaml: rewriteAbsoluteBundleUrl(manifest.tools.wasm_of_ocaml, currentManifestUrl)
45
+ },
46
+ ...(manifest.binaryenTools
47
+ ? {
48
+ binaryenTools: {
49
+ wasm_opt: rewriteAbsoluteBundleUrl(manifest.binaryenTools.wasm_opt, currentManifestUrl),
50
+ wasm_merge: rewriteAbsoluteBundleUrl(manifest.binaryenTools.wasm_merge, currentManifestUrl),
51
+ wasm_metadce: rewriteAbsoluteBundleUrl(manifest.binaryenTools.wasm_metadce, currentManifestUrl)
52
+ }
53
+ }
54
+ : {}),
55
+ ...(manifest.runtimePack
56
+ ? {
57
+ runtimePack: {
58
+ ...manifest.runtimePack,
59
+ asset: rewriteAbsoluteBundleUrl(manifest.runtimePack.asset, currentManifestUrl),
60
+ index: rewriteAbsoluteBundleUrl(manifest.runtimePack.index, currentManifestUrl)
61
+ }
62
+ }
63
+ : {}),
64
+ ocamlLibFiles: manifest.ocamlLibFiles.map((file) => ({
65
+ ...file,
66
+ ...(file.url ? { url: rewriteAbsoluteBundleUrl(file.url, currentManifestUrl) } : {})
67
+ })),
68
+ packages: manifest.packages.map((manifestPackage) => ({
69
+ ...manifestPackage,
70
+ files: manifestPackage.files.map((file) => ({
71
+ ...file,
72
+ ...(file.url ? { url: rewriteAbsoluteBundleUrl(file.url, currentManifestUrl) } : {})
73
+ }))
74
+ }))
75
+ };
76
+ }
77
+ async function loadCompiler(nextModuleUrl) {
78
+ if (!nextModuleUrl) {
79
+ throw new Error('OCaml runtime is not configured. Set runtimeAssets.ocaml.moduleUrl and runtimeAssets.ocaml.manifestUrl or sync the bundled wasm-of-js-of-ocaml assets.');
80
+ }
81
+ if (loadedModuleUrl === nextModuleUrl && compilerPromise) {
82
+ return await compilerPromise;
83
+ }
84
+ loadedModuleUrl = nextModuleUrl;
85
+ compiledResult = null;
86
+ compiledCacheKey = '';
87
+ compilerPromise = (async () => {
88
+ const module = (await import(/* @vite-ignore */ nextModuleUrl));
89
+ if (typeof module.compile !== 'function') {
90
+ throw new Error('wasm-of-js-of-ocaml bundle must export compile');
91
+ }
92
+ if (typeof module.createBrowserWorkerSystemDispatcher !== 'function') {
93
+ throw new Error('wasm-of-js-of-ocaml bundle must export createBrowserWorkerSystemDispatcher');
94
+ }
95
+ return module;
96
+ })();
97
+ return await compilerPromise;
98
+ }
99
+ async function loadManifest(nextManifestUrl) {
100
+ if (!nextManifestUrl) {
101
+ throw new Error('OCaml runtime is not configured. Set runtimeAssets.ocaml.moduleUrl and runtimeAssets.ocaml.manifestUrl or sync the bundled wasm-of-js-of-ocaml assets.');
102
+ }
103
+ if (loadedManifestUrl === nextManifestUrl && manifestPromise) {
104
+ return await manifestPromise;
105
+ }
106
+ loadedManifestUrl = nextManifestUrl;
107
+ compiledResult = null;
108
+ compiledCacheKey = '';
109
+ manifestPromise = (async () => {
110
+ const response = await fetch(nextManifestUrl, { cache: 'no-store' });
111
+ if (!response.ok) {
112
+ throw new Error(`failed to fetch OCaml manifest: ${response.status}`);
113
+ }
114
+ return rewriteManifest((await response.json()), nextManifestUrl);
115
+ })();
116
+ return await manifestPromise;
117
+ }
118
+ function getJsArtifact(result) {
119
+ const programArtifact = result.artifacts.find((artifact) => artifact.kind === 'js' && typeof artifact.data === 'string');
120
+ if (!programArtifact || typeof programArtifact.data !== 'string') {
121
+ throw new Error('OCaml compile result did not include a JavaScript artifact');
122
+ }
123
+ return programArtifact;
124
+ }
125
+ async function executeCompileResult(result, log = false) {
126
+ const programArtifact = getJsArtifact(result);
127
+ const assetFiles = result.artifacts.filter((artifact) => artifact.kind === 'wasm' || artifact.kind === 'asset');
128
+ const assetResolverKey = '__wasm_of_js_of_ocaml_resolve_asset';
129
+ const runtimePromiseKey = '__wasm_of_js_of_ocaml_runtime_promise';
130
+ const stdinHookKey = '__wasmIdleOcamlReadStdin';
131
+ const sourceDir = programArtifact.path.replace(/\/[^/]+$/, '');
132
+ const createdObjectUrls = [];
133
+ const stdinEncoder = new TextEncoder();
134
+ let stdinChunkOcaml = new Uint8Array(0);
135
+ let stdinChunkOffsetOcaml = 0;
136
+ const originalConsole = globalThis.console;
137
+ const originalFetch = globalThis.fetch.bind(globalThis);
138
+ const originalInstantiate = WebAssembly.instantiate.bind(WebAssembly);
139
+ const originalInstantiateStreaming = WebAssembly.instantiateStreaming
140
+ ? WebAssembly.instantiateStreaming.bind(WebAssembly)
141
+ : undefined;
142
+ const runtimeGlobal = globalThis;
143
+ const hadProcess = Object.prototype.hasOwnProperty.call(runtimeGlobal, 'process');
144
+ const hadRequire = Object.prototype.hasOwnProperty.call(runtimeGlobal, 'require');
145
+ const hadModule = Object.prototype.hasOwnProperty.call(runtimeGlobal, 'module');
146
+ const hadExports = Object.prototype.hasOwnProperty.call(runtimeGlobal, 'exports');
147
+ const hadFs = Object.prototype.hasOwnProperty.call(runtimeGlobal, 'fs');
148
+ const originalProcess = runtimeGlobal.process;
149
+ const originalRequire = runtimeGlobal.require;
150
+ const originalModule = runtimeGlobal.module;
151
+ const originalExports = runtimeGlobal.exports;
152
+ const originalFs = runtimeGlobal.fs;
153
+ const hadStdinHook = Object.prototype.hasOwnProperty.call(runtimeGlobal, stdinHookKey);
154
+ const originalStdinHook = runtimeGlobal[stdinHookKey];
155
+ const assetEntries = assetFiles
156
+ .filter((artifact) => artifact.data instanceof Uint8Array)
157
+ .map((assetFile) => {
158
+ const copiedAssetData = new Uint8Array(assetFile.data.byteLength);
159
+ copiedAssetData.set(assetFile.data);
160
+ const objectUrl = URL.createObjectURL(new Blob([copiedAssetData], {
161
+ type: assetFile.path.endsWith('.wasm')
162
+ ? 'application/wasm'
163
+ : 'application/octet-stream'
164
+ }));
165
+ createdObjectUrls.push(objectUrl);
166
+ const relativeFromSourceDir = assetFile.path.startsWith(`${sourceDir}/`)
167
+ ? assetFile.path.slice(sourceDir.length + 1)
168
+ : assetFile.path.replace(/^\/+/, '');
169
+ return {
170
+ path: assetFile.path,
171
+ basename: assetFile.path.split('/').at(-1) || assetFile.path,
172
+ relativeFromSourceDir,
173
+ objectUrl
174
+ };
175
+ });
176
+ const resolveAsset = (requestedAsset) => {
177
+ const candidates = [String(requestedAsset)];
178
+ try {
179
+ candidates.push(new URL(String(requestedAsset), self.location.href).pathname);
180
+ }
181
+ catch {
182
+ // ignore
183
+ }
184
+ for (const assetEntry of assetEntries) {
185
+ if (candidates.some((candidate) => candidate === assetEntry.path ||
186
+ candidate === assetEntry.relativeFromSourceDir ||
187
+ candidate.endsWith(`/${assetEntry.relativeFromSourceDir}`) ||
188
+ candidate.endsWith(`/${assetEntry.basename}`))) {
189
+ return assetEntry.objectUrl;
190
+ }
191
+ }
192
+ return null;
193
+ };
194
+ const readOcamlStdinBytes = (requestedBytes) => {
195
+ if (!stdinBufferOcaml) {
196
+ return null;
197
+ }
198
+ if (requestedBytes <= 0) {
199
+ return new Uint8Array(0);
200
+ }
201
+ while (stdinChunkOffsetOcaml >= stdinChunkOcaml.length) {
202
+ const chunk = waitForBufferedStdin(stdinBufferOcaml, () => postMessage({ buffer: true }));
203
+ if (chunk == null) {
204
+ stdinChunkOcaml = new Uint8Array(0);
205
+ stdinChunkOffsetOcaml = 0;
206
+ return null;
207
+ }
208
+ stdinChunkOcaml = stdinEncoder.encode(chunk);
209
+ stdinChunkOffsetOcaml = 0;
210
+ }
211
+ const end = Math.min(stdinChunkOffsetOcaml + requestedBytes, stdinChunkOcaml.length);
212
+ const bytes = stdinChunkOcaml.slice(stdinChunkOffsetOcaml, end);
213
+ stdinChunkOffsetOcaml = end;
214
+ return bytes;
215
+ };
216
+ globalThis.console = {
217
+ ...originalConsole,
218
+ log: (...args) => {
219
+ postMessage({
220
+ output: appendTrailingNewline(args.map((value) => String(value)).join(' '))
221
+ });
222
+ originalConsole.log(...args);
223
+ },
224
+ info: (...args) => {
225
+ postMessage({
226
+ output: appendTrailingNewline(args.map((value) => String(value)).join(' '))
227
+ });
228
+ originalConsole.info(...args);
229
+ },
230
+ warn: (...args) => {
231
+ postMessage({
232
+ output: appendTrailingNewline(args.map((value) => String(value)).join(' '))
233
+ });
234
+ originalConsole.warn(...args);
235
+ },
236
+ error: (...args) => {
237
+ postMessage({
238
+ output: appendTrailingNewline(args.map((value) => String(value)).join(' '))
239
+ });
240
+ originalConsole.error(...args);
241
+ }
242
+ };
243
+ WebAssembly.instantiate = (async (source, importObject) => {
244
+ return await originalInstantiate(source, importObject);
245
+ });
246
+ if (originalInstantiateStreaming) {
247
+ WebAssembly.instantiateStreaming = (async (source, importObject) => {
248
+ return await originalInstantiateStreaming(source, importObject);
249
+ });
250
+ }
251
+ globalThis[assetResolverKey] = resolveAsset;
252
+ globalThis.fetch = (async (input, init) => {
253
+ const requestUrl = typeof input === 'string' ? input : input instanceof URL ? input.toString() : input.url;
254
+ const resolvedAssetUrl = resolveAsset(requestUrl);
255
+ if (resolvedAssetUrl) {
256
+ return await originalFetch(resolvedAssetUrl, init);
257
+ }
258
+ return await originalFetch(input, init);
259
+ });
260
+ runtimeGlobal.process = undefined;
261
+ runtimeGlobal[stdinHookKey] = (requestedBytes = Number.MAX_SAFE_INTEGER) => {
262
+ const encoded = readOcamlStdinBytes(requestedBytes);
263
+ if (encoded == null) {
264
+ return null;
265
+ }
266
+ let byteString = '';
267
+ for (const byte of encoded) {
268
+ byteString += String.fromCharCode(byte);
269
+ }
270
+ return byteString;
271
+ };
272
+ const stdinFsShim = {
273
+ readSync(fileDescriptor, buffer, offset = 0, length = buffer.byteLength - offset) {
274
+ if (fileDescriptor !== 0 || !stdinBufferOcaml) {
275
+ return 0;
276
+ }
277
+ const encoded = readOcamlStdinBytes(length);
278
+ if (encoded == null) {
279
+ return 0;
280
+ }
281
+ buffer.set(encoded, offset);
282
+ return encoded.byteLength;
283
+ }
284
+ };
285
+ runtimeGlobal.fs = stdinFsShim;
286
+ runtimeGlobal.require = (specifier) => {
287
+ if (specifier === 'fs' || specifier === 'node:fs') {
288
+ return stdinFsShim;
289
+ }
290
+ throw new Error(`unsupported OCaml runtime require: ${specifier}`);
291
+ };
292
+ runtimeGlobal.module = { exports: {} };
293
+ runtimeGlobal.exports = runtimeGlobal.module.exports;
294
+ try {
295
+ let normalizedSource = normalizeAssetLoader(programArtifact.data, runtimePromiseKey);
296
+ const stdinReadReplacement = 'read($1,$2,$3,$4){var e=globalThis.__wasmIdleOcamlReadStdin?globalThis.__wasmIdleOcamlReadStdin($3):null;if(e==null)return 0;var h=e.length,f=new Uint8Array(h),i=0;for(;i<h;i++)f[i]=e.charCodeAt(i);var g=f.length<$3?f.length:$3;$1.set(f.subarray(0,g),$2);return g}';
297
+ const patchedSource = normalizedSource.replace(/read\(([A-Za-z$_][\w$]*),([A-Za-z$_][\w$]*),([A-Za-z$_][\w$]*),([A-Za-z$_][\w$]*)\)\{cz\(\4,mc,aha,ow\)\}/, stdinReadReplacement);
298
+ normalizedSource =
299
+ patchedSource !== normalizedSource
300
+ ? patchedSource
301
+ : normalizedSource.replace(/read\(([A-Za-z$_][\w$]*),([A-Za-z$_][\w$]*),([A-Za-z$_][\w$]*),([A-Za-z$_][\w$]*)\)\{[^{}]+\}(?=seek\([A-Za-z$_][\w$]*,[A-Za-z$_][\w$]*,[A-Za-z$_][\w$]*\)\{[^{}]+\}pos\(\)\{return-1\}close\(\)\{this\.log=undefined\}check_stream_semantics\([A-Za-z$_][\w$]*\)\{\})/, stdinReadReplacement);
302
+ normalizedSource = normalizedSource
303
+ .replace(/\bfs\.readSync\(/g, 'globalThis.fs.readSync(')
304
+ .replace(/read:\(([^)]*)\)=>[A-Za-z$_][\w$]*\.readSync\(/g, 'read:($1)=>globalThis.fs.readSync(');
305
+ if (log && normalizedSource === programArtifact.data) {
306
+ console.warn('[wasm-idle:ocaml-worker] stdin runtime patch did not match generated JS');
307
+ }
308
+ new Function(`${normalizedSource}\n//# sourceURL=${programArtifact.path}`)();
309
+ const runtimePromise = globalThis[runtimePromiseKey];
310
+ if (runtimePromise instanceof Promise) {
311
+ await runtimePromise;
312
+ }
313
+ postMessage({ results: true });
314
+ }
315
+ finally {
316
+ globalThis.console = originalConsole;
317
+ globalThis.fetch = originalFetch;
318
+ WebAssembly.instantiate = originalInstantiate;
319
+ if (originalInstantiateStreaming) {
320
+ WebAssembly.instantiateStreaming = originalInstantiateStreaming;
321
+ }
322
+ delete globalThis[runtimePromiseKey];
323
+ delete globalThis[assetResolverKey];
324
+ if (!hadProcess) {
325
+ delete runtimeGlobal.process;
326
+ }
327
+ else {
328
+ runtimeGlobal.process = originalProcess;
329
+ }
330
+ if (!hadRequire) {
331
+ delete runtimeGlobal.require;
332
+ }
333
+ else {
334
+ runtimeGlobal.require = originalRequire;
335
+ }
336
+ if (!hadModule) {
337
+ delete runtimeGlobal.module;
338
+ }
339
+ else {
340
+ runtimeGlobal.module = originalModule;
341
+ }
342
+ if (!hadExports) {
343
+ delete runtimeGlobal.exports;
344
+ }
345
+ else {
346
+ runtimeGlobal.exports = originalExports;
347
+ }
348
+ if (!hadFs) {
349
+ delete runtimeGlobal.fs;
350
+ }
351
+ else {
352
+ runtimeGlobal.fs = originalFs;
353
+ }
354
+ if (!hadStdinHook) {
355
+ delete runtimeGlobal[stdinHookKey];
356
+ }
357
+ else {
358
+ runtimeGlobal[stdinHookKey] = originalStdinHook;
359
+ }
360
+ for (const objectUrl of createdObjectUrls) {
361
+ URL.revokeObjectURL(objectUrl);
362
+ }
363
+ }
364
+ }
365
+ self.onmessage = async (event) => {
366
+ const { load, moduleUrl: nextModuleUrl, manifestUrl: nextManifestUrl, code, prepare, target = 'wasm', log = true, buffer } = event.data;
367
+ try {
368
+ if (load) {
369
+ moduleUrl = nextModuleUrl;
370
+ manifestUrl = nextManifestUrl;
371
+ await Promise.all([loadCompiler(moduleUrl), loadManifest(manifestUrl)]);
372
+ postMessage({ load: true });
373
+ return;
374
+ }
375
+ stdinBufferOcaml = buffer ? new Int32Array(buffer) : null;
376
+ if (log) {
377
+ console.log(`[wasm-idle:ocaml-worker] compile start prepare=${prepare} target=${target}`);
378
+ }
379
+ postMessage({ progress: { stage: 'compile-bootstrap', percent: 10 } });
380
+ const [compilerModule, manifest] = await Promise.all([
381
+ loadCompiler(moduleUrl),
382
+ loadManifest(manifestUrl)
383
+ ]);
384
+ postMessage({ progress: { stage: 'compile-ready', percent: 25 } });
385
+ const compileKey = `${target}\n${code}`;
386
+ let compiledFresh = false;
387
+ if (!compiledResult || compiledCacheKey !== compileKey) {
388
+ const result = await compilerModule.compile({
389
+ files: {
390
+ 'main.ml': code
391
+ },
392
+ entry: 'main.ml',
393
+ target,
394
+ effectsMode: 'cps'
395
+ }, {
396
+ system: compilerModule.createBrowserWorkerSystemDispatcher({
397
+ manifest
398
+ }),
399
+ toolchainRoot: '/static/toolchain'
400
+ });
401
+ compiledResult = result;
402
+ compiledCacheKey = compileKey;
403
+ compiledFresh = true;
404
+ }
405
+ const result = compiledResult;
406
+ if (log) {
407
+ console.log(`[wasm-idle:ocaml-worker] compile settled success=${result.success} diagnostics=${result.diagnostics?.length || 0}`);
408
+ }
409
+ if (compiledFresh && result.stdout) {
410
+ postMessage({ output: result.stdout });
411
+ }
412
+ if ((compiledFresh || !result.success) && result.stderr) {
413
+ postMessage({ output: result.stderr });
414
+ }
415
+ for (const diagnostic of result.diagnostics || []) {
416
+ postMessage({
417
+ diagnostic: {
418
+ fileName: diagnostic.file ?? null,
419
+ lineNumber: Math.max(1, Number(diagnostic.line || 1)),
420
+ columnNumber: typeof diagnostic.column === 'number'
421
+ ? Math.max(1, diagnostic.column)
422
+ : undefined,
423
+ severity: diagnostic.severity === 'warning' || diagnostic.severity === 'other'
424
+ ? diagnostic.severity
425
+ : 'error',
426
+ message: String(diagnostic.message || '')
427
+ }
428
+ });
429
+ }
430
+ postMessage({ progress: { stage: 'compile-finished', percent: 90 } });
431
+ if (!result.success) {
432
+ throw new Error(result.stderr ||
433
+ result.diagnostics?.map((diagnostic) => diagnostic.message || '').join('\n') ||
434
+ 'OCaml compilation failed');
435
+ }
436
+ if (prepare) {
437
+ postMessage({ results: true });
438
+ return;
439
+ }
440
+ postMessage({ progress: { stage: 'runtime-start', percent: 95 } });
441
+ await executeCompileResult(result, log);
442
+ }
443
+ catch (error) {
444
+ if (log) {
445
+ console.error('[wasm-idle:ocaml-worker] failed', error);
446
+ }
447
+ postMessage({ error: error?.message || String(error) });
448
+ }
449
+ };
@@ -0,0 +1 @@
1
+ export {};