diff --git a/ext/objspace/objspace_dump.c b/ext/objspace/objspace_dump.c index 544d11e254..c3619a9656 100644 --- a/ext/objspace/objspace_dump.c +++ b/ext/objspace/objspace_dump.c @@ -419,14 +419,37 @@ dump_object(VALUE obj, struct dump_config *dc) dump_append(dc, ", \"embedded\":true"); break; + case T_ICLASS: + if (rb_class_get_superclass(obj)) { + dump_append(dc, ", \"superclass\":"); + dump_append_ref(dc, rb_class_get_superclass(obj)); + } + break; + case T_CLASS: case T_MODULE: + if (rb_class_get_superclass(obj)) { + dump_append(dc, ", \"superclass\":"); + dump_append_ref(dc, rb_class_get_superclass(obj)); + } + if (dc->cur_obj_klass) { VALUE mod_name = rb_mod_name(obj); if (!NIL_P(mod_name)) { dump_append(dc, ", \"name\":\""); dump_append(dc, RSTRING_PTR(mod_name)); dump_append(dc, "\""); + } else { + VALUE real_mod_name = rb_mod_name(rb_class_real(obj)); + if (RTEST(real_mod_name)) { + dump_append(dc, ", \"real_class_name\":\""); + dump_append(dc, RSTRING_PTR(real_mod_name)); + dump_append(dc, "\""); + } + } + + if (FL_TEST(obj, FL_SINGLETON)) { + dump_append(dc, ", \"singleton\":true"); } } break; diff --git a/test/objspace/test_objspace.rb b/test/objspace/test_objspace.rb index 6b956e6d14..841a1e7c2a 100644 --- a/test/objspace/test_objspace.rb +++ b/test/objspace/test_objspace.rb @@ -299,6 +299,21 @@ class TestObjSpace < Test::Unit::TestCase assert_equal('{"type":"SYMBOL", "value":"foo"}', ObjectSpace.dump(:foo)) end + def test_dump_singleton_class + assert_include(ObjectSpace.dump(Object), '"name":"Object"') + assert_include(ObjectSpace.dump(Kernel), '"name":"Kernel"') + assert_include(ObjectSpace.dump(Object.new.singleton_class), '"real_class_name":"Object"') + + singleton = Object.new.singleton_class + singleton_dump = ObjectSpace.dump(singleton) + assert_include(singleton_dump, '"singleton":true') + if defined?(JSON) + assert_equal(Object, singleton.superclass) + superclass_address = JSON.parse(ObjectSpace.dump(Object)).fetch('address') + assert_equal(superclass_address, JSON.parse(singleton_dump).fetch('superclass')) + end + end + def test_dump_special_floats assert_match(/"value":"NaN"/, ObjectSpace.dump(Float::NAN)) assert_match(/"value":"Inf"/, ObjectSpace.dump(Float::INFINITY))