فهرست منبع

fix(compiler-dom): fix stringify static edge for partially eligible chunks in cached parent

close #11879
close #11890
Evan You 1 سال پیش
والد
کامیت
1d99d61c1b

+ 12 - 0
packages/compiler-dom/__tests__/transforms/__snapshots__/stringifyStatic.spec.ts.snap

@@ -1,5 +1,17 @@
 // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
 // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
 
 
+exports[`stringify static html > eligible content (elements > 20) + non-eligible content 1`] = `
+"const { createElementVNode: _createElementVNode, createStaticVNode: _createStaticVNode, openBlock: _openBlock, createElementBlock: _createElementBlock } = Vue
+
+return function render(_ctx, _cache) {
+  return (_openBlock(), _createElementBlock("div", null, _cache[0] || (_cache[0] = [
+    _createStaticVNode("<span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span>", 20),
+    _createElementVNode("div", { key: "1" }, "1", -1 /* HOISTED */),
+    _createStaticVNode("<span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span>", 20)
+  ])))
+}"
+`;
+
 exports[`stringify static html > escape 1`] = `
 exports[`stringify static html > escape 1`] = `
 "const { toDisplayString: _toDisplayString, normalizeClass: _normalizeClass, createElementVNode: _createElementVNode, createStaticVNode: _createStaticVNode, openBlock: _openBlock, createElementBlock: _createElementBlock } = Vue
 "const { toDisplayString: _toDisplayString, normalizeClass: _normalizeClass, createElementVNode: _createElementVNode, createStaticVNode: _createStaticVNode, openBlock: _openBlock, createElementBlock: _createElementBlock } = Vue
 
 

+ 14 - 0
packages/compiler-dom/__tests__/transforms/stringifyStatic.spec.ts

@@ -451,4 +451,18 @@ describe('stringify static html', () => {
     expect(ast.cached).toMatchObject([cachedArrayBailedMatcher()])
     expect(ast.cached).toMatchObject([cachedArrayBailedMatcher()])
     expect(code).toMatchSnapshot()
     expect(code).toMatchSnapshot()
   })
   })
+
+  test('eligible content (elements > 20) + non-eligible content', () => {
+    const { code } = compileWithStringify(
+      `<div>${repeat(
+        `<span/>`,
+        StringifyThresholds.NODE_COUNT,
+      )}<div key="1">1</div>${repeat(
+        `<span/>`,
+        StringifyThresholds.NODE_COUNT,
+      )}</div>`,
+    )
+
+    expect(code).toMatchSnapshot()
+  })
 })
 })

+ 12 - 6
packages/compiler-dom/src/transforms/stringifyStatic.ts

@@ -16,8 +16,6 @@ import {
   type TemplateChildNode,
   type TemplateChildNode,
   type TextCallNode,
   type TextCallNode,
   type TransformContext,
   type TransformContext,
-  type VNodeCall,
-  createArrayExpression,
   createCallExpression,
   createCallExpression,
   isStaticArgOf,
   isStaticArgOf,
 } from '@vue/compiler-core'
 } from '@vue/compiler-core'
@@ -106,15 +104,23 @@ export const stringifyStatic: HoistTransform = (children, context, parent) => {
         String(currentChunk.length),
         String(currentChunk.length),
       ])
       ])
 
 
+      const deleteCount = currentChunk.length - 1
+
       if (isParentCached) {
       if (isParentCached) {
-        ;((parent.codegenNode as VNodeCall).children as CacheExpression).value =
-          createArrayExpression([staticCall])
+        // if the parent is cached, then `children` is also the value of the
+        // CacheExpression. Just replace the corresponding range in the cached
+        // list with staticCall.
+        children.splice(
+          currentIndex - currentChunk.length,
+          currentChunk.length,
+          // @ts-expect-error
+          staticCall,
+        )
       } else {
       } else {
         // replace the first node's hoisted expression with the static vnode call
         // replace the first node's hoisted expression with the static vnode call
         ;(currentChunk[0].codegenNode as CacheExpression).value = staticCall
         ;(currentChunk[0].codegenNode as CacheExpression).value = staticCall
         if (currentChunk.length > 1) {
         if (currentChunk.length > 1) {
           // remove merged nodes from children
           // remove merged nodes from children
-          const deleteCount = currentChunk.length - 1
           children.splice(currentIndex - currentChunk.length + 1, deleteCount)
           children.splice(currentIndex - currentChunk.length + 1, deleteCount)
           // also adjust index for the remaining cache items
           // also adjust index for the remaining cache items
           const cacheIndex = context.cached.indexOf(
           const cacheIndex = context.cached.indexOf(
@@ -128,9 +134,9 @@ export const stringifyStatic: HoistTransform = (children, context, parent) => {
             }
             }
             context.cached.splice(cacheIndex - deleteCount + 1, deleteCount)
             context.cached.splice(cacheIndex - deleteCount + 1, deleteCount)
           }
           }
-          return deleteCount
         }
         }
       }
       }
+      return deleteCount
     }
     }
     return 0
     return 0
   }
   }