Skip to content

Commit 48892de

Browse files
committed
Ruby WASM WASI
1 parent a011b03 commit 48892de

File tree

17 files changed

+238
-76
lines changed

17 files changed

+238
-76
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,13 +69,15 @@ integration
6969
├ interpreter
7070
│ ├ micropython
7171
│ ├ pyodide
72+
│ ├ ruby-wasm-wasi
7273
│ ├ wasmoon
7374
│ ├ xxx.yy
7475
│ ├ xxx.toml
7576
│ └ utils.js
7677
├ _shared.js
7778
├ micropython.js
7879
├ pyodide.js
80+
├ ruby-wasm-wasi.js
7981
└ wasmoon.js
8082
```
8183

docs/README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ We also explicitly use that "_piece of software_" as the interpreter name it ref
3333

3434
* [pyodide](https://pyodide.org/en/stable/index.html) is the name of the interpreter that runs likely the most complete version of latest *Python*, enabling dozen official modules at run time, also offering a great *JS* integration in its core
3535
* [micropython](https://micropython.org/) is the name of the interpreter that runs a small subset of the *Python* standard library and is optimized to run in constrained environments such as *Mobile* phones, or even *Desktop*, thanks to its tiny size and an extremely fast bootstrap
36+
* [ruby-wasm-wasi](https://github.com/ruby/ruby.wasm) is the name of the (currently *experimental*) interpreter that adds *Ruby* to the list of programming languages currently supported
3637
* [wasmoon](https://github.com/ceifa/wasmoon) is the name of the interpreter that runs *Lua* on the browser and that, among the previous two interpreters, is fully compatible with all core features
3738

3839
`<script>` tags specify which *interpreter* to use via the `type` attribute. This is typically the full name of the interpreter:
@@ -48,6 +49,10 @@ We also explicitly use that "_piece of software_" as the interpreter name it ref
4849
print(sys.version)
4950
</script>
5051

52+
<script type="ruby-wasm-wasi">
53+
print "ruby #{ RUBY_VERSION }"
54+
</script>
55+
5156
<script type="wasmoon">
5257
print(_VERSION)
5358
</script>
@@ -765,6 +770,7 @@ Please note that if a worker is created explicitly, there won't be any element,
765770
| :------------- | :---: | :--------: | :--------: | :----------------: | :---------: | :---------: |
766771
| pyodide | • | • | • | • | • | • |
767772
| micropython | • | • | • | • | • | • |
773+
| ruby-wasm-wasi | • | • | • | ! | | |
768774
| wasmoon | • | • | • | ! | • | |
769775
770776
* **run** allows code to run synchronously and optionally return value

docs/index.js

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

docs/index.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

esm/custom.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@ const registry = new Map();
166166

167167
/**
168168
* @typedef {Object} CustomOptions custom configuration
169-
* @prop {'pyodide' | 'micropython' | 'wasmoon'} interpreter the interpreter to use
169+
* @prop {'pyodide' | 'micropython' | 'ruby-wasm-wasi' | 'wasmoon'} interpreter the interpreter to use
170170
* @prop {string} [version] the optional interpreter version to use
171171
* @prop {string} [config] the optional config to use within such interpreter
172172
*/

esm/interpreter/ruby-wasm-wasi.js

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import fetch from '@webreflection/fetch';
2+
3+
import { dedent } from '../utils.js';
4+
import { fetchFiles, fetchJSModules, fetchPaths } from './_utils.js';
5+
6+
const type = 'ruby-wasm-wasi';
7+
const jsType = type.replace(/\W+/g, '_');
8+
9+
// MISSING:
10+
// * there is no VFS apparently or I couldn't reach any
11+
// * I've no idea how to override the stderr and stdout
12+
// * I've no idea how to import packages
13+
14+
// REQUIRES INTEGRATION TEST
15+
/* c8 ignore start */
16+
export default {
17+
type,
18+
experimental: true,
19+
module: (version = '2.5.0') =>
20+
`https://cdn.jsdelivr.net/npm/@ruby/3.2-wasm-wasi@${version}/dist/browser/+esm`,
21+
async engine({ DefaultRubyVM }, config, url) {
22+
url = url.replace(/\/browser\/\+esm$/, '/ruby.wasm');
23+
const buffer = await fetch(url).arrayBuffer();
24+
const module = await WebAssembly.compile(buffer);
25+
const { vm: interpreter } = await DefaultRubyVM(module);
26+
if (config.files) await fetchFiles(this, interpreter, config.files);
27+
if (config.fetch) await fetchPaths(this, interpreter, config.fetch);
28+
if (config.js_modules) await fetchJSModules(config.js_modules);
29+
return interpreter;
30+
},
31+
// Fallback to globally defined module fields (i.e. $xworker)
32+
registerJSModule(interpreter, name, value) {
33+
name = name.replace(/\W+/g, '__');
34+
const id = `__module_${jsType}_${name}`;
35+
globalThis[id] = value;
36+
this.run(interpreter, `require "js";$${name}=JS.global[:${id}]`);
37+
delete globalThis[id];
38+
},
39+
run: (interpreter, code, ...args) => interpreter.eval(dedent(code), ...args),
40+
runAsync: (interpreter, code, ...args) => interpreter.evalAsync(dedent(code), ...args),
41+
async runEvent(interpreter, code, event) {
42+
// patch common xworker.onmessage/onerror cases
43+
if (/^xworker\.(on\w+)$/.test(code)) {
44+
const { $1: name } = RegExp;
45+
const id = `__module_${jsType}_event`;
46+
globalThis[id] = event;
47+
this.run(
48+
interpreter,
49+
`require "js";$xworker.call("${name}",JS.global[:${id}])`,
50+
);
51+
delete globalThis[id];
52+
} else {
53+
// Experimental: allows only events by fully qualified method name
54+
const method = this.run(interpreter, `method(:${code})`);
55+
await method.call(code, interpreter.wrap(event));
56+
}
57+
},
58+
transform: (_, value) => value,
59+
writeFile: () => {
60+
throw new Error(`writeFile is not supported in ${type}`);
61+
},
62+
};
63+
/* c8 ignore stop */

esm/interpreters.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ const register = (interpreter) => {
6060
//:RUNTIMES
6161
import micropython from './interpreter/micropython.js';
6262
import pyodide from './interpreter/pyodide.js';
63+
import ruby_wasm_wasi from './interpreter/ruby-wasm-wasi.js';
6364
import wasmoon from './interpreter/wasmoon.js';
64-
for (const interpreter of [micropython, pyodide, wasmoon])
65+
for (const interpreter of [micropython, pyodide, ruby_wasm_wasi, wasmoon])
6566
register(interpreter);

package-lock.json

Lines changed: 74 additions & 60 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)