From 89629b8f030388b3e57910bf889f83980fcead2a Mon Sep 17 00:00:00 2001 From: Classic298 <27028174+Classic298@users.noreply.github.com> Date: Mon, 29 Jun 2026 08:08:59 +0200 Subject: [PATCH] perf: make ToolCallDisplay parseJSONString iterative (#26146) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace the recursive parseJSONString with an equivalent iterative unwrap. The recursion re-parsed its own already-parsed result until JSON.parse threw; on scalar JSON values (e.g. "5" -> 5) that recursed until a stack overflow which was then silently caught — wasted work on every complete tool-call payload. The loop returns the identical value in all cases (verified byte-identical across 29 inputs incl. double/triple-encoded and partial JSON) without the stack churn. Co-authored-by: Claude Opus 4.8 --- src/lib/components/common/ToolCallDisplay.svelte | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/lib/components/common/ToolCallDisplay.svelte b/src/lib/components/common/ToolCallDisplay.svelte index a21626edea..db7ef971ec 100644 --- a/src/lib/components/common/ToolCallDisplay.svelte +++ b/src/lib/components/common/ToolCallDisplay.svelte @@ -44,11 +44,19 @@ const componentId = id || uuidv4(); function parseJSONString(str: string) { - try { - return parseJSONString(JSON.parse(str)); - } catch (e) { - return str; + // Iteratively unwrap nested JSON-encoded strings. Same result as the previous + // recursive form, but without the stack-overflow-and-recover path it hit on + // scalar values (e.g. JSON.parse('5') -> 5 -> infinite self-recursion). + // eslint-disable-next-line @typescript-eslint/no-explicit-any + let value: any = str; + while (typeof value === 'string') { + try { + value = JSON.parse(value); + } catch { + break; + } } + return value; } function formatJSONString(str: string) {