pFad - Phone/Frame/Anonymizer/Declutterfier! Saves Data!


--- a PPN by Garber Painting Akron. With Image Size Reduction included!

URL: http://github.com/jruby/jruby/commit/771afb025d962871b35eb3dc304d5260ae3972ab

/> base compareTo should not silence all Ruby raised exceptions (fixes #… · jruby/jruby@771afb0 · GitHub
Skip to content

Commit 771afb0

Browse files
committed
base compareTo should not silence all Ruby raised exceptions (fixes #2232)
this no longer makese sense - and leads to confusing behavior when Ruby objects are used within Java (delegating to <=> which might be user-defined) every-one is expected to handle <=> on 1.9 (and return nil if not comparable) on 1.8 we still swallow a NoMethodError as Object does not provide <=>
1 parent 3160c14 commit 771afb0

2 files changed

Lines changed: 55 additions & 12 deletions

File tree

core/src/main/java/org/jruby/RubyBasicObject.java

Lines changed: 31 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1115,18 +1115,17 @@ public IRubyObject op_not_equal(ThreadContext context, IRubyObject other) {
11151115
* @return 0 if equal,
11161116
* &lt; 0 if this is less than other,
11171117
* &gt; 0 if this is greater than other
1118-
* @throws IllegalArgumentException if the objects cannot be compared.
11191118
*/
11201119
public int compareTo(IRubyObject other) {
1121-
try {
1122-
IRubyObject cmp = invokedynamic(getRuntime().getCurrentContext(),
1123-
this, OP_CMP, other);
1120+
final Ruby runtime = getRuntime();
11241121

1125-
// if RubyBasicObject#op_cmp is used, the result may be nil
1126-
if (!cmp.isNil()) {
1127-
return (int) cmp.convertToInteger().getLongValue();
1128-
}
1129-
} catch (RaiseException ex) {
1122+
if ( runtime.is1_8() ) return compareTo18(runtime, other);
1123+
1124+
IRubyObject cmp = invokedynamic(runtime.getCurrentContext(), this, OP_CMP, other);
1125+
1126+
// if RubyBasicObject#op_cmp is used, the result may be nil (not comparable)
1127+
if ( ! cmp.isNil() ) {
1128+
return (int) cmp.convertToInteger().getLongValue();
11301129
}
11311130

11321131
/* We used to raise an error if two IRubyObject were not comparable, but
@@ -1141,6 +1140,27 @@ public int compareTo(IRubyObject other) {
11411140
return 0;
11421141
}
11431142

1143+
// on 1.8 nil (Object in general) is not comparable using <=> by default
1144+
private int compareTo18(final Ruby runtime, IRubyObject other) {
1145+
final ThreadContext context = runtime.getCurrentContext();
1146+
final IRubyObject $ex = context.getErrorInfo();
1147+
try {
1148+
IRubyObject cmp = invokedynamic(context, this, OP_CMP, other);
1149+
if ( ! cmp.isNil() ) {
1150+
return (int) cmp.convertToInteger().getLongValue();
1151+
}
1152+
}
1153+
catch (RaiseException e) {
1154+
RubyException re = e.getException();
1155+
if ( re instanceof RubyNoMethodError ) {
1156+
// e.g. NoMethodError: undefined method `<=>' for #<Object:0xceb431e>
1157+
context.setErrorInfo($ex); return 0;
1158+
}
1159+
throw e;
1160+
}
1161+
return 0;
1162+
}
1163+
11441164
public IRubyObject op_equal(ThreadContext context, IRubyObject obj) {
11451165
return op_equal_19(context, obj);
11461166
}
@@ -1878,11 +1898,10 @@ public IRubyObject eql_p(IRubyObject obj) {
18781898
}
18791899

18801900
public IRubyObject op_cmp(ThreadContext context, IRubyObject other) {
1881-
Ruby runtime = context.runtime;
18821901
if (this == other || invokedynamic(context, this, OP_EQUAL, other).isTrue()){
1883-
return RubyFixnum.zero(runtime);
1902+
return RubyFixnum.zero(context.runtime);
18841903
}
1885-
return runtime.getNil();
1904+
return context.nil;
18861905
}
18871906

18881907
/** rb_obj_init_copy

spec/java_integration/exceptions/rescue_spec.rb

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,4 +225,28 @@ def obj.go
225225

226226
end
227227

228+
SampleTask = Struct.new(:time) do
229+
include Comparable
230+
231+
def <=>(that)
232+
raise ArgumentError.new("unexpected #{self.inspect}") unless self.time
233+
raise ArgumentError.new("unexpected #{that.inspect}") unless that.time
234+
self.time <=> that.time
235+
end
236+
end
237+
238+
it 'does not swallow Ruby errors on compareTo' do
239+
queue = java.util.PriorityQueue.new(10)
240+
queue.add t2 = SampleTask.new(2)
241+
queue.add t1 = SampleTask.new(1)
242+
begin
243+
queue.add SampleTask.new(nil)
244+
rescue ArgumentError => e
245+
expect( e.message ).to start_with 'unexpected #<struct SampleTask'
246+
else
247+
fail 'compareTo did not raise'
248+
end
249+
expect( queue.first ).to be t1
250+
end
251+
228252
end

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad © 2024 Your Company Name. All rights reserved.





Check this box to remove all script contents from the fetched content.



Check this box to remove all images from the fetched content.


Check this box to remove all CSS styles from the fetched content.


Check this box to keep images inefficiently compressed and original size.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy