ruby-changes:65498
From: Kenichi <ko1@a...>
Date: Sat, 20 Mar 2021 20:46:28 +0900 (JST)
Subject: [ruby-changes:65498] 7954bb056b (master): Some Hash destructive methods ensure the receiver modifiable [Bug #17736]
https://git.ruby-lang.org/ruby.git/commit/?id=7954bb056b From 7954bb056be30e86c419fe3792064d28990a4999 Mon Sep 17 00:00:00 2001 From: Kenichi Kamiya <kachick1@g...> Date: Sat, 20 Mar 2021 19:35:36 +0900 Subject: Some Hash destructive methods ensure the receiver modifiable [Bug #17736] refs: * https://bugs.ruby-lang.org/issues/17736 * https://github.com/ruby/ruby/pull/4296 This commit aims to cover following methods * Hash#select! * Hash#filter! * Hash#keep_if * Hash#reject! * Hash#delete_if I think these are not all. --- * Ensure the receiver is modifiable or not * Assert the receiver is not modified --- hash.c | 2 ++ test/ruby/test_hash.rb | 42 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/hash.c b/hash.c index e9a3ca9..8f51f46 100644 --- a/hash.c +++ b/hash.c @@ -2476,6 +2476,7 @@ static int https://github.com/ruby/ruby/blob/trunk/hash.c#L2476 delete_if_i(VALUE key, VALUE value, VALUE hash) { if (RTEST(rb_yield_values(2, key, value))) { + rb_hash_modify(hash); return ST_DELETE; } return ST_CONTINUE; @@ -2705,6 +2706,7 @@ static int https://github.com/ruby/ruby/blob/trunk/hash.c#L2706 keep_if_i(VALUE key, VALUE value, VALUE hash) { if (!RTEST(rb_yield_values(2, key, value))) { + rb_hash_modify(hash); return ST_DELETE; } return ST_CONTINUE; diff --git a/test/ruby/test_hash.rb b/test/ruby/test_hash.rb index 3458053..849fd3a 100644 --- a/test/ruby/test_hash.rb +++ b/test/ruby/test_hash.rb @@ -439,6 +439,15 @@ class TestHash < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_hash.rb#L439 true } assert_equal(base.size, n) + + h = base.dup + assert_raise(FrozenError) do + h.delete_if do + h.freeze + true + end + end + assert_equal(base.dup, h) end def test_keep_if @@ -446,6 +455,14 @@ class TestHash < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_hash.rb#L455 assert_equal({3=>4,5=>6}, h.keep_if {|k, v| k + v >= 7 }) h = @cls[1=>2,3=>4,5=>6] assert_equal({1=>2,3=>4,5=>6}, h.keep_if{true}) + h = @cls[1=>2,3=>4,5=>6] + assert_raise(FrozenError) do + h.keep_if do + h.freeze + false + end + end + assert_equal(@cls[1=>2,3=>4,5=>6], h) end def test_compact @@ -743,6 +760,15 @@ class TestHash < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_hash.rb#L760 h = base.dup assert_equal(h3, h.reject! {|k,v| v }) assert_equal(h3, h) + + h = base.dup + assert_raise(FrozenError) do + h.reject! do + h.freeze + true + end + end + assert_equal(base.dup, h) end def test_replace @@ -1046,6 +1072,14 @@ class TestHash < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_hash.rb#L1072 assert_equal({3=>4,5=>6}, h) h = @cls[1=>2,3=>4,5=>6] assert_equal(nil, h.select!{true}) + h = @cls[1=>2,3=>4,5=>6] + assert_raise(FrozenError) do + h.select! do + h.freeze + false + end + end + assert_equal(@cls[1=>2,3=>4,5=>6], h) end def test_slice @@ -1098,6 +1132,14 @@ class TestHash < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_hash.rb#L1132 assert_equal({3=>4,5=>6}, h) h = @cls[1=>2,3=>4,5=>6] assert_equal(nil, h.filter!{true}) + h = @cls[1=>2,3=>4,5=>6] + assert_raise(FrozenError) do + h.filter! do + h.freeze + false + end + end + assert_equal(@cls[1=>2,3=>4,5=>6], h) end def test_clear2 -- cgit v1.1 -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/