mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
Merge pull request #4544 from shuujii/fix-include-prepend-and-extend-to-frozen-object
Fix `include`, `prepend` and `extend` to frozen object
This commit is contained in:
+3
-2
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user