diff --git a/lib/debug/session.rb b/lib/debug/session.rb index 6fbce7f0e..a9358d7c0 100644 --- a/lib/debug/session.rb +++ b/lib/debug/session.rb @@ -1061,12 +1061,14 @@ def step_command type, arg else leave_subsession [:step, type, arg&.to_i] end - when /\Aback\z/, /\Areset\z/ + when /\A(back)\z/, /\A(back)\s+(\d+)\z/, /\A(reset)\z/ if type != :in @ui.puts "only `step #{arg}` is supported." :retry else - request_tc [:step, arg.to_sym] + type = $1.to_sym + iter = $2&.to_i + request_tc [:step, type, iter] end else @ui.puts "Unknown option: #{arg}" diff --git a/lib/debug/thread_client.rb b/lib/debug/thread_client.rb index 3aa91a659..64c21019c 100644 --- a/lib/debug/thread_client.rb +++ b/lib/debug/thread_client.rb @@ -890,11 +890,12 @@ def wait_next_action_ break when :back + iter = iter || 1 if @recorder&.can_step_back? unless @recorder.backup_frames @recorder.backup_frames = @target_frames end - @recorder.step_back + @recorder.step_back iter raise SuspendReplay else puts "Can not step back more." @@ -1201,8 +1202,11 @@ def enabled? @tp_recorder.enabled? end - def step_back - @index += 1 + def step_back iter + @index += iter + if @index > @log.size + @index = @log.size + end end def step_forward diff --git a/test/console/record_test.rb b/test/console/record_test.rb index bdd402576..5d59d52b0 100644 --- a/test/console/record_test.rb +++ b/test/console/record_test.rb @@ -139,6 +139,74 @@ def test_1629263892 end end + class StepBackWithNumWhileReplayTest < ConsoleTestCase + def program + <<~RUBY + 1| def a + 2| return b() + 3| end + 4| + 5| def b + 6| return 1 + 7| end + 8| + 9| a() + 10| a() + 11| a() + 12| a() + 13| a() + 14| a() + RUBY + end + + def test_1663648816 + debug_code(program) do + type 'b 11' + type 'record on' + type 'c' + assert_line_num 11 + type 'step back 2' # multiple whitespaces + assert_line_num 6 + type 'step back 2' + assert_line_num 10 + type 'q!' + end + end + end + + class StepBackWhenNumberIsLargetThanLogIndex < ConsoleTestCase + def program + <<~RUBY + 1| def a + 2| return b() + 3| end + 4| + 5| def b + 6| return 1 + 7| end + 8| + 9| a() + 10| a() + 11| a() + 12| a() + 13| a() + 14| a() + RUBY + end + + def test_1663648816 + debug_code(program) do + type 'b 11' + type 'record on' + type 'c' + assert_line_num 11 + type 'step back 100' + assert_line_num 5 + type 'q!' + end + end + end + class RecordOnAfterStoppingOnceTest < ConsoleTestCase def program <<~RUBY