@ruby/wasm-wasi 2.5.1 → 2.5.2

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.
Files changed (32) hide show
  1. package/dist/browser.script.umd.js +181 -66
  2. package/dist/browser.umd.js +181 -66
  3. package/dist/cjs/bindgen/interfaces/ruby-js-js-runtime.d.ts +45 -0
  4. package/dist/cjs/bindgen/interfaces/ruby-js-ruby-runtime.d.ts +42 -0
  5. package/dist/cjs/bindgen/{rb-js-abi-host.d.ts → legacy/rb-js-abi-host.d.ts} +3 -3
  6. package/dist/cjs/bindgen/{rb-js-abi-host.js → legacy/rb-js-abi-host.js} +2 -2
  7. package/dist/cjs/binding.d.ts +54 -0
  8. package/dist/cjs/binding.js +72 -0
  9. package/dist/cjs/browser.js +6 -1
  10. package/dist/cjs/node.js +1 -1
  11. package/dist/cjs/vm.d.ts +12 -5
  12. package/dist/cjs/vm.js +104 -63
  13. package/dist/esm/bindgen/interfaces/ruby-js-js-runtime.d.ts +45 -0
  14. package/dist/esm/bindgen/interfaces/ruby-js-ruby-runtime.d.ts +42 -0
  15. package/dist/esm/bindgen/{rb-js-abi-host.d.ts → legacy/rb-js-abi-host.d.ts} +3 -3
  16. package/dist/esm/bindgen/{rb-js-abi-host.js → legacy/rb-js-abi-host.js} +2 -2
  17. package/dist/esm/binding.d.ts +54 -0
  18. package/dist/esm/binding.js +66 -0
  19. package/dist/esm/browser.js +7 -2
  20. package/dist/esm/node.js +1 -1
  21. package/dist/esm/vm.d.ts +12 -5
  22. package/dist/esm/vm.js +104 -63
  23. package/dist/index.umd.js +169 -63
  24. package/package.json +9 -8
  25. /package/dist/cjs/bindgen/{intrinsics.d.ts → legacy/intrinsics.d.ts} +0 -0
  26. /package/dist/cjs/bindgen/{intrinsics.js → legacy/intrinsics.js} +0 -0
  27. /package/dist/cjs/bindgen/{rb-abi-guest.d.ts → legacy/rb-abi-guest.d.ts} +0 -0
  28. /package/dist/cjs/bindgen/{rb-abi-guest.js → legacy/rb-abi-guest.js} +0 -0
  29. /package/dist/esm/bindgen/{intrinsics.d.ts → legacy/intrinsics.d.ts} +0 -0
  30. /package/dist/esm/bindgen/{intrinsics.js → legacy/intrinsics.js} +0 -0
  31. /package/dist/esm/bindgen/{rb-abi-guest.d.ts → legacy/rb-abi-guest.d.ts} +0 -0
  32. /package/dist/esm/bindgen/{rb-abi-guest.js → legacy/rb-abi-guest.js} +0 -0
@@ -0,0 +1,54 @@
1
+ import { RubyJsRubyRuntime } from "./bindgen/interfaces/ruby-js-ruby-runtime.js";
2
+ import * as RbAbi from "./bindgen/legacy/rb-abi-guest.js";
3
+ /**
4
+ * This interface bridges between the Ruby runtime and the JavaScript runtime
5
+ * and defines how to interact with underlying import/export functions.
6
+ */
7
+ export interface Binding {
8
+ rubyShowVersion(): void;
9
+ rubyInit(): void;
10
+ rubySysinit(args: string[]): void;
11
+ rubyOptions(args: string[]): void;
12
+ rubyScript(name: string): void;
13
+ rubyInitLoadpath(): void;
14
+ rbEvalStringProtect(str: string): [RbAbiValue, number];
15
+ rbFuncallvProtect(recv: RbAbiValue, mid: RbAbi.RbId, args: RbAbiValue[]): [RbAbiValue, number];
16
+ rbIntern(name: string): RbAbi.RbId;
17
+ rbErrinfo(): RbAbiValue;
18
+ rbClearErrinfo(): void;
19
+ rstringPtr(value: RbAbiValue): string;
20
+ rbVmBugreport(): void;
21
+ rbGcEnable(): boolean;
22
+ rbGcDisable(): boolean;
23
+ rbSetShouldProhibitRewind(newValue: boolean): boolean;
24
+ setInstance(instance: WebAssembly.Instance): Promise<void>;
25
+ addToImports(imports: WebAssembly.Imports): void;
26
+ }
27
+ export interface RbAbiValue {
28
+ }
29
+ export declare class LegacyBinding extends RbAbi.RbAbiGuest implements Binding {
30
+ setInstance(instance: WebAssembly.Instance): Promise<void>;
31
+ }
32
+ export declare class ComponentBinding implements Binding {
33
+ underlying: typeof RubyJsRubyRuntime;
34
+ constructor();
35
+ setUnderlying(underlying: typeof RubyJsRubyRuntime): void;
36
+ rubyShowVersion(): void;
37
+ rubyInit(): void;
38
+ rubySysinit(args: string[]): void;
39
+ rubyOptions(args: string[]): void;
40
+ rubyScript(name: string): void;
41
+ rubyInitLoadpath(): void;
42
+ rbEvalStringProtect(str: string): [RbAbiValue, number];
43
+ rbFuncallvProtect(recv: RbAbiValue, mid: number, args: RbAbiValue[]): [RbAbiValue, number];
44
+ rbIntern(name: string): number;
45
+ rbErrinfo(): RbAbiValue;
46
+ rbClearErrinfo(): void;
47
+ rstringPtr(value: RbAbiValue): string;
48
+ rbVmBugreport(): void;
49
+ rbGcEnable(): boolean;
50
+ rbGcDisable(): boolean;
51
+ rbSetShouldProhibitRewind(newValue: boolean): boolean;
52
+ setInstance(instance: WebAssembly.Instance): Promise<void>;
53
+ addToImports(imports: WebAssembly.Imports): void;
54
+ }
@@ -0,0 +1,66 @@
1
+ import * as RbAbi from "./bindgen/legacy/rb-abi-guest.js";
2
+ export class LegacyBinding extends RbAbi.RbAbiGuest {
3
+ async setInstance(instance) {
4
+ await this.instantiate(instance);
5
+ }
6
+ }
7
+ export class ComponentBinding {
8
+ constructor() { }
9
+ setUnderlying(underlying) {
10
+ this.underlying = underlying;
11
+ }
12
+ rubyShowVersion() {
13
+ this.underlying.rubyShowVersion();
14
+ }
15
+ rubyInit() {
16
+ this.underlying.rubyInit();
17
+ }
18
+ rubySysinit(args) {
19
+ this.underlying.rubySysinit(args);
20
+ }
21
+ rubyOptions(args) {
22
+ this.underlying.rubyOptions(args);
23
+ }
24
+ rubyScript(name) {
25
+ this.underlying.rubyScript(name);
26
+ }
27
+ rubyInitLoadpath() {
28
+ this.underlying.rubyInitLoadpath();
29
+ }
30
+ rbEvalStringProtect(str) {
31
+ return this.underlying.rbEvalStringProtect(str);
32
+ }
33
+ rbFuncallvProtect(recv, mid, args) {
34
+ return this.underlying.rbFuncallvProtect(recv, mid, args);
35
+ }
36
+ rbIntern(name) {
37
+ return this.underlying.rbIntern(name);
38
+ }
39
+ rbErrinfo() {
40
+ return this.underlying.rbErrinfo();
41
+ }
42
+ rbClearErrinfo() {
43
+ return this.underlying.rbClearErrinfo();
44
+ }
45
+ rstringPtr(value) {
46
+ return this.underlying.rstringPtr(value);
47
+ }
48
+ rbVmBugreport() {
49
+ this.underlying.rbVmBugreport();
50
+ }
51
+ rbGcEnable() {
52
+ return this.underlying.rbGcEnable();
53
+ }
54
+ rbGcDisable() {
55
+ return this.underlying.rbGcDisable();
56
+ }
57
+ rbSetShouldProhibitRewind(newValue) {
58
+ return this.underlying.rbSetShouldProhibitRewind(newValue);
59
+ }
60
+ async setInstance(instance) {
61
+ // No-op
62
+ }
63
+ addToImports(imports) {
64
+ // No-op
65
+ }
66
+ }
@@ -1,11 +1,16 @@
1
- import { WASI } from "@bjorn3/browser_wasi_shim";
1
+ import { File, OpenFile, PreopenDirectory, WASI } from "@bjorn3/browser_wasi_shim";
2
2
  import { consolePrinter } from "./console.js";
3
3
  import { RubyVM } from "./vm.js";
4
4
  export const DefaultRubyVM = async (rubyModule, options = {}) => {
5
5
  var _a, _b;
6
6
  const args = [];
7
7
  const env = Object.entries((_a = options.env) !== null && _a !== void 0 ? _a : {}).map(([k, v]) => `${k}=${v}`);
8
- const fds = [];
8
+ const fds = [
9
+ new OpenFile(new File([])),
10
+ new OpenFile(new File([])),
11
+ new OpenFile(new File([])),
12
+ new PreopenDirectory("/", new Map()),
13
+ ];
9
14
  const wasi = new WASI(args, env, fds, { debug: false });
10
15
  const vm = new RubyVM();
11
16
  const imports = {
package/dist/esm/node.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { WASI } from "wasi";
2
2
  import { RubyVM } from "./vm.js";
3
3
  export const DefaultRubyVM = async (rubyModule, options = {}) => {
4
- const wasi = new WASI({ env: options.env, version: "preview1" });
4
+ const wasi = new WASI({ env: options.env, version: "preview1", returnOnExit: true });
5
5
  const vm = new RubyVM();
6
6
  const imports = {
7
7
  wasi_snapshot_preview1: wasi.wasiImport,
package/dist/esm/vm.d.ts CHANGED
@@ -1,5 +1,7 @@
1
- import * as RbAbi from "./bindgen/rb-abi-guest.js";
2
- import { JsAbiValue } from "./bindgen/rb-js-abi-host.js";
1
+ import type { RubyJsJsRuntime } from "./bindgen/interfaces/ruby-js-js-runtime.js";
2
+ import type { RubyJsRubyRuntime } from "./bindgen/interfaces/ruby-js-ruby-runtime.js";
3
+ import { JsAbiValue } from "./bindgen/legacy/rb-js-abi-host.js";
4
+ import { Binding, RbAbiValue } from "./binding.js";
3
5
  /**
4
6
  * A Ruby VM instance
5
7
  *
@@ -20,12 +22,15 @@ import { JsAbiValue } from "./bindgen/rb-js-abi-host.js";
20
22
  *
21
23
  */
22
24
  export declare class RubyVM {
23
- guest: RbAbi.RbAbiGuest;
25
+ guest: Binding;
24
26
  private instance;
25
27
  private transport;
26
28
  private exceptionFormatter;
27
29
  private interfaceState;
28
- constructor();
30
+ constructor(binding?: Binding);
31
+ static _instantiate(initComponent: (_: typeof RubyJsJsRuntime) => Promise<typeof RubyJsRubyRuntime>, options: {
32
+ args?: string[];
33
+ }): Promise<RubyVM>;
29
34
  /**
30
35
  * Initialize the Ruby VM with the given command line arguments
31
36
  * @param args The command line arguments to pass to Ruby. Must be
@@ -48,6 +53,8 @@ export declare class RubyVM {
48
53
  * @param imports The import object to add to the WebAssembly instance
49
54
  */
50
55
  addToImports(imports: WebAssembly.Imports): void;
56
+ private throwProhibitRewindException;
57
+ private getImports;
51
58
  /**
52
59
  * Print the Ruby version to stdout
53
60
  */
@@ -132,7 +139,7 @@ export declare class RbValue {
132
139
  /**
133
140
  * @hideconstructor
134
141
  */
135
- constructor(inner: RbAbi.RbAbiValue, vm: RubyVM, privateObject: RubyVMPrivate);
142
+ constructor(inner: RbAbiValue, vm: RubyVM, privateObject: RubyVMPrivate);
136
143
  /**
137
144
  * Call a given method with given arguments
138
145
  *
package/dist/esm/vm.js CHANGED
@@ -1,5 +1,6 @@
1
- import * as RbAbi from "./bindgen/rb-abi-guest.js";
2
- import { addRbJsAbiHostToImports, } from "./bindgen/rb-js-abi-host.js";
1
+ import * as RbAbi from "./bindgen/legacy/rb-abi-guest.js";
2
+ import { addRbJsAbiHostToImports, } from "./bindgen/legacy/rb-js-abi-host.js";
3
+ import { ComponentBinding, LegacyBinding } from "./binding.js";
3
4
  /**
4
5
  * A Ruby VM instance
5
6
  *
@@ -20,7 +21,7 @@ import { addRbJsAbiHostToImports, } from "./bindgen/rb-js-abi-host.js";
20
21
  *
21
22
  */
22
23
  export class RubyVM {
23
- constructor() {
24
+ constructor(binding) {
24
25
  this.instance = null;
25
26
  this.interfaceState = {
26
27
  hasJSFrameAfterRbFrame: false,
@@ -29,6 +30,7 @@ export class RubyVM {
29
30
  // if the call stack has sandwitched JS frames like JS -> Ruby -> JS -> Ruby.
30
31
  const proxyExports = (exports) => {
31
32
  const excludedMethods = [
33
+ "setInstance",
32
34
  "addToImports",
33
35
  "instantiate",
34
36
  "rbSetShouldProhibitRewind",
@@ -63,10 +65,34 @@ export class RubyVM {
63
65
  }
64
66
  return exports;
65
67
  };
66
- this.guest = proxyExports(new RbAbi.RbAbiGuest());
68
+ this.guest = proxyExports(binding !== null && binding !== void 0 ? binding : new LegacyBinding());
67
69
  this.transport = new JsValueTransport();
68
70
  this.exceptionFormatter = new RbExceptionFormatter();
69
71
  }
72
+ static async _instantiate(initComponent, options) {
73
+ const binding = new ComponentBinding();
74
+ const vm = new RubyVM(binding);
75
+ class JsAbiValue {
76
+ constructor(underlying) {
77
+ this.underlying = underlying;
78
+ }
79
+ }
80
+ const imports = vm.getImports((from) => new JsAbiValue(from), (to) => to.underlying);
81
+ const component = await initComponent(Object.assign(Object.assign({}, imports), { throwProhibitRewindException: (message) => {
82
+ vm.throwProhibitRewindException(message);
83
+ }, procToJsFunction: () => {
84
+ const rbValue = new RbValue(component.exportRbValueToJs(), vm, vm.privateObject());
85
+ return new JsAbiValue((...args) => {
86
+ return rbValue.call("call", ...args.map((arg) => vm.wrap(arg))).toJS();
87
+ });
88
+ }, rbObjectToJsRbValue: () => {
89
+ const rbValue = new RbValue(component.exportRbValueToJs(), vm, vm.privateObject());
90
+ return new JsAbiValue(rbValue);
91
+ }, JsAbiValue: JsAbiValue }));
92
+ binding.setUnderlying(component);
93
+ vm.initialize(options.args);
94
+ return vm;
95
+ }
70
96
  /**
71
97
  * Initialize the Ruby VM with the given command line arguments
72
98
  * @param args The command line arguments to pass to Ruby. Must be
@@ -90,7 +116,7 @@ export class RubyVM {
90
116
  */
91
117
  async setInstance(instance) {
92
118
  this.instance = instance;
93
- await this.guest.instantiate(instance);
119
+ await this.guest.setInstance(instance);
94
120
  }
95
121
  /**
96
122
  * Add intrinsic import entries, which is necessary to interact JavaScript
@@ -99,43 +125,36 @@ export class RubyVM {
99
125
  */
100
126
  addToImports(imports) {
101
127
  this.guest.addToImports(imports);
102
- function wrapTry(f) {
103
- return (...args) => {
104
- try {
105
- return { tag: "success", val: f(...args) };
106
- }
107
- catch (e) {
108
- if (e instanceof RbFatalError) {
109
- // RbFatalError should not be caught by Ruby because it Ruby VM
110
- // can be already in an inconsistent state.
111
- throw e;
112
- }
113
- return { tag: "failure", val: e };
114
- }
115
- };
116
- }
117
128
  imports["rb-js-abi-host"] = {
118
129
  rb_wasm_throw_prohibit_rewind_exception: (messagePtr, messageLen) => {
119
130
  const memory = this.instance.exports.memory;
120
131
  const str = new TextDecoder().decode(new Uint8Array(memory.buffer, messagePtr, messageLen));
121
- let message = "Ruby APIs that may rewind the VM stack are prohibited under nested VM operation " +
122
- `(${str})\n` +
123
- "Nested VM operation means that the call stack has sandwitched JS frames like JS -> Ruby -> JS -> Ruby " +
124
- "caused by something like `window.rubyVM.eval(\"JS.global[:rubyVM].eval('Fiber.yield')\")`\n" +
125
- "\n" +
126
- "Please check your call stack and make sure that you are **not** doing any of the following inside the nested Ruby frame:\n" +
127
- " 1. Switching fibers (e.g. Fiber#resume, Fiber.yield, and Fiber#transfer)\n" +
128
- " Note that `evalAsync` JS API switches fibers internally\n" +
129
- " 2. Raising uncaught exceptions\n" +
130
- " Please catch all exceptions inside the nested operation\n" +
131
- " 3. Calling Continuation APIs\n";
132
- const error = new RbValue(this.guest.rbErrinfo(), this, this.privateObject());
133
- if (error.call("nil?").toString() === "false") {
134
- message += "\n" + this.exceptionFormatter.format(error, this, this.privateObject());
135
- }
136
- throw new RbFatalError(message);
132
+ this.throwProhibitRewindException(str);
137
133
  },
138
134
  };
135
+ addRbJsAbiHostToImports(imports, this.getImports((value) => value, (value) => value), (name) => {
136
+ return this.instance.exports[name];
137
+ });
138
+ }
139
+ throwProhibitRewindException(str) {
140
+ let message = "Ruby APIs that may rewind the VM stack are prohibited under nested VM operation " +
141
+ `(${str})\n` +
142
+ "Nested VM operation means that the call stack has sandwitched JS frames like JS -> Ruby -> JS -> Ruby " +
143
+ "caused by something like `window.rubyVM.eval(\"JS.global[:rubyVM].eval('Fiber.yield')\")`\n" +
144
+ "\n" +
145
+ "Please check your call stack and make sure that you are **not** doing any of the following inside the nested Ruby frame:\n" +
146
+ " 1. Switching fibers (e.g. Fiber#resume, Fiber.yield, and Fiber#transfer)\n" +
147
+ " Note that `evalAsync` JS API switches fibers internally\n" +
148
+ " 2. Raising uncaught exceptions\n" +
149
+ " Please catch all exceptions inside the nested operation\n" +
150
+ " 3. Calling Continuation APIs\n";
151
+ const error = new RbValue(this.guest.rbErrinfo(), this, this.privateObject());
152
+ if (error.call("nil?").toString() === "false") {
153
+ message += "\n" + this.exceptionFormatter.format(error, this, this.privateObject());
154
+ }
155
+ throw new RbFatalError(message);
156
+ }
157
+ getImports(toJSAbiValue, fromJSAbiValue) {
139
158
  // NOTE: The GC may collect objects that are still referenced by Wasm
140
159
  // locals because Asyncify cannot scan the Wasm stack above the JS frame.
141
160
  // So we need to keep track whether the JS frame is sandwitched by Ruby
@@ -154,9 +173,24 @@ export class RubyVM {
154
173
  }
155
174
  return imports;
156
175
  };
157
- addRbJsAbiHostToImports(imports, proxyImports({
176
+ function wrapTry(f) {
177
+ return (...args) => {
178
+ try {
179
+ return { tag: "success", val: f(...args) };
180
+ }
181
+ catch (e) {
182
+ if (e instanceof RbFatalError) {
183
+ // RbFatalError should not be caught by Ruby because it Ruby VM
184
+ // can be already in an inconsistent state.
185
+ throw e;
186
+ }
187
+ return { tag: "failure", val: toJSAbiValue(e) };
188
+ }
189
+ };
190
+ }
191
+ return proxyImports({
158
192
  evalJs: wrapTry((code) => {
159
- return Function(code)();
193
+ return toJSAbiValue(Function(code)());
160
194
  }),
161
195
  isJs: (value) => {
162
196
  // Just for compatibility with the old JS API
@@ -164,45 +198,47 @@ export class RubyVM {
164
198
  },
165
199
  globalThis: () => {
166
200
  if (typeof globalThis !== "undefined") {
167
- return globalThis;
201
+ return toJSAbiValue(globalThis);
168
202
  }
169
203
  else if (typeof global !== "undefined") {
170
- return global;
204
+ return toJSAbiValue(global);
171
205
  }
172
206
  else if (typeof window !== "undefined") {
173
- return window;
207
+ return toJSAbiValue(window);
174
208
  }
175
209
  throw new Error("unable to locate global object");
176
210
  },
177
211
  intToJsNumber: (value) => {
178
- return value;
212
+ return toJSAbiValue(value);
179
213
  },
180
214
  floatToJsNumber: (value) => {
181
- return value;
215
+ return toJSAbiValue(value);
182
216
  },
183
217
  stringToJsString: (value) => {
184
- return value;
218
+ return toJSAbiValue(value);
185
219
  },
186
220
  boolToJsBool: (value) => {
187
- return value;
221
+ return toJSAbiValue(value);
188
222
  },
189
223
  procToJsFunction: (rawRbAbiValue) => {
190
224
  const rbValue = this.rbValueOfPointer(rawRbAbiValue);
191
- return (...args) => {
225
+ return toJSAbiValue((...args) => {
192
226
  return rbValue.call("call", ...args.map((arg) => this.wrap(arg))).toJS();
193
- };
227
+ });
194
228
  },
195
229
  rbObjectToJsRbValue: (rawRbAbiValue) => {
196
- return this.rbValueOfPointer(rawRbAbiValue);
230
+ return toJSAbiValue(this.rbValueOfPointer(rawRbAbiValue));
197
231
  },
198
232
  jsValueToString: (value) => {
233
+ value = fromJSAbiValue(value);
199
234
  // According to the [spec](https://tc39.es/ecma262/multipage/text-processing.html#sec-string-constructor-string-value)
200
235
  // `String(value)` always returns a string.
201
236
  return String(value);
202
237
  },
203
238
  jsValueToInteger(value) {
239
+ value = fromJSAbiValue(value);
204
240
  if (typeof value === "number") {
205
- return { tag: "f64", val: value };
241
+ return { tag: "as-float", val: value };
206
242
  }
207
243
  else if (typeof value === "bigint") {
208
244
  return { tag: "bignum", val: BigInt(value).toString(10) + "\0" };
@@ -211,38 +247,40 @@ export class RubyVM {
211
247
  return { tag: "bignum", val: value + "\0" };
212
248
  }
213
249
  else if (typeof value === "undefined") {
214
- return { tag: "f64", val: 0 };
250
+ return { tag: "as-float", val: 0 };
215
251
  }
216
252
  else {
217
- return { tag: "f64", val: Number(value) };
253
+ return { tag: "as-float", val: Number(value) };
218
254
  }
219
255
  },
220
256
  exportJsValueToHost: (value) => {
221
257
  // See `JsValueExporter` for the reason why we need to do this
222
- this.transport.takeJsValue(value);
258
+ this.transport.takeJsValue(fromJSAbiValue(value));
223
259
  },
224
260
  importJsValueFromHost: () => {
225
- return this.transport.consumeJsValue();
261
+ return toJSAbiValue(this.transport.consumeJsValue());
226
262
  },
227
263
  instanceOf: (value, klass) => {
264
+ klass = fromJSAbiValue(klass);
228
265
  if (typeof klass === "function") {
229
- return value instanceof klass;
266
+ return fromJSAbiValue(value) instanceof klass;
230
267
  }
231
268
  else {
232
269
  return false;
233
270
  }
234
271
  },
235
272
  jsValueTypeof(value) {
236
- return typeof value;
273
+ return typeof fromJSAbiValue(value);
237
274
  },
238
275
  jsValueEqual(lhs, rhs) {
239
- return lhs == rhs;
276
+ return fromJSAbiValue(lhs) == fromJSAbiValue(rhs);
240
277
  },
241
278
  jsValueStrictlyEqual(lhs, rhs) {
242
- return lhs === rhs;
279
+ return fromJSAbiValue(lhs) === fromJSAbiValue(rhs);
243
280
  },
244
281
  reflectApply: wrapTry((target, thisArgument, args) => {
245
- return Reflect.apply(target, thisArgument, args);
282
+ const jsArgs = args.map((arg) => fromJSAbiValue(arg));
283
+ return toJSAbiValue(Reflect.apply(fromJSAbiValue(target), fromJSAbiValue(thisArgument), jsArgs));
246
284
  }),
247
285
  reflectConstruct: function (target, args) {
248
286
  throw new Error("Function not implemented.");
@@ -251,7 +289,7 @@ export class RubyVM {
251
289
  throw new Error("Function not implemented.");
252
290
  },
253
291
  reflectGet: wrapTry((target, propertyKey) => {
254
- return target[propertyKey];
292
+ return toJSAbiValue(fromJSAbiValue(target)[propertyKey]);
255
293
  }),
256
294
  reflectGetOwnPropertyDescriptor: function (target, propertyKey) {
257
295
  throw new Error("Function not implemented.");
@@ -272,13 +310,11 @@ export class RubyVM {
272
310
  throw new Error("Function not implemented.");
273
311
  },
274
312
  reflectSet: wrapTry((target, propertyKey, value) => {
275
- return Reflect.set(target, propertyKey, value);
313
+ return toJSAbiValue(Reflect.set(fromJSAbiValue(target), propertyKey, fromJSAbiValue(value)));
276
314
  }),
277
315
  reflectSetPrototypeOf: function (target, prototype) {
278
316
  throw new Error("Function not implemented.");
279
317
  },
280
- }), (name) => {
281
- return this.instance.exports[name];
282
318
  });
283
319
  }
284
320
  /**
@@ -611,7 +647,12 @@ function wrapRbOperation(vm, body) {
611
647
  }
612
648
  // All JS exceptions triggered by Ruby code are translated to Ruby exceptions,
613
649
  // so non-RbError exceptions are unexpected.
614
- vm.guest.rbVmBugreport();
650
+ try {
651
+ vm.guest.rbVmBugreport();
652
+ }
653
+ catch (e) {
654
+ console.error("Tried to report internal Ruby VM state but failed: ", e);
655
+ }
615
656
  if (e instanceof WebAssembly.RuntimeError && e.message === "unreachable") {
616
657
  const error = new RbError(`Something went wrong in Ruby VM: ${e}`);
617
658
  error.stack = e.stack;