Repository: gradio-app/gradio
File: js/json/shared/JSONNode.svelte (Svelte)

Code before:
		} else {
			child_nodes = [];
		}
	});

	function updateLineNumbers(): void {
		if (!root_element) return;
		const lines = root_element.querySelectorAll(".line");
		lines.forEach((line, index) => {
			const line_number = line.querySelector(".line-number");
			if (line_number) {
				line_number.setAttribute("data-pseudo-content", (index + 1).toString());
				line_number?.setAttribute(
					"aria-roledescription",
					`Line number ${index + 1}`
				);
				line_number?.setAttribute("title", `Line number ${index + 1}`);
			}
		});
	}

	$effect.pre(() => {
		if (is_root && root_element) {
			updateLineNumbers();
		}
	});
</script>

<div
	class="json-node"
	class:root={is_root}
	class:dark-mode={theme_mode === "dark"}
	bind:this={root_element}
	style="--depth: {depth};"
>
	<div class="line" class:collapsed>
		<span class="line-number"></span>
		<span class="content">
			{#if is_collapsible(value)}
				<button
					data-pseudo-content={interactive ? (collapsed ? "▶" : "▼") : ""}
					aria-label={collapsed ? "Expand" : "Collapse"}
					class="toggle"
					disabled={!interactive}
					on:click={toggle_collapse}
				/>
			{/if}
			{#if key !== null}
				<span class="key">"{key}"</span><span class="punctuation colon"
					>:
				</span>

Review comment (suggestion):
The use of `$effect.pre()` may cause a timing issue. The original code used `onMount()` and `afterUpdate()` which run after the DOM is updated, allowing `updateLineNumbers()` to query and update line elements that exist in the DOM.

`$effect.pre()` runs before DOM updates, which means the DOM elements may not be in their final state when `updateLineNumbers()` is called. This could cause the function to operate on stale DOM state or miss elements that haven't been rendered yet.

Consider using a regular `$effect()` instead, which runs after DOM updates and more closely matches the behavior of `afterUpdate()`. Alternatively, if you need to run before updates for a specific reason, ensure the logic accounts for potentially incomplete DOM state.

Code after:
				line_number?.setAttribute(
					"aria-roledescription",
					`Line number ${index + 1}`
				);
				line_number?.setAttribute("title", `Line number ${index + 1}`);
			}
		});
	}

	$effect(() => {
		if (is_root && root_element) {
			updateLineNumbers();
		}
	});
</script>

<div
	class="json-node"
	class:root={is_root}
	class:dark-mode={theme_mode === "dark"}
	bind:this={root_element}
	style="--depth: {depth};"
>
	<div class="line" class:collapsed>
		<span class="line-number"></span>
		<span class="content">
			{#if is_collapsible(value)}
				<button
					data-pseudo-content={interactive ? (collapsed ? "▶" : "▼") : ""}
					aria-label={collapsed ? "Expand" : "Collapse"}
					class="toggle"
					disabled={!interactive}
					onclick={toggle_collapse}
				/>
			{/if}
			{#if key !== null}
				<span class="key">"{key}"</span><span class="punctuation colon"
					>:
				</span>
			{/if}
			{#if is_collapsible(value)}
				<span
					class="punctuation bracket"
					class:square-bracket={Array.isArray(value)}
					>{Array.isArray(value) ? "[" : "{"}</span
				>
				{#if collapsed}
					<button onclick={toggle_collapse} class="preview">
						{get_collapsed_preview(value)}
					</button>
					<span