From 22247150c8ddf01cd4d2dd8baeb29363e4e84e28 Mon Sep 17 00:00:00 2001 From: ljodea Date: Wed, 29 Jul 2026 16:18:09 -0500 Subject: [PATCH] =?UTF-8?q?perf:=20O(n=C2=B2)=E2=86=92O(n)=20Map=20lookups?= =?UTF-8?q?=20for=20legacy=20`$:`=20reactive=20statements?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use Map.get/has instead of spread+find/includes when ordering and emitting legacy reactive statements. n is the number of `$:` statements per component. --- .changeset/legacy-reactive-map-lookups.md | 5 +++++ packages/svelte/src/compiler/phases/2-analyze/index.js | 3 ++- .../compiler/phases/3-transform/client/transform-client.js | 4 ++-- .../compiler/phases/3-transform/server/transform-server.js | 4 ++-- 4 files changed, 11 insertions(+), 5 deletions(-) create mode 100644 .changeset/legacy-reactive-map-lookups.md diff --git a/.changeset/legacy-reactive-map-lookups.md b/.changeset/legacy-reactive-map-lookups.md new file mode 100644 index 0000000000..ec6f4fbf9d --- /dev/null +++ b/.changeset/legacy-reactive-map-lookups.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +perf: O(n²)→O(n) Map lookups for legacy `$:` reactive statement ordering diff --git a/packages/svelte/src/compiler/phases/2-analyze/index.js b/packages/svelte/src/compiler/phases/2-analyze/index.js index 67e9030188..d5106f4f73 100644 --- a/packages/svelte/src/compiler/phases/2-analyze/index.js +++ b/packages/svelte/src/compiler/phases/2-analyze/index.js @@ -1314,7 +1314,8 @@ function order_reactive_statements(unsorted_reactive_declarations) { * @returns */ const add_declaration = (node, declaration) => { - if ([...reactive_declarations.values()].includes(declaration)) return; + // Visited set: each ReactiveStatement is stored under exactly one LabeledStatement node + if (reactive_declarations.has(node)) return; for (const binding of declaration.dependencies) { if (declaration.assignments.has(binding)) continue; diff --git a/packages/svelte/src/compiler/phases/3-transform/client/transform-client.js b/packages/svelte/src/compiler/phases/3-transform/client/transform-client.js index 552fe89960..cbb5f2eac7 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/transform-client.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/transform-client.js @@ -247,11 +247,11 @@ export function client_component(analysis, options) { } for (const [node] of analysis.reactive_statements) { - const statement = [...state.legacy_reactive_statements].find(([n]) => n === node); + const statement = state.legacy_reactive_statements.get(node); if (statement === undefined) { throw new Error('Could not find reactive statement'); } - instance.body.push(statement[1]); + instance.body.push(statement); } if (analysis.reactive_statements.size > 0) { diff --git a/packages/svelte/src/compiler/phases/3-transform/server/transform-server.js b/packages/svelte/src/compiler/phases/3-transform/server/transform-server.js index 24ca58bb41..0a533aec37 100644 --- a/packages/svelte/src/compiler/phases/3-transform/server/transform-server.js +++ b/packages/svelte/src/compiler/phases/3-transform/server/transform-server.js @@ -148,7 +148,7 @@ export function server_component(analysis, options) { const legacy_reactive_declarations = []; for (const [node] of analysis.reactive_statements) { - const statement = [...state.legacy_reactive_statements].find(([n]) => n === node); + const statement = state.legacy_reactive_statements.get(node); if (statement === undefined) { throw new Error('Could not find reactive statement'); } @@ -165,7 +165,7 @@ export function server_component(analysis, options) { } } - instance.body.push(statement[1]); + instance.body.push(statement); } if (legacy_reactive_declarations.length > 0) {