diff --git a/packages/compiler-core/src/transforms/hoistStatic.ts b/packages/compiler-core/src/transforms/hoistStatic.ts index baf1a2afce4..056e426425b 100644 --- a/packages/compiler-core/src/transforms/hoistStatic.ts +++ b/packages/compiler-core/src/transforms/hoistStatic.ts @@ -72,7 +72,7 @@ function walk( let staticType if ( !doNotHoistNode && - (staticType = getStaticType(child, resultCache)) > 0 + (staticType = getStaticType(context, child, resultCache)) > 0 ) { if (staticType === StaticType.HAS_RUNTIME_CONSTANT) { hasRuntimeConstant = true @@ -94,7 +94,7 @@ function walk( flag === PatchFlags.NEED_PATCH || flag === PatchFlags.TEXT) && !hasDynamicKeyOrRef(child) && - !hasCachedProps(child) + !hasCachedProps(context, child) ) { const props = getNodeProps(child) if (props) { @@ -104,7 +104,7 @@ function walk( } } } else if (child.type === NodeTypes.TEXT_CALL) { - const staticType = getStaticType(child.content, resultCache) + const staticType = getStaticType(context, child.content, resultCache) if (staticType > 0) { if (staticType === StaticType.HAS_RUNTIME_CONSTANT) { hasRuntimeConstant = true @@ -139,6 +139,7 @@ function walk( } export function getStaticType( + context: TransformContext, node: TemplateChildNode | SimpleExpressionNode, resultCache: Map = new Map() ): StaticType { @@ -156,11 +157,19 @@ export function getStaticType( return StaticType.NOT_STATIC } const flag = getPatchFlag(codegenNode) - if (!flag && !hasDynamicKeyOrRef(node) && !hasCachedProps(node)) { + if ( + !flag && + !hasDynamicKeyOrRef(node) && + !hasCachedProps(context, node) + ) { // element self is static. check its children. let returnType = StaticType.FULL_STATIC for (let i = 0; i < node.children.length; i++) { - const childType = getStaticType(node.children[i], resultCache) + const childType = getStaticType( + context, + node.children[i], + resultCache + ) if (childType === StaticType.NOT_STATIC) { resultCache.set(node, StaticType.NOT_STATIC) return StaticType.NOT_STATIC @@ -207,7 +216,7 @@ export function getStaticType( return StaticType.NOT_STATIC case NodeTypes.INTERPOLATION: case NodeTypes.TEXT_CALL: - return getStaticType(node.content, resultCache) + return getStaticType(context, node.content, resultCache) case NodeTypes.SIMPLE_EXPRESSION: return node.isConstant ? node.isRuntimeConstant @@ -221,7 +230,7 @@ export function getStaticType( if (isString(child) || isSymbol(child)) { continue } - const childType = getStaticType(child, resultCache) + const childType = getStaticType(context, child, resultCache) if (childType === StaticType.NOT_STATIC) { return StaticType.NOT_STATIC } else if (childType === StaticType.HAS_RUNTIME_CONSTANT) { @@ -242,10 +251,16 @@ function hasDynamicKeyOrRef(node: ElementNode): boolean { return !!(findProp(node, 'key', true) || findProp(node, 'ref', true)) } -function hasCachedProps(node: PlainElementNode): boolean { +function hasCachedProps( + context: TransformContext, + node: PlainElementNode +): boolean { if (__BROWSER__) { return false } + if (!context.cacheHandlers) { + return false + } const props = getNodeProps(node) if (props && props.type === NodeTypes.JS_OBJECT_EXPRESSION) { const { properties } = props diff --git a/packages/compiler-core/src/transforms/transformElement.ts b/packages/compiler-core/src/transforms/transformElement.ts index 7b34a79827b..944b1ed0859 100644 --- a/packages/compiler-core/src/transforms/transformElement.ts +++ b/packages/compiler-core/src/transforms/transformElement.ts @@ -157,7 +157,7 @@ export const transformElement: NodeTransform = (node, context) => { const hasDynamicTextChild = type === NodeTypes.INTERPOLATION || type === NodeTypes.COMPOUND_EXPRESSION - if (hasDynamicTextChild && !getStaticType(child)) { + if (hasDynamicTextChild && !getStaticType(context, child)) { patchFlag |= PatchFlags.TEXT } // pass directly if the only child is a text node @@ -293,7 +293,7 @@ export function buildProps( value.type === NodeTypes.JS_CACHE_EXPRESSION || ((value.type === NodeTypes.SIMPLE_EXPRESSION || value.type === NodeTypes.COMPOUND_EXPRESSION) && - getStaticType(value) > 0) + getStaticType(context, value) > 0) ) { // skip if the prop is a cached handler or has constant value return diff --git a/packages/compiler-core/src/transforms/vOn.ts b/packages/compiler-core/src/transforms/vOn.ts index 75759708bd3..6fc9d5449e2 100644 --- a/packages/compiler-core/src/transforms/vOn.ts +++ b/packages/compiler-core/src/transforms/vOn.ts @@ -35,7 +35,13 @@ export const transformOn: DirectiveTransform = ( augmentor ) => { const { loc, modifiers, arg } = dir as VOnDirectiveNode - if (!dir.exp && !modifiers.length) { + let exp: ExpressionNode | undefined = dir.exp as + | SimpleExpressionNode + | undefined + if (exp && !exp.content.trim()) { + exp = undefined + } + if (!exp && !modifiers.length) { context.onError(createCompilerError(ErrorCodes.X_V_ON_NO_EXPRESSION, loc)) } let eventName: ExpressionNode @@ -62,13 +68,7 @@ export const transformOn: DirectiveTransform = ( } // handler processing - let exp: ExpressionNode | undefined = dir.exp as - | SimpleExpressionNode - | undefined - if (exp && !exp.content.trim()) { - exp = undefined - } - let isCacheable: boolean = !exp + let isCacheable: boolean = __BROWSER__ ? false : context.cacheHandlers && !exp if (exp) { const isMemberExp = isMemberExpression(exp.content) const isInlineStatement = !(isMemberExp || fnExpRE.test(exp.content))