Skip to content

Commit

Permalink
Fix coercion of arrays in Kernel#Array and Array#product.
Browse files Browse the repository at this point in the history
Fixes #1961.
Fixes #1962.
  • Loading branch information
headius authored and enebo committed Sep 25, 2014
1 parent 51ed1b2 commit aafb40b
Show file tree
Hide file tree
Showing 4 changed files with 34 additions and 13 deletions.
2 changes: 1 addition & 1 deletion core/src/main/java/org/jruby/RubyArray.java
Expand Up @@ -3542,7 +3542,7 @@ public IRubyObject product19(ThreadContext context, IRubyObject[] args, Block bl
int counters[] = new int[n];

arrays[0] = this;
for (int i = 1; i < n; i++) arrays[i] = args[i - 1].convertToArray();
for (int i = 1; i < n; i++) arrays[i] = TypeConverter.to_ary(context, args[i - 1]);

int resultLen = 1;
for (int i = 0; i < n; i++) {
Expand Down
10 changes: 8 additions & 2 deletions core/src/main/java/org/jruby/RubyKernel.java
Expand Up @@ -375,11 +375,17 @@ public static IRubyObject abort(ThreadContext context, IRubyObject recv, IRubyOb
return runtime.getNil(); // not reached
}

@JRubyMethod(name = "Array", required = 1, module = true, visibility = PRIVATE)
public static IRubyObject new_array(ThreadContext context, IRubyObject recv, IRubyObject object) {
@JRubyMethod(name = "Array", required = 1, module = true, visibility = PRIVATE, compat = RUBY1_8)
public static IRubyObject new_array18(ThreadContext context, IRubyObject recv, IRubyObject object) {
return Helpers.asArray18(context, object);
}

// MRI: rb_f_array
@JRubyMethod(name = "Array", required = 1, module = true, visibility = PRIVATE, compat = RUBY1_9)
public static IRubyObject new_array(ThreadContext context, IRubyObject recv, IRubyObject object) {
return TypeConverter.rb_Array(context, object);
}

@JRubyMethod(name = "Complex", module = true, visibility = PRIVATE, compat = RUBY1_9)
public static IRubyObject new_complex(ThreadContext context, IRubyObject recv) {
return Helpers.invoke(context, context.runtime.getComplex(), "convert");
Expand Down
11 changes: 1 addition & 10 deletions core/src/main/java/org/jruby/runtime/Helpers.java
Expand Up @@ -1852,16 +1852,7 @@ public static RubyArray asArray18(ThreadContext context, IRubyObject value) {
// mri: rb_Array
// FIXME: Replace arrayValue/asArray18 with this on 9k (currently dead -- respond_to? logic broken further down the line -- fix that first)
public static RubyArray asArray(ThreadContext context, IRubyObject value) {
RubyClass array = context.runtime.getArray();
IRubyObject tmp = TypeConverter.convertToTypeWithCheck19(value, array, "to_ary");

if (tmp.isNil()) {
tmp = TypeConverter.convertToTypeWithCheck19(value, array, "to_a");

if (tmp.isNil()) return context.runtime.newEmptyArray();
}

return (RubyArray) tmp; // converters will guarantee it is RubyArray or raise.
return TypeConverter.rb_Array(context, value);
}

public static IRubyObject aryToAry(IRubyObject value) {
Expand Down
24 changes: 24 additions & 0 deletions core/src/main/java/org/jruby/util/TypeConverter.java
Expand Up @@ -27,6 +27,7 @@
package org.jruby.util;

import org.jruby.Ruby;
import org.jruby.RubyArray;
import org.jruby.RubyBignum;
import org.jruby.RubyBoolean;
import org.jruby.RubyClass;
Expand Down Expand Up @@ -283,6 +284,11 @@ public static IRubyObject checkStringType(Ruby runtime, IRubyObject obj) {
return TypeConverter.convertToTypeWithCheck(obj, runtime.getHash(), "to_str");
}

// MRI: rb_check_array_type
public static IRubyObject checkArrayType(IRubyObject self) {
return TypeConverter.convertToTypeWithCheck19(self, self.getRuntime().getArray(), "to_ary");
}

public static IRubyObject handleUncoercibleObject(boolean raise, IRubyObject obj, RubyClass target) throws RaiseException {
if (raise) throw obj.getRuntime().newTypeError("can't convert " + typeAsString(obj) + " into " + target);

Expand Down Expand Up @@ -330,6 +336,24 @@ public static IRubyObject convertToInteger(ThreadContext context, IRubyObject va
return tmp;
}

// MRI: rb_Array
public static RubyArray rb_Array(ThreadContext context, IRubyObject val) {
IRubyObject tmp = checkArrayType(val);

if (tmp.isNil()) {
tmp = convertToTypeWithCheck19(val, context.runtime.getArray(), "to_a");
if (tmp.isNil()) {
return context.runtime.newArray(val);
}
}
return (RubyArray)tmp;
}

// MRI: to_ary
public static RubyArray to_ary(ThreadContext context, IRubyObject ary) {
return (RubyArray)convertToType19(ary, context.runtime.getArray(), "to_ary");
}

private static void raiseIntegerBaseError(ThreadContext context) {
throw context.runtime.newArgumentError("base specified for non string value");
}
Expand Down

0 comments on commit aafb40b

Please sign in to comment.