]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(compiler-sfc): properly reuse hoisted asset imports
authorEvan You <yyx990803@gmail.com>
Thu, 16 Sep 2021 17:33:02 +0000 (13:33 -0400)
committerEvan You <yyx990803@gmail.com>
Thu, 16 Sep 2021 17:33:02 +0000 (13:33 -0400)
fix #4581

packages/compiler-sfc/__tests__/__snapshots__/templateTransformAssetUrl.spec.ts.snap
packages/compiler-sfc/__tests__/templateTransformAssetUrl.spec.ts
packages/compiler-sfc/src/templateTransformAssetUrl.ts

index ecc6738450f9b4893826db62c5300bd651873b5f..753f3f9a5247608d9ab75f9d22d1d39f4d1ddc95 100644 (file)
@@ -33,14 +33,17 @@ export function render(_ctx, _cache) {
 `;
 
 exports[`compiler sfc: transform asset url support uri fragment 1`] = `
-"import { openBlock as _openBlock, createElementBlock as _createElementBlock } from \\"vue\\"
+"import { createElementVNode as _createElementVNode, Fragment as _Fragment, openBlock as _openBlock, createElementBlock as _createElementBlock } from \\"vue\\"
 import _imports_0 from '@svg/file.svg'
 
 
 const _hoisted_1 = _imports_0 + '#fragment'
 
 export function render(_ctx, _cache) {
-  return (_openBlock(), _createElementBlock(\\"use\\", { href: _hoisted_1 }))
+  return (_openBlock(), _createElementBlock(_Fragment, null, [
+    _createElementVNode(\\"use\\", { href: _hoisted_1 }),
+    _createElementVNode(\\"use\\", { href: _hoisted_1 })
+  ], 64 /* STABLE_FRAGMENT */))
 }"
 `;
 
index ba25358371cb4cb58e7339bda77d18a05cfe7cd4..d07b92266860dd0fb85cbe4c6e329d245c9e4ea3 100644 (file)
@@ -41,7 +41,8 @@ describe('compiler sfc: transform asset url', () => {
    */
   test('support uri fragment', () => {
     const result = compileWithAssetUrls(
-      '<use href="~@svg/file.svg#fragment"></use>'
+      '<use href="~@svg/file.svg#fragment"></use>' +
+        '<use href="~@svg/file.svg#fragment"></use>'
     )
 
     expect(result.code).toMatchSnapshot()
index c65a47c22775ff20577e9bc5f18650e472e40a2e..4246817dff8d7bf25cae896a65884e8e520b7276 100644 (file)
@@ -5,6 +5,7 @@ import {
   ExpressionNode,
   NodeTransform,
   NodeTypes,
+  SimpleExpressionNode,
   SourceLocation,
   TransformContext
 } from '@vue/compiler-core'
@@ -153,30 +154,42 @@ function getImportsExpressionExp(
   context: TransformContext
 ): ExpressionNode {
   if (path) {
-    const existing = context.imports.find(i => i.path === path)
-    if (existing) {
-      return existing.exp as ExpressionNode
-    }
-    const name = `_imports_${context.imports.length}`
-    const exp = createSimpleExpression(
-      name,
-      false,
-      loc,
-      ConstantTypes.CAN_HOIST
-    )
-    context.imports.push({ exp, path })
-    if (hash && path) {
-      return context.hoist(
-        createSimpleExpression(
-          `${name} + '${hash}'`,
-          false,
-          loc,
-          ConstantTypes.CAN_HOIST
-        )
-      )
+    let name: string
+    let exp: SimpleExpressionNode
+    const existingIndex = context.imports.findIndex(i => i.path === path)
+    if (existingIndex > -1) {
+      name = `_imports_${existingIndex}`
+      exp = context.imports[existingIndex].exp as SimpleExpressionNode
     } else {
+      name = `_imports_${context.imports.length}`
+      exp = createSimpleExpression(name, false, loc, ConstantTypes.CAN_HOIST)
+      context.imports.push({ exp, path })
+    }
+
+    if (!hash) {
       return exp
     }
+
+    const hashExp = `${name} + '${hash}'`
+    const existingHoistIndex = context.hoists.findIndex(h => {
+      return (
+        h &&
+        h.type === NodeTypes.SIMPLE_EXPRESSION &&
+        !h.isStatic &&
+        h.content === hashExp
+      )
+    })
+    if (existingHoistIndex > -1) {
+      return createSimpleExpression(
+        `_hoisted_${existingHoistIndex + 1}`,
+        false,
+        loc,
+        ConstantTypes.CAN_HOIST
+      )
+    }
+    return context.hoist(
+      createSimpleExpression(hashExp, false, loc, ConstantTypes.CAN_HOIST)
+    )
   } else {
     return createSimpleExpression(`''`, false, loc, ConstantTypes.CAN_HOIST)
   }