From 8fa3995a1a02e9014ce01351e0260bec20ceefd7 Mon Sep 17 00:00:00 2001 From: KOBAYASHI Shuji Date: Thu, 25 Apr 2019 19:48:40 +0900 Subject: Singleton class of frozen object should be frozen Before this patch: p (class << Object.new.freeze; self end).frozen? #=> false sc = class << (o=Object.new); self end; o.freeze; p sc.frozen? #=> false After this patch / Ruby: p (class << Object.new.freeze; self end).frozen? #=> true sc = class << (o=Object.new); self end; o.freeze; p sc.frozen? #=> true --- mrbgems/mruby-metaprog/test/metaprog.rb | 16 ++++++++++++++++ src/class.c | 1 + src/kernel.c | 1 + test/t/class.rb | 7 +++++++ 4 files changed, 25 insertions(+) diff --git a/mrbgems/mruby-metaprog/test/metaprog.rb b/mrbgems/mruby-metaprog/test/metaprog.rb index 0abeb90a6..3aa1d8732 100644 --- a/mrbgems/mruby-metaprog/test/metaprog.rb +++ b/mrbgems/mruby-metaprog/test/metaprog.rb @@ -122,6 +122,22 @@ assert('Kernel#define_singleton_method') do assert_equal :singleton_method_ok, o.test_method end +assert('Kernel#singleton_class') do + o1 = Object.new + assert_same(o1.singleton_class, class << o1; self end) + + o2 = Object.new + sc2 = class << o2; self end + assert_same(o2.singleton_class, sc2) + + o3 = Object.new + sc3 = o3.singleton_class + o3.freeze + assert_predicate(sc3, :frozen?) + + assert_predicate(Object.new.freeze.singleton_class, :frozen?) +end + def labeled_module(name, &block) Module.new do (class <flags |= o->flags & MRB_FL_OBJ_IS_FROZEN; } static mrb_value diff --git a/src/kernel.c b/src/kernel.c index d9a1d36ce..45bca7558 100644 --- a/src/kernel.c +++ b/src/kernel.c @@ -438,6 +438,7 @@ mrb_obj_freeze(mrb_state *mrb, mrb_value self) struct RBasic *b = mrb_basic_ptr(self); if (!MRB_FROZEN_P(b)) { MRB_SET_FROZEN_FLAG(b); + if (b->c->tt == MRB_TT_SCLASS) MRB_SET_FROZEN_FLAG(b->c); } } return self; diff --git a/test/t/class.rb b/test/t/class.rb index 0c95677fc..e2839111c 100644 --- a/test/t/class.rb +++ b/test/t/class.rb @@ -356,6 +356,13 @@ assert('singleton tests') do end end end if Object.const_defined?(:Float) + + o = Object.new + sc = class << o; self end + o.freeze + assert_predicate(sc, :frozen?) + + assert_predicate(class << Object.new.freeze; self end, :frozen?) end assert('clone Class') do -- cgit v1.2.3