Skip to content

Commit 29f6552

Browse files
Update template package docs
1 parent 2302c01 commit 29f6552

File tree

4 files changed

+376
-270
lines changed

4 files changed

+376
-270
lines changed

packages/npm-packages/ruby-head-wasm-emscripten/README.md

Lines changed: 0 additions & 1 deletion
This file was deleted.
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
# ruby-head-wasm-emscripten
2+
3+
WebAssembly port of CRuby by Emscripten with a thin JavaScript wrapper.
4+
5+
This package distributes the latest `master` branch of CRuby.
6+
7+
## Installation
8+
9+
For instaling ruby-head-wasm-emscripten, just run this command in your shell:
10+
11+
```console
12+
$ npm install --save ruby-head-wasm-emscripten
13+
```
14+
15+
## Quick Start
16+
17+
This quick start is for browsers and Node.js environments. See [the example project](./example) for more details.
18+
19+
```javascript
20+
import { loadRuby } from "ruby-head-wasm-emscripten";
21+
22+
const main = async () => {
23+
const args = ["--disable-gems", "-e", "puts 'Hello :)'"];
24+
console.log(`$ ruby.wasm ${args.join(" ")}`);
25+
26+
const defaultModule = {
27+
locateFile: (path) => "./node_modules/ruby-head-wasm-emscripten/dist/" + path,
28+
setStatus: (msg) => console.log(msg),
29+
print: (line) => console.log(line),
30+
arguments: args,
31+
};
32+
33+
await loadRuby(defaultModule);
34+
};
35+
36+
main();
37+
38+
```
39+
40+
## APIs
41+
42+
`loadRuby(defaultModule): Promise<Module>`
43+
44+
This package provides only `loadRuby` function, which loads the Ruby interpreter and stdlib asynchronously.
45+
46+
This takes a `defaultModule` object as an argument, which is used as a base for the Emscripten's Module object.
47+
48+
### Module object
49+
50+
> Module is a global JavaScript object with attributes that Emscripten-generated code calls at various points in its execution.
51+
52+
https://emscripten.org/docs/api_reference/module.html
53+
54+
This package is a thin wrapper of Emscripten module, so you can control the behavior of the interpreter by modifying the Emscripten's Module object.
55+
56+
57+
## Building the package from source
58+
59+
For building the package from source, you need to prepare a Ruby build produced by Emscripten, and you need Emscripten SDK in your PATH.
60+
61+
The instructions for building a Ruby targeting WebAssembly are available at: [TODO](./).
62+
63+
Then, you can run the following command in your shell:
64+
65+
```console
66+
# Check the directory structure of your Ruby build
67+
$ tree -L 3 path/to/wasm32-unknown-emscripten-full/
68+
path/to/wasm32-unknown-emscripten-full/
69+
├── usr
70+
│ └── local
71+
│ ├── bin
72+
│ ├── include
73+
│ ├── lib
74+
│ └── share
75+
└── var
76+
└── lib
77+
└── gems
78+
$ ./build-package.sh path/to/wasm32-unknown-emscripten-full/
79+
Remember to build the main file with -s FORCE_FILESYSTEM=1 so that it includes support for loading this file package
80+
81+
index.js → dist...
82+
created dist in 3.5s
83+
```
84+
85+
It's recommended to build on a Docker container with the following command:
86+
87+
```console
88+
$ docker run -it --rm \
89+
-v $(pwd):/src \
90+
-v path/to/wasm32-unknown-emscripten-full:/install \
91+
emscripten/emsdk /bin/bash
92+
```
Lines changed: 273 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,275 @@
11
# ruby-head-wasm-wasi
22

3-
See also https://github.com/kateinoigakukun/ruby.wasm/blob/main/packages/npm-packages/ruby-wasm-wasi/README.md
3+
WebAssembly port of CRuby with WASI.
4+
5+
This package distributes the latest `master` branch of CRuby.
6+
7+
## Installation
8+
9+
For instaling ruby-head-wasm-wasi family, just run this command in your shell:
10+
11+
```console
12+
$ npm install --save ruby-head-wasm-wasi
13+
```
14+
15+
## Quick Start (for Node.js)
16+
17+
See [the example project](./example) for more details.
18+
19+
```javascript
20+
import fs from "fs/promises";
21+
import { DefaultRubyVM } from "ruby-head-wasm-wasi/dist/node.cjs.js";
22+
23+
const main = async () => {
24+
const binary = await fs.readFile(
25+
"./node_modules/ruby-head-wasm-wasi/dist/ruby.wasm"
26+
);
27+
const module = await WebAssembly.compile(binary);
28+
const { vm } = await DefaultRubyVM(module);
29+
30+
vm.eval(`
31+
luckiness = ["Lucky", "Unlucky"].sample
32+
puts "You are #{luckiness}"
33+
`);
34+
};
35+
36+
main();
37+
```
38+
39+
Then you can run the example project in your terminal:
40+
41+
```console
42+
$ node --experimental-wasi-unstable-preview1 index.node.js
43+
```
44+
45+
## Quick Start (for Browser)
46+
47+
In browser, you need a WASI polyfill
48+
See [the example project](./example) for more details.
49+
50+
```html
51+
<html>
52+
<script src="https://cdn.jsdelivr.net/npm/ruby-head-wasm-wasi@latest/dist/browser.umd.js"></script>
53+
<script>
54+
const { DefaultRubyVM } = window["ruby-wasm-wasi"];
55+
const main = async () => {
56+
// Fetch and instntiate WebAssembly binary
57+
const response = await fetch(
58+
"https://cdn.jsdelivr.net/npm/ruby-head-wasm-wasi@latest/dist/ruby.wasm"
59+
);
60+
const buffer = await response.arrayBuffer();
61+
const module = await WebAssembly.compile(buffer);
62+
const { vm } = await DefaultRubyVM(module);
63+
64+
vm.printVersion();
65+
vm.eval(`
66+
require "js"
67+
luckiness = ["Lucky", "Unlucky"].sample
68+
JS::eval("document.body.innerText = '#{luckiness}'")
69+
`);
70+
};
71+
72+
main();
73+
</script>
74+
<body></body>
75+
</html>
76+
```
77+
78+
<!-- The APIs section was generated by `npx documentation readme ./dist/index.esm.js --section=APIs` -->
79+
80+
## APIs
81+
82+
<!-- Generated by documentation.js. Update this documentation by updating the source code. -->
83+
84+
#### Table of Contents
85+
86+
- [ruby-head-wasm-wasi](#ruby-head-wasm-wasi)
87+
- [Installation](#installation)
88+
- [Quick Start (for Node.js)](#quick-start-for-nodejs)
89+
- [Quick Start (for Browser)](#quick-start-for-browser)
90+
- [APIs](#apis)
91+
- [Table of Contents](#table-of-contents)
92+
- [RubyVM](#rubyvm)
93+
- [Examples](#examples)
94+
- [initialize](#initialize)
95+
- [Parameters](#parameters)
96+
- [setInstance](#setinstance)
97+
- [Parameters](#parameters-1)
98+
- [addToImports](#addtoimports)
99+
- [Parameters](#parameters-2)
100+
- [printVersion](#printversion)
101+
- [eval](#eval)
102+
- [Parameters](#parameters-3)
103+
- [Examples](#examples-1)
104+
- [RbValue](#rbvalue)
105+
- [Parameters](#parameters-4)
106+
- [call](#call)
107+
- [Parameters](#parameters-5)
108+
- [Examples](#examples-2)
109+
- [toPrimitive](#toprimitive)
110+
- [Parameters](#parameters-6)
111+
- [toString](#tostring)
112+
- [toJS](#tojs)
113+
- [RbError](#rberror)
114+
- [Parameters](#parameters-7)
115+
- [Building the package from source](#building-the-package-from-source)
116+
117+
### RubyVM
118+
119+
A Ruby VM instance
120+
121+
#### Examples
122+
123+
```javascript
124+
const wasi = new WASI();
125+
const vm = new RubyVM();
126+
const imports = {
127+
wasi_snapshot_preview1: wasi.wasiImport,
128+
};
129+
130+
vm.addToImports(imports);
131+
132+
const instance = await WebAssembly.instantiate(rubyModule, imports);
133+
await vm.setInstance(instance);
134+
wasi.initialize(instance);
135+
```
136+
137+
#### initialize
138+
139+
Initialize the Ruby VM with the given command line arguments
140+
141+
##### Parameters
142+
143+
- `args` The command line arguments to pass to Ruby. Must be
144+
an array of strings starting with the Ruby program name. (optional, default `["ruby.wasm","--disable-gems","-e_=0"]`)
145+
146+
#### setInstance
147+
148+
Set a given instance to interact JavaScript and Ruby's
149+
WebAssembly instance. This method must be called before calling
150+
Ruby API.
151+
152+
##### Parameters
153+
154+
- `instance` The WebAssembly instance to interact with. Must
155+
be instantiated from a Ruby built with JS extension, and built
156+
with Reactor ABI instead of command line.
157+
158+
#### addToImports
159+
160+
Add intrinsic import entries, which is necessary to interact JavaScript
161+
and Ruby's WebAssembly instance.
162+
163+
##### Parameters
164+
165+
- `imports` The import object to add to the WebAssembly instance
166+
167+
#### printVersion
168+
169+
Print the Ruby version to stdout
170+
171+
#### eval
172+
173+
Runs a string of Ruby code from JavaScript
174+
175+
##### Parameters
176+
177+
- `code` The Ruby code to run
178+
179+
##### Examples
180+
181+
```javascript
182+
vm.eval("puts 'hello world'");
183+
const result = vm.eval("1 + 2");
184+
console.log(result.toString()); // 3
185+
```
186+
187+
Returns **any** the result of the last expression
188+
189+
### RbValue
190+
191+
A RbValue is an object that represents a value in Ruby
192+
193+
#### Parameters
194+
195+
- `inner`
196+
- `vm`
197+
- `exporter`
198+
199+
#### call
200+
201+
Call a given method with given arguments
202+
203+
##### Parameters
204+
205+
- `callee` name of the Ruby method to call
206+
- `args` **...any** arguments to pass to the method. Must be an array of RbValue
207+
208+
##### Examples
209+
210+
```javascript
211+
const ary = vm.eval("[1, 2, 3]");
212+
ary.call("push", 4);
213+
console.log(ary.call("sample").toString());
214+
```
215+
216+
#### toPrimitive
217+
218+
- **See**: <https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Symbol/toPrimitive>
219+
220+
##### Parameters
221+
222+
- `hint`
223+
224+
#### toString
225+
226+
Returns a string representation of the value by calling `to_s`
227+
228+
#### toJS
229+
230+
Returns a JavaScript object representation of the value
231+
by calling `to_js`.
232+
233+
Returns null if the value is not convertible to a JavaScript object.
234+
235+
### RbError
236+
237+
**Extends Error**
238+
239+
Error class thrown by Ruby execution
240+
241+
#### Parameters
242+
243+
- `message`
244+
245+
## Building the package from source
246+
247+
For building the package from source, you need to prepare a Ruby build produced by WASI SDK, and you need [`wit-bindgen`](https://github.com/bytecodealliance/wit-bindgen) and [`wasm-opt`](https://github.com/webassembly/binaryen#tools) in your PATH.
248+
249+
The instructions for building a Ruby targeting WebAssembly are available at: [TODO](./).
250+
251+
Then, you can run the following command in your shell:
252+
253+
```console
254+
# Check the directory structure of your Ruby build
255+
$ tree -L 3 path/to/wasm32-unknown-wasi-full-js/
256+
path/to/wasm32-unknown-wasi-full-js/
257+
├── usr
258+
│ └── local
259+
│ ├── bin
260+
│ ├── include
261+
│ ├── lib
262+
│ └── share
263+
└── var
264+
└── lib
265+
└── gems
266+
$ ./build-package.sh path/to/wasm32-unknown-wasi-full-js/
267+
Generating "/Users/katei/.ghq/github.com/kateinoigakukun/ruby.wasm/packages/ruby-head-wasm-wasi/src/bindgen/intrinsics.js"
268+
Generating "/Users/katei/.ghq/github.com/kateinoigakukun/ruby.wasm/packages/ruby-head-wasm-wasi/src/bindgen/rb-abi-guest.d.ts"
269+
Generating "/Users/katei/.ghq/github.com/kateinoigakukun/ruby.wasm/packages/ruby-head-wasm-wasi/src/bindgen/rb-abi-guest.js"
270+
Generating "/Users/katei/.ghq/github.com/kateinoigakukun/ruby.wasm/packages/ruby-head-wasm-wasi/src/bindgen/rb-js-abi-host.d.ts"
271+
Generating "/Users/katei/.ghq/github.com/kateinoigakukun/ruby.wasm/packages/ruby-head-wasm-wasi/src/bindgen/rb-js-abi-host.js"
272+
273+
src/index.ts → dist/index.umd.js, dist/index.esm.js, dist/index.cjs.js...
274+
created dist/index.umd.js, dist/index.esm.js, dist/index.cjs.js in 682ms
275+
```

packages/npm-packages/ruby-wasm-emscripten/README.md

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1-
# ruby-head-wasm-emscripten
1+
# ruby-wasm-emscripten
2+
3+
This package is a template for each channel-specific package.
4+
5+
| Channel | Package |
6+
| ------- | ------- |
7+
| `head` | [`ruby-head-wasm-emscripten`](./../ruby-head-wasm-emscripten) |
28

3-
See also https://github.com/kateinoigakukun/ruby.wasm/blob/main/packages/npm-packages/ruby-wasm-emscripten/README.md

0 commit comments

Comments
 (0)