@@ -1633,19 +1633,22 @@ public IRubyObject write(ThreadContext context, IRubyObject[] args) {
1633
1633
private static final MethodHandle CAT_WITH_CODE_RANGE ;
1634
1634
private static final MethodHandle MODIFY_AND_CLEAR_CODE_RANGE ;
1635
1635
private static final MethodHandle SUBSTR_ENC ;
1636
+ private static final MethodHandle CHECK_ENCODING ;
1636
1637
1637
1638
static {
1638
- MethodHandle cat , modify , substr ;
1639
+ MethodHandle cat , modify , substr , checkEncoding ;
1639
1640
MethodHandles .Lookup lookup = MethodHandles .lookup ();
1640
1641
try {
1641
1642
cat = lookup .findVirtual (RubyString .class , "catWithCodeRange" , MethodType .methodType (RubyString .class , RubyString .class ));
1642
1643
modify = lookup .findVirtual (RubyString .class , "modifyAndClearCodeRange" , MethodType .methodType (void .class ));
1643
1644
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 ));
1644
1646
} catch (NoSuchMethodException | IllegalAccessException ex ) {
1645
1647
try {
1646
1648
cat = lookup .findVirtual (RubyString .class , "cat19" , MethodType .methodType (RubyString .class , RubyString .class ));
1647
1649
modify = lookup .findVirtual (RubyString .class , "modify19" , MethodType .methodType (void .class ));
1648
1650
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 ));
1649
1652
} catch (NoSuchMethodException | IllegalAccessException ex2 ) {
1650
1653
throw new ExceptionInInitializerError (ex2 );
1651
1654
}
@@ -1654,6 +1657,7 @@ public IRubyObject write(ThreadContext context, IRubyObject[] args) {
1654
1657
CAT_WITH_CODE_RANGE = cat ;
1655
1658
MODIFY_AND_CLEAR_CODE_RANGE = modify ;
1656
1659
SUBSTR_ENC = substr ;
1660
+ CHECK_ENCODING = checkEncoding ;
1657
1661
}
1658
1662
1659
1663
private static void catString (RubyString myString , RubyString str ) {
@@ -1698,7 +1702,7 @@ private long stringIOWrite(ThreadContext context, Ruby runtime, IRubyObject arg)
1698
1702
if (enc != encStr && enc != ASCIIEncoding .INSTANCE && enc != USASCIIEncoding .INSTANCE ) {
1699
1703
RubyString converted = EncodingUtils .strConvEnc (context , str , encStr , enc );
1700
1704
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 );
1702
1706
}
1703
1707
str = converted ;
1704
1708
}
@@ -1732,16 +1736,20 @@ private long stringIOWrite(ThreadContext context, Ruby runtime, IRubyObject arg)
1732
1736
return len ;
1733
1737
}
1734
1738
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
+ }
1741
1746
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.
1743
1751
*/
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 ) {
1745
1753
CodeRangeable fakeCodeRangeable = new EncodingOnlyCodeRangeable (enc );
1746
1754
Encoding enc1 = StringSupport .areCompatible (fakeCodeRangeable , str );
1747
1755
if (enc1 == null ) throw context .runtime .newEncodingCompatibilityError ("incompatible character encodings: " +
0 commit comments