[Cheat Sheet] [FAQ] [API Reference] [Complete Examples] [Community Showcase]
To install the package, install @ruby/3.4-wasm-wasi
and @ruby/wasm-wasi
from npm:
npm install --save @ruby/3.4-wasm-wasi @ruby/wasm-wasi
Then instantiate a Ruby VM by the following code:
import fs from "fs/promises";
import { DefaultRubyVM } from "@ruby/wasm-wasi/dist/node";
const binary = await fs.readFile("./node_modules/@ruby/3.4-wasm-wasi/dist/ruby.wasm");
const module = await WebAssembly.compile(binary);
const { vm } = await DefaultRubyVM(module);
vm.eval(`puts "hello world"`);
Then run the example code with --experimental-wasi-unstable-preview1
flag to enable WASI support:
$ node --experimental-wasi-unstable-preview1 index.mjs
The easiest way to run Ruby on browser is to use browser.script.iife.js
script from CDN:
<html>
<script src="https://cdn.jsdelivr.net/npm/@ruby/3.4-wasm-wasi@2.7.1/dist/browser.script.iife.js"></script>
<script type="text/ruby">
require "js"
JS.global[:document].write "Hello, world!"
</script>
</html>
If you want to control Ruby VM from JavaScript, you can use @ruby/wasm-wasi
package API:
<html>
<script type="module">
import { DefaultRubyVM } from "https://cdn.jsdelivr.net/npm/@ruby/wasm-wasi@2.7.1/dist/browser/+esm";
const response = await fetch("https://cdn.jsdelivr.net/npm/@ruby/3.4-wasm-wasi@2.7.1/dist/ruby+stdlib.wasm");
const module = await WebAssembly.compileStreaming(response);
const { vm } = await DefaultRubyVM(module);
vm.eval(`
require "js"
JS.global[:document].write "Hello, world!"
`);
</script>
</html>
Alternative: Without ES Modules
<html>
<script src="https://cdn.jsdelivr.net/npm/@ruby/wasm-wasi@2.7.1/dist/browser.umd.js"></script>
<script>
const main = async () => {
const { DefaultRubyVM } = window["ruby-wasm-wasi"];
const response = await fetch("https://cdn.jsdelivr.net/npm/@ruby/3.4-wasm-wasi@2.7.1/dist/ruby+stdlib.wasm");
const module = await WebAssembly.compileStreaming(response);
const { vm } = await DefaultRubyVM(module);
vm.eval(`
require "js"
JS.global[:document].write "Hello, world!"
`);
}
main()
</script>
</html>
require "js"
document = JS.global[:document]
document[:title] = "Hello, world!"
require "js"
JS.global[:document].createElement("div")
JS.global[:document].call(:createElement, "div".to_js) # same as above
require "js"
JS.global.setTimeout(proc { puts "Hello, world!" }, 1000)
input = JS.global[:document].querySelector("input")
input.addEventListener("change") do |event|
puts event[:target][:value].to_s
end
data-eval="async"
attribute is required to use await
in <script>
tag:
<html>
<script src="https://cdn.jsdelivr.net/npm/@ruby/3.4-wasm-wasi@2.7.1/dist/browser.script.iife.js"></script>
<script type="text/ruby" data-eval="async">
require "js"
response = JS.global.fetch("https://www.ruby-lang.org/").await
puts response[:status]
</script>
</html>
Or using @ruby/wasm-wasi
package API RubyVM#evalAsync
:
<html>
<script type="module">
import { DefaultRubyVM } from "https://cdn.jsdelivr.net/npm/@ruby/wasm-wasi@2.7.1/dist/browser/+esm";
const response = await fetch("https://cdn.jsdelivr.net/npm/@ruby/3.4-wasm-wasi@2.7.1/dist/ruby+stdlib.wasm");
const module = await WebAssembly.compileStreaming(response);
const { vm } = await DefaultRubyVM(module);
vm.evalAsync(`
require "js"
response = JS.global.fetch("https://www.ruby-lang.org/").await
puts response[:status]
`);
</script>
</html>
require "js"
JS.global[:Date].new(2000, 9, 13)
require "js"
title = JS.global[:document].title # => JS::Object("Hello, world!")
title.to_s # => "Hello, world!"
require "js"
JS.global[:document].hasFocus? # => true
JS.global[:document].hasFocus # => JS::Object(true)
require "js"
rand = JS.global[:Math].random # JS::Object(0.123456789)
rand.to_i # => 0
rand.to_f # => 0.123456789