1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

Hash#transform_values! ensures receiver modifiable in block [Bug #17736]

This commit is contained in:
Kenichi Kamiya 2021-03-22 14:10:52 +09:00 committed by GitHub
parent db0ad48309
commit 7d3fdfb27d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
Notes: git 2021-03-22 14:11:14 +09:00
Merged: https://github.com/ruby/ruby/pull/4302

Merged-By: nobu <nobu@ruby-lang.org>
2 changed files with 10 additions and 0 deletions

1
hash.c
View file

@ -3303,6 +3303,7 @@ transform_values_foreach_replace(st_data_t *key, st_data_t *value, st_data_t arg
{ {
VALUE new_value = rb_yield((VALUE)*value); VALUE new_value = rb_yield((VALUE)*value);
VALUE hash = (VALUE)argp; VALUE hash = (VALUE)argp;
rb_hash_modify(hash);
RB_OBJ_WRITE(hash, value, new_value); RB_OBJ_WRITE(hash, value, new_value);
return ST_CONTINUE; return ST_CONTINUE;
} }

View file

@ -1803,6 +1803,15 @@ class TestHash < Test::Unit::TestCase
x = @cls[a: 1, b: 2, c: 3] x = @cls[a: 1, b: 2, c: 3]
y = x.transform_values!.with_index {|v, i| "#{v}.#{i}" } y = x.transform_values!.with_index {|v, i| "#{v}.#{i}" }
assert_equal(%w(1.0 2.1 3.2), y.values_at(:a, :b, :c)) assert_equal(%w(1.0 2.1 3.2), y.values_at(:a, :b, :c))
x = @cls[a: 1, b: 2, c: 3, d: 4, e: 5, f: 6, g: 7, h: 8, i: 9, j: 10]
assert_raise(FrozenError) do
x.transform_values!() do |v|
x.freeze if v == 2
v.succ
end
end
assert_equal(@cls[a: 2, b: 2, c: 3, d: 4, e: 5, f: 6, g: 7, h: 8, i: 9, j: 10], x)
end end
def test_broken_hash_value def test_broken_hash_value