diff --git a/lib/liquid/utils.rb b/lib/liquid/utils.rb index 38a406ef..4ec7d811 100644 --- a/lib/liquid/utils.rb +++ b/lib/liquid/utils.rb @@ -16,7 +16,11 @@ module Liquid # Maintains Ruby 1.8.7 String#each behaviour on 1.9 if collection.is_a?(String) - return collection.empty? ? [] : [collection] + return [] if collection.empty? + if from > 0 || to == 0 + Usage.increment("string_slice_bug") + end + return [collection] end return [] unless collection.respond_to?(:each) diff --git a/test/unit/tags/for_tag_unit_test.rb b/test/unit/tags/for_tag_unit_test.rb index 5a52c71c..cbb68fcb 100644 --- a/test/unit/tags/for_tag_unit_test.rb +++ b/test/unit/tags/for_tag_unit_test.rb @@ -12,4 +12,34 @@ class ForTagUnitTest < Minitest::Test template = Liquid::Template.parse('{% for item in items %}FOR{% else %}ELSE{% endfor %}') assert_equal(['FOR', 'ELSE'], template.root.nodelist[0].nodelist.map(&:nodelist).flatten) end + + def test_for_string_slice_bug_usage + template = Liquid::Template.parse("{% for x in str, offset: 1 %}{{ x }},{% endfor %}") + assert_usage("string_slice_bug") do + assert_equal("abc,", template.render({ "str" => "abc" })) + end + end + + def test_for_string_0_limit_usage + template = Liquid::Template.parse("{% for x in str, limit: 0 %}{{ x }},{% endfor %}") + assert_usage("string_slice_bug") do + assert_equal("abc,", template.render({ "str" => "abc" })) + end + end + + def test_for_string_no_slice_usage + template = Liquid::Template.parse("{% for x in str, offset: 0, limit: 1 %}{{ x }},{% endfor %}") + assert_usage("string_slice_bug", times: 0) do + assert_equal("abc,", template.render({ "str" => "abc" })) + end + end + + private + + def assert_usage(name, times: 1, &block) + count = 0 + result = Liquid::Usage.stub(:increment, ->(n) { count += 1 if n == name }, &block) + assert_equal(times, count) + result + end end