test: tests for hoistStatic

This commit is contained in:
Evan You
2019-10-07 17:12:22 -04:00
parent 802ecccc49
commit 57a5c61320
9 changed files with 655 additions and 83 deletions

View File

@@ -5,20 +5,42 @@ import {
ElementNode,
ElementTypes,
ElementCodegenNode,
ElementCodegenNodeWithDirective
ElementCodegenNodeWithDirective,
PlainElementNode,
ComponentNode,
TemplateNode
} from '../ast'
import { TransformContext } from '../transform'
import { APPLY_DIRECTIVES } from '../runtimeHelpers'
import { PatchFlags } from '@vue/shared'
import { isSlotOutlet } from '../utils'
export function hoistStatic(root: RootNode, context: TransformContext) {
walk(root.children, context, new Map<TemplateChildNode, boolean>())
walk(
root.children,
context,
new Map(),
isSingleElementRoot(root, root.children[0])
)
}
export function isSingleElementRoot(
root: RootNode,
child: TemplateChildNode
): child is PlainElementNode | ComponentNode | TemplateNode {
const { children } = root
return (
children.length === 1 &&
child.type === NodeTypes.ELEMENT &&
!isSlotOutlet(child)
)
}
function walk(
children: TemplateChildNode[],
context: TransformContext,
resultCache: Map<TemplateChildNode, boolean>
resultCache: Map<TemplateChildNode, boolean>,
doNotHoistNode: boolean = false
) {
for (let i = 0; i < children.length; i++) {
const child = children[i]
@@ -27,7 +49,7 @@ function walk(
child.type === NodeTypes.ELEMENT &&
child.tagType === ElementTypes.ELEMENT
) {
if (isStaticNode(child, resultCache)) {
if (!doNotHoistNode && isStaticNode(child, resultCache)) {
// whole tree is static
;(child as any).codegenNode = context.hoist(child.codegenNode!)
continue
@@ -51,11 +73,16 @@ function walk(
}
}
}
if (child.type === NodeTypes.ELEMENT || child.type === NodeTypes.FOR) {
if (child.type === NodeTypes.ELEMENT) {
walk(child.children, context, resultCache)
} else if (child.type === NodeTypes.FOR) {
// Do not hoist v-for single child because it has to be a block
walk(child.children, context, resultCache, child.children.length === 1)
} else if (child.type === NodeTypes.IF) {
for (let i = 0; i < child.branches.length; i++) {
walk(child.branches[i].children, context, resultCache)
const branchChildren = child.branches[i].children
// Do not hoist v-if single child because it has to be a block
walk(branchChildren, context, resultCache, branchChildren.length === 1)
}
}
}