import fetch from '@webreflection/fetch'; import { dedent } from '../utils.js'; import { fetchFiles, fetchJSModules, fetchPaths } from './_utils.js'; const type = 'ruby-wasm-wasi'; const jsType = type.replace(/\W+/g, '_'); // MISSING: // * there is no VFS apparently or I couldn't reach any // * I've no idea how to override the stderr and stdout // * I've no idea how to import packages // REQUIRES INTEGRATION TEST /* c8 ignore start */ export default { type, experimental: true, module: (version = '2.6.0') => `https://cdn.jsdelivr.net/npm/@ruby/3.2-wasm-wasi@${version}/dist/browser/+esm`, async engine({ DefaultRubyVM }, config, url) { url = url.replace(/\/browser\/\+esm$/, '/ruby.wasm'); const buffer = await fetch(url).arrayBuffer(); const module = await WebAssembly.compile(buffer); const { vm: interpreter } = await DefaultRubyVM(module); if (config.files) await fetchFiles(this, interpreter, config.files); if (config.fetch) await fetchPaths(this, interpreter, config.fetch); if (config.js_modules) await fetchJSModules(config.js_modules); return interpreter; }, // Fallback to globally defined module fields (i.e. $xworker) registerJSModule(interpreter, name, value) { name = name.replace(/\W+/g, '__'); const id = `__module_${jsType}_${name}`; globalThis[id] = value; this.run(interpreter, `require "js";$${name}=JS.global[:${id}]`); delete globalThis[id]; }, run: (interpreter, code, ...args) => interpreter.eval(dedent(code), ...args), runAsync: (interpreter, code, ...args) => interpreter.evalAsync(dedent(code), ...args), async runEvent(interpreter, code, event) { // patch common xworker.onmessage/onerror cases if (/^xworker\.(on\w+)$/.test(code)) { const { $1: name } = RegExp; const id = `__module_${jsType}_event`; globalThis[id] = event; this.run( interpreter, `require "js";$xworker.call("${name}",JS.global[:${id}])`, ); delete globalThis[id]; } else { // Experimental: allows only events by fully qualified method name const method = this.run(interpreter, `method(:${code})`); await method.call(code, interpreter.wrap(event)); } }, transform: (_, value) => value, writeFile: () => { throw new Error(`writeFile is not supported in ${type}`); }, }; /* c8 ignore stop */