You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
In Ruby 3.4+ compiled to WebAssembly (wasm32-wasi), the block-based patterns in lib/rubygems/deprecate.rb fail at boot. Converting these methods to use class_eval <<~RUBY with def (instead of define_method) resolves the issue.
The same code works correctly in Ruby 3.3 WASM builds and in all native (non-WASM) Ruby environments.
Boot a Rails application or any code that triggers Gem::Deprecate
Which command did you run?
Boot a Rails application or any code that triggers Gem::Deprecate on Ruby 3.4+ compiled to wasm32-wasi.
What were you expecting to happen?
The application boots successfully without errors, as it does in Ruby 3.3 WASM builds and all native Ruby environments.
What actually happened?
ArgumentError: wrong number of arguments (given 0, expected 1..3)
from internal:gem_prelude:2:in 'class_eval'
from internal:gem_prelude:2:in 'module:Deprecate'
from internal:gem_prelude:2:in 'module:Gem'
from internal:gem_prelude:2:in '<main>'
We tested multiple approaches to isolate the problem. All tests used Ruby 3.4 compiled to WASM with parse.y as the parser.
No.
Approach
Result
Error
1
class_eval do...end (original)
Fail
ArgumentError: wrong number of arguments (given 0, expected 1..3)
2
class_eval {...}
Fail
Same error as No.1
3
Remove class_eval, use define_method directly
Fail
tried to create Proc object without a block
4
define_method(name) do (with parentheses)
Fail
Same error as No.3
5
class_eval <<~RUBY with define_method inside
Fail
Same error as No.3 (block not received within string eval)
6
class_eval <<~RUBY with def #{name}
Pass
No error
Key observations:
Both do...end and {} block styles fail (No.1, No.2)
define_method also cannot receive blocks (No.3, No.4, No.5)
Only the combination of string-based class_eval and def-based method definition (no blocks at all) works (No.6)
The identical class_eval do...end code in Ruby 3.3 WASM builds works without issues
Run gem env and paste the output below
Ruby: 3.4.8 / 4.0.2 (compiled to wasm32-unknown-wasip1 via ruby_wasm 2.9.0)
RubyGems: bundled (3.6.x for 3.4, 3.7.x for 4.0)
wasi_sdk: 24.0
Workaround: Convert deprecate.rb's three methods (deprecate, rubygems_deprecate, rubygems_deprecate_command) from class_eval do / define_method to class_eval <<~RUBY / def style.
This eliminates all block passing and has no effect on non-WASM environments.
Describe the problem as clearly as you can
In Ruby 3.4+ compiled to WebAssembly (wasm32-wasi), the block-based patterns in
lib/rubygems/deprecate.rbfail at boot. Converting these methods to useclass_eval <<~RUBYwithdef(instead ofdefine_method) resolves the issue.The same code works correctly in Ruby 3.3 WASM builds and in all native (non-WASM) Ruby environments.
Did you try upgrading RubyGems?
Post steps to reproduce the problem
(to avoid the separate Prism crash — see Prism parser crashes in WASM (wasm32-wasi):
pm_parser_initout-of-bounds memory access prism#4065)Gem::DeprecateWhich command did you run?
Boot a Rails application or any code that triggers
Gem::Deprecateon Ruby 3.4+ compiled to wasm32-wasi.What were you expecting to happen?
The application boots successfully without errors, as it does in Ruby 3.3 WASM builds and all native Ruby environments.
What actually happened?
We tested multiple approaches to isolate the problem. All tests used Ruby 3.4 compiled to WASM with parse.y as the parser.
class_eval do...end(original)ArgumentError: wrong number of arguments (given 0, expected 1..3)class_eval {...}class_eval, usedefine_methoddirectlytried to create Proc object without a blockdefine_method(name) do(with parentheses)class_eval <<~RUBYwithdefine_methodinsideclass_eval <<~RUBYwithdef #{name}Key observations:
do...endand{}block styles fail (No.1, No.2)define_methodalso cannot receive blocks (No.3, No.4, No.5)class_evalanddef-based method definition (no blocks at all) works (No.6)class_eval do...endcode in Ruby 3.3 WASM builds works without issuesRun
gem envand paste the output belowWorkaround: Convert
deprecate.rb's three methods (deprecate,rubygems_deprecate,rubygems_deprecate_command) fromclass_eval do / define_methodtoclass_eval <<~RUBY / defstyle.This eliminates all block passing and has no effect on non-WASM environments.
Patch file (for Ruby 4.0; minor differences for 3.4 due to method signature changes):
https://github.com/aim2bpg/rubree/blob/main/ruby_wasm_patches/fix-deprecate-class-eval-block.patch
Related:
pm_parser_initout-of-bounds memory access prism#4065 —pm_parser_initout-of-bounds memory access in WASM (must be fixed independently)