Check method existence for Enumerators; fix #3920

The issue #3920 was fixed but the fundamental flaw of lack of stack
depth check along with fibers still remains, even though it's not
easy to cause the issue.  Use `MRB_GC_FIXED_ARENA` to avoid the issue
for workaround.

After this patch, `obj.to_enum` raises `ArgumentError` if the object
does not respond to the enumerating method. This is incompatible to
CRuby but I think this behavior is better and CRuby should be updated
to behave like this.
parent 31a961ac
......@@ -44,7 +44,7 @@ class Enumerator
def to_enum(meth=:each, *args, &block)
unless self.respond_to?(meth)
raise NoMethodError, "undefined method #{meth}"
raise ArgumentError, "undefined method #{meth}"
end
lz = Lazy.new(self, &block)
lz.obj = self
......
......@@ -614,6 +614,9 @@ module Kernel
# enum.first(4) # => [1, 1, 1, 2]
#
def to_enum(meth=:each, *args)
unless self.respond_to?(meth)
raise ArgumentError, "undefined method #{meth}"
end
Enumerator.new self, meth, *args
end
alias enum_for to_enum
......
......@@ -22,8 +22,7 @@ assert 'Enumerator.new' do
assert_equal [1,2,3], Enumerator.new(@obj, :foo, 1,2,3).to_a
assert_equal [1,2,3], Enumerator.new { |y| i = 0; loop { y << (i += 1) } }.take(3)
assert_raise(ArgumentError) { Enumerator.new }
enum = @obj.to_enum
assert_raise(NoMethodError) { enum.each {} }
assert_raise(ArgumentError) { @obj.to_enum }
# examples
fib = Enumerator.new do |y|
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment