Skip to content

Commit 8783931

Browse files
authored
Merge pull request #5 from 3scale/safe-concat
handle empty values with __tostring metatable
2 parents 4203133 + aecc1c6 commit 8783931

2 files changed

Lines changed: 34 additions & 6 deletions

File tree

lib/liquid.lua

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2018,17 +2018,19 @@ function Interpreter:visit_BinOp( node )
20182018
return false
20192019
end
20202020
end
2021+
20212022
if left_name == "Empty" then
20222023
local right_value = self:visit(node.right)
2023-
if right_value == nil or right_value == '' then
2024+
local str = self:obj2str(right_value)
2025+
if not str or str == '' then
20242026
if op == EQ then
20252027
return true
20262028
else
20272029
return false
20282030
end
20292031
end
20302032
if type(right_value) == "table" then
2031-
if next(right_value) then
2033+
if next(right_value) or (str and str ~= '') then
20322034
if op == NE then
20332035
return true
20342036
else
@@ -2045,15 +2047,18 @@ function Interpreter:visit_BinOp( node )
20452047
self:raise_error("Invalid empty comparision", node, 'op')
20462048
else
20472049
local left_value = self:visit(node.left)
2048-
if left_value == nil or left_value == '' then
2050+
local str = self:obj2str(left_value)
2051+
2052+
if not str or str == '' then
20492053
if op == EQ then
20502054
return true
20512055
else
20522056
return false
20532057
end
20542058
end
2059+
20552060
if type(left_value) == "table" then
2056-
if next(left_value) then
2061+
if next(left_value) or (str and str ~= '') then
20572062
if op == NE then
20582063
return true
20592064
else
@@ -2723,7 +2728,7 @@ do
27232728
elseif obj_type == "Boolean" then
27242729
return tostring(obj)
27252730
elseif type(mt__tostring(obj)) == 'function' then
2726-
return tostring(obj)
2731+
return tostring(obj) or ''
27272732
end
27282733
end
27292734

t/interpreter.t

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -690,7 +690,7 @@ too many loopcount. limit num:3
690690
location /t {
691691
content_by_lua_block {
692692
local Liquid = require 'liquid'
693-
local document = [[str = {{ str }}, arr = {{ arr | join: '+' }}]]
693+
local document = "str = {{ str }}, arr = {{ arr | join: '+' }}\n{%- if str == empty %}str is empty{%endif%}"
694694
local template = Liquid.Template:parse(document)
695695
696696
local str = setmetatable({}, { __tostring = function() return 'val' end })
@@ -704,3 +704,26 @@ GET /t
704704
str = val, arr = val+val
705705
--- no_error_log
706706
[error]
707+
708+
709+
=== TEST 27: variable with __tostring metatable but returns nil
710+
--- http_config eval: $::HttpConfig
711+
--- config
712+
location /t {
713+
content_by_lua_block {
714+
local Liquid = require 'liquid'
715+
local document = "str = {{ str }}, arr = {{ arr | join: '+' }}\n{% if str == empty %}str is empty{%endif%}"
716+
local template = Liquid.Template:parse(document)
717+
718+
local str = setmetatable({}, { __tostring = function() end })
719+
local context = Liquid.InterpreterContext:new({ str = str, arr = { str, str } })
720+
ngx.say(assert(template:render(context)))
721+
}
722+
}
723+
--- request
724+
GET /t
725+
--- response_body
726+
str = , arr = +
727+
str is empty
728+
--- no_error_log
729+
[error]

0 commit comments

Comments
 (0)