diff --git a/NEWS.md b/NEWS.md index 4575b2bcbee7e9..03f45a4bfb148b 100644 --- a/NEWS.md +++ b/NEWS.md @@ -185,13 +185,13 @@ They are still available on rubygems.org and can be installed with ### The following default gems are updated. * RubyGems 4.1.0.beta1 - * 4.0.3 to [v4.0.4][RubyGems-v4.0.4], [v4.0.5][RubyGems-v4.0.5], [v4.0.6][RubyGems-v4.0.6], [v4.0.7][RubyGems-v4.0.7], [v4.0.8][RubyGems-v4.0.8], [v4.0.9][RubyGems-v4.0.9], [v4.0.10][RubyGems-v4.0.10], [v4.0.11][RubyGems-v4.0.11], [v4.0.12][RubyGems-v4.0.12], [v4.0.13][RubyGems-v4.0.13], [v4.0.14][RubyGems-v4.0.14], [v4.0.15][RubyGems-v4.0.15], [v4.0.16][RubyGems-v4.0.16], [v4.0.17][RubyGems-v4.0.17], [v4.0.18][RubyGems-v4.0.18], [v4.0.19][RubyGems-v4.0.19], [v4.0.20][RubyGems-v4.0.20], [v4.1.0.beta1][RubyGems-v4.1.0.beta1] + * 4.0.3 to [v4.0.4][RubyGems-v4.0.4], [v4.0.5][RubyGems-v4.0.5], [v4.0.6][RubyGems-v4.0.6], [v4.0.7][RubyGems-v4.0.7], [v4.0.8][RubyGems-v4.0.8], [v4.0.9][RubyGems-v4.0.9], [v4.0.10][RubyGems-v4.0.10], [v4.0.11][RubyGems-v4.0.11], [v4.0.12][RubyGems-v4.0.12], [v4.0.13][RubyGems-v4.0.13], [v4.0.14][RubyGems-v4.0.14], [v4.0.15][RubyGems-v4.0.15], [v4.0.16][RubyGems-v4.0.16], [v4.0.17][RubyGems-v4.0.17], [v4.0.18][RubyGems-v4.0.18], [v4.0.19][RubyGems-v4.0.19], [v4.0.20][RubyGems-v4.0.20], [v4.0.21][RubyGems-v4.0.21], [v4.1.0.beta1][RubyGems-v4.1.0.beta1] * bundler 4.1.0.beta1 * 4.0.3 to [v4.0.4][bundler-v4.0.4], [v4.0.5][bundler-v4.0.5], [v4.0.6][bundler-v4.0.6], [v4.0.7][bundler-v4.0.7], [v4.0.8][bundler-v4.0.8], [v4.0.9][bundler-v4.0.9], [v4.0.10][bundler-v4.0.10], [v4.0.11][bundler-v4.0.11], [v4.0.12][bundler-v4.0.12], [v4.0.13][bundler-v4.0.13], [v4.0.14][bundler-v4.0.14], [v4.0.15][bundler-v4.0.15], [v4.0.16][bundler-v4.0.16], [v4.0.17][bundler-v4.0.17] * erb 6.0.7 * 6.0.1 to [v6.0.1.1][erb-v6.0.1.1], [v6.0.2][erb-v6.0.2], [v6.0.3][erb-v6.0.3], [v6.0.4][erb-v6.0.4], [v6.0.5][erb-v6.0.5], [v6.0.6][erb-v6.0.6], [v6.0.7][erb-v6.0.7] * error_highlight 0.7.2 -* io-console 0.9.2 +* io-console 0.9.3 * 0.8.2 to [v0.9.0][io-console-v0.9.0], [v0.9.1][io-console-v0.9.1], [v0.9.2][io-console-v0.9.2] * io-wait 999.999.999 * ipaddr 1.2.9 @@ -208,7 +208,7 @@ They are still available on rubygems.org and can be installed with * 1.7.0 to [v1.8.0][prism-v1.8.0], [v1.8.1][prism-v1.8.1], [v1.9.0][prism-v1.9.0] * psych 5.5.0 * 5.3.1 to [v5.4.0][psych-v5.4.0], [v5.5.0][psych-v5.5.0] -* resolv 0.7.1 +* resolv 0.7.2 * 0.7.0 to [v0.7.1][resolv-v0.7.1] * stringio 3.2.1.dev * strscan 3.1.9.dev @@ -510,6 +510,7 @@ A lot of work has gone into making Ractors more stable, performant, and usable. [RubyGems-v4.0.18]: https://github.com/rubygems/rubygems/releases/tag/v4.0.18 [RubyGems-v4.0.19]: https://github.com/rubygems/rubygems/releases/tag/v4.0.19 [RubyGems-v4.0.20]: https://github.com/rubygems/rubygems/releases/tag/v4.0.20 +[RubyGems-v4.0.21]: https://github.com/rubygems/rubygems/releases/tag/v4.0.21 [RubyGems-v4.1.0.beta1]: https://github.com/rubygems/rubygems/releases/tag/v4.1.0.beta1 [bundler-v4.0.4]: https://github.com/rubygems/rubygems/releases/tag/bundler-v4.0.4 [bundler-v4.0.5]: https://github.com/rubygems/rubygems/releases/tag/bundler-v4.0.5 diff --git a/array.c b/array.c index 0d5430860aa719..802270551c9bc6 100644 --- a/array.c +++ b/array.c @@ -4844,7 +4844,7 @@ rb_ary_zip(int argc, VALUE *argv, VALUE ary) else { result = rb_ary_new_capa(len); - for (i=0; iSpecial Record Separators Like some methods in class IO, method +gets+ honors two special record separators; -see {Special Line Separators}[https://docs.ruby-lang.org/en/master/IO.html#class-IO-label-Special+Line+Separator+Values]: +see {Special Line Separators}[rdoc-ref:IO@Special+Line+Separator+Values]: strio = StringIO.new(TEXT) strio.gets('') # Read "paragraph" (up to empty line). diff --git a/ext/io/console/console.c b/ext/io/console/console.c index d3f0a7d86041d0..aa19901a72825f 100644 --- a/ext/io/console/console.c +++ b/ext/io/console/console.c @@ -4,7 +4,7 @@ */ static const char *const -IO_CONSOLE_VERSION = "0.9.2"; +IO_CONSOLE_VERSION = "0.9.3"; #include "ruby.h" #include "ruby/io.h" diff --git a/ext/io/console/extconf.rb b/ext/io/console/extconf.rb index 65d3605762f530..6837d48f6bd4ff 100644 --- a/ext/io/console/extconf.rb +++ b/ext/io/console/extconf.rb @@ -61,11 +61,11 @@ console.#$OBJEXT: $(VK_HEADER) MK end - if vk_tool + if vk_tool and vk_mk = (File.read("#$srcdir/win32_vk.mk") rescue nil) unless conf.any? {|c| /^ *top_srcdir *=/.match?(c)} conf << "top_srcdir = $(srcdir)/../../..\n" end - conf.concat(depend_rules(File.read("#$srcdir/win32_vk.mk"))) + conf.concat(depend_rules(vk_mk)) end conf } diff --git a/lib/resolv.rb b/lib/resolv.rb index 07a39f0cf409ea..f2162f709b93fa 100644 --- a/lib/resolv.rb +++ b/lib/resolv.rb @@ -35,7 +35,7 @@ class Resolv # The version string - VERSION = "0.7.1" + VERSION = "0.7.2" ## # Looks up the first IP address for +name+. diff --git a/proc.c b/proc.c index 6206f2c5da668e..ddb834e4645bf6 100644 --- a/proc.c +++ b/proc.c @@ -4090,6 +4090,9 @@ method_inspect(VALUE method) } else { mklass = data->klass; + if (RB_TYPE_P(mklass, T_ICLASS)) { + mklass = RBASIC_CLASS(mklass); + } if (RCLASS_SINGLETON_P(mklass)) { VALUE v = RCLASS_ATTACHED_OBJECT(mklass); if (!(RB_TYPE_P(v, T_CLASS) || RB_TYPE_P(v, T_MODULE))) { diff --git a/ruby.c b/ruby.c index 0f8f1e3db90563..9fb594a139a38a 100644 --- a/ruby.c +++ b/ruby.c @@ -898,7 +898,6 @@ moreswitches(const char *s, ruby_cmdline_options_t *opt, int envopt) char **argv, *p; const char *ap = 0; VALUE argstr, argary; - void *ptr; VALUE src_enc_name = opt->src.enc.name; VALUE ext_enc_name = opt->ext.enc.name; @@ -935,7 +934,7 @@ moreswitches(const char *s, ruby_cmdline_options_t *opt, int envopt) rb_str_cat(argary, (char *)&ap, sizeof(ap)); VALUE ptr_obj; - argv = ptr = RB_ALLOCV_N(char *, ptr_obj, argc); + argv = RB_ALLOCV_N(char *, ptr_obj, argc); MEMMOVE(argv, RSTRING_PTR(argary), char *, argc); while ((i = proc_options(argc, argv, opt, envopt)) > 1 && envopt && (argc -= i) > 0) { diff --git a/spec/ruby/core/string/bit_clear_spec.rb b/spec/ruby/core/string/bit_clear_spec.rb index 1a73167a7f5e70..2cfa529e5e91a9 100644 --- a/spec/ruby/core/string/bit_clear_spec.rb +++ b/spec/ruby/core/string/bit_clear_spec.rb @@ -34,17 +34,17 @@ end it "raises an IndexError for an out of range bit offset" do - -> { "\x00".bit_clear(8) }.should.raise(IndexError) - -> { "\x00".bit_clear(-1) }.should.raise(IndexError) + -> { (+"\x00").bit_clear(8) }.should.raise(IndexError) + -> { (+"\x00").bit_clear(-1) }.should.raise(IndexError) end it "raises an IndexError when a region extends past the end" do - -> { "\x00".bit_clear(0, 9) }.should.raise(IndexError) - -> { "\x00".bit_clear(0..8) }.should.raise(IndexError) + -> { (+"\x00").bit_clear(0, 9) }.should.raise(IndexError) + -> { (+"\x00").bit_clear(0..8) }.should.raise(IndexError) end it "raises an ArgumentError for a negative length" do - -> { "\x00".bit_clear(0, -1) }.should.raise(ArgumentError) + -> { (+"\x00").bit_clear(0, -1) }.should.raise(ArgumentError) end it "raises a FrozenError if self is frozen" do diff --git a/spec/ruby/core/string/bit_flip_spec.rb b/spec/ruby/core/string/bit_flip_spec.rb index 9bf3136f2e168f..27fee9de4e3bfc 100644 --- a/spec/ruby/core/string/bit_flip_spec.rb +++ b/spec/ruby/core/string/bit_flip_spec.rb @@ -36,17 +36,17 @@ end it "raises an IndexError for an out of range bit offset" do - -> { "\x00".bit_flip(8) }.should.raise(IndexError) - -> { "\x00".bit_flip(-1) }.should.raise(IndexError) + -> { (+"\x00").bit_flip(8) }.should.raise(IndexError) + -> { (+"\x00").bit_flip(-1) }.should.raise(IndexError) end it "raises an IndexError when a region extends past the end" do - -> { "\x00".bit_flip(0, 9) }.should.raise(IndexError) - -> { "\x00".bit_flip(0..8) }.should.raise(IndexError) + -> { (+"\x00").bit_flip(0, 9) }.should.raise(IndexError) + -> { (+"\x00").bit_flip(0..8) }.should.raise(IndexError) end it "raises an ArgumentError for a negative length" do - -> { "\x00".bit_flip(0, -1) }.should.raise(ArgumentError) + -> { (+"\x00").bit_flip(0, -1) }.should.raise(ArgumentError) end it "raises a FrozenError if self is frozen" do diff --git a/spec/ruby/core/string/bit_set_spec.rb b/spec/ruby/core/string/bit_set_spec.rb index 6059c9f2459d27..4764342f630efc 100644 --- a/spec/ruby/core/string/bit_set_spec.rb +++ b/spec/ruby/core/string/bit_set_spec.rb @@ -34,17 +34,17 @@ end it "raises an IndexError for an out of range bit offset" do - -> { "\x00".bit_set(8) }.should.raise(IndexError) - -> { "\x00".bit_set(-1) }.should.raise(IndexError) + -> { (+"\x00").bit_set(8) }.should.raise(IndexError) + -> { (+"\x00").bit_set(-1) }.should.raise(IndexError) end it "raises an IndexError when a region extends past the end" do - -> { "\x00".bit_set(0, 9) }.should.raise(IndexError) - -> { "\x00".bit_set(0..8) }.should.raise(IndexError) + -> { (+"\x00").bit_set(0, 9) }.should.raise(IndexError) + -> { (+"\x00").bit_set(0..8) }.should.raise(IndexError) end it "raises an ArgumentError for a negative length" do - -> { "\x00".bit_set(0, -1) }.should.raise(ArgumentError) + -> { (+"\x00").bit_set(0, -1) }.should.raise(ArgumentError) end it "raises a FrozenError if self is frozen" do diff --git a/string.c b/string.c index 641553b8e3594a..bff524bd8a2f7f 100644 --- a/string.c +++ b/string.c @@ -7156,6 +7156,8 @@ str_mutate_single_bit(VALUE str, VALUE index, bool lsb_first, enum str_bit_mutat unsigned char *ptr; unsigned char mask; + rb_check_frozen(str); + if (str_bit_offset_out_of_range(RSTRING_LEN(str), offset.value)) { rb_raise(rb_eIndexError, "bit index out of range"); } @@ -7204,6 +7206,9 @@ str_mutate_bit(int argc, VALUE *argv, VALUE str, enum str_bit_mutation mutation) len = str_bit_length_from_index(length_v); } + /* Even a zero-length write requires a mutable receiver. */ + rb_check_frozen(str); + /* * A region that begins past the end is out of range even when it is * empty, and one that runs past the end is not allowed to silently @@ -7222,8 +7227,7 @@ str_mutate_bit(int argc, VALUE *argv, VALUE str, enum str_bit_mutation mutation) rb_raise(rb_eIndexError, "bit range out of range"); } } - /* Even a zero-length write requires a mutable receiver. */ - rb_check_frozen(str); + if (len == 0) return str; rb_str_modify(str); diff --git a/test/ruby/test_array.rb b/test/ruby/test_array.rb index 26c75305d78e91..de629760ca79aa 100644 --- a/test/ruby/test_array.rb +++ b/test/ruby/test_array.rb @@ -3125,6 +3125,18 @@ def test_zip_with_enumerator assert_equal([["a", 6], ["b", 7], ["c", 8]], a.zip(e), bug17814) end + def test_zip_modify_during_to_ary + # [Bug #22319] + a = (1..100_000).to_a + obj = Object.new + obj.define_singleton_method(:to_ary) do + a.clear + [1, 2, 3] + end + assert_nothing_raised { a.zip(obj) } + assert_equal([], a) + end + def test_transpose assert_equal([[1, :a], [2, :b], [3, :c]], [[1, 2, 3], [:a, :b, :c]].transpose) diff --git a/test/ruby/test_econv.rb b/test/ruby/test_econv.rb index 1d0641e91847a0..278e39e4511935 100644 --- a/test/ruby/test_econv.rb +++ b/test/ruby/test_econv.rb @@ -856,6 +856,20 @@ def test_iso2022jp_invalid_replace "\222\xA1x".encode("iso-2022-jp", "stateless-iso-2022-jp", :invalid => :replace)) end + def test_inspect_decorator_source_name + decorator_names = %w[ + amp_escape xml_text_escape xml_attr_content_escape xml_attr_quote + universal_newline crlf_newline cr_newline lf_newline + ] + all_assertions_foreach(nil, *decorator_names) do |decorator| + ec = Encoding::Converter.new('', decorator) + inspect = ec.inspect + 10_000.times {"A"*100} + GC.start(full_mark: true, immediate_sweep: true) + assert_equal inspect, ec.inspect + end + end + def test_convpath eucjp = Encoding::EUC_JP utf8 = Encoding::UTF_8 diff --git a/test/ruby/test_method.rb b/test/ruby/test_method.rb index 6285c9e1a410bf..b9e4c320f45e45 100644 --- a/test/ruby/test_method.rb +++ b/test/ruby/test_method.rb @@ -558,6 +558,12 @@ def o.foo; end; line_no = __LINE__ c5.extend(m) c6 = Class.new(c5) assert_equal("#(#{m.inspect})#prep(prepend)() #{__FILE__}:#{line_no}>", c6.method(:prep).inspect, bug17428) + + mod = Module.new { def foo; end }; line_no = __LINE__ + cls = Class.new { include mod } + o = cls.new + assert_equal("#", + o.method(:foo).unbind.bind(o).inspect, "[ruby-core:126737] [Bug #22321]") end def test_callee_top_level diff --git a/test/ruby/test_string.rb b/test/ruby/test_string.rb index 899ff08692aacb..4a7e8699d9d75b 100644 --- a/test/ruby/test_string.rb +++ b/test/ruby/test_string.rb @@ -1201,7 +1201,7 @@ def test_bit_set_clear_flip_region assert_raise(FrozenError) { S("\x00").freeze.bit_set(0, 0) } assert_raise(FrozenError) { S("\x00").freeze.bit_clear(0...0) } assert_raise(FrozenError) { S("\x00").freeze.bit_flip(8..) } - assert_raise(IndexError) { S("\x00").freeze.bit_set(9, 0) } + assert_raise(FrozenError) { S("\x00").freeze.bit_set(9, 0) } # Copy-on-write: mutating must not affect a shared sibling. shared = S("fooXbar").split(S("X")).last @@ -1209,6 +1209,79 @@ def test_bit_set_clear_flip_region assert_equal(S("\xFFar").b, shared.b) end + def test_bit_set_single_chilled_string_warning + return unless @cls == String + assert_bit_op_chilled_string_warning(:bit_set, 7000 * 8) + end + + def test_bit_clear_single_chilled_string_warning + return unless @cls == String + assert_bit_op_chilled_string_warning(:bit_clear, 7000 * 8) + end + + def test_bit_flip_single_chilled_string_warning + return unless @cls == String + assert_bit_op_chilled_string_warning(:bit_flip, 7000 * 8) + end + + def test_bit_set_region_chilled_string_warning + return unless @cls == String + assert_bit_op_chilled_string_warning(:bit_set, 7000 * 8, 2) + end + + def test_bit_clear_region_chilled_string_warning + return unless @cls == String + assert_bit_op_chilled_string_warning(:bit_clear, 7000 * 8, 2) + end + + def test_bit_flip_region_chilled_string_warning + return unless @cls == String + assert_bit_op_chilled_string_warning(:bit_flip, 7000 * 8, 2) + end + + def test_bit_set_range_chilled_string_warning + return unless @cls == String + assert_bit_op_chilled_string_warning(:bit_set, (7000 * 8)..(7100 * 8)) + end + + def test_bit_clear_range_chilled_string_warning + return unless @cls == String + assert_bit_op_chilled_string_warning(:bit_clear, (7000 * 8)..(7100 * 8)) + end + + def test_bit_flip_range_chilled_string_warning + return unless @cls == String + assert_bit_op_chilled_string_warning(:bit_flip, (7000 * 8)..(7100 * 8)) + end + + def assert_bit_op_chilled_string_warning(op, *args) + assert_separately([], "#{<<-"{#"}\n#{<<-'};'}") + $target = <<~STR # chilled string + #{("A"*63+"\n")*128} # 64*128 = 8192 + STR + END { + assert_raise(IndexError) {$target.#{op}(#{args.map(&:inspect).join(", ")})} + } + {# + $reentered = false + + module ReallocateWarning + def warn(message, category: nil, **kwargs) + if category == :deprecated && !$reentered + $reentered = true + $target.clear + $target << ("B" * 1024) + return nil + end + + super + end + end + + Warning.extend(ReallocateWarning) + }; + end + def test_bit_count assert_equal(0, S("").bit_count) assert_equal(0, S("\x00").bit_count) diff --git a/tool/sync_default_gems.rb b/tool/sync_default_gems.rb index 2232f5ac88d87b..0799a3d10cfa0a 100755 --- a/tool/sync_default_gems.rb +++ b/tool/sync_default_gems.rb @@ -304,9 +304,17 @@ def lib((upstream, branch), gemspec_in_subdir: false) ["test/zlib", "test/zlib"], ["zlib.gemspec", "ext/zlib/zlib.gemspec"], ]), + # Most files under tool/lib and tool/test belong to ruby/ruby, so map + # each upstream file rather than the directories. "test-unit-ruby-core":repo("ruby/test-unit-ruby-core", [ - ["lib", "tool/lib"], - ["test", "tool/test"], + ["lib/core_assertions.rb", "tool/lib/core_assertions.rb"], + ["lib/envutil.rb", "tool/lib/envutil.rb"], + ["lib/find_executable.rb", "tool/lib/find_executable.rb"], + ["lib/memory_status.rb", "tool/lib/memory_status.rb"], + ["test/test_core_assertions.rb", "tool/test/test_core_assertions.rb"], + ["test/test_envutil.rb", "tool/test/test_envutil.rb"], + ["test/test_find_executable.rb", "tool/test/test_find_executable.rb"], + ["test/test_memory_status.rb", "tool/test/test_memory_status.rb"], ]), }.transform_keys(&:to_s) @@ -464,7 +472,7 @@ def sync_default_gems(gem) end def check_prerelease_version(gem) - return if ["rubygems", "mmtk", "Onigmo"].include?(gem) + return if ["rubygems", "mmtk", "Onigmo", "test-unit-ruby-core"].include?(gem) require "net/https" require "json" @@ -484,7 +492,41 @@ def check_prerelease_version(gem) "lib/#{gem.split("-").join("/")}/#{gem}.gemspec", ].find{|gemspec| File.exist?(gemspec)} spec = Gem::Specification.load(gemspec) - puts "#{gem}-#{spec.version} is not latest version of rubygems.org" if spec.version.to_s != latest_version + version = spec.version + return if version.to_s == latest_version + + if !version.prerelease? and Gem::Version.correct?(latest_version) and + version > Gem::Version.new(latest_version) and + prerelease = mark_as_prerelease(gem, version) + puts "#{gem}-#{version} is not released yet, marked as #{prerelease}" + else + puts "#{gem}-#{version} is not latest version of rubygems.org" + end + end + + # Upstream bumps the version just after a release, so the synced tree holds a + # version nobody can install yet, and `bundle install` against it would lock + # to that version. Turn it into a prerelease instead. + def mark_as_prerelease(gem, version) + literal = %["#{version}"] + files = REPOSITORIES[gem].mappings.flat_map do |_src, dst| + File.directory?(dst) ? Dir.glob("#{dst}/**/*.{c,rb,gemspec}") : [dst] + end + found = files.uniq.filter_map do |file| + next unless File.file?(file) + source = File.binread(file) + definition = source.lines.find {|line| line.include?(literal) and line.include?("VERSION")} + [file, source, definition] if definition + end + unless found.size == 1 + puts "Cannot tell where #{gem}-#{version} is defined" + return nil + end + + file, source, definition = found[0] + prerelease = "#{version}.dev" + File.binwrite(file, source.sub(definition) {definition.sub(literal) {%["#{prerelease}"]}}) + prerelease end def message_filter(repo, sha, log, context: nil) diff --git a/tool/test/test_sync_default_gems.rb b/tool/test/test_sync_default_gems.rb index cf65173c3e887d..8f82dac1fcbd84 100755 --- a/tool/test/test_sync_default_gems.rb +++ b/tool/test/test_sync_default_gems.rb @@ -252,6 +252,23 @@ def test_minimize_dependencies MAKE end + def test_mark_as_prerelease + File.write("src/lib/common.rb", %[VERSION = "1.2.3"\n]) + Dir.chdir("src") do + assert_equal("1.2.3.dev", SyncDefaultGems.mark_as_prerelease(@target, Gem::Version.new("1.2.3"))) + end + assert_equal(%[VERSION = "1.2.3.dev"\n], File.read("src/lib/common.rb")) + end + + def test_mark_as_prerelease_undefined + out = capture_process_output_to([STDOUT]) do + Dir.chdir("src") do + assert_nil(SyncDefaultGems.mark_as_prerelease(@target, Gem::Version.new("1.2.3"))) + end + end + assert_match(/Cannot tell where/, out) + end + def test_unknown_repository assert_raise_with_message(RuntimeError, /unknown/) do SyncDefaultGems::REPOSITORIES["not-exist"] diff --git a/transcode.c b/transcode.c index de363c9dcd5789..35e5b43dce9a15 100644 --- a/transcode.c +++ b/transcode.c @@ -1045,6 +1045,8 @@ rb_econv_open0(const char *sname, const char *dname, int ecflags) SIZED_FREE_N(entries, num_trans); return NULL; } + sname = entries[0]->sname; + dname = entries[num_trans-1]->dname; } ec = rb_econv_open_by_transcoder_entries(num_trans, entries);