Skip to content

Commit d8f0e3c

Browse files
doc: Add cheat sheet and FAQ
1 parent 0ad0940 commit d8f0e3c

File tree

3 files changed

+205
-1
lines changed

3 files changed

+205
-1
lines changed

README.md

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,14 @@ It enables running Ruby application on browsers, WASI compatible WebAssembly run
99

1010
Try ruby.wasm in [TryRuby](https://try.ruby-lang.org/playground#code=puts+RUBY_DESCRIPTION&engine=cruby-3.2.0dev) in your browser.
1111

12+
## Quick Links
13+
14+
- [[**Cheat Sheet**]](./docs/cheat_sheet.md)
15+
- [[**FAQ**]](./docs/faq.md)
16+
- [[**API Reference**]](https://ruby.github.io/ruby.wasm/JS.html)
17+
- [[**Complete Examples**]](https://github.com/ruby/ruby.wasm/tree/main/packages/npm-packages/ruby-wasm-wasi/example)
18+
- [[**Community Showcase**]](https://github.com/ruby/ruby.wasm/wiki/Showcase)
19+
1220
## Quick Example: Ruby on browser
1321

1422
Create and save `index.html` page with the following contents:
@@ -17,7 +25,10 @@ Create and save `index.html` page with the following contents:
1725
<html>
1826
<script src="https://cdn.jsdelivr.net/npm/@ruby/[email protected]/dist/browser.script.iife.js"></script>
1927
<script type="text/ruby">
20-
puts "Hello, world!"
28+
require "js"
29+
30+
puts RUBY_VERSION # => Hello, world! (printed to the browser console)
31+
JS.global[:document].write "Hello, world!"
2132
</script>
2233
</html>
2334
```

docs/cheat_sheet.md

Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
[[**Cheat Sheet**]](./cheat_sheet.md)
2+
[[**FAQ**]](./faq.md)
3+
[[**Complete Examples**]](https://github.com/ruby/ruby.wasm/tree/main/packages/npm-packages/ruby-wasm-wasi/example)
4+
[[**Community Showcase**]](https://github.com/ruby/ruby.wasm/wiki/Showcase)
5+
6+
# ruby.wasm Cheat Sheet
7+
8+
## Node.js
9+
10+
To install the package, install `@ruby/3.2-wasm-wasi` and `@ruby/wasm-wasi` from npm:
11+
12+
```console
13+
npm install --save @ruby/3.2-wasm-wasi @ruby/wasm-wasi
14+
```
15+
16+
Then instantiate a Ruby VM by the following code:
17+
18+
```javascript
19+
import fs from "fs/promises";
20+
import { DefaultRubyVM } from "@ruby/wasm-wasi/dist/node";
21+
22+
const binary = await fs.readFile("./node_modules/@ruby/3.2-wasm-wasi/dist/ruby.wasm");
23+
const module = await WebAssembly.compile(binary);
24+
const { vm } = await DefaultRubyVM(module);
25+
vm.eval(`puts "hello world"`);
26+
```
27+
28+
Then run the example code with `--experimental-wasi-unstable-preview1` flag to enable WASI support:
29+
30+
```console
31+
$ node --experimental-wasi-unstable-preview1 index.mjs
32+
```
33+
34+
## Browser
35+
36+
The easiest way to run Ruby on browser is to use `browser.script.iife.js` script from CDN:
37+
38+
```html
39+
<html>
40+
<script src="https://cdn.jsdelivr.net/npm/@ruby/[email protected]/dist/browser.script.iife.js"></script>
41+
<script type="text/ruby">
42+
require "js"
43+
JS.global[:document].write "Hello, world!"
44+
</script>
45+
</html>
46+
```
47+
48+
If you want to control Ruby VM from JavaScript, you can use `@ruby/wasm-wasi` package API:
49+
50+
```html
51+
<html>
52+
<script type="module">
53+
import { DefaultRubyVM } from "https://cdn.jsdelivr.net/npm/@ruby/[email protected]/dist/esm/browser.js";
54+
const response = await fetch("https://cdn.jsdelivr.net/npm/@ruby/[email protected]/dist/ruby+stdlib.wasm");
55+
const module = await WebAssembly.compileStreaming(response);
56+
const { vm } = await DefaultRubyVM(module);
57+
58+
vm.eval(`
59+
require "js"
60+
JS.global[:document].write "Hello, world!"
61+
`);
62+
</script>
63+
</html>
64+
```
65+
66+
## Use JavaScript from Ruby
67+
68+
### Get/set JavaScript variables from Ruby
69+
70+
```ruby
71+
require "js"
72+
73+
document = JS.global[:document]
74+
document[:title] = "Hello, world!"
75+
```
76+
77+
### Call JavaScript methods from Ruby
78+
79+
```ruby
80+
require "js"
81+
82+
JS.global[:document].createElement("div")
83+
84+
JS.global[:document].call(:createElement, "div".to_js) # same as above
85+
```
86+
87+
### Pass Ruby `Proc` to JavaScript (Callback to Ruby)
88+
89+
```ruby
90+
require "js"
91+
92+
JS.global.setTimeout(proc { puts "Hello, world!" }, 1000)
93+
94+
input = JS.global[:document].querySelector("input")
95+
input.addEventListener("change") do |event|
96+
puts event[:target][:value].to_s
97+
end
98+
```
99+
100+
### `await` JavaScript `Promise` from Ruby
101+
102+
```html
103+
<html>
104+
<script src="https://cdn.jsdelivr.net/npm/@ruby/[email protected]/dist/browser.script.iife.js"></script>
105+
<script type="text/ruby" data-eval="async">
106+
require "js"
107+
108+
response = JS.global.fetch("https://www.ruby-lang.org/").await
109+
puts response[:status]
110+
</script>
111+
</html>
112+
```
113+
114+
Or using `@ruby/wasm-wasi` package API:
115+
116+
```html
117+
<html>
118+
<script type="module">
119+
import { DefaultRubyVM } from "https://cdn.jsdelivr.net/npm/@ruby/[email protected]/dist/esm/browser.js";
120+
const response = await fetch("https://cdn.jsdelivr.net/npm/@ruby/[email protected]/dist/ruby+stdlib.wasm");
121+
const module = await WebAssembly.compileStreaming(response);
122+
const { vm } = await DefaultRubyVM(module);
123+
124+
vm.evalAsync(`
125+
require "js"
126+
127+
response = JS.global.fetch("https://www.ruby-lang.org/").await
128+
puts response[:status]
129+
`);
130+
</script>
131+
</html>
132+
```
133+
134+
### `new` JavaScript instance from Ruby
135+
136+
```ruby
137+
require "js"
138+
139+
JS.global[:Date].new(2000, 9, 13)
140+
```
141+
142+
### Convert returned JavaScript `String` value to Ruby `String`
143+
144+
```ruby
145+
require "js"
146+
147+
title = JS.global[:document].title # => JS::Object("Hello, world!")
148+
title.to_s # => "Hello, world!"
149+
```
150+
151+
### Convert JavaScript `Boolean` value to Ruby `true`/`false`
152+
153+
```ruby
154+
require "js"
155+
156+
JS.global[:document].hasFocus? # => true
157+
JS.global[:document].hasFocus # => JS::Object(true)
158+
```
159+
160+
### Convert JavaScript `Number` value to Ruby `Integer`/`Float`
161+
162+
```ruby
163+
require "js"
164+
165+
rand = JS.global[:Math].random # JS::Object(0.123456789)
166+
rand.to_i # => 0
167+
rand.to_f # => 0.123456789
168+
```

docs/faq.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
[[**Cheat Sheet**]](./cheat_sheet.md)
2+
[[**FAQ**]](./faq.md)
3+
[[**API Reference**]](https://ruby.github.io/ruby.wasm/JS.html)
4+
[[**Complete Examples**]](https://github.com/ruby/ruby.wasm/tree/main/packages/npm-packages/ruby-wasm-wasi/example)
5+
[[**Community Showcase**]](https://github.com/ruby/ruby.wasm/wiki/Showcase)
6+
7+
# FAQ
8+
9+
## Where my `puts` output goes?
10+
11+
By default, `puts` output goes to `STDOUT` which is a JavaScript `console.log` function. You can override it by setting `$stdout` to a Ruby object which has `write` method.
12+
13+
```ruby
14+
$stdout = Object.new.tap do |obj|
15+
def obj.write(str)
16+
JS.global[:document].write(str)
17+
end
18+
end
19+
20+
puts "Hello, world!" # => Prints "Hello, world!" to the HTML document
21+
```
22+
23+
## How to run WebAssembly in Ruby
24+
25+
Use [`wasmtime` Ruby gem](https://rubygems.org/gems/wasmtime).

0 commit comments

Comments
 (0)