From aecc1c65ad57df07859f62a6a11de2db31bf9dcc Mon Sep 17 00:00:00 2001 From: Michal Cichra Date: Tue, 20 Feb 2018 09:17:31 +0100 Subject: [PATCH] handle empty values with __tostring metatable --- lib/liquid.lua | 15 ++++++++++----- t/interpreter.t | 25 ++++++++++++++++++++++++- 2 files changed, 34 insertions(+), 6 deletions(-) diff --git a/lib/liquid.lua b/lib/liquid.lua index 5b590ee..69b3852 100644 --- a/lib/liquid.lua +++ b/lib/liquid.lua @@ -2018,9 +2018,11 @@ function Interpreter:visit_BinOp( node ) return false end end + if left_name == "Empty" then local right_value = self:visit(node.right) - if right_value == nil or right_value == '' then + local str = self:obj2str(right_value) + if not str or str == '' then if op == EQ then return true else @@ -2028,7 +2030,7 @@ function Interpreter:visit_BinOp( node ) end end if type(right_value) == "table" then - if next(right_value) then + if next(right_value) or (str and str ~= '') then if op == NE then return true else @@ -2045,15 +2047,18 @@ function Interpreter:visit_BinOp( node ) self:raise_error("Invalid empty comparision", node, 'op') else local left_value = self:visit(node.left) - if left_value == nil or left_value == '' then + local str = self:obj2str(left_value) + + if not str or str == '' then if op == EQ then return true else return false end end + if type(left_value) == "table" then - if next(left_value) then + if next(left_value) or (str and str ~= '') then if op == NE then return true else @@ -2723,7 +2728,7 @@ do elseif obj_type == "Boolean" then return tostring(obj) elseif type(mt__tostring(obj)) == 'function' then - return tostring(obj) + return tostring(obj) or '' end end diff --git a/t/interpreter.t b/t/interpreter.t index 9f9f1f0..71341af 100644 --- a/t/interpreter.t +++ b/t/interpreter.t @@ -690,7 +690,7 @@ too many loopcount. limit num:3 location /t { content_by_lua_block { local Liquid = require 'liquid' - local document = [[str = {{ str }}, arr = {{ arr | join: '+' }}]] + local document = "str = {{ str }}, arr = {{ arr | join: '+' }}\n{%- if str == empty %}str is empty{%endif%}" local template = Liquid.Template:parse(document) local str = setmetatable({}, { __tostring = function() return 'val' end }) @@ -704,3 +704,26 @@ GET /t str = val, arr = val+val --- no_error_log [error] + + +=== TEST 27: variable with __tostring metatable but returns nil +--- http_config eval: $::HttpConfig +--- config + location /t { + content_by_lua_block { + local Liquid = require 'liquid' + local document = "str = {{ str }}, arr = {{ arr | join: '+' }}\n{% if str == empty %}str is empty{%endif%}" + local template = Liquid.Template:parse(document) + + local str = setmetatable({}, { __tostring = function() end }) + local context = Liquid.InterpreterContext:new({ str = str, arr = { str, str } }) + ngx.say(assert(template:render(context))) + } + } +--- request +GET /t +--- response_body +str = , arr = + +str is empty +--- no_error_log +[error]