Permalink
Browse files

Fix JRUBY-6892: Calling #drop on an Enumerator doesn't work properly

When "drop" is called on an Enumerator, the memory locations for the members of the return value were reused.
This resulted in a wrong result that the ticket describes. We address the problem by calling dup() whenever appropriate.
  • Loading branch information...
1 parent 09fa430 commit ebd0b8eab7698076ad917d12d977ac4b7f0a92c7 @BanzaiMan BanzaiMan committed with Prathamesh Sonpatki Sep 16, 2012
Showing with 14 additions and 1 deletion.
  1. +10 −0 spec/regression/JRUBY-6892_drop_on_enumerator_oddity_spec.rb
  2. +4 −1 src/org/jruby/RubyEnumerable.java
@@ -0,0 +1,10 @@
+require 'rspec'
+
+describe "Enumerable#drop" do
+ context "when called on an Enumerator" do
+ let(:enumerator) { (1..10).to_a.each_slice(3)}
+ it "should behave as if it is called on an Enumerable" do
+ enumerator.drop(2).should == [[7,8,9],[10]]
+ end
+ end
+end
@@ -281,7 +281,10 @@ public static IRubyObject drop(ThreadContext context, IRubyObject self, IRubyObj
public IRubyObject yield(ThreadContext context, IRubyObject arg) {
synchronized (result) {
if (i == 0) {
- result.append(arg);
+ // While iterating over an RubyEnumerator, "arg"
+ // gets overwritten by the new value, leading to JRUBY-6892.
+ // So call .dup() whenever appropriate.
+ result.append(arg.isImmediate() ? arg : arg.dup());
} else {
--i;
}

0 comments on commit ebd0b8e

Please sign in to comment.