From fa27bfe6e0eff396407bfb031ef1de5f5014e206 Mon Sep 17 00:00:00 2001 From: Julia Boutin Date: Thu, 27 Nov 2025 15:32:37 -0700 Subject: [PATCH] Preserve literal semantics in strict2 case/when Previously, strict2 case/when used `safe_parse_expression` to parse when expressions causing `blank`/`empty` to be treated as string literals (Expression::LITERALS maps 'empty' => ''), rather than method literals This caused unexpected behavior: ``` {%- case empty_obj -%} {%- when empty -%} previously: doesn't render (empty_obj == '' is false) now: renders (empty_obj.empty? is true) {%- endcase -%} ``` This commit instead calls `Condition.parse_expression` with `safe: true`, which will correctly handle `blank` and `empty` --- lib/liquid/tags/case.rb | 2 +- test/unit/tags/case_tag_unit_test.rb | 20 ++++++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/lib/liquid/tags/case.rb b/lib/liquid/tags/case.rb index b32ea1ae..e87e402e 100644 --- a/lib/liquid/tags/case.rb +++ b/lib/liquid/tags/case.rb @@ -118,7 +118,7 @@ module Liquid parser = @parse_context.new_parser(markup) loop do - expr = safe_parse_expression(parser) + expr = Condition.parse_expression(parse_context, parser.expression, safe: true) block = Condition.new(@left, '==', expr) block.attach(body) @blocks << block diff --git a/test/unit/tags/case_tag_unit_test.rb b/test/unit/tags/case_tag_unit_test.rb index 9d7d34a3..11458db8 100644 --- a/test/unit/tags/case_tag_unit_test.rb +++ b/test/unit/tags/case_tag_unit_test.rb @@ -82,6 +82,26 @@ class CaseTagUnitTest < Minitest::Test end end + def test_case_when_empty + template = <<~LIQUID + {%- case x -%} + {%- when 2 or empty -%} + 2 or empty + {%- else -%} + not 2 or empty + {%- endcase -%} + LIQUID + + with_error_modes(:lax, :strict, :strict2) do + assert_template_result("2 or empty", template, { 'x' => 2 }) + assert_template_result("2 or empty", template, { 'x' => {} }) + assert_template_result("2 or empty", template, { 'x' => [] }) + assert_template_result("not 2 or empty", template, { 'x' => { 'a' => 'b' } }) + assert_template_result("not 2 or empty", template, { 'x' => ['a'] }) + assert_template_result("not 2 or empty", template, { 'x' => 4 }) + end + end + def test_case_with_invalid_expression template = <<~LIQUID {%- case foo=>bar -%}