Do not destruct rest arguments for __send__
Formerly, `__send__(*args)` modified `args` with `Array#shift`.
This bug affects optcarrot.
This changeset avoids the array destruction by using
`args = args[1, len-1]`.
MODIFY
include/mruby/array.h
include/mruby/array.h
@@ -292,6 +292,9 @@ MRB_API mrb_value mrb_ary_join(mrb_state *mrb, mrb_value ary, mrb_value sep);
*/
MRB_API mrb_value mrb_ary_resize(mrb_state *mrb, mrb_value ary, mrb_int new_len);
+/* helper functions */
+mrb_value mrb_ary_subseq(mrb_state *mrb, mrb_value ary, mrb_int beg, mrb_int len);
+
MRB_END_DECL
#endif /* MRUBY_ARRAY_H */

MODIFY
src/array.c
src/array.c
@@ -808,6 +808,13 @@ ary_subseq(mrb_state *mrb, struct RArray *a, mrb_int beg, mrb_int len)
return mrb_obj_value(b);
}
+mrb_value
+mrb_ary_subseq(mrb_state *mrb, mrb_value ary, mrb_int beg, mrb_int len)
+{
+ struct RArray *a = mrb_ary_ptr(ary);
+ return ary_subseq(mrb, a, beg, len);
+}
+
static mrb_int
aget_index(mrb_state *mrb, mrb_value index)
{

MODIFY
src/vm.c
src/vm.c
@@ -625,7 +625,7 @@ mrb_f_send(mrb_state *mrb, mrb_value self)
ci->argc--;
}
else { /* variable length arguments */
- mrb_ary_shift(mrb, regs[0]);
+ regs[0] = mrb_ary_subseq(mrb, regs[0], 1, RARRAY_LEN(regs[0]) - 1);
}
if (MRB_METHOD_CFUNC_P(m)) {

MODIFY
test/t/kernel.rb
test/t/kernel.rb
@@ -100,6 +100,10 @@ assert('Kernel#__send__', '15.3.1.3.4') do
assert_true __send__(:respond_to?, :nil?)
# test without argument and without block
assert_equal String, __send__(:to_s).class
+
+ args = [:respond_to?, :nil?]
+ assert_true __send__(*args)
+ assert_equal [:respond_to?, :nil?], args
end
assert('Kernel#block_given?', '15.3.1.3.6') do

Do not destruct rest arguments for __send__

Formerly, `__send__(*args)` modified `args` with `Array#shift`.
This bug affects optcarrot.

This changeset avoids the array destruction by using
`args = args[1, len-1]`.