File tree 2 files changed +22
-3
lines changed
2 files changed +22
-3
lines changed Original file line number Diff line number Diff line change @@ -13,7 +13,7 @@ import { transformElement } from '../../src/transforms/transformElement'
13
13
import { transformExpression } from '../../src/transforms/transformExpression'
14
14
15
15
function parseWithVOn ( template : string , options : CompilerOptions = { } ) {
16
- const ast = parse ( template )
16
+ const ast = parse ( template , options )
17
17
transform ( ast , {
18
18
nodeTransforms : [ transformExpression , transformElement ] ,
19
19
directiveTransforms : {
@@ -405,6 +405,15 @@ describe('compiler: transform v-on', () => {
405
405
} )
406
406
} )
407
407
408
+ test ( 'bail on component member expression handler' , ( ) => {
409
+ const { root } = parseWithVOn ( `<comp v-on:click="foo" />` , {
410
+ prefixIdentifiers : true ,
411
+ cacheHandlers : true ,
412
+ isNativeTag : tag => tag === 'div'
413
+ } )
414
+ expect ( root . cached ) . toBe ( 0 )
415
+ } )
416
+
408
417
test ( 'inline function expression handler' , ( ) => {
409
418
const { root, node } = parseWithVOn ( `<div v-on:click="() => foo()" />` , {
410
419
prefixIdentifiers : true ,
Original file line number Diff line number Diff line change 6
6
ExpressionNode ,
7
7
NodeTypes ,
8
8
createCompoundExpression ,
9
- SimpleExpressionNode
9
+ SimpleExpressionNode ,
10
+ ElementTypes
10
11
} from '../ast'
11
12
import { capitalize , camelize } from '@vue/shared'
12
13
import { createCompilerError , ErrorCodes } from '../errors'
@@ -76,7 +77,16 @@ export const transformOn: DirectiveTransform = (
76
77
// with scope analysis, the function is hoistable if it has no reference
77
78
// to scope variables.
78
79
isCacheable =
79
- context . cacheHandlers && ! hasScopeRef ( exp , context . identifiers )
80
+ context . cacheHandlers &&
81
+ // #1541 bail if this is a member exp handler passed to a component -
82
+ // we need to use the original function to preserve arity,
83
+ // e.g. <transition> relies on checking cb.length to determine
84
+ // transition end handling. Inline function is ok since its arity
85
+ // is preserved even when cached.
86
+ ! ( isMemberExp && node . tagType === ElementTypes . COMPONENT ) &&
87
+ // bail if the function references closure variables (v-for, v-slot)
88
+ // it must be passed fresh to avoid stale values.
89
+ ! hasScopeRef ( exp , context . identifiers )
80
90
// If the expression is optimizable and is a member expression pointing
81
91
// to a function, turn it into invocation (and wrap in an arrow function
82
92
// below) so that it always accesses the latest value when called - thus
You can’t perform that action at this time.
0 commit comments