svelte 5.45.3 → 5.45.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/compiler/index.js +1 -1
- package/package.json +2 -2
- package/src/compiler/phases/2-analyze/index.js +5 -0
- package/src/internal/client/constants.js +1 -0
- package/src/internal/client/dev/debug.js +4 -4
- package/src/internal/client/dom/blocks/css-props.js +2 -3
- package/src/internal/client/dom/blocks/each.js +212 -222
- package/src/internal/client/dom/blocks/html.js +7 -5
- package/src/internal/client/dom/blocks/svelte-element.js +11 -14
- package/src/internal/client/dom/blocks/svelte-head.js +2 -2
- package/src/internal/client/dom/elements/transitions.js +15 -7
- package/src/internal/client/dom/hydration.js +2 -2
- package/src/internal/client/dom/operations.js +10 -13
- package/src/internal/client/dom/template.js +15 -13
- package/src/internal/client/reactivity/async.js +1 -6
- package/src/internal/client/reactivity/batch.js +1 -1
- package/src/internal/client/reactivity/effects.js +25 -27
- package/src/internal/client/render.js +5 -4
- package/src/internal/client/runtime.js +1 -1
- package/src/version.js +1 -1
- package/types/index.d.ts +2 -0
- package/types/index.d.ts.map +1 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/** @import { EachItem, EachState, Effect, MaybeSource, Source, TemplateNode, TransitionManager, Value } from '#client' */
|
|
1
|
+
/** @import { EachItem, EachOutroGroup, EachState, Effect, EffectNodes, MaybeSource, Source, TemplateNode, TransitionManager, Value } from '#client' */
|
|
2
2
|
/** @import { Batch } from '../../reactivity/batch.js'; */
|
|
3
3
|
import {
|
|
4
4
|
EACH_INDEX_REACTIVE,
|
|
@@ -29,31 +29,21 @@ import {
|
|
|
29
29
|
block,
|
|
30
30
|
branch,
|
|
31
31
|
destroy_effect,
|
|
32
|
-
run_out_transitions,
|
|
33
|
-
pause_children,
|
|
34
32
|
pause_effect,
|
|
35
33
|
resume_effect
|
|
36
34
|
} from '../../reactivity/effects.js';
|
|
37
35
|
import { source, mutable_source, internal_set } from '../../reactivity/sources.js';
|
|
38
36
|
import { array_from, is_array } from '../../../shared/utils.js';
|
|
39
|
-
import { COMMENT_NODE, INERT } from '#client/constants';
|
|
37
|
+
import { COMMENT_NODE, EFFECT_OFFSCREEN, INERT } from '#client/constants';
|
|
40
38
|
import { queue_micro_task } from '../task.js';
|
|
41
39
|
import { get } from '../../runtime.js';
|
|
42
40
|
import { DEV } from 'esm-env';
|
|
43
41
|
import { derived_safe_equal } from '../../reactivity/deriveds.js';
|
|
44
42
|
import { current_batch } from '../../reactivity/batch.js';
|
|
45
43
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
* @type {EachItem | null}
|
|
50
|
-
*/
|
|
51
|
-
export let current_each_item = null;
|
|
52
|
-
|
|
53
|
-
/** @param {EachItem | null} item */
|
|
54
|
-
export function set_current_each_item(item) {
|
|
55
|
-
current_each_item = item;
|
|
56
|
-
}
|
|
44
|
+
// When making substantive changes to this file, validate them with the each block stress test:
|
|
45
|
+
// https://svelte.dev/playground/1972b2cf46564476ad8c8c6405b23b7b
|
|
46
|
+
// This test also exists in this repo, as `packages/svelte/tests/manual/each-stress-test`
|
|
57
47
|
|
|
58
48
|
/**
|
|
59
49
|
* @param {any} _
|
|
@@ -67,7 +57,7 @@ export function index(_, i) {
|
|
|
67
57
|
* Pause multiple effects simultaneously, and coordinate their
|
|
68
58
|
* subsequent destruction. Used in each blocks
|
|
69
59
|
* @param {EachState} state
|
|
70
|
-
* @param {
|
|
60
|
+
* @param {Effect[]} to_destroy
|
|
71
61
|
* @param {null | Node} controlled_anchor
|
|
72
62
|
*/
|
|
73
63
|
function pause_effects(state, to_destroy, controlled_anchor) {
|
|
@@ -75,19 +65,44 @@ function pause_effects(state, to_destroy, controlled_anchor) {
|
|
|
75
65
|
var transitions = [];
|
|
76
66
|
var length = to_destroy.length;
|
|
77
67
|
|
|
68
|
+
/** @type {EachOutroGroup} */
|
|
69
|
+
var group;
|
|
70
|
+
var remaining = to_destroy.length;
|
|
71
|
+
|
|
78
72
|
for (var i = 0; i < length; i++) {
|
|
79
|
-
|
|
73
|
+
let effect = to_destroy[i];
|
|
74
|
+
|
|
75
|
+
pause_effect(
|
|
76
|
+
effect,
|
|
77
|
+
() => {
|
|
78
|
+
if (group) {
|
|
79
|
+
group.pending.delete(effect);
|
|
80
|
+
group.done.add(effect);
|
|
81
|
+
|
|
82
|
+
if (group.pending.size === 0) {
|
|
83
|
+
var groups = /** @type {Set<EachOutroGroup>} */ (state.outrogroups);
|
|
84
|
+
|
|
85
|
+
destroy_effects(array_from(group.done));
|
|
86
|
+
groups.delete(group);
|
|
87
|
+
|
|
88
|
+
if (groups.size === 0) {
|
|
89
|
+
state.outrogroups = null;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
} else {
|
|
93
|
+
remaining -= 1;
|
|
94
|
+
}
|
|
95
|
+
},
|
|
96
|
+
false
|
|
97
|
+
);
|
|
80
98
|
}
|
|
81
99
|
|
|
82
|
-
|
|
100
|
+
if (remaining === 0) {
|
|
83
101
|
// If we're in a controlled each block (i.e. the block is the only child of an
|
|
84
102
|
// element), and we are removing all items, _and_ there are no out transitions,
|
|
85
103
|
// we can use the fast path — emptying the element and replacing the anchor
|
|
86
104
|
var fast_path = transitions.length === 0 && controlled_anchor !== null;
|
|
87
105
|
|
|
88
|
-
// TODO only destroy effects if no pending batch needs them. otherwise,
|
|
89
|
-
// just set `item.o` back to `false`
|
|
90
|
-
|
|
91
106
|
if (fast_path) {
|
|
92
107
|
var anchor = /** @type {Element} */ (controlled_anchor);
|
|
93
108
|
var parent_node = /** @type {Element} */ (anchor.parentNode);
|
|
@@ -96,26 +111,34 @@ function pause_effects(state, to_destroy, controlled_anchor) {
|
|
|
96
111
|
parent_node.append(anchor);
|
|
97
112
|
|
|
98
113
|
state.items.clear();
|
|
99
|
-
link(state, to_destroy[0].prev, to_destroy[length - 1].next);
|
|
100
114
|
}
|
|
101
115
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
}
|
|
116
|
+
destroy_effects(to_destroy, !fast_path);
|
|
117
|
+
} else {
|
|
118
|
+
group = {
|
|
119
|
+
pending: new Set(to_destroy),
|
|
120
|
+
done: new Set()
|
|
121
|
+
};
|
|
109
122
|
|
|
110
|
-
|
|
111
|
-
|
|
123
|
+
(state.outrogroups ??= new Set()).add(group);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
112
126
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
127
|
+
/**
|
|
128
|
+
* @param {Effect[]} to_destroy
|
|
129
|
+
* @param {boolean} remove_dom
|
|
130
|
+
*/
|
|
131
|
+
function destroy_effects(to_destroy, remove_dom = true) {
|
|
132
|
+
// TODO only destroy effects if no pending batch needs them. otherwise,
|
|
133
|
+
// just re-add the `EFFECT_OFFSCREEN` flag
|
|
134
|
+
for (var i = 0; i < to_destroy.length; i++) {
|
|
135
|
+
destroy_effect(to_destroy[i], remove_dom);
|
|
136
|
+
}
|
|
117
137
|
}
|
|
118
138
|
|
|
139
|
+
/** @type {TemplateNode} */
|
|
140
|
+
var offscreen_anchor;
|
|
141
|
+
|
|
119
142
|
/**
|
|
120
143
|
* @template V
|
|
121
144
|
* @param {Element | Comment} node The next sibling node, or the parent node if this is a 'controlled' block
|
|
@@ -132,18 +155,13 @@ export function each(node, flags, get_collection, get_key, render_fn, fallback_f
|
|
|
132
155
|
/** @type {Map<any, EachItem>} */
|
|
133
156
|
var items = new Map();
|
|
134
157
|
|
|
135
|
-
/** @type {EachItem | null} */
|
|
136
|
-
var first = null;
|
|
137
|
-
|
|
138
158
|
var is_controlled = (flags & EACH_IS_CONTROLLED) !== 0;
|
|
139
|
-
var is_reactive_value = (flags & EACH_ITEM_REACTIVE) !== 0;
|
|
140
|
-
var is_reactive_index = (flags & EACH_INDEX_REACTIVE) !== 0;
|
|
141
159
|
|
|
142
160
|
if (is_controlled) {
|
|
143
161
|
var parent_node = /** @type {Element} */ (node);
|
|
144
162
|
|
|
145
163
|
anchor = hydrating
|
|
146
|
-
? set_hydrate_node(
|
|
164
|
+
? set_hydrate_node(get_first_child(parent_node))
|
|
147
165
|
: parent_node.appendChild(create_text());
|
|
148
166
|
}
|
|
149
167
|
|
|
@@ -151,7 +169,7 @@ export function each(node, flags, get_collection, get_key, render_fn, fallback_f
|
|
|
151
169
|
hydrate_next();
|
|
152
170
|
}
|
|
153
171
|
|
|
154
|
-
/** @type {
|
|
172
|
+
/** @type {Effect | null} */
|
|
155
173
|
var fallback = null;
|
|
156
174
|
|
|
157
175
|
// TODO: ideally we could use derived for runes mode but because of the ability
|
|
@@ -169,20 +187,19 @@ export function each(node, flags, get_collection, get_key, render_fn, fallback_f
|
|
|
169
187
|
var first_run = true;
|
|
170
188
|
|
|
171
189
|
function commit() {
|
|
190
|
+
state.fallback = fallback;
|
|
172
191
|
reconcile(state, array, anchor, flags, get_key);
|
|
173
192
|
|
|
174
193
|
if (fallback !== null) {
|
|
175
194
|
if (array.length === 0) {
|
|
176
|
-
if (fallback.
|
|
177
|
-
|
|
178
|
-
fallback.fragment = null;
|
|
195
|
+
if ((fallback.f & EFFECT_OFFSCREEN) === 0) {
|
|
196
|
+
resume_effect(fallback);
|
|
179
197
|
} else {
|
|
180
|
-
|
|
198
|
+
fallback.f ^= EFFECT_OFFSCREEN;
|
|
199
|
+
move(fallback, null, anchor);
|
|
181
200
|
}
|
|
182
|
-
|
|
183
|
-
effect.first = fallback.effect;
|
|
184
201
|
} else {
|
|
185
|
-
pause_effect(fallback
|
|
202
|
+
pause_effect(fallback, () => {
|
|
186
203
|
// TODO only null out if no pending batch needs it,
|
|
187
204
|
// otherwise re-add `fallback.fragment` and move the
|
|
188
205
|
// effect into it
|
|
@@ -214,10 +231,9 @@ export function each(node, flags, get_collection, get_key, render_fn, fallback_f
|
|
|
214
231
|
|
|
215
232
|
var keys = new Set();
|
|
216
233
|
var batch = /** @type {Batch} */ (current_batch);
|
|
217
|
-
var prev = null;
|
|
218
234
|
var defer = should_defer_append();
|
|
219
235
|
|
|
220
|
-
for (var
|
|
236
|
+
for (var index = 0; index < length; index += 1) {
|
|
221
237
|
if (
|
|
222
238
|
hydrating &&
|
|
223
239
|
hydrate_node.nodeType === COMMENT_NODE &&
|
|
@@ -230,48 +246,33 @@ export function each(node, flags, get_collection, get_key, render_fn, fallback_f
|
|
|
230
246
|
set_hydrating(false);
|
|
231
247
|
}
|
|
232
248
|
|
|
233
|
-
var value = array[
|
|
234
|
-
var key = get_key(value,
|
|
249
|
+
var value = array[index];
|
|
250
|
+
var key = get_key(value, index);
|
|
235
251
|
|
|
236
252
|
var item = first_run ? null : items.get(key);
|
|
237
253
|
|
|
238
254
|
if (item) {
|
|
239
255
|
// update before reconciliation, to trigger any async updates
|
|
240
|
-
if (
|
|
241
|
-
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
if (is_reactive_index) {
|
|
245
|
-
internal_set(/** @type {Value<number>} */ (item.i), i);
|
|
246
|
-
} else {
|
|
247
|
-
item.i = i;
|
|
248
|
-
}
|
|
256
|
+
if (item.v) internal_set(item.v, value);
|
|
257
|
+
if (item.i) internal_set(item.i, index);
|
|
249
258
|
|
|
250
259
|
if (defer) {
|
|
251
260
|
batch.skipped_effects.delete(item.e);
|
|
252
261
|
}
|
|
253
262
|
} else {
|
|
254
263
|
item = create_item(
|
|
255
|
-
|
|
256
|
-
|
|
264
|
+
items,
|
|
265
|
+
first_run ? anchor : (offscreen_anchor ??= create_text()),
|
|
257
266
|
value,
|
|
258
267
|
key,
|
|
259
|
-
|
|
268
|
+
index,
|
|
260
269
|
render_fn,
|
|
261
270
|
flags,
|
|
262
271
|
get_collection
|
|
263
272
|
);
|
|
264
273
|
|
|
265
|
-
if (first_run) {
|
|
266
|
-
item.
|
|
267
|
-
|
|
268
|
-
if (prev === null) {
|
|
269
|
-
first = item;
|
|
270
|
-
} else {
|
|
271
|
-
prev.next = item;
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
prev = item;
|
|
274
|
+
if (!first_run) {
|
|
275
|
+
item.e.f |= EFFECT_OFFSCREEN;
|
|
275
276
|
}
|
|
276
277
|
|
|
277
278
|
items.set(key, item);
|
|
@@ -282,19 +283,10 @@ export function each(node, flags, get_collection, get_key, render_fn, fallback_f
|
|
|
282
283
|
|
|
283
284
|
if (length === 0 && fallback_fn && !fallback) {
|
|
284
285
|
if (first_run) {
|
|
285
|
-
fallback =
|
|
286
|
-
fragment: null,
|
|
287
|
-
effect: branch(() => fallback_fn(anchor))
|
|
288
|
-
};
|
|
286
|
+
fallback = branch(() => fallback_fn(anchor));
|
|
289
287
|
} else {
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
fragment.append(target);
|
|
293
|
-
|
|
294
|
-
fallback = {
|
|
295
|
-
fragment,
|
|
296
|
-
effect: branch(() => fallback_fn(target))
|
|
297
|
-
};
|
|
288
|
+
fallback = branch(() => fallback_fn((offscreen_anchor ??= create_text())));
|
|
289
|
+
fallback.f |= EFFECT_OFFSCREEN;
|
|
298
290
|
}
|
|
299
291
|
}
|
|
300
292
|
|
|
@@ -335,7 +327,7 @@ export function each(node, flags, get_collection, get_key, render_fn, fallback_f
|
|
|
335
327
|
});
|
|
336
328
|
|
|
337
329
|
/** @type {EachState} */
|
|
338
|
-
var state = { effect, flags, items,
|
|
330
|
+
var state = { effect, flags, items, outrogroups: null, fallback };
|
|
339
331
|
|
|
340
332
|
first_run = false;
|
|
341
333
|
|
|
@@ -359,21 +351,21 @@ function reconcile(state, array, anchor, flags, get_key) {
|
|
|
359
351
|
|
|
360
352
|
var length = array.length;
|
|
361
353
|
var items = state.items;
|
|
362
|
-
var current = state.first;
|
|
354
|
+
var current = state.effect.first;
|
|
363
355
|
|
|
364
|
-
/** @type {undefined | Set<
|
|
356
|
+
/** @type {undefined | Set<Effect>} */
|
|
365
357
|
var seen;
|
|
366
358
|
|
|
367
|
-
/** @type {
|
|
359
|
+
/** @type {Effect | null} */
|
|
368
360
|
var prev = null;
|
|
369
361
|
|
|
370
|
-
/** @type {undefined | Set<
|
|
362
|
+
/** @type {undefined | Set<Effect>} */
|
|
371
363
|
var to_animate;
|
|
372
364
|
|
|
373
|
-
/** @type {
|
|
365
|
+
/** @type {Effect[]} */
|
|
374
366
|
var matched = [];
|
|
375
367
|
|
|
376
|
-
/** @type {
|
|
368
|
+
/** @type {Effect[]} */
|
|
377
369
|
var stashed = [];
|
|
378
370
|
|
|
379
371
|
/** @type {V} */
|
|
@@ -382,8 +374,8 @@ function reconcile(state, array, anchor, flags, get_key) {
|
|
|
382
374
|
/** @type {any} */
|
|
383
375
|
var key;
|
|
384
376
|
|
|
385
|
-
/** @type {
|
|
386
|
-
var
|
|
377
|
+
/** @type {Effect | undefined} */
|
|
378
|
+
var effect;
|
|
387
379
|
|
|
388
380
|
/** @type {number} */
|
|
389
381
|
var i;
|
|
@@ -392,13 +384,13 @@ function reconcile(state, array, anchor, flags, get_key) {
|
|
|
392
384
|
for (i = 0; i < length; i += 1) {
|
|
393
385
|
value = array[i];
|
|
394
386
|
key = get_key(value, i);
|
|
395
|
-
|
|
387
|
+
effect = /** @type {EachItem} */ (items.get(key)).e;
|
|
396
388
|
|
|
397
389
|
// offscreen == coming in now, no animation in that case,
|
|
398
390
|
// else this would happen https://github.com/sveltejs/svelte/issues/17181
|
|
399
|
-
if (
|
|
400
|
-
|
|
401
|
-
(to_animate ??= new Set()).add(
|
|
391
|
+
if ((effect.f & EFFECT_OFFSCREEN) === 0) {
|
|
392
|
+
effect.nodes?.a?.measure();
|
|
393
|
+
(to_animate ??= new Set()).add(effect);
|
|
402
394
|
}
|
|
403
395
|
}
|
|
404
396
|
}
|
|
@@ -407,38 +399,53 @@ function reconcile(state, array, anchor, flags, get_key) {
|
|
|
407
399
|
value = array[i];
|
|
408
400
|
key = get_key(value, i);
|
|
409
401
|
|
|
410
|
-
|
|
402
|
+
effect = /** @type {EachItem} */ (items.get(key)).e;
|
|
411
403
|
|
|
412
|
-
state.
|
|
404
|
+
if (state.outrogroups !== null) {
|
|
405
|
+
for (const group of state.outrogroups) {
|
|
406
|
+
group.pending.delete(effect);
|
|
407
|
+
group.done.delete(effect);
|
|
408
|
+
}
|
|
409
|
+
}
|
|
413
410
|
|
|
414
|
-
if (
|
|
415
|
-
|
|
411
|
+
if ((effect.f & EFFECT_OFFSCREEN) !== 0) {
|
|
412
|
+
effect.f ^= EFFECT_OFFSCREEN;
|
|
416
413
|
|
|
417
|
-
|
|
414
|
+
if (effect === current) {
|
|
415
|
+
move(effect, null, anchor);
|
|
416
|
+
} else {
|
|
417
|
+
var next = prev ? prev.next : current;
|
|
418
418
|
|
|
419
|
-
|
|
420
|
-
|
|
419
|
+
if (effect === state.effect.last) {
|
|
420
|
+
state.effect.last = effect.prev;
|
|
421
|
+
}
|
|
421
422
|
|
|
422
|
-
|
|
423
|
-
|
|
423
|
+
if (effect.prev) effect.prev.next = effect.next;
|
|
424
|
+
if (effect.next) effect.next.prev = effect.prev;
|
|
425
|
+
link(state, prev, effect);
|
|
426
|
+
link(state, effect, next);
|
|
424
427
|
|
|
425
|
-
|
|
426
|
-
|
|
428
|
+
move(effect, next, anchor);
|
|
429
|
+
prev = effect;
|
|
427
430
|
|
|
428
|
-
|
|
429
|
-
|
|
431
|
+
matched = [];
|
|
432
|
+
stashed = [];
|
|
433
|
+
|
|
434
|
+
current = prev.next;
|
|
435
|
+
continue;
|
|
436
|
+
}
|
|
430
437
|
}
|
|
431
438
|
|
|
432
|
-
if ((
|
|
433
|
-
resume_effect(
|
|
439
|
+
if ((effect.f & INERT) !== 0) {
|
|
440
|
+
resume_effect(effect);
|
|
434
441
|
if (is_animated) {
|
|
435
|
-
|
|
436
|
-
(to_animate ??= new Set()).delete(
|
|
442
|
+
effect.nodes?.a?.unfix();
|
|
443
|
+
(to_animate ??= new Set()).delete(effect);
|
|
437
444
|
}
|
|
438
445
|
}
|
|
439
446
|
|
|
440
|
-
if (
|
|
441
|
-
if (seen !== undefined && seen.has(
|
|
447
|
+
if (effect !== current) {
|
|
448
|
+
if (seen !== undefined && seen.has(effect)) {
|
|
442
449
|
if (matched.length < stashed.length) {
|
|
443
450
|
// more efficient to move later items to the front
|
|
444
451
|
var start = stashed[0];
|
|
@@ -469,14 +476,14 @@ function reconcile(state, array, anchor, flags, get_key) {
|
|
|
469
476
|
stashed = [];
|
|
470
477
|
} else {
|
|
471
478
|
// more efficient to move earlier items to the back
|
|
472
|
-
seen.delete(
|
|
473
|
-
move(
|
|
479
|
+
seen.delete(effect);
|
|
480
|
+
move(effect, current, anchor);
|
|
474
481
|
|
|
475
|
-
link(state,
|
|
476
|
-
link(state,
|
|
477
|
-
link(state, prev,
|
|
482
|
+
link(state, effect.prev, effect.next);
|
|
483
|
+
link(state, effect, prev === null ? state.effect.first : prev.next);
|
|
484
|
+
link(state, prev, effect);
|
|
478
485
|
|
|
479
|
-
prev =
|
|
486
|
+
prev = effect;
|
|
480
487
|
}
|
|
481
488
|
|
|
482
489
|
continue;
|
|
@@ -485,12 +492,8 @@ function reconcile(state, array, anchor, flags, get_key) {
|
|
|
485
492
|
matched = [];
|
|
486
493
|
stashed = [];
|
|
487
494
|
|
|
488
|
-
while (current !== null && current
|
|
489
|
-
|
|
490
|
-
// skip over adding it to our seen Set as the item is already being handled
|
|
491
|
-
if ((current.e.f & INERT) === 0) {
|
|
492
|
-
(seen ??= new Set()).add(current);
|
|
493
|
-
}
|
|
495
|
+
while (current !== null && current !== effect) {
|
|
496
|
+
(seen ??= new Set()).add(current);
|
|
494
497
|
stashed.push(current);
|
|
495
498
|
current = current.next;
|
|
496
499
|
}
|
|
@@ -498,42 +501,62 @@ function reconcile(state, array, anchor, flags, get_key) {
|
|
|
498
501
|
if (current === null) {
|
|
499
502
|
continue;
|
|
500
503
|
}
|
|
504
|
+
}
|
|
501
505
|
|
|
502
|
-
|
|
506
|
+
if ((effect.f & EFFECT_OFFSCREEN) === 0) {
|
|
507
|
+
matched.push(effect);
|
|
503
508
|
}
|
|
504
509
|
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
current = item.next;
|
|
510
|
+
prev = effect;
|
|
511
|
+
current = effect.next;
|
|
508
512
|
}
|
|
509
513
|
|
|
510
|
-
|
|
514
|
+
if (state.outrogroups !== null) {
|
|
515
|
+
for (const group of state.outrogroups) {
|
|
516
|
+
if (group.pending.size === 0) {
|
|
517
|
+
destroy_effects(array_from(group.done));
|
|
518
|
+
state.outrogroups?.delete(group);
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
if (state.outrogroups.size === 0) {
|
|
523
|
+
state.outrogroups = null;
|
|
524
|
+
}
|
|
525
|
+
}
|
|
511
526
|
|
|
512
527
|
if (current !== null || seen !== undefined) {
|
|
513
|
-
|
|
528
|
+
/** @type {Effect[]} */
|
|
529
|
+
var to_destroy = [];
|
|
530
|
+
|
|
531
|
+
if (seen !== undefined) {
|
|
532
|
+
for (effect of seen) {
|
|
533
|
+
if ((effect.f & INERT) === 0) {
|
|
534
|
+
to_destroy.push(effect);
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
}
|
|
514
538
|
|
|
515
539
|
while (current !== null) {
|
|
516
540
|
// If the each block isn't inert, then inert effects are currently outroing and will be removed once the transition is finished
|
|
517
|
-
if ((current.
|
|
541
|
+
if ((current.f & INERT) === 0 && current !== state.fallback) {
|
|
518
542
|
to_destroy.push(current);
|
|
519
543
|
}
|
|
544
|
+
|
|
520
545
|
current = current.next;
|
|
521
546
|
}
|
|
522
547
|
|
|
523
548
|
var destroy_length = to_destroy.length;
|
|
524
549
|
|
|
525
|
-
has_offscreen_items = items.size - destroy_length > length;
|
|
526
|
-
|
|
527
550
|
if (destroy_length > 0) {
|
|
528
551
|
var controlled_anchor = (flags & EACH_IS_CONTROLLED) !== 0 && length === 0 ? anchor : null;
|
|
529
552
|
|
|
530
553
|
if (is_animated) {
|
|
531
554
|
for (i = 0; i < destroy_length; i += 1) {
|
|
532
|
-
to_destroy[i].a?.measure();
|
|
555
|
+
to_destroy[i].nodes?.a?.measure();
|
|
533
556
|
}
|
|
534
557
|
|
|
535
558
|
for (i = 0; i < destroy_length; i += 1) {
|
|
536
|
-
to_destroy[i].a?.fix();
|
|
559
|
+
to_destroy[i].nodes?.a?.fix();
|
|
537
560
|
}
|
|
538
561
|
}
|
|
539
562
|
|
|
@@ -541,23 +564,11 @@ function reconcile(state, array, anchor, flags, get_key) {
|
|
|
541
564
|
}
|
|
542
565
|
}
|
|
543
566
|
|
|
544
|
-
// Append offscreen items at the end
|
|
545
|
-
if (has_offscreen_items) {
|
|
546
|
-
for (const item of items.values()) {
|
|
547
|
-
if (!item.o) {
|
|
548
|
-
link(state, prev, item);
|
|
549
|
-
prev = item;
|
|
550
|
-
}
|
|
551
|
-
}
|
|
552
|
-
}
|
|
553
|
-
|
|
554
|
-
state.effect.last = prev && prev.e;
|
|
555
|
-
|
|
556
567
|
if (is_animated) {
|
|
557
568
|
queue_micro_task(() => {
|
|
558
569
|
if (to_animate === undefined) return;
|
|
559
|
-
for (
|
|
560
|
-
|
|
570
|
+
for (effect of to_animate) {
|
|
571
|
+
effect.nodes?.a?.apply();
|
|
561
572
|
}
|
|
562
573
|
});
|
|
563
574
|
}
|
|
@@ -565,8 +576,8 @@ function reconcile(state, array, anchor, flags, get_key) {
|
|
|
565
576
|
|
|
566
577
|
/**
|
|
567
578
|
* @template V
|
|
568
|
-
* @param {
|
|
569
|
-
* @param {
|
|
579
|
+
* @param {Map<any, EachItem>} items
|
|
580
|
+
* @param {Node} anchor
|
|
570
581
|
* @param {V} value
|
|
571
582
|
* @param {unknown} key
|
|
572
583
|
* @param {number} index
|
|
@@ -575,102 +586,81 @@ function reconcile(state, array, anchor, flags, get_key) {
|
|
|
575
586
|
* @param {() => V[]} get_collection
|
|
576
587
|
* @returns {EachItem}
|
|
577
588
|
*/
|
|
578
|
-
function create_item(
|
|
579
|
-
var
|
|
580
|
-
|
|
581
|
-
|
|
589
|
+
function create_item(items, anchor, value, key, index, render_fn, flags, get_collection) {
|
|
590
|
+
var v =
|
|
591
|
+
(flags & EACH_ITEM_REACTIVE) !== 0
|
|
592
|
+
? (flags & EACH_ITEM_IMMUTABLE) === 0
|
|
593
|
+
? mutable_source(value, false, false)
|
|
594
|
+
: source(value)
|
|
595
|
+
: null;
|
|
582
596
|
|
|
583
|
-
var
|
|
584
|
-
var i = (flags & EACH_INDEX_REACTIVE) === 0 ? index : source(index);
|
|
597
|
+
var i = (flags & EACH_INDEX_REACTIVE) !== 0 ? source(index) : null;
|
|
585
598
|
|
|
586
|
-
if (DEV &&
|
|
599
|
+
if (DEV && v) {
|
|
587
600
|
// For tracing purposes, we need to link the source signal we create with the
|
|
588
601
|
// collection + index so that tracing works as intended
|
|
589
|
-
|
|
590
|
-
var collection_index = typeof i === 'number' ? index : i.v;
|
|
602
|
+
v.trace = () => {
|
|
591
603
|
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
|
|
592
|
-
get_collection()[
|
|
604
|
+
get_collection()[i?.v ?? index];
|
|
593
605
|
};
|
|
594
606
|
}
|
|
595
607
|
|
|
596
|
-
|
|
597
|
-
var item = {
|
|
598
|
-
i,
|
|
608
|
+
return {
|
|
599
609
|
v,
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
e: null,
|
|
604
|
-
o: false,
|
|
605
|
-
prev,
|
|
606
|
-
next: null
|
|
607
|
-
};
|
|
608
|
-
|
|
609
|
-
current_each_item = item;
|
|
610
|
-
|
|
611
|
-
try {
|
|
612
|
-
if (anchor === null) {
|
|
613
|
-
var fragment = document.createDocumentFragment();
|
|
614
|
-
fragment.append((anchor = create_text()));
|
|
615
|
-
}
|
|
616
|
-
|
|
617
|
-
item.e = branch(() => render_fn(/** @type {Node} */ (anchor), v, i, get_collection));
|
|
618
|
-
|
|
619
|
-
if (prev !== null) {
|
|
620
|
-
// we only need to set `prev.next = item`, because
|
|
621
|
-
// `item.prev = prev` was set on initialization.
|
|
622
|
-
// the effects themselves are already linked
|
|
623
|
-
prev.next = item;
|
|
624
|
-
}
|
|
610
|
+
i,
|
|
611
|
+
e: branch(() => {
|
|
612
|
+
render_fn(anchor, v ?? value, i ?? index, get_collection);
|
|
625
613
|
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
614
|
+
return () => {
|
|
615
|
+
items.delete(key);
|
|
616
|
+
};
|
|
617
|
+
})
|
|
618
|
+
};
|
|
630
619
|
}
|
|
631
620
|
|
|
632
621
|
/**
|
|
633
|
-
* @param {
|
|
634
|
-
* @param {
|
|
622
|
+
* @param {Effect} effect
|
|
623
|
+
* @param {Effect | null} next
|
|
635
624
|
* @param {Text | Element | Comment} anchor
|
|
636
625
|
*/
|
|
637
|
-
function move(
|
|
638
|
-
|
|
626
|
+
function move(effect, next, anchor) {
|
|
627
|
+
if (!effect.nodes) return;
|
|
628
|
+
|
|
629
|
+
var node = effect.nodes.start;
|
|
630
|
+
var end = effect.nodes.end;
|
|
639
631
|
|
|
640
|
-
var dest =
|
|
641
|
-
|
|
632
|
+
var dest =
|
|
633
|
+
next && (next.f & EFFECT_OFFSCREEN) === 0
|
|
634
|
+
? /** @type {EffectNodes} */ (next.nodes).start
|
|
635
|
+
: anchor;
|
|
642
636
|
|
|
643
|
-
while (node !== null
|
|
637
|
+
while (node !== null) {
|
|
644
638
|
var next_node = /** @type {TemplateNode} */ (get_next_sibling(node));
|
|
645
639
|
dest.before(node);
|
|
640
|
+
|
|
641
|
+
if (node === end) {
|
|
642
|
+
return;
|
|
643
|
+
}
|
|
644
|
+
|
|
646
645
|
node = next_node;
|
|
647
646
|
}
|
|
648
647
|
}
|
|
649
648
|
|
|
650
649
|
/**
|
|
651
650
|
* @param {EachState} state
|
|
652
|
-
* @param {
|
|
653
|
-
* @param {
|
|
651
|
+
* @param {Effect | null} prev
|
|
652
|
+
* @param {Effect | null} next
|
|
654
653
|
*/
|
|
655
654
|
function link(state, prev, next) {
|
|
656
655
|
if (prev === null) {
|
|
657
|
-
state.first = next;
|
|
658
|
-
state.effect.first = next && next.e;
|
|
656
|
+
state.effect.first = next;
|
|
659
657
|
} else {
|
|
660
|
-
if (prev.e.next) {
|
|
661
|
-
prev.e.next.prev = null;
|
|
662
|
-
}
|
|
663
|
-
|
|
664
658
|
prev.next = next;
|
|
665
|
-
prev.e.next = next && next.e;
|
|
666
659
|
}
|
|
667
660
|
|
|
668
|
-
if (next
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
}
|
|
672
|
-
|
|
661
|
+
if (next === null) {
|
|
662
|
+
state.effect.last = prev;
|
|
663
|
+
} else {
|
|
673
664
|
next.prev = prev;
|
|
674
|
-
next.e.prev = prev && prev.e;
|
|
675
665
|
}
|
|
676
666
|
}
|