Skip to content

Commit

Permalink
fix: ensure serialization still works with pseudo-IO classes
Browse files Browse the repository at this point in the history
Fixes #2773
  • Loading branch information
flavorjones committed Jan 22, 2023
1 parent 9e137bb commit 952ff44
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 2 deletions.
9 changes: 9 additions & 0 deletions CHANGELOG.md
Expand Up @@ -4,6 +4,15 @@ Nokogiri follows [Semantic Versioning](https://semver.org/), please see the [REA

---

## 1.14.1 / unreleased

### Fixed

* Serializing documents now works again with pseudo-IO objects that don't support IO's encoding API (like rubyzip's `Zip::OutputStream`). This was a regression in v1.14.0 due to the fix for [#752](https://github.com/sparklemotion/nokogiri/issues/752) in [#2434](https://github.com/sparklemotion/nokogiri/issues/2434), and was not completely fixed by [#2753](https://github.com/sparklemotion/nokogiri/issues/2753). [[#2773](https://github.com/sparklemotion/nokogiri/issues/2773)]

2e260f53e6b84b8f9c1b115b0ded85eebc8155d7


## 1.14.0 / 2023-01-12

### Notable Changes
Expand Down
1 change: 1 addition & 0 deletions Gemfile
Expand Up @@ -24,6 +24,7 @@ group :development do
gem "minitest-reporters", "= 1.5.0"
gem "ruby_memcheck", "1.2.0" unless RUBY_PLATFORM == "java"
gem "simplecov", "= 0.21.2"
gem "rubyzip", "~> 2.3.2"

# rubocop
if Gem::Requirement.new("~> 3.0").satisfied_by?(Gem::Version.new(RUBY_VERSION))
Expand Down
9 changes: 7 additions & 2 deletions ext/nokogiri/nokogiri.c
Expand Up @@ -112,8 +112,13 @@ noko_io_write(void *io, char *c_buffer, int c_buffer_len)
{
VALUE rb_args[2], rb_n_bytes_written;
VALUE rb_io = (VALUE)io;
VALUE rb_enc = rb_funcall(rb_io, id_external_encoding, 0);
rb_encoding *io_encoding = RB_NIL_P(rb_enc) ? rb_ascii8bit_encoding() : rb_to_encoding(rb_enc);
VALUE rb_enc = Qnil;
rb_encoding *io_encoding;

if (rb_respond_to(rb_io, id_external_encoding)) {
rb_enc = rb_funcall(rb_io, id_external_encoding, 0);
}
io_encoding = RB_NIL_P(rb_enc) ? rb_ascii8bit_encoding() : rb_to_encoding(rb_enc);

rb_args[0] = rb_io;
rb_args[1] = rb_enc_str_new(c_buffer, (long)c_buffer_len, io_encoding);
Expand Down
35 changes: 35 additions & 0 deletions test/xml/test_document_encoding.rb
Expand Up @@ -87,6 +87,41 @@ class TestDocumentEncoding < Nokogiri::TestCase
assert_equal(Encoding::UTF_16, output.encoding)
assert_equal(utf16_document.bytesize, output.bytesize)
end

describe "pseudo-IO" do
it "serializes correctly with Zip::OutputStream objects" do
# https://github.com/sparklemotion/nokogiri/issues/2773
require "zip"

xml = <<~XML
<?xml version="1.0" encoding="UTF-8"?>
<root>
<bar>A</bar>
</root>
XML

Dir.mktmpdir do |tmpdir|
zipfile_path = File.join(tmpdir, "test.zip")

Zip::OutputStream.open(zipfile_path) do |io|
io.put_next_entry("test-utf8.xml")
Nokogiri::XML(xml).write_to(io, encoding: "UTF-8")
end

Zip::InputStream.open(zipfile_path) do |io|
entry = io.get_next_entry
assert_equal("test-utf8.xml", entry.name)
output = io.read

# no final newline on jruby. descriptive, not prescriptive.
expected_length = Nokogiri.jruby? ? xml.bytesize - 1 : xml.bytesize

assert_equal(Encoding::UTF_8, output.encoding)
assert_equal(expected_length, output.bytesize)
end
end
end
end
end
end
end
Expand Down

0 comments on commit 952ff44

Please sign in to comment.