diff options
| author | nagachika <nagachika@ruby-lang.org> | 2024-02-25 18:29:16 +0900 |
|---|---|---|
| committer | nagachika <nagachika@ruby-lang.org> | 2024-02-25 18:29:16 +0900 |
| commit | 5e4606423da96c2e26b00981c22bddfce0d970bf (patch) | |
| tree | da97da4f6c496095f0436cdc8ed0480e41a496d9 | |
| parent | 1b9ff146e38c348519434754e0466352b8b25c50 (diff) | |
merge revision(s) f15123c34ce80f3928612befe2a9aaf4c9d27fda: [Backport #18743]
Fix stack trace for rescued StopIteration
---
enumerator.c | 15 +++++++++++++--
test/ruby/test_enumerator.rb | 20 ++++++++++++++++++++
2 files changed, 33 insertions(+), 2 deletions(-)
| -rw-r--r-- | enumerator.c | 15 | ||||
| -rw-r--r-- | test/ruby/test_enumerator.rb | 20 | ||||
| -rw-r--r-- | version.h | 2 |
3 files changed, 34 insertions, 3 deletions
diff --git a/enumerator.c b/enumerator.c index f6b3aae1f7..d587b63d32 100644 --- a/enumerator.c +++ b/enumerator.c @@ -164,7 +164,10 @@ static VALUE sym_each, sym_cycle, sym_yield; static VALUE lazy_use_super_method; +extern ID ruby_static_id_cause; + #define id_call idCall +#define id_cause ruby_static_id_cause #define id_each idEach #define id_eqq idEqq #define id_initialize idInitialize @@ -807,8 +810,16 @@ get_next_values(VALUE obj, struct enumerator *e) { VALUE curr, vs; - if (e->stop_exc) - rb_exc_raise(e->stop_exc); + if (e->stop_exc) { + VALUE exc = e->stop_exc; + VALUE result = rb_attr_get(exc, id_result); + VALUE mesg = rb_attr_get(exc, idMesg); + if (!NIL_P(mesg)) mesg = rb_str_dup(mesg); + VALUE stop_exc = rb_exc_new_str(rb_eStopIteration, mesg); + rb_ivar_set(stop_exc, id_cause, exc); + rb_ivar_set(stop_exc, id_result, result); + rb_exc_raise(stop_exc); + } curr = rb_fiber_current(); diff --git a/test/ruby/test_enumerator.rb b/test/ruby/test_enumerator.rb index 010c1e4969..bbaa91b703 100644 --- a/test/ruby/test_enumerator.rb +++ b/test/ruby/test_enumerator.rb @@ -244,6 +244,26 @@ class TestEnumerator < Test::Unit::TestCase assert_equal(res, exc.result) end + def test_stopiteration_rescue + e = [1].each + res = e.each {} + e.next + exc0 = assert_raise(StopIteration) { e.peek } + assert_include(exc0.backtrace.first, "test_enumerator.rb:#{__LINE__-1}:") + assert_nil(exc0.cause) + assert_equal(res, exc0.result) + + exc1 = assert_raise(StopIteration) { e.next } + assert_include(exc1.backtrace.first, "test_enumerator.rb:#{__LINE__-1}:") + assert_same(exc0, exc1.cause) + assert_equal(res, exc1.result) + + exc2 = assert_raise(StopIteration) { e.next } + assert_include(exc2.backtrace.first, "test_enumerator.rb:#{__LINE__-1}:") + assert_same(exc0, exc2.cause) + assert_equal(res, exc2.result) + end + def test_next_values o = Object.new def o.each @@ -11,7 +11,7 @@ # define RUBY_VERSION_MINOR RUBY_API_VERSION_MINOR #define RUBY_VERSION_TEENY 3 #define RUBY_RELEASE_DATE RUBY_RELEASE_YEAR_STR"-"RUBY_RELEASE_MONTH_STR"-"RUBY_RELEASE_DAY_STR -#define RUBY_PATCHLEVEL 158 +#define RUBY_PATCHLEVEL 159 #include "ruby/version.h" #include "ruby/internal/abi.h" |
