refactor(compiler-core): simplify hoistStatic check for nodes without patchFlag
close #1912
This commit is contained in:
parent
255a2bd178
commit
91700fbec2
@ -271,6 +271,22 @@ return function render(_ctx, _cache) {
|
|||||||
}"
|
}"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`compiler: hoistStatic transform prefixIdentifiers should NOT hoist keyed template v-for with plain element child 1`] = `
|
||||||
|
"const _Vue = Vue
|
||||||
|
|
||||||
|
return function render(_ctx, _cache) {
|
||||||
|
with (_ctx) {
|
||||||
|
const { renderList: _renderList, Fragment: _Fragment, openBlock: _openBlock, createBlock: _createBlock, createVNode: _createVNode } = _Vue
|
||||||
|
|
||||||
|
return (_openBlock(), _createBlock(\\"div\\", null, [
|
||||||
|
(_openBlock(true), _createBlock(_Fragment, null, _renderList(items, (item) => {
|
||||||
|
return (_openBlock(), _createBlock(\\"span\\", { key: item }))
|
||||||
|
}), 128 /* KEYED_FRAGMENT */))
|
||||||
|
]))
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
exports[`compiler: hoistStatic transform should NOT hoist components 1`] = `
|
exports[`compiler: hoistStatic transform should NOT hoist components 1`] = `
|
||||||
"const _Vue = Vue
|
"const _Vue = Vue
|
||||||
|
|
||||||
|
@ -600,5 +600,13 @@ describe('compiler: hoistStatic transform', () => {
|
|||||||
}).code
|
}).code
|
||||||
).toMatchSnapshot()
|
).toMatchSnapshot()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test('should NOT hoist keyed template v-for with plain element child', () => {
|
||||||
|
const root = transformWithHoist(
|
||||||
|
`<div><template v-for="item in items" :key="item"><span/></template></div>`
|
||||||
|
)
|
||||||
|
expect(root.hoists.length).toBe(0)
|
||||||
|
expect(generate(root).code).toMatchSnapshot()
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -7,13 +7,12 @@ import {
|
|||||||
PlainElementNode,
|
PlainElementNode,
|
||||||
ComponentNode,
|
ComponentNode,
|
||||||
TemplateNode,
|
TemplateNode,
|
||||||
ElementNode,
|
|
||||||
VNodeCall,
|
VNodeCall,
|
||||||
ParentNode
|
ParentNode
|
||||||
} from '../ast'
|
} from '../ast'
|
||||||
import { TransformContext } from '../transform'
|
import { TransformContext } from '../transform'
|
||||||
import { PatchFlags, isString, isSymbol } from '@vue/shared'
|
import { PatchFlags, isString, isSymbol } from '@vue/shared'
|
||||||
import { isSlotOutlet, findProp } from '../utils'
|
import { isSlotOutlet } from '../utils'
|
||||||
|
|
||||||
export function hoistStatic(root: RootNode, context: TransformContext) {
|
export function hoistStatic(root: RootNode, context: TransformContext) {
|
||||||
walk(
|
walk(
|
||||||
@ -93,8 +92,7 @@ function walk(
|
|||||||
(!flag ||
|
(!flag ||
|
||||||
flag === PatchFlags.NEED_PATCH ||
|
flag === PatchFlags.NEED_PATCH ||
|
||||||
flag === PatchFlags.TEXT) &&
|
flag === PatchFlags.TEXT) &&
|
||||||
!hasDynamicKeyOrRef(child) &&
|
!hasNonHoistableProps(child)
|
||||||
!hasCachedProps(child)
|
|
||||||
) {
|
) {
|
||||||
const props = getNodeProps(child)
|
const props = getNodeProps(child)
|
||||||
if (props) {
|
if (props) {
|
||||||
@ -156,7 +154,7 @@ export function getStaticType(
|
|||||||
return StaticType.NOT_STATIC
|
return StaticType.NOT_STATIC
|
||||||
}
|
}
|
||||||
const flag = getPatchFlag(codegenNode)
|
const flag = getPatchFlag(codegenNode)
|
||||||
if (!flag && !hasDynamicKeyOrRef(node) && !hasCachedProps(node)) {
|
if (!flag && !hasNonHoistableProps(node)) {
|
||||||
// element self is static. check its children.
|
// element self is static. check its children.
|
||||||
let returnType = StaticType.FULL_STATIC
|
let returnType = StaticType.FULL_STATIC
|
||||||
for (let i = 0; i < node.children.length; i++) {
|
for (let i = 0; i < node.children.length; i++) {
|
||||||
@ -238,28 +236,23 @@ export function getStaticType(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function hasDynamicKeyOrRef(node: ElementNode): boolean {
|
/**
|
||||||
return !!(findProp(node, 'key', true) || findProp(node, 'ref', true))
|
* Even for a node with no patch flag, it is possible for it to contain
|
||||||
}
|
* non-hoistable expressions that refers to scope variables, e.g. compiler
|
||||||
|
* injected keys or cached event handlers. Therefore we need to always check the
|
||||||
function hasCachedProps(node: PlainElementNode): boolean {
|
* codegenNode's props to be sure.
|
||||||
if (__BROWSER__) {
|
*/
|
||||||
return false
|
function hasNonHoistableProps(node: PlainElementNode): boolean {
|
||||||
}
|
|
||||||
const props = getNodeProps(node)
|
const props = getNodeProps(node)
|
||||||
if (props && props.type === NodeTypes.JS_OBJECT_EXPRESSION) {
|
if (props && props.type === NodeTypes.JS_OBJECT_EXPRESSION) {
|
||||||
const { properties } = props
|
const { properties } = props
|
||||||
for (let i = 0; i < properties.length; i++) {
|
for (let i = 0; i < properties.length; i++) {
|
||||||
const val = properties[i].value
|
const { key, value } = properties[i]
|
||||||
if (val.type === NodeTypes.JS_CACHE_EXPRESSION) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
// merged event handlers
|
|
||||||
if (
|
if (
|
||||||
val.type === NodeTypes.JS_ARRAY_EXPRESSION &&
|
key.type !== NodeTypes.SIMPLE_EXPRESSION ||
|
||||||
val.elements.some(
|
!key.isStatic ||
|
||||||
e => !isString(e) && e.type === NodeTypes.JS_CACHE_EXPRESSION
|
(value.type !== NodeTypes.SIMPLE_EXPRESSION ||
|
||||||
)
|
(!value.isStatic && !value.isConstant))
|
||||||
) {
|
) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,8 @@ import {
|
|||||||
BlockCodegenNode,
|
BlockCodegenNode,
|
||||||
IfNode,
|
IfNode,
|
||||||
createVNodeCall,
|
createVNodeCall,
|
||||||
AttributeNode
|
AttributeNode,
|
||||||
|
locStub
|
||||||
} from '../ast'
|
} from '../ast'
|
||||||
import { createCompilerError, ErrorCodes } from '../errors'
|
import { createCompilerError, ErrorCodes } from '../errors'
|
||||||
import { processExpression } from './transformExpression'
|
import { processExpression } from './transformExpression'
|
||||||
@ -222,7 +223,7 @@ function createChildrenCodegenNode(
|
|||||||
const { helper } = context
|
const { helper } = context
|
||||||
const keyProperty = createObjectProperty(
|
const keyProperty = createObjectProperty(
|
||||||
`key`,
|
`key`,
|
||||||
createSimpleExpression(`${keyIndex}`, false)
|
createSimpleExpression(`${keyIndex}`, false, locStub, true)
|
||||||
)
|
)
|
||||||
const { children } = branch
|
const { children } = branch
|
||||||
const firstChild = children[0]
|
const firstChild = children[0]
|
||||||
|
Loading…
Reference in New Issue
Block a user