web-console 2.3.0 → 3.3.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.
- checksums.yaml +4 -4
- data/CHANGELOG.markdown +41 -3
- data/MIT-LICENSE +1 -1
- data/README.markdown +14 -41
- data/lib/web_console/exception_mapper.rb +33 -0
- data/lib/web_console/extensions.rb +38 -16
- data/lib/web_console/integration/cruby.rb +18 -35
- data/lib/web_console/integration/rubinius.rb +22 -50
- data/lib/web_console/integration.rb +27 -2
- data/lib/web_console/middleware.rb +9 -10
- data/lib/web_console/railtie.rb +4 -7
- data/lib/web_console/request.rb +3 -3
- data/lib/web_console/session.rb +18 -13
- data/lib/web_console/templates/console.js.erb +1 -1
- data/lib/web_console/templates/layouts/javascript.erb +1 -1
- data/lib/web_console/testing/fake_middleware.rb +2 -6
- data/lib/web_console/version.rb +1 -1
- data/lib/web_console/view.rb +10 -1
- data/lib/web_console/whiny_request.rb +3 -3
- data/lib/web_console.rb +21 -16
- metadata +14 -49
- data/lib/web_console/helper.rb +0 -22
- data/lib/web_console/integration/jruby.rb +0 -111
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: caf063e0c1a30832d5fa0b6ce776514809889448
|
|
4
|
+
data.tar.gz: 0ea92426f743c1463500a0367b8d490501b80e20
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: dc7485fccd26fc2af5a0110215df7baf09188f6ee94d2cb02a6da71c649bb22f84070ff4f7dd0d1c34ba355ff962ac590f1cf8520b04bc4db91ef5256e8b7b49
|
|
7
|
+
data.tar.gz: f8e6b128bfc10fba1c76d95287a0316d028281acac1853b451f024a99c23b6c2d26a6ad3cb1fa4b87395aaabd4c446f2dc3a9d1f792ceff2e86b34c1b7e92e76
|
data/CHANGELOG.markdown
CHANGED
|
@@ -2,14 +2,51 @@
|
|
|
2
2
|
|
|
3
3
|
## master (unreleased)
|
|
4
4
|
|
|
5
|
+
## 3.3.1
|
|
6
|
+
|
|
7
|
+
Drop support for Rails `4.2.0`.
|
|
8
|
+
|
|
9
|
+
## 3.3.0
|
|
10
|
+
|
|
11
|
+
* [203](https://github.com/rails/web-console/pull/203) Map bindings to traces based on the trace __FILE__ and __LINE__ ([@gsamokovarov])
|
|
12
|
+
|
|
13
|
+
## 3.2.1
|
|
14
|
+
|
|
15
|
+
* [#202](https://github.com/rails/web-console/pull/202) Use first binding when there is no application binding ([@sh19910711])
|
|
16
|
+
|
|
17
|
+
## 3.2.0
|
|
18
|
+
|
|
19
|
+
* [#198](https://github.com/rails/web-console/pull/198) Pick the first application trace binding on errors ([@sh19910711])
|
|
20
|
+
* [#189](https://github.com/rails/web-console/pull/189) Silence ActionView rendering information ([@gsamokovarov])
|
|
21
|
+
|
|
22
|
+
## 3.1.1
|
|
23
|
+
|
|
24
|
+
* [#185](https://github.com/rails/web-console/pull/185) Fix `rails console` startup ([@gsamokovarov])
|
|
25
|
+
|
|
26
|
+
## 3.1.0
|
|
27
|
+
|
|
28
|
+
* [#182](https://github.com/rails/web-console/pull/182) Let `#console` live in `Kernel` ([@schneems])
|
|
29
|
+
* [#181](https://github.com/rails/web-console/pull/181) Log internal Web Console errors ([@gsamokovarov])
|
|
30
|
+
* [#180](https://github.com/rails/web-console/pull/180) Autoload Web Console constants for faster Rails boot time ([@herminiotorres])
|
|
31
|
+
|
|
32
|
+
## 3.0.0
|
|
33
|
+
|
|
34
|
+
* [#173](https://github.com/rails/web-console/pull/173) Revert "Change config.development_only default until 4.2.4 is released" ([@gsamokovarov])
|
|
35
|
+
* [#171](https://github.com/rails/web-console/pull/171) Fixed blocked IP logging ([@gsamokovarov])
|
|
36
|
+
* [#162](https://github.com/rails/web-console/pull/162) Render the console inside the body tag ([@gsamokovarov])
|
|
37
|
+
* [#165](https://github.com/rails/web-console/pull/165) Revamped integrations for CRuby and Rubinius ([@gsamokovarov])
|
|
38
|
+
|
|
5
39
|
## 2.3.0
|
|
6
40
|
|
|
7
|
-
|
|
8
|
-
|
|
41
|
+
This is mainly a Rails 5 compatibility release. If you have the chance, please
|
|
42
|
+
go to 3.1.0 instead.
|
|
43
|
+
|
|
44
|
+
* [#181](https://github.com/rails/web-console/pull/181) Log internal Web Console errors (@schneems)
|
|
45
|
+
* [#150](https://github.com/rails/web-console/pull/150) Revert #150. (@gsamokovarov)
|
|
9
46
|
|
|
10
47
|
## 2.2.1
|
|
11
48
|
|
|
12
|
-
* [#150](https://github.com/rails/web-console/pull/150) Change config.development_only default until 4.2.4 is released
|
|
49
|
+
* [#150](https://github.com/rails/web-console/pull/150) Change config.development_only default until 4.2.4 is released ([@gsamokovarov])
|
|
13
50
|
|
|
14
51
|
## 2.2.0
|
|
15
52
|
|
|
@@ -53,4 +90,5 @@
|
|
|
53
90
|
[@parterburn]: https://github.com/parterburn
|
|
54
91
|
[@sh19910711]: https://github.com/sh19910711
|
|
55
92
|
[@frenesim]: https://github.com/frenesim
|
|
93
|
+
[@herminiotorres]: https://github.com/herminiotorres
|
|
56
94
|
[@schneems]: https://github.com/schneems
|
data/MIT-LICENSE
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
Copyright 2014 Charlie Somerville, Genadi Samokovarov, Guillermo Iguaran and Ryan Dao
|
|
1
|
+
Copyright 2014-2016 Charlie Somerville, Genadi Samokovarov, Guillermo Iguaran and Ryan Dao
|
|
2
2
|
|
|
3
3
|
Permission is hereby granted, free of charge, to any person obtaining
|
|
4
4
|
a copy of this software and associated documentation files (the
|
data/README.markdown
CHANGED
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
<p align=right>
|
|
2
2
|
Documentation for:
|
|
3
|
-
<a href=https://github.com/rails/web-console/tree/
|
|
4
|
-
<a href=https://github.com/rails/web-console/tree/v2.1
|
|
5
|
-
<a href=https://github.com/rails/web-console/tree/
|
|
6
|
-
<a href=https://github.com/rails/web-console/tree/v2.1.2>v2.1.2</a>
|
|
7
|
-
<a href=https://github.com/rails/web-console/tree/v2.1.3>v2.1.3</a>
|
|
3
|
+
<a href=https://github.com/rails/web-console/tree/v1.0.4>v1.0.4</a>
|
|
4
|
+
<a href=https://github.com/rails/web-console/tree/v2.2.1>v2.2.1</a>
|
|
5
|
+
<a href=https://github.com/rails/web-console/tree/v3.0.0>v3.0.0</a>
|
|
8
6
|
</p>
|
|
9
7
|
|
|
10
8
|
# Web Console [](https://travis-ci.org/rails/web-console)
|
|
@@ -28,7 +26,7 @@ application, add the following to your `Gemfile`.
|
|
|
28
26
|
|
|
29
27
|
```ruby
|
|
30
28
|
group :development do
|
|
31
|
-
gem 'web-console'
|
|
29
|
+
gem 'web-console'
|
|
32
30
|
end
|
|
33
31
|
```
|
|
34
32
|
|
|
@@ -37,35 +35,9 @@ restart your server for the _Web Console_ to kick in.
|
|
|
37
35
|
|
|
38
36
|
## Runtime
|
|
39
37
|
|
|
40
|
-
_Web Console_ uses [John Mair]'s [binding_of_caller] to spawn a console in a
|
|
41
|
-
specific binding. This comes at the price of limited Ruby runtime support.
|
|
42
|
-
|
|
43
38
|
### CRuby
|
|
44
39
|
|
|
45
|
-
CRuby
|
|
46
|
-
|
|
47
|
-
### JRuby
|
|
48
|
-
|
|
49
|
-
JRuby needs to run in interpreted mode. You can enable it by:
|
|
50
|
-
|
|
51
|
-
```bash
|
|
52
|
-
export JRUBY_OPTS=-J-Djruby.compile.mode=OFF
|
|
53
|
-
|
|
54
|
-
# If you run JRuby 1.7.12 and above, you can use:
|
|
55
|
-
export JRUBY_OPTS=--dev
|
|
56
|
-
```
|
|
57
|
-
|
|
58
|
-
An unstable version of [binding_of_caller] is needed as the latest stable one
|
|
59
|
-
won't compile on _JRuby_. To install it, put the following in your application
|
|
60
|
-
`Gemfile`:
|
|
61
|
-
|
|
62
|
-
```ruby
|
|
63
|
-
group :development do
|
|
64
|
-
gem 'binding_of_caller', '0.7.3.pre1'
|
|
65
|
-
end
|
|
66
|
-
```
|
|
67
|
-
|
|
68
|
-
Only _JRuby_ 1.7, is supported (no JRuby 9K support at the moment).
|
|
40
|
+
CRuby 2.2 and above is required.
|
|
69
41
|
|
|
70
42
|
### Rubinius
|
|
71
43
|
|
|
@@ -75,7 +47,7 @@ Internal errors like `ZeroDevisionError` aren't caught.
|
|
|
75
47
|
|
|
76
48
|
The web console allows you to create an interactive Ruby session in your
|
|
77
49
|
browser. Those sessions are launched automatically in case on an error, but
|
|
78
|
-
they can also be launched manually in
|
|
50
|
+
they can also be launched manually in any page.
|
|
79
51
|
|
|
80
52
|
For example, calling `console` in a view will display a console in the current
|
|
81
53
|
page in the context of the view binding.
|
|
@@ -96,8 +68,10 @@ class PostsController < ApplicationController
|
|
|
96
68
|
end
|
|
97
69
|
```
|
|
98
70
|
|
|
99
|
-
|
|
100
|
-
|
|
71
|
+
The method is defined in `Kernel` and you can invoke it any application code.
|
|
72
|
+
|
|
73
|
+
Only one `console` invocation is allowed once per request. If you happen to
|
|
74
|
+
have multiple ones, a `WebConsole::DoubleRenderError` will be raised.
|
|
101
75
|
|
|
102
76
|
## Configuration
|
|
103
77
|
|
|
@@ -215,17 +189,16 @@ Make sure you configuration lives in `config/environments/development.rb`.
|
|
|
215
189
|
|
|
216
190
|
## Credits
|
|
217
191
|
|
|
218
|
-
* Shoutout to [Charlie Somerville] for [better_errors]
|
|
219
|
-
* Kudos to [John Mair] for [
|
|
192
|
+
* Shoutout to [Charlie Somerville] for [better_errors].
|
|
193
|
+
* Kudos to [John Mair] for [debug_inspector].
|
|
220
194
|
* Thanks to [Charles Oliver Nutter] for all the _JRuby_ feedback.
|
|
221
|
-
* Hugs and kisses to all of our [contributors]
|
|
195
|
+
* Hugs and kisses to all of our [contributors]!
|
|
222
196
|
|
|
223
197
|
[better_errors]: https://github.com/charliesome/better_errors
|
|
224
|
-
[
|
|
198
|
+
[debug_inspector]: https://github.com/banister/debug_inspector
|
|
225
199
|
[Charlie Somerville]: https://github.com/charliesome
|
|
226
200
|
[John Mair]: https://github.com/banister
|
|
227
201
|
[Charles Oliver Nutter]: https://github.com/headius
|
|
228
202
|
[templates]: https://github.com/rails/web-console/tree/master/lib/web_console/templates
|
|
229
|
-
[this]: https://github.com/rails/web-console/blob/master/lib/web_console/integration/cruby.rb#L20-L32
|
|
230
203
|
[rvt]: https://github.com/gsamokovarov/rvt
|
|
231
204
|
[contributors]: https://github.com/rails/web-console/graphs/contributors
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
module WebConsole
|
|
2
|
+
class ExceptionMapper
|
|
3
|
+
def initialize(exception)
|
|
4
|
+
@backtrace = exception.backtrace
|
|
5
|
+
@bindings = exception.bindings
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def first
|
|
9
|
+
guess_the_first_application_binding || @bindings.first
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def [](index)
|
|
13
|
+
guess_binding_for_index(index) || @bindings[index]
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
private
|
|
17
|
+
|
|
18
|
+
def guess_binding_for_index(index)
|
|
19
|
+
file, line = @backtrace[index].to_s.split(':')
|
|
20
|
+
line = line.to_i
|
|
21
|
+
|
|
22
|
+
@bindings.find do |binding|
|
|
23
|
+
binding.eval('__FILE__') == file && binding.eval('__LINE__') == line
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def guess_the_first_application_binding
|
|
28
|
+
@bindings.find do |binding|
|
|
29
|
+
binding.eval('__FILE__').to_s.start_with?(Rails.root.to_s)
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -1,23 +1,45 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
render_exception_without_web_console(request, exception).tap do
|
|
4
|
-
# Retain superficial Rails 5 compatibility.
|
|
5
|
-
env = Hash === request ? request : request.env
|
|
1
|
+
module Kernel
|
|
2
|
+
module_function
|
|
6
3
|
|
|
7
|
-
|
|
4
|
+
# Instructs Web Console to render a console in the specified binding.
|
|
5
|
+
#
|
|
6
|
+
# If +bidning+ isn't explicitly given it will default to the binding of the
|
|
7
|
+
# previous frame. E.g. the one that invoked +console+.
|
|
8
|
+
#
|
|
9
|
+
# Raises DoubleRenderError if a double +console+ invocation per request is
|
|
10
|
+
# detected.
|
|
11
|
+
def console(binding = WebConsole.caller_bindings.first)
|
|
12
|
+
raise WebConsole::DoubleRenderError if Thread.current[:__web_console_binding]
|
|
8
13
|
|
|
9
|
-
|
|
10
|
-
env['web_console.exception'] = error
|
|
14
|
+
Thread.current[:__web_console_binding] = binding
|
|
11
15
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
16
|
+
# Make sure nothing is rendered from the view helper. Otherwise
|
|
17
|
+
# you're gonna see unexpected #<Binding:0x007fee4302b078> in the
|
|
18
|
+
# templates.
|
|
19
|
+
nil
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
module ActionDispatch
|
|
24
|
+
class DebugExceptions
|
|
25
|
+
def render_exception_with_web_console(request, exception)
|
|
26
|
+
render_exception_without_web_console(request, exception).tap do
|
|
27
|
+
backtrace_cleaner = request.get_header('action_dispatch.backtrace_cleaner')
|
|
28
|
+
error = ExceptionWrapper.new(backtrace_cleaner, exception).exception
|
|
29
|
+
|
|
30
|
+
# Get the original exception if ExceptionWrapper decides to follow it.
|
|
31
|
+
Thread.current[:__web_console_exception] = error
|
|
32
|
+
|
|
33
|
+
# ActionView::Template::Error bypass ExceptionWrapper original
|
|
34
|
+
# exception following. The backtrace in the view is generated from
|
|
35
|
+
# reaching out to original_exception in the view.
|
|
36
|
+
if error.is_a?(ActionView::Template::Error)
|
|
37
|
+
Thread.current[:__web_console_exception] = error.cause
|
|
38
|
+
end
|
|
17
39
|
end
|
|
18
40
|
end
|
|
19
|
-
end
|
|
20
41
|
|
|
21
|
-
|
|
22
|
-
|
|
42
|
+
alias_method :render_exception_without_web_console, :render_exception
|
|
43
|
+
alias_method :render_exception, :render_exception_with_web_console
|
|
44
|
+
end
|
|
23
45
|
end
|
|
@@ -1,40 +1,23 @@
|
|
|
1
|
-
|
|
2
|
-
begin
|
|
3
|
-
# We share the same exception binding extraction mechanism as better_errors,
|
|
4
|
-
# so try to use it if it is already available. It also solves problems like
|
|
5
|
-
# charliesome/better_errors#272, caused by an infinite recursion.
|
|
6
|
-
require 'better_errors'
|
|
1
|
+
require 'debug_inspector'
|
|
7
2
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
rescue LoadError
|
|
13
|
-
# The bindings in which the exception originated in.
|
|
14
|
-
def bindings
|
|
15
|
-
@bindings || []
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
# CRuby calls #set_backtrace every time it raises an exception. Overriding
|
|
19
|
-
# it to assign the #bindings.
|
|
20
|
-
def set_backtrace_with_binding_of_caller(*args)
|
|
21
|
-
# Thanks to @charliesome who wrote this bit for better_errors.
|
|
22
|
-
unless Thread.current[:__web_console_exception_lock]
|
|
23
|
-
Thread.current[:__web_console_exception_lock] = true
|
|
24
|
-
begin
|
|
25
|
-
# Raising an exception here will cause all of the rubies to go into a
|
|
26
|
-
# stack overflow. Some rubies may even segfault. See
|
|
27
|
-
# https://bugs.ruby-lang.org/issues/10164 for details.
|
|
28
|
-
@bindings = binding.callers.drop(1)
|
|
29
|
-
ensure
|
|
30
|
-
Thread.current[:__web_console_exception_lock] = false
|
|
31
|
-
end
|
|
32
|
-
end
|
|
3
|
+
def WebConsole.caller_bindings
|
|
4
|
+
bindings = RubyVM::DebugInspector.open do |context|
|
|
5
|
+
context.backtrace_locations.each_index.map { |i| context.frame_binding(i) }
|
|
6
|
+
end
|
|
33
7
|
|
|
34
|
-
|
|
35
|
-
|
|
8
|
+
# For C functions, we can't extract a binding. In this case,
|
|
9
|
+
# DebugInspector#frame_binding would have returned us nil. That's why we need
|
|
10
|
+
# to compact the bindings.
|
|
11
|
+
#
|
|
12
|
+
# Dropping two bindings, removes the current Ruby one in this exact method,
|
|
13
|
+
# and the one in the caller method. The caller method binding can be obtained
|
|
14
|
+
# by Kernel#binding, if needed.
|
|
15
|
+
bindings.compact.drop(2)
|
|
16
|
+
end
|
|
36
17
|
|
|
37
|
-
|
|
38
|
-
|
|
18
|
+
TracePoint.trace(:raise) do |context|
|
|
19
|
+
exc = context.raised_exception
|
|
20
|
+
if exc.bindings.empty?
|
|
21
|
+
exc.instance_variable_set(:@bindings, WebConsole.caller_bindings)
|
|
39
22
|
end
|
|
40
23
|
end
|
|
@@ -1,62 +1,34 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
# Filters internal Rubinius locations.
|
|
4
|
-
#
|
|
5
|
-
# There are a couple of reasons why we wanna filter out the locations.
|
|
6
|
-
#
|
|
7
|
-
# * ::Kernel.raise, is implemented in Ruby for Rubinius. We don't wanna
|
|
8
|
-
# have the frame for it to align with the CRuby and JRuby implementations.
|
|
9
|
-
#
|
|
10
|
-
# * For internal methods location variables can be nil. We can't create a
|
|
11
|
-
# bindings for them.
|
|
12
|
-
#
|
|
13
|
-
# * Bindings from the current file are considered internal and ignored.
|
|
14
|
-
#
|
|
15
|
-
# We do that all that so we can align the bindings with the backtraces
|
|
16
|
-
# entries.
|
|
17
|
-
class InternalLocationFilter
|
|
18
|
-
def initialize(locations)
|
|
19
|
-
@locations = locations
|
|
20
|
-
end
|
|
1
|
+
def WebConsole.caller_bindings
|
|
2
|
+
locations = ::Rubinius::VM.backtrace(1, true)
|
|
21
3
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
# Gets the current bindings for all available Ruby frames.
|
|
32
|
-
#
|
|
33
|
-
# Filters the internal Rubinius and WebConsole frames.
|
|
34
|
-
def self.current_bindings
|
|
35
|
-
locations = ::Rubinius::VM.backtrace(1, true)
|
|
36
|
-
|
|
37
|
-
InternalLocationFilter.new(locations).filter.map do |location|
|
|
38
|
-
Binding.setup(
|
|
39
|
-
location.variables,
|
|
40
|
-
location.variables.method,
|
|
41
|
-
location.constant_scope,
|
|
42
|
-
location.variables.self,
|
|
43
|
-
location
|
|
44
|
-
)
|
|
45
|
-
end
|
|
46
|
-
end
|
|
4
|
+
# Kernel.raise, is implemented in Ruby for Rubinius. We don't wanna have
|
|
5
|
+
# the frame for it to align with the CRuby and JRuby implementations.
|
|
6
|
+
#
|
|
7
|
+
# For internal methods location variables can be nil. We can't create a
|
|
8
|
+
# bindings for them.
|
|
9
|
+
locations.reject! do |location|
|
|
10
|
+
location.file.start_with?('kernel/delta/kernel.rb') || location.variables.nil?
|
|
47
11
|
end
|
|
48
|
-
end
|
|
49
12
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
13
|
+
bindings = locations.map do |location|
|
|
14
|
+
Binding.setup(
|
|
15
|
+
location.variables,
|
|
16
|
+
location.variables.method,
|
|
17
|
+
location.constant_scope,
|
|
18
|
+
location.variables.self,
|
|
19
|
+
location
|
|
20
|
+
)
|
|
53
21
|
end
|
|
22
|
+
|
|
23
|
+
# Drop the binding of the direct caller. That one can be created by
|
|
24
|
+
# Kernel#binding.
|
|
25
|
+
bindings.drop(1)
|
|
54
26
|
end
|
|
55
27
|
|
|
56
28
|
::Rubinius.singleton_class.class_eval do
|
|
57
29
|
def raise_exception_with_current_bindings(exc)
|
|
58
30
|
if exc.bindings.empty?
|
|
59
|
-
exc.instance_variable_set(:@bindings, WebConsole
|
|
31
|
+
exc.instance_variable_set(:@bindings, WebConsole.caller_bindings)
|
|
60
32
|
end
|
|
61
33
|
|
|
62
34
|
raise_exception_without_current_bindings(exc)
|
|
@@ -1,8 +1,33 @@
|
|
|
1
|
+
class Exception
|
|
2
|
+
# Returns an array of the exception backtrace locations bindings.
|
|
3
|
+
#
|
|
4
|
+
# The list won't map to the traces in #backtrace 1 to 1, because we can't
|
|
5
|
+
# build bindings for every trace (C functions, for example).
|
|
6
|
+
#
|
|
7
|
+
# Every integration should set the instance variable.
|
|
8
|
+
def bindings
|
|
9
|
+
defined?(@bindings) ? @bindings : []
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
|
|
1
13
|
case RUBY_ENGINE
|
|
2
14
|
when 'rbx'
|
|
3
15
|
require 'web_console/integration/rubinius'
|
|
4
|
-
when 'jruby'
|
|
5
|
-
require 'web_console/integration/jruby'
|
|
6
16
|
when 'ruby'
|
|
7
17
|
require 'web_console/integration/cruby'
|
|
18
|
+
else
|
|
19
|
+
# Prevent a `method redefined; discarding old caller_bindings` warning.
|
|
20
|
+
|
|
21
|
+
module WebConsole
|
|
22
|
+
# Returns the Ruby bindings of Kernel#callers locations.
|
|
23
|
+
#
|
|
24
|
+
# The list of bindings here doesn't map 1 to 1 with Kernel#callers, as we
|
|
25
|
+
# can't build Ruby bindings for C functions or the equivalent native
|
|
26
|
+
# implementations in JRuby and Rubinius.
|
|
27
|
+
#
|
|
28
|
+
# This method needs to be overridden by every integration.
|
|
29
|
+
def self.caller_bindings
|
|
30
|
+
raise NotImplementedError
|
|
31
|
+
end
|
|
32
|
+
end
|
|
8
33
|
end
|
|
@@ -17,7 +17,7 @@ module WebConsole
|
|
|
17
17
|
def call(env)
|
|
18
18
|
app_exception = catch :app_exception do
|
|
19
19
|
request = create_regular_or_whiny_request(env)
|
|
20
|
-
return
|
|
20
|
+
return call_app(env) unless request.from_whitelisted_ip?
|
|
21
21
|
|
|
22
22
|
if id = id_for_repl_session_update(request)
|
|
23
23
|
return update_repl_session(id, request)
|
|
@@ -25,15 +25,9 @@ module WebConsole
|
|
|
25
25
|
return change_stack_trace(id, request)
|
|
26
26
|
end
|
|
27
27
|
|
|
28
|
-
status, headers, body =
|
|
28
|
+
status, headers, body = call_app(env)
|
|
29
29
|
|
|
30
|
-
if
|
|
31
|
-
session = Session.from_exception(exception)
|
|
32
|
-
elsif binding = env['web_console.binding']
|
|
33
|
-
session = Session.from_binding(binding)
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
if session && acceptable_content_type?(headers)
|
|
30
|
+
if session = Session.from(Thread.current) and acceptable_content_type?(headers)
|
|
37
31
|
response = Response.new(body, status, headers)
|
|
38
32
|
template = Template.new(env, session)
|
|
39
33
|
|
|
@@ -49,13 +43,18 @@ module WebConsole
|
|
|
49
43
|
WebConsole.logger.error("\n#{e.class}: #{e}\n\tfrom #{e.backtrace.join("\n\tfrom ")}")
|
|
50
44
|
raise e
|
|
51
45
|
ensure
|
|
46
|
+
# Clean up the fiber locals after the session creation. Object#console
|
|
47
|
+
# uses those to communicate the current binding or exception to the middleware.
|
|
48
|
+
Thread.current[:__web_console_exception] = nil
|
|
49
|
+
Thread.current[:__web_console_binding] = nil
|
|
50
|
+
|
|
52
51
|
raise app_exception if Exception === app_exception
|
|
53
52
|
end
|
|
54
53
|
|
|
55
54
|
private
|
|
56
55
|
|
|
57
56
|
def acceptable_content_type?(headers)
|
|
58
|
-
Mime::Type.parse(headers['Content-Type']).first == Mime
|
|
57
|
+
Mime::Type.parse(headers['Content-Type']).first == Mime[:html]
|
|
59
58
|
end
|
|
60
59
|
|
|
61
60
|
def json_response(opts = {})
|
data/lib/web_console/railtie.rb
CHANGED
|
@@ -6,21 +6,18 @@ module WebConsole
|
|
|
6
6
|
config.web_console.whitelisted_ips = %w( 127.0.0.1 ::1 )
|
|
7
7
|
|
|
8
8
|
initializer 'web_console.initialize' do
|
|
9
|
+
require 'web_console/integration'
|
|
9
10
|
require 'web_console/extensions'
|
|
10
11
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
ActiveSupport.on_load(:action_controller) do
|
|
16
|
-
ActionController::Base.send(:include, Helper)
|
|
12
|
+
if logger = ::Rails.logger
|
|
13
|
+
WebConsole.logger = logger
|
|
17
14
|
end
|
|
18
15
|
end
|
|
19
16
|
|
|
20
17
|
initializer 'web_console.development_only' do
|
|
21
18
|
unless (config.web_console.development_only == false) || Rails.env.development?
|
|
22
19
|
abort <<-END.strip_heredoc
|
|
23
|
-
Web Console is activated in the #{Rails.env} environment
|
|
20
|
+
Web Console is activated in the #{Rails.env} environment. This is
|
|
24
21
|
usually a mistake. To ensure it's only activated in development
|
|
25
22
|
mode, move it to the development group of your Gemfile:
|
|
26
23
|
|
data/lib/web_console/request.rb
CHANGED
|
@@ -5,14 +5,14 @@ module WebConsole
|
|
|
5
5
|
cattr_accessor :whitelisted_ips
|
|
6
6
|
@@whitelisted_ips = Whitelist.new
|
|
7
7
|
|
|
8
|
-
# Define a vendor MIME type. We can call it using Mime
|
|
8
|
+
# Define a vendor MIME type. We can call it using Mime[:web_console_v2].
|
|
9
9
|
Mime::Type.register 'application/vnd.web-console.v2', :web_console_v2
|
|
10
10
|
|
|
11
11
|
# Returns whether a request came from a whitelisted IP.
|
|
12
12
|
#
|
|
13
13
|
# For a request to hit Web Console features, it needs to come from a white
|
|
14
14
|
# listed IP.
|
|
15
|
-
def
|
|
15
|
+
def from_whitelisted_ip?
|
|
16
16
|
whitelisted_ips.include?(strict_remote_ip)
|
|
17
17
|
end
|
|
18
18
|
|
|
@@ -23,7 +23,7 @@ module WebConsole
|
|
|
23
23
|
|
|
24
24
|
# Returns whether the request is acceptable.
|
|
25
25
|
def acceptable?
|
|
26
|
-
xhr? && accepts.any? { |mime| Mime
|
|
26
|
+
xhr? && accepts.any? { |mime| Mime[:web_console_v2] == mime }
|
|
27
27
|
end
|
|
28
28
|
|
|
29
29
|
private
|
data/lib/web_console/session.rb
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
module WebConsole
|
|
2
|
-
# A session lets you persist
|
|
3
|
-
#
|
|
2
|
+
# A session lets you persist an +Evaluator+ instance in memory associated
|
|
3
|
+
# with multiple bindings.
|
|
4
4
|
#
|
|
5
5
|
# Each newly created session is persisted into memory and you can find it
|
|
6
|
-
# later its +id+.
|
|
6
|
+
# later by its +id+.
|
|
7
7
|
#
|
|
8
8
|
# A session may be associated with multiple bindings. This is used by the
|
|
9
9
|
# error pages only, as currently, this is the only client that needs to do
|
|
@@ -21,14 +21,19 @@ module WebConsole
|
|
|
21
21
|
inmemory_storage[id]
|
|
22
22
|
end
|
|
23
23
|
|
|
24
|
-
# Create a Session from an exception.
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
#
|
|
30
|
-
|
|
31
|
-
|
|
24
|
+
# Create a Session from an binding or exception in a storage.
|
|
25
|
+
#
|
|
26
|
+
# The storage is expected to respond to #[]. The binding is expected in
|
|
27
|
+
# :__web_console_binding and the exception in :__web_console_exception.
|
|
28
|
+
#
|
|
29
|
+
# Can return nil, if no binding or exception have been preserved in the
|
|
30
|
+
# storage.
|
|
31
|
+
def from(storage)
|
|
32
|
+
if exc = storage[:__web_console_exception]
|
|
33
|
+
new(ExceptionMapper.new(exc))
|
|
34
|
+
elsif binding = storage[:__web_console_binding]
|
|
35
|
+
new([binding])
|
|
36
|
+
end
|
|
32
37
|
end
|
|
33
38
|
end
|
|
34
39
|
|
|
@@ -37,8 +42,8 @@ module WebConsole
|
|
|
37
42
|
|
|
38
43
|
def initialize(bindings)
|
|
39
44
|
@id = SecureRandom.hex(16)
|
|
40
|
-
@bindings =
|
|
41
|
-
@evaluator = Evaluator.new(
|
|
45
|
+
@bindings = bindings
|
|
46
|
+
@evaluator = Evaluator.new(bindings.first)
|
|
42
47
|
|
|
43
48
|
store_into_memory
|
|
44
49
|
end
|
|
@@ -488,7 +488,7 @@ REPLConsole.request = function request(method, url, params, callback) {
|
|
|
488
488
|
xhr.open(method, url, true);
|
|
489
489
|
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
|
|
490
490
|
xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
|
|
491
|
-
xhr.setRequestHeader("Accept", "<%= Mime
|
|
491
|
+
xhr.setRequestHeader("Accept", "<%= Mime[:web_console_v2] %>");
|
|
492
492
|
xhr.send(params);
|
|
493
493
|
|
|
494
494
|
xhr.onreadystatechange = function() {
|
|
@@ -1,11 +1,7 @@
|
|
|
1
1
|
require 'action_view'
|
|
2
|
-
require '
|
|
3
|
-
require 'active_support/core_ext/string/access'
|
|
4
|
-
require 'json'
|
|
5
|
-
require 'web_console/whitelist'
|
|
6
|
-
require 'web_console/request'
|
|
7
|
-
require 'web_console/view'
|
|
2
|
+
require 'web_console'
|
|
8
3
|
require 'web_console/testing/helper'
|
|
4
|
+
Mime = { web_console_v2: 'fake' }
|
|
9
5
|
|
|
10
6
|
module WebConsole
|
|
11
7
|
module Testing
|
data/lib/web_console/version.rb
CHANGED
data/lib/web_console/view.rb
CHANGED
|
@@ -5,7 +5,7 @@ module WebConsole
|
|
|
5
5
|
# The error pages are special, because they are the only pages that
|
|
6
6
|
# currently require multiple bindings. We get those from exceptions.
|
|
7
7
|
def only_on_error_page(*args)
|
|
8
|
-
yield if
|
|
8
|
+
yield if Thread.current[:__web_console_exception].present?
|
|
9
9
|
end
|
|
10
10
|
|
|
11
11
|
# Render JavaScript inside a script tag and a closure.
|
|
@@ -14,6 +14,7 @@ module WebConsole
|
|
|
14
14
|
# script tag and enclosed in a closure, so you don't have to worry for
|
|
15
15
|
# leaking globals, unless you explicitly want to.
|
|
16
16
|
def render_javascript(template)
|
|
17
|
+
assign(template: template)
|
|
17
18
|
render(template: template, layout: 'layouts/javascript')
|
|
18
19
|
end
|
|
19
20
|
|
|
@@ -25,6 +26,14 @@ module WebConsole
|
|
|
25
26
|
render(template: template, layout: 'layouts/inlined_string')
|
|
26
27
|
end
|
|
27
28
|
|
|
29
|
+
# Custom ActionView::Base#render wrapper which silences all the log
|
|
30
|
+
# printings.
|
|
31
|
+
#
|
|
32
|
+
# Helps to keep the Rails logs clean during errors.
|
|
33
|
+
def render(*)
|
|
34
|
+
WebConsole.logger.silence { super }
|
|
35
|
+
end
|
|
36
|
+
|
|
28
37
|
# Override method for ActionView::Helpers::TranslationHelper#t.
|
|
29
38
|
#
|
|
30
39
|
# This method escapes the original return value for JavaScript, since the
|
|
@@ -4,9 +4,9 @@ module WebConsole
|
|
|
4
4
|
# If any calls to +from_whitelisted_ip?+ and +acceptable_content_type?+
|
|
5
5
|
# return false, an info log message will be displayed in users' logs.
|
|
6
6
|
class WhinyRequest < SimpleDelegator
|
|
7
|
-
def
|
|
8
|
-
whine_unless request.
|
|
9
|
-
"Cannot render console from #{request.
|
|
7
|
+
def from_whitelisted_ip?
|
|
8
|
+
whine_unless request.from_whitelisted_ip? do
|
|
9
|
+
"Cannot render console from #{request.strict_remote_ip}! " \
|
|
10
10
|
"Allowed networks: #{request.whitelisted_ips}"
|
|
11
11
|
end
|
|
12
12
|
end
|
data/lib/web_console.rb
CHANGED
|
@@ -1,25 +1,30 @@
|
|
|
1
|
-
require '
|
|
2
|
-
|
|
1
|
+
require 'active_support/dependencies/autoload'
|
|
3
2
|
require 'active_support/lazy_load_hooks'
|
|
4
3
|
require 'active_support/logger'
|
|
5
4
|
|
|
6
|
-
require 'web_console/integration'
|
|
7
|
-
require 'web_console/railtie'
|
|
8
|
-
require 'web_console/errors'
|
|
9
|
-
require 'web_console/helper'
|
|
10
|
-
require 'web_console/evaluator'
|
|
11
|
-
require 'web_console/session'
|
|
12
|
-
require 'web_console/template'
|
|
13
|
-
require 'web_console/middleware'
|
|
14
|
-
require 'web_console/whitelist'
|
|
15
|
-
require 'web_console/request'
|
|
16
|
-
require 'web_console/response'
|
|
17
|
-
require 'web_console/view'
|
|
18
|
-
require 'web_console/whiny_request'
|
|
19
|
-
|
|
20
5
|
module WebConsole
|
|
6
|
+
extend ActiveSupport::Autoload
|
|
7
|
+
|
|
8
|
+
autoload :View
|
|
9
|
+
autoload :Evaluator
|
|
10
|
+
autoload :ExceptionMapper
|
|
11
|
+
autoload :Session
|
|
12
|
+
autoload :Response
|
|
13
|
+
autoload :Request
|
|
14
|
+
autoload :WhinyRequest
|
|
15
|
+
autoload :Whitelist
|
|
16
|
+
autoload :Template
|
|
17
|
+
autoload :Middleware
|
|
18
|
+
|
|
19
|
+
autoload_at 'web_console/errors' do
|
|
20
|
+
autoload :Error
|
|
21
|
+
autoload :DoubleRenderError
|
|
22
|
+
end
|
|
23
|
+
|
|
21
24
|
mattr_accessor :logger
|
|
22
25
|
@@logger = ActiveSupport::Logger.new($stderr)
|
|
23
26
|
|
|
24
27
|
ActiveSupport.run_load_hooks(:web_console, self)
|
|
25
28
|
end
|
|
29
|
+
|
|
30
|
+
require 'web_console/railtie'
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: web-console
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version:
|
|
4
|
+
version: 3.3.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Charlie Somerville
|
|
@@ -11,7 +11,7 @@ authors:
|
|
|
11
11
|
autorequire:
|
|
12
12
|
bindir: bin
|
|
13
13
|
cert_chain: []
|
|
14
|
-
date: 2016-
|
|
14
|
+
date: 2016-07-05 00:00:00.000000000 Z
|
|
15
15
|
dependencies:
|
|
16
16
|
- !ruby/object:Gem::Dependency
|
|
17
17
|
name: railties
|
|
@@ -19,90 +19,56 @@ dependencies:
|
|
|
19
19
|
requirements:
|
|
20
20
|
- - ">="
|
|
21
21
|
- !ruby/object:Gem::Version
|
|
22
|
-
version: '
|
|
22
|
+
version: '5.0'
|
|
23
23
|
type: :runtime
|
|
24
24
|
prerelease: false
|
|
25
25
|
version_requirements: !ruby/object:Gem::Requirement
|
|
26
26
|
requirements:
|
|
27
27
|
- - ">="
|
|
28
28
|
- !ruby/object:Gem::Version
|
|
29
|
-
version: '
|
|
29
|
+
version: '5.0'
|
|
30
30
|
- !ruby/object:Gem::Dependency
|
|
31
31
|
name: activemodel
|
|
32
32
|
requirement: !ruby/object:Gem::Requirement
|
|
33
33
|
requirements:
|
|
34
34
|
- - ">="
|
|
35
35
|
- !ruby/object:Gem::Version
|
|
36
|
-
version: '
|
|
36
|
+
version: '5.0'
|
|
37
37
|
type: :runtime
|
|
38
38
|
prerelease: false
|
|
39
39
|
version_requirements: !ruby/object:Gem::Requirement
|
|
40
40
|
requirements:
|
|
41
41
|
- - ">="
|
|
42
42
|
- !ruby/object:Gem::Version
|
|
43
|
-
version: '
|
|
43
|
+
version: '5.0'
|
|
44
44
|
- !ruby/object:Gem::Dependency
|
|
45
|
-
name:
|
|
45
|
+
name: actionview
|
|
46
46
|
requirement: !ruby/object:Gem::Requirement
|
|
47
47
|
requirements:
|
|
48
48
|
- - ">="
|
|
49
49
|
- !ruby/object:Gem::Version
|
|
50
|
-
version: '
|
|
51
|
-
- - "<"
|
|
52
|
-
- !ruby/object:Gem::Version
|
|
53
|
-
version: '4.0'
|
|
50
|
+
version: '5.0'
|
|
54
51
|
type: :runtime
|
|
55
52
|
prerelease: false
|
|
56
53
|
version_requirements: !ruby/object:Gem::Requirement
|
|
57
54
|
requirements:
|
|
58
55
|
- - ">="
|
|
59
56
|
- !ruby/object:Gem::Version
|
|
60
|
-
version: '
|
|
61
|
-
- - "<"
|
|
62
|
-
- !ruby/object:Gem::Version
|
|
63
|
-
version: '4.0'
|
|
57
|
+
version: '5.0'
|
|
64
58
|
- !ruby/object:Gem::Dependency
|
|
65
|
-
name:
|
|
59
|
+
name: debug_inspector
|
|
66
60
|
requirement: !ruby/object:Gem::Requirement
|
|
67
61
|
requirements:
|
|
68
62
|
- - ">="
|
|
69
63
|
- !ruby/object:Gem::Version
|
|
70
|
-
version: 0
|
|
64
|
+
version: '0'
|
|
71
65
|
type: :runtime
|
|
72
66
|
prerelease: false
|
|
73
67
|
version_requirements: !ruby/object:Gem::Requirement
|
|
74
68
|
requirements:
|
|
75
69
|
- - ">="
|
|
76
70
|
- !ruby/object:Gem::Version
|
|
77
|
-
version: 0
|
|
78
|
-
- !ruby/object:Gem::Dependency
|
|
79
|
-
name: actionmailer
|
|
80
|
-
requirement: !ruby/object:Gem::Requirement
|
|
81
|
-
requirements:
|
|
82
|
-
- - ">="
|
|
83
|
-
- !ruby/object:Gem::Version
|
|
84
|
-
version: '4.0'
|
|
85
|
-
type: :development
|
|
86
|
-
prerelease: false
|
|
87
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
88
|
-
requirements:
|
|
89
|
-
- - ">="
|
|
90
|
-
- !ruby/object:Gem::Version
|
|
91
|
-
version: '4.0'
|
|
92
|
-
- !ruby/object:Gem::Dependency
|
|
93
|
-
name: activerecord
|
|
94
|
-
requirement: !ruby/object:Gem::Requirement
|
|
95
|
-
requirements:
|
|
96
|
-
- - ">="
|
|
97
|
-
- !ruby/object:Gem::Version
|
|
98
|
-
version: '4.0'
|
|
99
|
-
type: :development
|
|
100
|
-
prerelease: false
|
|
101
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
102
|
-
requirements:
|
|
103
|
-
- - ">="
|
|
104
|
-
- !ruby/object:Gem::Version
|
|
105
|
-
version: '4.0'
|
|
71
|
+
version: '0'
|
|
106
72
|
description:
|
|
107
73
|
email:
|
|
108
74
|
- charlie@charliesomerville.com
|
|
@@ -121,11 +87,10 @@ files:
|
|
|
121
87
|
- lib/web_console.rb
|
|
122
88
|
- lib/web_console/errors.rb
|
|
123
89
|
- lib/web_console/evaluator.rb
|
|
90
|
+
- lib/web_console/exception_mapper.rb
|
|
124
91
|
- lib/web_console/extensions.rb
|
|
125
|
-
- lib/web_console/helper.rb
|
|
126
92
|
- lib/web_console/integration.rb
|
|
127
93
|
- lib/web_console/integration/cruby.rb
|
|
128
|
-
- lib/web_console/integration/jruby.rb
|
|
129
94
|
- lib/web_console/integration/rubinius.rb
|
|
130
95
|
- lib/web_console/locales/en.yml
|
|
131
96
|
- lib/web_console/middleware.rb
|
|
@@ -165,7 +130,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
165
130
|
requirements:
|
|
166
131
|
- - ">="
|
|
167
132
|
- !ruby/object:Gem::Version
|
|
168
|
-
version:
|
|
133
|
+
version: 2.2.2
|
|
169
134
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
170
135
|
requirements:
|
|
171
136
|
- - ">="
|
data/lib/web_console/helper.rb
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
module WebConsole
|
|
2
|
-
module Helper
|
|
3
|
-
# Communicates with the middleware to render a console in a +binding+.
|
|
4
|
-
#
|
|
5
|
-
# If +bidning+ isn't explicitly given, Binding#of_caller will be used to
|
|
6
|
-
# get the binding of the previous frame. E.g. the one that invoked
|
|
7
|
-
# +console+.
|
|
8
|
-
#
|
|
9
|
-
# Raises DoubleRenderError if a double +console+ invocation per request is
|
|
10
|
-
# detected.
|
|
11
|
-
def console(binding = nil)
|
|
12
|
-
raise DoubleRenderError if request.env['web_console.binding']
|
|
13
|
-
|
|
14
|
-
request.env['web_console.binding'] = binding || ::Kernel.binding.of_caller(1)
|
|
15
|
-
|
|
16
|
-
# Make sure nothing is rendered from the view helper. Otherwise
|
|
17
|
-
# you're gonna see unexpected #<Binding:0x007fee4302b078> in the
|
|
18
|
-
# templates.
|
|
19
|
-
nil
|
|
20
|
-
end
|
|
21
|
-
end
|
|
22
|
-
end
|
|
@@ -1,111 +0,0 @@
|
|
|
1
|
-
require 'English'
|
|
2
|
-
require 'active_support/core_ext/string/strip'
|
|
3
|
-
|
|
4
|
-
java_import org.jruby.RubyInstanceConfig
|
|
5
|
-
|
|
6
|
-
module WebConsole
|
|
7
|
-
module JRuby
|
|
8
|
-
class << self
|
|
9
|
-
# Returns whether JRuby is ran in interpreted mode.
|
|
10
|
-
def interpreted_mode?
|
|
11
|
-
compile_mode = ::JRuby.runtime.instance_config.compile_mode
|
|
12
|
-
interpreted_mode = RubyInstanceConfig::CompileMode::OFF
|
|
13
|
-
|
|
14
|
-
compile_mode == interpreted_mode
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
# A proc to be used in Kernel#set_trace_func.
|
|
18
|
-
#
|
|
19
|
-
# It sets Exception#bindings for an error with all the bindings the
|
|
20
|
-
# current ThreadContext contains.
|
|
21
|
-
def set_exception_bindings_trace_func
|
|
22
|
-
proc do |event, file, line, id, binding, classname|
|
|
23
|
-
case event
|
|
24
|
-
when 'raise'
|
|
25
|
-
if $ERROR_INFO.bindings.empty?
|
|
26
|
-
# binding_of_caller will generate an improperly built binding at
|
|
27
|
-
# caller[1]. Every call to a non existent method, constant or a
|
|
28
|
-
# local variable will result in a Java NullPointerException.
|
|
29
|
-
#
|
|
30
|
-
# The binding that Kernel#set_trace_func is giving us is properly
|
|
31
|
-
# built, so we can use in place of the broken one.
|
|
32
|
-
bindings = ::Kernel.binding.callers.drop(2).unshift(binding)
|
|
33
|
-
$ERROR_INFO.instance_variable_set(:@bindings, bindings)
|
|
34
|
-
end
|
|
35
|
-
end
|
|
36
|
-
end
|
|
37
|
-
end
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
# A fake binding for JRuby in non interpreted mode.
|
|
41
|
-
#
|
|
42
|
-
# It won't actually evaluate any code, rather it will tell the user how to
|
|
43
|
-
# enable interpreted mode.
|
|
44
|
-
class FakeJRubyBinding
|
|
45
|
-
TURN_ON_INTERPRETED_MODE_TEXT = <<-END.strip_heredoc
|
|
46
|
-
JRuby needs to run in interpreted mode for introspection support.
|
|
47
|
-
|
|
48
|
-
To turn on interpreted mode, put -J-Djruby.compile.mode=OFF in the
|
|
49
|
-
JRUBY_OPTS environment variable.
|
|
50
|
-
END
|
|
51
|
-
|
|
52
|
-
def TURN_ON_INTERPRETED_MODE_TEXT.inspect
|
|
53
|
-
self
|
|
54
|
-
end
|
|
55
|
-
|
|
56
|
-
TURN_ON_INTERPRETED_MODE_TEXT.freeze
|
|
57
|
-
|
|
58
|
-
def eval(*)
|
|
59
|
-
TURN_ON_INTERPRETED_MODE_TEXT
|
|
60
|
-
end
|
|
61
|
-
end
|
|
62
|
-
|
|
63
|
-
# A fake array of FakeJRubyBinding objects.
|
|
64
|
-
#
|
|
65
|
-
# It is used in Exception#bindings to make sure that when users switch
|
|
66
|
-
# bindings on the UI, they get a FakeJRubyBinding notifying them what to do
|
|
67
|
-
# if they want introspection.
|
|
68
|
-
class FakeJRubyBindingsArray < Array
|
|
69
|
-
def [](*)
|
|
70
|
-
FakeJRubyBinding.new
|
|
71
|
-
end
|
|
72
|
-
|
|
73
|
-
# For Kernel#Array and other implicit conversion API. JRuby expects it to
|
|
74
|
-
# return an object that is_a? an Array. This is the reasoning of
|
|
75
|
-
# FakeJRubyBindingsArray being a subclass of Array.
|
|
76
|
-
def to_ary
|
|
77
|
-
self
|
|
78
|
-
end
|
|
79
|
-
end
|
|
80
|
-
end
|
|
81
|
-
end
|
|
82
|
-
|
|
83
|
-
if WebConsole::JRuby.interpreted_mode?
|
|
84
|
-
::Exception.class_eval do
|
|
85
|
-
def bindings
|
|
86
|
-
@bindings || []
|
|
87
|
-
end
|
|
88
|
-
end
|
|
89
|
-
|
|
90
|
-
# Kernel#set_trace_func will complain about not being able to capture all the
|
|
91
|
-
# events without the JRuby --debug flag.
|
|
92
|
-
silence_warnings do
|
|
93
|
-
set_trace_func WebConsole::JRuby.set_exception_bindings_trace_func
|
|
94
|
-
end
|
|
95
|
-
else
|
|
96
|
-
::Exception.class_eval do
|
|
97
|
-
def bindings
|
|
98
|
-
WebConsole::JRuby::FakeJRubyBindingsArray.new
|
|
99
|
-
end
|
|
100
|
-
end
|
|
101
|
-
|
|
102
|
-
::Binding.class_eval do
|
|
103
|
-
def of_caller(*)
|
|
104
|
-
WebConsole::JRuby::FakeJRubyBinding.new
|
|
105
|
-
end
|
|
106
|
-
|
|
107
|
-
def callers
|
|
108
|
-
WebConsole::JRuby::FakeJRubyBindingsArray.new
|
|
109
|
-
end
|
|
110
|
-
end
|
|
111
|
-
end
|