Skip to content

Commit b78fed8

Browse files
committed
merge main
2 parents 6166738 + e9cc7dc commit b78fed8

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
);
@@ -285,18 +294,19 @@ export function EachBlock(node, context) {
285294

286295
const { is_async } = node.metadata.expression;
287296

288-
const thunk = each_node_meta.array_name ?? b.thunk(collection, is_async);
297+
const thunk = b.thunk(collection, is_async);
298+
299+
const render_args = [b.id('$$anchor'), item];
300+
if (uses_index || collection_id) render_args.push(index);
301+
if (collection_id) render_args.push(collection_id);
289302

290303
/** @type {Expression[]} */
291304
const args = [
292305
context.state.node,
293306
b.literal(flags),
294307
is_async ? b.thunk(b.call('$.get', b.id('$$collection'))) : thunk,
295308
key_function,
296-
b.arrow(
297-
uses_index ? [b.id('$$anchor'), item, index] : [b.id('$$anchor'), item],
298-
b.block(declarations.concat(block.body))
299-
)
309+
b.arrow(render_args, b.block(declarations.concat(block.body)))
300310
];
301311

302312
if (node.fallback) {

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

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

595-
// Check if inner scope shadows something from outer scope.
596-
// This is necessary because we need access to the array expression of the each block
597-
// in the inner scope if bindings are used, in order to invalidate the array.
598-
let needs_array_deduplication = false;
599-
for (const [name] of scope.declarations) {
600-
if (state.scope.get(name) !== null) {
601-
needs_array_deduplication = true;
602-
}
603-
}
604-
605595
node.metadata = {
606596
expression: create_expression_metadata(),
607597
keyed: false,
608598
contains_group_binding: false,
609-
array_name: needs_array_deduplication ? state.scope.root.unique('$$array') : null,
610599
index: scope.root.unique('$$index'),
611600
declarations: scope.declarations,
612601
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
@@ -419,8 +419,6 @@ export namespace AST {
419419
expression: ExpressionMetadata;
420420
keyed: boolean;
421421
contains_group_binding: boolean;
422-
/** Set if something in the array expression is shadowed within the each block */
423-
array_name: Identifier | null;
424422
index: Identifier;
425423
declarations: Map<string, Binding>;
426424
/**

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)