diff --git a/projects/core/src/main/resources/data/computercraft/lua/rom/apis/textutils.lua b/projects/core/src/main/resources/data/computercraft/lua/rom/apis/textutils.lua index dd751989b..5b9bda014 100644 --- a/projects/core/src/main/resources/data/computercraft/lua/rom/apis/textutils.lua +++ b/projects/core/src/main/resources/data/computercraft/lua/rom/apis/textutils.lua @@ -296,6 +296,13 @@ local g_tLuaKeywords = { ["while"] = true, } +--- A version of the ipairs iterator which ignores metamethods +local function inext(tbl, i) + i = (i or 0) + 1 + local v = rawget(tbl, i) + if v == nil then return nil else return i, v end +end + local serialize_infinity = math.huge local function serialize_impl(t, tracking, indent, opts) local sType = type(t) @@ -322,11 +329,11 @@ local function serialize_impl(t, tracking, indent, opts) result = open local seen_keys = {} - for k, v in ipairs(t) do + for k, v in inext, t do seen_keys[k] = true result = result .. sub_indent .. serialize_impl(v, tracking, sub_indent, opts) .. comma end - for k, v in pairs(t) do + for k, v in next, t do if not seen_keys[k] then local sEntry if type(k) == "string" and not g_tLuaKeywords[k] and string.match(k, "^[%a_][%a%d_]*$") then diff --git a/projects/core/src/test/resources/test-rom/spec/apis/textutils_spec.lua b/projects/core/src/test/resources/test-rom/spec/apis/textutils_spec.lua index 3a1941ff7..482577bdb 100644 --- a/projects/core/src/test/resources/test-rom/spec/apis/textutils_spec.lua +++ b/projects/core/src/test/resources/test-rom/spec/apis/textutils_spec.lua @@ -118,6 +118,15 @@ describe("The textutils library", function() expect(textutils.serialise({ 1, 2, 3, a = 1, [false] = {} }, { compact = true })) :eq("{1,2,3,a=1,[false]={},}") end) + + it("ignores metatables", function() + local actual = { "a", true, x = 2 } + expect(textutils.serialise(setmetatable({}, { __index = actual }))):eq("{}") + expect(textutils.serialise(setmetatable({}, { __pairs = function() return pairs(actual) end }))):eq("{}") + + expect(textutils.serialise(setmetatable({ 1 }, { __index = actual }))):eq("{\n 1,\n}") + expect(textutils.serialise(setmetatable({ 1 }, { __pairs = function() return pairs(actual) end }))):eq("{\n 1,\n}") + end) end) describe("textutils.unserialise", function()