Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions lib/debug/thread_client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -340,10 +340,20 @@ def instance_eval_for_cmethod frame_self, src
frame_self.instance_eval(src)
end

SPECIAL_LOCALS = [
[:raised_exception, "_raised_"],
[:return_value, "_returned_"],
]

def frame_eval src, re_raise: false
@success_last_eval = false

b = current_frame&.eval_binding || TOPLEVEL_BINDING
b = b.dup

SPECIAL_LOCALS.each do |m, local_name|
b.local_variable_set(local_name, current_frame.send(m))
end

result = if b
f, _l = b.source_location
Expand Down
89 changes: 89 additions & 0 deletions test/debug/debugger_local_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
# frozen_string_literal: truk

require_relative '../support/test_case'

module DEBUGGER__
class DebuggerLocalsTest < TestCase
class RaisedTest < TestCase
def program
<<~RUBY
1| _rescued_ = 1111
2| foo rescue nil
3|
4| # check repl variable doesn't leak to the program
5| result = _rescued_ * 2
6| binding.b
RUBY
end

def test_raised_is_accessible_from_repl
debug_code(program) do
type "catch Exception"
type "c"
type "_raised_"
assert_line_text(/#<NameError: undefined local variable or method `foo' for main:Object/)
type "c"
type "result"
assert_line_text(/2222/)
type "c"
end
end

def test_raised_is_accessible_from_command
debug_code(program) do
type "catch Exception pre: p _raised_"
type "c"
assert_line_text(/#<NameError: undefined local variable or method `foo' for main:Object/)
type "c"
type "result"
assert_line_text(/2222/)
type "c"
end
end
end

class ReturnedTest < TestCase
def program
<<~RUBY
1| _returned_ = 1111
2|
3| def foo
4| "foo"
5| end
6|
7| foo
8|
9| # check repl variable doesn't leak to the program
10| result = _returned_ * 2
11|
12| binding.b
RUBY
end

def test_returned_is_accessible_from_repl
debug_code(program) do
type "b 5"
type "c"
type "_returned_ + 'bar'"
assert_line_text(/"foobar"/)
type "c"
type "result"
assert_line_text(/2222/)
type "q!"
end
end

def test_returned_is_accessible_from_command
debug_code(program) do
type "b 5 pre: p _returned_ + 'bar'"
type "c"
assert_line_text(/"foobar"/)
type "c"
type "result"
assert_line_text(/2222/)
type "q!"
end
end
end
end
end