Skip to content

Commit

Permalink
Showing 2 changed files with 27 additions and 0 deletions.
10 changes: 10 additions & 0 deletions core/src/main/java/org/jruby/RubyObjectSpace.java
Original file line number Diff line number Diff line change
@@ -151,6 +151,16 @@ public Object apply(IRubyObject arg1) {
for (IRubyObject arg : modules) {
block.yield(context, arg);
}
} else if (args[0].getClass() == MetaClass.class) {
// each_object(Cls.singleton_class) is basically a walk of Cls and all descendants of Cls.
// In other words, this is walking all instances of Cls's singleton class and its subclasses.
IRubyObject attached = ((MetaClass)args[0]).getAttached();
block.yield(context, attached);
if (attached instanceof RubyClass) {
for (RubyClass child : ((RubyClass)attached).subclasses(true)) {
block.yield(context, child);
}
}
} else {
if (!runtime.isObjectSpaceEnabled()) {
throw runtime.newRuntimeError("ObjectSpace is disabled; each_object will only work with Class, pass -X+O to enable");
17 changes: 17 additions & 0 deletions test/jruby/test_objectspace.rb
Original file line number Diff line number Diff line change
@@ -93,4 +93,21 @@ def test_finalization
assert_equal "finalizing #{results[0]}", results[1]
end
end

# See rails/rails#22376.
def test_each_object_singleton_class
# disable objectspace; we want this to always work
old_objectspace = JRuby.objectspace
JRuby.objectspace = false

a = Class.new
b = Class.new(a)
c = Class.new(a)
d = Class.new(b)

classes = ObjectSpace.each_object(a.singleton_class).to_a
assert_equal(classes.sort_by(&:name), [a, b, c, d])
ensure
JRuby.objectspace = old_objectspace
end
end

8 comments on commit d5ad593

@eregon
Copy link
Member

@eregon eregon commented on d5ad593 Nov 24, 2015

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would be quite interesting to have this test a RubySpec as well 😃

Sorry, something went wrong.

@headius
Copy link
Member Author

@headius headius commented on d5ad593 Nov 24, 2015 via email

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, something went wrong.

@chrisseaton
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I often have this dilemma - a spec makes sense for Truffle, as for example it exercises int and long code paths, but no other implementation has two representations of Fixnum like that so it doesn't make sense for anyone else.

@headius
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, after thinking about this, I guess it's specific enough to have its own spec. It took me a little thinking to realize that walking all instances of the singleton class is essentially like walking the class and its descendants, so it's worth spec'ing. In impls that don't track subclasses like JRuby, it will also be a test of the class/singleton structure.

Now the bigger question is whether it's valuable to have a spec for each_object(Class) and each_object(Module). They'd be specs we can always run in JRuby proper, so that's valuable to us, but they're really just subsets of each_object(some_class) that we're able to support another way...

@headius
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Heh, well writing and expanding the spec found a bug in my impl...so yay for @eregon bugging me to write the spec :-)

@eregon
Copy link
Member

@eregon eregon commented on d5ad593 Nov 24, 2015

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Common or realistic usages are always good spec examples!
Also, they tend to test more the integration with the rest and explain more clearly one possible intent for the method.

@headius
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, they tend to test more the integration with the rest

This was always one of my concerns about RubySpec...it isolates behaviors too much when interactions are just as important. So yes, good call again on having a spec.

@headius
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.