[Space Lua] tostring() respects __tostring metamethod with live stack frame
`tostring()` was delegating to `luaToString()` which calls `__tostring` with a dead stack frame, breaking metamethods that call back into globals. Now `tostringFunction` receives the live stack frame, looks up `__tostring` via `rawGet`, calls it through `luaCall` with the live frame, and validates the return is a string. Also add tests covering the basic case, the nested-call case, and the error path for a non-string return. Signed-off-by: Matouš Jan Fialka <mjf@mjf.cz>
This commit is contained in:
@@ -25,3 +25,30 @@ assertEqual(some(" \n"), nil)
|
||||
assertEqual(some({}), nil)
|
||||
assertEqual(some({"baz"})[1], "baz") -- compare an element to ensure passthrough
|
||||
assertEqual(some({foo="bar"})["foo"], "bar")
|
||||
|
||||
-- tostring: primitives
|
||||
assertEqual(tostring(nil), "nil")
|
||||
assertEqual(tostring(true), "true")
|
||||
assertEqual(tostring(false), "false")
|
||||
assertEqual(tostring(42), "42")
|
||||
assertEqual(tostring(3.14), "3.14")
|
||||
|
||||
-- tostring: `__tostring` metamethod is called with the live SF
|
||||
local mt = { __tostring = function(t) return "custom:" .. t.name end }
|
||||
local obj = setmetatable({ name = "lua" }, mt)
|
||||
assertEqual(tostring(obj), "custom:lua")
|
||||
|
||||
-- tostring: `__tostring` returning non-string must error
|
||||
local bad_mt = { __tostring = function(_) return 99 end }
|
||||
local bad_obj = setmetatable({}, bad_mt)
|
||||
local ok, err = pcall(tostring, bad_obj)
|
||||
assertEqual(ok, false)
|
||||
|
||||
-- tostring: `__tostring` on a nested call (SF propagation via `luaCall`)
|
||||
local inner_mt = {
|
||||
__tostring = function(t)
|
||||
return "inner:" .. tostring(t.val)
|
||||
end
|
||||
}
|
||||
local inner = setmetatable({ val = 7 }, inner_mt)
|
||||
assertEqual(tostring(inner), "inner:7")
|
||||
|
||||
Reference in New Issue
Block a user