Skip to content

Commit a5f500e

Browse files
authored
fix: keep spread non-delegated event handlers up to date (#16180)
* fix: keep spread non-delegated event handlers up to date #15961 introduced a regression where non-delegated events that were spread and updated were not getting updated. This fixes that by ensuring prev is actually updated to the most recent value * fix
1 parent 838f881 commit a5f500e

File tree

4 files changed

+55
-3
lines changed

4 files changed

+55
-3
lines changed

.changeset/odd-readers-laugh.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'svelte': patch
3+
---
4+
5+
fix: keep spread non-delegated event handlers up to date

packages/svelte/src/internal/client/dom/elements/attributes.js

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -483,8 +483,8 @@ export function attribute_effect(
483483

484484
block(() => {
485485
var next = fn(...deriveds.map(get));
486-
487-
set_attributes(element, prev, next, css_hash, skip_warning);
486+
/** @type {Record<string | symbol, any>} */
487+
var current = set_attributes(element, prev, next, css_hash, skip_warning);
488488

489489
if (inited && is_select && 'value' in next) {
490490
select_option(/** @type {HTMLSelectElement} */ (element), next.value, false);
@@ -501,9 +501,11 @@ export function attribute_effect(
501501
if (effects[symbol]) destroy_effect(effects[symbol]);
502502
effects[symbol] = branch(() => attach(element, () => n));
503503
}
504+
505+
current[symbol] = n;
504506
}
505507

506-
prev = next;
508+
prev = current;
507509
});
508510

509511
if (is_select) {
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { flushSync } from 'svelte';
2+
import { test } from '../../test';
3+
4+
export default test({
5+
test({ assert, target }) {
6+
const [change, increment] = target.querySelectorAll('button');
7+
8+
increment.click();
9+
flushSync();
10+
assert.htmlEqual(target.innerHTML, '<button>change handlers</button><button>1 / 1</button>');
11+
12+
change.click();
13+
flushSync();
14+
increment.click();
15+
flushSync();
16+
assert.htmlEqual(target.innerHTML, '<button>change handlers</button><button>3 / 3</button>');
17+
}
18+
});
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<script>
2+
let delegated = $state(0);
3+
let non_delegated = $state(0);
4+
let attrs = $state({
5+
onclick: () => {
6+
delegated += 1;
7+
},
8+
onclickcapture: () => {
9+
non_delegated += 1;
10+
}
11+
});
12+
</script>
13+
14+
<button
15+
onclick={() =>
16+
(attrs = {
17+
onclick: () => {
18+
delegated += 2;
19+
},
20+
onclickcapture: () => {
21+
non_delegated += 2;
22+
}
23+
})}
24+
>
25+
change handlers
26+
</button>
27+
<button {...attrs}>{delegated} / {non_delegated}</button>

0 commit comments

Comments
 (0)