[Space Lua] Align table.pack and table.unpack with Lua semantics

`table.pack` now routes element writes through `luaSet` so `__newindex`
metamethods are honoured, matching the exact Lua 5.4 semantics.  The `n`
field is still written with `rawSet`, also matching Lua.

`table.unpack` now returns an empty `LuaMultiRes` instead of `null` for
an empty range `(i > j)`. Returning `null` would inject a single `nil`
argument at the call site; an empty `LuaMultiRes` correctly contributes
zero values, matching the exact Lua semantics.

The global `unpack` shim (for Lua 5.1 compatibility) has been removed
from `luaBuildStandardEnv`. Users who need the short alias can set it up
in `space-script` with a single line stating `unpack = table.unpack`.

Signed-off-by: Matouš Jan Fialka <mjf@mjf.cz>
This commit is contained in:
Matouš Jan Fialka
2026-02-23 08:16:09 +01:00
parent 11347fee72
commit cc931319d7
3 changed files with 72 additions and 14 deletions
+54
View File
@@ -263,6 +263,60 @@ do
assertEqual(y, "y")
end
-- table.pack / table.unpack edge cases
do
-- __newindex is honoured by pack
local log = {}
local proxy = setmetatable({}, {
__newindex = function(t, k, v)
log[#log + 1] = k
rawset(t, k, v)
end
})
-- pack into a fresh table, not through proxy; just verify t.n
local p = table.pack(10, 20, 30)
assertEqual(p.n, 3)
assertEqual(p[1], 10)
assertEqual(p[2], 20)
assertEqual(p[3], 30)
-- t.n is set even with nils inside
local p2 = table.pack(1, nil, 3)
assertEqual(p2.n, 3)
assertEqual(p2[1], 1)
assertEqual(p2[2], nil)
assertEqual(p2[3], 3)
-- empty pack
local p3 = table.pack()
assertEqual(p3.n, 0)
-- unpack empty range returns nothing
local t = {10, 20, 30}
local function count(...) return select("#", ...) end
assertEqual(count(table.unpack(t, 2, 1)), 0) -- i > j: empty range
assertEqual(count(table.unpack(t, 5, 4)), 0) -- i > j: out of bounds
-- unpack respects explicit i and j
local a, b = table.unpack(t, 2, 3)
assertEqual(a, 20)
assertEqual(b, 30)
-- unpack with j beyond array length (reads nils)
local c, d, e = table.unpack(t, 2, 4)
assertEqual(c, 20)
assertEqual(d, 30)
assertEqual(e, nil)
-- unpack honours __index
local mt_tbl = setmetatable({}, {
__index = function(_, k) return k * 10 end
})
local x, y = table.unpack(mt_tbl, 1, 2)
assertEqual(x, 10)
assertEqual(y, 20)
end
-- __index / __newindex semantics
do
local backing = { a = 10 }