Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/slow-chefs-dream.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'svelte': patch
---

chore: improve each block fast-path heuristic
Original file line number Diff line number Diff line change
Expand Up @@ -2137,33 +2137,33 @@ export const template_visitors = {
}

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

if (
node.key &&
(node.key.type !== 'Identifier' || !node.index || node.key.name !== node.index)
) {
each_type |= EACH_KEYED;
// If there's a destructuring, then we likely need the generated $$index
if (node.index || node.context.type !== 'Identifier') {
each_type |= EACH_INDEX_REACTIVE;
}
if (
context.state.analysis.runes &&
node.key.type === 'Identifier' &&
node.context.type === 'Identifier' &&
node.context.name === node.key.name &&
context.state.options.immutable
(each_type & EACH_INDEX_REACTIVE) === 0
) {
// Fast-path
// Fast-path for when the key === item
each_item_is_reactive = false;
} else {
each_type |= EACH_ITEM_REACTIVE;
}
// If there's a destructuring, then we likely need the generated $$index
if (node.index || node.context.type !== 'Identifier') {
each_type |= EACH_INDEX_REACTIVE;
}
} else {
each_type |= EACH_ITEM_REACTIVE;
}
Expand Down Expand Up @@ -2289,7 +2289,7 @@ export const template_visitors = {
)
: b.literal(null);
const key_function =
node.key && (each_type & 1) /* EACH_ITEM_REACTIVE */ !== 0
node.key && ((each_type & EACH_ITEM_REACTIVE) !== 0 || context.state.options.dev)
? b.arrow(
[node.context.type === 'Identifier' ? node.context : b.id('$$item')],
b.block(
Expand Down