mirror of https://github.com/sveltejs/svelte
commit
dd3cfda172
@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
'svelte': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
perf: reuse the cached value in the `<option>`/`<select>` value guard
|
||||||
@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
'svelte': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
fix: apply ownership mutation ignores to binding assignments
|
||||||
@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
'svelte': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
perf: fold SSR block-open markers into the branch's first push
|
||||||
@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
'svelte': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
fix: report `derived_invalid_export` for `export let x = $derived(...)` in runes mode
|
||||||
@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
'svelte': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
fix: keep `defaultChecked` on hydrated radio inputs with spread attributes
|
||||||
@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
'svelte': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
fix: measure nested transitions before applying their starting styles
|
||||||
@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
'svelte': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
perf: emit `$.only_child` for elements with a single child
|
||||||
@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
'svelte': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
fix: omit `bind:focused` from SSR output (it has no HTML attribute)
|
||||||
@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
'svelte': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
fix: more robust rendering of Svelte custom element slots
|
||||||
@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
'svelte': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
fix: properly apply static textarea value attribute during CSR
|
||||||
@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
'svelte': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
fix: keep the dependencies of a reaction that throws, so deriveds it read are neither leaked nor stuck in their error
|
||||||
@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
'svelte': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
perf: use `$.comment()` for single-comment templates
|
||||||
@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
'svelte': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
chore: move `@types/trusted-types` to devDependencies
|
||||||
@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
'svelte': minor
|
||||||
|
---
|
||||||
|
|
||||||
|
feat: add `has` function to `createContext`
|
||||||
@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
'svelte': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
fix: transform derived assignments and select function bindings correctly during server-side rendering
|
||||||
@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
'svelte': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
fix: keep boolean attributes with an empty string value when rendering attribute objects on the server
|
||||||
@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
'svelte': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
fix: sync `SvelteURL` port signal when the protocol setter clears the port
|
||||||
@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
'svelte': minor
|
||||||
|
---
|
||||||
|
|
||||||
|
feat: support `defaultValue` on `<select>`
|
||||||
@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
'svelte': minor
|
||||||
|
---
|
||||||
|
|
||||||
|
feat: add getOrInsert/getOrInsertComputed to SvelteMap
|
||||||
@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
'svelte': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
fix: block declaration tags and `{@const}` on async values read inside closures
|
||||||
@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
'svelte': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
perf: treat `<img loading>` as a static element again
|
||||||
@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
'svelte': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
fix: preserve line feed character references in attribute values
|
||||||
@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
'svelte': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
fix: decode uppercase-`X` hex numeric character references (`&#X...;`)
|
||||||
@ -0,0 +1,9 @@
|
|||||||
|
import { test } from '../../test';
|
||||||
|
|
||||||
|
export default test({
|
||||||
|
error: {
|
||||||
|
code: 'derived_invalid_export',
|
||||||
|
message:
|
||||||
|
'Cannot export derived state from a module. To expose the current derived value, export a function returning its value'
|
||||||
|
}
|
||||||
|
});
|
||||||
@ -0,0 +1,4 @@
|
|||||||
|
<script>
|
||||||
|
let count = $state(0);
|
||||||
|
export let double = $derived(count * 2);
|
||||||
|
</script>
|
||||||
@ -0,0 +1 @@
|
|||||||
|
<p title="A
B">A
B</p>
|
||||||
@ -0,0 +1,53 @@
|
|||||||
|
{
|
||||||
|
"html": {
|
||||||
|
"type": "Fragment",
|
||||||
|
"start": 0,
|
||||||
|
"end": 32,
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"type": "Element",
|
||||||
|
"start": 0,
|
||||||
|
"end": 32,
|
||||||
|
"name": "p",
|
||||||
|
"attributes": [
|
||||||
|
{
|
||||||
|
"type": "Attribute",
|
||||||
|
"start": 3,
|
||||||
|
"end": 19,
|
||||||
|
"name": "title",
|
||||||
|
"name_loc": {
|
||||||
|
"start": {
|
||||||
|
"line": 1,
|
||||||
|
"column": 3,
|
||||||
|
"character": 3
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"line": 1,
|
||||||
|
"column": 8,
|
||||||
|
"character": 8
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"value": [
|
||||||
|
{
|
||||||
|
"start": 10,
|
||||||
|
"end": 18,
|
||||||
|
"type": "Text",
|
||||||
|
"raw": "A
B",
|
||||||
|
"data": "A\nB"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"type": "Text",
|
||||||
|
"start": 20,
|
||||||
|
"end": 28,
|
||||||
|
"raw": "A
B",
|
||||||
|
"data": "A B"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,14 @@
|
|||||||
|
<script>
|
||||||
|
import Nested from './Nested.svelte';
|
||||||
|
import { slide } from 'svelte/transition';
|
||||||
|
|
||||||
|
let { depth } = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="level-{depth}" in:slide|global={{ duration: 100 }}>
|
||||||
|
{#if depth > 0}
|
||||||
|
<Nested depth={depth - 1} />
|
||||||
|
{:else}
|
||||||
|
<div style="height: 100px">leaf</div>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
@ -0,0 +1,36 @@
|
|||||||
|
import { test } from '../../assert';
|
||||||
|
|
||||||
|
export default test({
|
||||||
|
async test({ assert, target }) {
|
||||||
|
const button = target.querySelector('button');
|
||||||
|
button?.click();
|
||||||
|
|
||||||
|
// wait for the transition's keyframes to be created
|
||||||
|
const animation = await new Promise((resolve, reject) => {
|
||||||
|
const start = performance.now();
|
||||||
|
|
||||||
|
function check() {
|
||||||
|
const outer = target.querySelector('.level-2');
|
||||||
|
const animation = outer
|
||||||
|
?.getAnimations()
|
||||||
|
.find((a) => a.effect?.getTiming().duration === 100);
|
||||||
|
|
||||||
|
if (animation) {
|
||||||
|
resolve(animation);
|
||||||
|
} else if (performance.now() - start > 2000) {
|
||||||
|
reject(new Error('timed out waiting for the transition to start'));
|
||||||
|
} else {
|
||||||
|
requestAnimationFrame(check);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
check();
|
||||||
|
});
|
||||||
|
|
||||||
|
// the outermost `slide` must have measured the element with its
|
||||||
|
// descendants at their natural size, not collapsed to zero by their
|
||||||
|
// own starting styles (#18421)
|
||||||
|
const keyframes = animation.effect?.getKeyframes() ?? [];
|
||||||
|
assert.equal(keyframes[keyframes.length - 1].height, '100px');
|
||||||
|
}
|
||||||
|
});
|
||||||
@ -0,0 +1,11 @@
|
|||||||
|
<script>
|
||||||
|
import Nested from './Nested.svelte';
|
||||||
|
|
||||||
|
let visible = $state(false);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<button onclick={() => (visible = !visible)}>toggle</button>
|
||||||
|
|
||||||
|
{#if visible}
|
||||||
|
<Nested depth={2} />
|
||||||
|
{/if}
|
||||||
@ -0,0 +1,10 @@
|
|||||||
|
import { tick } from 'svelte';
|
||||||
|
import { test } from '../../test';
|
||||||
|
|
||||||
|
// #18469 — a @const in a nested snippet reading an async declaration through a closure must block on it
|
||||||
|
export default test({
|
||||||
|
async test({ assert, target }) {
|
||||||
|
await tick();
|
||||||
|
assert.htmlEqual(target.innerHTML, '<p>true</p> <p>false</p>');
|
||||||
|
}
|
||||||
|
});
|
||||||
@ -0,0 +1,12 @@
|
|||||||
|
<script>
|
||||||
|
async function getValue() {
|
||||||
|
return new Set(['a', 'b', 'c']);
|
||||||
|
}
|
||||||
|
|
||||||
|
const value = await getValue();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{#each [['a', 'b'], ['a', 'x']] as keys}
|
||||||
|
{@const all_present = keys.every((k) => value.has(k))}
|
||||||
|
<p>{all_present}</p>
|
||||||
|
{/each}
|
||||||
@ -0,0 +1,11 @@
|
|||||||
|
import { tick } from 'svelte';
|
||||||
|
import { test } from '../../test';
|
||||||
|
|
||||||
|
// #18469 — a sync $derived in a nested snippet reading an async declaration through a closure must block on it
|
||||||
|
export default test({
|
||||||
|
ssrHtml: '<p>true</p> <p>false</p>',
|
||||||
|
async test({ assert, target }) {
|
||||||
|
await tick();
|
||||||
|
assert.htmlEqual(target.innerHTML, '<p>true</p> <p>false</p>');
|
||||||
|
}
|
||||||
|
});
|
||||||
@ -0,0 +1,17 @@
|
|||||||
|
<script>
|
||||||
|
async function getValue() {
|
||||||
|
return new Set(['a', 'b', 'c']);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{#snippet outer()}
|
||||||
|
{const value = $derived(await getValue())}
|
||||||
|
{#snippet inner(keys)}
|
||||||
|
{const all_present = $derived(keys.every((k) => value.has(k)))}
|
||||||
|
<p>{all_present}</p>
|
||||||
|
{/snippet}
|
||||||
|
{@render inner(['a', 'b'])}
|
||||||
|
{@render inner(['a', 'x'])}
|
||||||
|
{/snippet}
|
||||||
|
|
||||||
|
{@render outer()}
|
||||||
@ -0,0 +1,7 @@
|
|||||||
|
<script>
|
||||||
|
const { environment } = $props();
|
||||||
|
|
||||||
|
if (environment === 'client') {
|
||||||
|
throw new Error('oops');
|
||||||
|
}
|
||||||
|
</script>
|
||||||
@ -0,0 +1,14 @@
|
|||||||
|
import { tick } from 'svelte';
|
||||||
|
import { test } from '../../test';
|
||||||
|
|
||||||
|
export default test({
|
||||||
|
mode: ['hydrate'],
|
||||||
|
server_props: { environment: 'server' },
|
||||||
|
props: { environment: 'client' },
|
||||||
|
ssrHtml: 'loading inner loading nested',
|
||||||
|
|
||||||
|
async test({ assert, target }) {
|
||||||
|
await tick();
|
||||||
|
assert.htmlEqual(target.innerHTML, 'inner failed: oops outer failed: oops');
|
||||||
|
}
|
||||||
|
});
|
||||||
@ -0,0 +1,24 @@
|
|||||||
|
<script>
|
||||||
|
import Child from './Child.svelte';
|
||||||
|
|
||||||
|
const { environment } = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<svelte:boundary>
|
||||||
|
<Child {environment} />
|
||||||
|
{await new Promise(() => {})}
|
||||||
|
|
||||||
|
{#snippet pending()}loading inner{/snippet}
|
||||||
|
{#snippet failed(error)}inner failed: {error.message}{/snippet}
|
||||||
|
</svelte:boundary>
|
||||||
|
|
||||||
|
<svelte:boundary>
|
||||||
|
<svelte:boundary>
|
||||||
|
<Child {environment} />
|
||||||
|
{await new Promise(() => {})}
|
||||||
|
|
||||||
|
{#snippet pending()}loading nested{/snippet}
|
||||||
|
</svelte:boundary>
|
||||||
|
|
||||||
|
{#snippet failed(error)}outer failed: {error.message}{/snippet}
|
||||||
|
</svelte:boundary>
|
||||||
@ -1,7 +1,13 @@
|
|||||||
<script>
|
<script>
|
||||||
import { get } from './main.svelte';
|
import { get, has, has_unset } from './main.svelte';
|
||||||
|
|
||||||
const message = get();
|
const message = get();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<h1>{message}</h1>
|
<h1>{message}</h1>
|
||||||
|
{#if has()}
|
||||||
|
<h2>it's me</h2>
|
||||||
|
{/if}
|
||||||
|
{#if !has_unset()}
|
||||||
|
<h2>or not</h2>
|
||||||
|
{/if}
|
||||||
|
|||||||
@ -1,7 +1,13 @@
|
|||||||
<script>
|
<script>
|
||||||
import { get } from './main.svelte';
|
import { get, has, has_unset } from './main.svelte';
|
||||||
|
|
||||||
const message = get();
|
const message = get();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<h1>{message}</h1>
|
<h1>{message}</h1>
|
||||||
|
{#if has()}
|
||||||
|
<h2>it's me</h2>
|
||||||
|
{/if}
|
||||||
|
{#if !has_unset()}
|
||||||
|
<h2>or not</h2>
|
||||||
|
{/if}
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import { test } from '../../test';
|
import { test } from '../../test';
|
||||||
|
|
||||||
export default test({
|
export default test({
|
||||||
html: `<h1>hello</h1>`
|
html: `<h1>hello</h1><h2>it's me</h2><h2>or not</h2>`
|
||||||
});
|
});
|
||||||
|
|||||||
@ -1,6 +0,0 @@
|
|||||||
import { test } from '../../test';
|
|
||||||
|
|
||||||
export default test({
|
|
||||||
ssrHtml: '<p>LATER</p> <input value="LATER">',
|
|
||||||
html: '<p>LATER</p> <input>'
|
|
||||||
});
|
|
||||||
@ -0,0 +1,6 @@
|
|||||||
|
import { test } from '../../test';
|
||||||
|
|
||||||
|
export default test({
|
||||||
|
ssrHtml: '<p>y:y</p> <p>LATER</p> <input value="LATER">',
|
||||||
|
html: '<p>y:y</p> <p>LATER</p> <input>'
|
||||||
|
});
|
||||||
@ -0,0 +1,23 @@
|
|||||||
|
import { flushSync } from 'svelte';
|
||||||
|
import { test } from '../../test';
|
||||||
|
|
||||||
|
export default test({
|
||||||
|
mode: ['hydrate'],
|
||||||
|
|
||||||
|
async test({ assert, target }) {
|
||||||
|
const [a, b, reset] = target.querySelectorAll('input');
|
||||||
|
|
||||||
|
// let the deferred hydration cleanup run
|
||||||
|
await Promise.resolve();
|
||||||
|
flushSync();
|
||||||
|
|
||||||
|
b.checked = true;
|
||||||
|
reset.click();
|
||||||
|
await Promise.resolve();
|
||||||
|
flushSync();
|
||||||
|
|
||||||
|
assert.equal(a.defaultChecked, true);
|
||||||
|
assert.equal(a.checked, true);
|
||||||
|
assert.equal(b.checked, false);
|
||||||
|
}
|
||||||
|
});
|
||||||
@ -0,0 +1,9 @@
|
|||||||
|
<script>
|
||||||
|
let spread = { defaultChecked: true, checked: true };
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<form>
|
||||||
|
<input type="radio" name="option" value="a" {...spread} />
|
||||||
|
<input type="radio" name="option" value="b" />
|
||||||
|
<input type="reset" value="Reset" />
|
||||||
|
</form>
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue