Commit c900fff9 authored by Yukihiro "Matz" Matsumoto's avatar Yukihiro "Matz" Matsumoto Committed by GitHub

Merge pull request #3623 from take-cheeze/struct_freeze

Support `freeze` method in `Struct`.
parents c73da29a da5b7fa7
...@@ -84,6 +84,16 @@ mrb_struct_s_members_m(mrb_state *mrb, mrb_value klass) ...@@ -84,6 +84,16 @@ mrb_struct_s_members_m(mrb_state *mrb, mrb_value klass)
return ary; return ary;
} }
static void
mrb_struct_modify(mrb_state *mrb, mrb_value strct)
{
if (MRB_FROZEN_P(mrb_basic_ptr(strct))) {
mrb_raise(mrb, E_RUNTIME_ERROR, "can't modify frozen struct");
}
mrb_write_barrier(mrb, mrb_basic_ptr(strct));
}
/* 15.2.18.4.6 */ /* 15.2.18.4.6 */
/* /*
* call-seq: * call-seq:
...@@ -448,8 +458,8 @@ mrb_struct_aset_sym(mrb_state *mrb, mrb_value s, mrb_sym id, mrb_value val) ...@@ -448,8 +458,8 @@ mrb_struct_aset_sym(mrb_state *mrb, mrb_value s, mrb_sym id, mrb_value val)
ptr_members = RARRAY_PTR(members); ptr_members = RARRAY_PTR(members);
for (i=0; i<len; i++) { for (i=0; i<len; i++) {
if (mrb_symbol(ptr_members[i]) == id) { if (mrb_symbol(ptr_members[i]) == id) {
mrb_struct_modify(mrb, s);
ptr[i] = val; ptr[i] = val;
mrb_write_barrier(mrb, (struct RBasic*)mrb_ptr(s));
return val; return val;
} }
} }
...@@ -512,7 +522,7 @@ mrb_struct_aset(mrb_state *mrb, mrb_value s) ...@@ -512,7 +522,7 @@ mrb_struct_aset(mrb_state *mrb, mrb_value s)
"offset %S too large for struct(size:%S)", "offset %S too large for struct(size:%S)",
mrb_fixnum_value(i), mrb_fixnum_value(RSTRUCT_LEN(s))); mrb_fixnum_value(i), mrb_fixnum_value(RSTRUCT_LEN(s)));
} }
mrb_write_barrier(mrb, (struct RBasic*)mrb_ptr(s)); mrb_struct_modify(mrb, s);
return RSTRUCT_PTR(s)[i] = val; return RSTRUCT_PTR(s)[i] = val;
} }
......
...@@ -197,3 +197,16 @@ assert("Struct.new generates subclass of Struct") do ...@@ -197,3 +197,16 @@ assert("Struct.new generates subclass of Struct") do
Struct = original_struct Struct = original_struct
end end
end end
assert 'Struct#freeze' do
c = Struct.new :m
o = c.new
o.m = :test
assert_equal :test, o.m
o.freeze
assert_raise(RuntimeError) { o.m = :modify }
assert_raise(RuntimeError) { o[:m] = :modify }
assert_equal :test, o.m
end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment