Skip to content

Commit c5e5e60

Browse files
committed
fix: improve dynamic event handling
1 parent d17755a commit c5e5e60

File tree

3 files changed

+64
-19
lines changed

3 files changed

+64
-19
lines changed

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

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1148,25 +1148,7 @@ function serialize_event_handler(node, metadata, { state, visit }) {
11481148
])
11491149
);
11501150

1151-
if (handler.type === 'Identifier' || handler.type === 'MemberExpression') {
1152-
const id = object(handler);
1153-
const binding = id === null ? null : state.scope.get(id.name);
1154-
if (
1155-
binding !== null &&
1156-
(binding.kind === 'state' ||
1157-
binding.kind === 'frozen_state' ||
1158-
binding.declaration_kind === 'import' ||
1159-
binding.kind === 'legacy_reactive' ||
1160-
binding.kind === 'derived' ||
1161-
binding.kind === 'prop' ||
1162-
binding.kind === 'bindable_prop' ||
1163-
binding.kind === 'store_sub')
1164-
) {
1165-
handler = dynamic_handler();
1166-
} else {
1167-
handler = /** @type {Expression} */ (visit(handler));
1168-
}
1169-
} else if (
1151+
if (
11701152
metadata?.contains_call_expression &&
11711153
!(
11721154
(handler.type === 'ArrowFunctionExpression' || handler.type === 'FunctionExpression') &&
@@ -1193,6 +1175,24 @@ function serialize_event_handler(node, metadata, { state, visit }) {
11931175
)
11941176
])
11951177
);
1178+
} else if (handler.type === 'Identifier' || handler.type === 'MemberExpression') {
1179+
const id = object(handler);
1180+
const binding = id === null ? null : state.scope.get(id.name);
1181+
if (
1182+
binding !== null &&
1183+
(binding.kind === 'state' ||
1184+
binding.kind === 'frozen_state' ||
1185+
binding.declaration_kind === 'import' ||
1186+
binding.kind === 'legacy_reactive' ||
1187+
binding.kind === 'derived' ||
1188+
binding.kind === 'prop' ||
1189+
binding.kind === 'bindable_prop' ||
1190+
binding.kind === 'store_sub')
1191+
) {
1192+
handler = dynamic_handler();
1193+
} else {
1194+
handler = /** @type {Expression} */ (visit(handler));
1195+
}
11961196
} else if (handler.type === 'ConditionalExpression' || handler.type === 'LogicalExpression') {
11971197
handler = dynamic_handler();
11981198
} else {
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import { test } from '../../test';
2+
3+
export default test({
4+
html: '<button>Tama</button><button>Pochi</button><br><button>Change Function</button>',
5+
6+
test({ assert, logs, target }) {
7+
const [b1, b2, b3] = target.querySelectorAll('button');
8+
9+
b1?.click();
10+
b2?.click();
11+
b3?.click();
12+
b1?.click();
13+
b2?.click();
14+
15+
assert.deepEqual(logs, [
16+
'creating "Hello" handler for Tama',
17+
'Hello Tama',
18+
'creating "Hello" handler for Pochi',
19+
'Hello Pochi',
20+
'creating "Bye" handler for Tama',
21+
'Bye Tama',
22+
'creating "Bye" handler for Pochi',
23+
'Bye Pochi'
24+
]);
25+
}
26+
});
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<script>
2+
let saySomething = $state(name => {
3+
console.log('creating "Hello" handler for ' + name);
4+
return { handler: () => console.log('Hello ' + name) };
5+
});
6+
7+
function change() {
8+
saySomething = name => {
9+
console.log('creating "Bye" handler for ' + name);
10+
return { handler: () => console.log('Bye ' + name) };
11+
}
12+
}
13+
</script>
14+
15+
<button onclick={saySomething('Tama').handler}>Tama</button>
16+
<button onclick={saySomething('Pochi').handler}>Pochi</button>
17+
18+
<br>
19+
<button onclick={change}>Change Function</button>

0 commit comments

Comments
 (0)