-
-
Notifications
You must be signed in to change notification settings - Fork 329
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix Array keep_if, delete_if, reject!, select! #2069
Conversation
226c11f
to
005b28b
Compare
opal/corelib/array.rb
Outdated
self.splice(i2, updated.length); | ||
} | ||
|
||
if (raised) throw raised; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
MRI aborts iteration once the error has been thrown:
[1,2,3].keep_if { |i| p i; raise 'a' }
1
# ...backtrace
RuntimeError (a)
So I guess this check-and-throw should be somewhere above (same for other methods)
opal/corelib/array.rb
Outdated
for (var i = 0, i2 = 0, length = self.length; i < length; i++) { | ||
try { | ||
value = Opal.yield1(block, self[i]) | ||
} catch(error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also I guess it may catch and re-throw Opal.breaker
and Opal.returner
and thus, potentially exit the outer method call
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From what I saw they're already managed by the compiler.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
compiler manages only what is written in Ruby (but catch/re-throw here is in JS). maybe I'm wrong, but does it handle break
and return
inside keep_if
? 👍 if so, but I'm afraid it swallows the initial throw Opal.returner
and re-raises it once the loop is done (MRI most probably does a hard return
that aborts the loop)
Also, I'm not sure if it's actually that important. I've never seen such code 😄
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
just out of curiosity, here's what I got:
opal:elia/fix-delete-if-keep-if ⤑ bin/opal -e'def a;4.times{|n| [1,2,3].delete_if { |i| p i; return }; p n => n};end; a' ~/C/opal
1
opal:elia/fix-delete-if-keep-if ⤑ ruby -e'def a;4.times{|n| [1,2,3].delete_if { |i| p i; return }; p n => n};end; a' ~/C/opal
1
opal:elia/fix-delete-if-keep-if ⤑ ~/C/opal
Match CRuby behavior when exceptions are raised in the block and about when the array is updated.
Should give better performance and smaller code size.
005b28b
to
1d6d262
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the review, I've updated the code to stop calling the block and behave just like MRI.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
Match CRuby behavior when exceptions are raised in the block and about
when the array is updated.
Fixes #2067