Răsfoiți Sursa

Merge remote-tracking branch 'origin/main' into minor

daiwei 1 an în urmă
părinte
comite
61604f6375

+ 9 - 9
package.json

@@ -69,20 +69,20 @@
     "@rollup/plugin-json": "^6.1.0",
     "@rollup/plugin-node-resolve": "^16.0.0",
     "@rollup/plugin-replace": "5.0.4",
-    "@swc/core": "^1.10.8",
+    "@swc/core": "^1.10.15",
     "@types/hash-sum": "^1.0.2",
-    "@types/node": "^22.10.7",
+    "@types/node": "^22.12.0",
     "@types/semver": "^7.5.8",
     "@types/serve-handler": "^6.1.4",
-    "@vitest/coverage-v8": "^3.0.2",
+    "@vitest/coverage-v8": "^3.0.5",
     "@vue/consolidate": "1.0.0",
     "conventional-changelog-cli": "^5.0.0",
     "enquirer": "^2.4.1",
-    "esbuild": "^0.24.2",
+    "esbuild": "^0.25.0",
     "esbuild-plugin-polyfill-node": "^0.3.0",
     "eslint": "^9.18.0",
     "eslint-plugin-import-x": "^4.6.1",
-    "@vitest/eslint-plugin": "^1.1.25",
+    "@vitest/eslint-plugin": "^1.1.27",
     "estree-walker": "catalog:",
     "jsdom": "^26.0.0",
     "lint-staged": "^15.4.1",
@@ -95,11 +95,11 @@
     "prettier": "^3.4.2",
     "pretty-bytes": "^6.1.1",
     "pug": "^3.0.3",
-    "puppeteer": "~24.1.0",
+    "puppeteer": "~24.2.0",
     "rimraf": "^6.0.1",
-    "rollup": "^4.31.0",
+    "rollup": "^4.34.6",
     "rollup-plugin-dts": "^6.1.1",
-    "rollup-plugin-esbuild": "^6.1.1",
+    "rollup-plugin-esbuild": "^6.2.0",
     "rollup-plugin-polyfill-node": "^0.13.0",
     "semver": "^7.6.3",
     "serve": "^14.2.4",
@@ -110,7 +110,7 @@
     "typescript": "~5.6.2",
     "typescript-eslint": "^8.20.0",
     "vite": "catalog:",
-    "vitest": "^3.0.2"
+    "vitest": "^3.0.5"
   },
   "pnpm": {
     "peerDependencyRules": {

+ 1 - 1
packages-private/sfc-playground/src/download/template/package.json

@@ -12,6 +12,6 @@
   },
   "devDependencies": {
     "@vitejs/plugin-vue": "^5.2.1",
-    "vite": "^6.0.7"
+    "vite": "^6.1.0"
   }
 }

+ 1 - 1
packages/compiler-sfc/src/rewriteDefault.ts

@@ -39,7 +39,7 @@ export function rewriteDefaultAST(
   ast.forEach(node => {
     if (node.type === 'ExportDefaultDeclaration') {
       if (node.declaration.type === 'ClassDeclaration' && node.declaration.id) {
-        let start: number =
+        const start: number =
           node.declaration.decorators && node.declaration.decorators.length > 0
             ? node.declaration.decorators[
                 node.declaration.decorators.length - 1

+ 5 - 0
packages/runtime-core/src/components/KeepAlive.ts

@@ -187,6 +187,11 @@ const KeepAliveImpl: ComponentOptions = {
         // Update components tree
         devtoolsComponentAdded(instance)
       }
+
+      // for e2e test
+      if (__DEV__ && __BROWSER__) {
+        ;(instance as any).__keepAliveStorageContainer = storageContainer
+      }
     }
 
     function unmount(vnode: VNode) {

+ 7 - 1
packages/runtime-core/src/renderer.ts

@@ -2050,7 +2050,13 @@ function baseCreateRenderer(
         queuePostRenderEffect(() => transition!.enter(el!), parentSuspense)
       } else {
         const { leave, delayLeave, afterLeave } = transition!
-        const remove = () => hostInsert(el!, container, anchor)
+        const remove = () => {
+          if (vnode.ctx!.isUnmounted) {
+            hostRemove(el!)
+          } else {
+            hostInsert(el!, container, anchor)
+          }
+        }
         const performLeave = () => {
           leave(el!, () => {
             remove()

+ 69 - 0
packages/vue/__tests__/e2e/Transition.spec.ts

@@ -1,3 +1,4 @@
+import type { ElementHandle } from 'puppeteer'
 import { E2E_TIMEOUT, setupPuppeteer } from './e2eUtils'
 import path from 'node:path'
 import { Transition, createApp, h, nextTick, ref } from 'vue'
@@ -1653,6 +1654,74 @@ describe('e2e: Transition', () => {
       },
       E2E_TIMEOUT,
     )
+
+    // #12860
+    test(
+      'unmount children',
+      async () => {
+        const unmountSpy = vi.fn()
+        let storageContainer: ElementHandle<HTMLDivElement>
+        const setStorageContainer = (container: any) =>
+          (storageContainer = container)
+        await page().exposeFunction('unmountSpy', unmountSpy)
+        await page().exposeFunction('setStorageContainer', setStorageContainer)
+        await page().evaluate(() => {
+          const { unmountSpy, setStorageContainer } = window as any
+          const { createApp, ref, h, onUnmounted, getCurrentInstance } = (
+            window as any
+          ).Vue
+          createApp({
+            template: `
+            <div id="container">
+              <transition>
+                <KeepAlive :include="includeRef">
+                  <TrueBranch v-if="toggle"></TrueBranch>
+                </KeepAlive>
+              </transition>
+            </div>
+            <button id="toggleBtn" @click="click">button</button>
+          `,
+            components: {
+              TrueBranch: {
+                name: 'TrueBranch',
+                setup() {
+                  const instance = getCurrentInstance()
+                  onUnmounted(() => {
+                    unmountSpy()
+                    setStorageContainer(instance.__keepAliveStorageContainer)
+                  })
+                  const count = ref(0)
+                  return () => h('div', count.value)
+                },
+              },
+            },
+            setup: () => {
+              const includeRef = ref(['TrueBranch'])
+              const toggle = ref(true)
+              const click = () => {
+                toggle.value = !toggle.value
+                if (toggle.value) {
+                  includeRef.value = ['TrueBranch']
+                } else {
+                  includeRef.value = []
+                }
+              }
+              return { toggle, click, unmountSpy, includeRef }
+            },
+          }).mount('#app')
+        })
+
+        await transitionFinish()
+        expect(await html('#container')).toBe('<div>0</div>')
+
+        await click('#toggleBtn')
+        await transitionFinish()
+        expect(await html('#container')).toBe('<!--v-if-->')
+        expect(unmountSpy).toBeCalledTimes(1)
+        expect(await storageContainer!.evaluate(x => x.innerHTML)).toBe(``)
+      },
+      E2E_TIMEOUT,
+    )
   })
 
   describe('transition with Suspense', () => {

+ 4 - 4
packages/vue/__tests__/e2e/todomvc.spec.ts

@@ -139,7 +139,7 @@ describe('e2e: todomvc', () => {
     // editing triggered by blur
     await click('.filters li:nth-child(1) a')
     await timeout(1)
-    await click('.todo:nth-child(1) label', { clickCount: 2 })
+    await click('.todo:nth-child(1) label', { count: 2 })
     expect(await count('.todo.editing')).toBe(1)
     expect(await isFocused('.todo:nth-child(1) .edit')).toBe(true)
     await clearValue('.todo:nth-child(1) .edit')
@@ -149,13 +149,13 @@ describe('e2e: todomvc', () => {
     expect(await text('.todo:nth-child(1) label')).toBe('edited!')
 
     // editing triggered by enter
-    await click('.todo label', { clickCount: 2 })
+    await click('.todo label', { count: 2 })
     await enterValue('.todo:nth-child(1) .edit', 'edited again!')
     expect(await count('.todo.editing')).toBe(0)
     expect(await text('.todo:nth-child(1) label')).toBe('edited again!')
 
     // cancel
-    await click('.todo label', { clickCount: 2 })
+    await click('.todo label', { count: 2 })
     await clearValue('.todo:nth-child(1) .edit')
     await page().type('.todo:nth-child(1) .edit', 'edited!')
     await page().keyboard.press('Escape')
@@ -163,7 +163,7 @@ describe('e2e: todomvc', () => {
     expect(await text('.todo:nth-child(1) label')).toBe('edited again!')
 
     // empty value should remove
-    await click('.todo label', { clickCount: 2 })
+    await click('.todo label', { count: 2 })
     await enterValue('.todo:nth-child(1) .edit', ' ')
     expect(await count('.todo')).toBe(3)
 

+ 1 - 1
packages/vue/__tests__/e2e/tree.spec.ts

@@ -88,7 +88,7 @@ describe('e2e: tree', () => {
     expect(await isVisible('#demo ul')).toBe(true)
     expect(await text('#demo li div span')).toContain('[-]')
 
-    await click('#demo ul > .item div', { clickCount: 2 })
+    await click('#demo ul > .item div', { count: 2 })
     expect(await count('.item')).toBe(15)
     expect(await count('.item > ul')).toBe(5)
     expect(await text('#demo ul > .item:nth-child(1)')).toContain('[-]')

Fișier diff suprimat deoarece este prea mare
+ 236 - 242
pnpm-lock.yaml


+ 2 - 2
pnpm-workspace.yaml

@@ -8,5 +8,5 @@ catalog:
   'estree-walker': ^2.0.2
   'magic-string': ^0.30.11
   'source-map-js': ^1.2.0
-  'vite': ^5.4.0
-  '@vitejs/plugin-vue': ^5.1.2
+  'vite': ^5.4.14
+  '@vitejs/plugin-vue': ^5.2.1

+ 0 - 1
tsconfig.build.json

@@ -17,7 +17,6 @@
     "packages/runtime-dom/src",
     "packages/reactivity/src",
     "packages/shared/src",
-    "packages/global.d.ts",
     "packages/compiler-sfc/src",
     "packages/compiler-ssr/src",
     "packages/server-renderer/src"

Unele fișiere nu au fost afișate deoarece prea multe fișiere au fost modificate în acest diff