Skip to content

Commit

Permalink
Use same logic as IR for kwarg handling here
Browse files Browse the repository at this point in the history
When passing kwargs from a ruby2_keywords method to a core "real
keywords" method, we lose the keywordiness of the incoming hash
and raise an argument error for the arity mismatch. By using the
same logic as IR here, we properly handle the incoming r2k hash.

This same patch could be applied generally to all core methods that
accept keywords, but given the rarity of r2k to core "real
keywords" methods we have chosen to only do targeted fixes. This
reduces the potential impact (versus a new, more general solution)
and the required work (9.4.10 is eagerly awaited). We will explore
more reliable, general improvements to core method kwarg handling
in JRuby 10.

Fixes jruby#8389.
  • Loading branch information
headius committed Jan 8, 2025
1 parent 5f77c63 commit 10a265f
Showing 1 changed file with 9 additions and 5 deletions.
14 changes: 9 additions & 5 deletions core/src/main/java/org/jruby/RubyIO.java
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@
import org.jruby.exceptions.RaiseException;
import org.jruby.ext.fcntl.FcntlLibrary;
import org.jruby.internal.runtime.ThreadedRunnable;
import org.jruby.ir.runtime.IRRuntimeHelpers;
import org.jruby.platform.Platform;
import org.jruby.runtime.Arity;
import org.jruby.runtime.Block;
Expand Down Expand Up @@ -4292,21 +4293,24 @@ public static IRubyObject write(ThreadContext context, IRubyObject recv, IRubyOb

// MRI: io_s_write
public static IRubyObject ioStaticWrite(ThreadContext context, IRubyObject recv, IRubyObject[] argv, boolean binary) {
boolean keywords = hasKeywords(ThreadContext.resetCallInfo(context));
IRubyObject keywords = IRRuntimeHelpers.receiveKeywords(context, argv, false, true, false);
final Ruby runtime = context.runtime;
IRubyObject string, offset, opt;
string = offset = opt = context.nil;

switch (argv.length) {
case 4:
if (!keywords) throw runtime.newArgumentError(argv.length, 2, 3);
opt = argv[3].convertToHash();
if (!(keywords instanceof RubyHash)) throw runtime.newArgumentError(argv.length, 2, 3);
opt = keywords;
offset = argv[2];
string = argv[1];
break;
case 3:
opt = TypeConverter.checkHashType(runtime, argv[2]);
if (opt.isNil()) offset = argv[2];
if (keywords instanceof RubyHash) {
opt = keywords;
} else {
offset = argv[2];
}
string = argv[1];
break;
case 2:
Expand Down

0 comments on commit 10a265f

Please sign in to comment.