Skip to content

Commit e9cc7dc

Browse files
authored
chore: tweak each block code (#15094)
1 parent 3d828b4 commit e9cc7dc

File tree

4 files changed

+26
-29
lines changed

4 files changed

+26
-29
lines changed

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

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,6 @@ export function EachBlock(node, context) {
3535
context.state.template.push('<!>');
3636
}
3737

38-
if (each_node_meta.array_name !== null) {
39-
context.state.init.push(b.const(each_node_meta.array_name, b.thunk(collection)));
40-
}
41-
4238
let flags = 0;
4339

4440
if (node.metadata.keyed && node.index) {
@@ -120,8 +116,21 @@ export function EachBlock(node, context) {
120116
return [array, ...transitive_dependencies];
121117
});
122118

123-
if (each_node_meta.array_name) {
124-
indirect_dependencies.push(b.call(each_node_meta.array_name));
119+
/** @type {Identifier | null} */
120+
let collection_id = null;
121+
122+
// Check if inner scope shadows something from outer scope.
123+
// This is necessary because we need access to the array expression of the each block
124+
// in the inner scope if bindings are used, in order to invalidate the array.
125+
for (const [name] of context.state.scope.declarations) {
126+
if (context.state.scope.parent?.get(name) != null) {
127+
collection_id = context.state.scope.root.unique('$$array');
128+
break;
129+
}
130+
}
131+
132+
if (collection_id) {
133+
indirect_dependencies.push(b.call(collection_id));
125134
} else {
126135
indirect_dependencies.push(collection);
127136

@@ -195,7 +204,7 @@ export function EachBlock(node, context) {
195204
// TODO 6.0 this only applies in legacy mode, reassignments are
196205
// forbidden in runes mode
197206
return b.member(
198-
each_node_meta.array_name ? b.call(each_node_meta.array_name) : collection,
207+
collection_id ? b.call(collection_id) : collection,
199208
(flags & EACH_INDEX_REACTIVE) !== 0 ? get_value(index) : index,
200209
true
201210
);
@@ -207,7 +216,7 @@ export function EachBlock(node, context) {
207216
uses_index = true;
208217

209218
const left = b.member(
210-
each_node_meta.array_name ? b.call(each_node_meta.array_name) : collection,
219+
collection_id ? b.call(collection_id) : collection,
211220
(flags & EACH_INDEX_REACTIVE) !== 0 ? get_value(index) : index,
212221
true
213222
);
@@ -283,16 +292,17 @@ export function EachBlock(node, context) {
283292
);
284293
}
285294

295+
const render_args = [b.id('$$anchor'), item];
296+
if (uses_index || collection_id) render_args.push(index);
297+
if (collection_id) render_args.push(collection_id);
298+
286299
/** @type {Expression[]} */
287300
const args = [
288301
context.state.node,
289302
b.literal(flags),
290-
each_node_meta.array_name ? each_node_meta.array_name : b.thunk(collection),
303+
b.thunk(collection),
291304
key_function,
292-
b.arrow(
293-
uses_index ? [b.id('$$anchor'), item, index] : [b.id('$$anchor'), item],
294-
b.block(declarations.concat(block.body))
295-
)
305+
b.arrow(render_args, b.block(declarations.concat(block.body)))
296306
];
297307

298308
if (node.fallback) {

packages/svelte/src/compiler/phases/scope.js

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -575,21 +575,10 @@ export function create_scopes(ast, root, allow_reactive_declarations, parent) {
575575
}
576576
if (node.fallback) visit(node.fallback, { scope });
577577

578-
// Check if inner scope shadows something from outer scope.
579-
// This is necessary because we need access to the array expression of the each block
580-
// in the inner scope if bindings are used, in order to invalidate the array.
581-
let needs_array_deduplication = false;
582-
for (const [name] of scope.declarations) {
583-
if (state.scope.get(name) !== null) {
584-
needs_array_deduplication = true;
585-
}
586-
}
587-
588578
node.metadata = {
589579
expression: create_expression_metadata(),
590580
keyed: false,
591581
contains_group_binding: false,
592-
array_name: needs_array_deduplication ? state.scope.root.unique('$$array') : null,
593582
index: scope.root.unique('$$index'),
594583
declarations: scope.declarations,
595584
is_controlled: false

packages/svelte/src/compiler/types/template.d.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -414,8 +414,6 @@ export namespace AST {
414414
expression: ExpressionMetadata;
415415
keyed: boolean;
416416
contains_group_binding: boolean;
417-
/** Set if something in the array expression is shadowed within the each block */
418-
array_name: Identifier | null;
419417
index: Identifier;
420418
declarations: Map<string, Binding>;
421419
/**

packages/svelte/src/internal/client/dom/blocks/each.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -271,7 +271,7 @@ export function each(node, flags, get_collection, get_key, render_fn, fallback_f
271271
* @param {Array<V>} array
272272
* @param {EachState} state
273273
* @param {Element | Comment | Text} anchor
274-
* @param {(anchor: Node, item: MaybeSource<V>, index: number | Source<number>) => void} render_fn
274+
* @param {(anchor: Node, item: MaybeSource<V>, index: number | Source<number>, collection: () => V[]) => void} render_fn
275275
* @param {number} flags
276276
* @param {boolean} is_inert
277277
* @param {(value: V, index: number) => any} get_key
@@ -510,7 +510,7 @@ function update_item(item, value, index, type) {
510510
* @param {V} value
511511
* @param {unknown} key
512512
* @param {number} index
513-
* @param {(anchor: Node, item: V | Source<V>, index: number | Value<number>) => void} render_fn
513+
* @param {(anchor: Node, item: V | Source<V>, index: number | Value<number>, collection: () => V[]) => void} render_fn
514514
* @param {number} flags
515515
* @param {() => V[]} get_collection
516516
* @returns {EachItem}
@@ -559,7 +559,7 @@ function create_item(
559559
current_each_item = item;
560560

561561
try {
562-
item.e = branch(() => render_fn(anchor, v, i), hydrating);
562+
item.e = branch(() => render_fn(anchor, v, i, get_collection), hydrating);
563563

564564
item.e.prev = prev && prev.e;
565565
item.e.next = next && next.e;

0 commit comments

Comments
 (0)