@@ -1633,19 +1633,22 @@ public IRubyObject write(ThreadContext context, IRubyObject[] args) {
16331633 private static final MethodHandle CAT_WITH_CODE_RANGE ;
16341634 private static final MethodHandle MODIFY_AND_CLEAR_CODE_RANGE ;
16351635 private static final MethodHandle SUBSTR_ENC ;
1636+ private static final MethodHandle CHECK_ENCODING ;
16361637
16371638 static {
1638- MethodHandle cat , modify , substr ;
1639+ MethodHandle cat , modify , substr , checkEncoding ;
16391640 MethodHandles .Lookup lookup = MethodHandles .lookup ();
16401641 try {
16411642 cat = lookup .findVirtual (RubyString .class , "catWithCodeRange" , MethodType .methodType (RubyString .class , RubyString .class ));
16421643 modify = lookup .findVirtual (RubyString .class , "modifyAndClearCodeRange" , MethodType .methodType (void .class ));
16431644 substr = lookup .findVirtual (RubyString .class , "substrEnc" , MethodType .methodType (IRubyObject .class , Ruby .class , int .class , int .class ));
1645+ checkEncoding = lookup .findStatic (RubyEncoding .class , "checkEncoding" , MethodType .methodType (void .class , ThreadContext .class , Encoding .class , CodeRangeable .class ));
16441646 } catch (NoSuchMethodException | IllegalAccessException ex ) {
16451647 try {
16461648 cat = lookup .findVirtual (RubyString .class , "cat19" , MethodType .methodType (RubyString .class , RubyString .class ));
16471649 modify = lookup .findVirtual (RubyString .class , "modify19" , MethodType .methodType (void .class ));
16481650 substr = lookup .findVirtual (RubyString .class , "substr19" , MethodType .methodType (IRubyObject .class , Ruby .class , int .class , int .class ));
1651+ checkEncoding = lookup .findStatic (StringIO .class , "checkEncoding" , MethodType .methodType (void .class , ThreadContext .class , Encoding .class , CodeRangeable .class ));
16491652 } catch (NoSuchMethodException | IllegalAccessException ex2 ) {
16501653 throw new ExceptionInInitializerError (ex2 );
16511654 }
@@ -1654,6 +1657,7 @@ public IRubyObject write(ThreadContext context, IRubyObject[] args) {
16541657 CAT_WITH_CODE_RANGE = cat ;
16551658 MODIFY_AND_CLEAR_CODE_RANGE = modify ;
16561659 SUBSTR_ENC = substr ;
1660+ CHECK_ENCODING = checkEncoding ;
16571661 }
16581662
16591663 private static void catString (RubyString myString , RubyString str ) {
@@ -1698,7 +1702,7 @@ private long stringIOWrite(ThreadContext context, Ruby runtime, IRubyObject arg)
16981702 if (enc != encStr && enc != ASCIIEncoding .INSTANCE && enc != USASCIIEncoding .INSTANCE ) {
16991703 RubyString converted = EncodingUtils .strConvEnc (context , str , encStr , enc );
17001704 if (converted == str && encStr != ASCIIEncoding .INSTANCE && encStr != USASCIIEncoding .INSTANCE ) { /* conversion failed */
1701- rb_enc_check_hack (context , enc , str );
1705+ rb_enc_check (context , enc , str );
17021706 }
17031707 str = converted ;
17041708 }
@@ -1732,16 +1736,20 @@ private long stringIOWrite(ThreadContext context, Ruby runtime, IRubyObject arg)
17321736 return len ;
17331737 }
17341738
1735- /*
1736- This hack inlines the JRuby version of rb_enc_check (RubString.checkEncoding) because it only supports str1 being
1737- a true string. This breaks an expectation in StringIO test "test_write_encoding_conversion".
1738-
1739- If the StringIO string is blank, logic downstream from "rb_enc_check" in "encoding_compatible_latter" will simply
1740- choose the second encoding rather than fail as the test expects.
1739+ private static void rb_enc_check (ThreadContext context , Encoding enc , CodeRangeable str ) {
1740+ try {
1741+ CHECK_ENCODING .invokeExact (context , enc , str );
1742+ } catch (Throwable t ) {
1743+ Helpers .throwException (t );
1744+ }
1745+ }
17411746
1742- See discussion in https://github.com/ruby/stringio/pull/116.
1747+ /**
1748+ * Fallback version of rb_enc_check logic for JRuby prior to 9.4.13.0 that did not have a version accepting enc.
1749+ *
1750+ * See discussion in https://github.com/ruby/stringio/pull/116.
17431751 */
1744- private static void rb_enc_check_hack (ThreadContext context , Encoding enc , CodeRangeable str ) {
1752+ private static void checkEncoding (ThreadContext context , Encoding enc , CodeRangeable str ) {
17451753 CodeRangeable fakeCodeRangeable = new EncodingOnlyCodeRangeable (enc );
17461754 Encoding enc1 = StringSupport .areCompatible (fakeCodeRangeable , str );
17471755 if (enc1 == null ) throw context .runtime .newEncodingCompatibilityError ("incompatible character encodings: " +
0 commit comments