@@ -23,12 +23,12 @@ import { addRbJsAbiHostToImports, JsAbiValue } from "./bindgen/rb-js-abi-host";
23
23
export class RubyVM {
24
24
guest : RbAbi . RbAbiGuest ;
25
25
private instance : WebAssembly . Instance | null = null ;
26
- private exporter : JsValueExporter ;
26
+ private transport : JsValueTransport ;
27
27
private exceptionFormatter : RbExceptionFormatter ;
28
28
29
29
constructor ( ) {
30
30
this . guest = new RbAbi . RbAbiGuest ( ) ;
31
- this . exporter = new JsValueExporter ( ) ;
31
+ this . transport = new JsValueTransport ( ) ;
32
32
this . exceptionFormatter = new RbExceptionFormatter ( ) ;
33
33
}
34
34
@@ -101,9 +101,12 @@ export class RubyVM {
101
101
jsValueToString : ( value ) => {
102
102
return value . toString ( ) ;
103
103
} ,
104
- takeJsValue : ( value ) => {
104
+ exportJsValueToHost : ( value ) => {
105
105
// See `JsValueExporter` for the reason why we need to do this
106
- this . exporter . takeJsValue ( value ) ;
106
+ this . transport . takeJsValue ( value ) ;
107
+ } ,
108
+ importJsValueFromHost : ( ) => {
109
+ return this . transport . consumeJsValue ( ) ;
107
110
} ,
108
111
instanceOf : ( value , klass ) => {
109
112
if ( typeof klass === "function" ) {
@@ -180,8 +183,21 @@ export class RubyVM {
180
183
return evalRbCode ( this , this . privateObject ( ) , code ) ;
181
184
}
182
185
186
+ /**
187
+ * Wrap a JavaScript value into a Ruby JS::Object
188
+ * @param value The value to convert to RbValue
189
+ * @returns the RbValue object representing the given JS value
190
+ *
191
+ * @example
192
+ * const hash = vm.eval(`Hash.new`)
193
+ * hash.call("store", vm.eval(`"key1"`), vm.wrap(new Object()));
194
+ */
195
+ wrap ( value : any ) : RbValue {
196
+ return this . transport . importJsValue ( value , this ) ;
197
+ }
198
+
183
199
private privateObject ( ) : RubyVMPrivate {
184
- return { exporter : this . exporter , exceptionFormatter : this . exceptionFormatter }
200
+ return { transport : this . transport , exceptionFormatter : this . exceptionFormatter }
185
201
}
186
202
}
187
203
@@ -204,14 +220,26 @@ export class RubyVM {
204
220
*
205
221
* Note that `exportJsValue` is not reentrant.
206
222
*/
207
- class JsValueExporter {
208
- private _takenJsValues : JsAbiValue = null ;
223
+ class JsValueTransport {
224
+ private _takenJsValue : JsAbiValue = null ;
209
225
takeJsValue ( value : JsAbiValue ) {
210
- this . _takenJsValues = value ;
226
+ this . _takenJsValue = value ;
227
+ }
228
+ consumeJsValue ( ) : JsAbiValue {
229
+ return this . _takenJsValue ;
211
230
}
231
+
212
232
exportJsValue ( value : RbValue ) : JsAbiValue {
213
233
value . call ( "__export_to_js" ) ;
214
- return this . _takenJsValues ;
234
+ return this . _takenJsValue ;
235
+ }
236
+
237
+ importJsValue ( value : JsAbiValue , vm : RubyVM ) : RbValue {
238
+ this . _takenJsValue = value ;
239
+ return vm . eval ( `
240
+ require "js"
241
+ JS::Object.__import_from_js
242
+ ` ) ;
215
243
}
216
244
}
217
245
@@ -284,7 +312,7 @@ export class RbValue {
284
312
if ( jsValue . call ( "nil?" ) . toString ( ) === "true" ) {
285
313
return null ;
286
314
}
287
- return this . privateObject . exporter . exportJsValue ( jsValue ) ;
315
+ return this . privateObject . transport . exportJsValue ( jsValue ) ;
288
316
}
289
317
}
290
318
@@ -302,7 +330,7 @@ enum ruby_tag_type {
302
330
}
303
331
304
332
type RubyVMPrivate = {
305
- exporter : JsValueExporter ,
333
+ transport : JsValueTransport ,
306
334
exceptionFormatter : RbExceptionFormatter ,
307
335
} ;
308
336
0 commit comments