From 9e76c3c2639b0f030b617ffce4d4ca459939f565 Mon Sep 17 00:00:00 2001 From: st0012 Date: Sun, 13 Mar 2022 17:23:10 +0000 Subject: [PATCH] Adjust ThreadClient's frames management for nested subsession change (#558) --- lib/debug/thread_client.rb | 22 ++++++++++---- test/debug/break_test.rb | 61 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 78 insertions(+), 5 deletions(-) diff --git a/lib/debug/thread_client.rb b/lib/debug/thread_client.rb index 0ea605302..a97914549 100644 --- a/lib/debug/thread_client.rb +++ b/lib/debug/thread_client.rb @@ -85,7 +85,8 @@ def initialize id, q_evt, q_cmd, thr = Thread.current @is_management = false @id = id @thread = thr - @target_frames = nil + @frame_index_stack = [] + @frames_stack = [] @q_evt = q_evt @q_cmd = q_cmd @step_tp = nil @@ -102,19 +103,27 @@ def initialize id, q_evt, q_cmd, thr = Thread.current end def target_frames - @target_frames + @frames_stack.last end def set_target_frames(frames) - @target_frames = frames + @frames_stack << frames + end + + def pop_target_frames + @frames_stack.pop end def current_frame_index - @current_frame_index + @frame_index_stack.last end def set_current_frame_index(i) - @current_frame_index = i + @frame_index_stack << i + end + + def pop_current_frame_index + @frame_index_stack.pop end def deactivate @@ -305,6 +314,9 @@ def suspend event, tp = nil, bp: nil, sig: nil, postmortem_frames: nil, replay_f end wait_next_action + ensure + pop_target_frames + pop_current_frame_index end def replay_suspend diff --git a/test/debug/break_test.rb b/test/debug/break_test.rb index 34f35ac93..2686463e9 100644 --- a/test/debug/break_test.rb +++ b/test/debug/break_test.rb @@ -722,4 +722,65 @@ def test_the_path_option_supersede_skip_path_config end end end + + class NestedBreakTest < TestCase + def program + <<~RUBY + 1| class Foo + 2| def self.bar(num) + 3| num + 4| end + 5| end + 6| + 7| a = 10 + 8| binding.b + RUBY + end + + if RUBY_VERSION >= "3.1.0" + def test_method_breakpoint_can_be_triggered_inside_another_breakpoint + debug_code(program) do + type "break Foo.bar" + type "c" + + # stops at the first breakpoint + assert_line_num(8) + + # enters the second breakpoint + type "Foo.bar(a)" + assert_line_num(3) + type "num + 10" + assert_line_text(/20/) + type "c" + + # returns to the first breakpoint + assert_line_num(8) + type "a + 100" + assert_line_text(/110/) + + type "c" + end + end + else + def test_nested_breakpoint_will_be_ignored + debug_code(program) do + type "break Foo.bar" + type "c" + + # stops at the first breakpoint + assert_line_num(8) + + # doesn't enter the another subsession + type "Foo.bar(a)" + + # returns to the first breakpoint + assert_line_num(8) + type "a + 100" + assert_line_text(/110/) + + type "c" + end + end + end + end end