Skip to content

Commit 590f582

Browse files
committed
make each item first nodes explicit
1 parent 4fd8ce5 commit 590f582

File tree

3 files changed

+20
-27
lines changed

3 files changed

+20
-27
lines changed

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

Lines changed: 17 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import {
2525
import { source, mutable_source, set } from '../../reactivity/sources.js';
2626
import { is_array, is_frozen } from '../../utils.js';
2727
import { STATE_SYMBOL } from '../../constants.js';
28+
import { push_template_node } from '../template.js';
2829

2930
/**
3031
* The row of a keyed each block that is currently updating. We track this
@@ -168,10 +169,11 @@ export function each(anchor, flags, get_collection, get_key, render_fn, fallback
168169
break;
169170
}
170171

172+
var child_open = /** @type {Comment} */ (child_anchor);
171173
child_anchor = hydrate_anchor(child_anchor);
172174
var value = array[i];
173175
var key = get_key(value, i);
174-
item = create_item(child_anchor, prev, null, value, key, i, render_fn, flags);
176+
item = create_item(child_open, child_anchor, prev, null, value, key, i, render_fn, flags);
175177
state.items.set(key, item);
176178
child_anchor = /** @type {Comment} */ (child_anchor.nextSibling);
177179

@@ -278,8 +280,14 @@ function reconcile(array, state, anchor, render_fn, flags, get_key) {
278280
item = items.get(key);
279281

280282
if (item === undefined) {
283+
var child_open = /** @type {Text} */ (push_template_node(empty()));
284+
var child_anchor = current ? current.o : anchor;
285+
286+
child_anchor.before(child_open);
287+
281288
prev = create_item(
282-
current ? get_first_child(current) : anchor,
289+
child_open,
290+
child_anchor,
283291
prev,
284292
prev.next,
285293
value,
@@ -309,7 +317,7 @@ function reconcile(array, state, anchor, render_fn, flags, get_key) {
309317
if (matched.length < stashed.length) {
310318
// more efficient to move later items to the front
311319
var start = stashed[0];
312-
var local_anchor = get_first_child(start);
320+
var local_anchor = start.o;
313321
var j;
314322

315323
prev = start.prev;
@@ -338,7 +346,7 @@ function reconcile(array, state, anchor, render_fn, flags, get_key) {
338346
} else {
339347
// more efficient to move earlier items to the back
340348
seen.delete(item);
341-
move(item, current ? get_first_child(current) : anchor);
349+
move(item, current ? current.o : anchor);
342350

343351
link(item.prev, item.next);
344352
link(item, prev.next);
@@ -399,20 +407,6 @@ function reconcile(array, state, anchor, render_fn, flags, get_key) {
399407
}
400408
}
401409

402-
/**
403-
* @param {import('#client').EachItem} item
404-
* @returns {Text | Element | Comment}
405-
*/
406-
function get_first_child(item) {
407-
var current = item.e.dom;
408-
409-
if (is_array(current)) {
410-
return /** @type {Text | Element | Comment} */ (current[0]);
411-
}
412-
413-
return /** @type {Text | Element | Comment} */ (current);
414-
}
415-
416410
/**
417411
* @param {import('#client').EachItem} item
418412
* @param {any} value
@@ -434,6 +428,7 @@ function update_item(item, value, index, type) {
434428

435429
/**
436430
* @template V
431+
* @param {Comment | Text} open
437432
* @param {Node} anchor
438433
* @param {import('#client').EachItem | import('#client').EachState} prev
439434
* @param {import('#client').EachItem | null} next
@@ -444,7 +439,7 @@ function update_item(item, value, index, type) {
444439
* @param {number} flags
445440
* @returns {import('#client').EachItem}
446441
*/
447-
function create_item(anchor, prev, next, value, key, index, render_fn, flags) {
442+
function create_item(open, anchor, prev, next, value, key, index, render_fn, flags) {
448443
var previous_each_item = current_each_item;
449444

450445
try {
@@ -462,6 +457,7 @@ function create_item(anchor, prev, next, value, key, index, render_fn, flags) {
462457
a: null,
463458
// @ts-expect-error
464459
e: null,
460+
o: open,
465461
prev,
466462
next
467463
};
@@ -483,6 +479,8 @@ function create_item(anchor, prev, next, value, key, index, render_fn, flags) {
483479
* @param {Text | Element | Comment} anchor
484480
*/
485481
function move(item, anchor) {
482+
anchor.before(item.o);
483+
486484
var dom = item.e.dom;
487485

488486
if (dom !== null) {

packages/svelte/src/internal/client/dom/template.js

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,19 +21,12 @@ export function push_template_node(
2121
if (!is_array(current_dom)) {
2222
current_dom = effect.dom = [current_dom];
2323
}
24-
var anchor;
25-
// If we're working with an anchor, then remove it and put it at the end.
26-
if (current_dom[0].nodeType === 8) {
27-
anchor = current_dom.pop();
28-
}
24+
2925
if (is_array(dom)) {
3026
current_dom.push(...dom);
3127
} else {
3228
current_dom.push(dom);
3329
}
34-
if (anchor !== undefined) {
35-
current_dom.push(anchor);
36-
}
3730
}
3831
return dom;
3932
}

packages/svelte/src/internal/client/types.d.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,8 @@ export type EachItem = {
6767
i: number | Source<number>;
6868
/** key */
6969
k: unknown;
70+
/** anchor for items inserted before this */
71+
o: Comment | Text;
7072
prev: EachItem | EachState;
7173
next: EachItem | null;
7274
};

0 commit comments

Comments
 (0)