ladybug 0.1.1 → 0.1.2

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4240a28699151639735baf1b2a68005222ceea4d
4
- data.tar.gz: 1f06bc9dd9b9160624c3fde749432f3f5353516b
3
+ metadata.gz: b73479c1e9523e9a0f5798daed1707ed24baf74c
4
+ data.tar.gz: d046e7c87d246a2e3a156ad1bf71c23fc256789c
5
5
  SHA512:
6
- metadata.gz: 11bb0607a071ac3cad9d837eaa8c325d37ca2c5d8b00bae16f59a06f6b8c0fcad725d375368cabb47e19f4de72276180cdd830a96e93e9776943898f9b831355
7
- data.tar.gz: b8d1f5faeaaf0745bcda7416617f3e3720a3aec5c31ca072e781165321fa3880a8cb05f0e553e55d6835a17937bb0c37e1f136ff95e1492bb96656134f251f57
6
+ metadata.gz: c79d7443d7cebedbb3174fe5a340aa21d2c23d201df2fab87aa6294326c839b3371e187f46eb7d351f4c7c8ad8bf103197882ded9dfb588284f1ae3422eca4ed
7
+ data.tar.gz: 58f696d4d5dc454c68215c0a3780f9ea2c45d070db1e168f915f2be26bf7ec5e567a02c110439291962f8db88f4e481a4d70978e669f0d7f01c0129c8f8893b4
data/README.md CHANGED
@@ -6,7 +6,7 @@ Chrome Devtools as a user interface.
6
6
  It aims to provide a rich backend debugging experience in a UI that many
7
7
  web developers are already familiar with for debugging frontend Javascript.
8
8
 
9
- **This project is currently in a very early experimental phase.** Expect many limitations and bugs, and use at your own risk. If you try it out, please file
9
+ **This project is currently in an early experimental phase.** Expect many limitations and bugs. If you try it out, please file
10
10
  Github issues or [email me](mailto:gklitt@gmail.com) to help make this a
11
11
  more useful tool.
12
12
 
@@ -14,9 +14,9 @@ more useful tool.
14
14
 
15
15
  ## Get started
16
16
 
17
- 1) Install the gem:
17
+ 1) Install the gem, or add it to your Gemfile:
18
18
 
19
- `gem install --pre ladybug`
19
+ `gem install ladybug`
20
20
 
21
21
  2) ladybug is implemented as a Rack middleware, so you'll need to add
22
22
  `Ladybug::Middleware` to the Rack middleware stack.
@@ -24,7 +24,7 @@ For example, in Rails 5, add
24
24
  the following line to `config/application.rb`:
25
25
 
26
26
  ```
27
- config.middleware.insert_before(Rack::Sendfile, Ladybug::Middleware)
27
+ config.middleware.use(Ladybug::Middleware)
28
28
  ```
29
29
 
30
30
  3) Make sure you're using the puma web server, which is currently the
@@ -41,7 +41,11 @@ You should see your server program output something like:
41
41
  In the Sources tab, you can view your Ruby source code.
42
42
  If you set a breakpoint and then make another request to your server,
43
43
  it should pause on the breakpoint and you'll be able to inspect
44
- some variables in Devtools.
44
+ local and instance variables in Devtools.
45
+
46
+ 6) You can then use the "step over" button to step through your code,
47
+ or "continue" to continue code execution. "Step into" and "Step out"
48
+ also work in some contexts.
45
49
 
46
50
  **Security warning:** This debugger should only be run in local development.
47
51
  Running it on a server open to the internet could allow anyone to
@@ -49,11 +53,10 @@ execute code on your server without authenticating.
49
53
 
50
54
  ## Development status
51
55
 
52
- * basic pause/continue breakpoint control is supported, but "step over" and "step into" aren't fully supported yet.
53
- * inspecting primtive objects like strings and numbers works okay; support for more complex objects is in development.
54
56
  * So far, ladybug has only been tested with simple Rails applications running on
55
57
  Rails 5 with the puma web server. Eventually it aims to support more Rack
56
58
  applications and web servers (and perhaps even non-Rack applications).
59
+ * inspecting primtive objects like strings and numbers works okay; support for more complex objects is in development.
57
60
 
58
61
  ## Author
59
62
 
@@ -25,6 +25,8 @@ module Ladybug
25
25
 
26
26
  @parsed_files = {}
27
27
 
28
+ @break = nil
29
+
28
30
  # Todo: consider thread safety of mutating this hash
29
31
  Thread.new do
30
32
  preload_paths.each do |preload_path|
@@ -41,6 +43,20 @@ module Ladybug
41
43
  set_trace_func trace_func
42
44
  end
43
45
 
46
+ def debug
47
+ RubyVM::InstructionSequence.compile_option = {
48
+ trace_instruction: true
49
+ }
50
+ Thread.current.set_trace_func trace_func
51
+
52
+ yield
53
+ ensure
54
+ RubyVM::InstructionSequence.compile_option = {
55
+ trace_instruction: false
56
+ }
57
+ Thread.current.set_trace_func nil
58
+ end
59
+
44
60
  def on_pause(&block)
45
61
  @on_pause = block
46
62
  end
@@ -131,12 +147,12 @@ module Ladybug
131
147
  # remove ladybug code from a callstack and prepare it for comparison
132
148
  # this is a hack implemenetation for now, can be made better
133
149
  def clean(callstack)
134
- callstack.drop_while { |frame| frame.to_s.include? "ladybug" }
150
+ callstack.drop_while { |frame| frame.to_s.include? "ladybug/debugger.rb" }
135
151
  end
136
152
 
137
153
  # If we're in step over/in/out mode,
138
154
  # detect if we should break even if there's not a breakpoint set here
139
- def break_on_step?
155
+ def break_on_step?(filename:)
140
156
  # This is an important early return;
141
157
  # we don't want to do anything w/ the callstack unless
142
158
  # we're looking for a breakpoint, because
@@ -144,22 +160,21 @@ module Ladybug
144
160
  # which makes things really slow
145
161
  return false if @break.nil?
146
162
 
163
+ return false if @break == 'step_over' &&
164
+ @breakpoint_filename != filename
165
+
147
166
  bp_callstack = clean(@breakpoint_callstack)
148
167
  current_callstack = clean(Thread.current.backtrace_locations)
149
168
 
150
169
  if @break == 'step_over'
151
- return bp_callstack[1].to_s == current_callstack[1].to_s
170
+ return current_callstack[1].to_s == bp_callstack[1].to_s
152
171
  elsif @break == 'step_into'
153
- return stacks_equal?(bp_callstack, current_callstack[1..-1])
172
+ return current_callstack[1].to_s == bp_callstack[0].to_s
154
173
  elsif @break == 'step_out'
155
- return stacks_equal?(current_callstack, bp_callstack[1..-1])
174
+ return current_callstack[0].to_s == bp_callstack[1].to_s
156
175
  end
157
176
  end
158
177
 
159
- def stacks_equal?(stack1, stack2)
160
- stack1.map(&:to_s) == stack2.map(&:to_s)
161
- end
162
-
163
178
  def trace_func
164
179
  proc { |event, filename, line_number, id, binding, klass, *rest|
165
180
  # This check is called a lot so perhaps worth making faster,
@@ -168,12 +183,15 @@ module Ladybug
168
183
  bp[:filename] == filename && bp[:line_number] == line_number
169
184
  end
170
185
 
171
- if breakpoint_hit || break_on_step?
186
+ if breakpoint_hit || break_on_step?(filename: filename)
172
187
  local_variables =
173
188
  binding.local_variables.each_with_object({}) do |lvar, hash|
174
189
  hash[lvar] = binding.local_variable_get(lvar)
175
190
  end
176
191
 
192
+ # todo: may want to offer classes the ability to
193
+ # override this and define which instance variables to expose here?
194
+
177
195
  instance_variables =
178
196
  binding.eval("instance_variables").each_with_object({}) do |ivar, hash|
179
197
  hash[ivar] = binding.eval("instance_variable_get(:#{ivar})")
@@ -215,10 +233,12 @@ module Ladybug
215
233
  case message[:command]
216
234
  when 'continue'
217
235
  @break = nil
236
+ @breakpoint_filename = nil
218
237
  break
219
238
  when 'step_over'
220
239
  @break = 'step_over'
221
240
  @breakpoint_callstack = Thread.current.backtrace_locations
241
+ @breakpoint_filename = filename
222
242
  break
223
243
  when 'step_into'
224
244
  @break = 'step_into'
@@ -31,7 +31,9 @@ module Ladybug
31
31
  # Return async Rack response
32
32
  ws.rack_response
33
33
  else
34
- @app.call(env)
34
+ @debugger.debug do
35
+ @app.call(env)
36
+ end
35
37
  end
36
38
  end
37
39
 
@@ -224,42 +226,50 @@ module Ladybug
224
226
 
225
227
  script = @script_repository.find(absolute_path: info[:filename])
226
228
 
227
- location = {
228
- scriptId: script.id,
229
- lineNumber: info[:line_number] - 1,
230
- columnNumber: 0
231
- }
229
+ # currently we don't support going into functions
230
+ # that aren't in the path of our current app.
231
+ if script.nil?
232
+ puts "Debugger was paused on file outside of app: #{info[:filename]}"
233
+ puts "ladybug currently only supports pausing in app files."
234
+ @debugger.resume
235
+ else
236
+ location = {
237
+ scriptId: script.id,
238
+ lineNumber: info[:line_number] - 1,
239
+ columnNumber: 0
240
+ }
232
241
 
233
- msg_to_client = {
234
- method: "Debugger.paused",
235
- params: {
236
- callFrames: [
237
- {
238
- location: location,
239
- callFrameId: SecureRandom.uuid,
240
- functionName: info[:label],
241
- scopeChain: [
242
- {
243
- type: "local",
244
- startLocation: location,
245
- endLocation: location,
246
- object: {
247
- className: "Object",
248
- description: "Object",
249
- type: "object",
250
- objectId: object_id
242
+ msg_to_client = {
243
+ method: "Debugger.paused",
244
+ params: {
245
+ callFrames: [
246
+ {
247
+ location: location,
248
+ callFrameId: SecureRandom.uuid,
249
+ functionName: info[:label],
250
+ scopeChain: [
251
+ {
252
+ type: "local",
253
+ startLocation: location,
254
+ endLocation: location,
255
+ object: {
256
+ className: "Object",
257
+ description: "Object",
258
+ type: "object",
259
+ objectId: object_id
260
+ }
251
261
  }
252
- }
253
- ],
254
- url: script.virtual_url
255
- }
256
- ],
257
- hitBreakpoints: info[:breakpoint_id] ? [info[:breakpoint_id]] : [],
258
- reason: "other"
262
+ ],
263
+ url: script.virtual_url
264
+ }
265
+ ],
266
+ hitBreakpoints: info[:breakpoint_id] ? [info[:breakpoint_id]] : [],
267
+ reason: "other"
268
+ }
259
269
  }
260
- }
261
270
 
262
- ws.send(msg_to_client.to_json)
271
+ ws.send(msg_to_client.to_json)
272
+ end
263
273
  end
264
274
 
265
275
  @debugger.on_resume do
@@ -271,8 +281,6 @@ module Ladybug
271
281
  ws.send(msg_to_client.to_json)
272
282
  end
273
283
 
274
- @debugger.start
275
-
276
284
  ws
277
285
  end
278
286
  end
@@ -99,12 +99,10 @@ module Ladybug
99
99
  elsif object.is_a? Hash
100
100
  object.
101
101
  map do |key, value|
102
- kv = {
102
+ {
103
103
  name: key,
104
104
  value: serialize(value)
105
105
  }
106
-
107
- kv
108
106
  end.
109
107
  reject { |property| property[:value].nil? }
110
108
  elsif object.is_a? Array
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ladybug
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Geoffrey Litt