ruby-breakpoint 0.5.0 → 0.5.1

Sign up to get free protection for your applications and to get access to all the features.
data/Manifest CHANGED
@@ -1,35 +1,38 @@
1
- bin
2
- COPYING
3
- doc
4
- GPL
5
- lib
6
- Manifest
7
- NEWS
8
- README
9
- setup.rb
10
- TODO
11
- bin/breakpoint_client
12
- doc/classes
13
- doc/created.rid
14
- doc/files
15
- doc/fr_class_index.html
16
- doc/fr_file_index.html
17
- doc/fr_method_index.html
18
- doc/index.html
19
- doc/rdoc-style.css
20
- doc/classes/Binding.html
21
- doc/classes/Breakpoint
22
- doc/classes/Breakpoint.html
23
- doc/classes/Breakpoint/CommandBundle
24
- doc/classes/Breakpoint/CommandBundle.html
25
- doc/classes/Breakpoint/FailedAssertError.html
26
- doc/classes/Breakpoint/CommandBundle/Client.html
27
- doc/files/COPYING.html
28
- doc/files/lib
29
- doc/files/NEWS.html
30
- doc/files/README.html
31
- doc/files/TODO.html
32
- doc/files/lib/binding_of_caller_rb.html
33
- doc/files/lib/breakpoint_rb.html
34
- lib/binding_of_caller.rb
35
- lib/breakpoint.rb
1
+ bin
2
+ COPYING
3
+ doc
4
+ GPL
5
+ lib
6
+ Manifest
7
+ NEWS
8
+ README
9
+ setup.rb
10
+ TODO
11
+ bin/breakpoint_client
12
+ doc/classes
13
+ doc/created.rid
14
+ doc/files
15
+ doc/fr_class_index.html
16
+ doc/fr_file_index.html
17
+ doc/fr_method_index.html
18
+ doc/index.html
19
+ doc/rdoc-style.css
20
+ doc/classes/Binding.html
21
+ doc/classes/Breakpoint
22
+ doc/classes/Breakpoint.html
23
+ doc/classes/Handlers.html
24
+ doc/classes/Breakpoint/CommandBundle
25
+ doc/classes/Breakpoint/CommandBundle.html
26
+ doc/classes/Breakpoint/FailedAssertError.html
27
+ doc/classes/Breakpoint/CommandBundle/Client.html
28
+ doc/files/COPYING.html
29
+ doc/files/lib
30
+ doc/files/NEWS.html
31
+ doc/files/README.html
32
+ doc/files/TODO.html
33
+ doc/files/lib/binding_of_caller_rb.html
34
+ doc/files/lib/breakpoint_client_rb.html
35
+ doc/files/lib/breakpoint_rb.html
36
+ lib/binding_of_caller.rb
37
+ lib/breakpoint.rb
38
+ lib/breakpoint_client.rb
data/NEWS CHANGED
@@ -2,6 +2,20 @@
2
2
 
3
3
  This file sums up important changes that happened between releases.
4
4
 
5
+ == ruby-breakpoint 0.5.1
6
+ * Moved functionality of bin/breakpoint_client to lib/breakpoint_client.rb and
7
+ changed it so that it will respect previously set Options. (Should make it
8
+ easier for other libraries to integrate ruby-breakpoint with custom options.)
9
+ * Fixed trouble with .irbrc on remote breakpoint server when calling
10
+ DRb.activate_drb (see http://dev.rubyonrails.com/ticket/803)
11
+ * Fixed client.y not working (Need to undef DRbObject#to_yaml)
12
+ * Fixed client << 5 and similar not working
13
+ * Fixed client.require not working with some RubyGems versions
14
+ * WorkSpace#evaluate no longer extends strings and numerics with DRbUndumped
15
+ (Works around "DRb::DRbObject#to_str should return String" style bugs)
16
+ * Documented bug in Binding.of_caller() that causes Breakpoint.breakpoint()
17
+ to have a wrong object context. breakpoint() works correctly.
18
+
5
19
  == ruby-breakpoint 0.5.0
6
20
  * breakpoint_client has better logic for guessing the client-uri automatically.
7
21
  This ought to fix connection errors that were happening because the client
data/README CHANGED
@@ -1,7 +1,7 @@
1
- = ruby-breakpoint 0.5.0 README
1
+ = ruby-breakpoint 0.5.1 README
2
2
 
3
3
  ruby-breakpoint lets you inspect and modify state at run time. This allows you
4
- to diagnose bugs, patch
5
4
  applications and more all via IRB by simply doing a
5
+ to diagnose bugs, patch applications and more all via IRB by simply doing a
6
6
  method call at the place you want to investigate.
7
7
 
8
8
  ruby-breakpoint is integrated into the popular RubyOnRails and Nitro web
@@ -28,9 +28,9 @@ De-compress archive and enter its top directory. Then type:
28
28
  ($ su)
29
29
  # ruby setup.rb
30
30
 
31
- These simple step installs this program under the default location of Ruby
31
+ This simple step installs this program under the default location of Ruby
32
32
  libraries. You can also install files into your favorite directory by supplying
33
- setup.rb some options. Try "ruby setup.rb --help".
33
+ setup.rb with some options. Try "ruby setup.rb --help".
34
34
 
35
35
 
36
36
  == License
data/TODO CHANGED
@@ -5,6 +5,10 @@
5
5
  when DRb is not available. (E.g. on Debian)
6
6
 
7
7
  = Done
8
+
9
+ * breakpoint_client ought to handle the case that Options is already defined
10
+ so that RubyOnRails and other frameworks that might want to ship
11
+ ruby-breakpoint directly can overwrite the default options easily.
8
12
 
9
13
  * Do further research on the write SecurityError.
10
14
  See ruby-core for more information.
@@ -1,214 +1,3 @@
1
1
  #!/usr/bin/env ruby
2
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
3
+ require 'breakpoint_client'
@@ -1,221 +1,238 @@
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>&nbsp;&nbsp;
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&#8217;re not inside a method.
124
- </p>
125
- <p>
126
- It&#8217;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(&quot;lambda { |arg| counter += arg }&quot;, 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 # =&gt; 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&#8217;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">&amp;</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">&quot;return&quot;</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">&quot;binding&quot;</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">&quot;line&quot;</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">&quot;c-return&quot;</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">&quot;Binding.of_caller used in non-method context or &quot;</span> <span class="ruby-operator">+</span>
188
- 65: <span class="ruby-value str">&quot;trailing statements of method using it aren't in the block.&quot;</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>
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>&nbsp;&nbsp;
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&#8217;re not inside a method.
124
+ </p>
125
+ <p>
126
+ It&#8217;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(&quot;lambda { |arg| counter += arg }&quot;, 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 # =&gt; 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&#8217;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>
154
+ Please note that currently bindings returned by <a
155
+ href="Binding.html#M000003">Binding.of_caller</a>() will have a wrong self
156
+ context which means you can not call methods, access instance variables and
157
+ so on on the calling object. You can work around this by defining the
158
+ method which uses the binding on all objects and telling your users to use
159
+ them without a receiver. This is how ruby-breakpoint works around the
160
+ problem.
161
+ </p>
162
+ <p>
163
+ This is believed to be a bug in Ruby and has been reported to ruby-core.
164
+ See <a
165
+ href="http://www.ruby-forum.com/topic/67255">www.ruby-forum.com/topic/67255</a>
166
+ </p>
167
+ <p><a class="source-toggle" href="#"
168
+ onclick="toggleCode('M000003-source');return false;">[Source]</a></p>
169
+ <div class="method-source-code" id="M000003-source">
170
+ <pre>
171
+ <span class="ruby-comment cmt"># File lib/binding_of_caller.rb, line 46</span>
172
+ 46: <span class="ruby-keyword kw">def</span> <span class="ruby-constant">Binding</span>.<span class="ruby-identifier">of_caller</span>(<span class="ruby-operator">&amp;</span><span class="ruby-identifier">block</span>)
173
+ 47: <span class="ruby-identifier">old_critical</span> = <span class="ruby-constant">Thread</span>.<span class="ruby-identifier">critical</span>
174
+ 48: <span class="ruby-constant">Thread</span>.<span class="ruby-identifier">critical</span> = <span class="ruby-keyword kw">true</span>
175
+ 49: <span class="ruby-identifier">count</span> = <span class="ruby-value">0</span>
176
+ 50: <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>)
177
+ 51: <span class="ruby-keyword kw">if</span> <span class="ruby-identifier">error</span> <span class="ruby-keyword kw">then</span>
178
+ 52: <span class="ruby-constant">Thread</span>.<span class="ruby-identifier">critical</span> = <span class="ruby-identifier">old_critical</span>
179
+ 53: <span class="ruby-identifier">error</span>.<span class="ruby-identifier">call</span>
180
+ 54: <span class="ruby-keyword kw">end</span>
181
+ 55:
182
+ 56: <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>
183
+ 57: <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>
184
+ 58: <span class="ruby-keyword kw">if</span> <span class="ruby-identifier">type</span> <span class="ruby-operator">==</span> <span class="ruby-value str">&quot;return&quot;</span>
185
+ 59: <span class="ruby-identifier">count</span> <span class="ruby-operator">+=</span> <span class="ruby-value">1</span>
186
+ 60: <span class="ruby-comment cmt"># First this method and then calling one will return --
187
+ 61: <span class="ruby-comment cmt"># the trace event of the second event gets the context
188
+ 62: <span class="ruby-comment cmt"># of the method which called the method that called this
189
+ 63: <span class="ruby-comment cmt"># method.
190
+ 64: <span class="ruby-keyword kw">if</span> <span class="ruby-identifier">count</span> <span class="ruby-operator">==</span> <span class="ruby-value">2</span>
191
+ 65: <span class="ruby-comment cmt"># It would be nice if we could restore the trace_func
192
+ 66: <span class="ruby-comment cmt"># that was set before we swapped in our own one, but
193
+ 67: <span class="ruby-comment cmt"># this is impossible without overloading set_trace_func
194
+ 68: <span class="ruby-comment cmt"># in current Ruby.
195
+ 69: <span class="ruby-identifier">set_trace_func</span>(<span class="ruby-keyword kw">nil</span>)
196
+ 70: <span class="ruby-identifier">cc</span>.<span class="ruby-identifier">call</span>(<span class="ruby-identifier">context</span>, <span class="ruby-keyword kw">nil</span>, <span class="ruby-identifier">extra_data</span>)
197
+ 71: <span class="ruby-keyword kw">end</span>
198
+ 72: <span class="ruby-keyword kw">elsif</span> <span class="ruby-identifier">type</span> <span class="ruby-operator">==</span> <span class="ruby-value str">&quot;line&quot;</span> <span class="ruby-keyword kw">then</span>
199
+ 73: <span class="ruby-keyword kw">nil</span>
200
+ 74: <span class="ruby-keyword kw">elsif</span> <span class="ruby-identifier">type</span> <span class="ruby-operator">==</span> <span class="ruby-value str">&quot;c-return&quot;</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>
201
+ 75: <span class="ruby-keyword kw">nil</span>
202
+ 76: <span class="ruby-keyword kw">else</span>
203
+ 77: <span class="ruby-identifier">set_trace_func</span>(<span class="ruby-keyword kw">nil</span>)
204
+ 78: <span class="ruby-identifier">error_msg</span> = <span class="ruby-value str">&quot;Binding.of_caller used in non-method context or &quot;</span> <span class="ruby-operator">+</span>
205
+ 79: <span class="ruby-value str">&quot;trailing statements of method using it aren't in the block.&quot;</span>
206
+ 80: <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>)
207
+ 81: <span class="ruby-keyword kw">end</span>
208
+ 82: <span class="ruby-keyword kw">end</span>
209
+ 83:
210
+ 84: <span class="ruby-keyword kw">unless</span> <span class="ruby-identifier">result</span>
211
+ 85: <span class="ruby-identifier">set_trace_func</span>(<span class="ruby-identifier">tracer</span>)
212
+ 86: <span class="ruby-keyword kw">return</span> <span class="ruby-keyword kw">nil</span>
213
+ 87: <span class="ruby-keyword kw">else</span>
214
+ 88: <span class="ruby-constant">Thread</span>.<span class="ruby-identifier">critical</span> = <span class="ruby-identifier">old_critical</span>
215
+ 89: <span class="ruby-keyword kw">case</span> <span class="ruby-identifier">block</span>.<span class="ruby-identifier">arity</span>
216
+ 90: <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>)
217
+ 91: <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>)
218
+ 92: <span class="ruby-keyword kw">end</span>
219
+ 93: <span class="ruby-keyword kw">end</span>
220
+ 94: <span class="ruby-keyword kw">end</span>
221
+ </pre>
222
+ </div>
223
+ </div>
224
+ </div>
225
+
226
+
227
+ </div>
228
+
229
+
230
+ </div>
231
+
232
+
233
+ <div id="validator-badges">
234
+ <p><small><a href="http://validator.w3.org/check/referer">[Validate]</a></small></p>
235
+ </div>
236
+
237
+ </body>
221
238
  </html>