From 415091b0ee2de66e622145028f00523f2032ce77 Mon Sep 17 00:00:00 2001 From: Evan You Date: Tue, 17 May 2022 16:39:48 +0800 Subject: [PATCH] fix(compiler-core): should generate HYDRATE_EVENTS flag on dynamic component that resolves to element fix #5870 --- .../__tests__/transforms/transformElement.spec.ts | 15 +++++++++++++++ .../src/transforms/transformElement.ts | 13 ++++++++++--- .../src/transforms/transformSlotOutlet.ts | 8 +++++++- .../src/transforms/ssrTransformComponent.ts | 13 +++++++++++-- .../src/transforms/ssrTransformElement.ts | 2 ++ 5 files changed, 45 insertions(+), 6 deletions(-) diff --git a/packages/compiler-core/__tests__/transforms/transformElement.spec.ts b/packages/compiler-core/__tests__/transforms/transformElement.spec.ts index b672799adf4..bec7e119bd3 100644 --- a/packages/compiler-core/__tests__/transforms/transformElement.spec.ts +++ b/packages/compiler-core/__tests__/transforms/transformElement.spec.ts @@ -1053,6 +1053,21 @@ describe('compiler: element transform', () => { genFlagText([PatchFlags.PROPS, PatchFlags.HYDRATE_EVENTS]) ) }) + + // #5870 + test('HYDRATE_EVENTS on dynamic component', () => { + const { node } = parseWithElementTransform( + ``, + { + directiveTransforms: { + on: transformOn + } + } + ) + expect(node.patchFlag).toBe( + genFlagText([PatchFlags.PROPS, PatchFlags.HYDRATE_EVENTS]) + ) + }) }) describe('dynamic component', () => { diff --git a/packages/compiler-core/src/transforms/transformElement.ts b/packages/compiler-core/src/transforms/transformElement.ts index 403c5c6e382..2d15227f70f 100644 --- a/packages/compiler-core/src/transforms/transformElement.ts +++ b/packages/compiler-core/src/transforms/transformElement.ts @@ -121,7 +121,13 @@ export const transformElement: NodeTransform = (node, context) => { // props if (props.length > 0) { - const propsBuildResult = buildProps(node, context) + const propsBuildResult = buildProps( + node, + context, + undefined, + isComponent, + isDynamicComponent + ) vnodeProps = propsBuildResult.props patchFlag = propsBuildResult.patchFlag dynamicPropNames = propsBuildResult.dynamicPropNames @@ -380,6 +386,8 @@ export function buildProps( node: ElementNode, context: TransformContext, props: ElementNode['props'] = node.props, + isComponent: boolean, + isDynamicComponent: boolean, ssr = false ): { props: PropsExpression | undefined @@ -389,7 +397,6 @@ export function buildProps( shouldUseBlock: boolean } { const { tag, loc: elementLoc, children } = node - const isComponent = node.tagType === ElementTypes.COMPONENT let properties: ObjectExpression['properties'] = [] const mergeArgs: PropsExpression[] = [] const runtimeDirectives: DirectiveNode[] = [] @@ -411,8 +418,8 @@ export function buildProps( const name = key.content const isEventHandler = isOn(name) if ( - !isComponent && isEventHandler && + (!isComponent || isDynamicComponent) && // omit the flag for click handlers because hydration gives click // dedicated fast path. name.toLowerCase() !== 'onclick' && diff --git a/packages/compiler-core/src/transforms/transformSlotOutlet.ts b/packages/compiler-core/src/transforms/transformSlotOutlet.ts index 394684b408d..409bfabb6ed 100644 --- a/packages/compiler-core/src/transforms/transformSlotOutlet.ts +++ b/packages/compiler-core/src/transforms/transformSlotOutlet.ts @@ -87,7 +87,13 @@ export function processSlotOutlet( } if (nonNameProps.length > 0) { - const { props, directives } = buildProps(node, context, nonNameProps) + const { props, directives } = buildProps( + node, + context, + nonNameProps, + false, + false + ) slotProps = props if (directives.length) { diff --git a/packages/compiler-ssr/src/transforms/ssrTransformComponent.ts b/packages/compiler-ssr/src/transforms/ssrTransformComponent.ts index b02d3afddb5..dfb78136a9d 100644 --- a/packages/compiler-ssr/src/transforms/ssrTransformComponent.ts +++ b/packages/compiler-ssr/src/transforms/ssrTransformComponent.ts @@ -34,7 +34,8 @@ import { TRANSITION_GROUP, CREATE_VNODE, CallExpression, - JSChildNode + JSChildNode, + RESOLVE_DYNAMIC_COMPONENT } from '@vue/compiler-dom' import { SSR_RENDER_COMPONENT, SSR_RENDER_VNODE } from '../runtimeHelpers' import { @@ -83,6 +84,8 @@ export const ssrTransformComponent: NodeTransform = (node, context) => { } const component = resolveComponentType(node, context, true /* ssr */) + const isDynamicComponent = + isObject(component) && component.callee === RESOLVE_DYNAMIC_COMPONENT componentTypeMap.set(node, component) if (isSymbol(component)) { @@ -116,7 +119,13 @@ export const ssrTransformComponent: NodeTransform = (node, context) => { if (node.props.length) { // note we are not passing ssr: true here because for components, v-on // handlers should still be passed - const { props, directives } = buildProps(node, context) + const { props, directives } = buildProps( + node, + context, + undefined, + true, + isDynamicComponent + ) if (props || directives.length) { propsExp = buildSSRProps(props, directives, context) } diff --git a/packages/compiler-ssr/src/transforms/ssrTransformElement.ts b/packages/compiler-ssr/src/transforms/ssrTransformElement.ts index be530ebb5bc..a082d94eb57 100644 --- a/packages/compiler-ssr/src/transforms/ssrTransformElement.ts +++ b/packages/compiler-ssr/src/transforms/ssrTransformElement.ts @@ -89,6 +89,8 @@ export const ssrTransformElement: NodeTransform = (node, context) => { node, context, node.props, + false /* isComponent */, + false /* isDynamicComponent */, true /* ssr */ ) if (props || directives.length) {