From 8d5e71f85633fa9c809080b42c873cd44a9f8eab Mon Sep 17 00:00:00 2001 From: Dylan Thacker-Smith Date: Wed, 27 May 2015 18:59:51 -0400 Subject: [PATCH 1/2] Allow the exception handler to convert exceptions to hide error messages. --- lib/liquid/context.rb | 22 +++++++++++++++++----- lib/liquid/template.rb | 6 ++---- test/integration/error_handling_test.rb | 17 ++++++++++++++--- test/test_helper.rb | 4 ++++ 4 files changed, 37 insertions(+), 12 deletions(-) diff --git a/lib/liquid/context.rb b/lib/liquid/context.rb index eba7c89..bafbd63 100644 --- a/lib/liquid/context.rb +++ b/lib/liquid/context.rb @@ -13,7 +13,7 @@ module Liquid # context['bob'] #=> nil class Context class Context attr_reader :scopes, :errors, :registers, :environments, :resource_limits - attr_accessor :exception_handler, :render_errors + attr_accessor :exception_handler def initialize(environments = {}, outer_scope = {}, registers = {}, rethrow_errors = false, resource_limits = nil) @environments = [environments].flatten @@ -22,12 +22,11 @@ module Liquid @errors = [] @resource_limits = resource_limits || ResourceLimits.new(Template.default_resource_limits) squash_instance_assigns_with_environments - @render_errors = true @this_stack_used = false if rethrow_errors - self.exception_handler = ->(e) { true } + self.exception_handler = ->(e) { raise } end @interrupts = [] @@ -68,9 +67,22 @@ module Liquid e.set_line_number_from_token(token) end + output = nil + + if exception_handler + result = exception_handler.call(e) + case result + when Exception + e = result + e.set_line_number_from_token(token) if e.is_a?(Liquid::Error) + when String + output = result + else + raise if result + end + end errors.push(e) - raise if exception_handler && exception_handler.call(e) - render_errors ? Liquid::Error.render(e) : '' + output || Liquid::Error.render(e) end def invoke(method, *args) diff --git a/lib/liquid/template.rb b/lib/liquid/template.rb index 3791c89..a6e36b1 100644 --- a/lib/liquid/template.rb +++ b/lib/liquid/template.rb @@ -17,7 +17,7 @@ module Liquid locale: I18n.new } - attr_accessor :root, :render_errors + attr_accessor :root attr_reader :resource_limits @@file_system = BlankFileSystem.new @@ -168,7 +168,7 @@ module Liquid c = args.shift if @rethrow_errors - c.exception_handler = ->(e) { true } + c.exception_handler = ->(e) { raise } end c @@ -183,8 +183,6 @@ module Liquid raise ArgumentError, "Expected Hash or Liquid::Context as parameter" end - context.render_errors = self.render_errors unless self.render_errors.nil? - case args.last when Hash options = args.pop diff --git a/test/integration/error_handling_test.rb b/test/integration/error_handling_test.rb index 67848fc..0a5878c 100644 --- a/test/integration/error_handling_test.rb +++ b/test/integration/error_handling_test.rb @@ -186,10 +186,21 @@ class ErrorHandlingTest < Minitest::Test end end - def test_disabling_error_rendering + def test_exception_handler_with_string_result template = Liquid::Template.parse('This is an argument error: {{ errors.argument_error }}') - template.render_errors = false - assert_equal 'This is an argument error: ', template.render('errors' => ErrorDrop.new) + output = template.render({ 'errors' => ErrorDrop.new }, exception_handler: ->(e) { '' }) + assert_equal 'This is an argument error: ', output assert_equal [ArgumentError], template.errors.map(&:class) end + + class InternalError < Liquid::Error + end + + def test_exception_handler_with_exception_result + template = Liquid::Template.parse('This is a runtime error: {{ errors.runtime_error }}') + handler = ->(e) { e.is_a?(Liquid::Error) ? e : InternalError.new('internal') } + output = template.render({ 'errors' => ErrorDrop.new }, exception_handler: handler) + assert_equal 'This is a runtime error: Liquid error: internal', output + assert_equal [InternalError], template.errors.map(&:class) + end end diff --git a/test/test_helper.rb b/test/test_helper.rb index 0e21838..fa81e8f 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -102,6 +102,10 @@ class ErrorDrop < Liquid::Drop raise Liquid::SyntaxError, 'syntax error' end + def runtime_error + raise RuntimeError, 'runtime error' + end + def exception raise Exception, 'exception' end From 8ff1b8e01f81efc1419110a4463fcf3b0c3b605a Mon Sep 17 00:00:00 2001 From: Dylan Thacker-Smith Date: Thu, 28 May 2015 09:22:02 -0400 Subject: [PATCH 2/2] Test set_line_number_from_token after exception is converted. --- test/integration/error_handling_test.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/integration/error_handling_test.rb b/test/integration/error_handling_test.rb index 0a5878c..54922ca 100644 --- a/test/integration/error_handling_test.rb +++ b/test/integration/error_handling_test.rb @@ -197,10 +197,10 @@ class ErrorHandlingTest < Minitest::Test end def test_exception_handler_with_exception_result - template = Liquid::Template.parse('This is a runtime error: {{ errors.runtime_error }}') + template = Liquid::Template.parse('This is a runtime error: {{ errors.runtime_error }}', line_numbers: true) handler = ->(e) { e.is_a?(Liquid::Error) ? e : InternalError.new('internal') } output = template.render({ 'errors' => ErrorDrop.new }, exception_handler: handler) - assert_equal 'This is a runtime error: Liquid error: internal', output + assert_equal 'This is a runtime error: Liquid error (line 1): internal', output assert_equal [InternalError], template.errors.map(&:class) end end