@ -714,7 +714,7 @@ function serialize_inline_component(node, component_name, context, anchor = cont
lets . push ( /** @type {ExpressionStatement} */ ( context . visit ( attribute ) ) ) ;
lets . push ( /** @type {ExpressionStatement} */ ( context . visit ( attribute ) ) ) ;
} else if ( attribute . type === 'OnDirective' ) {
} else if ( attribute . type === 'OnDirective' ) {
events [ attribute . name ] || = [ ] ;
events [ attribute . name ] || = [ ] ;
let handler = serialize _event _handler ( attribute , context ) ;
let handler = serialize _event _handler ( attribute , null , context ) ;
if ( attribute . modifiers . includes ( 'once' ) ) {
if ( attribute . modifiers . includes ( 'once' ) ) {
handler = b . call ( '$.once' , handler ) ;
handler = b . call ( '$.once' , handler ) ;
}
}
@ -1122,9 +1122,10 @@ function serialize_render_stmt(update) {
/ * *
/ * *
* Serializes the event handler function of the ` on: ` directive
* Serializes the event handler function of the ` on: ` directive
* @ param { Pick < import ( '#compiler' ) . OnDirective , 'name' | 'modifiers' | 'expression' > } node
* @ param { Pick < import ( '#compiler' ) . OnDirective , 'name' | 'modifiers' | 'expression' > } node
* @ param { null | { contains _call _expression : boolean ; dynamic : boolean ; } | null } metadata
* @ param { import ( '../types.js' ) . ComponentContext } context
* @ param { import ( '../types.js' ) . ComponentContext } context
* /
* /
function serialize _event _handler ( node , { state , visit } ) {
function serialize _event _handler ( node , metadata , { state , visit } ) {
/** @type {Expression} */
/** @type {Expression} */
let handler ;
let handler ;
@ -1166,10 +1167,33 @@ function serialize_event_handler(node, { state, visit }) {
handler = /** @type {Expression} */ ( visit ( handler ) ) ;
handler = /** @type {Expression} */ ( visit ( handler ) ) ;
}
}
} else if (
} else if (
handler . type === 'CallExpression' ||
metadata ? . contains _call _expression &&
handler . type === 'ConditionalExpression' ||
! (
handler . type === 'LogicalExpression'
( handler . type === 'ArrowFunctionExpression' || handler . type === 'FunctionExpression' ) &&
handler . metadata . hoistable
)
) {
) {
// Create a derived dynamic event handler
const id = b . id ( state . scope . generate ( 'event_handler' ) ) ;
state . init . push (
b . var ( id , b . call ( '$.derived' , b . thunk ( /** @type {Expression} */ ( visit ( handler ) ) ) ) )
) ;
handler = b . function (
null ,
[ b . rest ( b . id ( '$$args' ) ) ] ,
b . block ( [
b . return (
b . call (
b . member ( b . call ( '$.get' , id ) , b . id ( 'apply' ) , false , true ) ,
b . this ,
b . id ( '$$args' )
)
)
] )
) ;
} else if ( handler . type === 'ConditionalExpression' || handler . type === 'LogicalExpression' ) {
handler = dynamic _handler ( ) ;
handler = dynamic _handler ( ) ;
} else {
} else {
handler = /** @type {Expression} */ ( visit ( handler ) ) ;
handler = /** @type {Expression} */ ( visit ( handler ) ) ;
@ -1206,17 +1230,18 @@ function serialize_event_handler(node, { state, visit }) {
/ * *
/ * *
* Serializes an event handler function of the ` on: ` directive or an attribute starting with ` on `
* Serializes an event handler function of the ` on: ` directive or an attribute starting with ` on `
* @ param { { name : string ; modifiers : string [ ] ; expression : Expression | null ; delegated ? : import ( '#compiler' ) . DelegatedEvent | null ; } } node
* @ param { { name : string ; modifiers : string [ ] ; expression : Expression | null ; delegated ? : import ( '#compiler' ) . DelegatedEvent | null ; } } node
* @ param { null | { contains _call _expression : boolean ; dynamic : boolean ; } } metadata
* @ param { import ( '../types.js' ) . ComponentContext } context
* @ param { import ( '../types.js' ) . ComponentContext } context
* /
* /
function serialize _event ( node , context) {
function serialize _event ( node , metadata, context) {
const state = context . state ;
const state = context . state ;
/** @type {Statement} */
/** @type {Statement} */
let statement ;
let statement ;
if ( node . expression ) {
if ( node . expression ) {
let handler = serialize _event _handler ( node , context) ;
let handler = serialize _event _handler ( node , metadata, context) ;
const event _name = node . name ;
const event _name = node . name ;
const delegated = node . delegated ;
const delegated = node . delegated ;
@ -1285,7 +1310,12 @@ function serialize_event(node, context) {
statement = b . stmt ( b . call ( '$.event' , ... args ) ) ;
statement = b . stmt ( b . call ( '$.event' , ... args ) ) ;
} else {
} else {
statement = b . stmt (
statement = b . stmt (
b . call ( '$.event' , b . literal ( node . name ) , state . node , serialize _event _handler ( node , context ) )
b . call (
'$.event' ,
b . literal ( node . name ) ,
state . node ,
serialize _event _handler ( node , metadata , context )
)
) ;
) ;
}
}
@ -1323,6 +1353,7 @@ function serialize_event_attribute(node, context) {
modifiers ,
modifiers ,
delegated : node . metadata . delegated
delegated : node . metadata . delegated
} ,
} ,
! Array . isArray ( node . value ) && node . value ? . type === 'ExpressionTag' ? node . value . metadata : null ,
context
context
) ;
) ;
}
}
@ -2797,7 +2828,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 , context ) ;
serialize _event ( node , null , context ) ;
} ,
} ,
UseDirective ( node , { state , next , visit } ) {
UseDirective ( node , { state , next , visit } ) {
const params = [ b . id ( '$$node' ) ] ;
const params = [ b . id ( '$$node' ) ] ;