]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
chore: Merge branch 'minor' into edison/feat/vaporTransition edison/feat/vaporTransition 12962/head
authordaiwei <daiwei521@126.com>
Tue, 15 Jul 2025 01:45:47 +0000 (09:45 +0800)
committerdaiwei <daiwei521@126.com>
Tue, 15 Jul 2025 01:45:47 +0000 (09:45 +0800)
1  2 
packages/compiler-vapor/src/generators/block.ts
packages/runtime-core/src/apiCreateApp.ts
packages/runtime-core/src/index.ts
packages/runtime-core/src/renderer.ts
packages/runtime-dom/src/index.ts
packages/runtime-vapor/src/apiCreateFor.ts
packages/runtime-vapor/src/block.ts
packages/runtime-vapor/src/component.ts
packages/runtime-vapor/src/index.ts
packages/runtime-vapor/src/vdomInterop.ts

index 0811921bd9655f2f9e61a913ce0495a80c312393,30347394756b90e7c63a385a91dc745597b43f4c..d101962ba4faea3ef52b42148c2513cf22fa0582
@@@ -38,16 -36,12 +37,16 @@@ export function genBlockContent
    block: BlockIRNode,
    context: CodegenContext,
    root?: boolean,
-   customReturns?: (returns: CodeFragment[]) => CodeFragment[],
+   genEffectsExtraFrag?: () => CodeFragment[],
  ): CodeFragment[] {
    const [frag, push] = buildCodeFragment()
 -  const { dynamic, effect, operation, returns } = block
 +  const { dynamic, effect, operation, returns, key } = block
    const resetBlock = context.enterBlock(block)
  
 +  if (block.hasDeferredVShow) {
 +    push(NEWLINE, `const deferredApplyVShows = []`)
 +  }
 +
    if (root) {
      for (let name of context.ir.component) {
        const id = toValidAssetId(name, 'component')
    }
  
    push(...genOperations(operation, context))
-   push(...genEffects(effect, context))
+   push(...genEffects(effect, context, genEffectsExtraFrag))
  
 +  if (block.hasDeferredVShow) {
 +    push(NEWLINE, `deferredApplyVShows.forEach(fn => fn())`)
 +  }
 +
 +  if (dynamic.needsKey) {
 +    for (const child of dynamic.children) {
 +      const keyValue = key
 +        ? genExpression(key, context)
 +        : JSON.stringify(child.id)
 +      push(NEWLINE, `n${child.id}.$key = `, ...keyValue)
 +    }
 +  }
 +
    push(NEWLINE, `return `)
  
    const returnNodes = returns.map(n => `n${n}`)
index 167b2ae28ebafa3f244ea7621bedbde5d633ced6,a1409a7fe442e2247b357e40a5449075f95ec471..4c18a11f493f2a726bb1a25f4420bafa36243edd
@@@ -26,8 -26,8 +26,8 @@@ import type { InjectionKey } from './ap
  import { warn } from './warning'
  import type { VNode } from './vnode'
  import { devtoolsInitApp, devtoolsUnmountApp } from './devtools'
- import { NO, extend, isFunction, isObject } from '@vue/shared'
+ import { NO, extend, hasOwn, isFunction, isObject } from '@vue/shared'
 -import { version } from '.'
 +import { type TransitionHooks, version } from '.'
  import { installAppCompatProperties } from './compat/global'
  import type { NormalizedPropsOptions } from './componentProps'
  import type { ObjectEmitsOptions } from './componentEmits'
Simple merge
index 87d71d702143ce7c3814d81a873dcbcd5aa72261,bad40f14393292b9443de30996946f86a31192b1..37e50fb233dc92b789da2ec0253f4130275f525a
@@@ -731,22 -738,25 +738,26 @@@ function baseCreateRenderer
      }
      // #1583 For inside suspense + suspense not resolved case, enter hook should call when suspense resolved
      // #1689 For inside suspense + suspense resolved case, just call it
 -    const needCallTransitionHooks = needTransition(parentSuspense, transition)
 -    if (needCallTransitionHooks) {
 -      transition!.beforeEnter(el)
 +    if (transition) {
 +      performTransitionEnter(
 +        el,
 +        transition,
 +        () => hostInsert(el, container, anchor),
 +        parentSuspense,
 +      )
 +    } else {
 +      hostInsert(el, container, anchor)
      }
 -    hostInsert(el, container, anchor)
 -    if (
 -      (vnodeHook = props && props.onVnodeMounted) ||
 -      needCallTransitionHooks ||
 -      dirs
 -    ) {
 +
 +    if ((vnodeHook = props && props.onVnodeMounted) || dirs) {
-       queuePostRenderEffect(() => {
-         vnodeHook && invokeVNodeHook(vnodeHook, parentComponent, vnode)
-         dirs && invokeDirectiveHook(vnode, null, parentComponent, 'mounted')
-       }, parentSuspense)
+       queuePostRenderEffect(
+         () => {
+           vnodeHook && invokeVNodeHook(vnodeHook, parentComponent, vnode)
 -          needCallTransitionHooks && transition!.enter(el)
+           dirs && invokeDirectiveHook(vnode, null, parentComponent, 'mounted')
+         },
+         undefined,
+         parentSuspense,
+       )
      }
    }
  
@@@ -2657,50 -2744,7 +2732,50 @@@ export function invalidateMount(hooks: 
    }
  }
  
 -function getVaporInterface(
 +// shared between vdom and vapor
 +export function performTransitionEnter(
 +  el: RendererElement,
 +  transition: TransitionHooks,
 +  insert: () => void,
 +  parentSuspense: SuspenseBoundary | null,
 +): void {
 +  if (needTransition(parentSuspense, transition)) {
 +    transition.beforeEnter(el)
 +    insert()
-     queuePostRenderEffect(() => transition.enter(el), parentSuspense)
++    queuePostRenderEffect(() => transition.enter(el), undefined, parentSuspense)
 +  } else {
 +    insert()
 +  }
 +}
 +
 +// shared between vdom and vapor
 +export function performTransitionLeave(
 +  el: RendererElement,
 +  transition: TransitionHooks,
 +  remove: () => void,
 +  isElement: boolean = true,
 +): void {
 +  const performRemove = () => {
 +    remove()
 +    if (transition && !transition.persisted && transition.afterLeave) {
 +      transition.afterLeave()
 +    }
 +  }
 +
 +  if (isElement && transition && !transition.persisted) {
 +    const { leave, delayLeave } = transition
 +    const performLeave = () => leave(el, performRemove)
 +    if (delayLeave) {
 +      delayLeave(el, performRemove, performLeave)
 +    } else {
 +      performLeave()
 +    }
 +  } else {
 +    performRemove()
 +  }
 +}
 +
 +export function getVaporInterface(
    instance: ComponentInternalInstance | null,
    vnode: VNode,
  ): VaporInteropInterface {
Simple merge
index f60294f29f1e599b8df70816389a612d8072ad35,426a5c56b5b1ba226f352a31985c524ee1b87cf7..8b03a59bfc5b1fa090315639396aaf8a60e2d581
@@@ -329,14 -363,9 +364,14 @@@ export const createFor = 
        itemRef,
        keyRef,
        indexRef,
-       getKey && getKey(item, key, index),
+       key2,
      ))
  
 +    // apply transition for new nodes
 +    if (frag.$transition) {
 +      applyTransitionHooks(block.nodes, frag.$transition, false)
 +    }
 +
      if (parent) insert(block.nodes, parent, anchor)
  
      return block
index 6c882badcd5eef42e517a2ef30c86b5e1d6327c3,e021ce84b051432f5bda391d9459f04453ac9a13..09a7ed2e70c103c0d61ae816bd1e9bc1dec78d27
@@@ -6,40 -6,15 +6,40 @@@ import 
    unmountComponent,
  } from './component'
  import { createComment, createTextNode } from './dom/node'
- import { EffectScope, pauseTracking, resetTracking } from '@vue/reactivity'
+ import { EffectScope, setActiveSub } from '@vue/reactivity'
  import { isHydrating } from './dom/hydration'
 +import {
 +  type TransitionHooks,
 +  type TransitionProps,
 +  type TransitionState,
 +  performTransitionEnter,
 +  performTransitionLeave,
 +} from '@vue/runtime-dom'
 +import {
 +  applyTransitionHooks,
 +  applyTransitionLeaveHooks,
 +} from './components/Transition'
 +
 +export interface TransitionOptions {
 +  $key?: any
 +  $transition?: VaporTransitionHooks
 +}
 +
 +export interface VaporTransitionHooks extends TransitionHooks {
 +  state: TransitionState
 +  props: TransitionProps
 +  instance: VaporComponentInstance
 +  // mark transition hooks as disabled so that it skips during
 +  // inserting
 +  disabled?: boolean
 +}
 +
 +export type TransitionBlock =
 +  | (Node & TransitionOptions)
 +  | (VaporFragment & TransitionOptions)
 +  | (DynamicFragment & TransitionOptions)
  
 -export type Block =
 -  | Node
 -  | VaporFragment
 -  | DynamicFragment
 -  | VaporComponentInstance
 -  | Block[]
 +export type Block = TransitionBlock | VaporComponentInstance | Block[]
  
  export type BlockFn = (...args: any[]) => Block
  
@@@ -78,40 -47,23 +78,40 @@@ export class DynamicFragment extends Va
      }
      this.current = key
  
-     pauseTracking()
+     const prevSub = setActiveSub()
      const parent = this.anchor.parentNode
 +    const transition = this.$transition
 +    const renderBranch = () => {
 +      if (render) {
 +        this.scope = new EffectScope()
 +        this.nodes = this.scope.run(render) || []
 +        if (transition) {
 +          this.$transition = applyTransitionHooks(this.nodes, transition)
 +        }
 +        if (parent) insert(this.nodes, parent, this.anchor)
 +      } else {
 +        this.scope = undefined
 +        this.nodes = []
 +      }
 +    }
  
      // teardown previous branch
      if (this.scope) {
        this.scope.stop()
 -      parent && remove(this.nodes, parent)
 +      const mode = transition && transition.mode
 +      if (mode) {
 +        applyTransitionLeaveHooks(this.nodes, transition, renderBranch)
 +        parent && remove(this.nodes, parent)
 +        if (mode === 'out-in') {
-           resetTracking()
++          setActiveSub(prevSub)
 +          return
 +        }
 +      } else {
 +        parent && remove(this.nodes, parent)
 +      }
      }
  
 -    if (render) {
 -      this.scope = new EffectScope()
 -      this.nodes = this.scope.run(render) || []
 -      if (parent) insert(this.nodes, parent, this.anchor)
 -    } else {
 -      this.scope = undefined
 -      this.nodes = []
 -    }
 +    renderBranch()
  
      if (this.fallback && !isValidBlock(this.nodes)) {
        parent && remove(this.nodes, parent)
index a407268eb56be282b819373d33ff77d4ac8b0946,da57882c49de648cd4abdda7c133af7cc390b262..d3fb8453ae515bbd7c38983224523b7d4e2911df
@@@ -297,21 -289,36 +295,36 @@@ export function applyFallthroughProps
   */
  export function devRender(instance: VaporComponentInstance): void {
    instance.block =
-     callWithErrorHandling(
-       instance.type.render!,
-       instance,
-       ErrorCodes.RENDER_FUNCTION,
-       [
-         instance.setupState,
-         instance.props,
-         instance.emit,
-         instance.attrs,
-         instance.slots,
-       ],
-     ) || []
+     (instance.type.render
+       ? callWithErrorHandling(
+           instance.type.render,
+           instance,
+           ErrorCodes.RENDER_FUNCTION,
+           [
+             instance.setupState,
+             instance.props,
+             instance.emit,
+             instance.attrs,
+             instance.slots,
+           ],
+         )
+       : callWithErrorHandling(
+           isFunction(instance.type) ? instance.type : instance.type.setup!,
+           instance,
+           ErrorCodes.SETUP_FUNCTION,
+           [
+             instance.props,
+             {
+               slots: instance.slots,
+               attrs: instance.attrs,
+               emit: instance.emit,
+               expose: instance.expose,
+             },
+           ],
+         )) || []
  }
  
 -const emptyContext: GenericAppContext = {
 +export const emptyContext: GenericAppContext = {
    app: null as any,
    config: {},
    provides: /*@__PURE__*/ Object.create(null),
Simple merge
index 15e595f3ec8c04339d01e6a405779f283e19c9ce,8c1dd2cee2ba4c2ee2beddcc64025ed5909da542..b5bb141ad3fc9a88b90e2d9295fce01953991e37
@@@ -17,7 -16,7 +17,8 @@@ import 
    isEmitListener,
    onScopeDispose,
    renderSlot,
 +  setTransitionHooks as setVNodeTransitionHooks,
+   shallowReactive,
    shallowRef,
    simpleSetCurrentInstance,
  } from '@vue/runtime-dom'