Skip to content

Commit 600a7ad

Browse files
committed
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
1 parent 931f211 commit 600a7ad

File tree

4 files changed

+54
-4
lines changed

4 files changed

+54
-4
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: 4 additions & 4 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);
@@ -495,15 +495,15 @@ export function attribute_effect(
495495
}
496496

497497
for (let symbol of Object.getOwnPropertySymbols(next)) {
498-
var n = next[symbol];
498+
var n = (current[symbol] = next[symbol]);
499499

500500
if (symbol.description === ATTACHMENT_KEY && (!prev || n !== prev[symbol])) {
501501
if (effects[symbol]) destroy_effect(effects[symbol]);
502502
effects[symbol] = branch(() => attach(element, () => n));
503503
}
504504
}
505505

506-
prev = next;
506+
prev = current;
507507
});
508508

509509
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)