refactor: cache constant check result on transform context
also fix edge case for missed createVNode import on static svg nodes
This commit is contained in:
parent
ad4d3915d3
commit
a8352506f6
@ -111,6 +111,7 @@ export interface TransformContext
|
|||||||
removeIdentifiers(exp: ExpressionNode | string): void
|
removeIdentifiers(exp: ExpressionNode | string): void
|
||||||
hoist(exp: JSChildNode): SimpleExpressionNode
|
hoist(exp: JSChildNode): SimpleExpressionNode
|
||||||
cache<T extends JSChildNode>(exp: T, isVNode?: boolean): CacheExpression | T
|
cache<T extends JSChildNode>(exp: T, isVNode?: boolean): CacheExpression | T
|
||||||
|
constantCache: Map<TemplateChildNode, ConstantTypes>
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createTransformContext(
|
export function createTransformContext(
|
||||||
@ -163,6 +164,7 @@ export function createTransformContext(
|
|||||||
directives: new Set(),
|
directives: new Set(),
|
||||||
hoists: [],
|
hoists: [],
|
||||||
imports: new Set(),
|
imports: new Set(),
|
||||||
|
constantCache: new Map(),
|
||||||
temps: 0,
|
temps: 0,
|
||||||
cached: 0,
|
cached: 0,
|
||||||
identifiers: Object.create(null),
|
identifiers: Object.create(null),
|
||||||
|
@ -14,12 +14,12 @@ import {
|
|||||||
import { TransformContext } from '../transform'
|
import { TransformContext } from '../transform'
|
||||||
import { PatchFlags, isString, isSymbol } from '@vue/shared'
|
import { PatchFlags, isString, isSymbol } from '@vue/shared'
|
||||||
import { isSlotOutlet } from '../utils'
|
import { isSlotOutlet } from '../utils'
|
||||||
|
import { CREATE_VNODE } from '../runtimeHelpers'
|
||||||
|
|
||||||
export function hoistStatic(root: RootNode, context: TransformContext) {
|
export function hoistStatic(root: RootNode, context: TransformContext) {
|
||||||
walk(
|
walk(
|
||||||
root,
|
root,
|
||||||
context,
|
context,
|
||||||
new Map(),
|
|
||||||
// Root node is unfortunately non-hoistable due to potential parent
|
// Root node is unfortunately non-hoistable due to potential parent
|
||||||
// fallthrough attributes.
|
// fallthrough attributes.
|
||||||
isSingleElementRoot(root, root.children[0])
|
isSingleElementRoot(root, root.children[0])
|
||||||
@ -41,7 +41,6 @@ export function isSingleElementRoot(
|
|||||||
function walk(
|
function walk(
|
||||||
node: ParentNode,
|
node: ParentNode,
|
||||||
context: TransformContext,
|
context: TransformContext,
|
||||||
resultCache: Map<TemplateChildNode, ConstantTypes>,
|
|
||||||
doNotHoistNode: boolean = false
|
doNotHoistNode: boolean = false
|
||||||
) {
|
) {
|
||||||
let hasHoistedNode = false
|
let hasHoistedNode = false
|
||||||
@ -65,7 +64,7 @@ function walk(
|
|||||||
) {
|
) {
|
||||||
const constantType = doNotHoistNode
|
const constantType = doNotHoistNode
|
||||||
? ConstantTypes.NOT_CONSTANT
|
? ConstantTypes.NOT_CONSTANT
|
||||||
: getConstantType(child, resultCache)
|
: getConstantType(child, context)
|
||||||
if (constantType > ConstantTypes.NOT_CONSTANT) {
|
if (constantType > ConstantTypes.NOT_CONSTANT) {
|
||||||
if (constantType < ConstantTypes.CAN_STRINGIFY) {
|
if (constantType < ConstantTypes.CAN_STRINGIFY) {
|
||||||
canStringify = false
|
canStringify = false
|
||||||
@ -87,7 +86,7 @@ function walk(
|
|||||||
(!flag ||
|
(!flag ||
|
||||||
flag === PatchFlags.NEED_PATCH ||
|
flag === PatchFlags.NEED_PATCH ||
|
||||||
flag === PatchFlags.TEXT) &&
|
flag === PatchFlags.TEXT) &&
|
||||||
getGeneratedPropsConstantType(child, resultCache) >=
|
getGeneratedPropsConstantType(child, context) >=
|
||||||
ConstantTypes.CAN_HOIST
|
ConstantTypes.CAN_HOIST
|
||||||
) {
|
) {
|
||||||
const props = getNodeProps(child)
|
const props = getNodeProps(child)
|
||||||
@ -98,7 +97,7 @@ function walk(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (child.type === NodeTypes.TEXT_CALL) {
|
} else if (child.type === NodeTypes.TEXT_CALL) {
|
||||||
const contentType = getConstantType(child.content, resultCache)
|
const contentType = getConstantType(child.content, context)
|
||||||
if (contentType > 0) {
|
if (contentType > 0) {
|
||||||
if (contentType < ConstantTypes.CAN_STRINGIFY) {
|
if (contentType < ConstantTypes.CAN_STRINGIFY) {
|
||||||
canStringify = false
|
canStringify = false
|
||||||
@ -112,17 +111,16 @@ function walk(
|
|||||||
|
|
||||||
// walk further
|
// walk further
|
||||||
if (child.type === NodeTypes.ELEMENT) {
|
if (child.type === NodeTypes.ELEMENT) {
|
||||||
walk(child, context, resultCache)
|
walk(child, context)
|
||||||
} else if (child.type === NodeTypes.FOR) {
|
} else if (child.type === NodeTypes.FOR) {
|
||||||
// Do not hoist v-for single child because it has to be a block
|
// Do not hoist v-for single child because it has to be a block
|
||||||
walk(child, context, resultCache, child.children.length === 1)
|
walk(child, context, child.children.length === 1)
|
||||||
} else if (child.type === NodeTypes.IF) {
|
} else if (child.type === NodeTypes.IF) {
|
||||||
for (let i = 0; i < child.branches.length; i++) {
|
for (let i = 0; i < child.branches.length; i++) {
|
||||||
// Do not hoist v-if single child because it has to be a block
|
// Do not hoist v-if single child because it has to be a block
|
||||||
walk(
|
walk(
|
||||||
child.branches[i],
|
child.branches[i],
|
||||||
context,
|
context,
|
||||||
resultCache,
|
|
||||||
child.branches[i].children.length === 1
|
child.branches[i].children.length === 1
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -136,14 +134,15 @@ function walk(
|
|||||||
|
|
||||||
export function getConstantType(
|
export function getConstantType(
|
||||||
node: TemplateChildNode | SimpleExpressionNode,
|
node: TemplateChildNode | SimpleExpressionNode,
|
||||||
resultCache: Map<TemplateChildNode, ConstantTypes> = new Map()
|
context: TransformContext
|
||||||
): ConstantTypes {
|
): ConstantTypes {
|
||||||
|
const { constantCache } = context
|
||||||
switch (node.type) {
|
switch (node.type) {
|
||||||
case NodeTypes.ELEMENT:
|
case NodeTypes.ELEMENT:
|
||||||
if (node.tagType !== ElementTypes.ELEMENT) {
|
if (node.tagType !== ElementTypes.ELEMENT) {
|
||||||
return ConstantTypes.NOT_CONSTANT
|
return ConstantTypes.NOT_CONSTANT
|
||||||
}
|
}
|
||||||
const cached = resultCache.get(node)
|
const cached = constantCache.get(node)
|
||||||
if (cached !== undefined) {
|
if (cached !== undefined) {
|
||||||
return cached
|
return cached
|
||||||
}
|
}
|
||||||
@ -161,12 +160,9 @@ export function getConstantType(
|
|||||||
// non-hoistable expressions that refers to scope variables, e.g. compiler
|
// non-hoistable expressions that refers to scope variables, e.g. compiler
|
||||||
// injected keys or cached event handlers. Therefore we need to always
|
// injected keys or cached event handlers. Therefore we need to always
|
||||||
// check the codegenNode's props to be sure.
|
// check the codegenNode's props to be sure.
|
||||||
const generatedPropsType = getGeneratedPropsConstantType(
|
const generatedPropsType = getGeneratedPropsConstantType(node, context)
|
||||||
node,
|
|
||||||
resultCache
|
|
||||||
)
|
|
||||||
if (generatedPropsType === ConstantTypes.NOT_CONSTANT) {
|
if (generatedPropsType === ConstantTypes.NOT_CONSTANT) {
|
||||||
resultCache.set(node, ConstantTypes.NOT_CONSTANT)
|
constantCache.set(node, ConstantTypes.NOT_CONSTANT)
|
||||||
return ConstantTypes.NOT_CONSTANT
|
return ConstantTypes.NOT_CONSTANT
|
||||||
}
|
}
|
||||||
if (generatedPropsType < returnType) {
|
if (generatedPropsType < returnType) {
|
||||||
@ -175,9 +171,9 @@ export function getConstantType(
|
|||||||
|
|
||||||
// 2. its children.
|
// 2. its children.
|
||||||
for (let i = 0; i < node.children.length; i++) {
|
for (let i = 0; i < node.children.length; i++) {
|
||||||
const childType = getConstantType(node.children[i], resultCache)
|
const childType = getConstantType(node.children[i], context)
|
||||||
if (childType === ConstantTypes.NOT_CONSTANT) {
|
if (childType === ConstantTypes.NOT_CONSTANT) {
|
||||||
resultCache.set(node, ConstantTypes.NOT_CONSTANT)
|
constantCache.set(node, ConstantTypes.NOT_CONSTANT)
|
||||||
return ConstantTypes.NOT_CONSTANT
|
return ConstantTypes.NOT_CONSTANT
|
||||||
}
|
}
|
||||||
if (childType < returnType) {
|
if (childType < returnType) {
|
||||||
@ -193,9 +189,9 @@ export function getConstantType(
|
|||||||
for (let i = 0; i < node.props.length; i++) {
|
for (let i = 0; i < node.props.length; i++) {
|
||||||
const p = node.props[i]
|
const p = node.props[i]
|
||||||
if (p.type === NodeTypes.DIRECTIVE && p.name === 'bind' && p.exp) {
|
if (p.type === NodeTypes.DIRECTIVE && p.name === 'bind' && p.exp) {
|
||||||
const expType = getConstantType(p.exp, resultCache)
|
const expType = getConstantType(p.exp, context)
|
||||||
if (expType === ConstantTypes.NOT_CONSTANT) {
|
if (expType === ConstantTypes.NOT_CONSTANT) {
|
||||||
resultCache.set(node, ConstantTypes.NOT_CONSTANT)
|
constantCache.set(node, ConstantTypes.NOT_CONSTANT)
|
||||||
return ConstantTypes.NOT_CONSTANT
|
return ConstantTypes.NOT_CONSTANT
|
||||||
}
|
}
|
||||||
if (expType < returnType) {
|
if (expType < returnType) {
|
||||||
@ -210,12 +206,13 @@ export function getConstantType(
|
|||||||
// nested updates.
|
// nested updates.
|
||||||
if (codegenNode.isBlock) {
|
if (codegenNode.isBlock) {
|
||||||
codegenNode.isBlock = false
|
codegenNode.isBlock = false
|
||||||
|
context.helper(CREATE_VNODE)
|
||||||
}
|
}
|
||||||
|
|
||||||
resultCache.set(node, returnType)
|
constantCache.set(node, returnType)
|
||||||
return returnType
|
return returnType
|
||||||
} else {
|
} else {
|
||||||
resultCache.set(node, ConstantTypes.NOT_CONSTANT)
|
constantCache.set(node, ConstantTypes.NOT_CONSTANT)
|
||||||
return ConstantTypes.NOT_CONSTANT
|
return ConstantTypes.NOT_CONSTANT
|
||||||
}
|
}
|
||||||
case NodeTypes.TEXT:
|
case NodeTypes.TEXT:
|
||||||
@ -227,7 +224,7 @@ export function getConstantType(
|
|||||||
return ConstantTypes.NOT_CONSTANT
|
return ConstantTypes.NOT_CONSTANT
|
||||||
case NodeTypes.INTERPOLATION:
|
case NodeTypes.INTERPOLATION:
|
||||||
case NodeTypes.TEXT_CALL:
|
case NodeTypes.TEXT_CALL:
|
||||||
return getConstantType(node.content, resultCache)
|
return getConstantType(node.content, context)
|
||||||
case NodeTypes.SIMPLE_EXPRESSION:
|
case NodeTypes.SIMPLE_EXPRESSION:
|
||||||
return node.constType
|
return node.constType
|
||||||
case NodeTypes.COMPOUND_EXPRESSION:
|
case NodeTypes.COMPOUND_EXPRESSION:
|
||||||
@ -237,7 +234,7 @@ export function getConstantType(
|
|||||||
if (isString(child) || isSymbol(child)) {
|
if (isString(child) || isSymbol(child)) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
const childType = getConstantType(child, resultCache)
|
const childType = getConstantType(child, context)
|
||||||
if (childType === ConstantTypes.NOT_CONSTANT) {
|
if (childType === ConstantTypes.NOT_CONSTANT) {
|
||||||
return ConstantTypes.NOT_CONSTANT
|
return ConstantTypes.NOT_CONSTANT
|
||||||
} else if (childType < returnType) {
|
} else if (childType < returnType) {
|
||||||
@ -256,7 +253,7 @@ export function getConstantType(
|
|||||||
|
|
||||||
function getGeneratedPropsConstantType(
|
function getGeneratedPropsConstantType(
|
||||||
node: PlainElementNode,
|
node: PlainElementNode,
|
||||||
resultCache: Map<TemplateChildNode, ConstantTypes>
|
context: TransformContext
|
||||||
): ConstantTypes {
|
): ConstantTypes {
|
||||||
let returnType = ConstantTypes.CAN_STRINGIFY
|
let returnType = ConstantTypes.CAN_STRINGIFY
|
||||||
const props = getNodeProps(node)
|
const props = getNodeProps(node)
|
||||||
@ -264,7 +261,7 @@ function getGeneratedPropsConstantType(
|
|||||||
const { properties } = props
|
const { properties } = props
|
||||||
for (let i = 0; i < properties.length; i++) {
|
for (let i = 0; i < properties.length; i++) {
|
||||||
const { key, value } = properties[i]
|
const { key, value } = properties[i]
|
||||||
const keyType = getConstantType(key, resultCache)
|
const keyType = getConstantType(key, context)
|
||||||
if (keyType === ConstantTypes.NOT_CONSTANT) {
|
if (keyType === ConstantTypes.NOT_CONSTANT) {
|
||||||
return keyType
|
return keyType
|
||||||
}
|
}
|
||||||
@ -274,7 +271,7 @@ function getGeneratedPropsConstantType(
|
|||||||
if (value.type !== NodeTypes.SIMPLE_EXPRESSION) {
|
if (value.type !== NodeTypes.SIMPLE_EXPRESSION) {
|
||||||
return ConstantTypes.NOT_CONSTANT
|
return ConstantTypes.NOT_CONSTANT
|
||||||
}
|
}
|
||||||
const valueType = getConstantType(value, resultCache)
|
const valueType = getConstantType(value, context)
|
||||||
if (valueType === ConstantTypes.NOT_CONSTANT) {
|
if (valueType === ConstantTypes.NOT_CONSTANT) {
|
||||||
return valueType
|
return valueType
|
||||||
}
|
}
|
||||||
|
@ -168,7 +168,7 @@ export const transformElement: NodeTransform = (node, context) => {
|
|||||||
type === NodeTypes.COMPOUND_EXPRESSION
|
type === NodeTypes.COMPOUND_EXPRESSION
|
||||||
if (
|
if (
|
||||||
hasDynamicTextChild &&
|
hasDynamicTextChild &&
|
||||||
getConstantType(child) === ConstantTypes.NOT_CONSTANT
|
getConstantType(child, context) === ConstantTypes.NOT_CONSTANT
|
||||||
) {
|
) {
|
||||||
patchFlag |= PatchFlags.TEXT
|
patchFlag |= PatchFlags.TEXT
|
||||||
}
|
}
|
||||||
@ -373,7 +373,7 @@ export function buildProps(
|
|||||||
value.type === NodeTypes.JS_CACHE_EXPRESSION ||
|
value.type === NodeTypes.JS_CACHE_EXPRESSION ||
|
||||||
((value.type === NodeTypes.SIMPLE_EXPRESSION ||
|
((value.type === NodeTypes.SIMPLE_EXPRESSION ||
|
||||||
value.type === NodeTypes.COMPOUND_EXPRESSION) &&
|
value.type === NodeTypes.COMPOUND_EXPRESSION) &&
|
||||||
getConstantType(value) > 0)
|
getConstantType(value, context) > 0)
|
||||||
) {
|
) {
|
||||||
// skip if the prop is a cached handler or has constant value
|
// skip if the prop is a cached handler or has constant value
|
||||||
return
|
return
|
||||||
|
@ -82,7 +82,7 @@ export const transformText: NodeTransform = (node, context) => {
|
|||||||
// mark dynamic text with flag so it gets patched inside a block
|
// mark dynamic text with flag so it gets patched inside a block
|
||||||
if (
|
if (
|
||||||
!context.ssr &&
|
!context.ssr &&
|
||||||
getConstantType(child) === ConstantTypes.NOT_CONSTANT
|
getConstantType(child, context) === ConstantTypes.NOT_CONSTANT
|
||||||
) {
|
) {
|
||||||
callArgs.push(
|
callArgs.push(
|
||||||
PatchFlags.TEXT +
|
PatchFlags.TEXT +
|
||||||
|
Loading…
Reference in New Issue
Block a user