fix: apply dynamic event fixes to OnDirective (#12582)

* fix: apply dynamic event fixes to OnDirective

* build
pull/12588/head
Dominic Gannaway 4 months ago committed by GitHub
parent 528d3468d0
commit 37f58cf318
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -0,0 +1,5 @@
---
'svelte': patch
---
fix: apply dynamic event fixes to OnDirective

@ -612,7 +612,11 @@ function read_attribute(parser) {
type, type,
name: directive_name, name: directive_name,
modifiers, modifiers,
expression expression,
metadata: {
dynamic: false,
contains_call_expression: false
}
}; };
if (directive.type === 'ClassDirective') { if (directive.type === 'ClassDirective') {

@ -1299,7 +1299,9 @@ const common_visitors = {
CallExpression(node, context) { CallExpression(node, context) {
const { expression, render_tag } = context.state; const { expression, render_tag } = context.state;
if ( if (
(expression?.type === 'ExpressionTag' || expression?.type === 'SpreadAttribute') && (expression?.type === 'ExpressionTag' ||
expression?.type === 'SpreadAttribute' ||
expression?.type === 'OnDirective') &&
!is_known_safe_call(node, context) !is_known_safe_call(node, context)
) { ) {
expression.metadata.contains_call_expression = true; expression.metadata.contains_call_expression = true;
@ -1367,7 +1369,7 @@ const common_visitors = {
if (parent?.type === 'SvelteElement' || parent?.type === 'RegularElement') { if (parent?.type === 'SvelteElement' || parent?.type === 'RegularElement') {
state.analysis.event_directive_node ??= node; state.analysis.event_directive_node ??= node;
} }
next(); next({ ...state, expression: node });
}, },
BindDirective(node, context) { BindDirective(node, context) {
let i = context.path.length; let i = context.path.length;

@ -3,6 +3,7 @@ import type { ComponentAnalysis, ReactiveStatement } from '../types.js';
import type { import type {
ClassDirective, ClassDirective,
ExpressionTag, ExpressionTag,
OnDirective,
RenderTag, RenderTag,
SpreadAttribute, SpreadAttribute,
SvelteNode, SvelteNode,
@ -20,7 +21,7 @@ export interface AnalysisState {
/** Which slots the current parent component has */ /** Which slots the current parent component has */
component_slots: Set<string>; component_slots: Set<string>;
/** The current {expression}, if any */ /** The current {expression}, if any */
expression: ExpressionTag | ClassDirective | SpreadAttribute | null; expression: ExpressionTag | ClassDirective | OnDirective | SpreadAttribute | null;
/** The current {@render ...} tag, if any */ /** The current {@render ...} tag, if any */
render_tag: null | RenderTag; render_tag: null | RenderTag;
private_derived_state: string[]; private_derived_state: string[];

@ -2838,7 +2838,7 @@ export const template_visitors = {
context.next({ ...context.state, in_constructor: false }); context.next({ ...context.state, in_constructor: false });
}, },
OnDirective(node, context) { OnDirective(node, context) {
serialize_event(node, null, context); serialize_event(node, node.metadata, context);
}, },
UseDirective(node, { state, next, visit }) { UseDirective(node, { state, next, visit }) {
const params = [b.id('$$node')]; const params = [b.id('$$node')];

@ -211,6 +211,10 @@ export interface OnDirective extends BaseNode {
/** The 'y' in `on:x={y}` */ /** The 'y' in `on:x={y}` */
expression: null | Expression; expression: null | Expression;
modifiers: string[]; // TODO specify modifiers: string[]; // TODO specify
metadata: {
contains_call_expression: boolean;
dynamic: boolean;
};
} }
export type DelegatedEvent = export type DelegatedEvent =

@ -0,0 +1,26 @@
import { test } from '../../test';
export default test({
html: '<button>Tama</button><button>Pochi</button><br><button>Change Function</button>',
test({ assert, logs, target }) {
const [b1, b2, b3] = target.querySelectorAll('button');
b1?.click();
b2?.click();
b3?.click();
b1?.click();
b2?.click();
assert.deepEqual(logs, [
'creating "Hello" handler for Tama',
'Hello Tama',
'creating "Hello" handler for Pochi',
'Hello Pochi',
'creating "Bye" handler for Tama',
'Bye Tama',
'creating "Bye" handler for Pochi',
'Bye Pochi'
]);
}
});

@ -0,0 +1,19 @@
<script>
let saySomething = $state(name => {
console.log('creating "Hello" handler for ' + name);
return { handler: () => console.log('Hello ' + name) };
});
function change() {
saySomething = name => {
console.log('creating "Bye" handler for ' + name);
return { handler: () => console.log('Bye ' + name) };
}
}
</script>
<button on:click={saySomething('Tama').handler}>Tama</button>
<button on:click={saySomething('Pochi').handler}>Pochi</button>
<br>
<button on:click={change}>Change Function</button>

@ -1636,6 +1636,10 @@ declare module 'svelte/compiler' {
/** The 'y' in `on:x={y}` */ /** The 'y' in `on:x={y}` */
expression: null | Expression; expression: null | Expression;
modifiers: string[]; // TODO specify modifiers: string[]; // TODO specify
metadata: {
contains_call_expression: boolean;
dynamic: boolean;
};
} }
type DelegatedEvent = type DelegatedEvent =

Loading…
Cancel
Save