]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(compiler-core): fix hoisting logic for elements with cached handlers + other...
authorEvan You <yyx990803@gmail.com>
Mon, 16 Aug 2021 19:57:10 +0000 (15:57 -0400)
committerEvan You <yyx990803@gmail.com>
Mon, 16 Aug 2021 19:57:10 +0000 (15:57 -0400)
fix #4327

packages/compiler-core/__tests__/transforms/__snapshots__/hoistStatic.spec.ts.snap
packages/compiler-core/__tests__/transforms/hoistStatic.spec.ts
packages/compiler-core/src/transforms/hoistStatic.ts

index 0a6ca2322011e620a0fae54cdf7a1a8180225e0b..73c714d837eb8132b24388b46ace69e9a41dfc19 100644 (file)
@@ -211,6 +211,21 @@ return function render(_ctx, _cache) {
 }"
 `;
 
+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\\"
+
+export function render(_ctx, _cache) {
+  return (_openBlock(), _createElementBlock(\\"div\\", null, [
+    _createElementVNode(\\"div\\", null, [
+      _createElementVNode(\\"div\\", {
+        class: _normalizeClass({}),
+        onClick: _cache[0] || (_cache[0] = (...args) => (_ctx.foo && _ctx.foo(...args)))
+      })
+    ])
+  ]))
+}"
+`;
+
 exports[`compiler: hoistStatic transform prefixIdentifiers should NOT hoist elements with cached handlers 1`] = `
 "import { createElementVNode as _createElementVNode, openBlock as _openBlock, createElementBlock as _createElementBlock } from \\"vue\\"
 
index e21fe7459cd8a5829724914f1fe60e10c895af16..0cbd4910a303488eabdec6625ecaa1e6f2f5cf9b 100644 (file)
@@ -590,6 +590,25 @@ describe('compiler: hoistStatic transform', () => {
       ).toMatchSnapshot()
     })
 
+    test('should NOT hoist elements with cached handlers + other bindings', () => {
+      const root = transformWithHoist(
+        `<div><div><div :class="{}" @click="foo"/></div></div>`,
+        {
+          prefixIdentifiers: true,
+          cacheHandlers: true
+        }
+      )
+
+      expect(root.cached).toBe(1)
+      expect(root.hoists.length).toBe(0)
+      expect(
+        generate(root, {
+          mode: 'module',
+          prefixIdentifiers: true
+        }).code
+      ).toMatchSnapshot()
+    })
+
     test('should NOT hoist keyed template v-for with plain element child', () => {
       const root = transformWithHoist(
         `<div><template v-for="item in items" :key="item"><span/></template></div>`
index 1ea895acedfe2c519a4b6f438e7ffc923858f31a..27cc017a93adf383a3fdf92f05ced79aa621a02b 100644 (file)
@@ -335,16 +335,17 @@ function getGeneratedPropsConstantType(
       if (keyType < returnType) {
         returnType = keyType
       }
-      if (value.type !== NodeTypes.SIMPLE_EXPRESSION) {
+      let valueType: ConstantTypes
+      if (value.type === NodeTypes.SIMPLE_EXPRESSION) {
+        valueType = getConstantType(value, context)
+      } else if (value.type === NodeTypes.JS_CALL_EXPRESSION) {
         // some helper calls can be hoisted,
         // such as the `normalizeProps` generated by the compiler for pre-normalize class,
         // in this case we need to respect the ConstanType of the helper's argments
-        if (value.type === NodeTypes.JS_CALL_EXPRESSION) {
-          return getConstantTypeOfHelperCall(value, context)
-        }
-        return ConstantTypes.NOT_CONSTANT
+        valueType = getConstantTypeOfHelperCall(value, context)
+      } else {
+        valueType = ConstantTypes.NOT_CONSTANT
       }
-      const valueType = getConstantType(value, context)
       if (valueType === ConstantTypes.NOT_CONSTANT) {
         return valueType
       }