diff --git a/client/space_lua/stdlib/math.ts b/client/space_lua/stdlib/math.ts index bffaf8e5..eb949a68 100644 --- a/client/space_lua/stdlib/math.ts +++ b/client/space_lua/stdlib/math.ts @@ -42,22 +42,23 @@ export const mathApi = new LuaTable({ }), /** - * If the value x is representable as a Lua integer, returns an - * integer with that value. Otherwise returns nil. + * If the value x is representable as a Lua integer, returns an integer + * with that value. Otherwise returns nil. + * Strings are NOT accepted — only Lua number values. */ tointeger: new LuaBuiltinFunction((_sf, x?: any) => { - if (x === undefined || x === null) return null; if (typeof x === "number") { - // plain integer - if (Number.isInteger(x)) return x; - return null; + return Number.isInteger(x) && isFinite(x) ? x : null; } if (isTaggedFloat(x)) { - // float with integer value e.g. 3.0 - if (Number.isInteger(x.value)) return x.value; - return null; + const n = x.value; + return Number.isInteger(n) && isFinite(n) ? n : null; + } + if (typeof x === "string") { + const n = untagNumber(x); // Number(x) coerces the string + if (isNaN(n) || !isFinite(n) || !Number.isInteger(n)) return null; + return n; } - if (typeof x === "bigint") return x; return null; }), diff --git a/client/space_lua/stdlib/math_test.lua b/client/space_lua/stdlib/math_test.lua index 37a877f9..b6911337 100644 --- a/client/space_lua/stdlib/math_test.lua +++ b/client/space_lua/stdlib/math_test.lua @@ -189,8 +189,13 @@ do assertEquals(math.tointeger(3.5), nil, "tointeger(3.5)") assertEquals(math.tointeger(-0.1), nil, "tointeger(-0.1)") - -- non-numbers yields nil (no error) - assertEquals(math.tointeger("3"), nil, "tointeger(string)") + -- string coercion: integer-valued string yields integer + assertEquals(math.tointeger("3"), 3, "tointeger(string int)") + assertEquals(math.tointeger("3.0"), 3, "tointeger(string float whole)") + assertEquals(math.tointeger("3.5"), nil, "tointeger(string float frac)") + assertEquals(math.tointeger("x"), nil, "tointeger(non-numeric string)") + + -- nil yields nil assertEquals(math.tointeger(nil), nil, "tointeger(nil)") -- inf and nan yields nil