Skip to content

Commit 3b30896

Browse files
committed
Add C API function rb_proc_call_with_block_kw
1 parent b1249fd commit 3b30896

File tree

3 files changed

+35
-0
lines changed

3 files changed

+35
-0
lines changed

spec/ruby/optional/capi/ext/proc_spec.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,10 @@ VALUE proc_spec_rb_proc_call_with_block(VALUE self, VALUE prc, VALUE args, VALUE
8484
return rb_proc_call_with_block(prc, RARRAY_LENINT(args), RARRAY_PTR(args), block);
8585
}
8686

87+
static VALUE proc_spec_rb_proc_call_with_block_kw(VALUE self, VALUE prc, VALUE args, VALUE block) {
88+
return rb_proc_call_with_block_kw(prc, RARRAY_LENINT(args), RARRAY_PTR(args), block, RB_PASS_KEYWORDS);
89+
}
90+
8791
VALUE proc_spec_rb_obj_is_proc(VALUE self, VALUE prc) {
8892
return rb_obj_is_proc(prc);
8993
}
@@ -133,6 +137,7 @@ void Init_proc_spec(void) {
133137
rb_define_method(cls, "rb_proc_call", proc_spec_rb_proc_call, 2);
134138
rb_define_method(cls, "rb_proc_call_kw", proc_spec_rb_proc_call_kw, 2);
135139
rb_define_method(cls, "rb_proc_call_with_block", proc_spec_rb_proc_call_with_block, 3);
140+
rb_define_method(cls, "rb_proc_call_with_block_kw", proc_spec_rb_proc_call_with_block_kw, 3);
136141
rb_define_method(cls, "rb_Proc_new", proc_spec_rb_Proc_new, 1);
137142
rb_define_method(cls, "rb_obj_is_proc", proc_spec_rb_obj_is_proc, 1);
138143
}

spec/ruby/optional/capi/proc_spec.rb

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,32 @@
113113
end
114114
end
115115

116+
describe "rb_proc_call_with_block_kw" do
117+
it "passes keyword arguments and a block to the proc" do
118+
prc = proc { |*args, **kw, &block| [args, kw, block.call(42)] }
119+
block = proc { |n| n }
120+
121+
@p.rb_proc_call_with_block_kw(prc, [{}], block).should == [[], {}, 42]
122+
@p.rb_proc_call_with_block_kw(prc, [{a: 1}], block).should == [[], {a: 1}, 42]
123+
@p.rb_proc_call_with_block_kw(prc, [{b: 2}, {a: 1}], block).should == [[{b: 2}], {a: 1}, 42]
124+
@p.rb_proc_call_with_block_kw(prc, [{b: 2}, {}], block).should == [[{b: 2}], {}, 42]
125+
end
126+
127+
it "raises TypeError if the last argument is not a Hash" do
128+
prc = proc { |*args, **kwargs, &block| [args, kw, block.call(42)] }
129+
130+
-> {
131+
@p.rb_proc_call_with_block_kw(prc, [42], proc {})
132+
}.should raise_error(TypeError, 'no implicit conversion of Integer into Hash')
133+
end
134+
135+
it "passes keyword arguments to the proc when a block is nil" do
136+
prc = proc { |*args, **kw| [args, kw] }
137+
138+
@p.rb_proc_call_with_block_kw(prc, [{}], nil).should == [[], {}]
139+
end
140+
end
141+
116142
describe "rb_obj_is_proc" do
117143
it "returns true for Proc" do
118144
prc = Proc.new {|a,b| a * b }

src/main/c/cext/proc.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@ VALUE rb_proc_call_with_block(VALUE recv, int argc, const VALUE *argv, VALUE pro
2727
return rb_funcall_with_block(recv, rb_intern("call"), argc, argv, proc);
2828
}
2929

30+
VALUE rb_proc_call_with_block_kw(VALUE recv, int argc, const VALUE *argv, VALUE proc, int kw_splat) {
31+
return rb_funcall_with_block_kw(recv, rb_intern("call"), argc, argv, proc, kw_splat);
32+
}
33+
3034
int rb_proc_arity(VALUE self) {
3135
return polyglot_as_i32(RUBY_INVOKE_NO_WRAP(self, "arity"));
3236
}

0 commit comments

Comments
 (0)