@@ -26,9 +26,9 @@ import { DefaultRubyVM } from "ruby-head-wasm-wasi/dist/node.cjs.js";
26
26
27
27
const main = async () => {
28
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.wasm"
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.wasm"
32
32
" ./node_modules/ruby-head-wasm-wasi/dist/ruby.wasm"
33
33
);
34
34
const module = await WebAssembly .compile (binary);
@@ -62,9 +62,9 @@ See [the example project](https://github.com/ruby/ruby.wasm/tree/main/packages/n
62
62
const main = async () => {
63
63
// Fetch and instntiate WebAssembly binary
64
64
const response = await fetch (
65
- // Tips: Replace the binary with debug info if you want symbolicated stack trace.
66
- // (only nightly release for now)
67
- // "https://cdn.jsdelivr.net/npm/ruby-head-wasm-wasi@latest/dist/ruby.debug.wasm"
65
+ // Tips: Replace the binary with debug info if you want symbolicated stack trace.
66
+ // (only nightly release for now)
67
+ // "https://cdn.jsdelivr.net/npm/ruby-head-wasm-wasi@latest/dist/ruby.debug.wasm"
68
68
" https://cdn.jsdelivr.net/npm/ruby-head-wasm-wasi@latest/dist/ruby.wasm"
69
69
);
70
70
const buffer = await response .arrayBuffer ();
@@ -85,44 +85,68 @@ See [the example project](https://github.com/ruby/ruby.wasm/tree/main/packages/n
85
85
</html >
86
86
```
87
87
88
- <!-- The APIs section was generated by `npx documentation readme ./dist/index.esm.js --section=APIs` -->
88
+ ## GC limitation with JavaScript interoperability
89
+
90
+ 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.
91
+
92
+ The following code will cause a memory leak:
93
+
94
+ ``` javascript
95
+ class JNode {
96
+ setRNode (rnode ) {
97
+ this .rnode = rnode;
98
+ }
99
+ }
100
+ jnode = new JNode ();
101
+
102
+ rnode = vm .eval (`
103
+ class RNode
104
+ def set_jnode(jnode)
105
+ @jnode = jnode
106
+ end
107
+ end
108
+ RNode.new
109
+ ` );
110
+
111
+ rnode .call (" set_jnode" , vm .wrap (jnode));
112
+ jnode .setRNode (rnode);
113
+ ```
114
+
115
+ <!-- The APIs section was generated by `npx documentation readme ../ruby-wasm-wasi/dist/index.esm.js --section=APIs` -->
89
116
90
117
## APIs
91
118
92
119
<!-- Generated by documentation.js. Update this documentation by updating the source code. -->
93
120
94
121
#### Table of Contents
95
122
96
- - [ ruby-head-wasm-wasi] ( #ruby-head-wasm-wasi )
97
- - [ Installation] ( #installation )
98
- - [ Quick Start (for Node.js)] ( #quick-start-for-nodejs )
99
- - [ Quick Start (for Browser)] ( #quick-start-for-browser )
100
- - [ APIs] ( #apis )
101
- - [ Table of Contents] ( #table-of-contents )
102
- - [ RubyVM] ( #rubyvm )
103
- - [ Examples] ( #examples )
104
- - [ initialize] ( #initialize )
105
- - [ Parameters] ( #parameters )
106
- - [ setInstance] ( #setinstance )
107
- - [ Parameters] ( #parameters-1 )
108
- - [ addToImports] ( #addtoimports )
109
- - [ Parameters] ( #parameters-2 )
110
- - [ printVersion] ( #printversion )
111
- - [ eval] ( #eval )
112
- - [ Parameters] ( #parameters-3 )
113
- - [ Examples] ( #examples-1 )
114
- - [ RbValue] ( #rbvalue )
115
- - [ Parameters] ( #parameters-4 )
116
- - [ call] ( #call )
117
- - [ Parameters] ( #parameters-5 )
118
- - [ Examples] ( #examples-2 )
119
- - [ toPrimitive] ( #toprimitive )
120
- - [ Parameters] ( #parameters-6 )
121
- - [ toString] ( #tostring )
122
- - [ toJS] ( #tojs )
123
- - [ RbError] ( #rberror )
124
- - [ Parameters] ( #parameters-7 )
125
- - [ Building the package from source] ( #building-the-package-from-source )
123
+ - [ RubyVM] ( #rubyvm )
124
+ - [ Examples] ( #examples )
125
+ - [ initialize] ( #initialize )
126
+ - [ Parameters] ( #parameters )
127
+ - [ setInstance] ( #setinstance )
128
+ - [ Parameters] ( #parameters-1 )
129
+ - [ addToImports] ( #addtoimports )
130
+ - [ Parameters] ( #parameters-2 )
131
+ - [ printVersion] ( #printversion )
132
+ - [ eval] ( #eval )
133
+ - [ Parameters] ( #parameters-3 )
134
+ - [ Examples] ( #examples-1 )
135
+ - [ wrap] ( #wrap )
136
+ - [ Parameters] ( #parameters-4 )
137
+ - [ Examples] ( #examples-2 )
138
+ - [ JsValueTransport] ( #jsvaluetransport )
139
+ - [ RbValue] ( #rbvalue )
140
+ - [ Parameters] ( #parameters-5 )
141
+ - [ call] ( #call )
142
+ - [ Parameters] ( #parameters-6 )
143
+ - [ Examples] ( #examples-3 )
144
+ - [ toPrimitive] ( #toprimitive )
145
+ - [ Parameters] ( #parameters-7 )
146
+ - [ toString] ( #tostring )
147
+ - [ toJS] ( #tojs )
148
+ - [ RbError] ( #rberror )
149
+ - [ Parameters] ( #parameters-8 )
126
150
127
151
### RubyVM
128
152
@@ -142,6 +166,7 @@ vm.addToImports(imports);
142
166
const instance = await WebAssembly .instantiate (rubyModule, imports);
143
167
await vm .setInstance (instance);
144
168
wasi .initialize (instance);
169
+ vm .initialize ();
145
170
```
146
171
147
172
#### initialize
@@ -196,6 +221,44 @@ console.log(result.toString()); // 3
196
221
197
222
Returns ** any** the result of the last expression
198
223
224
+ #### wrap
225
+
226
+ Wrap a JavaScript value into a Ruby JS::Object
227
+
228
+ ##### Parameters
229
+
230
+ - ` value ` The value to convert to RbValue
231
+
232
+ ##### Examples
233
+
234
+ ``` javascript
235
+ const hash = vm .eval (` Hash.new` );
236
+ hash .call (" store" , vm .eval (` "key1"` ), vm .wrap (new Object ()));
237
+ ```
238
+
239
+ Returns ** any** the RbValue object representing the given JS value
240
+
241
+ ### JsValueTransport
242
+
243
+ Export a JS value held by the Ruby VM to the JS environment.
244
+ This is implemented in a dirty way since wit cannot reference resources
245
+ defined in other interfaces.
246
+ In our case, we can't express ` function(v: rb-abi-value) -> js-abi-value `
247
+ because ` rb-js-abi-host.wit ` , that defines ` js-abi-value ` , is implemented
248
+ by embedder side (JS) but ` rb-abi-guest.wit ` , that defines ` rb-abi-value `
249
+ is implemented by guest side (Wasm).
250
+
251
+ This class is a helper to export by:
252
+
253
+ 1 . Call ` function __export_to_js(v: rb-abi-value) ` defined in guest from embedder side.
254
+ 2 . Call ` function takeJsValue(v: js-abi-value) ` defined in embedder from guest side with
255
+ underlying JS value of given ` rb-abi-value ` .
256
+ 3 . Then ` takeJsValue ` implementation escapes the given JS value to the ` _takenJsValues `
257
+ stored in embedder side.
258
+ 4 . Finally, embedder side can take ` _takenJsValues ` .
259
+
260
+ Note that ` exportJsValue ` is not reentrant.
261
+
199
262
### RbValue
200
263
201
264
A RbValue is an object that represents a value in Ruby
@@ -204,7 +267,7 @@ A RbValue is an object that represents a value in Ruby
204
267
205
268
- ` inner `
206
269
- ` vm `
207
- - ` exporter `
270
+ - ` privateObject `
208
271
209
272
#### call
210
273
0 commit comments