summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog5
-rw-r--r--NEWS2
-rw-r--r--ext/-test-/hash/delete.c14
-rw-r--r--ext/-test-/hash/extconf.rb7
-rw-r--r--ext/-test-/hash/init.c11
-rw-r--r--hash.c14
-rw-r--r--test/-ext-/hash/test_delete.rb19
7 files changed, 65 insertions, 7 deletions
diff --git a/ChangeLog b/ChangeLog
index b0af89a968..250a8c7b2b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+Thu Oct 23 21:42:54 2014 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * hash.c (rb_hash_delete): now does not call the block given to
+ the current method. [ruby-core:65861] [Bug #10413]
+
Thu Oct 23 19:13:26 2014 Nobuyoshi Nakada <nobu@ruby-lang.org>
* vm_method.c (rb_method_entry_make): warn redefinition only for
diff --git a/NEWS b/NEWS
index ee0510bdb9..158545c0a7 100644
--- a/NEWS
+++ b/NEWS
@@ -289,6 +289,8 @@ with all sufficient information, see the ChangeLog file.
* RUBY_INTERNAL_EVENT_GC_EXIT
r47528
+* rb_hash_delete() now does not call the block given to the current method.
+
=== Build system updates
* jemalloc is optionally supported via `./configure --with-jemalloc`
diff --git a/ext/-test-/hash/delete.c b/ext/-test-/hash/delete.c
new file mode 100644
index 0000000000..de54e3694f
--- /dev/null
+++ b/ext/-test-/hash/delete.c
@@ -0,0 +1,14 @@
+#include "ruby.h"
+
+static VALUE
+hash_delete(VALUE hash, VALUE key)
+{
+ VALUE ret = rb_hash_delete(hash, key);
+ return ret == Qundef ? Qfalse : Qtrue;
+}
+
+void
+Init_delete(VALUE klass)
+{
+ rb_define_method(klass, "delete", hash_delete, 1);
+}
diff --git a/ext/-test-/hash/extconf.rb b/ext/-test-/hash/extconf.rb
new file mode 100644
index 0000000000..9d4ef4f935
--- /dev/null
+++ b/ext/-test-/hash/extconf.rb
@@ -0,0 +1,7 @@
+$INCFLAGS << " -I$(topdir) -I$(top_srcdir)"
+$srcs = Dir[File.join($srcdir, "*.{#{SRC_EXT.join(%q{,})}}")]
+inits = $srcs.map {|s| File.basename(s, ".*")}
+inits.delete("init")
+inits.map! {|s|"X(#{s})"}
+$defs << "-DTEST_INIT_FUNCS(X)=\"#{inits.join(' ')}\""
+create_makefile("-test-/hash")
diff --git a/ext/-test-/hash/init.c b/ext/-test-/hash/init.c
new file mode 100644
index 0000000000..9f6cbde652
--- /dev/null
+++ b/ext/-test-/hash/init.c
@@ -0,0 +1,11 @@
+#include "ruby.h"
+
+#define init(n) {void Init_##n(VALUE klass); Init_##n(klass);}
+
+void
+Init_hash(void)
+{
+ VALUE mBug = rb_define_module("Bug");
+ VALUE klass = rb_define_class_under(mBug, "Hash", rb_cHash);
+ TEST_INIT_FUNCS(init);
+}
diff --git a/hash.c b/hash.c
index a150f935b2..4933205d67 100644
--- a/hash.c
+++ b/hash.c
@@ -972,8 +972,8 @@ rb_hash_index(VALUE hash, VALUE value)
return rb_hash_key(hash, value);
}
-static VALUE
-rb_hash_delete_key(VALUE hash, VALUE key)
+VALUE
+rb_hash_delete(VALUE hash, VALUE key)
{
st_data_t ktmp = (st_data_t)key, val;
@@ -1008,13 +1008,13 @@ rb_hash_delete_key(VALUE hash, VALUE key)
*
*/
-VALUE
-rb_hash_delete(VALUE hash, VALUE key)
+static VALUE
+rb_hash_delete_m(VALUE hash, VALUE key)
{
VALUE val;
rb_hash_modify_check(hash);
- val = rb_hash_delete_key(hash, key);
+ val = rb_hash_delete(hash, key);
if (val != Qundef) return val;
if (rb_block_given_p()) {
return rb_yield(key);
@@ -1066,7 +1066,7 @@ rb_hash_shift(VALUE hash)
else {
rb_hash_foreach(hash, shift_i_safe, (VALUE)&var);
if (var.key != Qundef) {
- rb_hash_delete_key(hash, var.key);
+ rb_hash_delete(hash, var.key);
return rb_assoc_new(var.key, var.val);
}
}
@@ -3881,7 +3881,7 @@ Init_Hash(void)
rb_define_method(rb_cHash,"values_at", rb_hash_values_at, -1);
rb_define_method(rb_cHash,"shift", rb_hash_shift, 0);
- rb_define_method(rb_cHash,"delete", rb_hash_delete, 1);
+ rb_define_method(rb_cHash,"delete", rb_hash_delete_m, 1);
rb_define_method(rb_cHash,"delete_if", rb_hash_delete_if, 0);
rb_define_method(rb_cHash,"keep_if", rb_hash_keep_if, 0);
rb_define_method(rb_cHash,"select", rb_hash_select, 0);
diff --git a/test/-ext-/hash/test_delete.rb b/test/-ext-/hash/test_delete.rb
new file mode 100644
index 0000000000..d4f2023e75
--- /dev/null
+++ b/test/-ext-/hash/test_delete.rb
@@ -0,0 +1,19 @@
+require 'test/unit'
+require '-test-/hash'
+
+class TestHash < Test::Unit::TestCase
+ class TestDelete < Test::Unit::TestCase
+ def test_delete
+ hash = Bug::Hash.new
+ hash[1] = 2
+ called = false
+ assert_equal 1, hash.size
+ assert_equal true, hash.delete(1) {called = true}
+ assert_equal false, called, "block called"
+ assert_equal 0, hash.size
+ assert_equal false, hash.delete(1) {called = true}
+ assert_equal false, called, "block called"
+ assert_equal 0, hash.size
+ end
+ end
+end