diff --git a/packages/svelte/src/compiler/phases/3-transform/client/visitors/shared/events.js b/packages/svelte/src/compiler/phases/3-transform/client/visitors/shared/events.js index f23f7548ec..a88d656ddb 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/visitors/shared/events.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/visitors/shared/events.js @@ -46,8 +46,12 @@ export function visit_event_attribute(node, context) { // When we hoist a function we assign an array with the function and all // hoisted closure params. - const args = [handler, ...hoisted_params]; - delegated_assignment = b.array(args); + if (hoisted_params) { + const args = [handler, ...hoisted_params]; + delegated_assignment = b.array(args); + } else { + delegated_assignment = handler; + } } else { delegated_assignment = handler; } @@ -123,11 +127,17 @@ export function build_event_handler(node, metadata, context) { } // function declared in the script - if ( - handler.type === 'Identifier' && - context.state.scope.get(handler.name)?.declaration_kind !== 'import' - ) { - return handler; + if (handler.type === 'Identifier') { + const kind = context.state.scope.get(handler.name)?.declaration_kind; + if (kind === 'function') { + return handler; + } + // local variable can be assigned directly + // except in dev mode where when need $.apply() + // in order to handle warnings. + if (!dev && kind !== 'import') { + return handler; + } } if (metadata.has_call) { diff --git a/packages/svelte/src/internal/client/dom/elements/events.js b/packages/svelte/src/internal/client/dom/elements/events.js index 25ece5f569..0c1bb1dada 100644 --- a/packages/svelte/src/internal/client/dom/elements/events.js +++ b/packages/svelte/src/internal/client/dom/elements/events.js @@ -238,7 +238,7 @@ export function handle_event_propagation(event) { var delegated = current_target['__' + event_name]; if ( - delegated !== undefined && + delegated != null && (!(/** @type {any} */ (current_target).disabled) || // DOM could've been updated already by the time this is reached, so we check this as well // -> the target could not have been disabled because it emits the event in the first place @@ -311,13 +311,11 @@ export function apply( error = e; } - if (typeof handler === 'function') { - handler.apply(element, args); - } else if (has_side_effects || handler != null || error) { + if (typeof handler !== 'function' && (has_side_effects || handler != null || error)) { const filename = component?.[FILENAME]; const location = loc ? ` at ${filename}:${loc[0]}:${loc[1]}` : ` in ${filename}`; - - const event_name = args[0].type; + const phase = args[0]?.eventPhase < Event.BUBBLING_PHASE ? 'capture' : ''; + const event_name = args[0]?.type + phase; const description = `\`${event_name}\` handler${location}`; const suggestion = remove_parens ? 'remove the trailing `()`' : 'add a leading `() =>`'; @@ -327,4 +325,5 @@ export function apply( throw error; } } + handler?.apply(element, args); }