mirror of https://github.com/sveltejs/svelte
commit
35c3601b3b
@ -0,0 +1,5 @@
|
||||
---
|
||||
'svelte': patch
|
||||
---
|
||||
|
||||
fix: improve props aliasing
|
||||
@ -0,0 +1,5 @@
|
||||
---
|
||||
'svelte': patch
|
||||
---
|
||||
|
||||
feat: add support for `{@const}` inside snippet block
|
||||
@ -0,0 +1,5 @@
|
||||
---
|
||||
'svelte': patch
|
||||
---
|
||||
|
||||
fix: improve whitespace handling
|
||||
@ -0,0 +1,5 @@
|
||||
---
|
||||
'svelte': patch
|
||||
---
|
||||
|
||||
fix: improve each block fallback handling
|
||||
@ -0,0 +1,5 @@
|
||||
---
|
||||
'svelte': patch
|
||||
---
|
||||
|
||||
fix: improve attribute directive reactivity detection
|
||||
@ -0,0 +1,5 @@
|
||||
---
|
||||
'svelte': patch
|
||||
---
|
||||
|
||||
fix: improve $inspect batching
|
||||
@ -0,0 +1,5 @@
|
||||
---
|
||||
'svelte': patch
|
||||
---
|
||||
|
||||
chore: improve readonly prop messaging
|
||||
@ -0,0 +1,5 @@
|
||||
---
|
||||
'svelte': patch
|
||||
---
|
||||
|
||||
feat: add `gamepadconnected` and `gamepaddisconnected` events
|
||||
@ -0,0 +1,5 @@
|
||||
---
|
||||
'svelte': patch
|
||||
---
|
||||
|
||||
fix: better handle array property deletion reactivity
|
||||
@ -0,0 +1,5 @@
|
||||
---
|
||||
'svelte': patch
|
||||
---
|
||||
|
||||
fix: improve unstate type definition
|
||||
@ -0,0 +1,5 @@
|
||||
---
|
||||
'svelte': patch
|
||||
---
|
||||
|
||||
fix: improve event delegation handler hoisting
|
||||
@ -0,0 +1,5 @@
|
||||
---
|
||||
'svelte': patch
|
||||
---
|
||||
|
||||
fix: correctly reflect readonly proxy marker
|
||||
@ -0,0 +1,5 @@
|
||||
---
|
||||
'svelte': patch
|
||||
---
|
||||
|
||||
chore: improve each block fast-path heuristic
|
||||
@ -0,0 +1,5 @@
|
||||
---
|
||||
'svelte': patch
|
||||
---
|
||||
|
||||
fix: improve html tag svg behaviour
|
||||
@ -0,0 +1,5 @@
|
||||
---
|
||||
'svelte': patch
|
||||
---
|
||||
|
||||
fix: ensure class constructor values are proxied
|
||||
@ -0,0 +1,5 @@
|
||||
---
|
||||
'svelte': patch
|
||||
---
|
||||
|
||||
fix: better support for top-level snippet declarations
|
||||
@ -0,0 +1,5 @@
|
||||
---
|
||||
'svelte': patch
|
||||
---
|
||||
|
||||
fix: cleanup each block animations on destroy
|
||||
@ -0,0 +1,5 @@
|
||||
---
|
||||
'svelte': patch
|
||||
---
|
||||
|
||||
fix: improve each block index handling
|
||||
@ -0,0 +1,60 @@
|
||||
import { flushSync } from 'svelte';
|
||||
import { ok, test } from '../../test';
|
||||
|
||||
export default test({
|
||||
async test({ assert, target, window }) {
|
||||
const button = target.querySelector('button');
|
||||
ok(button);
|
||||
|
||||
assert.htmlEqual(
|
||||
target.innerHTML,
|
||||
`
|
||||
<button>Remove last</button><div class="list"><label><input type="checkbox">
|
||||
write
|
||||
some
|
||||
docs</label><label><input type="checkbox">
|
||||
start
|
||||
writing
|
||||
JSConf
|
||||
talk</label><label><input type="checkbox">
|
||||
buy
|
||||
some
|
||||
milk</label><label><input type="checkbox">
|
||||
mow
|
||||
the
|
||||
lawn</label><label><input type="checkbox">
|
||||
feed
|
||||
the
|
||||
turtle</label><label><input type="checkbox">
|
||||
fix
|
||||
some
|
||||
bugs</label></div>`
|
||||
);
|
||||
|
||||
flushSync(() => {
|
||||
button.click();
|
||||
});
|
||||
|
||||
assert.htmlEqual(
|
||||
target.innerHTML,
|
||||
`
|
||||
<button>Remove last</button><div class="list"><label><input type="checkbox">
|
||||
write
|
||||
some
|
||||
docs</label><label><input type="checkbox">
|
||||
start
|
||||
writing
|
||||
JSConf
|
||||
talk</label><label><input type="checkbox">
|
||||
buy
|
||||
some
|
||||
milk</label><label><input type="checkbox">
|
||||
mow
|
||||
the
|
||||
lawn</label><label><input type="checkbox">
|
||||
feed
|
||||
the
|
||||
turtle</label></div>`
|
||||
);
|
||||
}
|
||||
});
|
||||
@ -0,0 +1,28 @@
|
||||
<script>
|
||||
import { flip } from 'svelte/animate';
|
||||
|
||||
let todos = [
|
||||
{ id: 1, done: false, description: 'write some docs' },
|
||||
{ id: 2, done: false, description: 'start writing JSConf talk' },
|
||||
{ id: 3, done: true, description: 'buy some milk' },
|
||||
{ id: 4, done: false, description: 'mow the lawn' },
|
||||
{ id: 5, done: false, description: 'feed the turtle' },
|
||||
{ id: 6, done: false, description: 'fix some bugs' }
|
||||
];
|
||||
|
||||
function update() {
|
||||
todos = [...todos]
|
||||
todos.pop();
|
||||
}
|
||||
</script>
|
||||
|
||||
<button on:click={update}>Remove last</button>
|
||||
|
||||
<div class="list">
|
||||
{#each todos as todo (todo.id)}
|
||||
<label animate:flip>
|
||||
<input type="checkbox" bind:checked={todo.done} />
|
||||
{todo.description}
|
||||
</label>
|
||||
{/each}
|
||||
</div>
|
||||
@ -0,0 +1,5 @@
|
||||
import { test } from '../../test';
|
||||
|
||||
export default test({
|
||||
html: `<div>0</div><div>1</div>`
|
||||
});
|
||||
@ -0,0 +1,3 @@
|
||||
{#each {length: 2} as item, i (`${i}`)}
|
||||
<div>{i}</div>
|
||||
{/each}
|
||||
@ -0,0 +1,7 @@
|
||||
import { test } from '../../test';
|
||||
|
||||
export default test({
|
||||
compileOptions: { dev: true }, // tests `@validate_store` code generation
|
||||
|
||||
html: `<button>clicks:\n0</button>`
|
||||
});
|
||||
@ -0,0 +1,12 @@
|
||||
<script>
|
||||
import {writable} from 'svelte/store'
|
||||
let store = writable(0)
|
||||
</script>
|
||||
|
||||
<button onclick={() => {
|
||||
if(store && $store){
|
||||
|
||||
}
|
||||
}}>
|
||||
clicks: {$store}
|
||||
</button>
|
||||
@ -0,0 +1,14 @@
|
||||
import { ok, test } from '../../test';
|
||||
|
||||
export default test({
|
||||
test({ assert, target, component }) {
|
||||
let svg = target.querySelector('svg');
|
||||
ok(svg);
|
||||
|
||||
assert.equal(svg.namespaceURI, 'http://www.w3.org/2000/svg');
|
||||
assert.htmlEqual(
|
||||
svg.outerHTML,
|
||||
'<svg height="24" style="border:1px solid red;" width="24"><path d="M17 11h1a3 3 0 0 1 0 6h-1"></path><path d="M9 12v6"></path><path d="M13 12v6"></path><path d="M14 7.5c-1 0-1.44.5-3 .5s-2-.5-3-.5-1.72.5-2.5.5a2.5 2.5 0 0 1 0-5c.78 0 1.57.5 2.5.5S9.44 2 11 2s2 1.5 3 1.5 1.72-.5 2.5-.5a2.5 2.5 0 0 1 0 5c-.78 0-1.5-.5-2.5-.5Z"></path><path d="M5 8v12a2 2 0 0 0 2 2h8a2 2 0 0 0 2-2V8"></path></svg>'
|
||||
);
|
||||
}
|
||||
});
|
||||
@ -0,0 +1,7 @@
|
||||
<script>
|
||||
let content = '<path d="M17 11h1a3 3 0 0 1 0 6h-1" /><path d="M9 12v6" /><path d="M13 12v6" /><path d="M14 7.5c-1 0-1.44.5-3 .5s-2-.5-3-.5-1.72.5-2.5.5a2.5 2.5 0 0 1 0-5c.78 0 1.57.5 2.5.5S9.44 2 11 2s2 1.5 3 1.5 1.72-.5 2.5-.5a2.5 2.5 0 0 1 0 5c-.78 0-1.5-.5-2.5-.5Z" /><path d="M5 8v12a2 2 0 0 0 2 2h8a2 2 0 0 0 2-2V8" />'
|
||||
</script>
|
||||
|
||||
<svg width="24" height="24" style="border:1px solid red;">
|
||||
{@html content}
|
||||
</svg>
|
||||
@ -0,0 +1,15 @@
|
||||
import { test } from '../../test';
|
||||
|
||||
export default test({
|
||||
html: `<button>0</button>`,
|
||||
|
||||
async test({ assert, target }) {
|
||||
const btn = target.querySelector('button');
|
||||
|
||||
await btn?.click();
|
||||
assert.htmlEqual(target.innerHTML, `<button>1</button>`);
|
||||
|
||||
await btn?.click();
|
||||
assert.htmlEqual(target.innerHTML, `<button>2</button>`);
|
||||
}
|
||||
});
|
||||
@ -0,0 +1,16 @@
|
||||
<script>
|
||||
class Counter {
|
||||
#count = $state();
|
||||
|
||||
constructor(v) {
|
||||
this.#count = v;
|
||||
}
|
||||
|
||||
get count() {
|
||||
return this.#count;
|
||||
}
|
||||
}
|
||||
const counter = new Counter({ count: 0 });
|
||||
</script>
|
||||
|
||||
<button on:click={() => counter.count.count++}>{counter.count.count}</button>
|
||||
@ -0,0 +1,15 @@
|
||||
import { test } from '../../test';
|
||||
|
||||
export default test({
|
||||
html: `<button>0</button>`,
|
||||
|
||||
async test({ assert, target }) {
|
||||
const btn = target.querySelector('button');
|
||||
|
||||
await btn?.click();
|
||||
assert.htmlEqual(target.innerHTML, `<button>1</button>`);
|
||||
|
||||
await btn?.click();
|
||||
assert.htmlEqual(target.innerHTML, `<button>2</button>`);
|
||||
}
|
||||
});
|
||||
@ -0,0 +1,12 @@
|
||||
<script>
|
||||
class Counter {
|
||||
count = $state();
|
||||
|
||||
constructor(v) {
|
||||
this.count = v;
|
||||
}
|
||||
}
|
||||
const counter = new Counter({ count: 0 });
|
||||
</script>
|
||||
|
||||
<button on:click={() => counter.count.count++}>{counter.count.count}</button>
|
||||
@ -0,0 +1,17 @@
|
||||
import { flushSync } from 'svelte';
|
||||
import { test } from '../../test';
|
||||
|
||||
export default test({
|
||||
async test({ assert, target, component }) {
|
||||
const [b1] = target.querySelectorAll('button');
|
||||
assert.htmlEqual(target.innerHTML, '<div>abc</div><button>Toggle</button>');
|
||||
flushSync(() => {
|
||||
b1.click();
|
||||
});
|
||||
assert.htmlEqual(target.innerHTML, '<div>Fallback</div><button>Toggle</button>');
|
||||
flushSync(() => {
|
||||
b1.click();
|
||||
});
|
||||
assert.htmlEqual(target.innerHTML, '<div>abc</div><button>Toggle</button>');
|
||||
}
|
||||
});
|
||||
@ -0,0 +1,22 @@
|
||||
<script>
|
||||
let data = $state({a:1, b:2, c:3});
|
||||
let filter = $state(false);
|
||||
|
||||
function toggle_filter(){
|
||||
if(filter) {
|
||||
filter = false;
|
||||
data = {a:1, b:2, c:3};
|
||||
} else {
|
||||
filter = true;
|
||||
data = {};
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<div>
|
||||
{#each Object.keys(data) as key}
|
||||
{key}
|
||||
{:else}
|
||||
Fallback
|
||||
{/each}
|
||||
</div>
|
||||
<button onclick={toggle_filter}>Toggle</button>
|
||||
@ -0,0 +1,52 @@
|
||||
import { flushSync } from 'svelte';
|
||||
import { test } from '../../test';
|
||||
|
||||
export default test({
|
||||
html: `<button>push</button><button>pop</button><p>1</p><p>2</p><p>3</p>`,
|
||||
|
||||
async test({ assert, target }) {
|
||||
const [btn1, btn2] = target.querySelectorAll('button');
|
||||
|
||||
flushSync(() => {
|
||||
btn1.click();
|
||||
});
|
||||
|
||||
assert.htmlEqual(
|
||||
target.innerHTML,
|
||||
`<button>push</button><button>pop</button><p>1</p><p>2</p><p>3</p><p>4</p>`
|
||||
);
|
||||
|
||||
flushSync(() => {
|
||||
btn1.click();
|
||||
});
|
||||
|
||||
assert.htmlEqual(
|
||||
target.innerHTML,
|
||||
`<button>push</button><button>pop</button><p>1</p><p>2</p><p>3</p><p>4</p><p>5</p>`
|
||||
);
|
||||
|
||||
flushSync(() => {
|
||||
btn2.click();
|
||||
});
|
||||
|
||||
assert.htmlEqual(
|
||||
target.innerHTML,
|
||||
`<button>push</button><button>pop</button><p>1</p><p>2</p><p>3</p><p>4</p>`
|
||||
);
|
||||
|
||||
flushSync(() => {
|
||||
btn2.click();
|
||||
});
|
||||
|
||||
assert.htmlEqual(
|
||||
target.innerHTML,
|
||||
`<button>push</button><button>pop</button><p>1</p><p>2</p><p>3</p>`
|
||||
);
|
||||
|
||||
flushSync(() => {
|
||||
btn2.click();
|
||||
});
|
||||
|
||||
assert.htmlEqual(target.innerHTML, `<button>push</button><button>pop</button><p>1</p><p>2</p>`);
|
||||
}
|
||||
});
|
||||
@ -0,0 +1,15 @@
|
||||
<script>
|
||||
let numbers = $state([{id: 1}, {id: 2}, {id: 3}]);
|
||||
</script>
|
||||
|
||||
<button onclick={() => numbers.push({id: numbers.length + 1})}>
|
||||
push
|
||||
</button>
|
||||
|
||||
<button onclick={() => numbers.pop()}>
|
||||
pop
|
||||
</button>
|
||||
|
||||
{#each numbers as number}
|
||||
<p>{number.id}</p>
|
||||
{/each}
|
||||
@ -0,0 +1,16 @@
|
||||
import { test } from '../../test';
|
||||
|
||||
export default test({
|
||||
html: `<div style="color: red;"></div><div class="red"></div><button>toggle</button`,
|
||||
|
||||
async test({ assert, target }) {
|
||||
const [b1] = target.querySelectorAll('button');
|
||||
|
||||
b1?.click();
|
||||
await Promise.resolve();
|
||||
assert.htmlEqual(
|
||||
target.innerHTML,
|
||||
'<div class="blue" style="color: blue;"></div><div class="blue"></div><button>toggle</button>'
|
||||
);
|
||||
}
|
||||
});
|
||||
@ -0,0 +1,18 @@
|
||||
<script>
|
||||
let value = $state('red');
|
||||
|
||||
const getValue = () => {
|
||||
return value;
|
||||
}
|
||||
const getClass = () => {
|
||||
return value === 'blue';
|
||||
}
|
||||
const getSpread = () => {
|
||||
return { class: value };
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class:blue={getClass()} style:color={getValue()}></div>
|
||||
<div {...getSpread()}></div>
|
||||
<button on:click={() => value = 'blue'}>toggle</button>
|
||||
|
||||
@ -0,0 +1,5 @@
|
||||
<script>
|
||||
let { count: definedCount } = $props();
|
||||
</script>
|
||||
|
||||
<button on:click={() => definedCount++}>{definedCount}</button>
|
||||
@ -0,0 +1,32 @@
|
||||
import { test } from '../../test';
|
||||
|
||||
export default test({
|
||||
html: `
|
||||
<p>0 0 0 0</p>
|
||||
<button>0</button>
|
||||
<button>0</button>
|
||||
<button>0</button>
|
||||
<button>0</button>
|
||||
`,
|
||||
|
||||
async test({ assert, target, component }) {
|
||||
const [b1, b2, b3, b4] = target.querySelectorAll('button');
|
||||
|
||||
b1.click();
|
||||
b2.click();
|
||||
b3.click();
|
||||
b4.click();
|
||||
await Promise.resolve();
|
||||
|
||||
assert.htmlEqual(
|
||||
target.innerHTML,
|
||||
`
|
||||
<p>1 1 0 0</p>
|
||||
<button>1</button>
|
||||
<button>1</button>
|
||||
<button>1</button>
|
||||
<button>1</button>
|
||||
`
|
||||
);
|
||||
}
|
||||
});
|
||||
@ -0,0 +1,15 @@
|
||||
<script>
|
||||
import Counter from './Counter.svelte';
|
||||
|
||||
let bound = $state(0);
|
||||
let bound_nested = $state({count: 0});
|
||||
let unbound = $state(0);
|
||||
let unbound_nested = $state({count: 0});
|
||||
</script>
|
||||
|
||||
<p>{bound} {bound_nested.count} {unbound} {unbound_nested.count}</p>
|
||||
|
||||
<Counter bind:count={bound} />
|
||||
<Counter bind:count={bound_nested.count} />
|
||||
<Counter count={unbound} />
|
||||
<Counter count={unbound_nested.count} />
|
||||
@ -0,0 +1,16 @@
|
||||
import { test } from '../../test';
|
||||
|
||||
export default test({
|
||||
html: `<button>0</button>`,
|
||||
async test({ assert, target }) {
|
||||
const btn = target.querySelector('button');
|
||||
|
||||
assert.htmlEqual(target.innerHTML, '<button>0</button>');
|
||||
|
||||
await btn?.click();
|
||||
assert.htmlEqual(target.innerHTML, '<button>2</button>');
|
||||
|
||||
await btn?.click();
|
||||
assert.htmlEqual(target.innerHTML, '<button>4</button>');
|
||||
}
|
||||
});
|
||||
@ -0,0 +1,10 @@
|
||||
<script>
|
||||
let count = $state(0);
|
||||
</script>
|
||||
|
||||
{#snippet counter()}
|
||||
{@const doubled = count * 2}
|
||||
<button on:click={() => (count += 1)}>{doubled}</button>
|
||||
{/snippet}
|
||||
|
||||
{@render counter()}
|
||||
@ -0,0 +1,8 @@
|
||||
import { test } from '../../test';
|
||||
|
||||
export default test({
|
||||
compileOptions: {
|
||||
dev: true // Render in dev mode to check that the validation error is not thrown
|
||||
},
|
||||
html: `<p>hello world</p>`
|
||||
});
|
||||
@ -0,0 +1,7 @@
|
||||
<script>
|
||||
const {children = snippet} = $props();
|
||||
</script>
|
||||
{@render children()}
|
||||
{#snippet snippet()}
|
||||
<p>hello world</p>
|
||||
{/snippet}
|
||||
@ -0,0 +1,8 @@
|
||||
import { test } from '../../test';
|
||||
|
||||
export default test({
|
||||
compileOptions: {
|
||||
dev: true // Render in dev mode to check that the validation error is not thrown
|
||||
},
|
||||
html: `A\nB\nC\nD`
|
||||
});
|
||||
@ -0,0 +1,5 @@
|
||||
A
|
||||
{#snippet snip()}C{/snippet}
|
||||
B
|
||||
{@render snip()}
|
||||
D
|
||||
@ -0,0 +1,11 @@
|
||||
<script>
|
||||
import Component2 from './Component2.svelte';
|
||||
const {state} = $props();
|
||||
|
||||
function render(state) {
|
||||
return state
|
||||
}
|
||||
</script>
|
||||
|
||||
<Component2 state={render(state)} />
|
||||
|
||||
@ -0,0 +1,5 @@
|
||||
<script>
|
||||
const {state} = $props();
|
||||
</script>
|
||||
|
||||
{state}
|
||||
@ -0,0 +1,13 @@
|
||||
import { test } from '../../test';
|
||||
|
||||
export default test({
|
||||
compileOptions: {
|
||||
dev: true
|
||||
},
|
||||
async test({ assert, target }) {
|
||||
const btn = target.querySelector('button');
|
||||
|
||||
await btn?.click();
|
||||
assert.htmlEqual(target.innerHTML, `<button></button>\n[object Object]`);
|
||||
}
|
||||
});
|
||||
@ -0,0 +1,12 @@
|
||||
<script>
|
||||
import Component from './Component.svelte';
|
||||
|
||||
let state = $state();
|
||||
</script>
|
||||
|
||||
<button onclick={() => {
|
||||
state = {}
|
||||
}}></button>
|
||||
{#if state}
|
||||
<Component state={state} />
|
||||
{/if}
|
||||
Loading…
Reference in new issue