Skip to content

Commit cb529fc

Browse files
authored
chore: improve each block fast-path heuristic (#9855)
* chore: improve each block fast-path heuristic * chore: improve each block fast-path heuristic
1 parent 3a9b143 commit cb529fc

File tree

2 files changed

+17
-12
lines changed

2 files changed

+17
-12
lines changed

.changeset/slow-chefs-dream.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'svelte': patch
3+
---
4+
5+
chore: improve each block fast-path heuristic

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

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2137,33 +2137,33 @@ export const template_visitors = {
21372137
}
21382138

21392139
// The runtime needs to know what kind of each block this is in order to optimize for the
2140-
// immutable + key==entry case. In that case, the item doesn't need to be reactive, because
2141-
// the array as a whole is immutable, so if something changes, it either has to recreate the
2142-
// array or use nested reactivity through runes.
2143-
// TODO this feels a bit "hidden performance boost"-style, investigate if there's a way
2144-
// to make this apply in more cases
2140+
// key === item (we avoid extra allocations). In that case, the item doesn't need to be reactive.
2141+
// We can guarantee this by knowing that in order for the item of the each block to change, they
2142+
// would need to mutate the key/item directly in the array. Given that in runes mode we use ===
2143+
// equality, we can apply a fast-path (as long as the index isn't reactive).
21452144
let each_type = 0;
21462145

21472146
if (
21482147
node.key &&
21492148
(node.key.type !== 'Identifier' || !node.index || node.key.name !== node.index)
21502149
) {
21512150
each_type |= EACH_KEYED;
2151+
// If there's a destructuring, then we likely need the generated $$index
2152+
if (node.index || node.context.type !== 'Identifier') {
2153+
each_type |= EACH_INDEX_REACTIVE;
2154+
}
21522155
if (
2156+
context.state.analysis.runes &&
21532157
node.key.type === 'Identifier' &&
21542158
node.context.type === 'Identifier' &&
21552159
node.context.name === node.key.name &&
2156-
context.state.options.immutable
2160+
(each_type & EACH_INDEX_REACTIVE) === 0
21572161
) {
2158-
// Fast-path
2162+
// Fast-path for when the key === item
21592163
each_item_is_reactive = false;
21602164
} else {
21612165
each_type |= EACH_ITEM_REACTIVE;
21622166
}
2163-
// If there's a destructuring, then we likely need the generated $$index
2164-
if (node.index || node.context.type !== 'Identifier') {
2165-
each_type |= EACH_INDEX_REACTIVE;
2166-
}
21672167
} else {
21682168
each_type |= EACH_ITEM_REACTIVE;
21692169
}
@@ -2289,7 +2289,7 @@ export const template_visitors = {
22892289
)
22902290
: b.literal(null);
22912291
const key_function =
2292-
node.key && (each_type & 1) /* EACH_ITEM_REACTIVE */ !== 0
2292+
node.key && ((each_type & EACH_ITEM_REACTIVE) !== 0 || context.state.options.dev)
22932293
? b.arrow(
22942294
[node.context.type === 'Identifier' ? node.context : b.id('$$item')],
22952295
b.block(

0 commit comments

Comments
 (0)