From 7fbc933f4d80c0259ee24872ba790681cf3cbe76 Mon Sep 17 00:00:00 2001 From: Travis Date: Mon, 23 May 2022 09:40:53 +0800 Subject: [PATCH] fix(compiler-core): fix svg with directives being incorrectly hoisted (#5919) fix #5289 --- .../__snapshots__/hoistStatic.spec.ts.snap | 24 +++++++++++++++++++ .../__tests__/transforms/hoistStatic.spec.ts | 6 +++++ .../src/transforms/hoistStatic.ts | 9 +++++++ 3 files changed, 39 insertions(+) diff --git a/packages/compiler-core/__tests__/transforms/__snapshots__/hoistStatic.spec.ts.snap b/packages/compiler-core/__tests__/transforms/__snapshots__/hoistStatic.spec.ts.snap index 73c714d8..15b5cf4c 100644 --- a/packages/compiler-core/__tests__/transforms/__snapshots__/hoistStatic.spec.ts.snap +++ b/packages/compiler-core/__tests__/transforms/__snapshots__/hoistStatic.spec.ts.snap @@ -211,6 +211,30 @@ return function render(_ctx, _cache) { }" `; +exports[`compiler: hoistStatic transform prefixIdentifiers should NOT hoist SVG with directives 1`] = ` +"const _Vue = Vue +const { createElementVNode: _createElementVNode } = _Vue + +const _hoisted_1 = /*#__PURE__*/_createElementVNode(\\"path\\", { d: \\"M2,3H5.5L12\\" }, null, -1 /* HOISTED */) +const _hoisted_2 = [ + _hoisted_1 +] + +return function render(_ctx, _cache) { + with (_ctx) { + const { createElementVNode: _createElementVNode, resolveDirective: _resolveDirective, openBlock: _openBlock, createElementBlock: _createElementBlock, withDirectives: _withDirectives } = _Vue + + const _directive_foo = _resolveDirective(\\"foo\\") + + return (_openBlock(), _createElementBlock(\\"div\\", null, [ + _withDirectives((_openBlock(), _createElementBlock(\\"svg\\", null, _hoisted_2)), [ + [_directive_foo] + ]) + ])) + } +}" +`; + exports[`compiler: hoistStatic transform prefixIdentifiers should NOT hoist elements with cached handlers + other bindings 1`] = ` "import { normalizeClass as _normalizeClass, createElementVNode as _createElementVNode, openBlock as _openBlock, createElementBlock as _createElementBlock } from \\"vue\\" diff --git a/packages/compiler-core/__tests__/transforms/hoistStatic.spec.ts b/packages/compiler-core/__tests__/transforms/hoistStatic.spec.ts index 0cbd4910..2c4421ae 100644 --- a/packages/compiler-core/__tests__/transforms/hoistStatic.spec.ts +++ b/packages/compiler-core/__tests__/transforms/hoistStatic.spec.ts @@ -616,5 +616,11 @@ describe('compiler: hoistStatic transform', () => { expect(root.hoists.length).toBe(0) expect(generate(root).code).toMatchSnapshot() }) + + test('should NOT hoist SVG with directives', () => { + const root = transformWithHoist(`
`) + expect(root.hoists.length).toBe(2) + expect(generate(root).code).toMatchSnapshot() + }) }) }) diff --git a/packages/compiler-core/src/transforms/hoistStatic.ts b/packages/compiler-core/src/transforms/hoistStatic.ts index ae95eadb..84805258 100644 --- a/packages/compiler-core/src/transforms/hoistStatic.ts +++ b/packages/compiler-core/src/transforms/hoistStatic.ts @@ -230,6 +230,15 @@ export function getConstantType( // static then they don't need to be blocks since there will be no // nested updates. if (codegenNode.isBlock) { + // except set custom directives. + for (let i = 0; i < node.props.length; i++) { + const p = node.props[i] + if (p.type === NodeTypes.DIRECTIVE) { + constantCache.set(node, ConstantTypes.NOT_CONSTANT) + return ConstantTypes.NOT_CONSTANT + } + } + context.removeHelper(OPEN_BLOCK) context.removeHelper( getVNodeBlockHelper(context.inSSR, codegenNode.isComponent)