svelte 5.56.9 → 5.57.0
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/elements.d.ts +3 -0
- package/package.json +3 -3
- package/src/compiler/migrate/index.js +6 -1
- package/src/compiler/phases/1-parse/acorn.js +1 -1
- package/src/compiler/phases/1-parse/read/style.js +16 -6
- package/src/compiler/phases/1-parse/utils/html.js +12 -7
- package/src/compiler/phases/2-analyze/css/css-prune.js +10 -0
- package/src/compiler/phases/2-analyze/index.js +45 -18
- package/src/compiler/phases/2-analyze/visitors/AwaitExpression.js +10 -4
- package/src/compiler/phases/2-analyze/visitors/CallExpression.js +1 -1
- package/src/compiler/phases/2-analyze/visitors/DeclarationTag.js +2 -1
- package/src/compiler/phases/2-analyze/visitors/ExportNamedDeclaration.js +10 -10
- package/src/compiler/phases/2-analyze/visitors/SvelteBody.js +4 -4
- package/src/compiler/phases/2-analyze/visitors/SvelteDocument.js +4 -4
- package/src/compiler/phases/2-analyze/visitors/SvelteWindow.js +4 -4
- package/src/compiler/phases/2-analyze/visitors/shared/a11y/index.js +14 -2
- package/src/compiler/phases/2-analyze/visitors/shared/element.js +2 -8
- package/src/compiler/phases/2-analyze/visitors/shared/utils.js +23 -1
- package/src/compiler/phases/3-transform/client/transform-client.js +2 -2
- package/src/compiler/phases/3-transform/client/transform-template/index.js +6 -0
- package/src/compiler/phases/3-transform/client/utils.js +35 -8
- package/src/compiler/phases/3-transform/client/visitors/AssignmentExpression.js +16 -3
- package/src/compiler/phases/3-transform/client/visitors/AwaitBlock.js +6 -6
- package/src/compiler/phases/3-transform/client/visitors/BindDirective.js +10 -13
- package/src/compiler/phases/3-transform/client/visitors/ConstTag.js +19 -8
- package/src/compiler/phases/3-transform/client/visitors/DeclarationTag.js +3 -2
- package/src/compiler/phases/3-transform/client/visitors/EachBlock.js +4 -1
- package/src/compiler/phases/3-transform/client/visitors/Fragment.js +2 -7
- package/src/compiler/phases/3-transform/client/visitors/HtmlTag.js +2 -1
- package/src/compiler/phases/3-transform/client/visitors/IfBlock.js +2 -1
- package/src/compiler/phases/3-transform/client/visitors/KeyBlock.js +2 -1
- package/src/compiler/phases/3-transform/client/visitors/RegularElement.js +119 -46
- package/src/compiler/phases/3-transform/client/visitors/SvelteElement.js +2 -1
- package/src/compiler/phases/3-transform/client/visitors/UpdateExpression.js +0 -1
- package/src/compiler/phases/3-transform/client/visitors/VariableDeclaration.js +11 -4
- package/src/compiler/phases/3-transform/client/visitors/shared/element.js +6 -1
- package/src/compiler/phases/3-transform/client/visitors/shared/fragment.js +1 -6
- package/src/compiler/phases/3-transform/client/visitors/shared/utils.js +5 -5
- package/src/compiler/phases/3-transform/css/index.js +5 -1
- package/src/compiler/phases/3-transform/server/transform-server.js +20 -9
- package/src/compiler/phases/3-transform/server/visitors/AssignmentExpression.js +1 -1
- package/src/compiler/phases/3-transform/server/visitors/DeclarationTag.js +1 -1
- package/src/compiler/phases/3-transform/server/visitors/EachBlock.js +8 -2
- package/src/compiler/phases/3-transform/server/visitors/IfBlock.js +4 -4
- package/src/compiler/phases/3-transform/server/visitors/LabeledStatement.js +1 -0
- package/src/compiler/phases/3-transform/server/visitors/RegularElement.js +1 -1
- package/src/compiler/phases/3-transform/server/visitors/SvelteBoundary.js +9 -4
- package/src/compiler/phases/3-transform/server/visitors/VariableDeclaration.js +4 -2
- package/src/compiler/phases/3-transform/server/visitors/shared/element.js +53 -47
- package/src/compiler/phases/3-transform/server/visitors/shared/utils.js +31 -1
- package/src/compiler/phases/bindings.js +3 -1
- package/src/compiler/phases/nodes.js +4 -0
- package/src/compiler/print/index.js +95 -24
- package/src/easing/index.js +62 -0
- package/src/internal/client/constants.js +9 -0
- package/src/internal/client/context.js +33 -56
- package/src/internal/client/dev/hmr.js +15 -4
- package/src/internal/client/dom/blocks/boundary.js +21 -12
- package/src/internal/client/dom/blocks/css-props.js +3 -3
- package/src/internal/client/dom/blocks/slot.js +19 -0
- package/src/internal/client/dom/blocks/svelte-head.js +8 -0
- package/src/internal/client/dom/css.js +6 -1
- package/src/internal/client/dom/elements/attributes.js +37 -35
- package/src/internal/client/dom/elements/bindings/select.js +99 -9
- package/src/internal/client/dom/elements/bindings/this.js +7 -2
- package/src/internal/client/dom/elements/events.js +19 -1
- package/src/internal/client/dom/elements/transitions.js +81 -68
- package/src/internal/client/dom/operations.js +21 -1
- package/src/internal/client/error-handling.js +10 -2
- package/src/internal/client/index.js +9 -2
- package/src/internal/client/proxy.js +8 -3
- package/src/internal/client/reactivity/async.js +23 -3
- package/src/internal/client/reactivity/batch.js +1 -0
- package/src/internal/client/reactivity/effects.js +14 -1
- package/src/internal/client/reactivity/sources.js +7 -1
- package/src/internal/client/render.js +4 -8
- package/src/internal/client/runtime.js +45 -33
- package/src/internal/client/warnings.js +0 -11
- package/src/internal/server/abort-signal.js +8 -9
- package/src/internal/server/context.js +9 -48
- package/src/internal/server/index.js +1 -1
- package/src/internal/server/renderer.js +164 -52
- package/src/internal/shared/attributes.js +4 -2
- package/src/internal/shared/clone.js +2 -0
- package/src/internal/shared/context.js +53 -0
- package/src/internal/shared/errors.js +2 -2
- package/src/legacy/legacy-server.js +1 -1
- package/src/reactivity/map.js +22 -0
- package/src/reactivity/url.js +2 -0
- package/src/transition/index.js +18 -7
- package/src/version.js +1 -1
- package/types/index.d.ts +148 -46
- package/types/index.d.ts.map +2 -2
|
@@ -337,6 +337,7 @@ export function transition(flags, element, get_fn, get_params) {
|
|
|
337
337
|
*/
|
|
338
338
|
function animate(element, options, counterpart, t2, on_begin, on_finish) {
|
|
339
339
|
var is_intro = t2 === 1;
|
|
340
|
+
var aborted = false;
|
|
340
341
|
|
|
341
342
|
if (is_function(options)) {
|
|
342
343
|
// In the case of a deferred transition (such as `crossfade`), `option` will be
|
|
@@ -344,7 +345,6 @@ function animate(element, options, counterpart, t2, on_begin, on_finish) {
|
|
|
344
345
|
// once the DOM has been updated...
|
|
345
346
|
/** @type {Animation} */
|
|
346
347
|
var a;
|
|
347
|
-
var aborted = false;
|
|
348
348
|
|
|
349
349
|
queue_micro_task(() => {
|
|
350
350
|
if (aborted) return;
|
|
@@ -381,99 +381,112 @@ function animate(element, options, counterpart, t2, on_begin, on_finish) {
|
|
|
381
381
|
|
|
382
382
|
const { delay = 0, css, tick, easing = linear } = options;
|
|
383
383
|
|
|
384
|
-
|
|
384
|
+
/** @type {globalThis.Animation} */
|
|
385
|
+
var animation;
|
|
385
386
|
|
|
386
|
-
|
|
387
|
-
if (tick) {
|
|
388
|
-
tick(0, 1); // TODO put in nested effect, to avoid interleaved reads/writes?
|
|
389
|
-
}
|
|
387
|
+
var get_t = () => 1 - t2;
|
|
390
388
|
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
389
|
+
// wait a microtask before applying the initial styles and creating the dummy animation,
|
|
390
|
+
// so that transitions created in the same batch (e.g. on nested elements) all measure
|
|
391
|
+
// the DOM first (#18421). this still happens before the next paint, so the element
|
|
392
|
+
// won't be rendered without styles applied (#14732)
|
|
393
|
+
queue_micro_task(() => {
|
|
394
|
+
if (aborted) return;
|
|
396
395
|
|
|
397
|
-
|
|
396
|
+
var keyframes = [];
|
|
398
397
|
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
// fill forwards to prevent the element from rendering without styles applied
|
|
404
|
-
// see https://github.com/sveltejs/svelte/issues/14732
|
|
405
|
-
var animation = element.animate(keyframes, { duration: delay, fill: 'forwards' });
|
|
398
|
+
if (is_intro && counterpart === undefined) {
|
|
399
|
+
if (tick) {
|
|
400
|
+
tick(0, 1); // TODO put in nested effect, to avoid interleaved reads/writes?
|
|
401
|
+
}
|
|
406
402
|
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
403
|
+
if (css) {
|
|
404
|
+
var styles = css_to_keyframe(css(0, 1));
|
|
405
|
+
keyframes.push(styles, styles);
|
|
406
|
+
}
|
|
407
|
+
}
|
|
410
408
|
|
|
411
|
-
|
|
409
|
+
// create a dummy animation that lasts as long as the delay (but with whatever devtools
|
|
410
|
+
// multiplier is in effect). in the common case that it is `0`, we keep it anyway so that
|
|
411
|
+
// the CSS keyframes aren't created until the DOM is updated
|
|
412
|
+
//
|
|
413
|
+
// fill forwards to prevent the element from rendering without styles applied
|
|
414
|
+
// see https://github.com/sveltejs/svelte/issues/14732
|
|
415
|
+
animation = element.animate(keyframes, { duration: delay, fill: 'forwards' });
|
|
412
416
|
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
counterpart?.abort();
|
|
417
|
+
animation.onfinish = () => {
|
|
418
|
+
// remove dummy animation from the stack to prevent conflict with main animation
|
|
419
|
+
animation.cancel();
|
|
417
420
|
|
|
418
|
-
|
|
419
|
-
var duration = /** @type {number} */ (options.duration) * Math.abs(delta);
|
|
420
|
-
var keyframes = [];
|
|
421
|
+
on_begin();
|
|
421
422
|
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
* TODO 6.0 remove this, if possible
|
|
427
|
-
*/
|
|
428
|
-
var needs_overflow_hidden = false;
|
|
423
|
+
// for bidirectional transitions, we start from the current position,
|
|
424
|
+
// rather than doing a full intro/outro
|
|
425
|
+
var t1 = counterpart?.t() ?? 1 - t2;
|
|
426
|
+
counterpart?.abort();
|
|
429
427
|
|
|
430
|
-
|
|
431
|
-
|
|
428
|
+
var delta = t2 - t1;
|
|
429
|
+
var duration = /** @type {number} */ (options.duration) * Math.abs(delta);
|
|
430
|
+
var keyframes = [];
|
|
431
|
+
|
|
432
|
+
if (duration > 0) {
|
|
433
|
+
/**
|
|
434
|
+
* Whether or not the CSS includes `overflow: hidden`, in which case we need to
|
|
435
|
+
* add it as an inline style to work around a Safari <18 bug
|
|
436
|
+
* TODO 6.0 remove this, if possible
|
|
437
|
+
*/
|
|
438
|
+
var needs_overflow_hidden = false;
|
|
432
439
|
|
|
433
|
-
|
|
434
|
-
var
|
|
435
|
-
var styles = css_to_keyframe(css(t, 1 - t));
|
|
436
|
-
keyframes.push(styles);
|
|
440
|
+
if (css) {
|
|
441
|
+
var n = Math.ceil(duration / (1000 / 60)); // `n` must be an integer, or we risk missing the `t2` value
|
|
437
442
|
|
|
438
|
-
|
|
443
|
+
for (var i = 0; i <= n; i += 1) {
|
|
444
|
+
var t = t1 + delta * easing(i / n);
|
|
445
|
+
var styles = css_to_keyframe(css(t, 1 - t));
|
|
446
|
+
keyframes.push(styles);
|
|
447
|
+
|
|
448
|
+
needs_overflow_hidden ||= styles.overflow === 'hidden';
|
|
449
|
+
}
|
|
439
450
|
}
|
|
440
|
-
}
|
|
441
451
|
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
452
|
+
if (needs_overflow_hidden) {
|
|
453
|
+
/** @type {HTMLElement} */ (element).style.overflow = 'hidden';
|
|
454
|
+
}
|
|
445
455
|
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
456
|
+
get_t = () => {
|
|
457
|
+
var time = /** @type {number} */ (
|
|
458
|
+
/** @type {globalThis.Animation} */ (animation).currentTime
|
|
459
|
+
);
|
|
450
460
|
|
|
451
|
-
|
|
452
|
-
|
|
461
|
+
return t1 + delta * easing(time / duration);
|
|
462
|
+
};
|
|
453
463
|
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
464
|
+
if (tick) {
|
|
465
|
+
loop(() => {
|
|
466
|
+
if (animation.playState !== 'running') return false;
|
|
457
467
|
|
|
458
|
-
|
|
459
|
-
|
|
468
|
+
var t = get_t();
|
|
469
|
+
tick(t, 1 - t);
|
|
460
470
|
|
|
461
|
-
|
|
462
|
-
|
|
471
|
+
return true;
|
|
472
|
+
});
|
|
473
|
+
}
|
|
463
474
|
}
|
|
464
|
-
}
|
|
465
475
|
|
|
466
|
-
|
|
476
|
+
animation = element.animate(keyframes, { duration, fill: 'forwards' });
|
|
467
477
|
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
478
|
+
animation.onfinish = () => {
|
|
479
|
+
get_t = () => t2;
|
|
480
|
+
tick?.(t2, 1 - t2);
|
|
481
|
+
on_finish();
|
|
482
|
+
};
|
|
472
483
|
};
|
|
473
|
-
};
|
|
484
|
+
});
|
|
474
485
|
|
|
475
486
|
return {
|
|
476
487
|
abort: () => {
|
|
488
|
+
aborted = true;
|
|
489
|
+
|
|
477
490
|
if (animation) {
|
|
478
491
|
animation.cancel();
|
|
479
492
|
// This prevents memory leaks in Chromium
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/** @import { Effect, TemplateNode } from '#client' */
|
|
2
|
-
import { hydrate_node, hydrating, set_hydrate_node } from './hydration.js';
|
|
2
|
+
import { hydrate_node, hydrating, reset, set_hydrate_node } from './hydration.js';
|
|
3
3
|
import { DEV } from 'esm-env';
|
|
4
4
|
import { init_array_prototype_warnings } from '../dev/equality.js';
|
|
5
5
|
import { get_descriptor, is_extensible } from '../../shared/utils.js';
|
|
@@ -165,6 +165,26 @@ export function first_child(node, is_text = false) {
|
|
|
165
165
|
return hydrate_node;
|
|
166
166
|
}
|
|
167
167
|
|
|
168
|
+
/**
|
|
169
|
+
* `child`, for the very common case of an element with exactly one child. Resetting the
|
|
170
|
+
* hydration cursor is part of the same step, so the compiler doesn't have to emit a
|
|
171
|
+
* separate `reset` call for every `<p>{text}</p>` in an app.
|
|
172
|
+
* Don't mark this as side-effect-free, hydration needs to walk all nodes
|
|
173
|
+
* @param {TemplateNode} node
|
|
174
|
+
* @param {boolean} [is_text]
|
|
175
|
+
* @returns {TemplateNode | null}
|
|
176
|
+
*/
|
|
177
|
+
export function only_child(node, is_text = false) {
|
|
178
|
+
if (!hydrating) {
|
|
179
|
+
return get_first_child(node);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
var first = child(node, is_text);
|
|
183
|
+
reset(node);
|
|
184
|
+
|
|
185
|
+
return first;
|
|
186
|
+
}
|
|
187
|
+
|
|
168
188
|
/**
|
|
169
189
|
* Don't mark this as side-effect-free, hydration needs to walk all nodes
|
|
170
190
|
* @param {TemplateNode} node
|
|
@@ -3,7 +3,14 @@
|
|
|
3
3
|
import { DEV } from 'esm-env';
|
|
4
4
|
import { FILENAME } from '../../constants.js';
|
|
5
5
|
import { is_firefox } from './dom/operations.js';
|
|
6
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
ERROR_VALUE,
|
|
8
|
+
BOUNDARY_EFFECT,
|
|
9
|
+
REACTION_RAN,
|
|
10
|
+
EFFECT,
|
|
11
|
+
DESTROYED,
|
|
12
|
+
DESTROYING
|
|
13
|
+
} from './constants.js';
|
|
7
14
|
import { define_property, get_descriptor } from '../shared/utils.js';
|
|
8
15
|
import { active_effect, active_reaction } from './runtime.js';
|
|
9
16
|
|
|
@@ -50,7 +57,8 @@ export function invoke_error_boundary(error, effect) {
|
|
|
50
57
|
}
|
|
51
58
|
|
|
52
59
|
while (effect !== null) {
|
|
53
|
-
|
|
60
|
+
// Skip boundaries that are destroyed/destroying and cannot meaningfully handle the error.
|
|
61
|
+
if ((effect.f & BOUNDARY_EFFECT) !== 0 && (effect.f & (DESTROYED | DESTROYING)) === 0) {
|
|
54
62
|
if ((effect.f & REACTION_RAN) === 0) {
|
|
55
63
|
// we are still creating the boundary effect
|
|
56
64
|
throw error;
|
|
@@ -33,7 +33,6 @@ export {
|
|
|
33
33
|
set_xlink_attribute,
|
|
34
34
|
set_value,
|
|
35
35
|
set_checked,
|
|
36
|
-
set_selected,
|
|
37
36
|
set_default_checked,
|
|
38
37
|
set_default_value,
|
|
39
38
|
CLASS,
|
|
@@ -62,7 +61,13 @@ export {
|
|
|
62
61
|
} from './dom/elements/bindings/media.js';
|
|
63
62
|
export { bind_online } from './dom/elements/bindings/navigator.js';
|
|
64
63
|
export { bind_prop } from './dom/elements/bindings/props.js';
|
|
65
|
-
export {
|
|
64
|
+
export {
|
|
65
|
+
bind_select_value,
|
|
66
|
+
init_select,
|
|
67
|
+
select_option,
|
|
68
|
+
set_selected,
|
|
69
|
+
set_default_select_value
|
|
70
|
+
} from './dom/elements/bindings/select.js';
|
|
66
71
|
export { bind_element_size, bind_resize_observer } from './dom/elements/bindings/size.js';
|
|
67
72
|
export { bind_this } from './dom/elements/bindings/this.js';
|
|
68
73
|
export {
|
|
@@ -103,6 +108,7 @@ export {
|
|
|
103
108
|
run,
|
|
104
109
|
save,
|
|
105
110
|
track_reactivity_loss,
|
|
111
|
+
unsave,
|
|
106
112
|
run_after_blockers,
|
|
107
113
|
wait
|
|
108
114
|
} from './reactivity/async.js';
|
|
@@ -163,6 +169,7 @@ export { proxy } from './proxy.js';
|
|
|
163
169
|
export { create_custom_element } from './dom/elements/custom-element.js';
|
|
164
170
|
export {
|
|
165
171
|
child,
|
|
172
|
+
only_child,
|
|
166
173
|
first_child,
|
|
167
174
|
sibling,
|
|
168
175
|
$window as window,
|
|
@@ -22,7 +22,7 @@ import {
|
|
|
22
22
|
flush_eager_effects,
|
|
23
23
|
set_eager_effects_deferred
|
|
24
24
|
} from './reactivity/sources.js';
|
|
25
|
-
import { PROXY_PATH_SYMBOL, STATE_SYMBOL } from '#client/constants';
|
|
25
|
+
import { COMPONENT_SYMBOL, PROXY_PATH_SYMBOL, STATE_SYMBOL } from '#client/constants';
|
|
26
26
|
import { UNINITIALIZED } from '../../constants.js';
|
|
27
27
|
import * as e from './errors.js';
|
|
28
28
|
import { tag } from './dev/tracing.js';
|
|
@@ -38,8 +38,13 @@ const regex_is_valid_identifier = /^[a-zA-Z_$][a-zA-Z_$0-9]*$/;
|
|
|
38
38
|
* @returns {T}
|
|
39
39
|
*/
|
|
40
40
|
export function proxy(value) {
|
|
41
|
-
// if non-proxyable, or
|
|
42
|
-
if (
|
|
41
|
+
// if non-proxyable, a component instance, or already a proxy, return `value`
|
|
42
|
+
if (
|
|
43
|
+
typeof value !== 'object' ||
|
|
44
|
+
value === null ||
|
|
45
|
+
STATE_SYMBOL in value ||
|
|
46
|
+
COMPONENT_SYMBOL in value
|
|
47
|
+
) {
|
|
43
48
|
return value;
|
|
44
49
|
}
|
|
45
50
|
|
|
@@ -8,7 +8,6 @@ import {
|
|
|
8
8
|
set_component_context,
|
|
9
9
|
set_dev_stack
|
|
10
10
|
} from '../context.js';
|
|
11
|
-
import { Boundary } from '../dom/blocks/boundary.js';
|
|
12
11
|
import { invoke_error_boundary } from '../error-handling.js';
|
|
13
12
|
import {
|
|
14
13
|
active_effect,
|
|
@@ -25,7 +24,6 @@ import {
|
|
|
25
24
|
set_reactivity_loss_tracker
|
|
26
25
|
} from './deriveds.js';
|
|
27
26
|
import { aborted } from './effects.js';
|
|
28
|
-
import { queue_micro_task } from '../dom/task.js';
|
|
29
27
|
|
|
30
28
|
/**
|
|
31
29
|
* @param {Blocker[]} blockers
|
|
@@ -156,6 +154,9 @@ export function capture() {
|
|
|
156
154
|
};
|
|
157
155
|
}
|
|
158
156
|
|
|
157
|
+
/** `true` between a `save` thunk restoring a context and the end of that synchronous segment */
|
|
158
|
+
var restored = false;
|
|
159
|
+
|
|
159
160
|
/**
|
|
160
161
|
* Wraps an `await` expression in such a way that the effect context that was
|
|
161
162
|
* active before the expression evaluated can be reapplied afterwards —
|
|
@@ -166,15 +167,32 @@ export function capture() {
|
|
|
166
167
|
*/
|
|
167
168
|
export async function save(promise) {
|
|
168
169
|
var restore = capture();
|
|
170
|
+
// the context restored by an earlier `save` in this expression must not
|
|
171
|
+
// outlive the synchronous segment that is about to end at this `await`
|
|
172
|
+
unsave();
|
|
169
173
|
var value = await promise;
|
|
170
174
|
|
|
171
175
|
return () => {
|
|
172
176
|
restore();
|
|
173
|
-
|
|
177
|
+
restored = true;
|
|
174
178
|
return value;
|
|
175
179
|
};
|
|
176
180
|
}
|
|
177
181
|
|
|
182
|
+
/**
|
|
183
|
+
* Unset the context if a `save` thunk restored it in the current synchronous segment,
|
|
184
|
+
* so that a foreign microtask can never run inside a restored reaction context.
|
|
185
|
+
* Called at every suspension point, and at the end of async expression bodies —
|
|
186
|
+
* `async () => (await $.save(a))().b` becomes `async () => { try { return (await $.save(a))().b; } finally { $.unsave(); } }`
|
|
187
|
+
* @template T
|
|
188
|
+
* @param {T} [value]
|
|
189
|
+
* @returns {T}
|
|
190
|
+
*/
|
|
191
|
+
export function unsave(value) {
|
|
192
|
+
if (restored) unset_context();
|
|
193
|
+
return /** @type {T} */ (value);
|
|
194
|
+
}
|
|
195
|
+
|
|
178
196
|
/**
|
|
179
197
|
* Reset `current_async_effect` after the `promise` resolves, so
|
|
180
198
|
* that we can emit `await_reactivity_loss` warnings
|
|
@@ -183,6 +201,7 @@ export async function save(promise) {
|
|
|
183
201
|
* @returns {Promise<() => T>}
|
|
184
202
|
*/
|
|
185
203
|
export async function track_reactivity_loss(promise) {
|
|
204
|
+
unsave();
|
|
186
205
|
var previous_reactivity_loss_tracker = reactivity_loss_tracker;
|
|
187
206
|
// Ensure that unrelated reads after an async operation is kicked off don't cause false positives
|
|
188
207
|
queueMicrotask(() => {
|
|
@@ -269,6 +288,7 @@ export async function* for_await_track_reactivity_loss(iterable) {
|
|
|
269
288
|
}
|
|
270
289
|
|
|
271
290
|
export function unset_context(deactivate_batch = true) {
|
|
291
|
+
restored = false;
|
|
272
292
|
set_active_effect(null);
|
|
273
293
|
set_active_reaction(null);
|
|
274
294
|
set_component_context(null);
|
|
@@ -34,8 +34,10 @@ import {
|
|
|
34
34
|
ASYNC,
|
|
35
35
|
CONNECTED,
|
|
36
36
|
MANAGED_EFFECT,
|
|
37
|
-
DESTROYING
|
|
37
|
+
DESTROYING,
|
|
38
|
+
PAUSED
|
|
38
39
|
} from '#client/constants';
|
|
40
|
+
import { invoke_error_boundary } from '../error-handling.js';
|
|
39
41
|
import * as e from '../errors.js';
|
|
40
42
|
import { DEV } from 'esm-env';
|
|
41
43
|
import { define_property } from '../../shared/utils.js';
|
|
@@ -449,6 +451,11 @@ export function execute_effect_teardown(effect) {
|
|
|
449
451
|
set_active_reaction(null);
|
|
450
452
|
try {
|
|
451
453
|
teardown.call(null);
|
|
454
|
+
} catch (error) {
|
|
455
|
+
// Route teardown errors through the boundary system so that a live
|
|
456
|
+
// ancestor <svelte:boundary> can handle them. Boundaries that are
|
|
457
|
+
// themselves mid-teardown are skipped by invoke_error_boundary.
|
|
458
|
+
invoke_error_boundary(error, effect.parent);
|
|
452
459
|
} finally {
|
|
453
460
|
set_is_destroying_effect(previously_destroying_effect);
|
|
454
461
|
set_active_reaction(previous_reaction);
|
|
@@ -610,6 +617,7 @@ export function pause_effect(effect, callback, destroy = true) {
|
|
|
610
617
|
/** @type {TransitionManager[]} */
|
|
611
618
|
var transitions = [];
|
|
612
619
|
|
|
620
|
+
effect.f |= PAUSED;
|
|
613
621
|
pause_children(effect, transitions, true);
|
|
614
622
|
|
|
615
623
|
var fn = () => {
|
|
@@ -677,6 +685,7 @@ function pause_children(effect, transitions, local) {
|
|
|
677
685
|
* @param {Effect} effect
|
|
678
686
|
*/
|
|
679
687
|
export function resume_effect(effect) {
|
|
688
|
+
effect.f &= ~PAUSED;
|
|
680
689
|
resume_children(effect, true);
|
|
681
690
|
}
|
|
682
691
|
|
|
@@ -685,6 +694,10 @@ export function resume_effect(effect) {
|
|
|
685
694
|
* @param {boolean} local
|
|
686
695
|
*/
|
|
687
696
|
function resume_children(effect, local) {
|
|
697
|
+
// this subtree was paused for its own reasons (e.g. a block whose condition
|
|
698
|
+
// is still false) — its controller will resume or destroy it
|
|
699
|
+
if ((effect.f & PAUSED) !== 0) return;
|
|
700
|
+
|
|
688
701
|
if ((effect.f & INERT) === 0) return;
|
|
689
702
|
effect.f ^= INERT;
|
|
690
703
|
|
|
@@ -180,7 +180,13 @@ export function set(source, value, should_proxy = false) {
|
|
|
180
180
|
*/
|
|
181
181
|
export function internal_set(source, value, updated_during_traversal = null) {
|
|
182
182
|
if (!source.equals(value)) {
|
|
183
|
-
|
|
183
|
+
if (is_destroying_effect) {
|
|
184
|
+
old_values.set(source, value);
|
|
185
|
+
} else if (!old_values.has(source)) {
|
|
186
|
+
// only record the value from before the first write in this flush, otherwise a
|
|
187
|
+
// teardown would see the value from before whichever write happened to be last
|
|
188
|
+
old_values.set(source, source.v);
|
|
189
|
+
}
|
|
184
190
|
|
|
185
191
|
var batch = Batch.ensure();
|
|
186
192
|
batch.capture(source, value);
|
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
} from './dom/operations.js';
|
|
11
11
|
import { HYDRATION_END, HYDRATION_ERROR, HYDRATION_START } from '../../constants.js';
|
|
12
12
|
import { active_effect } from './runtime.js';
|
|
13
|
-
import { push, pop, component_context } from './context.js';
|
|
13
|
+
import { push, pop, component_context, mark_as_component } from './context.js';
|
|
14
14
|
import { component_root } from './reactivity/effects.js';
|
|
15
15
|
import { hydrate_node, hydrating, set_hydrate_node, set_hydrating } from './dom/hydration.js';
|
|
16
16
|
import { array_from } from '../shared/utils.js';
|
|
@@ -23,7 +23,7 @@ import * as w from './warnings.js';
|
|
|
23
23
|
import * as e from './errors.js';
|
|
24
24
|
import { assign_nodes } from './dom/template.js';
|
|
25
25
|
import { is_passive_event } from '../../utils.js';
|
|
26
|
-
import { COMMENT_NODE,
|
|
26
|
+
import { COMMENT_NODE, TEXT_CACHE } from './constants.js';
|
|
27
27
|
import { boundary } from './dom/blocks/boundary.js';
|
|
28
28
|
|
|
29
29
|
/**
|
|
@@ -193,7 +193,7 @@ function _mount(
|
|
|
193
193
|
|
|
194
194
|
should_intro = intro;
|
|
195
195
|
// @ts-expect-error the public typings are not what the actual function looks like
|
|
196
|
-
component = Component(anchor_node, props) ||
|
|
196
|
+
component = Component(anchor_node, props) || mark_as_component();
|
|
197
197
|
should_intro = true;
|
|
198
198
|
|
|
199
199
|
if (hydrating) {
|
|
@@ -323,11 +323,7 @@ export function unmount(component, options) {
|
|
|
323
323
|
}
|
|
324
324
|
|
|
325
325
|
if (DEV) {
|
|
326
|
-
|
|
327
|
-
w.state_proxy_unmount();
|
|
328
|
-
} else {
|
|
329
|
-
w.lifecycle_double_unmount();
|
|
330
|
-
}
|
|
326
|
+
w.lifecycle_double_unmount();
|
|
331
327
|
}
|
|
332
328
|
|
|
333
329
|
return Promise.resolve();
|
|
@@ -133,7 +133,7 @@ export function set_untracked_writes(value) {
|
|
|
133
133
|
**/
|
|
134
134
|
export let write_version = 1;
|
|
135
135
|
|
|
136
|
-
/** @type {number} Used to version each read of a source of derived to avoid duplicating
|
|
136
|
+
/** @type {number} Used to version each read of a source of derived to avoid duplicating dependencies inside a reaction */
|
|
137
137
|
let read_version = 0;
|
|
138
138
|
|
|
139
139
|
export let update_version = read_version;
|
|
@@ -258,37 +258,7 @@ export function update_reaction(reaction) {
|
|
|
258
258
|
var fn = /** @type {Function} */ (reaction.fn);
|
|
259
259
|
var result = fn();
|
|
260
260
|
reaction.f |= REACTION_RAN;
|
|
261
|
-
var deps = reaction
|
|
262
|
-
|
|
263
|
-
// Don't remove reactions during fork;
|
|
264
|
-
// they must remain for when fork is discarded
|
|
265
|
-
var is_fork = current_batch?.is_fork;
|
|
266
|
-
|
|
267
|
-
if (new_deps !== null) {
|
|
268
|
-
var i;
|
|
269
|
-
|
|
270
|
-
if (!is_fork) {
|
|
271
|
-
remove_reactions(reaction, skipped_deps);
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
if (deps !== null && skipped_deps > 0) {
|
|
275
|
-
deps.length = skipped_deps + new_deps.length;
|
|
276
|
-
for (i = 0; i < new_deps.length; i++) {
|
|
277
|
-
deps[skipped_deps + i] = new_deps[i];
|
|
278
|
-
}
|
|
279
|
-
} else {
|
|
280
|
-
reaction.deps = deps = new_deps;
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
if (effect_tracking() && (reaction.f & CONNECTED) !== 0) {
|
|
284
|
-
for (i = skipped_deps; i < deps.length; i++) {
|
|
285
|
-
(deps[i].reactions ??= []).push(reaction);
|
|
286
|
-
}
|
|
287
|
-
}
|
|
288
|
-
} else if (!is_fork && deps !== null && skipped_deps < deps.length) {
|
|
289
|
-
remove_reactions(reaction, skipped_deps);
|
|
290
|
-
deps.length = skipped_deps;
|
|
291
|
-
}
|
|
261
|
+
var deps = update_dependencies(reaction);
|
|
292
262
|
|
|
293
263
|
// If we're inside an effect and we have untracked writes, then we need to
|
|
294
264
|
// ensure that if any of those untracked writes result in re-invalidation
|
|
@@ -300,7 +270,7 @@ export function update_reaction(reaction) {
|
|
|
300
270
|
deps !== null &&
|
|
301
271
|
(reaction.f & (DERIVED | MAYBE_DIRTY | DIRTY)) === 0
|
|
302
272
|
) {
|
|
303
|
-
for (i = 0; i < /** @type {Source[]} */ (untracked_writes).length; i++) {
|
|
273
|
+
for (var i = 0; i < /** @type {Source[]} */ (untracked_writes).length; i++) {
|
|
304
274
|
schedule_possible_effect_self_invalidation(
|
|
305
275
|
untracked_writes[i],
|
|
306
276
|
/** @type {Effect} */ (reaction)
|
|
@@ -344,6 +314,9 @@ export function update_reaction(reaction) {
|
|
|
344
314
|
|
|
345
315
|
return result;
|
|
346
316
|
} catch (error) {
|
|
317
|
+
// still commit the deps read before the throw, otherwise deriveds connected by this run keep no reader and the reaction never re-runs when they change
|
|
318
|
+
update_dependencies(reaction);
|
|
319
|
+
|
|
347
320
|
return handle_error(error);
|
|
348
321
|
} finally {
|
|
349
322
|
reaction.f ^= REACTION_IS_UPDATING;
|
|
@@ -358,6 +331,45 @@ export function update_reaction(reaction) {
|
|
|
358
331
|
}
|
|
359
332
|
}
|
|
360
333
|
|
|
334
|
+
/**
|
|
335
|
+
* @param {Reaction} reaction
|
|
336
|
+
*/
|
|
337
|
+
function update_dependencies(reaction) {
|
|
338
|
+
var deps = reaction.deps;
|
|
339
|
+
|
|
340
|
+
// Don't remove reactions during fork;
|
|
341
|
+
// they must remain for when fork is discarded
|
|
342
|
+
var is_fork = current_batch?.is_fork;
|
|
343
|
+
|
|
344
|
+
if (new_deps !== null) {
|
|
345
|
+
var i;
|
|
346
|
+
|
|
347
|
+
if (!is_fork) {
|
|
348
|
+
remove_reactions(reaction, skipped_deps);
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
if (deps !== null && skipped_deps > 0) {
|
|
352
|
+
deps.length = skipped_deps + new_deps.length;
|
|
353
|
+
for (i = 0; i < new_deps.length; i++) {
|
|
354
|
+
deps[skipped_deps + i] = new_deps[i];
|
|
355
|
+
}
|
|
356
|
+
} else {
|
|
357
|
+
reaction.deps = deps = new_deps;
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
if (effect_tracking() && (reaction.f & CONNECTED) !== 0) {
|
|
361
|
+
for (i = skipped_deps; i < deps.length; i++) {
|
|
362
|
+
(deps[i].reactions ??= []).push(reaction);
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
} else if (!is_fork && deps !== null && skipped_deps < deps.length) {
|
|
366
|
+
remove_reactions(reaction, skipped_deps);
|
|
367
|
+
deps.length = skipped_deps;
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
return deps;
|
|
371
|
+
}
|
|
372
|
+
|
|
361
373
|
/**
|
|
362
374
|
* @template V
|
|
363
375
|
* @param {Reaction} signal
|
|
@@ -247,17 +247,6 @@ export function state_proxy_equality_mismatch(operator) {
|
|
|
247
247
|
}
|
|
248
248
|
}
|
|
249
249
|
|
|
250
|
-
/**
|
|
251
|
-
* Tried to unmount a state proxy, rather than a component
|
|
252
|
-
*/
|
|
253
|
-
export function state_proxy_unmount() {
|
|
254
|
-
if (DEV) {
|
|
255
|
-
console.warn(`%c[svelte] state_proxy_unmount\n%cTried to unmount a state proxy, rather than a component\nhttps://svelte.dev/e/state_proxy_unmount`, bold, normal);
|
|
256
|
-
} else {
|
|
257
|
-
console.warn(`https://svelte.dev/e/state_proxy_unmount`);
|
|
258
|
-
}
|
|
259
|
-
}
|
|
260
|
-
|
|
261
250
|
/**
|
|
262
251
|
* A `<svelte:boundary>` `reset` function only resets the boundary the first time it is called
|
|
263
252
|
*/
|
|
@@ -1,13 +1,12 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ssr_context } from './context.js';
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
let
|
|
3
|
+
export function getAbortSignal() {
|
|
4
|
+
let context = ssr_context;
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
}
|
|
6
|
+
while (context !== null) {
|
|
7
|
+
if (context.r !== null) return context.r.global.get_abort_signal();
|
|
8
|
+
context = context.p;
|
|
9
|
+
}
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
return (controller ??= new AbortController()).signal;
|
|
11
|
+
return new AbortController().signal;
|
|
13
12
|
}
|