@@ -7,13 +7,12 @@ import {
7
7
PlainElementNode ,
8
8
ComponentNode ,
9
9
TemplateNode ,
10
- ElementNode ,
11
10
VNodeCall ,
12
11
ParentNode
13
12
} from '../ast'
14
13
import { TransformContext } from '../transform'
15
14
import { PatchFlags , isString , isSymbol } from '@vue/shared'
16
- import { isSlotOutlet , findProp } from '../utils'
15
+ import { isSlotOutlet } from '../utils'
17
16
18
17
export function hoistStatic ( root : RootNode , context : TransformContext ) {
19
18
walk (
@@ -93,8 +92,7 @@ function walk(
93
92
( ! flag ||
94
93
flag === PatchFlags . NEED_PATCH ||
95
94
flag === PatchFlags . TEXT ) &&
96
- ! hasDynamicKeyOrRef ( child ) &&
97
- ! hasCachedProps ( child )
95
+ ! hasNonHoistableProps ( child )
98
96
) {
99
97
const props = getNodeProps ( child )
100
98
if ( props ) {
@@ -156,7 +154,7 @@ export function getStaticType(
156
154
return StaticType . NOT_STATIC
157
155
}
158
156
const flag = getPatchFlag ( codegenNode )
159
- if ( ! flag && ! hasDynamicKeyOrRef ( node ) && ! hasCachedProps ( node ) ) {
157
+ if ( ! flag && ! hasNonHoistableProps ( node ) ) {
160
158
// element self is static. check its children.
161
159
let returnType = StaticType . FULL_STATIC
162
160
for ( let i = 0 ; i < node . children . length ; i ++ ) {
@@ -238,28 +236,23 @@ export function getStaticType(
238
236
}
239
237
}
240
238
241
- function hasDynamicKeyOrRef ( node : ElementNode ) : boolean {
242
- return ! ! ( findProp ( node , 'key' , true ) || findProp ( node , 'ref' , true ) )
243
- }
244
-
245
- function hasCachedProps ( node : PlainElementNode ) : boolean {
246
- if ( __BROWSER__ ) {
247
- return false
248
- }
239
+ /**
240
+ * Even for a node with no patch flag, it is possible for it to contain
241
+ * non-hoistable expressions that refers to scope variables, e.g. compiler
242
+ * injected keys or cached event handlers. Therefore we need to always check the
243
+ * codegenNode's props to be sure.
244
+ */
245
+ function hasNonHoistableProps ( node : PlainElementNode ) : boolean {
249
246
const props = getNodeProps ( node )
250
247
if ( props && props . type === NodeTypes . JS_OBJECT_EXPRESSION ) {
251
248
const { properties } = props
252
249
for ( let i = 0 ; i < properties . length ; i ++ ) {
253
- const val = properties [ i ] . value
254
- if ( val . type === NodeTypes . JS_CACHE_EXPRESSION ) {
255
- return true
256
- }
257
- // merged event handlers
250
+ const { key, value } = properties [ i ]
258
251
if (
259
- val . type === NodeTypes . JS_ARRAY_EXPRESSION &&
260
- val . elements . some (
261
- e => ! isString ( e ) && e . type === NodeTypes . JS_CACHE_EXPRESSION
262
- )
252
+ key . type !== NodeTypes . SIMPLE_EXPRESSION ||
253
+ ! key . isStatic ||
254
+ ( value . type !== NodeTypes . SIMPLE_EXPRESSION ||
255
+ ( ! value . isStatic && ! value . isConstant ) )
263
256
) {
264
257
return true
265
258
}
0 commit comments