Skip to content

Commit bc32b7c

Browse files
authored
fix: ensure rest props access on hoisted event handlers works (#12298)
If an even handler is hoisted and said event handler access rest props, we can't be sure whether or not it will access it via `$$props` (optimized) or via `rest()` - therefore we add both as params in this edge case fixes #12279
1 parent 8026377 commit bc32b7c

File tree

5 files changed

+34
-0
lines changed

5 files changed

+34
-0
lines changed

.changeset/loud-insects-arrive.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: ensure rest props access on hoisted event handlers works

packages/svelte/src/compiler/phases/3-transform/client/utils.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -547,6 +547,11 @@ function get_hoistable_params(node, context) {
547547
} else {
548548
// create a copy to remove start/end tags which would mess up source maps
549549
push_unique(b.id(binding.node.name));
550+
// rest props are often accessed through the $$props object for optimization reasons,
551+
// but we can't know if the delegated event handler will use it, so we need to add both as params
552+
if (binding.kind === 'rest_prop' && context.state.analysis.runes) {
553+
push_unique(b.id('$$props'));
554+
}
550555
}
551556
}
552557
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { flushSync } from 'svelte';
2+
import { test } from '../../test';
3+
4+
export default test({
5+
mode: ['client'],
6+
test({ assert, target, logs }) {
7+
const btn = target.querySelector('button');
8+
9+
btn?.click();
10+
flushSync();
11+
12+
assert.deepEqual(logs, ['worked']);
13+
}
14+
});
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<script>
2+
let { label, ...rest } = $props();
3+
</script>
4+
5+
<button onclick={() => rest?.onclick()}>{label}</button>
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<script>
2+
import Child from './child.svelte';
3+
</script>
4+
5+
<Child label="click me" onclick={() => console.log('worked')} />

0 commit comments

Comments
 (0)