mirror of https://github.com/sveltejs/svelte
commit
0af2ad75b1
@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
'svelte': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
fix: prevent untracked derived reads from retaining disconnected dependencies
|
||||||
@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
'svelte': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
fix: restore hydration state when custom element attribute updates throw
|
||||||
@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
'svelte': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
fix: flush anything pending before invoking flushSync callback function
|
||||||
@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
'svelte': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
fix: preserve location information for `await` wrappers
|
||||||
@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
'svelte': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
fix: keep a reactive assignment with no dependencies when `migrate` cannot turn it into a declaration
|
||||||
@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
'svelte': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
fix: don't hang `migrate` on a declaration that shares a line with its script tag
|
||||||
@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
'svelte': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
fix: don't warn about a redundant `link` role on `<area>` elements without an `href`
|
||||||
@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
'svelte': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
fix: read batch-local array on each-block commit
|
||||||
@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
'svelte': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
fix: error at compile time when a declaration in a snippet redeclares one of its parameters
|
||||||
@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
'svelte': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
fix: error when using `let:` directives on a component with a `children` snippet
|
||||||
@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
'svelte': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
fix: ignore stale boundary reset callbacks
|
||||||
@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
'svelte': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
fix: handle deferred transitions aborted before initialization
|
||||||
@ -0,0 +1,10 @@
|
|||||||
|
import { test } from '../../test';
|
||||||
|
|
||||||
|
export default test({
|
||||||
|
error: {
|
||||||
|
code: 'let_directive_snippet_conflict',
|
||||||
|
message:
|
||||||
|
'Cannot use `let:` directives on a component that has a `children` snippet. Use snippet parameters instead (e.g. `{#snippet children({ item: x })}`)',
|
||||||
|
position: [62, 74]
|
||||||
|
}
|
||||||
|
});
|
||||||
@ -0,0 +1,7 @@
|
|||||||
|
<script>
|
||||||
|
import Child from './irrelevant';
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<Child let:item={x}>
|
||||||
|
{#snippet children()}{x}{/snippet}
|
||||||
|
</Child>
|
||||||
@ -0,0 +1,10 @@
|
|||||||
|
import { test } from '../../test';
|
||||||
|
|
||||||
|
export default test({
|
||||||
|
error: {
|
||||||
|
code: 'let_directive_snippet_conflict',
|
||||||
|
message:
|
||||||
|
'Cannot use `let:` directives on a component that has a `children` snippet. Use snippet parameters instead (e.g. `{#snippet children({ value })}`)',
|
||||||
|
position: [359, 368]
|
||||||
|
}
|
||||||
|
});
|
||||||
@ -0,0 +1,23 @@
|
|||||||
|
<script>
|
||||||
|
import Child from './irrelevant';
|
||||||
|
import Parent from './irrelevant';
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<!-- ok -->
|
||||||
|
<Child let:value>
|
||||||
|
{value}
|
||||||
|
{#snippet foo()}x{/snippet}
|
||||||
|
</Child>
|
||||||
|
<Child>
|
||||||
|
{#snippet children({ value })}{value}{/snippet}
|
||||||
|
</Child>
|
||||||
|
<Parent>
|
||||||
|
<Child slot="foo" let:value>
|
||||||
|
{#snippet children()}{value}{/snippet}
|
||||||
|
</Child>
|
||||||
|
</Parent>
|
||||||
|
|
||||||
|
<!-- invalid -->
|
||||||
|
<Child let:value>
|
||||||
|
{#snippet children()}Value is: {value}{/snippet}
|
||||||
|
</Child>
|
||||||
@ -0,0 +1,8 @@
|
|||||||
|
<script>
|
||||||
|
$: count = 7;
|
||||||
|
$: other = 8;
|
||||||
|
let obj = {};
|
||||||
|
$: obj.x = 1;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<p>{count} {other} {obj.x}</p>
|
||||||
@ -0,0 +1,14 @@
|
|||||||
|
<script>
|
||||||
|
import { run } from 'svelte/legacy';
|
||||||
|
|
||||||
|
let count = $state(7);
|
||||||
|
|
||||||
|
let other = $state(8);
|
||||||
|
|
||||||
|
let obj = $state({});
|
||||||
|
run(() => {
|
||||||
|
obj.x = 1;
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<p>{count} {other} {obj.x}</p>
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
<script>export let answer</script>
|
||||||
|
<p>{answer}</p>
|
||||||
@ -0,0 +1,3 @@
|
|||||||
|
<script>
|
||||||
|
let { answer } = $props();</script>
|
||||||
|
<p>{answer}</p>
|
||||||
@ -0,0 +1,13 @@
|
|||||||
|
import { flushSync } from 'svelte';
|
||||||
|
import { test } from '../../test';
|
||||||
|
|
||||||
|
export default test({
|
||||||
|
async test({ assert, target }) {
|
||||||
|
const [button] = target.querySelectorAll('button');
|
||||||
|
|
||||||
|
button.click();
|
||||||
|
flushSync();
|
||||||
|
|
||||||
|
assert.htmlEqual(target.innerHTML, '<button>Reproduce</button><p>Deferred outro</p>');
|
||||||
|
}
|
||||||
|
});
|
||||||
@ -0,0 +1,24 @@
|
|||||||
|
<script>
|
||||||
|
import { crossfade } from 'svelte/transition';
|
||||||
|
|
||||||
|
let visible = $state(true);
|
||||||
|
let restore = $state(false);
|
||||||
|
const [send] = crossfade({});
|
||||||
|
|
||||||
|
$effect(() => {
|
||||||
|
if (restore) visible = true;
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<button
|
||||||
|
onclick={() => {
|
||||||
|
visible = false;
|
||||||
|
restore = true;
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Reproduce
|
||||||
|
</button>
|
||||||
|
|
||||||
|
{#if visible}
|
||||||
|
<p out:send={{ key: 'item' }}>Deferred outro</p>
|
||||||
|
{/if}
|
||||||
@ -0,0 +1,50 @@
|
|||||||
|
import { tick } from 'svelte';
|
||||||
|
import { test } from '../../test';
|
||||||
|
|
||||||
|
/** @type {Array<() => void>} */
|
||||||
|
const resolvers = [];
|
||||||
|
|
||||||
|
export default test({
|
||||||
|
transformError: (error) => new Promise((resolve) => resolvers.push(() => resolve(error))),
|
||||||
|
|
||||||
|
async test({ assert, target, logs }) {
|
||||||
|
const [error, toggle, reset, destroy] = target.querySelectorAll('button');
|
||||||
|
const paragraph = /** @type {HTMLParagraphElement} */ (target.querySelector('p'));
|
||||||
|
|
||||||
|
error.click();
|
||||||
|
await tick();
|
||||||
|
resolvers.shift()?.();
|
||||||
|
await tick();
|
||||||
|
assert.htmlEqual(paragraph.innerHTML, 'boom');
|
||||||
|
|
||||||
|
// A retained reset is inert after its boundary has been destroyed
|
||||||
|
toggle.click();
|
||||||
|
await tick();
|
||||||
|
reset.click();
|
||||||
|
await tick();
|
||||||
|
assert.htmlEqual(paragraph.innerHTML, 'boom');
|
||||||
|
|
||||||
|
// Resolving an error transform cannot resume a destroyed boundary
|
||||||
|
toggle.click();
|
||||||
|
await tick();
|
||||||
|
error.click();
|
||||||
|
await tick();
|
||||||
|
toggle.click();
|
||||||
|
await tick();
|
||||||
|
resolvers.shift()?.();
|
||||||
|
await tick();
|
||||||
|
assert.htmlEqual(paragraph.innerHTML, 'boom');
|
||||||
|
|
||||||
|
// A failed snippet's reset is also inert while the boundary is being destroyed
|
||||||
|
toggle.click();
|
||||||
|
await tick();
|
||||||
|
error.click();
|
||||||
|
await tick();
|
||||||
|
resolvers.shift()?.();
|
||||||
|
await tick();
|
||||||
|
destroy.click();
|
||||||
|
await tick();
|
||||||
|
assert.htmlEqual(paragraph.innerHTML, 'boom,boom');
|
||||||
|
assert.deepEqual(logs, ['render', 'render', 'render']);
|
||||||
|
}
|
||||||
|
});
|
||||||
@ -0,0 +1,47 @@
|
|||||||
|
<script>
|
||||||
|
let show = $state(true);
|
||||||
|
let must_throw = $state(false);
|
||||||
|
let reset;
|
||||||
|
let element;
|
||||||
|
let errors = $state([]);
|
||||||
|
let reset_during_cleanup = false;
|
||||||
|
|
||||||
|
function throw_error() {
|
||||||
|
throw new Error('boom');
|
||||||
|
}
|
||||||
|
|
||||||
|
function toggle() {
|
||||||
|
must_throw = false;
|
||||||
|
show = !show;
|
||||||
|
}
|
||||||
|
|
||||||
|
function reset_on_cleanup(_, reset_boundary) {
|
||||||
|
return {
|
||||||
|
destroy() {
|
||||||
|
if (reset_during_cleanup) reset_boundary();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function track_render() {
|
||||||
|
console.log('render');
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<button onclick={() => (must_throw = true)}>error</button>
|
||||||
|
<button onclick={toggle}>toggle</button>
|
||||||
|
<button onclick={() => reset()}>reset</button>
|
||||||
|
<button onclick={() => { reset_during_cleanup = true; toggle(); }}>destroy</button>
|
||||||
|
<p>{errors.join(',')}</p>
|
||||||
|
|
||||||
|
{#if show}
|
||||||
|
<svelte:boundary onerror={(error, fn) => { errors.push(error.message); reset = fn; }}>
|
||||||
|
{track_render()}
|
||||||
|
<input bind:this={element} />
|
||||||
|
{must_throw ? throw_error() : ''}
|
||||||
|
|
||||||
|
{#snippet failed(_, failed_reset)}
|
||||||
|
<input bind:this={element} use:reset_on_cleanup={failed_reset} />
|
||||||
|
{/snippet}
|
||||||
|
</svelte:boundary>
|
||||||
|
{/if}
|
||||||
@ -0,0 +1,11 @@
|
|||||||
|
import { tick } from 'svelte';
|
||||||
|
import { test } from '../../test';
|
||||||
|
|
||||||
|
export default test({
|
||||||
|
mode: ['hydrate'],
|
||||||
|
|
||||||
|
async test({ assert, target }) {
|
||||||
|
await tick();
|
||||||
|
assert.htmlEqual(target.innerHTML, '<p>failed: setter error</p><p>after</p>');
|
||||||
|
}
|
||||||
|
});
|
||||||
@ -0,0 +1,22 @@
|
|||||||
|
<script module>
|
||||||
|
if (!customElements.get('throwing-element')) {
|
||||||
|
customElements.define(
|
||||||
|
'throwing-element',
|
||||||
|
class extends HTMLElement {
|
||||||
|
set value(_) {
|
||||||
|
throw new Error('setter error');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<svelte:boundary>
|
||||||
|
<throwing-element {...{ value: 'boom' }}></throwing-element>
|
||||||
|
|
||||||
|
{#snippet failed(error)}
|
||||||
|
<p>failed: {error.message}</p>
|
||||||
|
{/snippet}
|
||||||
|
</svelte:boundary>
|
||||||
|
|
||||||
|
<p>after</p>
|
||||||
@ -0,0 +1,14 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"code": "declaration_duplicate",
|
||||||
|
"message": "`item` has already been declared",
|
||||||
|
"start": {
|
||||||
|
"line": 13,
|
||||||
|
"column": 8
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"line": 13,
|
||||||
|
"column": 12
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
@ -0,0 +1,17 @@
|
|||||||
|
<!-- this is ok -->
|
||||||
|
{#snippet row1(item)}
|
||||||
|
{#if item}
|
||||||
|
{const item = 1}
|
||||||
|
<p>{item}</p>
|
||||||
|
{/if}
|
||||||
|
{/snippet}
|
||||||
|
|
||||||
|
{@render row1(5)}
|
||||||
|
|
||||||
|
<!-- this is not -->
|
||||||
|
{#snippet row2(item)}
|
||||||
|
{const item = 1}
|
||||||
|
<p>{item}</p>
|
||||||
|
{/snippet}
|
||||||
|
|
||||||
|
{@render row2(5)}
|
||||||
Loading…
Reference in new issue