From a2f685c7c0d1ad3116a624fc47a82724869e7f26 Mon Sep 17 00:00:00 2001 From: Jean Boussier Date: Thu, 1 Jun 2023 11:34:12 +0200 Subject: [PATCH] Cleanly fallback when failing to tokenize ERB templates Fix: https://github.com/rails/rails/issues/48319 Followup: https://github.com/rails/rails/pull/48184 --- actionview/lib/action_view/template/handlers/erb.rb | 2 +- .../test/unparseable_runtime_error_2.html.erb | 8 ++++++++ actionview/test/template/render_test.rb | 13 +++++++++++++ .../lib/active_support/core_ext/erb/util.rb | 5 +++-- 4 files changed, 25 insertions(+), 3 deletions(-) create mode 100644 actionview/test/fixtures/test/unparseable_runtime_error_2.html.erb diff --git a/actionview/lib/action_view/template/handlers/erb.rb b/actionview/lib/action_view/template/handlers/erb.rb index 87ab3453b1..781217fc93 100644 --- a/actionview/lib/action_view/template/handlers/erb.rb +++ b/actionview/lib/action_view/template/handlers/erb.rb @@ -54,7 +54,7 @@ def translate_location(spot, backtrace_location, source) spot[:script_lines] = source.lines spot - rescue LocationParsingError + rescue NotImplementedError, LocationParsingError nil end diff --git a/actionview/test/fixtures/test/unparseable_runtime_error_2.html.erb b/actionview/test/fixtures/test/unparseable_runtime_error_2.html.erb new file mode 100644 index 0000000000..06c5a835fe --- /dev/null +++ b/actionview/test/fixtures/test/unparseable_runtime_error_2.html.erb @@ -0,0 +1,8 @@ +

Oh no!

+This template has a runtime error + + <% if true %> + <%= method_that_does_not_exist %>a + <% end %> + +Yikes! diff --git a/actionview/test/template/render_test.rb b/actionview/test/template/render_test.rb index 6b25a05405..a1576caf78 100644 --- a/actionview/test/template/render_test.rb +++ b/actionview/test/template/render_test.rb @@ -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 diff --git a/activesupport/lib/active_support/core_ext/erb/util.rb b/activesupport/lib/active_support/core_ext/erb/util.rb index 3ce848374c..71c8d8fccf 100644 --- a/activesupport/lib/active_support/core_ext/erb/util.rb +++ b/activesupport/lib/active_support/core_ext/erb/util.rb @@ -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