@ruby/head-wasm-wasi 2.3.0-2023-11-29-b
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +336 -0
- package/dist/LICENSE +21 -0
- package/dist/NOTICE +1293 -0
- package/dist/bindgen/rb-abi-guest.d.ts +140 -0
- package/dist/bindgen/rb-js-abi-host.d.ts +53 -0
- package/dist/browser.cjs.js +3248 -0
- package/dist/browser.d.ts +10 -0
- package/dist/browser.esm.js +3243 -0
- package/dist/browser.script.cjs.js +3375 -0
- package/dist/browser.script.d.ts +5 -0
- package/dist/browser.script.esm.js +3373 -0
- package/dist/browser.script.iife.js +4778 -0
- package/dist/browser.script.umd.js +3381 -0
- package/dist/browser.umd.js +3251 -0
- package/dist/index.cjs.js +1195 -0
- package/dist/index.d.ts +192 -0
- package/dist/index.esm.js +1190 -0
- package/dist/index.umd.js +1201 -0
- package/dist/node.cjs.js +1212 -0
- package/dist/node.d.ts +10 -0
- package/dist/node.esm.js +1210 -0
- package/dist/ruby+stdlib.wasm +0 -0
- package/dist/ruby.debug+stdlib.wasm +0 -0
- package/dist/ruby.wasm +0 -0
- package/package.json +71 -0
package/README.md
ADDED
|
@@ -0,0 +1,336 @@
|
|
|
1
|
+
# @ruby/head-wasm-wasi
|
|
2
|
+
|
|
3
|
+
WebAssembly port of CRuby with WASI.
|
|
4
|
+
|
|
5
|
+
This package distributes the latest `master` branch of CRuby.
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
For installing `@ruby/head-wasm-wasi` family, just run this command in your shell:
|
|
10
|
+
|
|
11
|
+
```console
|
|
12
|
+
$ npm install --save @ruby/head-wasm-wasi@latest
|
|
13
|
+
# or if you want the nightly snapshot
|
|
14
|
+
$ npm install --save @ruby/head-wasm-wasi@next
|
|
15
|
+
# or you can specify the exact snapshot version
|
|
16
|
+
$ npm install --save @ruby/head-wasm-wasi@2.3.0-2023-11-26-a
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Quick Start (for Node.js)
|
|
20
|
+
|
|
21
|
+
See [the example project](https://github.com/ruby/ruby.wasm/tree/main/packages/npm-packages/ruby-wasm-wasi/example) for more details.
|
|
22
|
+
|
|
23
|
+
```javascript
|
|
24
|
+
import fs from "fs/promises";
|
|
25
|
+
import { DefaultRubyVM } from "@ruby/wasm-wasi/dist/node.cjs.js";
|
|
26
|
+
|
|
27
|
+
const main = async () => {
|
|
28
|
+
const binary = await fs.readFile(
|
|
29
|
+
// Tips: Replace the binary with debug info if you want symbolicated stack trace.
|
|
30
|
+
// (only nightly release for now)
|
|
31
|
+
// "./node_modules/@ruby/head-wasm-wasi/dist/ruby.debug+stdlib.wasm"
|
|
32
|
+
"./node_modules/@ruby/head-wasm-wasi/dist/ruby.wasm"
|
|
33
|
+
);
|
|
34
|
+
const module = await WebAssembly.compile(binary);
|
|
35
|
+
const { vm } = await DefaultRubyVM(module);
|
|
36
|
+
|
|
37
|
+
vm.eval(`
|
|
38
|
+
luckiness = ["Lucky", "Unlucky"].sample
|
|
39
|
+
puts "You are #{luckiness}"
|
|
40
|
+
`);
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
main();
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Then you can run the example project in your terminal:
|
|
47
|
+
|
|
48
|
+
```console
|
|
49
|
+
$ node --experimental-wasi-unstable-preview1 index.node.js
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Quick Start (for Browser)
|
|
53
|
+
|
|
54
|
+
In browser, you need a WASI polyfill. See [the example project](https://github.com/ruby/ruby.wasm/tree/main/packages/npm-packages/ruby-wasm-wasi/example) for more details.
|
|
55
|
+
|
|
56
|
+
```html
|
|
57
|
+
<html>
|
|
58
|
+
<script src="https://cdn.jsdelivr.net/npm/@ruby/wasm-wasi@latest/dist/browser.umd.js"></script>
|
|
59
|
+
<script>
|
|
60
|
+
const { DefaultRubyVM } = window["ruby-wasm-wasi"];
|
|
61
|
+
const main = async () => {
|
|
62
|
+
// Fetch and instantiate WebAssembly binary
|
|
63
|
+
const response = await fetch(
|
|
64
|
+
// Tips: Replace the binary with debug info if you want symbolicated stack trace.
|
|
65
|
+
// (only nightly release for now)
|
|
66
|
+
// "https://cdn.jsdelivr.net/npm/@ruby/head-wasm-wasi@next/dist/ruby.debug+stdlib.wasm"
|
|
67
|
+
"https://cdn.jsdelivr.net/npm/@ruby/head-wasm-wasi@latest/dist/ruby.wasm"
|
|
68
|
+
);
|
|
69
|
+
const buffer = await response.arrayBuffer();
|
|
70
|
+
const module = await WebAssembly.compile(buffer);
|
|
71
|
+
const { vm } = await DefaultRubyVM(module);
|
|
72
|
+
|
|
73
|
+
vm.printVersion();
|
|
74
|
+
vm.eval(`
|
|
75
|
+
require "js"
|
|
76
|
+
luckiness = ["Lucky", "Unlucky"].sample
|
|
77
|
+
JS::eval("document.body.innerText = '#{luckiness}'")
|
|
78
|
+
`);
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
main();
|
|
82
|
+
</script>
|
|
83
|
+
<body></body>
|
|
84
|
+
</html>
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## GC limitation with JavaScript interoperability
|
|
88
|
+
|
|
89
|
+
Since JavaScript's GC system and Ruby's GC system are separated and not cooperative, they cannot collect cyclic references between JavaScript and Ruby objects.
|
|
90
|
+
|
|
91
|
+
The following code will cause a memory leak:
|
|
92
|
+
|
|
93
|
+
```javascript
|
|
94
|
+
class JNode {
|
|
95
|
+
setRNode(rnode) {
|
|
96
|
+
this.rnode = rnode;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
jnode = new JNode();
|
|
100
|
+
|
|
101
|
+
rnode = vm.eval(`
|
|
102
|
+
class RNode
|
|
103
|
+
def set_jnode(jnode)
|
|
104
|
+
@jnode = jnode
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
RNode.new
|
|
108
|
+
`);
|
|
109
|
+
|
|
110
|
+
rnode.call("set_jnode", vm.wrap(jnode));
|
|
111
|
+
jnode.setRNode(rnode);
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
<!-- The APIs section was generated by `npx documentation readme ../ruby-wasm-wasi/dist/index.esm.js --section=APIs` -->
|
|
115
|
+
|
|
116
|
+
## APIs
|
|
117
|
+
|
|
118
|
+
<!-- Generated by documentation.js. Update this documentation by updating the source code. -->
|
|
119
|
+
|
|
120
|
+
#### Table of Contents
|
|
121
|
+
|
|
122
|
+
- [RubyVM](#rubyvm)
|
|
123
|
+
- [Examples](#examples)
|
|
124
|
+
- [initialize](#initialize)
|
|
125
|
+
- [Parameters](#parameters)
|
|
126
|
+
- [setInstance](#setinstance)
|
|
127
|
+
- [Parameters](#parameters-1)
|
|
128
|
+
- [addToImports](#addtoimports)
|
|
129
|
+
- [Parameters](#parameters-2)
|
|
130
|
+
- [printVersion](#printversion)
|
|
131
|
+
- [eval](#eval)
|
|
132
|
+
- [Parameters](#parameters-3)
|
|
133
|
+
- [Examples](#examples-1)
|
|
134
|
+
- [evalAsync](#evalasync)
|
|
135
|
+
- [Parameters](#parameters-4)
|
|
136
|
+
- [Examples](#examples-2)
|
|
137
|
+
- [wrap](#wrap)
|
|
138
|
+
- [Parameters](#parameters-5)
|
|
139
|
+
- [Examples](#examples-3)
|
|
140
|
+
- [RbValue](#rbvalue)
|
|
141
|
+
- [call](#call)
|
|
142
|
+
- [Parameters](#parameters-6)
|
|
143
|
+
- [Examples](#examples-4)
|
|
144
|
+
- [toPrimitive](#toprimitive)
|
|
145
|
+
- [Parameters](#parameters-7)
|
|
146
|
+
- [toString](#tostring)
|
|
147
|
+
- [toJS](#tojs)
|
|
148
|
+
- [RbError](#rberror)
|
|
149
|
+
|
|
150
|
+
### RubyVM
|
|
151
|
+
|
|
152
|
+
A Ruby VM instance
|
|
153
|
+
|
|
154
|
+
#### Examples
|
|
155
|
+
|
|
156
|
+
```javascript
|
|
157
|
+
const wasi = new WASI();
|
|
158
|
+
const vm = new RubyVM();
|
|
159
|
+
const imports = {
|
|
160
|
+
wasi_snapshot_preview1: wasi.wasiImport,
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
vm.addToImports(imports);
|
|
164
|
+
|
|
165
|
+
const instance = await WebAssembly.instantiate(rubyModule, imports);
|
|
166
|
+
await vm.setInstance(instance);
|
|
167
|
+
wasi.initialize(instance);
|
|
168
|
+
vm.initialize();
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
#### initialize
|
|
172
|
+
|
|
173
|
+
Initialize the Ruby VM with the given command line arguments
|
|
174
|
+
|
|
175
|
+
##### Parameters
|
|
176
|
+
|
|
177
|
+
- `args` The command line arguments to pass to Ruby. Must be
|
|
178
|
+
an array of strings starting with the Ruby program name. (optional, default `["ruby.wasm","--disable-gems","-e_=0"]`)
|
|
179
|
+
|
|
180
|
+
#### setInstance
|
|
181
|
+
|
|
182
|
+
Set a given instance to interact JavaScript and Ruby's
|
|
183
|
+
WebAssembly instance. This method must be called before calling
|
|
184
|
+
Ruby API.
|
|
185
|
+
|
|
186
|
+
##### Parameters
|
|
187
|
+
|
|
188
|
+
- `instance` The WebAssembly instance to interact with. Must
|
|
189
|
+
be instantiated from a Ruby built with JS extension, and built
|
|
190
|
+
with Reactor ABI instead of command line.
|
|
191
|
+
|
|
192
|
+
#### addToImports
|
|
193
|
+
|
|
194
|
+
Add intrinsic import entries, which is necessary to interact JavaScript
|
|
195
|
+
and Ruby's WebAssembly instance.
|
|
196
|
+
|
|
197
|
+
##### Parameters
|
|
198
|
+
|
|
199
|
+
- `imports` The import object to add to the WebAssembly instance
|
|
200
|
+
|
|
201
|
+
#### printVersion
|
|
202
|
+
|
|
203
|
+
Print the Ruby version to stdout
|
|
204
|
+
|
|
205
|
+
#### eval
|
|
206
|
+
|
|
207
|
+
Runs a string of Ruby code from JavaScript
|
|
208
|
+
|
|
209
|
+
##### Parameters
|
|
210
|
+
|
|
211
|
+
- `code` The Ruby code to run
|
|
212
|
+
|
|
213
|
+
##### Examples
|
|
214
|
+
|
|
215
|
+
```javascript
|
|
216
|
+
vm.eval("puts 'hello world'");
|
|
217
|
+
const result = vm.eval("1 + 2");
|
|
218
|
+
console.log(result.toString()); // 3
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
Returns **any** the result of the last expression
|
|
222
|
+
|
|
223
|
+
#### evalAsync
|
|
224
|
+
|
|
225
|
+
Runs a string of Ruby code with top-level `JS::Object#await`
|
|
226
|
+
Returns a promise that resolves when execution completes.
|
|
227
|
+
|
|
228
|
+
##### Parameters
|
|
229
|
+
|
|
230
|
+
- `code` The Ruby code to run
|
|
231
|
+
|
|
232
|
+
##### Examples
|
|
233
|
+
|
|
234
|
+
```javascript
|
|
235
|
+
const text = await vm.evalAsync(`
|
|
236
|
+
require 'js'
|
|
237
|
+
response = JS.global.fetch('https://example.com').await
|
|
238
|
+
response.text.await
|
|
239
|
+
`);
|
|
240
|
+
console.log(text.toString()); // <html>...</html>
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
Returns **any** a promise that resolves to the result of the last expression
|
|
244
|
+
|
|
245
|
+
#### wrap
|
|
246
|
+
|
|
247
|
+
Wrap a JavaScript value into a Ruby JS::Object
|
|
248
|
+
|
|
249
|
+
##### Parameters
|
|
250
|
+
|
|
251
|
+
- `value` The value to convert to RbValue
|
|
252
|
+
|
|
253
|
+
##### Examples
|
|
254
|
+
|
|
255
|
+
```javascript
|
|
256
|
+
const hash = vm.eval(`Hash.new`);
|
|
257
|
+
hash.call("store", vm.eval(`"key1"`), vm.wrap(new Object()));
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
Returns **any** the RbValue object representing the given JS value
|
|
261
|
+
|
|
262
|
+
### RbValue
|
|
263
|
+
|
|
264
|
+
A RbValue is an object that represents a value in Ruby
|
|
265
|
+
|
|
266
|
+
#### call
|
|
267
|
+
|
|
268
|
+
Call a given method with given arguments
|
|
269
|
+
|
|
270
|
+
##### Parameters
|
|
271
|
+
|
|
272
|
+
- `callee` name of the Ruby method to call
|
|
273
|
+
- `args` **...any** arguments to pass to the method. Must be an array of RbValue
|
|
274
|
+
|
|
275
|
+
##### Examples
|
|
276
|
+
|
|
277
|
+
```javascript
|
|
278
|
+
const ary = vm.eval("[1, 2, 3]");
|
|
279
|
+
ary.call("push", 4);
|
|
280
|
+
console.log(ary.call("sample").toString());
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
#### toPrimitive
|
|
284
|
+
|
|
285
|
+
- **See**: <https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Symbol/toPrimitive>
|
|
286
|
+
|
|
287
|
+
##### Parameters
|
|
288
|
+
|
|
289
|
+
- `hint` Preferred type of the result primitive value. `"number"`, `"string"`, or `"default"`.
|
|
290
|
+
|
|
291
|
+
#### toString
|
|
292
|
+
|
|
293
|
+
Returns a string representation of the value by calling `to_s`
|
|
294
|
+
|
|
295
|
+
#### toJS
|
|
296
|
+
|
|
297
|
+
Returns a JavaScript object representation of the value
|
|
298
|
+
by calling `to_js`.
|
|
299
|
+
|
|
300
|
+
Returns null if the value is not convertible to a JavaScript object.
|
|
301
|
+
|
|
302
|
+
### RbError
|
|
303
|
+
|
|
304
|
+
**Extends Error**
|
|
305
|
+
|
|
306
|
+
Error class thrown by Ruby execution
|
|
307
|
+
|
|
308
|
+
## Building the package from source
|
|
309
|
+
|
|
310
|
+
The instructions for building a Ruby targeting WebAssembly are available [here](https://github.com/ruby/ruby.wasm#building-from-source).
|
|
311
|
+
|
|
312
|
+
Then, you can run the following command in your shell:
|
|
313
|
+
|
|
314
|
+
```console
|
|
315
|
+
# Check the directory structure of your Ruby build
|
|
316
|
+
$ tree -L 3 path/to/wasm32-unknown-wasi-full-js/
|
|
317
|
+
path/to/wasm32-unknown-wasi-full-js/
|
|
318
|
+
├── usr
|
|
319
|
+
│ └── local
|
|
320
|
+
│ ├── bin
|
|
321
|
+
│ ├── include
|
|
322
|
+
│ ├── lib
|
|
323
|
+
│ └── share
|
|
324
|
+
└── var
|
|
325
|
+
└── lib
|
|
326
|
+
└── gems
|
|
327
|
+
$ ./build-package.sh path/to/wasm32-unknown-wasi-full-js/
|
|
328
|
+
Generating "/Users/katei/.ghq/github.com/ruby/ruby.wasm/packages/ruby-head-wasm-wasi/src/bindgen/intrinsics.js"
|
|
329
|
+
Generating "/Users/katei/.ghq/github.com/ruby/ruby.wasm/packages/ruby-head-wasm-wasi/src/bindgen/rb-abi-guest.d.ts"
|
|
330
|
+
Generating "/Users/katei/.ghq/github.com/ruby/ruby.wasm/packages/ruby-head-wasm-wasi/src/bindgen/rb-abi-guest.js"
|
|
331
|
+
Generating "/Users/katei/.ghq/github.com/ruby/ruby.wasm/packages/ruby-head-wasm-wasi/src/bindgen/rb-js-abi-host.d.ts"
|
|
332
|
+
Generating "/Users/katei/.ghq/github.com/ruby/ruby.wasm/packages/ruby-head-wasm-wasi/src/bindgen/rb-js-abi-host.js"
|
|
333
|
+
|
|
334
|
+
src/index.ts → dist/index.umd.js, dist/index.esm.js, dist/index.cjs.js...
|
|
335
|
+
created dist/index.umd.js, dist/index.esm.js, dist/index.cjs.js in 682ms
|
|
336
|
+
```
|
package/dist/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2022 Yuta Saito
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|