[Haml] Ensure that haml_buffer is reset even if an exception is raised.

Closes gh-53
This commit is contained in:
Nathan Weizenbaum 2009-11-03 20:08:43 -08:00
parent a13763678a
commit 4fe3e5045f
4 changed files with 35 additions and 5 deletions

View File

@ -12,6 +12,9 @@
* Fixed a bug in outer-whitespace nuking where whitespace-only Ruby strings * Fixed a bug in outer-whitespace nuking where whitespace-only Ruby strings
blocked whitespace nuking beyond them. blocked whitespace nuking beyond them.
* Use `ensure` to protect the resetting of the Haml output buffer
against exceptions that are raised within the compiled Haml code.
## [2.2.10](http://github.com/nex3/haml/commit/2.2.10) ## [2.2.10](http://github.com/nex3/haml/commit/2.2.10)
* Fixed a bug where elements with dynamic attributes and no content * Fixed a bug where elements with dynamic attributes and no content

View File

@ -174,15 +174,13 @@ module Haml
@haml_buffer = buffer @haml_buffer = buffer
end end
str = eval(precompiled + ";" + precompiled_method_return_value, eval(precompiled + ";" + precompiled_method_return_value,
scope, @options[:filename], @options[:line]) scope, @options[:filename], @options[:line])
ensure
# Get rid of the current buffer # Get rid of the current buffer
scope_object.instance_eval do scope_object.instance_eval do
@haml_buffer = buffer.upper @haml_buffer = buffer.upper
end end
str
end end
alias_method :to_html, :render alias_method :to_html, :render

View File

@ -92,14 +92,17 @@ module Haml
# Returns the precompiled string with the preamble and postamble # Returns the precompiled string with the preamble and postamble
def precompiled_with_ambles(local_names) def precompiled_with_ambles(local_names)
preamble = <<END.gsub("\n", ";") preamble = <<END.gsub("\n", ";")
begin
extend Haml::Helpers extend Haml::Helpers
_hamlout = @haml_buffer = Haml::Buffer.new(@haml_buffer, #{options_for_buffer.inspect}) _hamlout = @haml_buffer = Haml::Buffer.new(@haml_buffer, #{options_for_buffer.inspect})
_erbout = _hamlout.buffer _erbout = _hamlout.buffer
__in_erb_template = true __in_erb_template = true
END END
postamble = <<END.gsub("\n", ";") postamble = <<END.gsub("\n", ";")
@haml_buffer = @haml_buffer.upper
#{precompiled_method_return_value} #{precompiled_method_return_value}
ensure
@haml_buffer = @haml_buffer.upper
end
END END
preamble + locals_code(local_names) + precompiled + postamble preamble + locals_code(local_names) + precompiled + postamble
end end

View File

@ -962,6 +962,32 @@ END
assert_equal("FOO\n", engine("= upcase").render_proc("foo".instance_eval{binding}).call) assert_equal("FOO\n", engine("= upcase").render_proc("foo".instance_eval{binding}).call)
end end
def test_haml_buffer_gets_reset_even_with_exception
scope = Object.new
render("- raise Haml::Error", :scope => scope)
assert(false, "Expected exception")
rescue Exception
assert_nil(scope.send(:haml_buffer))
end
def test_def_method_haml_buffer_gets_reset_even_with_exception
scope = Object.new
engine("- raise Haml::Error").def_method(scope, :render)
scope.render
assert(false, "Expected exception")
rescue Exception
assert_nil(scope.send(:haml_buffer))
end
def test_render_proc_haml_buffer_gets_reset_even_with_exception
scope = Object.new
proc = engine("- raise Haml::Error").render_proc(scope)
proc.call
assert(false, "Expected exception")
rescue Exception
assert_nil(scope.send(:haml_buffer))
end
def test_ugly_true def test_ugly_true
assert_equal("<div id='outer'>\n<div id='inner'>\n<p>hello world</p>\n</div>\n</div>\n", assert_equal("<div id='outer'>\n<div id='inner'>\n<p>hello world</p>\n</div>\n</div>\n",
render("#outer\n #inner\n %p hello world", :ugly => true)) render("#outer\n #inner\n %p hello world", :ugly => true))