|
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, '_'); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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; |
|
}, |
|
|
|
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) { |
|
|
|
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 { |
|
|
|
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}`); |
|
}, |
|
}; |
|
|
|
|