Skip to content

Commit

Permalink
Range should raise TypeError if necessary method is not defined
Browse files Browse the repository at this point in the history
For more information, please see bug #14048.
  • Loading branch information
nomadium committed Mar 27, 2018
1 parent 1b7c330 commit ec02fe1
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 2 deletions.
4 changes: 2 additions & 2 deletions core/src/main/java/org/jruby/RubyArray.java
Expand Up @@ -1484,7 +1484,7 @@ private IRubyObject arefCommon(IRubyObject arg0) {
ThreadContext context = runtime.getCurrentContext();
ArraySites sites = sites(context);

if (RubyRange.isRangeLike(context, arg0, sites.respond_to_begin, sites.respond_to_end)) {
if (RubyRange.isRangeLike(context, arg0, sites.begin_checked, sites.end_checked, sites.exclude_end_checked)) {
RubyRange range = RubyRange.rangeFromRangeLike(context, arg0, sites.begin, sites.end, sites.exclude_end);

long[] beglen = range.begLen(realLength, 0);
Expand Down Expand Up @@ -1538,7 +1538,7 @@ public IRubyObject aset(IRubyObject arg0, IRubyObject arg1) {
ThreadContext context = getRuntime().getCurrentContext();
ArraySites sites = sites(context);

if (RubyRange.isRangeLike(context, arg0, sites.respond_to_begin, sites.respond_to_end)) {
if (RubyRange.isRangeLike(context, arg0, sites.begin_checked, sites.end_checked, sites.exclude_end_checked)) {
RubyRange range = RubyRange.rangeFromRangeLike(context, arg0, sites.begin, sites.end, sites.exclude_end);

long beg = range.begLen0(realLength);
Expand Down
16 changes: 16 additions & 0 deletions core/src/main/java/org/jruby/RubyRange.java
Expand Up @@ -954,6 +954,22 @@ public static boolean isRangeLike(ThreadContext context, IRubyObject obj, Respon
respond_to_end.respondsTo(context, obj, obj);
}

/**
* Return true if the given object responds to "begin", "end" and "exclude_end?" methods.
*
* @param context current context
* @param obj possibly range-like object
* @param begin_checked checked site for begin
* @param end_checked checked site for end
* @param exclude_end_checked checked site for exclude_end?
* @return
*/
public static boolean isRangeLike(ThreadContext context, IRubyObject obj, JavaSites.CheckedSites begin_checked, JavaSites.CheckedSites end_checked, JavaSites.CheckedSites exclude_end_checked) {
return (obj.checkCallMethod(context, begin_checked) != null) &&
(obj.checkCallMethod(context, end_checked) != null) &&
(obj.checkCallMethod(context, exclude_end_checked) != null);
}

// MRI: rb_range_beg_len
public static IRubyObject rangeBeginLength(ThreadContext context, IRubyObject range, int len, int[] begLen, int err) {
JavaSites.RangeSites sites = sites(context);
Expand Down
3 changes: 3 additions & 0 deletions core/src/main/java/org/jruby/runtime/JavaSites.java
Expand Up @@ -91,6 +91,9 @@ public static class KernelSites {
}

public static class ArraySites {
public final CheckedSites begin_checked = new CheckedSites("begin");
public final CheckedSites end_checked = new CheckedSites("end");
public final CheckedSites exclude_end_checked = new CheckedSites("exclude_end?");
public final CheckedSites to_ary_checked = new CheckedSites("to_ary");
public final RespondToCallSite respond_to_to_ary = new RespondToCallSite("to_ary");
public final CallSite to_ary = new FunctionalCachingCallSite("to_ary");
Expand Down

0 comments on commit ec02fe1

Please sign in to comment.