readapt 1.4.4 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/rspec.yml +38 -0
  3. data/.gitignore +16 -16
  4. data/.rspec +2 -2
  5. data/.travis.yml +19 -19
  6. data/CHANGELOG.md +103 -100
  7. data/Gemfile +4 -4
  8. data/LICENSE.txt +21 -21
  9. data/README.md +37 -37
  10. data/Rakefile +14 -14
  11. data/bin/console +14 -14
  12. data/bin/setup +8 -8
  13. data/exe/readapt +5 -5
  14. data/ext/readapt/breakpoints.c +83 -83
  15. data/ext/readapt/breakpoints.h +11 -11
  16. data/ext/readapt/extconf.rb +0 -0
  17. data/ext/readapt/frame.c +137 -137
  18. data/ext/readapt/frame.h +17 -17
  19. data/ext/readapt/inspector.c +51 -51
  20. data/ext/readapt/inspector.h +8 -8
  21. data/ext/readapt/lookup_table.c +211 -211
  22. data/ext/readapt/lookup_table.h +30 -30
  23. data/ext/readapt/monitor.c +0 -0
  24. data/ext/readapt/monitor.h +0 -0
  25. data/ext/readapt/normalize.c +62 -62
  26. data/ext/readapt/normalize.h +7 -7
  27. data/ext/readapt/readapt.c +18 -18
  28. data/ext/readapt/stack.c +86 -86
  29. data/ext/readapt/stack.h +20 -20
  30. data/ext/readapt/threads.c +1 -1
  31. data/ext/readapt/threads.h +0 -0
  32. data/lib/readapt/adapter.rb +98 -98
  33. data/lib/readapt/breakpoint.rb +21 -21
  34. data/lib/readapt/data_reader.rb +62 -62
  35. data/lib/readapt/debugger.rb +227 -227
  36. data/lib/readapt/error.rb +63 -63
  37. data/lib/readapt/finder.rb +34 -34
  38. data/lib/readapt/frame.rb +40 -40
  39. data/lib/readapt/input.rb +7 -7
  40. data/lib/readapt/message/attach.rb +11 -11
  41. data/lib/readapt/message/base.rb +32 -32
  42. data/lib/readapt/message/configuration_done.rb +11 -11
  43. data/lib/readapt/message/continue.rb +15 -15
  44. data/lib/readapt/message/disconnect.rb +13 -13
  45. data/lib/readapt/message/evaluate.rb +19 -19
  46. data/lib/readapt/message/initialize.rb +21 -21
  47. data/lib/readapt/message/launch.rb +11 -11
  48. data/lib/readapt/message/next.rb +12 -12
  49. data/lib/readapt/message/pause.rb +11 -11
  50. data/lib/readapt/message/scopes.rb +26 -26
  51. data/lib/readapt/message/set_breakpoints.rb +25 -25
  52. data/lib/readapt/message/set_exception_breakpoints.rb +11 -11
  53. data/lib/readapt/message/stack_trace.rb +38 -38
  54. data/lib/readapt/message/step_in.rb +11 -11
  55. data/lib/readapt/message/step_out.rb +11 -11
  56. data/lib/readapt/message/threads.rb +18 -18
  57. data/lib/readapt/message/variables.rb +53 -53
  58. data/lib/readapt/message.rb +62 -62
  59. data/lib/readapt/monitor.rb +0 -0
  60. data/lib/readapt/output.rb +25 -25
  61. data/lib/readapt/references.rb +27 -27
  62. data/lib/readapt/server.rb +22 -22
  63. data/lib/readapt/shell.rb +104 -104
  64. data/lib/readapt/snapshot.rb +0 -0
  65. data/lib/readapt/thread.rb +20 -20
  66. data/lib/readapt/variable.rb +0 -0
  67. data/lib/readapt/version.rb +3 -3
  68. data/lib/readapt.rb +21 -21
  69. data/readapt.gemspec +39 -39
  70. metadata +8 -7
@@ -1,18 +1,18 @@
1
- # frozen_string_literal: true
2
-
3
- module Readapt
4
- module Message
5
- class Threads < Base
6
- def run
7
- set_body({
8
- threads: debugger.threads.map do |thr|
9
- {
10
- id: thr.id,
11
- name: thr.name
12
- }
13
- end
14
- })
15
- end
16
- end
17
- end
18
- end
1
+ # frozen_string_literal: true
2
+
3
+ module Readapt
4
+ module Message
5
+ class Threads < Base
6
+ def run
7
+ set_body({
8
+ threads: debugger.threads.map do |thr|
9
+ {
10
+ id: thr.id,
11
+ name: thr.name
12
+ }
13
+ end
14
+ })
15
+ end
16
+ end
17
+ end
18
+ end
@@ -1,53 +1,53 @@
1
- # frozen_string_literal: true
2
-
3
- module Readapt
4
- module Message
5
- class Variables < Base
6
- def run
7
- ref = arguments['variablesReference']
8
- frame = debugger.frame(ref)
9
- # @todo 1 is a magic number representing the toplevel binding (see
10
- # Message::Scopes)
11
- vars = if ref == 1
12
- global_variables.map do |gv|
13
- Variable.new(gv, eval(gv.to_s))
14
- end
15
- else
16
- if frame != Frame::NULL_FRAME && !frame.nil?
17
- frame.locals
18
- else
19
- obj = References.get(ref)
20
- result = []
21
- if obj.is_a?(Array)
22
- obj.each_with_index do |itm, idx|
23
- result.push Variable.new("[#{idx}]", itm)
24
- end
25
- elsif obj.is_a?(Hash)
26
- obj.each_pair do |idx, itm|
27
- result.push Variable.new("[#{idx}]", itm)
28
- end
29
- else
30
- obj.instance_variables.sort.each do |iv|
31
- result.push Variable.new(iv, obj.instance_variable_get(iv))
32
- end
33
- obj.class.class_variables.sort.each do |cv|
34
- result.push Variable.new(cv, obj.class.class_variable_get(cv))
35
- end
36
- end
37
- result
38
- end
39
- end
40
- set_body({
41
- variables: vars.map do |var|
42
- {
43
- name: var.name,
44
- value: var.value,
45
- type: var.type,
46
- variablesReference: var.reference
47
- }
48
- end
49
- })
50
- end
51
- end
52
- end
53
- end
1
+ # frozen_string_literal: true
2
+
3
+ module Readapt
4
+ module Message
5
+ class Variables < Base
6
+ def run
7
+ ref = arguments['variablesReference']
8
+ frame = debugger.frame(ref)
9
+ # @todo 1 is a magic number representing the toplevel binding (see
10
+ # Message::Scopes)
11
+ vars = if ref == 1
12
+ global_variables.map do |gv|
13
+ Variable.new(gv, eval(gv.to_s))
14
+ end
15
+ else
16
+ if frame != Frame::NULL_FRAME && !frame.nil?
17
+ frame.locals
18
+ else
19
+ obj = References.get(ref)
20
+ result = []
21
+ if obj.is_a?(Array)
22
+ obj.each_with_index do |itm, idx|
23
+ result.push Variable.new("[#{idx}]", itm)
24
+ end
25
+ elsif obj.is_a?(Hash)
26
+ obj.each_pair do |idx, itm|
27
+ result.push Variable.new("[#{idx}]", itm)
28
+ end
29
+ else
30
+ obj.instance_variables.sort.each do |iv|
31
+ result.push Variable.new(iv, obj.instance_variable_get(iv))
32
+ end
33
+ obj.class.class_variables.sort.each do |cv|
34
+ result.push Variable.new(cv, obj.class.class_variable_get(cv))
35
+ end
36
+ end
37
+ result
38
+ end
39
+ end
40
+ set_body({
41
+ variables: vars.map do |var|
42
+ {
43
+ name: var.name,
44
+ value: var.value,
45
+ type: var.type,
46
+ variablesReference: var.reference
47
+ }
48
+ end
49
+ })
50
+ end
51
+ end
52
+ end
53
+ end
@@ -1,62 +1,62 @@
1
- # frozen_string_literal: true
2
-
3
- require 'readapt/message/base'
4
- require 'readapt/message/initialize'
5
- require 'readapt/message/launch'
6
- require 'readapt/message/set_breakpoints'
7
- require 'readapt/message/set_exception_breakpoints'
8
- require 'readapt/message/configuration_done'
9
- require 'readapt/message/threads'
10
- require 'readapt/message/stack_trace'
11
- require 'readapt/message/scopes'
12
- require 'readapt/message/continue'
13
- require 'readapt/message/variables'
14
- require 'readapt/message/next'
15
- require 'readapt/message/step_in'
16
- require 'readapt/message/step_out'
17
- require 'readapt/message/disconnect'
18
- require 'readapt/message/attach'
19
- require 'readapt/message/pause'
20
- require 'readapt/message/evaluate'
21
-
22
- module Readapt
23
- module Message
24
- @@messages = {}
25
- @@seq = 0
26
-
27
- def self.register name, klass
28
- @@messages[name] = klass
29
- end
30
-
31
- def self.process arguments, debugger
32
- klass = @@messages[arguments['command']]
33
- if klass.nil?
34
- STDERR.puts "Debugger received unrecognized command `#{arguments['command']}`"
35
- Message::Base.new(arguments, debugger)
36
- else
37
- message = klass.new(arguments['arguments'], debugger)
38
- message.run
39
- message
40
- end
41
- end
42
-
43
- register 'initialize', Message::Initialize
44
- register 'attach', Message::Attach
45
- register 'launch', Message::Launch
46
- register 'setBreakpoints', Message::SetBreakpoints
47
- register 'setExceptionBreakpoints', Message::SetExceptionBreakpoints
48
- register 'configurationDone', Message::ConfigurationDone
49
- register 'threads', Message::Threads
50
- register 'stackTrace', Message::StackTrace
51
- register 'scopes', Message::Scopes
52
- register 'continue', Message::Continue
53
- register 'variables', Message::Variables
54
- register 'next', Message::Next
55
- register 'stepIn', Message::StepIn
56
- register 'stepOut', Message::StepOut
57
- register 'disconnect', Message::Disconnect
58
- register 'pause', Message::Pause
59
- register 'evaluate', Message::Evaluate
60
- # register 'source', Message::Base # @todo Placeholder
61
- end
62
- end
1
+ # frozen_string_literal: true
2
+
3
+ require 'readapt/message/base'
4
+ require 'readapt/message/initialize'
5
+ require 'readapt/message/launch'
6
+ require 'readapt/message/set_breakpoints'
7
+ require 'readapt/message/set_exception_breakpoints'
8
+ require 'readapt/message/configuration_done'
9
+ require 'readapt/message/threads'
10
+ require 'readapt/message/stack_trace'
11
+ require 'readapt/message/scopes'
12
+ require 'readapt/message/continue'
13
+ require 'readapt/message/variables'
14
+ require 'readapt/message/next'
15
+ require 'readapt/message/step_in'
16
+ require 'readapt/message/step_out'
17
+ require 'readapt/message/disconnect'
18
+ require 'readapt/message/attach'
19
+ require 'readapt/message/pause'
20
+ require 'readapt/message/evaluate'
21
+
22
+ module Readapt
23
+ module Message
24
+ @@messages = {}
25
+ @@seq = 0
26
+
27
+ def self.register name, klass
28
+ @@messages[name] = klass
29
+ end
30
+
31
+ def self.process arguments, debugger
32
+ klass = @@messages[arguments['command']]
33
+ if klass.nil?
34
+ STDERR.puts "Debugger received unrecognized command `#{arguments['command']}`"
35
+ Message::Base.new(arguments, debugger)
36
+ else
37
+ message = klass.new(arguments['arguments'], debugger)
38
+ message.run
39
+ message
40
+ end
41
+ end
42
+
43
+ register 'initialize', Message::Initialize
44
+ register 'attach', Message::Attach
45
+ register 'launch', Message::Launch
46
+ register 'setBreakpoints', Message::SetBreakpoints
47
+ register 'setExceptionBreakpoints', Message::SetExceptionBreakpoints
48
+ register 'configurationDone', Message::ConfigurationDone
49
+ register 'threads', Message::Threads
50
+ register 'stackTrace', Message::StackTrace
51
+ register 'scopes', Message::Scopes
52
+ register 'continue', Message::Continue
53
+ register 'variables', Message::Variables
54
+ register 'next', Message::Next
55
+ register 'stepIn', Message::StepIn
56
+ register 'stepOut', Message::StepOut
57
+ register 'disconnect', Message::Disconnect
58
+ register 'pause', Message::Pause
59
+ register 'evaluate', Message::Evaluate
60
+ # register 'source', Message::Base # @todo Placeholder
61
+ end
62
+ end
File without changes
@@ -1,25 +1,25 @@
1
- module Readapt
2
- module Output
3
- class << self
4
- attr_accessor :adapter
5
- end
6
-
7
- def receiving data
8
- send_event('output', {
9
- output: data.force_encoding('utf-8'),
10
- category: 'stdout'
11
- })
12
- end
13
-
14
- def send_event event, data
15
- obj = {
16
- type: 'event',
17
- event: event
18
- }
19
- obj[:body] = data unless data.nil?
20
- json = obj.to_json
21
- envelope = "Content-Length: #{json.bytesize}\r\n\r\n#{json}"
22
- Output.adapter.write envelope
23
- end
24
- end
25
- end
1
+ module Readapt
2
+ module Output
3
+ class << self
4
+ attr_accessor :adapter
5
+ end
6
+
7
+ def receiving data
8
+ send_event('output', {
9
+ output: data.force_encoding('utf-8'),
10
+ category: 'stdout'
11
+ })
12
+ end
13
+
14
+ def send_event event, data
15
+ obj = {
16
+ type: 'event',
17
+ event: event
18
+ }
19
+ obj[:body] = data unless data.nil?
20
+ json = obj.to_json
21
+ envelope = "Content-Length: #{json.bytesize}\r\n\r\n#{json}"
22
+ Output.adapter.write envelope
23
+ end
24
+ end
25
+ end
@@ -1,27 +1,27 @@
1
- module Readapt
2
- module References
3
- module_function
4
-
5
- @variable_reference_map = {}
6
- @reference_variable_map = {}
7
- @reference_id = 1000
8
-
9
- def clear
10
- @variable_reference_map.clear
11
- @reference_variable_map.clear
12
- @reference_id = 1000
13
- end
14
-
15
- def identify object
16
- return @variable_reference_map[object] if @variable_reference_map.has_key?(object)
17
- @reference_id += 1
18
- @variable_reference_map[object] = @reference_id
19
- @reference_variable_map[@reference_id] = object
20
- @reference_id
21
- end
22
-
23
- def get id
24
- @reference_variable_map[id]
25
- end
26
- end
27
- end
1
+ module Readapt
2
+ module References
3
+ module_function
4
+
5
+ @variable_reference_map = {}
6
+ @reference_variable_map = {}
7
+ @reference_id = 1000
8
+
9
+ def clear
10
+ @variable_reference_map.clear
11
+ @reference_variable_map.clear
12
+ @reference_id = 1000
13
+ end
14
+
15
+ def identify object
16
+ return @variable_reference_map[object] if @variable_reference_map.has_key?(object)
17
+ @reference_id += 1
18
+ @variable_reference_map[object] = @reference_id
19
+ @reference_variable_map[@reference_id] = object
20
+ @reference_id
21
+ end
22
+
23
+ def get id
24
+ @reference_variable_map[id]
25
+ end
26
+ end
27
+ end
@@ -1,22 +1,22 @@
1
- require 'securerandom'
2
- require 'stringio'
3
-
4
- module Readapt
5
- module Server
6
- class << self
7
- attr_accessor :target_in
8
- attr_accessor :target_pid
9
- end
10
-
11
- def opening
12
- Error.adapter = self
13
- Output.adapter = self
14
- end
15
-
16
- def receiving data
17
- Server.target_in.syswrite data
18
- rescue Errno::EPIPE, IOError
19
- close
20
- end
21
- end
22
- end
1
+ require 'securerandom'
2
+ require 'stringio'
3
+
4
+ module Readapt
5
+ module Server
6
+ class << self
7
+ attr_accessor :target_in
8
+ attr_accessor :target_pid
9
+ end
10
+
11
+ def opening
12
+ Error.adapter = self
13
+ Output.adapter = self
14
+ end
15
+
16
+ def receiving data
17
+ Server.target_in.syswrite data
18
+ rescue Errno::EPIPE, IOError
19
+ close
20
+ end
21
+ end
22
+ end
data/lib/readapt/shell.rb CHANGED
@@ -1,104 +1,104 @@
1
- require 'thor'
2
- require 'backport'
3
- require 'open3'
4
- require 'securerandom'
5
- require 'socket'
6
-
7
- module Readapt
8
- class Shell < Thor
9
- map %w[--version -v] => :version
10
-
11
- desc "--version, -v", "Print the version"
12
- def version
13
- puts Readapt::VERSION
14
- end
15
-
16
- desc 'socket', 'Run a DAP server over TCP'
17
- option :host, type: :string, aliases: :h, description: 'The server host', default: '127.0.0.1'
18
- option :port, type: :numeric, aliases: :p, description: 'The server port', default: 1234
19
- def socket
20
- machine = Backport::Machine.new
21
- machine.run do
22
- prepare_machine machine
23
- server = Backport::Server::Tcpip.new(host: options[:host], port: options[:port], adapter: Readapt::Server)
24
- machine.prepare server
25
- STDERR.puts "Readapt Debugger #{Readapt::VERSION} is listening HOST=#{options[:host]} PORT=#{options[:port]} PID=#{Process.pid}"
26
- end
27
- end
28
- map serve: :socket
29
-
30
- desc 'stdio', 'Run a DAP server over STDIO'
31
- def stdio
32
- machine = Backport::Machine.new
33
- machine.run do
34
- prepare_machine machine
35
- server = Backport::Server::Stdio.new(adapter: Readapt::Server)
36
- machine.prepare server
37
- end
38
- end
39
-
40
- desc 'target [PROCID]', 'Run a target process'
41
- def target procid = nil
42
- STDIN.binmode
43
- STDOUT.binmode
44
- STDERR.binmode
45
- STDOUT.sync = true
46
- STDERR.sync = true
47
- Readapt::Adapter.procid = procid
48
- machine = Backport::Machine.new
49
- Signal.trap("INT") do
50
- graceful_shutdown machine
51
- end
52
- Signal.trap("TERM") do
53
- graceful_shutdown machine
54
- end
55
- machine.run do
56
- debugger = Readapt::Debugger.new
57
- Readapt::Adapter.host debugger
58
- machine.prepare Backport::Server::Stdio.new(input: STDIN, output: STDERR, adapter: Readapt::Adapter)
59
- end
60
- end
61
-
62
- private
63
-
64
- # @param machine [Backport::Machine]
65
- # @return [void]
66
- def prepare_machine machine
67
- STDOUT.sync = true
68
- STDERR.sync = true
69
- Signal.trap("INT") do
70
- graceful_shutdown machine
71
- end
72
- Signal.trap("TERM") do
73
- graceful_shutdown machine
74
- end
75
- procid = SecureRandom.hex(8)
76
- Readapt::Error.procid = procid
77
- stdin, stdout, stderr, thr = Open3.popen3('ruby', $0, 'target', procid)
78
- stdin.sync = true
79
- stdout.sync = true
80
- stderr.sync = true
81
- stdin.binmode
82
- Readapt::Server.target_in = stdin
83
- Readapt::Server.target_pid = thr[:pid]
84
- output = Backport::Server::Stdio.new(input: stdout, output: stdin, adapter: Readapt::Output)
85
- error = Backport::Server::Stdio.new(input: stderr, output: stdin, adapter: Readapt::Error)
86
- machine.prepare output
87
- machine.prepare error
88
- at_exit do
89
- begin
90
- Process.kill 'KILL', thr[:pid]
91
- rescue Errno::ESRCH
92
- # Ignore
93
- end
94
- end
95
- end
96
-
97
- # @param machine [Backport::Machine]
98
- # @return [void]
99
- def graceful_shutdown machine
100
- machine.stop
101
- exit
102
- end
103
- end
104
- end
1
+ require 'thor'
2
+ require 'backport'
3
+ require 'open3'
4
+ require 'securerandom'
5
+ require 'socket'
6
+
7
+ module Readapt
8
+ class Shell < Thor
9
+ map %w[--version -v] => :version
10
+
11
+ desc "--version, -v", "Print the version"
12
+ def version
13
+ puts Readapt::VERSION
14
+ end
15
+
16
+ desc 'socket', 'Run a DAP server over TCP'
17
+ option :host, type: :string, aliases: :h, description: 'The server host', default: '127.0.0.1'
18
+ option :port, type: :numeric, aliases: :p, description: 'The server port', default: 1234
19
+ def socket
20
+ machine = Backport::Machine.new
21
+ machine.run do
22
+ prepare_machine machine
23
+ server = Backport::Server::Tcpip.new(host: options[:host], port: options[:port], adapter: Readapt::Server)
24
+ machine.prepare server
25
+ STDERR.puts "Readapt Debugger #{Readapt::VERSION} is listening HOST=#{options[:host]} PORT=#{options[:port]} PID=#{Process.pid}"
26
+ end
27
+ end
28
+ map serve: :socket
29
+
30
+ desc 'stdio', 'Run a DAP server over STDIO'
31
+ def stdio
32
+ machine = Backport::Machine.new
33
+ machine.run do
34
+ prepare_machine machine
35
+ server = Backport::Server::Stdio.new(adapter: Readapt::Server)
36
+ machine.prepare server
37
+ end
38
+ end
39
+
40
+ desc 'target [PROCID]', 'Run a target process'
41
+ def target procid = nil
42
+ STDIN.binmode
43
+ STDOUT.binmode
44
+ STDERR.binmode
45
+ STDOUT.sync = true
46
+ STDERR.sync = true
47
+ Readapt::Adapter.procid = procid
48
+ machine = Backport::Machine.new
49
+ Signal.trap("INT") do
50
+ graceful_shutdown machine
51
+ end
52
+ Signal.trap("TERM") do
53
+ graceful_shutdown machine
54
+ end
55
+ machine.run do
56
+ debugger = Readapt::Debugger.new
57
+ Readapt::Adapter.host debugger
58
+ machine.prepare Backport::Server::Stdio.new(input: STDIN, output: STDERR, adapter: Readapt::Adapter)
59
+ end
60
+ end
61
+
62
+ private
63
+
64
+ # @param machine [Backport::Machine]
65
+ # @return [void]
66
+ def prepare_machine machine
67
+ STDOUT.sync = true
68
+ STDERR.sync = true
69
+ Signal.trap("INT") do
70
+ graceful_shutdown machine
71
+ end
72
+ Signal.trap("TERM") do
73
+ graceful_shutdown machine
74
+ end
75
+ procid = SecureRandom.hex(8)
76
+ Readapt::Error.procid = procid
77
+ stdin, stdout, stderr, thr = Open3.popen3('ruby', $0, 'target', procid)
78
+ stdin.sync = true
79
+ stdout.sync = true
80
+ stderr.sync = true
81
+ stdin.binmode
82
+ Readapt::Server.target_in = stdin
83
+ Readapt::Server.target_pid = thr[:pid]
84
+ output = Backport::Server::Stdio.new(input: stdout, output: stdin, adapter: Readapt::Output)
85
+ error = Backport::Server::Stdio.new(input: stderr, output: stdin, adapter: Readapt::Error)
86
+ machine.prepare output
87
+ machine.prepare error
88
+ at_exit do
89
+ begin
90
+ Process.kill 'KILL', thr[:pid]
91
+ rescue Errno::ESRCH
92
+ # Ignore
93
+ end
94
+ end
95
+ end
96
+
97
+ # @param machine [Backport::Machine]
98
+ # @return [void]
99
+ def graceful_shutdown machine
100
+ machine.stop
101
+ exit
102
+ end
103
+ end
104
+ end
File without changes
@@ -1,20 +1,20 @@
1
- # frozen_string_literal: true
2
-
3
- require 'ostruct'
4
-
5
- module Readapt
6
- class Thread
7
- # @return [Symbol]
8
- attr_accessor :control
9
-
10
- # @return [String]
11
- def name
12
- @name ||= "Thread #{id}"
13
- end
14
-
15
- # # @return [Object]
16
- def object
17
- ObjectSpace._id2ref(thread_object_id)
18
- end
19
- end
20
- end
1
+ # frozen_string_literal: true
2
+
3
+ require 'ostruct'
4
+
5
+ module Readapt
6
+ class Thread
7
+ # @return [Symbol]
8
+ attr_accessor :control
9
+
10
+ # @return [String]
11
+ def name
12
+ @name ||= "Thread #{id}"
13
+ end
14
+
15
+ # # @return [Object]
16
+ def object
17
+ ObjectSpace._id2ref(thread_object_id)
18
+ end
19
+ end
20
+ end