svelte 5.45.2 → 5.45.4
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/1-parse/index.js +32 -16
- package/src/compiler/phases/1-parse/read/context.js +3 -12
- package/src/compiler/phases/1-parse/state/element.js +79 -55
- package/src/compiler/phases/1-parse/state/tag.js +5 -16
- package/src/compiler/phases/2-analyze/index.js +7 -2
- package/src/compiler/phases/2-analyze/visitors/Identifier.js +2 -1
- package/src/compiler/phases/2-analyze/visitors/RegularElement.js +3 -2
- package/src/compiler/phases/3-transform/client/transform-template/index.js +1 -2
- package/src/compiler/phases/3-transform/client/visitors/BindDirective.js +27 -11
- package/src/compiler/phases/3-transform/client/visitors/CallExpression.js +2 -1
- package/src/compiler/phases/3-transform/client/visitors/Component.js +1 -2
- package/src/compiler/phases/3-transform/client/visitors/Fragment.js +1 -1
- package/src/compiler/phases/3-transform/client/visitors/RegularElement.js +1 -0
- package/src/compiler/phases/3-transform/client/visitors/SvelteComponent.js +2 -1
- package/src/compiler/phases/3-transform/client/visitors/SvelteHead.js +1 -1
- package/src/compiler/phases/3-transform/client/visitors/SvelteSelf.js +2 -1
- package/src/compiler/phases/3-transform/client/visitors/TitleElement.js +1 -1
- package/src/compiler/phases/3-transform/client/visitors/VariableDeclaration.js +2 -1
- package/src/compiler/phases/3-transform/client/visitors/shared/component.js +27 -25
- package/src/compiler/phases/3-transform/client/visitors/shared/events.js +8 -2
- package/src/compiler/phases/3-transform/client/visitors/shared/fragment.js +10 -4
- package/src/compiler/phases/3-transform/client/visitors/shared/utils.js +2 -2
- package/src/compiler/phases/3-transform/server/visitors/RegularElement.js +1 -1
- package/src/compiler/phases/3-transform/server/visitors/SvelteElement.js +1 -1
- package/src/compiler/phases/3-transform/server/visitors/shared/element.js +2 -2
- package/src/compiler/phases/nodes.js +4 -2
- package/src/compiler/state.js +12 -4
- package/src/compiler/utils/builders.js +6 -2
- package/src/internal/client/dev/debug.js +365 -7
- package/src/internal/client/dom/blocks/each.js +24 -44
- package/src/internal/client/dom/blocks/html.js +3 -3
- package/src/internal/client/dom/blocks/svelte-element.js +8 -11
- package/src/internal/client/dom/elements/transitions.js +15 -7
- package/src/internal/client/dom/template.js +12 -10
- package/src/internal/client/reactivity/async.js +1 -6
- package/src/internal/client/reactivity/batch.js +4 -1
- package/src/internal/client/reactivity/effects.js +20 -16
- package/src/internal/client/reactivity/sources.js +2 -0
- package/src/internal/client/render.js +2 -2
- package/src/internal/client/runtime.js +1 -1
- package/src/internal/server/hydratable.js +11 -1
- package/src/version.js +1 -1
- package/types/index.d.ts +18 -11
- package/types/index.d.ts.map +1 -1
|
@@ -5,12 +5,18 @@ import {
|
|
|
5
5
|
BOUNDARY_EFFECT,
|
|
6
6
|
BRANCH_EFFECT,
|
|
7
7
|
CLEAN,
|
|
8
|
+
CONNECTED,
|
|
8
9
|
DERIVED,
|
|
10
|
+
DIRTY,
|
|
9
11
|
EFFECT,
|
|
10
12
|
ASYNC,
|
|
13
|
+
DESTROYED,
|
|
14
|
+
INERT,
|
|
11
15
|
MAYBE_DIRTY,
|
|
12
16
|
RENDER_EFFECT,
|
|
13
|
-
ROOT_EFFECT
|
|
17
|
+
ROOT_EFFECT,
|
|
18
|
+
WAS_MARKED,
|
|
19
|
+
MANAGED_EFFECT
|
|
14
20
|
} from '#client/constants';
|
|
15
21
|
import { snapshot } from '../../shared/clone.js';
|
|
16
22
|
import { untrack } from '../runtime.js';
|
|
@@ -30,11 +36,13 @@ export function root(effect) {
|
|
|
30
36
|
/**
|
|
31
37
|
*
|
|
32
38
|
* @param {Effect} effect
|
|
39
|
+
* @param {boolean} append_effect
|
|
40
|
+
* @returns {string}
|
|
33
41
|
*/
|
|
34
|
-
|
|
42
|
+
function effect_label(effect, append_effect = false) {
|
|
35
43
|
const flags = effect.f;
|
|
36
44
|
|
|
37
|
-
let label =
|
|
45
|
+
let label = `(unknown ${append_effect ? 'effect' : ''})`;
|
|
38
46
|
|
|
39
47
|
if ((flags & ROOT_EFFECT) !== 0) {
|
|
40
48
|
label = 'root';
|
|
@@ -42,6 +50,8 @@ export function log_effect_tree(effect, depth = 0) {
|
|
|
42
50
|
label = 'boundary';
|
|
43
51
|
} else if ((flags & BLOCK_EFFECT) !== 0) {
|
|
44
52
|
label = 'block';
|
|
53
|
+
} else if ((flags & MANAGED_EFFECT) !== 0) {
|
|
54
|
+
label = 'managed';
|
|
45
55
|
} else if ((flags & ASYNC) !== 0) {
|
|
46
56
|
label = 'async';
|
|
47
57
|
} else if ((flags & BRANCH_EFFECT) !== 0) {
|
|
@@ -52,6 +62,20 @@ export function log_effect_tree(effect, depth = 0) {
|
|
|
52
62
|
label = 'effect';
|
|
53
63
|
}
|
|
54
64
|
|
|
65
|
+
if (append_effect && !label.endsWith('effect')) {
|
|
66
|
+
label += ' effect';
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return label;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
*
|
|
73
|
+
* @param {Effect} effect
|
|
74
|
+
*/
|
|
75
|
+
export function log_effect_tree(effect, depth = 0) {
|
|
76
|
+
const flags = effect.f;
|
|
77
|
+
const label = effect_label(effect);
|
|
78
|
+
|
|
55
79
|
let status =
|
|
56
80
|
(flags & CLEAN) !== 0 ? 'clean' : (flags & MAYBE_DIRTY) !== 0 ? 'maybe dirty' : 'dirty';
|
|
57
81
|
|
|
@@ -86,13 +110,13 @@ export function log_effect_tree(effect, depth = 0) {
|
|
|
86
110
|
console.groupEnd();
|
|
87
111
|
}
|
|
88
112
|
|
|
89
|
-
if (effect.
|
|
113
|
+
if (effect.nodes) {
|
|
90
114
|
// eslint-disable-next-line no-console
|
|
91
|
-
console.log(effect.
|
|
115
|
+
console.log(effect.nodes.start);
|
|
92
116
|
|
|
93
|
-
if (effect.
|
|
117
|
+
if (effect.nodes.start !== effect.nodes.end) {
|
|
94
118
|
// eslint-disable-next-line no-console
|
|
95
|
-
console.log(effect.
|
|
119
|
+
console.log(effect.nodes.end);
|
|
96
120
|
}
|
|
97
121
|
}
|
|
98
122
|
|
|
@@ -140,3 +164,337 @@ function log_dep(dep) {
|
|
|
140
164
|
);
|
|
141
165
|
}
|
|
142
166
|
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Logs all reactions of a source or derived transitively
|
|
170
|
+
* @param {Derived | Value} signal
|
|
171
|
+
*/
|
|
172
|
+
export function log_reactions(signal) {
|
|
173
|
+
/** @type {Set<Derived | Value>} */
|
|
174
|
+
const visited = new Set();
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Returns an array of flag names that are set on the given flags bitmask
|
|
178
|
+
* @param {number} flags
|
|
179
|
+
* @returns {string[]}
|
|
180
|
+
*/
|
|
181
|
+
function get_derived_flag_names(flags) {
|
|
182
|
+
/** @type {string[]} */
|
|
183
|
+
const names = [];
|
|
184
|
+
|
|
185
|
+
if ((flags & CLEAN) !== 0) names.push('CLEAN');
|
|
186
|
+
if ((flags & DIRTY) !== 0) names.push('DIRTY');
|
|
187
|
+
if ((flags & MAYBE_DIRTY) !== 0) names.push('MAYBE_DIRTY');
|
|
188
|
+
if ((flags & CONNECTED) !== 0) names.push('CONNECTED');
|
|
189
|
+
if ((flags & WAS_MARKED) !== 0) names.push('WAS_MARKED');
|
|
190
|
+
if ((flags & INERT) !== 0) names.push('INERT');
|
|
191
|
+
if ((flags & DESTROYED) !== 0) names.push('DESTROYED');
|
|
192
|
+
|
|
193
|
+
return names;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* @param {Derived | Value} d
|
|
198
|
+
* @param {number} depth
|
|
199
|
+
*/
|
|
200
|
+
function log_derived(d, depth) {
|
|
201
|
+
const flags = d.f;
|
|
202
|
+
const flag_names = get_derived_flag_names(flags);
|
|
203
|
+
const flags_str = flag_names.length > 0 ? `(${flag_names.join(', ')})` : '(no flags)';
|
|
204
|
+
|
|
205
|
+
// eslint-disable-next-line no-console
|
|
206
|
+
console.group(
|
|
207
|
+
`%c${flags & DERIVED ? '$derived' : '$state'} %c${d.label ?? '<unknown>'} %c${flags_str}`,
|
|
208
|
+
'font-weight: bold; color: CornflowerBlue',
|
|
209
|
+
'font-weight: normal; color: inherit',
|
|
210
|
+
'font-weight: normal; color: gray'
|
|
211
|
+
);
|
|
212
|
+
|
|
213
|
+
// eslint-disable-next-line no-console
|
|
214
|
+
console.log(untrack(() => snapshot(d.v)));
|
|
215
|
+
|
|
216
|
+
if ('fn' in d) {
|
|
217
|
+
// eslint-disable-next-line no-console
|
|
218
|
+
console.log('%cfn:', 'font-weight: bold', d.fn);
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
if (d.reactions !== null && d.reactions.length > 0) {
|
|
222
|
+
// eslint-disable-next-line no-console
|
|
223
|
+
console.group('%creactions', 'font-weight: bold');
|
|
224
|
+
|
|
225
|
+
for (const reaction of d.reactions) {
|
|
226
|
+
if ((reaction.f & DERIVED) !== 0) {
|
|
227
|
+
const derived_reaction = /** @type {Derived} */ (reaction);
|
|
228
|
+
|
|
229
|
+
if (visited.has(derived_reaction)) {
|
|
230
|
+
// eslint-disable-next-line no-console
|
|
231
|
+
console.log(
|
|
232
|
+
`%c$derived %c${derived_reaction.label ?? '<unknown>'} %c(already seen)`,
|
|
233
|
+
'font-weight: bold; color: CornflowerBlue',
|
|
234
|
+
'font-weight: normal; color: inherit',
|
|
235
|
+
'font-weight: bold; color: orange'
|
|
236
|
+
);
|
|
237
|
+
} else {
|
|
238
|
+
visited.add(derived_reaction);
|
|
239
|
+
log_derived(derived_reaction, depth + 1);
|
|
240
|
+
}
|
|
241
|
+
} else {
|
|
242
|
+
// It's an effect
|
|
243
|
+
const label = effect_label(/** @type {Effect} */ (reaction), true);
|
|
244
|
+
const status = (flags & MAYBE_DIRTY) !== 0 ? 'maybe dirty' : 'dirty';
|
|
245
|
+
|
|
246
|
+
// Collect parent statuses
|
|
247
|
+
/** @type {string[]} */
|
|
248
|
+
const parent_statuses = [];
|
|
249
|
+
let show = false;
|
|
250
|
+
let current = /** @type {Effect} */ (reaction).parent;
|
|
251
|
+
while (current !== null) {
|
|
252
|
+
const parent_flags = current.f;
|
|
253
|
+
if ((parent_flags & (ROOT_EFFECT | BRANCH_EFFECT)) !== 0) {
|
|
254
|
+
const parent_status = (parent_flags & CLEAN) !== 0 ? 'clean' : 'not clean';
|
|
255
|
+
if (parent_status === 'clean' && parent_statuses.includes('not clean')) show = true;
|
|
256
|
+
parent_statuses.push(parent_status);
|
|
257
|
+
}
|
|
258
|
+
if (!current.parent) break;
|
|
259
|
+
current = current.parent;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
// Check if reaction is reachable from root
|
|
263
|
+
const seen_effects = new Set();
|
|
264
|
+
let reachable = false;
|
|
265
|
+
/**
|
|
266
|
+
* @param {Effect | null} effect
|
|
267
|
+
*/
|
|
268
|
+
function check_reachable(effect) {
|
|
269
|
+
if (effect === null || reachable) return;
|
|
270
|
+
if (effect === reaction) {
|
|
271
|
+
reachable = true;
|
|
272
|
+
return;
|
|
273
|
+
}
|
|
274
|
+
if (effect.f & DESTROYED) return;
|
|
275
|
+
if (seen_effects.has(effect)) {
|
|
276
|
+
throw new Error('');
|
|
277
|
+
}
|
|
278
|
+
seen_effects.add(effect);
|
|
279
|
+
let child = effect.first;
|
|
280
|
+
while (child !== null) {
|
|
281
|
+
check_reachable(child);
|
|
282
|
+
child = child.next;
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
try {
|
|
286
|
+
if (current) check_reachable(current);
|
|
287
|
+
} catch (e) {
|
|
288
|
+
// eslint-disable-next-line no-console
|
|
289
|
+
console.log(
|
|
290
|
+
`%c⚠️ Circular reference detected in effect tree`,
|
|
291
|
+
'font-weight: bold; color: red',
|
|
292
|
+
seen_effects
|
|
293
|
+
);
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
if (!reachable) {
|
|
297
|
+
// eslint-disable-next-line no-console
|
|
298
|
+
console.log(
|
|
299
|
+
`%c⚠️ Effect is NOT reachable from its parent chain`,
|
|
300
|
+
'font-weight: bold; color: red'
|
|
301
|
+
);
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
const parent_status_str = show ? ` (${parent_statuses.join(', ')})` : '';
|
|
305
|
+
|
|
306
|
+
// eslint-disable-next-line no-console
|
|
307
|
+
console.log(
|
|
308
|
+
`%c${label} (${status})${parent_status_str}`,
|
|
309
|
+
`font-weight: bold; color: ${parent_status_str ? 'red' : 'green'}`,
|
|
310
|
+
reaction
|
|
311
|
+
);
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
// eslint-disable-next-line no-console
|
|
316
|
+
console.groupEnd();
|
|
317
|
+
} else {
|
|
318
|
+
// eslint-disable-next-line no-console
|
|
319
|
+
console.log('%cno reactions', 'font-style: italic; color: gray');
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
// eslint-disable-next-line no-console
|
|
323
|
+
console.groupEnd();
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
// eslint-disable-next-line no-console
|
|
327
|
+
console.group(`%cDerived Reactions Graph`, 'font-weight: bold; color: purple');
|
|
328
|
+
|
|
329
|
+
visited.add(signal);
|
|
330
|
+
log_derived(signal, 0);
|
|
331
|
+
|
|
332
|
+
// eslint-disable-next-line no-console
|
|
333
|
+
console.groupEnd();
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
/**
|
|
337
|
+
* Traverses an effect tree and logs branches where a non-clean branch exists below a clean branch
|
|
338
|
+
* @param {Effect} effect
|
|
339
|
+
*/
|
|
340
|
+
export function log_inconsistent_branches(effect) {
|
|
341
|
+
const root_effect = root(effect);
|
|
342
|
+
|
|
343
|
+
/**
|
|
344
|
+
* @typedef {{
|
|
345
|
+
* effect: Effect,
|
|
346
|
+
* status: 'clean' | 'maybe dirty' | 'dirty',
|
|
347
|
+
* parent_clean: boolean,
|
|
348
|
+
* children: BranchInfo[]
|
|
349
|
+
* }} BranchInfo
|
|
350
|
+
*/
|
|
351
|
+
|
|
352
|
+
/**
|
|
353
|
+
* Collects branch effects from the tree
|
|
354
|
+
* @param {Effect} eff
|
|
355
|
+
* @param {boolean} parent_clean - whether any ancestor branch is clean
|
|
356
|
+
* @returns {BranchInfo[]}
|
|
357
|
+
*/
|
|
358
|
+
function collect_branches(eff, parent_clean) {
|
|
359
|
+
/** @type {BranchInfo[]} */
|
|
360
|
+
const branches = [];
|
|
361
|
+
const flags = eff.f;
|
|
362
|
+
const is_branch = (flags & BRANCH_EFFECT) !== 0;
|
|
363
|
+
|
|
364
|
+
if (is_branch) {
|
|
365
|
+
const status =
|
|
366
|
+
(flags & CLEAN) !== 0 ? 'clean' : (flags & MAYBE_DIRTY) !== 0 ? 'maybe dirty' : 'dirty';
|
|
367
|
+
|
|
368
|
+
/** @type {BranchInfo[]} */
|
|
369
|
+
const child_branches = [];
|
|
370
|
+
|
|
371
|
+
let child = eff.first;
|
|
372
|
+
while (child !== null) {
|
|
373
|
+
child_branches.push(...collect_branches(child, status === 'clean'));
|
|
374
|
+
child = child.next;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
branches.push({
|
|
378
|
+
effect: eff,
|
|
379
|
+
status,
|
|
380
|
+
parent_clean,
|
|
381
|
+
children: child_branches
|
|
382
|
+
});
|
|
383
|
+
} else {
|
|
384
|
+
// Not a branch, continue traversing
|
|
385
|
+
let child = eff.first;
|
|
386
|
+
while (child !== null) {
|
|
387
|
+
branches.push(...collect_branches(child, parent_clean));
|
|
388
|
+
child = child.next;
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
return branches;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
/**
|
|
396
|
+
* Checks if a branch tree contains any inconsistencies (non-clean below clean)
|
|
397
|
+
* @param {BranchInfo} branch
|
|
398
|
+
* @param {boolean} ancestor_clean
|
|
399
|
+
* @returns {boolean}
|
|
400
|
+
*/
|
|
401
|
+
function has_inconsistency(branch, ancestor_clean) {
|
|
402
|
+
const is_inconsistent = ancestor_clean && branch.status !== 'clean';
|
|
403
|
+
if (is_inconsistent) return true;
|
|
404
|
+
|
|
405
|
+
const new_ancestor_clean = ancestor_clean || branch.status === 'clean';
|
|
406
|
+
for (const child of branch.children) {
|
|
407
|
+
if (has_inconsistency(child, new_ancestor_clean)) return true;
|
|
408
|
+
}
|
|
409
|
+
return false;
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
/**
|
|
413
|
+
* Logs a branch and its children, but only if there are inconsistencies
|
|
414
|
+
* @param {BranchInfo} branch
|
|
415
|
+
* @param {boolean} ancestor_clean
|
|
416
|
+
* @param {number} depth
|
|
417
|
+
*/
|
|
418
|
+
function log_branch(branch, ancestor_clean, depth) {
|
|
419
|
+
const is_inconsistent = ancestor_clean && branch.status !== 'clean';
|
|
420
|
+
const new_ancestor_clean = ancestor_clean || branch.status === 'clean';
|
|
421
|
+
|
|
422
|
+
// Only log if this branch or any descendant has an inconsistency
|
|
423
|
+
if (!has_inconsistency(branch, ancestor_clean) && !is_inconsistent) {
|
|
424
|
+
return;
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
const style = is_inconsistent
|
|
428
|
+
? 'font-weight: bold; color: red'
|
|
429
|
+
: branch.status === 'clean'
|
|
430
|
+
? 'font-weight: normal; color: green'
|
|
431
|
+
: 'font-weight: bold; color: orange';
|
|
432
|
+
|
|
433
|
+
const warning = is_inconsistent ? ' ⚠️ INCONSISTENT' : '';
|
|
434
|
+
|
|
435
|
+
// eslint-disable-next-line no-console
|
|
436
|
+
console.group(`%cbranch (${branch.status})${warning}`, style);
|
|
437
|
+
|
|
438
|
+
// eslint-disable-next-line no-console
|
|
439
|
+
console.log('%ceffect:', 'font-weight: bold', branch.effect);
|
|
440
|
+
|
|
441
|
+
if (branch.effect.fn) {
|
|
442
|
+
// eslint-disable-next-line no-console
|
|
443
|
+
console.log('%cfn:', 'font-weight: bold', branch.effect.fn);
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
if (branch.effect.deps !== null) {
|
|
447
|
+
// eslint-disable-next-line no-console
|
|
448
|
+
console.groupCollapsed('%cdeps', 'font-weight: normal');
|
|
449
|
+
for (const dep of branch.effect.deps) {
|
|
450
|
+
log_dep(dep);
|
|
451
|
+
}
|
|
452
|
+
// eslint-disable-next-line no-console
|
|
453
|
+
console.groupEnd();
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
if (is_inconsistent) {
|
|
457
|
+
log_effect_tree(branch.effect);
|
|
458
|
+
} else if (branch.children.length > 0) {
|
|
459
|
+
// eslint-disable-next-line no-console
|
|
460
|
+
console.group('%cchild branches', 'font-weight: bold');
|
|
461
|
+
for (const child of branch.children) {
|
|
462
|
+
log_branch(child, new_ancestor_clean, depth + 1);
|
|
463
|
+
}
|
|
464
|
+
// eslint-disable-next-line no-console
|
|
465
|
+
console.groupEnd();
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
// eslint-disable-next-line no-console
|
|
469
|
+
console.groupEnd();
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
const branches = collect_branches(root_effect, false);
|
|
473
|
+
|
|
474
|
+
// Check if there are any inconsistencies at all
|
|
475
|
+
let has_any_inconsistency = false;
|
|
476
|
+
for (const branch of branches) {
|
|
477
|
+
if (has_inconsistency(branch, false)) {
|
|
478
|
+
has_any_inconsistency = true;
|
|
479
|
+
break;
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
if (!has_any_inconsistency) {
|
|
484
|
+
// eslint-disable-next-line no-console
|
|
485
|
+
console.log('%cNo inconsistent branches found', 'font-weight: bold; color: green');
|
|
486
|
+
return;
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
// eslint-disable-next-line no-console
|
|
490
|
+
console.group(`%cInconsistent Branches (non-clean below clean)`, 'font-weight: bold; color: red');
|
|
491
|
+
|
|
492
|
+
for (const branch of branches) {
|
|
493
|
+
log_branch(branch, false, 0);
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
// eslint-disable-next-line no-console
|
|
497
|
+
console.groupEnd();
|
|
498
|
+
|
|
499
|
+
return true;
|
|
500
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/** @import { EachItem, EachState, Effect, MaybeSource, Source, TemplateNode, TransitionManager, Value } from '#client' */
|
|
1
|
+
/** @import { EachItem, 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,
|
|
@@ -43,18 +43,6 @@ import { DEV } from 'esm-env';
|
|
|
43
43
|
import { derived_safe_equal } from '../../reactivity/deriveds.js';
|
|
44
44
|
import { current_batch } from '../../reactivity/batch.js';
|
|
45
45
|
|
|
46
|
-
/**
|
|
47
|
-
* The row of a keyed each block that is currently updating. We track this
|
|
48
|
-
* so that `animate:` directives have something to attach themselves to
|
|
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
|
-
}
|
|
57
|
-
|
|
58
46
|
/**
|
|
59
47
|
* @param {any} _
|
|
60
48
|
* @param {number} i
|
|
@@ -243,8 +231,6 @@ export function each(node, flags, get_collection, get_key, render_fn, fallback_f
|
|
|
243
231
|
|
|
244
232
|
if (is_reactive_index) {
|
|
245
233
|
internal_set(/** @type {Value<number>} */ (item.i), i);
|
|
246
|
-
} else {
|
|
247
|
-
item.i = i;
|
|
248
234
|
}
|
|
249
235
|
|
|
250
236
|
if (defer) {
|
|
@@ -397,7 +383,7 @@ function reconcile(state, array, anchor, flags, get_key) {
|
|
|
397
383
|
// offscreen == coming in now, no animation in that case,
|
|
398
384
|
// else this would happen https://github.com/sveltejs/svelte/issues/17181
|
|
399
385
|
if (item.o) {
|
|
400
|
-
item.a?.measure();
|
|
386
|
+
item.e.nodes?.a?.measure();
|
|
401
387
|
(to_animate ??= new Set()).add(item);
|
|
402
388
|
}
|
|
403
389
|
}
|
|
@@ -432,7 +418,7 @@ function reconcile(state, array, anchor, flags, get_key) {
|
|
|
432
418
|
if ((item.e.f & INERT) !== 0) {
|
|
433
419
|
resume_effect(item.e);
|
|
434
420
|
if (is_animated) {
|
|
435
|
-
item.a?.unfix();
|
|
421
|
+
item.e.nodes?.a?.unfix();
|
|
436
422
|
(to_animate ??= new Set()).delete(item);
|
|
437
423
|
}
|
|
438
424
|
}
|
|
@@ -485,7 +471,7 @@ function reconcile(state, array, anchor, flags, get_key) {
|
|
|
485
471
|
matched = [];
|
|
486
472
|
stashed = [];
|
|
487
473
|
|
|
488
|
-
while (current !== null && current
|
|
474
|
+
while (current !== null && current !== item) {
|
|
489
475
|
// If the each block isn't inert and an item has an effect that is already inert,
|
|
490
476
|
// skip over adding it to our seen Set as the item is already being handled
|
|
491
477
|
if ((current.e.f & INERT) === 0) {
|
|
@@ -529,11 +515,11 @@ function reconcile(state, array, anchor, flags, get_key) {
|
|
|
529
515
|
|
|
530
516
|
if (is_animated) {
|
|
531
517
|
for (i = 0; i < destroy_length; i += 1) {
|
|
532
|
-
to_destroy[i].a?.measure();
|
|
518
|
+
to_destroy[i].e.nodes?.a?.measure();
|
|
533
519
|
}
|
|
534
520
|
|
|
535
521
|
for (i = 0; i < destroy_length; i += 1) {
|
|
536
|
-
to_destroy[i].a?.fix();
|
|
522
|
+
to_destroy[i].e.nodes?.a?.fix();
|
|
537
523
|
}
|
|
538
524
|
}
|
|
539
525
|
|
|
@@ -557,7 +543,7 @@ function reconcile(state, array, anchor, flags, get_key) {
|
|
|
557
543
|
queue_micro_task(() => {
|
|
558
544
|
if (to_animate === undefined) return;
|
|
559
545
|
for (item of to_animate) {
|
|
560
|
-
item.a?.apply();
|
|
546
|
+
item.e.nodes?.a?.apply();
|
|
561
547
|
}
|
|
562
548
|
});
|
|
563
549
|
}
|
|
@@ -576,7 +562,6 @@ function reconcile(state, array, anchor, flags, get_key) {
|
|
|
576
562
|
* @returns {EachItem}
|
|
577
563
|
*/
|
|
578
564
|
function create_item(anchor, prev, value, key, index, render_fn, flags, get_collection) {
|
|
579
|
-
var previous_each_item = current_each_item;
|
|
580
565
|
var reactive = (flags & EACH_ITEM_REACTIVE) !== 0;
|
|
581
566
|
var mutable = (flags & EACH_ITEM_IMMUTABLE) === 0;
|
|
582
567
|
|
|
@@ -598,7 +583,6 @@ function create_item(anchor, prev, value, key, index, render_fn, flags, get_coll
|
|
|
598
583
|
i,
|
|
599
584
|
v,
|
|
600
585
|
k: key,
|
|
601
|
-
a: null,
|
|
602
586
|
// @ts-expect-error
|
|
603
587
|
e: null,
|
|
604
588
|
o: false,
|
|
@@ -606,27 +590,21 @@ function create_item(anchor, prev, value, key, index, render_fn, flags, get_coll
|
|
|
606
590
|
next: null
|
|
607
591
|
};
|
|
608
592
|
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
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));
|
|
593
|
+
if (anchor === null) {
|
|
594
|
+
var fragment = document.createDocumentFragment();
|
|
595
|
+
fragment.append((anchor = create_text()));
|
|
596
|
+
}
|
|
618
597
|
|
|
619
|
-
|
|
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
|
-
}
|
|
598
|
+
item.e = branch(() => render_fn(/** @type {Node} */ (anchor), v, i, get_collection));
|
|
625
599
|
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
600
|
+
if (prev !== null) {
|
|
601
|
+
// we only need to set `prev.next = item`, because
|
|
602
|
+
// `item.prev = prev` was set on initialization.
|
|
603
|
+
// the effects themselves are already linked
|
|
604
|
+
prev.next = item;
|
|
629
605
|
}
|
|
606
|
+
|
|
607
|
+
return item;
|
|
630
608
|
}
|
|
631
609
|
|
|
632
610
|
/**
|
|
@@ -635,10 +613,12 @@ function create_item(anchor, prev, value, key, index, render_fn, flags, get_coll
|
|
|
635
613
|
* @param {Text | Element | Comment} anchor
|
|
636
614
|
*/
|
|
637
615
|
function move(item, next, anchor) {
|
|
638
|
-
|
|
616
|
+
if (!item.e.nodes) return;
|
|
617
|
+
|
|
618
|
+
var end = item.next ? /** @type {EffectNodes} */ (item.next.e.nodes).start : anchor;
|
|
639
619
|
|
|
640
|
-
var dest = next ? /** @type {
|
|
641
|
-
var node = /** @type {TemplateNode} */ (item.e.
|
|
620
|
+
var dest = next ? /** @type {EffectNodes} */ (next.e.nodes).start : anchor;
|
|
621
|
+
var node = /** @type {TemplateNode} */ (item.e.nodes.start);
|
|
642
622
|
|
|
643
623
|
while (node !== null && node !== end) {
|
|
644
624
|
var next_node = /** @type {TemplateNode} */ (get_next_sibling(node));
|
|
@@ -54,9 +54,9 @@ export function html(node, get_value, svg = false, mathml = false, skip_warning
|
|
|
54
54
|
return;
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
-
if (effect.
|
|
58
|
-
remove_effect_dom(effect.
|
|
59
|
-
effect.
|
|
57
|
+
if (effect.nodes !== null) {
|
|
58
|
+
remove_effect_dom(effect.nodes.start, /** @type {TemplateNode} */ (effect.nodes.end));
|
|
59
|
+
effect.nodes = null;
|
|
60
60
|
}
|
|
61
61
|
|
|
62
62
|
if (value === '') return;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/** @import { Effect, TemplateNode } from '#client' */
|
|
1
|
+
/** @import { Effect, EffectNodes, TemplateNode } from '#client' */
|
|
2
2
|
import { FILENAME, NAMESPACE_SVG } from '../../../../constants.js';
|
|
3
3
|
import {
|
|
4
4
|
hydrate_next,
|
|
@@ -10,7 +10,6 @@ import {
|
|
|
10
10
|
import { create_text, get_first_child } from '../operations.js';
|
|
11
11
|
import { block, teardown } from '../../reactivity/effects.js';
|
|
12
12
|
import { set_should_intro } from '../../render.js';
|
|
13
|
-
import { current_each_item, set_current_each_item } from './each.js';
|
|
14
13
|
import { active_effect } from '../../runtime.js';
|
|
15
14
|
import { component_context, dev_stack } from '../../context.js';
|
|
16
15
|
import { DEV } from 'esm-env';
|
|
@@ -18,6 +17,7 @@ import { EFFECT_TRANSPARENT, ELEMENT_NODE } from '#client/constants';
|
|
|
18
17
|
import { assign_nodes } from '../template.js';
|
|
19
18
|
import { is_raw_text_element } from '../../../../utils.js';
|
|
20
19
|
import { BranchManager } from './branches.js';
|
|
20
|
+
import { set_animation_effect_override } from '../elements/transitions.js';
|
|
21
21
|
|
|
22
22
|
/**
|
|
23
23
|
* @param {Comment | Element} node
|
|
@@ -48,11 +48,10 @@ export function element(node, get_tag, is_svg, render_fn, get_namespace, locatio
|
|
|
48
48
|
var anchor = /** @type {TemplateNode} */ (hydrating ? hydrate_node : node);
|
|
49
49
|
|
|
50
50
|
/**
|
|
51
|
-
* The keyed `{#each ...}` item block, if any, that this element is inside.
|
|
52
51
|
* We track this so we can set it when changing the element, allowing any
|
|
53
52
|
* `animate:` directive to bind itself to the correct block
|
|
54
53
|
*/
|
|
55
|
-
var
|
|
54
|
+
var parent_effect = /** @type {Effect} */ (active_effect);
|
|
56
55
|
|
|
57
56
|
var branches = new BranchManager(anchor, false);
|
|
58
57
|
|
|
@@ -67,10 +66,6 @@ export function element(node, get_tag, is_svg, render_fn, get_namespace, locatio
|
|
|
67
66
|
}
|
|
68
67
|
|
|
69
68
|
branches.ensure(next_tag, (anchor) => {
|
|
70
|
-
// See explanation of `each_item_block` above
|
|
71
|
-
var previous_each_item = current_each_item;
|
|
72
|
-
set_current_each_item(each_item_block);
|
|
73
|
-
|
|
74
69
|
if (next_tag) {
|
|
75
70
|
element = hydrating
|
|
76
71
|
? /** @type {Element} */ (element)
|
|
@@ -112,21 +107,23 @@ export function element(node, get_tag, is_svg, render_fn, get_namespace, locatio
|
|
|
112
107
|
}
|
|
113
108
|
}
|
|
114
109
|
|
|
110
|
+
set_animation_effect_override(parent_effect);
|
|
111
|
+
|
|
115
112
|
// `child_anchor` is undefined if this is a void element, but we still
|
|
116
113
|
// need to call `render_fn` in order to run actions etc. If the element
|
|
117
114
|
// contains children, it's a user error (which is warned on elsewhere)
|
|
118
115
|
// and the DOM will be silently discarded
|
|
119
116
|
render_fn(element, child_anchor);
|
|
117
|
+
|
|
118
|
+
set_animation_effect_override(null);
|
|
120
119
|
}
|
|
121
120
|
|
|
122
121
|
// we do this after calling `render_fn` so that child effects don't override `nodes.end`
|
|
123
|
-
/** @type {Effect} */ (active_effect).
|
|
122
|
+
/** @type {Effect & { nodes: EffectNodes }} */ (active_effect).nodes.end = element;
|
|
124
123
|
|
|
125
124
|
anchor.before(element);
|
|
126
125
|
}
|
|
127
126
|
|
|
128
|
-
set_current_each_item(previous_each_item);
|
|
129
|
-
|
|
130
127
|
if (hydrating) {
|
|
131
128
|
set_hydrate_node(anchor);
|
|
132
129
|
}
|