ruby-breakpoint 0.5.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.
- data/COPYING +56 -0
- data/GPL +340 -0
- data/Manifest +35 -0
- data/NEWS +18 -0
- data/README +43 -0
- data/TODO +31 -0
- data/bin/breakpoint_client +214 -0
- data/doc/classes/Binding.html +221 -0
- data/doc/classes/Breakpoint.html +540 -0
- data/doc/classes/Breakpoint/CommandBundle.html +207 -0
- data/doc/classes/Breakpoint/CommandBundle/Client.html +201 -0
- data/doc/classes/Breakpoint/FailedAssertError.html +118 -0
- data/doc/created.rid +1 -0
- data/doc/files/COPYING.html +163 -0
- data/doc/files/NEWS.html +135 -0
- data/doc/files/README.html +154 -0
- data/doc/files/TODO.html +162 -0
- data/doc/files/lib/binding_of_caller_rb.html +101 -0
- data/doc/files/lib/breakpoint_rb.html +202 -0
- data/doc/fr_class_index.html +31 -0
- data/doc/fr_file_index.html +32 -0
- data/doc/fr_method_index.html +38 -0
- data/doc/index.html +24 -0
- data/doc/rdoc-style.css +208 -0
- data/lib/binding_of_caller.rb +80 -0
- data/lib/breakpoint.rb +547 -0
- data/setup.rb +1360 -0
- metadata +82 -0
data/README
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
= ruby-breakpoint 0.5.0 README
|
2
|
+
|
3
|
+
ruby-breakpoint lets you inspect and modify state at run time. This allows you
|
4
|
+
to diagnose bugs, patch
|
5
|
applications and more all via IRB by simply doing a
|
6
|
+
method call at the place you want to investigate.
|
7
|
+
|
8
|
+
ruby-breakpoint is integrated into the popular RubyOnRails and Nitro web
|
9
|
+
development frameworks. In the past it has also been a part of the Ruby
|
10
|
+
dev-utils Project.
|
11
|
+
|
12
|
+
ruby-breakpoint is available from http://ruby-breakpoint.rubyforge.org/ --
|
13
|
+
that web site also is a good place for discussing new features, filing bug
|
14
|
+
reports and so on.
|
15
|
+
|
16
|
+
See the NEWS file for the changes that were done in this release.
|
17
|
+
|
18
|
+
|
19
|
+
== Requirements
|
20
|
+
|
21
|
+
* Ruby >= 1.8.2
|
22
|
+
* DRb, IRB (usually shipped with Ruby, but not on Debian)
|
23
|
+
|
24
|
+
|
25
|
+
== Installation
|
26
|
+
|
27
|
+
De-compress archive and enter its top directory. Then type:
|
28
|
+
|
29
|
+
($ su)
|
30
|
+
# ruby setup.rb
|
31
|
+
|
32
|
+
These simple step installs this program under the default location of Ruby
|
33
|
+
libraries. You can also install files into your favorite directory by supplying
|
34
|
+
setup.rb some options. Try "ruby setup.rb --help".
|
35
|
+
|
36
|
+
|
37
|
+
== License
|
38
|
+
|
39
|
+
Dual licensed under GPL and Ruby's custom license. See COPYING.
|
40
|
+
|
41
|
+
|
42
|
+
== Author
|
43
|
+
|
44
|
+
Florian Gross, flgr@ccan.de
|
data/TODO
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
= TODO
|
2
|
+
|
3
|
+
* Factor out remote breakpoint support to a separate file so it can be loaded
|
4
|
+
on-demand. This would allow the local breakpoint functionality to work even
|
5
|
+
when DRb is not available. (E.g. on Debian)
|
6
|
+
|
7
|
+
= Done
|
8
|
+
|
9
|
+
* Do further research on the write SecurityError.
|
10
|
+
See ruby-core for more information.
|
11
|
+
* This seems to have been a bug in Ruby 1.8.1 and early snapshots in Ruby 1.8.2.
|
12
|
+
The problem can be fixed by updating to a more current Ruby. More information
|
13
|
+
regarding this is available at the Wiki:
|
14
|
+
|
15
|
+
http://ruby-breakpoint.rubyforge.org/wiki/wiki.pl?FrequentlyAskedQuestions
|
16
|
+
|
17
|
+
* Find out whether we need to add Windows and Linux wrappers to the bin/ directory
|
18
|
+
* This is handled correctly by RubyGems. setup.rb only copies the .rb file to a
|
19
|
+
suitable directory, but that should work in the usual case.
|
20
|
+
|
21
|
+
* breakpoint_client needs logic for detecting the default client uri based on the
|
22
|
+
server uri:
|
23
|
+
* drbunix:/foo/bar => drbunix:#{File.join(Dir.tmpdir, "#{random}.breakpoint")}
|
24
|
+
(require 'tmpdir')
|
25
|
+
* druby://localhost:port => druby://localhost:#{rand_port}
|
26
|
+
|
27
|
+
* Mention available ressources (especially the FAQ) in breakpoint_client --help
|
28
|
+
|
29
|
+
* Document drbunix:/ uris and how they are more secure than druby:// with ACLs.
|
30
|
+
Suggest that this be used in environments where there are lots of users sharing
|
31
|
+
the same system. (E.g. web hosters)
|
@@ -0,0 +1,214 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'breakpoint'
|
4
|
+
require 'optparse'
|
5
|
+
require 'timeout'
|
6
|
+
require 'tmpdir'
|
7
|
+
|
8
|
+
Options = {
|
9
|
+
:ClientURI => nil,
|
10
|
+
:ServerURI => "druby://localhost:42531",
|
11
|
+
:RetryDelay => 3,
|
12
|
+
:Permanent => false,
|
13
|
+
:Verbose => false
|
14
|
+
}
|
15
|
+
|
16
|
+
ARGV.options do |opts|
|
17
|
+
script_name = File.basename($0)
|
18
|
+
opts.banner = [
|
19
|
+
"Usage: ruby #{script_name} [Options] [server uri]",
|
20
|
+
"",
|
21
|
+
"This tool lets you connect to a breakpoint service ",
|
22
|
+
"which was started via Breakpoint.activate_drb.",
|
23
|
+
"",
|
24
|
+
"The server uri defaults to druby://localhost:42531",
|
25
|
+
"",
|
26
|
+
"Having trouble or need help?",
|
27
|
+
"* Homepage: http://ruby-breakpoint.rubyforge.org/ (has FAQ!)",
|
28
|
+
"* Author: Florian Gross, flgr@ccan.de (Read homepage first!)"
|
29
|
+
].join("\n")
|
30
|
+
|
31
|
+
opts.separator ""
|
32
|
+
|
33
|
+
opts.on("-c", "--client-uri=uri",
|
34
|
+
"Run the client on the specified uri.",
|
35
|
+
"This can be used to specify the port",
|
36
|
+
"that the client uses to allow for back",
|
37
|
+
"connections from the server.",
|
38
|
+
"Default: Find a good URI automatically.",
|
39
|
+
"Example: -c druby://localhost:12345"
|
40
|
+
) { |Options[:ClientURI]| }
|
41
|
+
|
42
|
+
opts.on("-s", "--server-uri=uri",
|
43
|
+
"Connect to the server specified at the",
|
44
|
+
"specified uri.",
|
45
|
+
"Default: druby://localhost:42531"
|
46
|
+
) { |Options[:ServerURI]| }
|
47
|
+
|
48
|
+
opts.on("-R", "--retry-delay=delay", Integer,
|
49
|
+
"Automatically try to reconnect to the",
|
50
|
+
"server after delay seconds when the",
|
51
|
+
"connection failed or timed out.",
|
52
|
+
"A value of 0 disables automatical",
|
53
|
+
"reconnecting completely.",
|
54
|
+
"Default: 10"
|
55
|
+
) { |Options[:RetryDelay]| }
|
56
|
+
|
57
|
+
opts.on("-P", "--[no-]permanent",
|
58
|
+
"Run the breakpoint client in permanent mode.",
|
59
|
+
"This means that the client will keep continue",
|
60
|
+
"running even after the server has closed the",
|
61
|
+
"connection. Useful for example in Rails.",
|
62
|
+
"Default: non-permanent"
|
63
|
+
) { |Options[:Permanent]| }
|
64
|
+
|
65
|
+
opts.on("-V", "--[no-]verbose",
|
66
|
+
"Run the breakpoint client in verbose mode.",
|
67
|
+
"Will produce more messages, for example between",
|
68
|
+
"individual breakpoints. This might help in seeing",
|
69
|
+
"that the breakpoint client is still alive, but adds",
|
70
|
+
"quite a bit of clutter.",
|
71
|
+
"Default: non-verbose"
|
72
|
+
) { |Options[:Verbose]| }
|
73
|
+
|
74
|
+
opts.separator ""
|
75
|
+
|
76
|
+
opts.on("-h", "--help",
|
77
|
+
"Show this help message."
|
78
|
+
) { puts opts; exit }
|
79
|
+
opts.on("-v", "--version",
|
80
|
+
"Display the version information."
|
81
|
+
) do
|
82
|
+
id = %q$Id: breakpoint_client 50 2005-02-26 19:31:51Z flgr $
|
83
|
+
puts id.sub("Id: ", "")
|
84
|
+
puts "(Breakpoint::Version = #{Breakpoint::Version})"
|
85
|
+
exit
|
86
|
+
end
|
87
|
+
|
88
|
+
opts.parse!
|
89
|
+
end
|
90
|
+
|
91
|
+
Options[:ServerURI] = ARGV[0] if ARGV[0]
|
92
|
+
Options[:ClientURI] ||= case Options[:ServerURI]
|
93
|
+
when /^drbunix:(.+)$/i then
|
94
|
+
"drbunix:" << File.join(Dir.tmpdir, $1.gsub(/\W/, "_")) << ".breakpoint_client"
|
95
|
+
when %r{^druby://(localhost|127\.0\.0\.1|::1):(\d+)$}i then
|
96
|
+
"druby://" << $1 << ":" << $2.succ
|
97
|
+
end
|
98
|
+
|
99
|
+
puts "ClientURI is #{Options[:ClientURI] || "unspecified"}" if Options[:Verbose]
|
100
|
+
|
101
|
+
module Handlers
|
102
|
+
extend self
|
103
|
+
|
104
|
+
def breakpoint_handler(workspace, message)
|
105
|
+
puts message
|
106
|
+
IRB.start(nil, nil, workspace)
|
107
|
+
|
108
|
+
puts ""
|
109
|
+
if Options[:Verbose] then
|
110
|
+
puts "Resumed execution. Waiting for next breakpoint...", ""
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
def eval_handler(code)
|
115
|
+
result = eval(code, TOPLEVEL_BINDING)
|
116
|
+
if result then
|
117
|
+
DRbObject.new(result)
|
118
|
+
else
|
119
|
+
result
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
def collision_handler()
|
124
|
+
msg = [
|
125
|
+
" *** Breakpoint service collision ***",
|
126
|
+
" Another Breakpoint service tried to use the",
|
127
|
+
" port already occupied by this one. It will",
|
128
|
+
" keep waiting until this Breakpoint service",
|
129
|
+
" is shut down.",
|
130
|
+
" ",
|
131
|
+
" If you are using the Breakpoint library for",
|
132
|
+
" debugging a Rails or other CGI application",
|
133
|
+
" this likely means that this Breakpoint",
|
134
|
+
" session belongs to an earlier, outdated",
|
135
|
+
" request and should be shut down via 'exit'."
|
136
|
+
].join("\n")
|
137
|
+
|
138
|
+
if RUBY_PLATFORM["win"] then
|
139
|
+
# This sucks. Sorry, I'm not doing this because
|
140
|
+
# I like funky message boxes -- I need to do this
|
141
|
+
# because on Windows I have no way of displaying
|
142
|
+
# my notification via puts() when gets() is still
|
143
|
+
# being performed on STDIN. I have not found a
|
144
|
+
# better solution.
|
145
|
+
begin
|
146
|
+
require 'tk'
|
147
|
+
root = TkRoot.new { withdraw }
|
148
|
+
Tk.messageBox('message' => msg, 'type' => 'ok')
|
149
|
+
root.destroy
|
150
|
+
rescue Exception
|
151
|
+
puts "", msg, ""
|
152
|
+
end
|
153
|
+
else
|
154
|
+
puts "", msg, ""
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
# Used for checking whether we are currently in the reconnecting loop.
|
160
|
+
reconnecting = false
|
161
|
+
|
162
|
+
loop do
|
163
|
+
DRb.start_service(Options[:ClientURI])
|
164
|
+
|
165
|
+
begin
|
166
|
+
service = DRbObject.new(nil, Options[:ServerURI])
|
167
|
+
|
168
|
+
begin
|
169
|
+
ehandler = Handlers.method(:eval_handler)
|
170
|
+
chandler = Handlers.method(:collision_handler)
|
171
|
+
handler = Handlers.method(:breakpoint_handler)
|
172
|
+
service.eval_handler = ehandler
|
173
|
+
service.collision_handler = chandler
|
174
|
+
service.handler = handler
|
175
|
+
|
176
|
+
reconnecting = false
|
177
|
+
if Options[:Verbose] then
|
178
|
+
puts "Connection established. Waiting for breakpoint...", ""
|
179
|
+
end
|
180
|
+
|
181
|
+
loop do
|
182
|
+
begin
|
183
|
+
service.ping
|
184
|
+
rescue DRb::DRbConnError => error
|
185
|
+
puts "Server exited. Closing connection...", ""
|
186
|
+
DRb.stop_service
|
187
|
+
exit! unless Options[:Permanent]
|
188
|
+
break
|
189
|
+
end
|
190
|
+
|
191
|
+
sleep(0.5)
|
192
|
+
end
|
193
|
+
ensure
|
194
|
+
service.eval_handler = nil
|
195
|
+
service.collision_handler = nil
|
196
|
+
service.handler = nil
|
197
|
+
end
|
198
|
+
rescue Exception => error
|
199
|
+
if Options[:RetryDelay] > 0 then
|
200
|
+
if not reconnecting then
|
201
|
+
reconnecting = true
|
202
|
+
puts "No connection to breakpoint service at #{Options[:ServerURI]} " +
|
203
|
+
"(#{error.class})"
|
204
|
+
puts error.backtrace if $DEBUG
|
205
|
+
puts "Tries to connect will be made every #{Options[:RetryDelay]} seconds..."
|
206
|
+
end
|
207
|
+
|
208
|
+
sleep Options[:RetryDelay]
|
209
|
+
retry
|
210
|
+
else
|
211
|
+
raise
|
212
|
+
end
|
213
|
+
end
|
214
|
+
end
|
@@ -0,0 +1,221 @@
|
|
1
|
+
<?xml version="1.0" encoding="iso-8859-1"?>
|
2
|
+
<!DOCTYPE html
|
3
|
+
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
4
|
+
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
5
|
+
|
6
|
+
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
7
|
+
<head>
|
8
|
+
<title>Class: Binding</title>
|
9
|
+
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
|
10
|
+
<meta http-equiv="Content-Script-Type" content="text/javascript" />
|
11
|
+
<link rel="stylesheet" href=".././rdoc-style.css" type="text/css" media="screen" />
|
12
|
+
<script type="text/javascript">
|
13
|
+
// <![CDATA[
|
14
|
+
|
15
|
+
function popupCode( url ) {
|
16
|
+
window.open(url, "Code", "resizable=yes,scrollbars=yes,toolbar=no,status=no,height=150,width=400")
|
17
|
+
}
|
18
|
+
|
19
|
+
function toggleCode( id ) {
|
20
|
+
if ( document.getElementById )
|
21
|
+
elem = document.getElementById( id );
|
22
|
+
else if ( document.all )
|
23
|
+
elem = eval( "document.all." + id );
|
24
|
+
else
|
25
|
+
return false;
|
26
|
+
|
27
|
+
elemStyle = elem.style;
|
28
|
+
|
29
|
+
if ( elemStyle.display != "block" ) {
|
30
|
+
elemStyle.display = "block"
|
31
|
+
} else {
|
32
|
+
elemStyle.display = "none"
|
33
|
+
}
|
34
|
+
|
35
|
+
return true;
|
36
|
+
}
|
37
|
+
|
38
|
+
// Make codeblocks hidden by default
|
39
|
+
document.writeln( "<style type=\"text/css\">div.method-source-code { display: none }</style>" )
|
40
|
+
|
41
|
+
// ]]>
|
42
|
+
</script>
|
43
|
+
|
44
|
+
</head>
|
45
|
+
<body>
|
46
|
+
|
47
|
+
|
48
|
+
|
49
|
+
<div id="classHeader">
|
50
|
+
<table class="header-table">
|
51
|
+
<tr class="top-aligned-row">
|
52
|
+
<td><strong>Class</strong></td>
|
53
|
+
<td class="class-name-in-header">Binding</td>
|
54
|
+
</tr>
|
55
|
+
<tr class="top-aligned-row">
|
56
|
+
<td><strong>In:</strong></td>
|
57
|
+
<td>
|
58
|
+
<a href="../files/lib/binding_of_caller_rb.html">
|
59
|
+
lib/binding_of_caller.rb
|
60
|
+
</a>
|
61
|
+
<br />
|
62
|
+
</td>
|
63
|
+
</tr>
|
64
|
+
|
65
|
+
<tr class="top-aligned-row">
|
66
|
+
<td><strong>Parent:</strong></td>
|
67
|
+
<td>
|
68
|
+
Object
|
69
|
+
</td>
|
70
|
+
</tr>
|
71
|
+
</table>
|
72
|
+
</div>
|
73
|
+
<!-- banner header -->
|
74
|
+
|
75
|
+
<div id="bodyContent">
|
76
|
+
|
77
|
+
|
78
|
+
|
79
|
+
<div id="contextContent">
|
80
|
+
|
81
|
+
|
82
|
+
|
83
|
+
</div>
|
84
|
+
|
85
|
+
<div id="method-list">
|
86
|
+
<h3 class="section-bar">Methods</h3>
|
87
|
+
|
88
|
+
<div class="name-list">
|
89
|
+
<a href="#M000003">of_caller</a>
|
90
|
+
</div>
|
91
|
+
</div>
|
92
|
+
|
93
|
+
</div>
|
94
|
+
|
95
|
+
|
96
|
+
<!-- if includes -->
|
97
|
+
|
98
|
+
<div id="section">
|
99
|
+
|
100
|
+
|
101
|
+
|
102
|
+
|
103
|
+
|
104
|
+
|
105
|
+
|
106
|
+
|
107
|
+
<!-- if method_list -->
|
108
|
+
<div id="methods">
|
109
|
+
<h3 class="section-bar">Public Class methods</h3>
|
110
|
+
|
111
|
+
<div id="method-M000003" class="method-detail">
|
112
|
+
<a name="M000003"></a>
|
113
|
+
|
114
|
+
<div class="method-heading">
|
115
|
+
<a href="#M000003" class="method-signature">
|
116
|
+
<span class="method-name">of_caller</span><span class="method-args">() {|result| ...}</span>
|
117
|
+
</a>
|
118
|
+
</div>
|
119
|
+
|
120
|
+
<div class="method-description">
|
121
|
+
<p>
|
122
|
+
This method returns the binding of the method that called your method. It
|
123
|
+
will raise an Exception when you’re not inside a method.
|
124
|
+
</p>
|
125
|
+
<p>
|
126
|
+
It’s used like this:
|
127
|
+
</p>
|
128
|
+
<pre>
|
129
|
+
def inc_counter(amount = 1)
|
130
|
+
Binding.of_caller do |binding|
|
131
|
+
# Create a lambda that will increase the variable 'counter'
|
132
|
+
# in the caller of this method when called.
|
133
|
+
inc = eval("lambda { |arg| counter += arg }", binding)
|
134
|
+
# We can refer to amount from inside this block safely.
|
135
|
+
inc.call(amount)
|
136
|
+
end
|
137
|
+
# No other statements can go here. Put them inside the block.
|
138
|
+
end
|
139
|
+
counter = 0
|
140
|
+
2.times { inc_counter }
|
141
|
+
counter # => 2
|
142
|
+
</pre>
|
143
|
+
<p>
|
144
|
+
<a href="Binding.html#M000003">Binding.of_caller</a> must be the last
|
145
|
+
statement in the method. This means that you will have to put everything
|
146
|
+
you want to do after the call to <a
|
147
|
+
href="Binding.html#M000003">Binding.of_caller</a> into the block of it.
|
148
|
+
This should be no problem however, because Ruby has closures. If you
|
149
|
+
don’t do this an Exception will be raised. Because of the way that <a
|
150
|
+
href="Binding.html#M000003">Binding.of_caller</a> is implemented it has to
|
151
|
+
be done this way.
|
152
|
+
</p>
|
153
|
+
<p><a class="source-toggle" href="#"
|
154
|
+
onclick="toggleCode('M000003-source');return false;">[Source]</a></p>
|
155
|
+
<div class="method-source-code" id="M000003-source">
|
156
|
+
<pre>
|
157
|
+
<span class="ruby-comment cmt"># File lib/binding_of_caller.rb, line 35</span>
|
158
|
+
35: <span class="ruby-keyword kw">def</span> <span class="ruby-constant">Binding</span>.<span class="ruby-identifier">of_caller</span>(<span class="ruby-operator">&</span><span class="ruby-identifier">block</span>)
|
159
|
+
36: <span class="ruby-identifier">old_critical</span> = <span class="ruby-constant">Thread</span>.<span class="ruby-identifier">critical</span>
|
160
|
+
37: <span class="ruby-constant">Thread</span>.<span class="ruby-identifier">critical</span> = <span class="ruby-keyword kw">true</span>
|
161
|
+
38: <span class="ruby-identifier">count</span> = <span class="ruby-value">0</span>
|
162
|
+
39: <span class="ruby-identifier">cc</span>, <span class="ruby-identifier">result</span>, <span class="ruby-identifier">error</span>, <span class="ruby-identifier">extra_data</span> = <span class="ruby-constant">Continuation</span>.<span class="ruby-identifier">create</span>(<span class="ruby-keyword kw">nil</span>, <span class="ruby-keyword kw">nil</span>)
|
163
|
+
40: <span class="ruby-identifier">error</span>.<span class="ruby-identifier">call</span> <span class="ruby-keyword kw">if</span> <span class="ruby-identifier">error</span>
|
164
|
+
41:
|
165
|
+
42: <span class="ruby-identifier">tracer</span> = <span class="ruby-identifier">lambda</span> <span class="ruby-keyword kw">do</span> <span class="ruby-operator">|</span><span class="ruby-operator">*</span><span class="ruby-identifier">args</span><span class="ruby-operator">|</span>
|
166
|
+
43: <span class="ruby-identifier">type</span>, <span class="ruby-identifier">context</span>, <span class="ruby-identifier">extra_data</span> = <span class="ruby-identifier">args</span>[<span class="ruby-value">0</span>], <span class="ruby-identifier">args</span>[<span class="ruby-value">4</span>], <span class="ruby-identifier">args</span>
|
167
|
+
44: <span class="ruby-keyword kw">if</span> <span class="ruby-identifier">type</span> <span class="ruby-operator">==</span> <span class="ruby-value str">"return"</span>
|
168
|
+
45: <span class="ruby-identifier">count</span> <span class="ruby-operator">+=</span> <span class="ruby-value">1</span>
|
169
|
+
46: <span class="ruby-comment cmt"># First this method and then calling one will return --</span>
|
170
|
+
47: <span class="ruby-comment cmt"># the trace event of the second event gets the context</span>
|
171
|
+
48: <span class="ruby-comment cmt"># of the method which called the method that called this</span>
|
172
|
+
49: <span class="ruby-comment cmt"># method.</span>
|
173
|
+
50: <span class="ruby-keyword kw">if</span> <span class="ruby-identifier">count</span> <span class="ruby-operator">==</span> <span class="ruby-value">2</span>
|
174
|
+
51: <span class="ruby-comment cmt"># It would be nice if we could restore the trace_func</span>
|
175
|
+
52: <span class="ruby-comment cmt"># that was set before we swapped in our own one, but</span>
|
176
|
+
53: <span class="ruby-comment cmt"># this is impossible without overloading set_trace_func</span>
|
177
|
+
54: <span class="ruby-comment cmt"># in current Ruby.</span>
|
178
|
+
55: <span class="ruby-identifier">set_trace_func</span>(<span class="ruby-keyword kw">nil</span>)
|
179
|
+
56: <span class="ruby-identifier">cc</span>.<span class="ruby-identifier">call</span>(<span class="ruby-identifier">eval</span>(<span class="ruby-value str">"binding"</span>, <span class="ruby-identifier">context</span>), <span class="ruby-keyword kw">nil</span>, <span class="ruby-identifier">extra_data</span>)
|
180
|
+
57: <span class="ruby-keyword kw">end</span>
|
181
|
+
58: <span class="ruby-keyword kw">elsif</span> <span class="ruby-identifier">type</span> <span class="ruby-operator">==</span> <span class="ruby-value str">"line"</span> <span class="ruby-keyword kw">then</span>
|
182
|
+
59: <span class="ruby-keyword kw">nil</span>
|
183
|
+
60: <span class="ruby-keyword kw">elsif</span> <span class="ruby-identifier">type</span> <span class="ruby-operator">==</span> <span class="ruby-value str">"c-return"</span> <span class="ruby-keyword kw">and</span> <span class="ruby-identifier">extra_data</span>[<span class="ruby-value">3</span>] <span class="ruby-operator">==</span> <span class="ruby-identifier">:set_trace_func</span> <span class="ruby-keyword kw">then</span>
|
184
|
+
61: <span class="ruby-keyword kw">nil</span>
|
185
|
+
62: <span class="ruby-keyword kw">else</span>
|
186
|
+
63: <span class="ruby-identifier">set_trace_func</span>(<span class="ruby-keyword kw">nil</span>)
|
187
|
+
64: <span class="ruby-identifier">error_msg</span> = <span class="ruby-value str">"Binding.of_caller used in non-method context or "</span> <span class="ruby-operator">+</span>
|
188
|
+
65: <span class="ruby-value str">"trailing statements of method using it aren't in the block."</span>
|
189
|
+
66: <span class="ruby-identifier">cc</span>.<span class="ruby-identifier">call</span>(<span class="ruby-keyword kw">nil</span>, <span class="ruby-identifier">lambda</span> { <span class="ruby-identifier">raise</span>(<span class="ruby-constant">ArgumentError</span>, <span class="ruby-identifier">error_msg</span>) }, <span class="ruby-keyword kw">nil</span>)
|
190
|
+
67: <span class="ruby-keyword kw">end</span>
|
191
|
+
68: <span class="ruby-keyword kw">end</span>
|
192
|
+
69:
|
193
|
+
70: <span class="ruby-keyword kw">unless</span> <span class="ruby-identifier">result</span>
|
194
|
+
71: <span class="ruby-identifier">set_trace_func</span>(<span class="ruby-identifier">tracer</span>)
|
195
|
+
72: <span class="ruby-keyword kw">return</span> <span class="ruby-keyword kw">nil</span>
|
196
|
+
73: <span class="ruby-keyword kw">else</span>
|
197
|
+
74: <span class="ruby-constant">Thread</span>.<span class="ruby-identifier">critical</span> = <span class="ruby-identifier">old_critical</span>
|
198
|
+
75: <span class="ruby-keyword kw">case</span> <span class="ruby-identifier">block</span>.<span class="ruby-identifier">arity</span>
|
199
|
+
76: <span class="ruby-keyword kw">when</span> <span class="ruby-value">1</span> <span class="ruby-keyword kw">then</span> <span class="ruby-keyword kw">yield</span>(<span class="ruby-identifier">result</span>)
|
200
|
+
77: <span class="ruby-keyword kw">else</span> <span class="ruby-keyword kw">yield</span>(<span class="ruby-identifier">result</span>, <span class="ruby-identifier">extra_data</span>)
|
201
|
+
78: <span class="ruby-keyword kw">end</span>
|
202
|
+
79: <span class="ruby-keyword kw">end</span>
|
203
|
+
80: <span class="ruby-keyword kw">end</span>
|
204
|
+
</pre>
|
205
|
+
</div>
|
206
|
+
</div>
|
207
|
+
</div>
|
208
|
+
|
209
|
+
|
210
|
+
</div>
|
211
|
+
|
212
|
+
|
213
|
+
</div>
|
214
|
+
|
215
|
+
|
216
|
+
<div id="validator-badges">
|
217
|
+
<p><small><a href="http://validator.w3.org/check/referer">[Validate]</a></small></p>
|
218
|
+
</div>
|
219
|
+
|
220
|
+
</body>
|
221
|
+
</html>
|