diff options
author | Jeremy Evans <code@jeremyevans.net> | 2023-12-07 12:16:09 -0800 |
---|---|---|
committer | Jeremy Evans <code@jeremyevans.net> | 2023-12-09 13:15:47 -0800 |
commit | f64357540eabad0f1bfaa6be60710d153325b064 (patch) | |
tree | ee39e6ae564d823a53402daaf3c79606e41ad3a7 | |
parent | a950f230788d51e13d16596e37cb77e4cc6e2311 (diff) |
Ensure super(**kw, &block) calls kw.to_hash before block.to_proc
Similar as previous commit, but handles the super case with
explicit arguments.
-rw-r--r-- | compile.c | 3 | ||||
-rw-r--r-- | test/ruby/test_call.rb | 20 |
2 files changed, 23 insertions, 0 deletions
@@ -9229,6 +9229,9 @@ compile_super(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, i VALUE vargc = setup_args(iseq, args, RNODE_SUPER(node)->nd_args, &flag, &keywords); CHECK(!NIL_P(vargc)); argc = FIX2INT(vargc); + if ((flag & VM_CALL_ARGS_BLOCKARG) && (flag & VM_CALL_KW_SPLAT) && !(flag & VM_CALL_KW_SPLAT_MUT)) { + ADD_INSN(args, node, splatkw); + } } else { /* NODE_ZSUPER */ diff --git a/test/ruby/test_call.rb b/test/ruby/test_call.rb index d009691fd0..92c5e604b5 100644 --- a/test/ruby/test_call.rb +++ b/test/ruby/test_call.rb @@ -164,6 +164,26 @@ class TestCall < Test::Unit::TestCase assert_equal([:to_a, :to_hash, :to_proc], ary) end + def test_kwsplat_block_order_super + def self.t(splat) + o = Object.new + ary = [] + o.define_singleton_method(:to_a) {ary << :to_a; []} + o.define_singleton_method(:to_hash) {ary << :to_hash; {}} + o.define_singleton_method(:to_proc) {ary << :to_proc; lambda{}} + if splat + super(*o, **o, &o) + else + super(**o, &o) + end + ary + end + extend Module.new{def t(...) end} + + assert_equal([:to_hash, :to_proc], t(false)) + assert_equal([:to_a, :to_hash, :to_proc], t(true)) + end + OVER_STACK_LEN = (ENV['RUBY_OVER_STACK_LEN'] || 150).to_i # Greater than VM_ARGC_STACK_MAX OVER_STACK_ARGV = OVER_STACK_LEN.times.to_a.freeze |