|
55 | 55 | import org.jruby.runtime.marshal.DataType; |
56 | 56 | import org.jruby.util.ArraySupport; |
57 | 57 | import org.jruby.util.ByteList; |
| 58 | +import org.jruby.util.CodeRangeable; |
58 | 59 | import org.jruby.util.StringSupport; |
59 | 60 | import org.jruby.util.TypeConverter; |
60 | 61 | import org.jruby.util.func.ObjectObjectIntFunction; |
@@ -1655,7 +1656,7 @@ private long stringIOWrite(ThreadContext context, Ruby runtime, IRubyObject arg) |
1655 | 1656 | if (enc != encStr && enc != ASCIIEncoding.INSTANCE && enc != USASCIIEncoding.INSTANCE) { |
1656 | 1657 | RubyString converted = EncodingUtils.strConvEnc(context, str, encStr, enc); |
1657 | 1658 | if (converted == str && encStr != ASCIIEncoding.INSTANCE && encStr != USASCIIEncoding.INSTANCE) { /* conversion failed */ |
1658 | | - ptr.string.checkEncoding(str); |
| 1659 | + rb_enc_check_hack(context, enc, str); |
1659 | 1660 | } |
1660 | 1661 | str = converted; |
1661 | 1662 | } |
@@ -1689,6 +1690,50 @@ private long stringIOWrite(ThreadContext context, Ruby runtime, IRubyObject arg) |
1689 | 1690 | return len; |
1690 | 1691 | } |
1691 | 1692 |
|
| 1693 | + /* |
| 1694 | + This hack inlines the JRuby version of rb_enc_check (RubString.checkEncoding) because it only supports str1 being |
| 1695 | + a true string. This breaks an expectation in StringIO test "test_write_encoding_conversion". |
| 1696 | +
|
| 1697 | + If the StringIO string is blank, logic downstream from "rb_enc_check" in "encoding_compatible_latter" will simply |
| 1698 | + choose the second encoding rather than fail as the test expects. |
| 1699 | +
|
| 1700 | + See discussion in https://github.com/ruby/stringio/pull/116. |
| 1701 | + */ |
| 1702 | + private static void rb_enc_check_hack(ThreadContext context, Encoding enc, CodeRangeable str) { |
| 1703 | + CodeRangeable fakeCodeRangeable = new EncodingOnlyCodeRangeable(enc); |
| 1704 | + Encoding enc1 = StringSupport.areCompatible(fakeCodeRangeable, str); |
| 1705 | + if (enc1 == null) throw context.runtime.newEncodingCompatibilityError("incompatible character encodings: " + |
| 1706 | + enc1 + " and " + str.getByteList().getEncoding()); |
| 1707 | + } |
| 1708 | + |
| 1709 | + private static class EncodingOnlyCodeRangeable implements CodeRangeable { |
| 1710 | + private final Encoding enc; |
| 1711 | + |
| 1712 | + public EncodingOnlyCodeRangeable(Encoding enc) {this.enc = enc;} |
| 1713 | + @Override |
| 1714 | + public int getCodeRange() {return 0;} |
| 1715 | + @Override |
| 1716 | + public int scanForCodeRange() {return 0;} |
| 1717 | + @Override |
| 1718 | + public boolean isCodeRangeValid() {return false;} |
| 1719 | + @Override |
| 1720 | + public void setCodeRange(int codeRange) {} |
| 1721 | + @Override |
| 1722 | + public void clearCodeRange() {} |
| 1723 | + @Override |
| 1724 | + public void keepCodeRange() {} |
| 1725 | + @Override |
| 1726 | + public void modifyAndKeepCodeRange() {} |
| 1727 | + @Override |
| 1728 | + public Encoding checkEncoding(CodeRangeable other) {return null;} |
| 1729 | + @Override |
| 1730 | + public ByteList getByteList() {return new ByteList(0, enc);} |
| 1731 | + @Override |
| 1732 | + public void modify() {} |
| 1733 | + @Override |
| 1734 | + public void modify(int length) {} |
| 1735 | + } |
| 1736 | + |
1692 | 1737 | @JRubyMethod |
1693 | 1738 | public IRubyObject set_encoding(ThreadContext context, IRubyObject ext_enc) { |
1694 | 1739 | Encoding enc; |
|
0 commit comments