diff --git a/.github/workflows/liquid.yml b/.github/workflows/liquid.yml index ccc3c0d1..4722f60b 100644 --- a/.github/workflows/liquid.yml +++ b/.github/workflows/liquid.yml @@ -6,7 +6,6 @@ jobs: strategy: matrix: entry: - - { ruby: '2.5', allowed-failure: false } - { ruby: '2.7', allowed-failure: false } - { ruby: '3.0', allowed-failure: false } - { ruby: ruby-head, allowed-failure: true } diff --git a/lib/liquid/c.rb b/lib/liquid/c.rb index 2649c366..259c7d8f 100644 --- a/lib/liquid/c.rb +++ b/lib/liquid/c.rb @@ -86,7 +86,7 @@ def new_tokenizer(source, start_line_number: nil, for_liquid_tag: false) def parse_expression(markup) if liquid_c_nodes_disabled? - Liquid::Expression.ruby_parse(markup) + Liquid::Expression.parse(markup) else Liquid::C::Expression.lax_parse(markup) end @@ -207,22 +207,17 @@ class << self def lax_parse(markup) strict_parse(markup) rescue Liquid::SyntaxError - Liquid::Expression.ruby_parse(markup) + Liquid::Expression.parse(markup) end - end -end - -Liquid::Expression.class_eval do - class << self - alias_method :ruby_parse, :parse - def c_parse(markup) - Liquid::C::Expression.lax_parse(markup) - end + # Default to strict parsing, since Liquid::C::Expression.parse should only really + # be used with constant expressions. Otherwise, prefer parse_context.parse_expression. + alias_method :parse, :strict_parse end end Liquid::Context.class_eval do + alias_method :ruby_parse_evaluate, :[] alias_method :ruby_evaluate, :evaluate alias_method :ruby_find_variable, :find_variable alias_method :ruby_strict_variables=, :strict_variables= @@ -232,6 +227,10 @@ def c_parse(markup) def c_find_variable_kwarg(key, raise_on_not_found: true) c_find_variable(key, raise_on_not_found) end + + def c_parse_evaluate(expression) + c_evaluate(Liquid::C::Expression.lax_parse(expression)) + end end Liquid::ResourceLimits.class_eval do @@ -256,15 +255,15 @@ class << self def enabled=(value) @enabled = value if value + Liquid::Context.send(:alias_method, :[], :c_parse_evaluate) Liquid::Context.send(:alias_method, :evaluate, :c_evaluate) Liquid::Context.send(:alias_method, :find_variable, :c_find_variable_kwarg) Liquid::Context.send(:alias_method, :strict_variables=, :c_strict_variables=) - Liquid::Expression.singleton_class.send(:alias_method, :parse, :c_parse) else + Liquid::Context.send(:alias_method, :[], :ruby_parse_evaluate) Liquid::Context.send(:alias_method, :evaluate, :ruby_evaluate) Liquid::Context.send(:alias_method, :find_variable, :ruby_find_variable) Liquid::Context.send(:alias_method, :strict_variables=, :ruby_strict_variables=) - Liquid::Expression.singleton_class.send(:alias_method, :parse, :ruby_parse) end end end diff --git a/test/unit/expression_test.rb b/test/unit/expression_test.rb index 08e1bae4..dbcf4433 100644 --- a/test/unit/expression_test.rb +++ b/test/unit/expression_test.rb @@ -159,7 +159,7 @@ def test_disassemble_int16 end def test_disable_c_nodes - context = Liquid::Context.new({ "x" => 123 }) + context = Liquid::Context.new({ "x" => 123, "y" => { 123 => 42 } }) expr = Liquid::ParseContext.new.parse_expression("x") assert_instance_of(Liquid::C::Expression, expr) @@ -168,6 +168,11 @@ def test_disable_c_nodes expr = Liquid::ParseContext.new(disable_liquid_c_nodes: true).parse_expression("x") assert_instance_of(Liquid::VariableLookup, expr) assert_equal(123, context.evaluate(expr)) + + expr = Liquid::ParseContext.new(disable_liquid_c_nodes: true).parse_expression("y[x]") + assert_instance_of(Liquid::VariableLookup, expr) + assert_instance_of(Liquid::VariableLookup, expr.lookups.first) + assert_equal(42, context.evaluate(expr)) end private