ruby/ruby.wasm

`RbError: SystemStackError: stack level too deep` when using `require 'json'` with `vm.evalAsync`

terrablue opened this issue · 4 comments

If I try to use require 'json' with vm.evalAsync, I get a RbError: SystemStackError: stack level too deep error.

No error if I use vm.eval.

Example code (with 3.2):

await vm.evalAsync("require 'json'");

In this case, I'm using the node_modules/@ruby/3.2-wasm-wasi/dist/ruby+stdlib.wasm file to get the JSON module.

You need some workaround to address 3.2-specific issue like below:

<html>
  <script type="module">
    import { DefaultRubyVM } from "https://cdn.jsdelivr.net/npm/@ruby/wasm-wasi@2.4.0/dist/browser/+esm";
    const response = await fetch("https://cdn.jsdelivr.net/npm/@ruby/3.2-wasm-wasi@2.4.0/dist/ruby+stdlib.wasm");
    const module = await WebAssembly.compileStreaming(response);
    const { vm } = await DefaultRubyVM(module, { env: {
      "RUBY_FIBER_MACHINE_STACK_SIZE": "8388608"
    }});

    await vm.evalAsync("require 'json'; puts :ok");
  </script>
</html>

browser.script.iife.js contains the workaround, but browser.js doesn't since it's Ruby version independent, so you need to put it manually:

main(pkg, {
env: {
// WORKAROUND(katei): setjmp consumes a LOT of stack in Ruby 3.2,
// so we extend default Fiber stack size as well as main stack
// size allocated by wasm-ld's --stack-size. 8MB is enough for
// most cases. See https://github.com/ruby/ruby.wasm/issues/273
"RUBY_FIBER_MACHINE_STACK_SIZE": "8388608"
}
})

The root problem has been fixed in the head, so the workaround is necessary only for 3.2

I see. I'm using it with NodeJS though, sorry if that was unclear. Would I pass the same options to DefaultRubyVM there too?

Alternatively I'll just switch to head.

The same option is also available for node.js

Thanks, that worked!