fix: prevent stack overflow on recursive toString for List and Map
Add `String.safeToString_` static method that tracks objects currently being converted to string per fiber, returning "..." when recursion is detected. Wrap List.toString and Map.toString with this guard to handle self-referential and mutually recursive structures without crashing.
This commit is contained in:
@@ -14,4 +14,37 @@ class Foo {
|
||||
|
||||
IO.print([1, new Foo, 2]) // expect: [1, Foo.toString, 2]
|
||||
|
||||
// TODO: Handle lists that contain themselves.
|
||||
// Lists that directly contain themselves.
|
||||
var list = []
|
||||
list.add(list)
|
||||
IO.print(list) // expect: [...]
|
||||
|
||||
list = [1, 2]
|
||||
list[0] = list
|
||||
IO.print(list) // expect: [..., 2]
|
||||
|
||||
list = [1, 2]
|
||||
list[1] = list
|
||||
IO.print(list) // expect: [1, ...]
|
||||
|
||||
// Lists that indirectly contain themselves.
|
||||
list = [null, [2, [3, null, 4], null, 5], 6]
|
||||
list[0] = list
|
||||
list[1][1][1] = list
|
||||
list[1][2] = list
|
||||
IO.print(list) // expect: [..., [2, [3, ..., 4], ..., 5], 6]
|
||||
|
||||
// List containing an object that calls toString on a recursive list.
|
||||
class Box {
|
||||
new(field) { _field = field }
|
||||
toString { "box " + _field.toString }
|
||||
}
|
||||
|
||||
list = [1, 2]
|
||||
list.add(new Box(list))
|
||||
IO.print(list) // expect: [1, 2, box ...]
|
||||
|
||||
// List containing a map containing the list.
|
||||
list = [1, null, 2]
|
||||
list[1] = {"list": list}
|
||||
IO.print(list) // expect: [1, {list: ...}, 2]
|
||||
|
||||
@@ -24,4 +24,28 @@ IO.print(s == "{1: 2, 3: 4, 5: 6}" ||
|
||||
s == "{5: 6, 1: 2, 3: 4}" ||
|
||||
s == "{5: 6, 3: 4, 1: 2}") // expect: true
|
||||
|
||||
// TODO: Handle maps that contain themselves.
|
||||
// Map that directly contains itself.
|
||||
var map = {}
|
||||
map["key"] = map
|
||||
IO.print(map) // expect: {key: ...}
|
||||
|
||||
// Map that indirectly contains itself.
|
||||
map = {}
|
||||
map["a"] = {"b": {"c": map}}
|
||||
|
||||
IO.print(map) // expect: {a: {b: {c: ...}}}
|
||||
|
||||
// Map containing an object that calls toString on a recursive map.
|
||||
class Box {
|
||||
new(field) { _field = field }
|
||||
toString { "box " + _field.toString }
|
||||
}
|
||||
|
||||
map = {}
|
||||
map["box"] = new Box(map)
|
||||
IO.print(map) // expect: {box: box ...}
|
||||
|
||||
// Map containing a list containing the map.
|
||||
map = {}
|
||||
map["list"] = [1, map, 2]
|
||||
IO.print(map) // expect: {list: [1, ..., 2]}
|
||||
|
||||
Reference in New Issue
Block a user