Skip to content

Commit be626e1

Browse files
committed
perf: hoist variables which are not mutated or reassigned
1 parent 6307a33 commit be626e1

File tree

6 files changed

+62
-2
lines changed

6 files changed

+62
-2
lines changed

.changeset/twelve-peaches-jam.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'svelte': patch
3+
---
4+
5+
perf: hoist variables which are not mutated or reassigned

packages/svelte/src/compiler/phases/3-transform/client/visitors/javascript-runes.js

+16-2
Original file line numberDiff line numberDiff line change
@@ -151,13 +151,27 @@ export const javascript_visitors_runes = {
151151

152152
return { ...node, body };
153153
},
154-
VariableDeclaration(node, { state, visit }) {
154+
VariableDeclaration(node, { path, state, visit }) {
155155
const declarations = [];
156156

157157
for (const declarator of node.declarations) {
158158
const init = unwrap_ts_expression(declarator.init);
159159
const rune = get_rune(init, state.scope);
160-
if (!rune || rune === '$effect.active' || rune === '$effect.root' || rune === '$inspect') {
160+
161+
if (
162+
!rune &&
163+
init != null &&
164+
declarator.id.type === 'Identifier'
165+
) {
166+
const is_top_level = path.at(-1)?.type === 'Program';
167+
const binding = state.scope.owner(declarator.id.name)?.declarations.get(declarator.id.name);
168+
if (is_top_level && binding && !binding.mutated && !binding.reassigned) {
169+
state.hoisted.push(b.declaration('const', declarator.id, init));
170+
continue;
171+
}
172+
}
173+
174+
if (!rune || rune === '$effect.active' || rune === '$effect.root' || rune === '$inspect') {
161175
if (init != null && is_hoistable_function(init)) {
162176
const hoistable_function = visit(init);
163177
state.hoisted.push(
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import { test } from '../../test';
2+
3+
export default test({});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// index.svelte (Svelte VERSION)
2+
// Note: compiler output will change before 5.0 is released!
3+
import "svelte/internal/disclose-version";
4+
import * as $ from "svelte/internal";
5+
6+
const count = 0;
7+
var frag = $.template(`<p> </p>`);
8+
9+
export default function Hoist_unmodified_var($$anchor, $$props) {
10+
$.push($$props, true);
11+
12+
/* Init */
13+
var p = $.open($$anchor, true, frag);
14+
var text = $.child(p);
15+
16+
text.nodeValue = $.stringify(count);
17+
$.close($$anchor, p);
18+
$.pop();
19+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// index.svelte (Svelte VERSION)
2+
// Note: compiler output will change before 5.0 is released!
3+
import * as $ from "svelte/internal/server";
4+
5+
export default function Hoist_unmodified_var($$payload, $$props) {
6+
$.push(true);
7+
8+
let count = 0;
9+
10+
$$payload.out += `<p>${$.escape_text(count)}</p>`;
11+
$.pop();
12+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<svelte:options runes={true} />
2+
3+
<script>
4+
let count = 0;
5+
</script>
6+
7+
<p>{count}</p>

0 commit comments

Comments
 (0)