Skip to content

Commit 8cab71c

Browse files
authored
Merge pull request rails#53696 from martinemde/martinemde/handle-multi-line-template-errors
Avoid crashing when highlighting ERB templates with multi-line methods
2 parents 9add4d9 + 5857b8f commit 8cab71c

File tree

3 files changed

+26
-3
lines changed

3 files changed

+26
-3
lines changed

actionview/CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
* Fix a crash in ERB template error highlighting when the error occurs on a
2+
line in the compiled template that is past the end of the source template.
3+
4+
*Martin Emde*
5+
16
* Improve reliability of ERB template error highlighting.
27
Fix infinite loops and crashes in highlighting and
38
improve tolerance for alternate ERB handlers.

actionview/lib/action_view/template/handlers/erb.rb

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,9 @@ def handles_encoding?
4242
# source location inside the template.
4343
def translate_location(spot, backtrace_location, source)
4444
# Tokenize the source line
45-
tokens = ::ERB::Util.tokenize(source.lines[backtrace_location.lineno - 1])
45+
source_lines = source.lines
46+
return nil if source_lines.size < backtrace_location.lineno
47+
tokens = ::ERB::Util.tokenize(source_lines[backtrace_location.lineno - 1])
4648
new_first_column = find_offset(spot[:snippet], tokens, spot[:first_column])
4749
lineno_delta = spot[:first_lineno] - backtrace_location.lineno
4850
spot[:first_lineno] -= lineno_delta
@@ -51,7 +53,7 @@ def translate_location(spot, backtrace_location, source)
5153
column_delta = spot[:first_column] - new_first_column
5254
spot[:first_column] -= column_delta
5355
spot[:last_column] -= column_delta
54-
spot[:script_lines] = source.lines
56+
spot[:script_lines] = source_lines
5557

5658
spot
5759
rescue NotImplementedError, LocationParsingError

actionview/test/template/template_test.rb

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -339,10 +339,11 @@ def test_template_translate_location
339339
assert_equal expected, new_template(source).translate_location(backtrace_location, spot)
340340
end
341341

342+
# merely tests for the case where the backtrace and spot disagree about lineno
342343
def test_template_translate_location_lineno_offset
343344
highlight = "nomethoderror"
344345
source = "<%= nomethoderror %>"
345-
compiled = "\n'.freeze; @output_buffer.append= nomethoderror ; @output_buffer.safe_append='\n"
346+
compiled = "'.freeze; @output_buffer.append= nomethoderror ; @output_buffer.safe_append='"
346347

347348
backtrace_location = Data.define(:lineno).new(lineno: 1)
348349
spot = spot_highlight(compiled, highlight, first_lineno: 2, last_lineno: 2)
@@ -351,6 +352,21 @@ def test_template_translate_location_lineno_offset
351352
assert_equal expected, new_template(source).translate_location(backtrace_location, spot)
352353
end
353354

355+
# We are testing the failure case here. `find_offset` doesn't correctly handle the case
356+
# where the line number is not the same in the backtrace and template.
357+
def test_template_translate_location_with_multiline_code_source
358+
highlight = "nomethoderror"
359+
source = "<%=\ngood(\n nomethoderror\n) %>"
360+
extracted_line = " nomethoderror\n"
361+
compiled = "ValidatedOutputBuffer.wrap(@output_buffer, ({}), ' \ngood(\n nomethoderror\n" \
362+
") '.freeze, true).safe_none_append=( \ngood(\n nomethoderror\n) );\n@output_buffer"
363+
364+
backtrace_location = Data.define(:lineno).new(lineno: 6)
365+
spot = spot_highlight(compiled, highlight, first_column: 1, first_lineno: 6, last_lineno: 6, snippet: extracted_line)
366+
367+
assert_equal spot, new_template(source).translate_location(backtrace_location, spot)
368+
end
369+
354370
def test_template_translate_location_with_multibye_string_before_highlight
355371
highlight = "nomethoderror"
356372
source = String.new("\u{a5}<%= nomethoderror %>", encoding: Encoding::UTF_8) # yen symbol

0 commit comments

Comments
 (0)