mirror of https://github.com/sveltejs/svelte
fix: tighten up event attributes and hoisting logic (#9433)
- add event delegation to spread_attributes - add event attributes to spread - don't delegate when bindings/actions on the same element in order to preserve backwards compatibility of ordering - don't hoist identifiers when one of them is used in an event that is not delegateable --------- Co-authored-by: Simon Holthausen <simon.holthausen@vercel.com>baseballyama-docs/string-event
parent
3f56baf760
commit
73ae5ef5bc
@ -0,0 +1,5 @@
|
||||
---
|
||||
'svelte': patch
|
||||
---
|
||||
|
||||
fix: handle event attribute spreading with event delegation
|
@ -0,0 +1,18 @@
|
||||
import { test } from '../../test';
|
||||
|
||||
// Checks that event handlers are not hoisted when one of them is not delegateable
|
||||
export default test({
|
||||
html: `<button>0</button>`,
|
||||
|
||||
async test({ assert, target }) {
|
||||
const [button] = target.querySelectorAll('button');
|
||||
|
||||
button.click();
|
||||
await Promise.resolve();
|
||||
assert.htmlEqual(target.innerHTML, '<button>1</button>');
|
||||
|
||||
button.dispatchEvent(new MouseEvent('mouseenter'));
|
||||
await Promise.resolve();
|
||||
assert.htmlEqual(target.innerHTML, '<button>2</button>');
|
||||
}
|
||||
});
|
@ -0,0 +1,11 @@
|
||||
<script>
|
||||
let count = $state(0)
|
||||
|
||||
function increment() {
|
||||
count += 1
|
||||
}
|
||||
</script>
|
||||
|
||||
<button onclick={increment} onmouseenter={increment}>
|
||||
{count}
|
||||
</button>
|
@ -0,0 +1,67 @@
|
||||
import { flushSync } from 'svelte';
|
||||
import { test } from '../../test';
|
||||
|
||||
export default test({
|
||||
html: `
|
||||
<button>click me</button>
|
||||
<button>click me</button>
|
||||
<button>click me</button>
|
||||
<button>click me</button>
|
||||
`,
|
||||
|
||||
async test({ assert, target }) {
|
||||
const [b1, b2, b3, b4] = target.querySelectorAll('button');
|
||||
|
||||
flushSync(() => {
|
||||
b1?.click();
|
||||
});
|
||||
assert.htmlEqual(
|
||||
target.innerHTML,
|
||||
`
|
||||
<button>click spread</button>
|
||||
<button>click spread</button>
|
||||
<button>click spread</button>
|
||||
<button>click spread</button>
|
||||
`
|
||||
);
|
||||
|
||||
flushSync(() => {
|
||||
b2?.click();
|
||||
});
|
||||
assert.htmlEqual(
|
||||
target.innerHTML,
|
||||
`
|
||||
<button>click onclick</button>
|
||||
<button>click onclick</button>
|
||||
<button>click onclick</button>
|
||||
<button>click onclick</button>
|
||||
`
|
||||
);
|
||||
|
||||
flushSync(() => {
|
||||
b3?.click();
|
||||
});
|
||||
assert.htmlEqual(
|
||||
target.innerHTML,
|
||||
`
|
||||
<button>click spread</button>
|
||||
<button>click spread</button>
|
||||
<button>click spread!</button>
|
||||
<button>click spread!</button>
|
||||
`
|
||||
);
|
||||
|
||||
flushSync(() => {
|
||||
b4?.click();
|
||||
});
|
||||
assert.htmlEqual(
|
||||
target.innerHTML,
|
||||
`
|
||||
<button>click onclick</button>
|
||||
<button>click onclick</button>
|
||||
<button>click onclick?</button>
|
||||
<button>click onclick?</button>
|
||||
`
|
||||
);
|
||||
}
|
||||
});
|
@ -0,0 +1,21 @@
|
||||
<script>
|
||||
let text = $state('click me');
|
||||
let text2 = $state('');
|
||||
let spread = { onclick: () => text = 'click spread' };
|
||||
</script>
|
||||
|
||||
<button onclick={() => text = 'click onclick'} {...spread}>
|
||||
{text}
|
||||
</button>
|
||||
|
||||
<button {...spread} onclick={() => text = 'click onclick'}>
|
||||
{text}
|
||||
</button>
|
||||
|
||||
<button onclick={() => text = 'click onclick'} {...spread} on:click={() => text2 = '!'}>
|
||||
{text}{text2}
|
||||
</button>
|
||||
|
||||
<button on:click={() => text2 = '?'} {...spread} onclick={() => text = 'click onclick'}>
|
||||
{text}{text2}
|
||||
</button>
|
Loading…
Reference in new issue