diff options
| author | KOBAYASHI Shuji <[email protected]> | 2019-06-30 14:46:38 +0900 |
|---|---|---|
| committer | KOBAYASHI Shuji <[email protected]> | 2019-06-30 15:06:39 +0900 |
| commit | 97c9e6b00032cd8a7132b43911c05e44732a4c56 (patch) | |
| tree | 6b4099c5c7a8e6b0b7bc542d66ca601c682face6 | |
| parent | cf6972408335a69f2f6cc007f74c6afd316d0d96 (diff) | |
| download | mruby-97c9e6b00032cd8a7132b43911c05e44732a4c56.tar.gz mruby-97c9e6b00032cd8a7132b43911c05e44732a4c56.zip | |
Fix `include`, `prepend` and `extend` to frozen object
| -rw-r--r-- | src/class.c | 5 | ||||
| -rw-r--r-- | test/t/kernel.rb | 3 | ||||
| -rw-r--r-- | test/t/module.rb | 27 |
3 files changed, 33 insertions, 2 deletions
diff --git a/src/class.c b/src/class.c index 373f2aec7..1064870a8 100644 --- a/src/class.c +++ b/src/class.c @@ -1070,8 +1070,8 @@ include_module_at(mrb_state *mrb, struct RClass *c, struct RClass *ins_pos, stru MRB_API void mrb_include_module(mrb_state *mrb, struct RClass *c, struct RClass *m) { - int changed = include_module_at(mrb, c, find_origin(c), m, 1); - if (changed < 0) { + mrb_check_frozen(mrb, c); + if (include_module_at(mrb, c, find_origin(c), m, 1) < 0) { mrb_raise(mrb, E_ARGUMENT_ERROR, "cyclic include detected"); } } @@ -1082,6 +1082,7 @@ mrb_prepend_module(mrb_state *mrb, struct RClass *c, struct RClass *m) struct RClass *origin; int changed = 0; + mrb_check_frozen(mrb, c); if (!(c->flags & MRB_FL_CLASS_IS_PREPENDED)) { origin = (struct RClass*)mrb_obj_alloc(mrb, MRB_TT_ICLASS, c); origin->flags |= MRB_FL_CLASS_IS_ORIGIN | MRB_FL_CLASS_IS_INHERITED; diff --git a/test/t/kernel.rb b/test/t/kernel.rb index 1e48069f2..ecfb863a8 100644 --- a/test/t/kernel.rb +++ b/test/t/kernel.rb @@ -240,6 +240,9 @@ assert('Kernel#extend', '15.3.1.3.13') do assert_true a.respond_to?(:test_method) assert_false b.respond_to?(:test_method) + + assert_raise(FrozenError) { Object.new.freeze.extend(Test4ExtendModule) } + assert_raise(FrozenError, TypeError) { :sym.extend(Test4ExtendModule) } end assert('Kernel#extend works on toplevel', '15.3.1.3.13') do diff --git a/test/t/module.rb b/test/t/module.rb index 571f4759d..7f869bf1f 100644 --- a/test/t/module.rb +++ b/test/t/module.rb @@ -59,6 +59,7 @@ assert('Module#append_features', '15.2.2.4.10') do end assert_equal Test4AppendFeatures2, Test4AppendFeatures2.const_get(:Const4AppendFeatures2) + assert_raise(FrozenError) { Module.new.append_features Class.new.freeze } end assert('Module#attr NameError') do @@ -275,6 +276,18 @@ assert('Module#const_missing', '15.2.2.4.22') do assert_equal 42, Test4ConstMissing.const_get(:ConstDoesntExist) end +assert('Module#extend_object', '15.2.2.4.25') do + cls = Class.new + mod = Module.new { def foo; end } + a = cls.new + b = cls.new + mod.extend_object(b) + assert_false a.respond_to?(:foo) + assert_true b.respond_to?(:foo) + assert_raise(FrozenError) { mod.extend_object(cls.new.freeze) } + assert_raise(FrozenError, TypeError) { mod.extend_object(1) } +end + assert('Module#include', '15.2.2.4.27') do module Test4Include Const4Include = 42 @@ -288,6 +301,7 @@ assert('Module#include', '15.2.2.4.27') do assert_equal 42, Test4Include2.const_get(:Const4Include) assert_equal Test4Include2, Test4Include2.include_result + assert_raise(FrozenError) { Module.new.freeze.include Test4Include } end assert('Module#include?', '15.2.2.4.28') do @@ -398,6 +412,15 @@ assert('Module#define_method') do end end +assert 'Module#prepend_features' do + mod = Module.new { def m; :mod end } + cls = Class.new { def m; :cls end } + assert_equal :cls, cls.new.m + mod.prepend_features(cls) + assert_equal :mod, cls.new.m + assert_raise(FrozenError) { Module.new.prepend_features(Class.new.freeze) } +end + # @!group prepend assert('Module#prepend') do module M0 @@ -632,6 +655,10 @@ end # end # end; #end + + assert 'Module#prepend to frozen class' do + assert_raise(FrozenError) { Class.new.freeze.prepend Module.new } + end # @!endgroup prepend assert('Module#to_s') do |
