Cleanly fallback when failing to tokenize ERB templates

Fix: https://github.com/rails/rails/issues/48319
Followup: https://github.com/rails/rails/pull/48184
This commit is contained in:
Jean Boussier 2023-06-01 11:34:12 +02:00
parent d026af43c3
commit a2f685c7c0
4 changed files with 25 additions and 3 deletions

@ -54,7 +54,7 @@ def translate_location(spot, backtrace_location, source)
spot[:script_lines] = source.lines
spot
rescue LocationParsingError
rescue NotImplementedError, LocationParsingError
nil
end

@ -0,0 +1,8 @@
<h1>Oh no!</h1>
This template has a runtime error
<b>
<% if true %>
<%= method_that_does_not_exist %>a
<% end %>
</b>
Yikes!

@ -234,6 +234,19 @@ def test_render_location_conditional_append
assert_equal 8, translated_spot[:first_column]
end
def test_render_location_conditional_append_2
ex = assert_raises(ActionView::Template::Error) {
@view.render(template: "test/unparseable_runtime_error_2")
}
erb_btl = ex.backtrace_locations.first
# Get the spot information from ErrorHighlight
translating_frame = ActionDispatch::ExceptionWrapper::SourceMapLocation.new(erb_btl, ex.template)
translated_spot = translating_frame.spot(ex.cause)
assert_instance_of Integer, translated_spot[:first_column]
end
end
def test_render_partial

@ -166,6 +166,7 @@ def self.tokenize(source) # :nodoc:
while !source.eos?
pos = source.pos
source.scan_until(/(?:#{start_re}|#{finish_re})/)
raise NotImplementedError if source.matched.nil?
len = source.pos - source.matched.bytesize - pos
case source.matched
@ -176,13 +177,13 @@ def self.tokenize(source) # :nodoc:
tokens << [:CODE, source.matched] unless source.matched.empty?
tokens << [:CLOSE, source.scan(finish_re)] unless source.eos?
else
raise NotImplemented
raise NotImplementedError
end
when finish_re
tokens << [:CODE, source.string[pos, len]] if len > 0
tokens << [:CLOSE, source.matched]
else
raise NotImplemented, source.matched
raise NotImplementedError, source.matched
end
end