ruby-breakpoint 0.5.0 → 0.5.1

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/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>