better_errors 2.5.1 → 2.9.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +130 -0
  3. data/.github/workflows/release.yml +64 -0
  4. data/.ruby-version +1 -0
  5. data/Gemfile +6 -1
  6. data/README.md +34 -2
  7. data/better_errors.gemspec +3 -1
  8. data/gemfiles/pry010.gemfile +2 -1
  9. data/gemfiles/pry011.gemfile +2 -1
  10. data/gemfiles/pry09.gemfile +2 -1
  11. data/gemfiles/rack.gemfile +2 -1
  12. data/gemfiles/rack_boc.gemfile +2 -1
  13. data/gemfiles/rails42.gemfile +3 -1
  14. data/gemfiles/rails42_boc.gemfile +3 -1
  15. data/gemfiles/rails42_haml.gemfile +3 -1
  16. data/gemfiles/rails50.gemfile +3 -1
  17. data/gemfiles/rails50_boc.gemfile +3 -1
  18. data/gemfiles/rails50_haml.gemfile +3 -1
  19. data/gemfiles/rails51.gemfile +3 -1
  20. data/gemfiles/rails51_boc.gemfile +3 -1
  21. data/gemfiles/rails51_haml.gemfile +3 -1
  22. data/gemfiles/rails52.gemfile +3 -1
  23. data/gemfiles/rails52_boc.gemfile +3 -1
  24. data/gemfiles/rails52_haml.gemfile +3 -1
  25. data/gemfiles/rails60.gemfile +8 -0
  26. data/gemfiles/rails60_boc.gemfile +9 -0
  27. data/gemfiles/rails60_haml.gemfile +9 -0
  28. data/lib/better_errors.rb +20 -33
  29. data/lib/better_errors/editor.rb +99 -0
  30. data/lib/better_errors/error_page.rb +31 -4
  31. data/lib/better_errors/exception_hint.rb +29 -0
  32. data/lib/better_errors/middleware.rb +59 -12
  33. data/lib/better_errors/raised_exception.rb +25 -4
  34. data/lib/better_errors/stack_frame.rb +8 -2
  35. data/lib/better_errors/templates/main.erb +61 -17
  36. data/lib/better_errors/templates/text.erb +5 -2
  37. data/lib/better_errors/templates/variable_info.erb +9 -2
  38. data/lib/better_errors/version.rb +1 -1
  39. metadata +28 -7
  40. data/.travis.yml +0 -62
@@ -1,12 +1,23 @@
1
+ require 'better_errors/exception_hint'
2
+
1
3
  # @private
2
4
  module BetterErrors
3
5
  class RaisedException
4
- attr_reader :exception, :message, :backtrace
6
+ attr_reader :exception, :message, :backtrace, :hint
5
7
 
6
8
  def initialize(exception)
7
- if exception.respond_to?(:cause)
9
+ if exception.class.name == "ActionView::Template::Error" && exception.respond_to?(:cause)
10
+ # Rails 6+ exceptions of this type wrap the "real" exception, and the real exception
11
+ # is actually more useful than the ActionView-provided wrapper. Once Better Errors
12
+ # supports showing all exceptions in the cause stack, this should go away. Or perhaps
13
+ # this can be changed to provide guidance by showing the second error in the cause stack
14
+ # under this condition.
8
15
  exception = exception.cause if exception.cause
9
16
  elsif exception.respond_to?(:original_exception) && exception.original_exception
17
+ # This supports some specific Rails exceptions, and this is not intended to act the same as
18
+ # the Ruby's {Exception#cause}.
19
+ # It's possible this should only support ActionView::Template::Error, but by not changing
20
+ # this we're preserving longstanding behavior of Better Errors with Rails < 6.
10
21
  exception = exception.original_exception
11
22
  end
12
23
 
@@ -14,6 +25,7 @@ module BetterErrors
14
25
  @message = exception.message
15
26
 
16
27
  setup_backtrace
28
+ setup_hint
17
29
  massage_syntax_error
18
30
  end
19
31
 
@@ -36,8 +48,13 @@ module BetterErrors
36
48
 
37
49
  def setup_backtrace_from_bindings
38
50
  @backtrace = exception.__better_errors_bindings_stack.map { |binding|
39
- file = binding.eval "__FILE__"
40
- line = binding.eval "__LINE__"
51
+ if binding.respond_to?(:source_location) # Ruby >= 2.6
52
+ file = binding.source_location[0]
53
+ line = binding.source_location[1]
54
+ else
55
+ file = binding.eval "__FILE__"
56
+ line = binding.eval "__LINE__"
57
+ end
41
58
  name = binding.frame_description
42
59
  StackFrame.new(file, line, name, binding)
43
60
  }
@@ -64,5 +81,9 @@ module BetterErrors
64
81
  end
65
82
  end
66
83
  end
84
+
85
+ def setup_hint
86
+ @hint = ExceptionHint.new(exception).hint
87
+ end
67
88
  end
68
89
  end
@@ -69,7 +69,10 @@ module BetterErrors
69
69
  def local_variables
70
70
  return {} unless frame_binding
71
71
 
72
- frame_binding.eval("local_variables").each_with_object({}) do |name, hash|
72
+ lv = frame_binding.eval("local_variables")
73
+ return {} unless lv
74
+
75
+ lv.each_with_object({}) do |name, hash|
73
76
  # Ruby 2.2's local_variables will include the hidden #$! variable if
74
77
  # called from within a rescue context. This is not a valid variable name,
75
78
  # so the local_variable_get method complains. This should probably be
@@ -94,7 +97,10 @@ module BetterErrors
94
97
  end
95
98
 
96
99
  def visible_instance_variables
97
- frame_binding.eval("instance_variables") - BetterErrors.ignored_instance_variables
100
+ iv = frame_binding.eval("instance_variables")
101
+ return {} unless iv
102
+
103
+ iv - BetterErrors.ignored_instance_variables
98
104
  end
99
105
 
100
106
  def to_s
@@ -90,7 +90,7 @@
90
90
  nav.sidebar,
91
91
  .frame_info {
92
92
  position: fixed;
93
- top: 95px;
93
+ top: 102px;
94
94
  bottom: 0;
95
95
 
96
96
  box-sizing: border-box;
@@ -102,7 +102,7 @@
102
102
  nav.sidebar {
103
103
  width: 40%;
104
104
  left: 20px;
105
- top: 115px;
105
+ top: 122px;
106
106
  bottom: 20px;
107
107
  }
108
108
 
@@ -131,7 +131,7 @@
131
131
  header.exception {
132
132
  padding: 18px 20px;
133
133
 
134
- height: 59px;
134
+ height: 66px;
135
135
  min-height: 59px;
136
136
 
137
137
  overflow: hidden;
@@ -146,6 +146,14 @@
146
146
  }
147
147
 
148
148
  /* Heading */
149
+ header.exception .fix-actions {
150
+ margin-top: .5em;
151
+ }
152
+
153
+ header.exception .fix-actions input[type=submit] {
154
+ font-weight: bold;
155
+ }
156
+
149
157
  header.exception h2 {
150
158
  font-weight: 200;
151
159
  font-size: 11pt;
@@ -153,7 +161,7 @@
153
161
 
154
162
  header.exception h2,
155
163
  header.exception p {
156
- line-height: 1.4em;
164
+ line-height: 1.5em;
157
165
  overflow: hidden;
158
166
  white-space: pre;
159
167
  text-overflow: ellipsis;
@@ -166,7 +174,7 @@
166
174
 
167
175
  header.exception p {
168
176
  font-weight: 200;
169
- font-size: 20pt;
177
+ font-size: 17pt;
170
178
  color: white;
171
179
  }
172
180
 
@@ -587,6 +595,9 @@
587
595
  color: #8080a0;
588
596
  padding-left: 20px;
589
597
  }
598
+ .console-has-been-used .live-console-hint {
599
+ display: none;
600
+ }
590
601
 
591
602
  .hint:before {
592
603
  content: '\25b2';
@@ -603,17 +614,6 @@
603
614
  margin: 10px 0;
604
615
  }
605
616
 
606
- .sub:before {
607
- content: '';
608
- display: block;
609
- width: 100%;
610
- height: 4px;
611
-
612
- border-radius: 2px;
613
- background: rgba(0, 150, 200, 0.05);
614
- box-shadow: 1px 1px 0 rgba(255, 255, 255, 0.7), inset 0 0 0 1px rgba(0, 0, 0, 0.04), inset 2px 2px 2px rgba(0, 0, 0, 0.07);
615
- }
616
-
617
617
  .sub h3 {
618
618
  color: #39a;
619
619
  font-size: 1.1em;
@@ -744,6 +744,21 @@
744
744
  <header class="exception">
745
745
  <h2><strong><%= exception_type %></strong> <span>at <%= request_path %></span></h2>
746
746
  <p><%= exception_message %></p>
747
+ <% unless active_support_actions.empty? %>
748
+ <div class='fix-actions'>
749
+ <% active_support_actions.each do |action, _| %>
750
+ <form class="button_to" method="post" action="<%= action_dispatch_action_endpoint %>">
751
+ <input type="submit" value="<%= action %>">
752
+ <input type="hidden" name="action" value="<%= action %>">
753
+ <input type="hidden" name="error" value="<%= exception_type %>">
754
+ <input type="hidden" name="location" value="<%= request_path %>">
755
+ </form>
756
+ <% end %>
757
+ </div>
758
+ <% end %>
759
+ <% if exception_hint %>
760
+ <h2>Hint: <%= exception_hint %></h2>
761
+ <% end %>
747
762
  </header>
748
763
  </div>
749
764
 
@@ -780,6 +795,7 @@
780
795
  (function() {
781
796
 
782
797
  var OID = "<%= id %>";
798
+ var csrfToken = "<%= csrf_token %>";
783
799
 
784
800
  var previousFrame = null;
785
801
  var previousFrameInfo = null;
@@ -790,6 +806,7 @@
790
806
  var req = new XMLHttpRequest();
791
807
  req.open("POST", "//" + window.location.host + <%== uri_prefix.gsub("<", "&lt;").inspect %> + "/__better_errors/" + OID + "/" + method, true);
792
808
  req.setRequestHeader("Content-Type", "application/json");
809
+ opts.csrfToken = csrfToken;
793
810
  req.send(JSON.stringify(opts));
794
811
  req.onreadystatechange = function() {
795
812
  if(req.readyState == 4) {
@@ -803,6 +820,28 @@
803
820
  return html.replace(/&/, "&amp;").replace(/</g, "&lt;");
804
821
  }
805
822
 
823
+ function hasConsoleBeenUsedPreviously() {
824
+ return !!document.cookie.split('; ').find(function(cookie) {
825
+ return cookie.startsWith('BetterErrors-has-used-console=');
826
+ });
827
+ }
828
+
829
+ var consoleHasBeenUsed = hasConsoleBeenUsedPreviously();
830
+
831
+ function consoleWasJustUsed() {
832
+ if (consoleHasBeenUsed) {
833
+ return;
834
+ }
835
+
836
+ hideConsoleHint();
837
+ consoleHasBeenUsed = true;
838
+ document.cookie = "BetterErrors-has-used-console=true;path=/;max-age=31536000;samesite"
839
+ }
840
+
841
+ function hideConsoleHint() {
842
+ document.querySelector('body').className += " console-has-been-used";
843
+ }
844
+
806
845
  function REPL(index) {
807
846
  this.index = index;
808
847
 
@@ -824,15 +863,20 @@
824
863
  this.inputElement = this.container.querySelector("input");
825
864
  this.outputElement = this.container.querySelector("pre");
826
865
 
866
+ if (consoleHasBeenUsed) {
867
+ hideConsoleHint();
868
+ }
869
+
827
870
  var self = this;
828
871
  this.inputElement.onkeydown = function(ev) {
829
872
  self.onKeyDown(ev);
873
+ consoleWasJustUsed();
830
874
  };
831
875
 
832
876
  this.setPrompt(">>");
833
877
 
834
878
  REPL.all[this.index] = this;
835
- }
879
+ };
836
880
 
837
881
  REPL.prototype.focus = function() {
838
882
  this.inputElement.focus();
@@ -1,7 +1,10 @@
1
1
  <%== text_heading("=", "%s at %s" % [exception_type, request_path]) %>
2
2
 
3
- > <%== exception_message %>
4
- <% if backtrace_frames.any? %>
3
+ <%== exception_message %>
4
+
5
+ > To access an interactive console with this error, point your browser to: /__better_errors
6
+
7
+ <% if backtrace_frames.any? -%>
5
8
 
6
9
  <%== text_heading("-", "%s, line %i" % [first_frame.pretty_path, first_frame.line]) %>
7
10
 
@@ -1,7 +1,14 @@
1
1
  <header class="trace_info clearfix">
2
2
  <div class="title">
3
3
  <h2 class="name"><%= @frame.name %></h2>
4
- <div class="location"><span class="filename"><a href="<%= editor_url(@frame) %>"><%= @frame.pretty_path %></a></span></div>
4
+ <div class="location">
5
+ <span class="filename">
6
+ <a
7
+ href="<%= editor_url(@frame) %>"
8
+ <%= ENV.key?('BETTER_ERRORS_INSIDE_FRAME') ? "target=_blank" : '' %>
9
+ ><%= @frame.pretty_path %></a>
10
+ </span>
11
+ </div>
5
12
  </div>
6
13
  <div class="code_block clearfix">
7
14
  <%== html_formatted_code_block @frame %>
@@ -18,7 +25,7 @@
18
25
  </header>
19
26
 
20
27
  <% if BetterErrors.binding_of_caller_available? && @frame.frame_binding %>
21
- <div class="hint">
28
+ <div class="hint live-console-hint">
22
29
  This is a live shell. Type in here.
23
30
  </div>
24
31
 
@@ -1,3 +1,3 @@
1
1
  module BetterErrors
2
- VERSION = "2.5.1"
2
+ VERSION = "2.9.1"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: better_errors
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.5.1
4
+ version: 2.9.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Charlie Somerville
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-02-14 00:00:00.000000000 Z
11
+ date: 2020-11-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -39,7 +39,7 @@ dependencies:
39
39
  - !ruby/object:Gem::Version
40
40
  version: '3.5'
41
41
  - !ruby/object:Gem::Dependency
42
- name: rspec-its
42
+ name: rspec-html-matchers
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - ">="
@@ -53,7 +53,7 @@ dependencies:
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
55
  - !ruby/object:Gem::Dependency
56
- name: yard
56
+ name: rspec-its
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - ">="
@@ -67,7 +67,7 @@ dependencies:
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
69
  - !ruby/object:Gem::Dependency
70
- name: kramdown
70
+ name: yard
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
73
  - - ">="
@@ -80,6 +80,20 @@ dependencies:
80
80
  - - ">="
81
81
  - !ruby/object:Gem::Version
82
82
  version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: kramdown
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">"
88
+ - !ruby/object:Gem::Version
89
+ version: 2.0.0
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">"
95
+ - !ruby/object:Gem::Version
96
+ version: 2.0.0
83
97
  - !ruby/object:Gem::Dependency
84
98
  name: erubi
85
99
  requirement: !ruby/object:Gem::Requirement
@@ -132,8 +146,10 @@ extensions: []
132
146
  extra_rdoc_files: []
133
147
  files:
134
148
  - ".coveralls.yml"
149
+ - ".github/workflows/ci.yml"
150
+ - ".github/workflows/release.yml"
135
151
  - ".gitignore"
136
- - ".travis.yml"
152
+ - ".ruby-version"
137
153
  - ".yardopts"
138
154
  - CHANGELOG.md
139
155
  - Gemfile
@@ -157,12 +173,17 @@ files:
157
173
  - gemfiles/rails52.gemfile
158
174
  - gemfiles/rails52_boc.gemfile
159
175
  - gemfiles/rails52_haml.gemfile
176
+ - gemfiles/rails60.gemfile
177
+ - gemfiles/rails60_boc.gemfile
178
+ - gemfiles/rails60_haml.gemfile
160
179
  - lib/better_errors.rb
161
180
  - lib/better_errors/code_formatter.rb
162
181
  - lib/better_errors/code_formatter/html.rb
163
182
  - lib/better_errors/code_formatter/text.rb
183
+ - lib/better_errors/editor.rb
164
184
  - lib/better_errors/error_page.rb
165
185
  - lib/better_errors/exception_extension.rb
186
+ - lib/better_errors/exception_hint.rb
166
187
  - lib/better_errors/inspectable_value.rb
167
188
  - lib/better_errors/middleware.rb
168
189
  - lib/better_errors/rails.rb
@@ -197,7 +218,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
197
218
  - !ruby/object:Gem::Version
198
219
  version: '0'
199
220
  requirements: []
200
- rubygems_version: 3.0.1
221
+ rubygems_version: 3.1.4
201
222
  signing_key:
202
223
  specification_version: 4
203
224
  summary: Better error page for Rails and other Rack apps
@@ -1,62 +0,0 @@
1
- sudo: false
2
- language: ruby
3
- cache: bundler
4
- before_install:
5
- # Since Rails 4.2 only supports rubygems < 2, we must install an older version for it.
6
- - >
7
- if [[ "$BUNDLE_GEMFILE" =~ "rails42" ]]; then
8
- rvm @global do gem install rubygems-update -v '<2'
9
- update_rubygems
10
- rvm @global do gem uninstall bundler --force --executables
11
- rvm @global do gem install bundler -v "~> 1.3"
12
- fi
13
-
14
- notifications:
15
- webhooks:
16
- # With COVERALLS_PARALLEL, coverage information sent to coveralls will not be processed until
17
- # this webhook is sent.
18
- # https://coveralls.zendesk.com/hc/en-us/articles/203484329-Parallel-Build-Webhook
19
- - secure: "YnHYbTq51ySistjvOxsuNhyg4GLuUffEJstTYeGYXiBF7HG5h43IVYo8KNuLzwkgsOYBcNo+YMdQX7qCqJffSbhsr1FZRSzBmjFFxcyD4hu+ukM2theZ4mePVAZiePscYvQPRNY4hIb4d3egStJEytkalDhB3sOebF57tIaCssg="
20
- rvm:
21
- - 2.2.10
22
- - 2.3.7
23
- - 2.4.4
24
- - 2.5.1
25
- - ruby-head
26
- gemfile:
27
- - gemfiles/rails42.gemfile
28
- - gemfiles/rails50.gemfile
29
- - gemfiles/rails51.gemfile
30
- - gemfiles/rails52.gemfile
31
- - gemfiles/rails42_haml.gemfile
32
- - gemfiles/rails50_haml.gemfile
33
- - gemfiles/rails51_haml.gemfile
34
- - gemfiles/rails52_haml.gemfile
35
- - gemfiles/rails42_boc.gemfile
36
- - gemfiles/rails50_boc.gemfile
37
- - gemfiles/rails51_boc.gemfile
38
- - gemfiles/rails52_boc.gemfile
39
- - gemfiles/rack.gemfile
40
- - gemfiles/rack_boc.gemfile
41
- - gemfiles/pry09.gemfile
42
- - gemfiles/pry010.gemfile
43
- - gemfiles/pry011.gemfile
44
- matrix:
45
- fast_finish: true
46
- allow_failures:
47
- - rvm: ruby-head
48
- - gemfile: gemfiles/pry010.gemfile
49
- - gemfile: gemfiles/pry011.gemfile
50
- exclude:
51
- - rvm: 2.4.4
52
- gemfile: gemfiles/rails42.gemfile
53
- - rvm: 2.4.4
54
- gemfile: gemfiles/rails42_boc.gemfile
55
- - rvm: 2.4.4
56
- gemfile: gemfiles/rails42_haml.gemfile
57
- - rvm: 2.5.1
58
- gemfile: gemfiles/rails42.gemfile
59
- - rvm: 2.5.1
60
- gemfile: gemfiles/rails42_boc.gemfile
61
- - rvm: 2.5.1
62
- gemfile: gemfiles/rails42_haml.gemfile