diff --git a/CHANGELOG.md b/CHANGELOG.md index ce230e8..4255ca5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,10 @@ The format is based on [Keep a Changelog][kac], and this project adheres to - `World:get()` now has fast paths for up to four components. - Getting one component is now more than 2x faster and this scales with more components. +### Fixed + +- The debugger now gracefully handles cyclic tables. + ## [0.9.0-beta.0] - 2024-11-15 ### Added diff --git a/lib/debugger/formatTable.luau b/lib/debugger/formatTable.luau index 01dacd2..ea8989e 100644 --- a/lib/debugger/formatTable.luau +++ b/lib/debugger/formatTable.luau @@ -1,6 +1,7 @@ local stringColor = "#dcdcaa" local numberColor = "#b0c4de" local keywordColor = "#c586c0" +local dimmedColor = "#808080" function colorize(value, color) if type(value) == "number" then @@ -38,10 +39,17 @@ local FormatMode = { Short = "Short", Long = "Long", } -local function formatTable(object, mode, _padLength, _depth) + +local function formatTable(object, mode, _padLength, _depth, _seen) mode = mode or FormatMode.Short _padLength = _padLength or 0 _depth = _depth or 1 + _seen = _seen or {} + + if _seen[object] then + return colorize("<cyclic>", dimmedColor) + end + _seen[object] = true local max = if mode == FormatMode.Short then 7 else 1000 @@ -87,7 +95,7 @@ local function formatTable(object, mode, _padLength, _depth) part ..= "[{..}]=" else part ..= "[" - part ..= formatTable(key, FormatMode.Short, #str + #part + _padLength, _depth + 1) + part ..= formatTable(key, FormatMode.Short, #str + #part + _padLength, _depth + 1, _seen) part ..= "] = " end end @@ -107,7 +115,7 @@ local function formatTable(object, mode, _padLength, _depth) if mode == FormatMode.Short then part ..= "{..}" else - part ..= formatTable(value, FormatMode.Long, #str + #part + _padLength, _depth + 1) + part ..= formatTable(value, FormatMode.Long, #str + #part + _padLength, _depth + 1, _seen) end elseif mode == FormatMode.Long and (luaType == "userdata" or luaType == "vector") then if robloxType == "CFrame" then @@ -153,6 +161,8 @@ local function formatTable(object, mode, _padLength, _depth) str ..= "}" end + _seen[object] = nil + return str end