@@ -97,6 +97,7 @@ export class RubyVM {
97
97
return value . toString ( ) ;
98
98
} ,
99
99
takeJsValue : ( value ) => {
100
+ // See `JsValueExporter` for the reason why we need to do this
100
101
this . exporter . takeJsValue ( value ) ;
101
102
} ,
102
103
instanceOf : ( value , klass ) => {
@@ -175,12 +176,32 @@ export class RubyVM {
175
176
}
176
177
}
177
178
179
+ /**
180
+ * Export a JS value held by the Ruby VM to the JS environment.
181
+ * This is implemented in a dirty way since wit cannot reference resources
182
+ * defined in other interfaces.
183
+ * In our case, we can't express `function(v: rb-abi-value) -> js-abi-value`
184
+ * because `rb-js-abi-host.wit`, that defines `js-abi-value`, is implemented
185
+ * by embedder side (JS) but `rb-abi-guest.wit`, that defines `rb-abi-value`
186
+ * is implemented by guest side (Wasm).
187
+ *
188
+ * This class is a helper to export by:
189
+ * 1. Call `function __export_to_js(v: rb-abi-value)` defined in guest from embedder side.
190
+ * 2. Call `function takeJsValue(v: js-abi-value)` defined in embedder from guest side with
191
+ * underlying JS value of given `rb-abi-value`.
192
+ * 3. Then `takeJsValue` implementation escapes the given JS value to the `_takenJsValues`
193
+ * stored in embedder side.
194
+ * 4. Finally, embedder side can take `_takenJsValues`.
195
+ *
196
+ * Note that `exportJsValue` is not reentrant.
197
+ */
178
198
class JsValueExporter {
179
199
private _takenJsValues : JsAbiValue = null ;
180
200
takeJsValue ( value : JsAbiValue ) {
181
201
this . _takenJsValues = value ;
182
202
}
183
- exportJsValue ( ) : JsAbiValue {
203
+ exportJsValue ( value : RbValue ) : JsAbiValue {
204
+ value . call ( "__export_to_js" ) ;
184
205
return this . _takenJsValues ;
185
206
}
186
207
}
@@ -254,8 +275,7 @@ export class RbValue {
254
275
if ( jsValue . call ( "nil?" ) . toString ( ) === "true" ) {
255
276
return null ;
256
277
}
257
- jsValue . call ( "__export_to_js" ) ;
258
- return this . privateObject . exporter . exportJsValue ( ) ;
278
+ return this . privateObject . exporter . exportJsValue ( jsValue ) ;
259
279
}
260
280
}
261
281
0 commit comments