diff options
| -rw-r--r-- | mrbgems/mruby-compiler/core/codegen.c | 6 | ||||
| -rw-r--r-- | mrbgems/mruby-object-ext/test/object.rb | 28 | ||||
| -rw-r--r-- | mrbgems/mruby-string-ext/src/string.c | 3 | ||||
| -rw-r--r-- | mrbgems/mruby-string-ext/test/string.rb | 12 | ||||
| -rw-r--r-- | mrbgems/mruby-struct/src/struct.c | 2 | ||||
| -rw-r--r-- | mrbgems/mruby-struct/test/struct.rb | 21 | ||||
| -rw-r--r-- | src/string.c | 4 | ||||
| -rw-r--r-- | src/vm.c | 14 | ||||
| -rw-r--r-- | test/t/codegen.rb | 11 | ||||
| -rw-r--r-- | test/t/string.rb | 14 |
10 files changed, 105 insertions, 10 deletions
diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c index 0c84dd558..39d62348a 100644 --- a/mrbgems/mruby-compiler/core/codegen.c +++ b/mrbgems/mruby-compiler/core/codegen.c @@ -1798,8 +1798,10 @@ codegen(codegen_scope *s, node *tree, int val) int pos; pop(); - if (val && vsp >= 0) { - genop(s, MKOP_AB(OP_MOVE, vsp, cursp())); + if (val) { + if (vsp >= 0) { + genop(s, MKOP_AB(OP_MOVE, vsp, cursp())); + } pos = genop(s, MKOP_AsBx(name[0]=='|'?OP_JMPIF:OP_JMPNOT, cursp(), 0)); } else { diff --git a/mrbgems/mruby-object-ext/test/object.rb b/mrbgems/mruby-object-ext/test/object.rb index fe56f1ec5..f0742f8ce 100644 --- a/mrbgems/mruby-object-ext/test/object.rb +++ b/mrbgems/mruby-object-ext/test/object.rb @@ -23,3 +23,31 @@ assert('Object#tap') do ], ret assert_equal(:tap_ok, Class.new {def m; tap{return :tap_ok}; end}.new.m) end + +assert('instance_exec on primitives with class and module definition') do + begin + class A + 1.instance_exec do + class B + end + end + end + + assert_kind_of Class, A::B + ensure + Object.remove_const :A + end + + begin + class A + 1.instance_exec do + module B + end + end + end + + assert_kind_of Module, A::B + ensure + Object.remove_const :A + end +end diff --git a/mrbgems/mruby-string-ext/src/string.c b/mrbgems/mruby-string-ext/src/string.c index 122ee5454..dfac907ec 100644 --- a/mrbgems/mruby-string-ext/src/string.c +++ b/mrbgems/mruby-string-ext/src/string.c @@ -23,10 +23,11 @@ static mrb_value mrb_str_setbyte(mrb_state *mrb, mrb_value str) { mrb_int pos, byte; - long len = RSTRING_LEN(str); + long len; mrb_get_args(mrb, "ii", &pos, &byte); + len = RSTRING_LEN(str); if (pos < -len || len <= pos) mrb_raisef(mrb, E_INDEX_ERROR, "index %S is out of array", mrb_fixnum_value(pos)); if (pos < 0) diff --git a/mrbgems/mruby-string-ext/test/string.rb b/mrbgems/mruby-string-ext/test/string.rb index a5d55a7ee..228a236af 100644 --- a/mrbgems/mruby-string-ext/test/string.rb +++ b/mrbgems/mruby-string-ext/test/string.rb @@ -30,6 +30,18 @@ assert('String#setbyte') do assert_equal("Hello", str1) end +assert("String#setbyte raises IndexError if arg conversion resizes String") do + $s = "01234\n" + class Tmp + def to_i + $s.chomp! '' + 95 + end + end + tmp = Tmp.new + assert_raise(IndexError) { $s.setbyte(5, tmp) } +end + assert('String#byteslice') do str1 = "hello" assert_equal("e", str1.byteslice(1)) diff --git a/mrbgems/mruby-struct/src/struct.c b/mrbgems/mruby-struct/src/struct.c index 0ccb7f4cb..8c8f54f27 100644 --- a/mrbgems/mruby-struct/src/struct.c +++ b/mrbgems/mruby-struct/src/struct.c @@ -203,7 +203,7 @@ make_struct(mrb_state *mrb, mrb_value name, mrb_value members, struct RClass * k } if (mrb_const_defined_at(mrb, mrb_obj_value(klass), id)) { mrb_warn(mrb, "redefining constant Struct::%S", name); - /* ?rb_mod_remove_const(klass, mrb_sym2name(mrb, id)); */ + mrb_const_remove(mrb, mrb_obj_value(klass), id); } c = mrb_define_class_under(mrb, klass, RSTRING_PTR(name), klass); } diff --git a/mrbgems/mruby-struct/test/struct.rb b/mrbgems/mruby-struct/test/struct.rb index 02ecf69e4..bbfe18cb2 100644 --- a/mrbgems/mruby-struct/test/struct.rb +++ b/mrbgems/mruby-struct/test/struct.rb @@ -158,3 +158,24 @@ assert("Struct#dig") do assert_equal 1, a.dig(:purple, :red) assert_equal 1, a.dig(1, 0) end + +assert("Struct.new removes existing constant") do + begin + assert_not_equal Struct.new("Test", :a), Struct.new("Test", :a, :b) + ensure + Struct.remove_const :Test + end +end + +assert("Struct#initialize_copy requires struct to be the same type") do + begin + Struct.new("Test", :a) + a = Struct::Test.new("a") + Struct.new("Test", :a, :b) + assert_raise(TypeError) do + a.initialize_copy(Struct::Test.new("a", "b")) + end + ensure + Struct.remove_const :Test + end +end diff --git a/src/string.c b/src/string.c index 5e490bf03..f47294291 100644 --- a/src/string.c +++ b/src/string.c @@ -1235,11 +1235,13 @@ mrb_str_chomp_bang(mrb_state *mrb, mrb_value str) char *p, *pp; mrb_int rslen; mrb_int len; + mrb_int argc; struct RString *s = mrb_str_ptr(str); mrb_str_modify(mrb, s); + argc = mrb_get_args(mrb, "|S", &rs); len = RSTR_LEN(s); - if (mrb_get_args(mrb, "|S", &rs) == 0) { + if (argc == 0) { if (len == 0) return mrb_nil_value(); smart_chomp: if (RSTR_PTR(s)[len-1] == '\n') { @@ -2261,7 +2261,7 @@ RETRY_TRY_BLOCK: CASE(OP_CLASS) { /* A B R(A) := newclass(R(A),Syms(B),R(A+1)) */ - struct RClass *c = 0; + struct RClass *c = 0, *baseclass; int a = GETARG_A(i); mrb_value base, super; mrb_sym id = syms[GETARG_B(i)]; @@ -2269,7 +2269,10 @@ RETRY_TRY_BLOCK: base = regs[a]; super = regs[a+1]; if (mrb_nil_p(base)) { - base = mrb_obj_value(mrb->c->ci->target_class); + baseclass = mrb->c->ci->proc->target_class; + if (!baseclass) baseclass = mrb->c->ci->target_class; + + base = mrb_obj_value(baseclass); } c = mrb_vm_define_class(mrb, base, super, id); regs[a] = mrb_obj_value(c); @@ -2279,14 +2282,17 @@ RETRY_TRY_BLOCK: CASE(OP_MODULE) { /* A B R(A) := newmodule(R(A),Syms(B)) */ - struct RClass *c = 0; + struct RClass *c = 0, *baseclass; int a = GETARG_A(i); mrb_value base; mrb_sym id = syms[GETARG_B(i)]; base = regs[a]; if (mrb_nil_p(base)) { - base = mrb_obj_value(mrb->c->ci->target_class); + baseclass = mrb->c->ci->proc->target_class; + if (!baseclass) baseclass = mrb->c->ci->target_class; + + base = mrb_obj_value(baseclass); } c = mrb_vm_define_module(mrb, base, id); regs[a] = mrb_obj_value(c); diff --git a/test/t/codegen.rb b/test/t/codegen.rb new file mode 100644 index 000000000..f910d37fb --- /dev/null +++ b/test/t/codegen.rb @@ -0,0 +1,11 @@ +## +# Codegen tests + +assert('peephole optimization does not eliminate move whose result is reused') do + assert_raise LocalJumpError do + def method + yield + end + method(&a &&= 0) + end +end diff --git a/test/t/string.rb b/test/t/string.rb index e67389b5c..80fcbe6fa 100644 --- a/test/t/string.rb +++ b/test/t/string.rb @@ -251,6 +251,19 @@ assert('String#chomp!', '15.2.10.5.10') do assert_equal 'abc', e end +assert('String#chomp! uses the correct length') do + class A + def to_str + $s.replace("AA") + "A" + end + end + + $s = "AAA" + $s.chomp!(A.new) + assert_equal $s, "A" +end + assert('String#chop', '15.2.10.5.11') do a = ''.chop b = 'abc'.chop @@ -683,4 +696,3 @@ assert('String#freeze') do assert_raise(RuntimeError) { str.upcase! } end - |
