Skip to content
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

🐛 Support displaying variables with non-unicode data #758

Merged
merged 3 commits into from
Oct 25, 2022
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
8 changes: 7 additions & 1 deletion lib/debug/server_dap.rb
Original file line number Diff line number Diff line change
Expand Up @@ -687,7 +687,13 @@ def register_vars vars, tid
class ThreadClient
def value_inspect obj
# TODO: max length should be configuarable?
DEBUGGER__.safe_inspect obj, short: true, max_length: 4 * 1024
str = DEBUGGER__.safe_inspect obj, short: true, max_length: 4 * 1024

if str.encoding == Encoding::UTF_8
str.scrub
else
str.encode(Encoding::UTF_8, invalid: :replace, undef: :replace)
end
end

def process_dap args
Expand Down
59 changes: 59 additions & 0 deletions test/protocol/binary_data_dap_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# frozen_string_literal: true

require_relative '../support/protocol_test_case'

module DEBUGGER__
class BinaryDataDAPTest < ProtocolTestCase
def test_binary_data_gets_encoded
program = <<~RUBY
1| class PassthroughInspect
2| def initialize(data)
3| @data = data
4| end
5|
6| def inspect
7| @data
8| end
9| end
10|
11| with_binary_data = PassthroughInspect.new([8, 200, 1].pack('CCC'))
12| with_binary_data
RUBY
run_protocol_scenario(program, cdp: false) do
req_add_breakpoint 12
req_continue
assert_locals_result(
[
{ name: '%self', value: 'main', type: 'Object' },
{ name: 'with_binary_data', value: [8, 200, 1].pack('CCC').encode(Encoding::UTF_8, invalid: :replace, undef: :replace), type: 'PassthroughInspect' }
]
)
req_terminate_debuggee
end
end

def test_frozen_strings_are_supported
# When `inspect` fails, `DEBUGGER__.safe_inspect` returns a frozen error message
# Just returning a frozen string wouldn't work, as `DEBUGGER__.safe_inspect` constructs
# the return value with a buffer.
program = <<~RUBY
1| class Uninspectable
2| def inspect; raise 'error'; end
3| end
4| broken_inspect = Uninspectable.new
5| broken_inspect
RUBY
run_protocol_scenario(program, cdp: false) do
req_add_breakpoint 5
req_continue
assert_locals_result(
[
{ name: '%self', value: 'main', type: 'Object' },
{ name: 'broken_inspect', value: /#inspect raises/, type: 'Uninspectable' }
]
)
req_terminate_debuggee
end
end
end
end