svelte 5.43.7 → 5.43.9
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 +1 -1
- package/src/compiler/phases/1-parse/utils/create.js +1 -2
- package/src/compiler/phases/2-analyze/index.js +269 -187
- package/src/compiler/phases/2-analyze/visitors/AwaitExpression.js +0 -4
- package/src/compiler/phases/3-transform/client/visitors/AwaitBlock.js +29 -15
- package/src/compiler/phases/3-transform/client/visitors/ConstTag.js +50 -14
- package/src/compiler/phases/3-transform/client/visitors/Fragment.js +5 -14
- package/src/compiler/phases/3-transform/client/visitors/SnippetBlock.js +2 -8
- package/src/compiler/phases/3-transform/client/visitors/SvelteBoundary.js +12 -2
- package/src/compiler/phases/3-transform/client/visitors/shared/fragment.js +1 -1
- package/src/compiler/phases/3-transform/server/visitors/ConstTag.js +25 -1
- package/src/compiler/phases/3-transform/server/visitors/EachBlock.js +2 -6
- package/src/compiler/phases/3-transform/server/visitors/Fragment.js +8 -1
- package/src/compiler/phases/3-transform/server/visitors/IfBlock.js +1 -5
- package/src/compiler/phases/3-transform/server/visitors/SnippetBlock.js +0 -5
- package/src/compiler/phases/3-transform/server/visitors/SvelteBoundary.js +3 -10
- package/src/compiler/phases/3-transform/server/visitors/shared/component.js +1 -6
- package/src/compiler/phases/nodes.js +4 -0
- package/src/compiler/phases/scope.js +8 -4
- package/src/compiler/utils/builders.js +1 -1
- package/src/internal/client/dom/blocks/each.js +156 -236
- package/src/internal/client/reactivity/deriveds.js +5 -2
- package/src/internal/client/reactivity/effects.js +33 -37
- package/src/internal/client/reactivity/sources.js +17 -9
- package/src/version.js +1 -1
|
@@ -38,7 +38,7 @@ import { source, mutable_source, internal_set } from '../../reactivity/sources.j
|
|
|
38
38
|
import { array_from, is_array } from '../../../shared/utils.js';
|
|
39
39
|
import { COMMENT_NODE, INERT } from '#client/constants';
|
|
40
40
|
import { queue_micro_task } from '../task.js';
|
|
41
|
-
import {
|
|
41
|
+
import { get } from '../../runtime.js';
|
|
42
42
|
import { DEV } from 'esm-env';
|
|
43
43
|
import { derived_safe_equal } from '../../reactivity/deriveds.js';
|
|
44
44
|
import { current_batch } from '../../reactivity/batch.js';
|
|
@@ -67,41 +67,51 @@ export function index(_, i) {
|
|
|
67
67
|
* Pause multiple effects simultaneously, and coordinate their
|
|
68
68
|
* subsequent destruction. Used in each blocks
|
|
69
69
|
* @param {EachState} state
|
|
70
|
-
* @param {EachItem[]}
|
|
70
|
+
* @param {EachItem[]} to_destroy
|
|
71
71
|
* @param {null | Node} controlled_anchor
|
|
72
72
|
*/
|
|
73
|
-
function pause_effects(state,
|
|
74
|
-
var items_map = state.items;
|
|
75
|
-
|
|
73
|
+
function pause_effects(state, to_destroy, controlled_anchor) {
|
|
76
74
|
/** @type {TransitionManager[]} */
|
|
77
75
|
var transitions = [];
|
|
78
|
-
var length =
|
|
76
|
+
var length = to_destroy.length;
|
|
79
77
|
|
|
80
78
|
for (var i = 0; i < length; i++) {
|
|
81
|
-
pause_children(
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
var is_controlled = length > 0 && transitions.length === 0 && controlled_anchor !== null;
|
|
85
|
-
// If we have a controlled anchor, it means that the each block is inside a single
|
|
86
|
-
// DOM element, so we can apply a fast-path for clearing the contents of the element.
|
|
87
|
-
if (is_controlled) {
|
|
88
|
-
var parent_node = /** @type {Element} */ (
|
|
89
|
-
/** @type {Element} */ (controlled_anchor).parentNode
|
|
90
|
-
);
|
|
91
|
-
clear_text_content(parent_node);
|
|
92
|
-
parent_node.append(/** @type {Element} */ (controlled_anchor));
|
|
93
|
-
items_map.clear();
|
|
94
|
-
link(state, items[0].prev, items[length - 1].next);
|
|
79
|
+
pause_children(to_destroy[i].e, transitions, true);
|
|
95
80
|
}
|
|
96
81
|
|
|
97
82
|
run_out_transitions(transitions, () => {
|
|
83
|
+
// If we're in a controlled each block (i.e. the block is the only child of an
|
|
84
|
+
// element), and we are removing all items, _and_ there are no out transitions,
|
|
85
|
+
// we can use the fast path — emptying the element and replacing the anchor
|
|
86
|
+
var fast_path = transitions.length === 0 && controlled_anchor !== null;
|
|
87
|
+
|
|
88
|
+
// TODO only destroy effects if no pending batch needs them. otherwise,
|
|
89
|
+
// just set `item.o` back to `false`
|
|
90
|
+
|
|
91
|
+
if (fast_path) {
|
|
92
|
+
var anchor = /** @type {Element} */ (controlled_anchor);
|
|
93
|
+
var parent_node = /** @type {Element} */ (anchor.parentNode);
|
|
94
|
+
|
|
95
|
+
clear_text_content(parent_node);
|
|
96
|
+
parent_node.append(anchor);
|
|
97
|
+
|
|
98
|
+
state.items.clear();
|
|
99
|
+
link(state, to_destroy[0].prev, to_destroy[length - 1].next);
|
|
100
|
+
}
|
|
101
|
+
|
|
98
102
|
for (var i = 0; i < length; i++) {
|
|
99
|
-
var item =
|
|
100
|
-
|
|
101
|
-
|
|
103
|
+
var item = to_destroy[i];
|
|
104
|
+
|
|
105
|
+
if (!fast_path) {
|
|
106
|
+
state.items.delete(item.k);
|
|
102
107
|
link(state, item.prev, item.next);
|
|
103
108
|
}
|
|
104
|
-
|
|
109
|
+
|
|
110
|
+
destroy_effect(item.e, !fast_path);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
if (state.first === to_destroy[0]) {
|
|
114
|
+
state.first = to_destroy[0].prev;
|
|
105
115
|
}
|
|
106
116
|
});
|
|
107
117
|
}
|
|
@@ -123,6 +133,8 @@ export function each(node, flags, get_collection, get_key, render_fn, fallback_f
|
|
|
123
133
|
var state = { flags, items: new Map(), first: null };
|
|
124
134
|
|
|
125
135
|
var is_controlled = (flags & EACH_IS_CONTROLLED) !== 0;
|
|
136
|
+
var is_reactive_value = (flags & EACH_ITEM_REACTIVE) !== 0;
|
|
137
|
+
var is_reactive_index = (flags & EACH_INDEX_REACTIVE) !== 0;
|
|
126
138
|
|
|
127
139
|
if (is_controlled) {
|
|
128
140
|
var parent_node = /** @type {Element} */ (node);
|
|
@@ -136,14 +148,9 @@ export function each(node, flags, get_collection, get_key, render_fn, fallback_f
|
|
|
136
148
|
hydrate_next();
|
|
137
149
|
}
|
|
138
150
|
|
|
139
|
-
/** @type {Effect | null} */
|
|
151
|
+
/** @type {{ fragment: DocumentFragment | null, effect: Effect } | null} */
|
|
140
152
|
var fallback = null;
|
|
141
153
|
|
|
142
|
-
var was_empty = false;
|
|
143
|
-
|
|
144
|
-
/** @type {Map<any, EachItem>} */
|
|
145
|
-
var offscreen_items = new Map();
|
|
146
|
-
|
|
147
154
|
// TODO: ideally we could use derived for runes mode but because of the ability
|
|
148
155
|
// to use a store which can be mutated, we can't do that here as mutating a store
|
|
149
156
|
// will still result in the collection array being the same from the store
|
|
@@ -156,51 +163,36 @@ export function each(node, flags, get_collection, get_key, render_fn, fallback_f
|
|
|
156
163
|
/** @type {V[]} */
|
|
157
164
|
var array;
|
|
158
165
|
|
|
159
|
-
|
|
160
|
-
var each_effect;
|
|
166
|
+
var first_run = true;
|
|
161
167
|
|
|
162
168
|
function commit() {
|
|
163
|
-
reconcile(
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
state,
|
|
167
|
-
offscreen_items,
|
|
168
|
-
anchor,
|
|
169
|
-
render_fn,
|
|
170
|
-
flags,
|
|
171
|
-
get_key,
|
|
172
|
-
get_collection
|
|
173
|
-
);
|
|
174
|
-
|
|
175
|
-
if (fallback_fn !== null) {
|
|
169
|
+
reconcile(each_effect, array, state, anchor, flags, get_key);
|
|
170
|
+
|
|
171
|
+
if (fallback !== null) {
|
|
176
172
|
if (array.length === 0) {
|
|
177
|
-
if (fallback) {
|
|
178
|
-
|
|
173
|
+
if (fallback.fragment) {
|
|
174
|
+
anchor.before(fallback.fragment);
|
|
175
|
+
fallback.fragment = null;
|
|
179
176
|
} else {
|
|
180
|
-
fallback
|
|
177
|
+
resume_effect(fallback.effect);
|
|
181
178
|
}
|
|
182
|
-
|
|
183
|
-
|
|
179
|
+
|
|
180
|
+
each_effect.first = fallback.effect;
|
|
181
|
+
} else {
|
|
182
|
+
pause_effect(fallback.effect, () => {
|
|
183
|
+
// TODO only null out if no pending batch needs it,
|
|
184
|
+
// otherwise re-add `fallback.fragment` and move the
|
|
185
|
+
// effect into it
|
|
184
186
|
fallback = null;
|
|
185
187
|
});
|
|
186
188
|
}
|
|
187
189
|
}
|
|
188
190
|
}
|
|
189
191
|
|
|
190
|
-
block(() => {
|
|
191
|
-
// store a reference to the effect so that we can update the start/end nodes in reconciliation
|
|
192
|
-
each_effect ??= /** @type {Effect} */ (active_effect);
|
|
193
|
-
|
|
192
|
+
var each_effect = block(() => {
|
|
194
193
|
array = /** @type {V[]} */ (get(each_array));
|
|
195
194
|
var length = array.length;
|
|
196
195
|
|
|
197
|
-
if (was_empty && length === 0) {
|
|
198
|
-
// ignore updates if the array is empty,
|
|
199
|
-
// and it already was empty on previous run
|
|
200
|
-
return;
|
|
201
|
-
}
|
|
202
|
-
was_empty = length === 0;
|
|
203
|
-
|
|
204
196
|
/** `true` if there was a hydration mismatch. Needs to be a `let` or else it isn't treeshaken out */
|
|
205
197
|
let mismatch = false;
|
|
206
198
|
|
|
@@ -217,34 +209,48 @@ export function each(node, flags, get_collection, get_key, render_fn, fallback_f
|
|
|
217
209
|
}
|
|
218
210
|
}
|
|
219
211
|
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
212
|
+
var keys = new Set();
|
|
213
|
+
var batch = /** @type {Batch} */ (current_batch);
|
|
214
|
+
var prev = null;
|
|
215
|
+
var defer = should_defer_append();
|
|
216
|
+
|
|
217
|
+
for (var i = 0; i < length; i += 1) {
|
|
218
|
+
if (
|
|
219
|
+
hydrating &&
|
|
220
|
+
hydrate_node.nodeType === COMMENT_NODE &&
|
|
221
|
+
/** @type {Comment} */ (hydrate_node).data === HYDRATION_END
|
|
222
|
+
) {
|
|
223
|
+
// The server rendered fewer items than expected,
|
|
224
|
+
// so break out and continue appending non-hydrated items
|
|
225
|
+
anchor = /** @type {Comment} */ (hydrate_node);
|
|
226
|
+
mismatch = true;
|
|
227
|
+
set_hydrating(false);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
var value = array[i];
|
|
231
|
+
var key = get_key(value, i);
|
|
232
|
+
|
|
233
|
+
var item = first_run ? null : state.items.get(key);
|
|
234
|
+
|
|
235
|
+
if (item) {
|
|
236
|
+
// update before reconciliation, to trigger any async updates
|
|
237
|
+
if (is_reactive_value) {
|
|
238
|
+
internal_set(item.v, value);
|
|
239
239
|
}
|
|
240
240
|
|
|
241
|
-
|
|
242
|
-
|
|
241
|
+
if (is_reactive_index) {
|
|
242
|
+
internal_set(/** @type {Value<number>} */ (item.i), i);
|
|
243
|
+
} else {
|
|
244
|
+
item.i = i;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
if (defer) {
|
|
248
|
+
batch.skipped_effects.delete(item.e);
|
|
249
|
+
}
|
|
250
|
+
} else {
|
|
243
251
|
item = create_item(
|
|
244
|
-
|
|
245
|
-
state,
|
|
252
|
+
first_run ? anchor : null,
|
|
246
253
|
prev,
|
|
247
|
-
null,
|
|
248
254
|
value,
|
|
249
255
|
key,
|
|
250
256
|
i,
|
|
@@ -252,58 +258,50 @@ export function each(node, flags, get_collection, get_key, render_fn, fallback_f
|
|
|
252
258
|
flags,
|
|
253
259
|
get_collection
|
|
254
260
|
);
|
|
255
|
-
state.items.set(key, item);
|
|
256
261
|
|
|
257
|
-
|
|
258
|
-
|
|
262
|
+
if (first_run) {
|
|
263
|
+
item.o = true;
|
|
264
|
+
|
|
265
|
+
if (prev === null) {
|
|
266
|
+
state.first = item;
|
|
267
|
+
} else {
|
|
268
|
+
prev.next = item;
|
|
269
|
+
}
|
|
259
270
|
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
271
|
+
prev = item;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
state.items.set(key, item);
|
|
263
275
|
}
|
|
276
|
+
|
|
277
|
+
keys.add(key);
|
|
264
278
|
}
|
|
265
279
|
|
|
266
|
-
if (
|
|
267
|
-
if (
|
|
268
|
-
fallback =
|
|
280
|
+
if (length === 0 && fallback_fn && !fallback) {
|
|
281
|
+
if (first_run) {
|
|
282
|
+
fallback = {
|
|
283
|
+
fragment: null,
|
|
284
|
+
effect: branch(() => fallback_fn(anchor))
|
|
285
|
+
};
|
|
286
|
+
} else {
|
|
287
|
+
var fragment = document.createDocumentFragment();
|
|
288
|
+
var target = create_text();
|
|
289
|
+
fragment.append(target);
|
|
290
|
+
|
|
291
|
+
fallback = {
|
|
292
|
+
fragment,
|
|
293
|
+
effect: branch(() => fallback_fn(target))
|
|
294
|
+
};
|
|
269
295
|
}
|
|
270
|
-
}
|
|
271
|
-
if (should_defer_append()) {
|
|
272
|
-
var keys = new Set();
|
|
273
|
-
var batch = /** @type {Batch} */ (current_batch);
|
|
274
|
-
|
|
275
|
-
for (i = 0; i < length; i += 1) {
|
|
276
|
-
value = array[i];
|
|
277
|
-
key = get_key(value, i);
|
|
278
|
-
|
|
279
|
-
var existing = state.items.get(key) ?? offscreen_items.get(key);
|
|
280
|
-
|
|
281
|
-
if (existing) {
|
|
282
|
-
// update before reconciliation, to trigger any async updates
|
|
283
|
-
if ((flags & (EACH_ITEM_REACTIVE | EACH_INDEX_REACTIVE)) !== 0) {
|
|
284
|
-
update_item(existing, value, i, flags);
|
|
285
|
-
}
|
|
286
|
-
} else {
|
|
287
|
-
item = create_item(
|
|
288
|
-
null,
|
|
289
|
-
state,
|
|
290
|
-
null,
|
|
291
|
-
null,
|
|
292
|
-
value,
|
|
293
|
-
key,
|
|
294
|
-
i,
|
|
295
|
-
render_fn,
|
|
296
|
-
flags,
|
|
297
|
-
get_collection,
|
|
298
|
-
true
|
|
299
|
-
);
|
|
300
|
-
|
|
301
|
-
offscreen_items.set(key, item);
|
|
302
|
-
}
|
|
296
|
+
}
|
|
303
297
|
|
|
304
|
-
|
|
305
|
-
|
|
298
|
+
// remove excess nodes
|
|
299
|
+
if (hydrating && length > 0) {
|
|
300
|
+
set_hydrate_node(skip_nodes());
|
|
301
|
+
}
|
|
306
302
|
|
|
303
|
+
if (!first_run) {
|
|
304
|
+
if (defer) {
|
|
307
305
|
for (const [key, item] of state.items) {
|
|
308
306
|
if (!keys.has(key)) {
|
|
309
307
|
batch.skipped_effects.add(item.e);
|
|
@@ -311,6 +309,9 @@ export function each(node, flags, get_collection, get_key, render_fn, fallback_f
|
|
|
311
309
|
}
|
|
312
310
|
|
|
313
311
|
batch.oncommit(commit);
|
|
312
|
+
batch.ondiscard(() => {
|
|
313
|
+
// TODO presumably we need to do something here?
|
|
314
|
+
});
|
|
314
315
|
} else {
|
|
315
316
|
commit();
|
|
316
317
|
}
|
|
@@ -330,6 +331,8 @@ export function each(node, flags, get_collection, get_key, render_fn, fallback_f
|
|
|
330
331
|
get(each_array);
|
|
331
332
|
});
|
|
332
333
|
|
|
334
|
+
first_run = false;
|
|
335
|
+
|
|
333
336
|
if (hydrating) {
|
|
334
337
|
anchor = hydrate_node;
|
|
335
338
|
}
|
|
@@ -341,32 +344,17 @@ export function each(node, flags, get_collection, get_key, render_fn, fallback_f
|
|
|
341
344
|
* @param {Effect} each_effect
|
|
342
345
|
* @param {Array<V>} array
|
|
343
346
|
* @param {EachState} state
|
|
344
|
-
* @param {Map<any, EachItem>} offscreen_items
|
|
345
347
|
* @param {Element | Comment | Text} anchor
|
|
346
|
-
* @param {(anchor: Node, item: MaybeSource<V>, index: number | Source<number>, collection: () => V[]) => void} render_fn
|
|
347
348
|
* @param {number} flags
|
|
348
349
|
* @param {(value: V, index: number) => any} get_key
|
|
349
|
-
* @param {() => V[]} get_collection
|
|
350
350
|
* @returns {void}
|
|
351
351
|
*/
|
|
352
|
-
function reconcile(
|
|
353
|
-
each_effect,
|
|
354
|
-
array,
|
|
355
|
-
state,
|
|
356
|
-
offscreen_items,
|
|
357
|
-
anchor,
|
|
358
|
-
render_fn,
|
|
359
|
-
flags,
|
|
360
|
-
get_key,
|
|
361
|
-
get_collection
|
|
362
|
-
) {
|
|
352
|
+
function reconcile(each_effect, array, state, anchor, flags, get_key) {
|
|
363
353
|
var is_animated = (flags & EACH_IS_ANIMATED) !== 0;
|
|
364
|
-
var should_update = (flags & (EACH_ITEM_REACTIVE | EACH_INDEX_REACTIVE)) !== 0;
|
|
365
354
|
|
|
366
355
|
var length = array.length;
|
|
367
356
|
var items = state.items;
|
|
368
|
-
var
|
|
369
|
-
var current = first;
|
|
357
|
+
var current = state.first;
|
|
370
358
|
|
|
371
359
|
/** @type {undefined | Set<EachItem>} */
|
|
372
360
|
var seen;
|
|
@@ -399,12 +387,10 @@ function reconcile(
|
|
|
399
387
|
for (i = 0; i < length; i += 1) {
|
|
400
388
|
value = array[i];
|
|
401
389
|
key = get_key(value, i);
|
|
402
|
-
item = items.get(key);
|
|
390
|
+
item = /** @type {EachItem} */ (items.get(key));
|
|
403
391
|
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
(to_animate ??= new Set()).add(item);
|
|
407
|
-
}
|
|
392
|
+
item.a?.measure();
|
|
393
|
+
(to_animate ??= new Set()).add(item);
|
|
408
394
|
}
|
|
409
395
|
}
|
|
410
396
|
|
|
@@ -412,40 +398,20 @@ function reconcile(
|
|
|
412
398
|
value = array[i];
|
|
413
399
|
key = get_key(value, i);
|
|
414
400
|
|
|
415
|
-
item = items.get(key);
|
|
401
|
+
item = /** @type {EachItem} */ (items.get(key));
|
|
416
402
|
|
|
417
|
-
|
|
418
|
-
var pending = offscreen_items.get(key);
|
|
403
|
+
state.first ??= item;
|
|
419
404
|
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
items.set(key, pending);
|
|
405
|
+
if (!item.o) {
|
|
406
|
+
item.o = true;
|
|
423
407
|
|
|
424
|
-
|
|
408
|
+
var next = prev ? prev.next : current;
|
|
425
409
|
|
|
426
|
-
|
|
427
|
-
|
|
410
|
+
link(state, prev, item);
|
|
411
|
+
link(state, item, next);
|
|
428
412
|
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
} else {
|
|
432
|
-
var child_anchor = current ? /** @type {TemplateNode} */ (current.e.nodes_start) : anchor;
|
|
433
|
-
|
|
434
|
-
prev = create_item(
|
|
435
|
-
child_anchor,
|
|
436
|
-
state,
|
|
437
|
-
prev,
|
|
438
|
-
prev === null ? state.first : prev.next,
|
|
439
|
-
value,
|
|
440
|
-
key,
|
|
441
|
-
i,
|
|
442
|
-
render_fn,
|
|
443
|
-
flags,
|
|
444
|
-
get_collection
|
|
445
|
-
);
|
|
446
|
-
}
|
|
447
|
-
|
|
448
|
-
items.set(key, prev);
|
|
413
|
+
move(item, next, anchor);
|
|
414
|
+
prev = item;
|
|
449
415
|
|
|
450
416
|
matched = [];
|
|
451
417
|
stashed = [];
|
|
@@ -454,10 +420,6 @@ function reconcile(
|
|
|
454
420
|
continue;
|
|
455
421
|
}
|
|
456
422
|
|
|
457
|
-
if (should_update) {
|
|
458
|
-
update_item(item, value, i, flags);
|
|
459
|
-
}
|
|
460
|
-
|
|
461
423
|
if ((item.e.f & INERT) !== 0) {
|
|
462
424
|
resume_effect(item.e);
|
|
463
425
|
if (is_animated) {
|
|
@@ -575,63 +537,30 @@ function reconcile(
|
|
|
575
537
|
});
|
|
576
538
|
}
|
|
577
539
|
|
|
540
|
+
// TODO i have an inkling that the rest of this function is wrong...
|
|
541
|
+
// the offscreen items need to be linked, so that they all update correctly.
|
|
542
|
+
// the last onscreen item should link to the first offscreen item, etc
|
|
578
543
|
each_effect.first = state.first && state.first.e;
|
|
579
544
|
each_effect.last = prev && prev.e;
|
|
580
545
|
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
}
|
|
584
|
-
|
|
585
|
-
offscreen_items.clear();
|
|
586
|
-
}
|
|
587
|
-
|
|
588
|
-
/**
|
|
589
|
-
* @param {EachItem} item
|
|
590
|
-
* @param {any} value
|
|
591
|
-
* @param {number} index
|
|
592
|
-
* @param {number} type
|
|
593
|
-
* @returns {void}
|
|
594
|
-
*/
|
|
595
|
-
function update_item(item, value, index, type) {
|
|
596
|
-
if ((type & EACH_ITEM_REACTIVE) !== 0) {
|
|
597
|
-
internal_set(item.v, value);
|
|
598
|
-
}
|
|
599
|
-
|
|
600
|
-
if ((type & EACH_INDEX_REACTIVE) !== 0) {
|
|
601
|
-
internal_set(/** @type {Value<number>} */ (item.i), index);
|
|
602
|
-
} else {
|
|
603
|
-
item.i = index;
|
|
546
|
+
if (prev) {
|
|
547
|
+
prev.e.next = null;
|
|
604
548
|
}
|
|
605
549
|
}
|
|
606
550
|
|
|
607
551
|
/**
|
|
608
552
|
* @template V
|
|
609
553
|
* @param {Node | null} anchor
|
|
610
|
-
* @param {EachState} state
|
|
611
554
|
* @param {EachItem | null} prev
|
|
612
|
-
* @param {EachItem | null} next
|
|
613
555
|
* @param {V} value
|
|
614
556
|
* @param {unknown} key
|
|
615
557
|
* @param {number} index
|
|
616
558
|
* @param {(anchor: Node, item: V | Source<V>, index: number | Value<number>, collection: () => V[]) => void} render_fn
|
|
617
559
|
* @param {number} flags
|
|
618
560
|
* @param {() => V[]} get_collection
|
|
619
|
-
* @param {boolean} [deferred]
|
|
620
561
|
* @returns {EachItem}
|
|
621
562
|
*/
|
|
622
|
-
function create_item(
|
|
623
|
-
anchor,
|
|
624
|
-
state,
|
|
625
|
-
prev,
|
|
626
|
-
next,
|
|
627
|
-
value,
|
|
628
|
-
key,
|
|
629
|
-
index,
|
|
630
|
-
render_fn,
|
|
631
|
-
flags,
|
|
632
|
-
get_collection,
|
|
633
|
-
deferred
|
|
634
|
-
) {
|
|
563
|
+
function create_item(anchor, prev, value, key, index, render_fn, flags, get_collection) {
|
|
635
564
|
var previous_each_item = current_each_item;
|
|
636
565
|
var reactive = (flags & EACH_ITEM_REACTIVE) !== 0;
|
|
637
566
|
var mutable = (flags & EACH_ITEM_IMMUTABLE) === 0;
|
|
@@ -657,8 +586,9 @@ function create_item(
|
|
|
657
586
|
a: null,
|
|
658
587
|
// @ts-expect-error
|
|
659
588
|
e: null,
|
|
589
|
+
o: false,
|
|
660
590
|
prev,
|
|
661
|
-
next
|
|
591
|
+
next: null
|
|
662
592
|
};
|
|
663
593
|
|
|
664
594
|
current_each_item = item;
|
|
@@ -669,25 +599,15 @@ function create_item(
|
|
|
669
599
|
fragment.append((anchor = create_text()));
|
|
670
600
|
}
|
|
671
601
|
|
|
672
|
-
item.e = branch(() => render_fn(/** @type {Node} */ (anchor), v, i, get_collection)
|
|
602
|
+
item.e = branch(() => render_fn(/** @type {Node} */ (anchor), v, i, get_collection));
|
|
673
603
|
|
|
674
604
|
item.e.prev = prev && prev.e;
|
|
675
|
-
item.e.next = next && next.e;
|
|
676
605
|
|
|
677
|
-
if (prev
|
|
678
|
-
if (!deferred) {
|
|
679
|
-
state.first = item;
|
|
680
|
-
}
|
|
681
|
-
} else {
|
|
606
|
+
if (prev !== null) {
|
|
682
607
|
prev.next = item;
|
|
683
608
|
prev.e.next = item.e;
|
|
684
609
|
}
|
|
685
610
|
|
|
686
|
-
if (next !== null) {
|
|
687
|
-
next.prev = item;
|
|
688
|
-
next.e.prev = item.e;
|
|
689
|
-
}
|
|
690
|
-
|
|
691
611
|
return item;
|
|
692
612
|
} finally {
|
|
693
613
|
current_each_item = previous_each_item;
|
|
@@ -11,7 +11,8 @@ import {
|
|
|
11
11
|
STALE_REACTION,
|
|
12
12
|
ASYNC,
|
|
13
13
|
WAS_MARKED,
|
|
14
|
-
CONNECTED
|
|
14
|
+
CONNECTED,
|
|
15
|
+
DESTROYED
|
|
15
16
|
} from '#client/constants';
|
|
16
17
|
import {
|
|
17
18
|
active_reaction,
|
|
@@ -296,7 +297,9 @@ function get_derived_parent_effect(derived) {
|
|
|
296
297
|
var parent = derived.parent;
|
|
297
298
|
while (parent !== null) {
|
|
298
299
|
if ((parent.f & DERIVED) === 0) {
|
|
299
|
-
|
|
300
|
+
// The original parent effect might've been destroyed but the derived
|
|
301
|
+
// is used elsewhere now - do not return the destroyed effect in that case
|
|
302
|
+
return (parent.f & DESTROYED) === 0 ? /** @type {Effect} */ (parent) : null;
|
|
300
303
|
}
|
|
301
304
|
parent = parent.parent;
|
|
302
305
|
}
|
|
@@ -80,10 +80,9 @@ function push_effect(effect, parent_effect) {
|
|
|
80
80
|
* @param {number} type
|
|
81
81
|
* @param {null | (() => void | (() => void))} fn
|
|
82
82
|
* @param {boolean} sync
|
|
83
|
-
* @param {boolean} push
|
|
84
83
|
* @returns {Effect}
|
|
85
84
|
*/
|
|
86
|
-
function create_effect(type, fn, sync
|
|
85
|
+
function create_effect(type, fn, sync) {
|
|
87
86
|
var parent = active_effect;
|
|
88
87
|
|
|
89
88
|
if (DEV) {
|
|
@@ -133,43 +132,41 @@ function create_effect(type, fn, sync, push = true) {
|
|
|
133
132
|
schedule_effect(effect);
|
|
134
133
|
}
|
|
135
134
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
var e = effect;
|
|
135
|
+
/** @type {Effect | null} */
|
|
136
|
+
var e = effect;
|
|
139
137
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
}
|
|
138
|
+
// if an effect has already ran and doesn't need to be kept in the tree
|
|
139
|
+
// (because it won't re-run, has no DOM, and has no teardown etc)
|
|
140
|
+
// then we skip it and go to its child (if any)
|
|
141
|
+
if (
|
|
142
|
+
sync &&
|
|
143
|
+
e.deps === null &&
|
|
144
|
+
e.teardown === null &&
|
|
145
|
+
e.nodes_start === null &&
|
|
146
|
+
e.first === e.last && // either `null`, or a singular child
|
|
147
|
+
(e.f & EFFECT_PRESERVED) === 0
|
|
148
|
+
) {
|
|
149
|
+
e = e.first;
|
|
150
|
+
if ((type & BLOCK_EFFECT) !== 0 && (type & EFFECT_TRANSPARENT) !== 0 && e !== null) {
|
|
151
|
+
e.f |= EFFECT_TRANSPARENT;
|
|
155
152
|
}
|
|
153
|
+
}
|
|
156
154
|
|
|
157
|
-
|
|
158
|
-
|
|
155
|
+
if (e !== null) {
|
|
156
|
+
e.parent = parent;
|
|
159
157
|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
158
|
+
if (parent !== null) {
|
|
159
|
+
push_effect(e, parent);
|
|
160
|
+
}
|
|
163
161
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
}
|
|
162
|
+
// if we're in a derived, add the effect there too
|
|
163
|
+
if (
|
|
164
|
+
active_reaction !== null &&
|
|
165
|
+
(active_reaction.f & DERIVED) !== 0 &&
|
|
166
|
+
(type & ROOT_EFFECT) === 0
|
|
167
|
+
) {
|
|
168
|
+
var derived = /** @type {Derived} */ (active_reaction);
|
|
169
|
+
(derived.effects ??= []).push(e);
|
|
173
170
|
}
|
|
174
171
|
}
|
|
175
172
|
|
|
@@ -406,10 +403,9 @@ export function block(fn, flags = 0) {
|
|
|
406
403
|
|
|
407
404
|
/**
|
|
408
405
|
* @param {(() => void)} fn
|
|
409
|
-
* @param {boolean} [push]
|
|
410
406
|
*/
|
|
411
|
-
export function branch(fn
|
|
412
|
-
return create_effect(BRANCH_EFFECT | EFFECT_PRESERVED, fn, true
|
|
407
|
+
export function branch(fn) {
|
|
408
|
+
return create_effect(BRANCH_EFFECT | EFFECT_PRESERVED, fn, true);
|
|
413
409
|
}
|
|
414
410
|
|
|
415
411
|
/**
|