k0kubun / hamlit

High Performance Haml Implementation
https://rubygems.org/gems/hamlit
Other
981 stars 59 forks source link

engine truncating method calls in interpolation in attributes #118

Closed michaelglass closed 6 years ago

michaelglass commented 6 years ago

Here's a minimal test case. I don't have Temple or C chops to fix this totally on my own. Happy to dive in if anyone wants to pair!

Does not happen, (e.g. everything is good) if...

fails when

def test_interpolation_should_work_inside_attributes
  assert_equal("123", "#{"1".concat "2", "3"}")
  assert_equal("<p class='a 13'>foo</p>", render('%p{class: "a #{"1".concat "2", "3"}"} foo').chomp)
end

produces

Error:
EngineTest#test_interpolation_should_work_inside_attributes:
SyntaxError: (eval):1: syntax error, unexpected ')', expecting tSTRING_DEND
..._class(true, "#{"1".concat "2")); _buf << ("'></p>\n".freeze...
...                              ^
(eval):1: syntax error, unexpected end-of-input, expecting tSTRING_DEND
...e); _buf = _buf.join("".freeze)
...                               ^
    test/test_helper.rb:62:in `eval'
    test/test_helper.rb:62:in `render'
    test/haml/engine_test.rb:108:in `render'
    test/haml/engine_test.rb:154:in `test_interpolation_should_work_inside_attributes'```

the string that's produced is

```ruby
_buf = []; _buf << ("<p 3='".freeze); _buf << (::Hamlit::Utils.escape_html(())); _buf << ("' class='".freeze); _buf << (::Hamlit::AttributeBuilder.build_class(true, "#{"1".concat "2")); _buf << ("'></p>\n".freeze); _buf = _buf.join("".freeze)

hand-prettified, that's

_buf = []
_buf << "<p 3='".freeze
_buf << ::Hamlit::Utils.escape_html(())
_buf << "' class='".freeze
#                                            missing stuff here     vvvv
_buf << ::Hamlit::AttributeBuilder.build_class(true, "#{"1".concat "2")
#                                            missing stuff here     ^^^^
_buf << "'></p>\n".freeze
_buf = _buf.join("".freeze)
WaKeMaTTa commented 6 years ago

You have a mistake in your minimal spec

- assert_equal("<p class='a 13'>foo</p>", render('%p{class: "a #{"1".concat "2", "3"}"} foo').chomp)
+ assert_equal("<p class='a 123'>foo</p>", render('%p{class: "a #{"1".concat "2", "3"}"} foo').chomp)
k0kubun commented 6 years ago

Fixed in Hamlit 2.8.7. Please try it.

michaelglass commented 6 years ago

I have never had someone address a bug report so quickly. I have been telling everyone I know about this experience (including people that have no idea what I'm talking about, e.g. my friends' children).

Thank you so much!