]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
chore: Merge branch 'edison/fix/dynamicComponentWithVHtml' into edison/testVapor
authordaiwei <daiwei521@126.com>
Wed, 18 Jun 2025 09:36:39 +0000 (17:36 +0800)
committerdaiwei <daiwei521@126.com>
Thu, 19 Jun 2025 01:20:17 +0000 (09:20 +0800)
1  2 
packages/compiler-vapor/__tests__/transforms/__snapshots__/transformTemplateRef.spec.ts.snap
packages/compiler-vapor/__tests__/transforms/transformTemplateRef.spec.ts
packages/runtime-core/__tests__/hydration.spec.ts
packages/runtime-core/src/components/BaseTransition.ts
packages/runtime-core/src/renderer.ts
packages/runtime-dom/src/components/TransitionGroup.ts
packages/runtime-vapor/__tests__/componentAttrs.spec.ts
packages/runtime-vapor/src/apiCreateFor.ts
packages/runtime-vapor/src/component.ts
packages/server-renderer/__tests__/ssrSlot.spec.ts

index 793c11cede3cab6bbe72bba6f72b76b7aad9d754,20519cf997fe0668819d98291972b4e920151a35..d5c418c16e86bcfec88e435c19600d40b454a47a
@@@ -1843,36 -1846,60 +1846,90 @@@ describe('SSR hydration', () => 
      }
    })
  
 +  describe('dynamic anchor', () => {
 +    test('two consecutive components', () => {
 +      const Comp = {
 +        render() {
 +          return createTextVNode('foo')
 +        },
 +      }
 +      const { vnode, container } = mountWithHydration(
 +        `<div><span></span>foo<!--[[-->foo<!--]]--><span></span></div>`,
 +        () => h('div', null, [h('span'), h(Comp), h(Comp), h('span')]),
 +      )
 +      expect(vnode.el).toBe(container.firstChild)
 +      expect(`Hydration children mismatch`).not.toHaveBeenWarned()
 +    })
 +
 +    test('multiple consecutive components', () => {
 +      const Comp = {
 +        render() {
 +          return createTextVNode('foo')
 +        },
 +      }
 +      const { vnode, container } = mountWithHydration(
 +        `<div><span></span>foo<!--[[-->foo<!--]]-->foo<span></span></div>`,
 +        () => h('div', null, [h('span'), h(Comp), h(Comp), h(Comp), h('span')]),
 +      )
 +      expect(vnode.el).toBe(container.firstChild)
 +      expect(`Hydration children mismatch`).not.toHaveBeenWarned()
 +    })
 +  })
 +
+   test('hmr reload child wrapped in KeepAlive', async () => {
+     const id = 'child-reload'
+     const Child = {
+       __hmrId: id,
+       template: `<div>foo</div>`,
+     }
+     createRecord(id, Child)
+     const appId = 'test-app-id'
+     const App = {
+       __hmrId: appId,
+       components: { Child },
+       template: `
+       <div>
+         <KeepAlive>
+           <Child />
+         </KeepAlive>
+       </div>
+       `,
+     }
+     const root = document.createElement('div')
+     root.innerHTML = await renderToString(h(App))
+     createSSRApp(App).mount(root)
+     expect(root.innerHTML).toBe('<div><div>foo</div></div>')
+     reload(id, {
+       __hmrId: id,
+       template: `<div>bar</div>`,
+     })
+     await nextTick()
+     expect(root.innerHTML).toBe('<div><div>bar</div></div>')
+   })
+   test('hmr root reload', async () => {
+     const appId = 'test-app-id'
+     const App = {
+       __hmrId: appId,
+       template: `<div>foo</div>`,
+     }
+     const root = document.createElement('div')
+     root.innerHTML = await renderToString(h(App))
+     createSSRApp(App).mount(root)
+     expect(root.innerHTML).toBe('<div>foo</div>')
+     reload(appId, {
+       __hmrId: appId,
+       template: `<div>bar</div>`,
+     })
+     await nextTick()
+     expect(root.innerHTML).toBe('<div>bar</div>')
+   })
    describe('mismatch handling', () => {
      test('text node', () => {
        const { container } = mountWithHydration(`foo`, () => 'bar')
Simple merge
index 8e38dbf0f232b867303e3f8559ec9fdf4d673c30,72af535d385e0a837df6fccea72e9f0bae6e7213..abf3e0954243dec714c336f73c3801f35af57543
@@@ -96,8 -97,22 +97,9 @@@ const TransitionGroupImpl: ComponentOpt
  
        movedChildren.forEach(c => {
          const el = c.el as ElementWithTransition
 -        const style = el.style
 -        addTransitionClass(el, moveClass)
 -        style.transform = style.webkitTransform = style.transitionDuration = ''
 -        const cb = ((el as any)[moveCbKey] = (e: TransitionEvent) => {
 -          if (e && e.target !== el) {
 -            return
 -          }
 -          if (!e || /transform$/.test(e.propertyName)) {
 -            el.removeEventListener('transitionend', cb)
 -            ;(el as any)[moveCbKey] = null
 -            removeTransitionClass(el, moveClass)
 -          }
 -        })
 -        el.addEventListener('transitionend', cb)
 +        handleMovedChildren(el, moveClass)
        })
+       prevChildren = []
      })
  
      return () => {
index 7bde89fbb13d909f748cd16ea85cf5e321adf458,62529149ad4ce09256fe2f3d931f1541b86c336e..19ee7182716f6b091cb20dc57b7df9a221f93a5f
@@@ -8,14 -9,9 +9,15 @@@ import 
    shallowReadArray,
    shallowRef,
    toReactive,
+   toReadonly,
  } from '@vue/reactivity'
 -import { getSequence, isArray, isObject, isString } from '@vue/shared'
 +import {
 +  FOR_ANCHOR_LABEL,
 +  getSequence,
 +  isArray,
 +  isObject,
 +  isString,
 +} from '@vue/shared'
  import { createComment, createTextNode } from './dom/node'
  import {
    type Block,
index 55fdcffeb04cc39e5ed4a986d8bd3ac55959171c,c6602ec961bc23ea27bad8cf72c3381a7a9562f5..4cc7051afc1b63c80e4e56bd6db81db149246332
@@@ -491,13 -471,20 +491,21 @@@ export function createComponentWithFall
    rawProps?: LooseRawProps | null,
    rawSlots?: LooseRawSlots | null,
    isSingleRoot?: boolean,
 +  appContext?: GenericAppContext,
  ): HTMLElement | VaporComponentInstance {
    if (!isString(comp)) {
 -    return createComponent(comp, rawProps, rawSlots, isSingleRoot)
 +    return createComponent(comp, rawProps, rawSlots, isSingleRoot, appContext)
    }
  
 -  const el = document.createElement(comp)
+   const _insertionParent = insertionParent
+   const _insertionAnchor = insertionAnchor
+   if (isHydrating) {
+     locateHydrationNode()
+   } else {
+     resetInsertionState()
+   }
 +  const el = createElement(comp)
    // mark single root
    ;(el as any).$root = isSingleRoot
  
index d17e34bc7c0b54477c855d79cb4a3df7253374d0,4cc7fd97ef2cd51609e85682a7a84535ee486d1a..e8435225481ac12831da2d8084b624481ecf5f81
@@@ -156,6 -154,38 +156,38 @@@ describe('ssr: slot', () => 
      ).toBe(`<div><p>1</p><p>2</p></div>`)
    })
  
 -    ).toBe(`<div><!--[--> new header <!--]--></div>`)
+   // #12438
+   test('async component slot with v-if true', async () => {
+     const Layout = defineAsyncComponent(() =>
+       Promise.resolve({
+         template: `<div><slot name="header">default header</slot></div>`,
+       }),
+     )
+     const LayoutLoader = {
+       setup(_: any, context: any) {
+         return () => h(Layout, {}, context.slots)
+       },
+     }
+     expect(
+       await renderToString(
+         createApp({
+           components: {
+             LayoutLoader,
+           },
+           template: `
+             <Suspense>
+               <LayoutLoader>
+                 <template v-if="true" #header>
+                   new header
+                 </template>
+               </LayoutLoader>
+             </Suspense>
+           `,
+         }),
+       ),
++    ).toBe(`<div><!--[--> new header <!--]--><!--slot--></div>`)
+   })
    // #11326
    test('dynamic component slot', async () => {
      expect(