Don't stackoverflow on recursive lists and maps. Fix #3.
This commit is contained in:
+39
-9
@@ -141,6 +141,34 @@ static const char* coreLibSource =
|
||||
"}\n"
|
||||
"\n"
|
||||
"class String is Sequence {\n"
|
||||
" // Avoids recursively calling [toString] on [object] and overflowing the\n"
|
||||
" // stack.\n"
|
||||
" //\n"
|
||||
" // If we are already within a call to [safeToString_] on [object] in this\n"
|
||||
" // fiber, then this returns \"...\". Otherwise, it returns the result of\n"
|
||||
" // calling [ifUnseen].\n"
|
||||
" static safeToString_(object, ifUnseen) {\n"
|
||||
" if (__seenByFiber == null) __seenByFiber = new Map\n"
|
||||
" var seen = __seenByFiber[Fiber.current]\n"
|
||||
" if (seen == null) {\n"
|
||||
" __seenByFiber[Fiber.current] = seen = new List\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" // See if we are recursing on it.\n"
|
||||
" for (outer in seen) {\n"
|
||||
" if (Object.same(outer, object)) return \"...\"\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" seen.add(object)\n"
|
||||
"\n"
|
||||
" var result = ifUnseen.call()\n"
|
||||
"\n"
|
||||
" seen.removeAt(-1)\n"
|
||||
" if (seen.count == 0) __seenByFiber.remove(Fiber.current)\n"
|
||||
"\n"
|
||||
" return result\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" bytes { new StringByteSequence(this) }\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
@@ -162,7 +190,7 @@ static const char* coreLibSource =
|
||||
" return other\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" toString { \"[\" + join(\", \") + \"]\" }\n"
|
||||
" toString { String.safeToString_(this) { \"[\" + join(\", \") + \"]\" } }\n"
|
||||
"\n"
|
||||
" +(other) {\n"
|
||||
" var result = this[0..-1]\n"
|
||||
@@ -178,16 +206,18 @@ static const char* coreLibSource =
|
||||
" values { new MapValueSequence(this) }\n"
|
||||
"\n"
|
||||
" toString {\n"
|
||||
" var first = true\n"
|
||||
" var result = \"{\"\n"
|
||||
" return String.safeToString_(this) {\n"
|
||||
" var first = true\n"
|
||||
" var result = \"{\"\n"
|
||||
"\n"
|
||||
" for (key in keys) {\n"
|
||||
" if (!first) result = result + \", \"\n"
|
||||
" first = false\n"
|
||||
" result = result + key.toString + \": \" + this[key].toString\n"
|
||||
" for (key in keys) {\n"
|
||||
" if (!first) result = result + \", \"\n"
|
||||
" first = false\n"
|
||||
" result = result + key.toString + \": \" + this[key].toString\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" return result + \"}\"\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" return result + \"}\"\n"
|
||||
" }\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
|
||||
Reference in New Issue
Block a user