svelte 5.57.1 → 5.57.2
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/errors.js +10 -0
- package/src/compiler/migrate/index.js +15 -4
- package/src/compiler/phases/1-parse/state/tag.js +2 -0
- package/src/compiler/phases/2-analyze/visitors/LetDirective.js +22 -0
- package/src/compiler/phases/2-analyze/visitors/shared/a11y/index.js +2 -2
- package/src/compiler/phases/3-transform/client/visitors/AwaitExpression.js +2 -1
- package/src/compiler/phases/3-transform/client/visitors/shared/events.js +3 -2
- package/src/compiler/phases/scope.js +8 -0
- package/src/compiler/print/index.js +3 -1
- package/src/index-client.js +1 -1
- package/src/internal/client/dev/tracing.js +3 -1
- package/src/internal/client/dom/blocks/boundary.js +39 -8
- package/src/internal/client/dom/blocks/each.js +8 -6
- package/src/internal/client/dom/blocks/svelte-element.js +3 -1
- package/src/internal/client/dom/css.js +1 -1
- package/src/internal/client/dom/elements/attributes.js +168 -148
- package/src/internal/client/dom/elements/bindings/document.js +3 -2
- package/src/internal/client/dom/elements/transitions.js +3 -3
- package/src/internal/client/error-handling.js +5 -1
- package/src/internal/client/reactivity/async.js +5 -0
- package/src/internal/client/reactivity/batch.js +12 -4
- package/src/internal/client/reactivity/sources.js +3 -3
- package/src/internal/client/runtime.js +13 -16
- package/src/internal/server/index.js +1 -1
- package/src/reactivity/date.js +2 -2
- package/src/reactivity/url-search-params.js +1 -1
- package/src/version.js +1 -1
- package/types/index.d.ts.map +1 -1
|
@@ -298,182 +298,202 @@ function set_attributes(
|
|
|
298
298
|
var is_option_element = element.nodeName === OPTION_TAG;
|
|
299
299
|
var is_select_element = element.nodeName === SELECT_TAG;
|
|
300
300
|
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
next[key]
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
if (next.class) {
|
|
309
|
-
next.class = clsx(next.class);
|
|
310
|
-
} else if (css_hash || next[CLASS]) {
|
|
311
|
-
next.class = null; /* force call to set_class() */
|
|
312
|
-
}
|
|
313
|
-
|
|
314
|
-
if (next[STYLE]) {
|
|
315
|
-
next.style ??= null; /* force call to set_style() */
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
var setters = get_setters(element);
|
|
319
|
-
|
|
320
|
-
if (element.nodeName === INPUT_TAG && 'type' in next && ('value' in next || '__value' in next)) {
|
|
321
|
-
var type = next.type;
|
|
322
|
-
|
|
323
|
-
if (type !== current.type || (type === undefined && element.hasAttribute('type'))) {
|
|
324
|
-
current.type = type;
|
|
325
|
-
set_attribute(element, 'type', type, skip_warning);
|
|
301
|
+
try {
|
|
302
|
+
for (var key in prev) {
|
|
303
|
+
// don't null our internal $$onX listeners
|
|
304
|
+
if (!(key in next) && key[0] + key[1] !== '$$') {
|
|
305
|
+
next[key] = null;
|
|
306
|
+
}
|
|
326
307
|
}
|
|
327
|
-
}
|
|
328
308
|
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
// Up here because we want to do this for the initial value, too, even if it's undefined,
|
|
335
|
-
// and this wouldn't be reached in case of undefined because of the equality check below
|
|
336
|
-
if (is_option_element && key === 'value' && value == null) {
|
|
337
|
-
// The <option> element is a special case because removing the value attribute means
|
|
338
|
-
// the value is set to the text content of the option element, and setting the value
|
|
339
|
-
// to null or undefined means the value is set to the string "null" or "undefined".
|
|
340
|
-
// To align with how we handle this case in non-spread-scenarios, this logic is needed.
|
|
341
|
-
// There's a super-edge-case bug here that is left in in favor of smaller code size:
|
|
342
|
-
// Because of the "set missing props to null" logic above, we can't differentiate
|
|
343
|
-
// between a missing value and an explicitly set value of null or undefined. That means
|
|
344
|
-
// that once set, the value attribute of an <option> element can't be removed. This is
|
|
345
|
-
// a very rare edge case, and removing the attribute altogether isn't possible either
|
|
346
|
-
// for the <option value={undefined}> case, so we're not losing any functionality here.
|
|
347
|
-
// @ts-ignore
|
|
348
|
-
element.value = element.__value = '';
|
|
349
|
-
current[key] = value;
|
|
350
|
-
continue;
|
|
309
|
+
if (next.class) {
|
|
310
|
+
next.class = clsx(next.class);
|
|
311
|
+
} else if (css_hash || next[CLASS]) {
|
|
312
|
+
next.class = null; /* force call to set_class() */
|
|
351
313
|
}
|
|
352
314
|
|
|
353
|
-
if (
|
|
354
|
-
|
|
355
|
-
set_class(element, is_html, value, css_hash, prev?.[CLASS], next[CLASS]);
|
|
356
|
-
current[key] = value;
|
|
357
|
-
current[CLASS] = next[CLASS];
|
|
358
|
-
continue;
|
|
315
|
+
if (next[STYLE]) {
|
|
316
|
+
next.style ??= null; /* force call to set_style() */
|
|
359
317
|
}
|
|
360
318
|
|
|
361
|
-
|
|
362
|
-
set_style(element, value, prev?.[STYLE], next[STYLE]);
|
|
363
|
-
current[key] = value;
|
|
364
|
-
current[STYLE] = next[STYLE];
|
|
365
|
-
continue;
|
|
366
|
-
}
|
|
319
|
+
var setters = get_setters(element);
|
|
367
320
|
|
|
368
|
-
|
|
321
|
+
if (
|
|
322
|
+
element.nodeName === INPUT_TAG &&
|
|
323
|
+
'type' in next &&
|
|
324
|
+
('value' in next || '__value' in next)
|
|
325
|
+
) {
|
|
326
|
+
var type = next.type;
|
|
369
327
|
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
328
|
+
if (type !== current.type || (type === undefined && element.hasAttribute('type'))) {
|
|
329
|
+
current.type = type;
|
|
330
|
+
set_attribute(element, 'type', type, skip_warning);
|
|
331
|
+
}
|
|
373
332
|
}
|
|
374
333
|
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
334
|
+
// since key is captured we use const
|
|
335
|
+
for (const key in next) {
|
|
336
|
+
// let instead of var because referenced in a closure
|
|
337
|
+
let value = next[key];
|
|
338
|
+
|
|
339
|
+
// Up here because we want to do this for the initial value, too, even if it's undefined,
|
|
340
|
+
// and this wouldn't be reached in case of undefined because of the equality check below
|
|
341
|
+
if (is_option_element && key === 'value' && value == null) {
|
|
342
|
+
// The <option> element is a special case because removing the value attribute means
|
|
343
|
+
// the value is set to the text content of the option element, and setting the value
|
|
344
|
+
// to null or undefined means the value is set to the string "null" or "undefined".
|
|
345
|
+
// To align with how we handle this case in non-spread-scenarios, this logic is needed.
|
|
346
|
+
// There's a super-edge-case bug here that is left in in favor of smaller code size:
|
|
347
|
+
// Because of the "set missing props to null" logic above, we can't differentiate
|
|
348
|
+
// between a missing value and an explicitly set value of null or undefined. That means
|
|
349
|
+
// that once set, the value attribute of an <option> element can't be removed. This is
|
|
350
|
+
// a very rare edge case, and removing the attribute altogether isn't possible either
|
|
351
|
+
// for the <option value={undefined}> case, so we're not losing any functionality here.
|
|
352
|
+
// @ts-ignore
|
|
353
|
+
element.value = element.__value = '';
|
|
354
|
+
current[key] = value;
|
|
355
|
+
continue;
|
|
356
|
+
}
|
|
379
357
|
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
358
|
+
if (key === 'class') {
|
|
359
|
+
var is_html = element.namespaceURI === 'http://www.w3.org/1999/xhtml';
|
|
360
|
+
set_class(element, is_html, value, css_hash, prev?.[CLASS], next[CLASS]);
|
|
361
|
+
current[key] = value;
|
|
362
|
+
current[CLASS] = next[CLASS];
|
|
363
|
+
continue;
|
|
364
|
+
}
|
|
386
365
|
|
|
387
|
-
if (
|
|
388
|
-
|
|
389
|
-
|
|
366
|
+
if (key === 'style') {
|
|
367
|
+
set_style(element, value, prev?.[STYLE], next[STYLE]);
|
|
368
|
+
current[key] = value;
|
|
369
|
+
current[STYLE] = next[STYLE];
|
|
370
|
+
continue;
|
|
390
371
|
}
|
|
391
372
|
|
|
392
|
-
|
|
393
|
-
// Listening to same event but different handler -> our handle function below takes care of this
|
|
394
|
-
// If we were to remove and add listeners in this case, it could happen that the event is "swallowed"
|
|
395
|
-
// (the browser seems to not know yet that a new one exists now) and doesn't reach the handler
|
|
396
|
-
// https://github.com/sveltejs/svelte/issues/11903
|
|
397
|
-
if (value != null) continue;
|
|
373
|
+
var prev_value = current[key];
|
|
398
374
|
|
|
399
|
-
|
|
400
|
-
|
|
375
|
+
// Skip if value is unchanged, unless it's `undefined` and the element still has the attribute
|
|
376
|
+
if (value === prev_value && !(value === undefined && element.hasAttribute(key))) {
|
|
377
|
+
continue;
|
|
401
378
|
}
|
|
402
379
|
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
380
|
+
current[key] = value;
|
|
381
|
+
|
|
382
|
+
var prefix = key[0] + key[1]; // this is faster than key.slice(0, 2)
|
|
383
|
+
if (prefix === '$$') continue;
|
|
384
|
+
|
|
385
|
+
if (prefix === 'on') {
|
|
386
|
+
/** @type {{ capture?: true }} */
|
|
387
|
+
const opts = {};
|
|
388
|
+
const event_handle_key = '$$' + key;
|
|
389
|
+
let event_name = key.slice(2);
|
|
390
|
+
var is_delegated = can_delegate_event(event_name);
|
|
391
|
+
|
|
392
|
+
if (is_capture_event(event_name)) {
|
|
393
|
+
event_name = event_name.slice(0, -7);
|
|
394
|
+
opts.capture = true;
|
|
413
395
|
}
|
|
414
396
|
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
autofocus(/** @type {HTMLElement} */ (element), Boolean(value));
|
|
422
|
-
} else if (!is_custom_element && (key === '__value' || (key === 'value' && value != null))) {
|
|
423
|
-
// @ts-ignore We're not running this for custom elements because __value is actually
|
|
424
|
-
// how Lit stores the current value on the element, and messing with that would break things.
|
|
425
|
-
element.value = element.__value = value;
|
|
426
|
-
} else if (key === 'selected' && is_option_element) {
|
|
427
|
-
set_selected(/** @type {HTMLOptionElement} */ (element), value);
|
|
428
|
-
} else {
|
|
429
|
-
var name = key;
|
|
430
|
-
if (!preserve_attribute_case) {
|
|
431
|
-
name = normalize_attribute(name);
|
|
432
|
-
}
|
|
397
|
+
if (!is_delegated && prev_value) {
|
|
398
|
+
// Listening to same event but different handler -> our handle function below takes care of this
|
|
399
|
+
// If we were to remove and add listeners in this case, it could happen that the event is "swallowed"
|
|
400
|
+
// (the browser seems to not know yet that a new one exists now) and doesn't reach the handler
|
|
401
|
+
// https://github.com/sveltejs/svelte/issues/11903
|
|
402
|
+
if (value != null) continue;
|
|
433
403
|
|
|
434
|
-
|
|
404
|
+
element.removeEventListener(event_name, current[event_handle_key], opts);
|
|
405
|
+
current[event_handle_key] = null;
|
|
406
|
+
}
|
|
435
407
|
|
|
436
|
-
|
|
437
|
-
|
|
408
|
+
if (is_delegated) {
|
|
409
|
+
delegated(event_name, element, value);
|
|
410
|
+
delegate([event_name]);
|
|
411
|
+
} else if (value != null) {
|
|
412
|
+
/**
|
|
413
|
+
* @this {any}
|
|
414
|
+
* @param {Event} evt
|
|
415
|
+
*/
|
|
416
|
+
function handle(evt) {
|
|
417
|
+
current[key].call(this, evt);
|
|
418
|
+
}
|
|
438
419
|
|
|
439
|
-
|
|
440
|
-
|
|
420
|
+
current[event_handle_key] = create_event(event_name, element, handle, opts);
|
|
421
|
+
}
|
|
422
|
+
} else if (key === 'style') {
|
|
423
|
+
// avoid using the setter
|
|
424
|
+
set_attribute(element, key, value);
|
|
425
|
+
} else if (key === 'autofocus') {
|
|
426
|
+
autofocus(/** @type {HTMLElement} */ (element), Boolean(value));
|
|
427
|
+
} else if (!is_custom_element && (key === '__value' || (key === 'value' && value != null))) {
|
|
428
|
+
// @ts-ignore We're not running this for custom elements because __value is actually
|
|
429
|
+
// how Lit stores the current value on the element, and messing with that would break things.
|
|
430
|
+
element.__value = value;
|
|
431
|
+
// we don't set the value if it hasn't changed. This supports invalid number inputs like `1e` because
|
|
432
|
+
// 1. user types 1e
|
|
433
|
+
// 2. the state is updated reading e.target.value which is ''
|
|
434
|
+
// 3. the spreaded value is ''
|
|
435
|
+
// 4. updating input.value would thus, clear the user value
|
|
436
|
+
if (
|
|
437
|
+
prev_value == null ||
|
|
438
|
+
// @ts-ignore
|
|
439
|
+
element.value !== value ||
|
|
440
|
+
(value === 0 && element.nodeName === PROGRESS_TAG)
|
|
441
|
+
) {
|
|
442
|
+
// @ts-ignore
|
|
443
|
+
element.value = value;
|
|
444
|
+
}
|
|
445
|
+
} else if (key === 'selected' && is_option_element) {
|
|
446
|
+
set_selected(/** @type {HTMLOptionElement} */ (element), value);
|
|
447
|
+
} else {
|
|
448
|
+
var name = key;
|
|
449
|
+
if (!preserve_attribute_case) {
|
|
450
|
+
name = normalize_attribute(name);
|
|
451
|
+
}
|
|
441
452
|
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
453
|
+
var is_default = name === 'defaultValue' || name === 'defaultChecked';
|
|
454
|
+
|
|
455
|
+
// A select's default value is represented by selected options, not a property.
|
|
456
|
+
if (is_select_element && name === 'defaultValue') continue;
|
|
457
|
+
|
|
458
|
+
if (value == null && !is_custom_element && !is_default) {
|
|
459
|
+
attributes[key] = null;
|
|
460
|
+
|
|
461
|
+
if (name === 'value' || name === 'checked') {
|
|
462
|
+
// removing value/checked also removes defaultValue/defaultChecked — preserve
|
|
463
|
+
let input = /** @type {HTMLInputElement} */ (element);
|
|
464
|
+
const use_default = prev === undefined;
|
|
465
|
+
if (name === 'value') {
|
|
466
|
+
let previous = input.defaultValue;
|
|
467
|
+
input.removeAttribute(name);
|
|
468
|
+
input.defaultValue = previous;
|
|
469
|
+
// @ts-ignore
|
|
470
|
+
input.value = input.__value = use_default ? previous : null;
|
|
471
|
+
} else {
|
|
472
|
+
let previous = input.defaultChecked;
|
|
473
|
+
input.removeAttribute(name);
|
|
474
|
+
input.defaultChecked = previous;
|
|
475
|
+
input.checked = use_default ? previous : false;
|
|
476
|
+
}
|
|
452
477
|
} else {
|
|
453
|
-
|
|
454
|
-
input.removeAttribute(name);
|
|
455
|
-
input.defaultChecked = previous;
|
|
456
|
-
input.checked = use_default ? previous : false;
|
|
478
|
+
element.removeAttribute(key);
|
|
457
479
|
}
|
|
458
|
-
} else
|
|
459
|
-
|
|
480
|
+
} else if (
|
|
481
|
+
is_default ||
|
|
482
|
+
((is_custom_element || typeof value !== 'string') && setters.has(name))
|
|
483
|
+
) {
|
|
484
|
+
// @ts-ignore
|
|
485
|
+
element[name] = value;
|
|
486
|
+
// remove it from attributes's cache
|
|
487
|
+
if (name in attributes) attributes[name] = UNINITIALIZED;
|
|
488
|
+
} else if (typeof value !== 'function') {
|
|
489
|
+
set_attribute(element, name, value, skip_warning);
|
|
460
490
|
}
|
|
461
|
-
} else if (
|
|
462
|
-
is_default ||
|
|
463
|
-
((is_custom_element || typeof value !== 'string') && setters.has(name))
|
|
464
|
-
) {
|
|
465
|
-
// @ts-ignore
|
|
466
|
-
element[name] = value;
|
|
467
|
-
// remove it from attributes's cache
|
|
468
|
-
if (name in attributes) attributes[name] = UNINITIALIZED;
|
|
469
|
-
} else if (typeof value !== 'function') {
|
|
470
|
-
set_attribute(element, name, value, skip_warning);
|
|
471
491
|
}
|
|
472
492
|
}
|
|
473
|
-
}
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
493
|
+
} finally {
|
|
494
|
+
if (is_hydrating_custom_element) {
|
|
495
|
+
set_hydrating(true);
|
|
496
|
+
}
|
|
477
497
|
}
|
|
478
498
|
|
|
479
499
|
return current;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { listen } from './shared.js';
|
|
1
|
+
import { listen, without_reactive_context } from './shared.js';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* @param {(activeElement: Element | null) => void} update
|
|
@@ -12,6 +12,7 @@ export function bind_active_element(update) {
|
|
|
12
12
|
return;
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
// Removing the focused element fires `focusout` while an effect is running
|
|
16
|
+
without_reactive_context(() => update(document.activeElement));
|
|
16
17
|
});
|
|
17
18
|
}
|
|
@@ -359,9 +359,9 @@ function animate(element, options, counterpart, t2, on_begin, on_finish) {
|
|
|
359
359
|
aborted = true;
|
|
360
360
|
a?.abort();
|
|
361
361
|
},
|
|
362
|
-
deactivate: () => a
|
|
363
|
-
reset: () => a
|
|
364
|
-
t: () => a
|
|
362
|
+
deactivate: () => a?.deactivate(),
|
|
363
|
+
reset: () => a?.reset(),
|
|
364
|
+
t: () => a?.t() ?? 1 - t2
|
|
365
365
|
};
|
|
366
366
|
}
|
|
367
367
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/** @import { Derived, Effect } from '#client' */
|
|
2
2
|
/** @import { Boundary } from './dom/blocks/boundary.js' */
|
|
3
3
|
import { DEV } from 'esm-env';
|
|
4
|
-
import { FILENAME } from '../../constants.js';
|
|
4
|
+
import { FILENAME, HYDRATION_ERROR } from '../../constants.js';
|
|
5
5
|
import { is_firefox } from './dom/operations.js';
|
|
6
6
|
import {
|
|
7
7
|
ERROR_VALUE,
|
|
@@ -52,6 +52,10 @@ export function handle_error(error) {
|
|
|
52
52
|
* @param {Effect | null} effect
|
|
53
53
|
*/
|
|
54
54
|
export function invoke_error_boundary(error, effect) {
|
|
55
|
+
if (error === HYDRATION_ERROR) {
|
|
56
|
+
throw error;
|
|
57
|
+
}
|
|
58
|
+
|
|
55
59
|
if (effect !== null && (effect.f & DESTROYED) !== 0) {
|
|
56
60
|
return;
|
|
57
61
|
}
|
|
@@ -103,6 +103,11 @@ export function flatten(blockers, sync, async, fn) {
|
|
|
103
103
|
|
|
104
104
|
if (blocker_promise) {
|
|
105
105
|
blocker_promise.then(() => {
|
|
106
|
+
if ((parent.f & DESTROYED) !== 0) {
|
|
107
|
+
decrement_pending();
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
|
|
106
111
|
restore();
|
|
107
112
|
run();
|
|
108
113
|
unset_context();
|
|
@@ -1032,15 +1032,15 @@ export class Batch {
|
|
|
1032
1032
|
*/
|
|
1033
1033
|
export function flushSync(fn) {
|
|
1034
1034
|
var was_flushing_sync = is_flushing_sync;
|
|
1035
|
+
var prev_previous_batch = previous_batch;
|
|
1036
|
+
previous_batch = null;
|
|
1035
1037
|
is_flushing_sync = true;
|
|
1036
1038
|
|
|
1037
1039
|
try {
|
|
1038
1040
|
var result;
|
|
1039
1041
|
|
|
1040
1042
|
if (fn) {
|
|
1041
|
-
|
|
1042
|
-
current_batch.flush();
|
|
1043
|
-
}
|
|
1043
|
+
flushSync(); // flush anything pending through the while loop below
|
|
1044
1044
|
|
|
1045
1045
|
result = fn();
|
|
1046
1046
|
}
|
|
@@ -1056,6 +1056,7 @@ export function flushSync(fn) {
|
|
|
1056
1056
|
}
|
|
1057
1057
|
} finally {
|
|
1058
1058
|
is_flushing_sync = was_flushing_sync;
|
|
1059
|
+
previous_batch = prev_previous_batch;
|
|
1059
1060
|
}
|
|
1060
1061
|
}
|
|
1061
1062
|
|
|
@@ -1295,6 +1296,10 @@ export function eager(fn) {
|
|
|
1295
1296
|
let version = version_map.get(parent) ?? source(0);
|
|
1296
1297
|
version_map.set(parent, version);
|
|
1297
1298
|
|
|
1299
|
+
if (DEV) {
|
|
1300
|
+
version.label ??= '$state.eager version';
|
|
1301
|
+
}
|
|
1302
|
+
|
|
1298
1303
|
teardown(() => {
|
|
1299
1304
|
if (parent.f & DESTROYING) version_map.delete(parent);
|
|
1300
1305
|
});
|
|
@@ -1402,6 +1407,8 @@ export function fork(fn) {
|
|
|
1402
1407
|
e.fork_timing();
|
|
1403
1408
|
}
|
|
1404
1409
|
|
|
1410
|
+
flushSync();
|
|
1411
|
+
|
|
1405
1412
|
var batch = Batch.ensure();
|
|
1406
1413
|
batch.is_fork = true;
|
|
1407
1414
|
batch_values = new Map();
|
|
@@ -1409,7 +1416,8 @@ export function fork(fn) {
|
|
|
1409
1416
|
var committed = false;
|
|
1410
1417
|
var settled = batch.settled();
|
|
1411
1418
|
|
|
1412
|
-
|
|
1419
|
+
fn();
|
|
1420
|
+
flushSync();
|
|
1413
1421
|
|
|
1414
1422
|
return {
|
|
1415
1423
|
commit: async () => {
|
|
@@ -46,7 +46,7 @@ import { set_signal_status, update_derived_status } from './status.js';
|
|
|
46
46
|
/** @type {Set<Effect>} */
|
|
47
47
|
export let eager_effects = new Set();
|
|
48
48
|
|
|
49
|
-
/** @type {Map<
|
|
49
|
+
/** @type {Map<Value, any>} */
|
|
50
50
|
export const old_values = new Map();
|
|
51
51
|
|
|
52
52
|
/**
|
|
@@ -141,7 +141,7 @@ export function mutate(source, value) {
|
|
|
141
141
|
|
|
142
142
|
/**
|
|
143
143
|
* @template V
|
|
144
|
-
* @param {
|
|
144
|
+
* @param {Value<V>} source
|
|
145
145
|
* @param {V} value
|
|
146
146
|
* @param {boolean} [should_proxy]
|
|
147
147
|
* @returns {V}
|
|
@@ -181,7 +181,7 @@ var count_deps = 0;
|
|
|
181
181
|
|
|
182
182
|
/**
|
|
183
183
|
* @template V
|
|
184
|
-
* @param {
|
|
184
|
+
* @param {Value<V>} source
|
|
185
185
|
* @param {V} value
|
|
186
186
|
* @param {Effect[] | null} [updated_during_traversal]
|
|
187
187
|
* @returns {V}
|
|
@@ -60,11 +60,6 @@ import { without_reactive_context } from './dom/elements/bindings/shared.js';
|
|
|
60
60
|
import { set_signal_status, update_derived_status } from './reactivity/status.js';
|
|
61
61
|
import * as w from './warnings.js';
|
|
62
62
|
|
|
63
|
-
/**
|
|
64
|
-
* True if updating in an effect context that is reactive (i.e. not branch/root effects)
|
|
65
|
-
*/
|
|
66
|
-
let is_updating_effect = false;
|
|
67
|
-
|
|
68
63
|
export let is_destroying_effect = false;
|
|
69
64
|
|
|
70
65
|
/** @param {boolean} value */
|
|
@@ -93,7 +88,7 @@ export function set_active_effect(effect) {
|
|
|
93
88
|
/**
|
|
94
89
|
* When sources are created within a reaction, reading and writing
|
|
95
90
|
* them within that reaction should not cause a re-run
|
|
96
|
-
* @type {null | Set<
|
|
91
|
+
* @type {null | Set<Value>}
|
|
97
92
|
*/
|
|
98
93
|
export let current_sources = null;
|
|
99
94
|
|
|
@@ -121,11 +116,11 @@ export let skipped_deps = 0;
|
|
|
121
116
|
/**
|
|
122
117
|
* Tracks writes that the effect it's executed in doesn't listen to yet,
|
|
123
118
|
* so that the dependency can be added to the effect later on if it then reads it
|
|
124
|
-
* @type {null |
|
|
119
|
+
* @type {null | Value[]}
|
|
125
120
|
*/
|
|
126
121
|
export let untracked_writes = null;
|
|
127
122
|
|
|
128
|
-
/** @param {null |
|
|
123
|
+
/** @param {null | Value[]} value */
|
|
129
124
|
export function set_untracked_writes(value) {
|
|
130
125
|
untracked_writes = value;
|
|
131
126
|
}
|
|
@@ -410,7 +405,7 @@ function remove_reaction(signal, dependency) {
|
|
|
410
405
|
// In a fork it's possible that a derived is executed and gets reactions, then commits, but is
|
|
411
406
|
// never re-executed. This is possible when the derived is only executed once in the context
|
|
412
407
|
// of a new branch which happens before fork.commit() runs. In this case, the derived still has
|
|
413
|
-
// UNINITIALIZED as its value, and then when it's
|
|
408
|
+
// UNINITIALIZED as its value, and then when it's losing its reactions we need to ensure it stays
|
|
414
409
|
// DIRTY so it is reexecuted once someone wants its value again.
|
|
415
410
|
if (derived.v !== UNINITIALIZED) {
|
|
416
411
|
update_derived_status(derived);
|
|
@@ -462,10 +457,8 @@ export function update_effect(effect) {
|
|
|
462
457
|
set_signal_status(effect, CLEAN);
|
|
463
458
|
|
|
464
459
|
var previous_effect = active_effect;
|
|
465
|
-
var was_updating_effect = is_updating_effect;
|
|
466
460
|
|
|
467
461
|
active_effect = effect;
|
|
468
|
-
is_updating_effect = (flags & (BRANCH_EFFECT | ROOT_EFFECT)) === 0; // Branch/root effects are not reactive contexts
|
|
469
462
|
|
|
470
463
|
if (DEV) {
|
|
471
464
|
var previous_component_fn = dev_current_component_function;
|
|
@@ -498,7 +491,6 @@ export function update_effect(effect) {
|
|
|
498
491
|
}
|
|
499
492
|
}
|
|
500
493
|
} finally {
|
|
501
|
-
is_updating_effect = was_updating_effect;
|
|
502
494
|
active_effect = previous_effect;
|
|
503
495
|
|
|
504
496
|
if (DEV) {
|
|
@@ -680,13 +672,12 @@ export function get(signal) {
|
|
|
680
672
|
return value;
|
|
681
673
|
}
|
|
682
674
|
|
|
683
|
-
// connect disconnected deriveds
|
|
684
|
-
// or inside another derived that is already connected
|
|
675
|
+
// connect disconnected deriveds when reading them inside a connected reaction
|
|
685
676
|
var should_connect =
|
|
686
677
|
(derived.f & CONNECTED) === 0 &&
|
|
687
678
|
!untracking &&
|
|
688
679
|
active_reaction !== null &&
|
|
689
|
-
(
|
|
680
|
+
(active_reaction.f & CONNECTED) !== 0;
|
|
690
681
|
|
|
691
682
|
var is_new = (derived.f & REACTION_RAN) === 0;
|
|
692
683
|
|
|
@@ -728,7 +719,13 @@ function reconnect(derived) {
|
|
|
728
719
|
if (derived.deps === null) return;
|
|
729
720
|
|
|
730
721
|
for (const dep of derived.deps) {
|
|
731
|
-
|
|
722
|
+
var reactions = dep.reactions;
|
|
723
|
+
|
|
724
|
+
if (reactions === null) {
|
|
725
|
+
dep.reactions = [derived];
|
|
726
|
+
} else if (!includes.call(reactions, derived)) {
|
|
727
|
+
reactions.push(derived);
|
|
728
|
+
}
|
|
732
729
|
|
|
733
730
|
if ((dep.f & DERIVED) !== 0 && (dep.f & CONNECTED) === 0) {
|
|
734
731
|
unfreeze_derived_effects(/** @type {Derived} */ (dep));
|
|
@@ -168,7 +168,7 @@ export function attributes(attrs, css_hash, classes, styles, flags = 0) {
|
|
|
168
168
|
// value/checked takes precedence over defaultValue/defaultChecked
|
|
169
169
|
name = name === 'defaultvalue' ? 'value' : 'checked';
|
|
170
170
|
if (name in attrs) continue;
|
|
171
|
-
// We're checking prior entries
|
|
171
|
+
// We're checking prior entries as well because "name in attrs" is not enough as the attributes may have different casing
|
|
172
172
|
for (let j = 0; j < names.length; j++) {
|
|
173
173
|
if (names[j].toLowerCase() === name) continue outer;
|
|
174
174
|
}
|
package/src/reactivity/date.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/** @import {
|
|
1
|
+
/** @import { Derived } from '#client' */
|
|
2
2
|
import { derived } from '../internal/client/index.js';
|
|
3
3
|
import { set, state } from '../internal/client/reactivity/sources.js';
|
|
4
4
|
import { tag } from '../internal/client/dev/tracing.js';
|
|
@@ -42,7 +42,7 @@ var inited = false;
|
|
|
42
42
|
export class SvelteDate extends Date {
|
|
43
43
|
#time = state(super.getTime());
|
|
44
44
|
|
|
45
|
-
/** @type {Map<keyof Date,
|
|
45
|
+
/** @type {Map<keyof Date, Derived<unknown>>} */
|
|
46
46
|
#deriveds = new Map();
|
|
47
47
|
|
|
48
48
|
#reaction = active_reaction;
|
|
@@ -42,7 +42,7 @@ export class SvelteURLSearchParams extends URLSearchParams {
|
|
|
42
42
|
if (!this.#url || this.#updating) return;
|
|
43
43
|
this.#updating = true;
|
|
44
44
|
|
|
45
|
-
const search =
|
|
45
|
+
const search = super.toString();
|
|
46
46
|
this.#url.search = search && `?${search}`;
|
|
47
47
|
|
|
48
48
|
this.#updating = false;
|
package/src/version.js
CHANGED