Skip to content

Commit 87eea20

Browse files
committed
Fix Array #select! and #keep_if methods
1 parent 7bd0f12 commit 87eea20

File tree

2 files changed

+22
-7
lines changed

2 files changed

+22
-7
lines changed

CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,8 @@ Compatibility:
6868
* Fix `File.open` and support `flags` option (#2820, @andrykonchin).
6969
* Support writing to `RData.dfree` for native extensions (#2830, #2732, #2165, @eregon).
7070
* Fix `IO#write` and support multiple arguments with different encodings (#2829, @andrykonchin).
71-
* Fix `Array` methods `reject`, `reject!`, `inject`, `map`, `select`, `each_index` and handle a case when array is modified by a passed block like CRuby does (#2822, andrykonchin, @eregon).
71+
* Fix `Array` methods `reject`, `reject!`, `inject`, `map`, `select`, `each_index` and handle a case when array is modified by a passed block like CRuby does (#2822, @andrykonchin, @eregon).
72+
* Fix `Array` methods `select!` and `keep_if` and handle a case when exception is raised in a passed block properly (@andrykonchin).
7273

7374
Performance:
7475

src/main/ruby/truffleruby/core/array.rb

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -697,10 +697,8 @@ def join(sep=nil)
697697

698698
def keep_if(&block)
699699
return to_enum(:keep_if) { size } unless block_given?
700-
701-
Primitive.check_frozen self
702-
703-
Primitive.steal_array_storage(self, select(&block))
700+
select!(&block)
701+
self
704702
end
705703

706704
def last(n=undefined)
@@ -1205,8 +1203,24 @@ def select!(&block)
12051203

12061204
Primitive.check_frozen self
12071205

1208-
ary = select(&block)
1209-
Primitive.steal_array_storage(self, ary) unless size == ary.size
1206+
original_size = size
1207+
selected_size = 0
1208+
1209+
each_with_index do |e, i|
1210+
abnormal_termination = true
1211+
to_select = yield e
1212+
abnormal_termination = false
1213+
1214+
if to_select
1215+
self[selected_size] = e
1216+
selected_size += 1
1217+
end
1218+
ensure
1219+
self[selected_size..-1] = self[i..-1] if abnormal_termination
1220+
end
1221+
1222+
self[selected_size..-1] = []
1223+
self unless selected_size == original_size
12101224
end
12111225
alias_method :filter!, :select!
12121226

0 commit comments

Comments
 (0)