Skip to content

Commit 04d53c1

Browse files
committed
Simpler inline cycle check for stringify
1 parent 6bc2c06 commit 04d53c1

1 file changed

Lines changed: 12 additions & 32 deletions

File tree

src/compiler/utilities.ts

Lines changed: 12 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -2422,38 +2422,10 @@ namespace ts {
24222422
? JSON.stringify
24232423
: stringifyFallback;
24242424

2425-
function hasCycles(value: any, stack: any[]) {
2426-
/* tslint:disable:no-null */
2427-
if (typeof value !== "object" || value === null) {
2428-
return false;
2429-
}
2430-
/* tslint:enable:no-null */
2431-
2432-
if (stack.lastIndexOf(value) !== -1) {
2433-
return true;
2434-
}
2435-
2436-
stack.push(value);
2437-
2438-
for (const key in value) {
2439-
if (hasProperty(value, key) && hasCycles(value[key], stack)) {
2440-
return true;
2441-
}
2442-
}
2443-
2444-
stack.pop();
2445-
return false;
2446-
}
2447-
24482425
/**
2449-
* Serialize an object graph into a JSON string. This is intended only for use on an acyclic graph
2450-
* as the fallback implementation does not check for circular references by default.
2426+
* Serialize an object graph into a JSON string.
24512427
*/
24522428
function stringifyFallback(value: any): string {
2453-
if (Debug.shouldAssert(AssertionLevel.Aggressive)) {
2454-
Debug.assert(!hasCycles(value, []), "Detected circular reference before serializing object graph.");
2455-
}
2456-
24572429
// JSON.stringify returns `undefined` here, instead of the string "undefined".
24582430
return value === undefined ? undefined : stringifyValue(value);
24592431
}
@@ -2462,10 +2434,18 @@ namespace ts {
24622434
return typeof value === "string" ? `"${escapeString(value)}"`
24632435
: typeof value === "number" ? isFinite(value) ? String(value) : "null"
24642436
: typeof value === "boolean" ? value ? "true" : "false"
2465-
: typeof value === "object" ? isArray(value) ? stringifyArray(value) : stringifyObject(value)
2437+
: typeof value === "object" && value ? isArray(value) ? cycleCheck(stringifyArray, value) : cycleCheck(stringifyObject, value)
24662438
: /*fallback*/ "null";
24672439
}
24682440

2441+
function cycleCheck(cb: (value: any) => string, value: any) {
2442+
Debug.assert(!value.hasOwnProperty("__cycle"), "Converting circular structure to JSON");
2443+
value.__cycle = true;
2444+
const result = cb(value);
2445+
delete value.__cycle;
2446+
return result;
2447+
}
2448+
24692449
function stringifyArray(value: any) {
24702450
return `[${reduceLeft(value, stringifyElement, "")}]`;
24712451
}
@@ -2475,11 +2455,11 @@ namespace ts {
24752455
}
24762456

24772457
function stringifyObject(value: any) {
2478-
return value ? `{${reduceProperties(value, stringifyProperty, "")}}` : "null";
2458+
return `{${reduceProperties(value, stringifyProperty, "")}}`;
24792459
}
24802460

24812461
function stringifyProperty(memo: string, value: any, key: string) {
2482-
return value === undefined || typeof value === "function" ? memo
2462+
return value === undefined || typeof value === "function" || key === "__cycle" ? memo
24832463
: (memo ? memo + "," : memo) + `"${escapeString(key)}":${stringifyValue(value)}`;
24842464
}
24852465

0 commit comments

Comments
 (0)