]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
chore: Merge branch 'minor' into edison/feat/vaporTeleport
authordaiwei <daiwei521@126.com>
Wed, 16 Jul 2025 13:44:27 +0000 (21:44 +0800)
committerdaiwei <daiwei521@126.com>
Wed, 16 Jul 2025 13:44:27 +0000 (21:44 +0800)
1  2 
packages/runtime-core/src/components/Teleport.ts
packages/runtime-core/src/hmr.ts
packages/runtime-core/src/index.ts
packages/runtime-vapor/src/apiCreateFor.ts
packages/runtime-vapor/src/apiTemplateRef.ts
packages/runtime-vapor/src/component.ts
packages/runtime-vapor/src/fragment.ts
packages/runtime-vapor/src/hmr.ts
packages/runtime-vapor/src/index.ts
packages/runtime-vapor/src/renderEffect.ts
packages/runtime-vapor/src/vdomInterop.ts

Simple merge
Simple merge
index a0f780406c9b05b5f7e0a29dcf4b7737af6df718,426a5c56b5b1ba226f352a31985c524ee1b87cf7..05112408526d1880ef42a4c517cace2ee6a8bda0
@@@ -10,10 -9,16 +9,11 @@@ import 
    shallowRef,
    toReactive,
    toReadonly,
+   watch,
  } from '@vue/reactivity'
- import { getSequence, isArray, isObject, isString } from '@vue/shared'
+ import { isArray, isObject, isString } from '@vue/shared'
  import { createComment, createTextNode } from './dom/node'
 -import {
 -  type Block,
 -  VaporFragment,
 -  insert,
 -  remove as removeBlock,
 -} from './block'
 +import { type Block, insert, remove as removeBlock } from './block'
  import { warn } from '@vue/runtime-dom'
  import { currentInstance, isVaporComponent } from './component'
  import type { DynamicSlot } from './componentSlots'
index 3e4fcb221c377b6cfb0ca14bef1bbebe9da7372b,0000000000000000000000000000000000000000..0b1bc3a36332180c80c3db6601c9f453f36ab561
mode 100644,000000..100644
--- /dev/null
@@@ -1,69 -1,0 +1,69 @@@
- import { EffectScope, pauseTracking, resetTracking } from '@vue/reactivity'
++import { EffectScope, setActiveSub } from '@vue/reactivity'
 +import { createComment, createTextNode } from './dom/node'
 +import { type Block, type BlockFn, insert, isValidBlock, remove } from './block'
 +
 +export class VaporFragment {
 +  nodes: Block
 +  target?: ParentNode | null
 +  targetAnchor?: Node | null
 +  anchor?: Node
 +  insert?: (parent: ParentNode, anchor: Node | null) => void
 +  remove?: (parent?: ParentNode) => void
 +  getNodes?: () => Block
 +
 +  constructor(nodes: Block) {
 +    this.nodes = nodes
 +  }
 +}
 +
 +export class DynamicFragment extends VaporFragment {
 +  anchor: Node
 +  scope: EffectScope | undefined
 +  current?: BlockFn
 +  fallback?: BlockFn
 +
 +  constructor(anchorLabel?: string) {
 +    super([])
 +    this.anchor =
 +      __DEV__ && anchorLabel ? createComment(anchorLabel) : createTextNode()
 +  }
 +
 +  update(render?: BlockFn, key: any = render): void {
 +    if (key === this.current) {
 +      return
 +    }
 +    this.current = key
 +
-     pauseTracking()
++    const prevSub = setActiveSub()
 +    const parent = this.anchor.parentNode
 +
 +    // teardown previous branch
 +    if (this.scope) {
 +      this.scope.stop()
 +      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 = []
 +    }
 +
 +    if (this.fallback && !isValidBlock(this.nodes)) {
 +      parent && remove(this.nodes, parent)
 +      this.nodes =
 +        (this.scope || (this.scope = new EffectScope())).run(this.fallback) ||
 +        []
 +      parent && insert(this.nodes, parent, this.anchor)
 +    }
 +
-     resetTracking()
++    setActiveSub(prevSub)
 +  }
 +}
 +
 +export function isFragment(val: NonNullable<unknown>): val is VaporFragment {
 +  return val instanceof VaporFragment
 +}
index 63e5376896a2fa63ae020aad7682a16abe487e5b,c96c1afa13054e1230f9cef57a5fa9d9d04e5c19..17b1bd0f23794f99968b2a1881bf349620be147e
@@@ -20,12 -18,7 +19,11 @@@ export function hmrRerender(instance: V
    const parent = normalized[0].parentNode!
    const anchor = normalized[normalized.length - 1].nextSibling
    remove(instance.block, parent)
-   const prev = currentInstance
-   simpleSetCurrentInstance(instance)
 +  if (instance.hmrRerenderEffects) {
 +    instance.hmrRerenderEffects.forEach(e => e())
 +    instance.hmrRerenderEffects.length = 0
 +  }
+   const prev = setCurrentInstance(instance)
    pushWarningContext(instance)
    devRender(instance)
    popWarningContext()
@@@ -49,7 -41,6 +46,7 @@@ export function hmrReload
      instance.rawSlots,
      instance.isSingleRoot,
    )
-   simpleSetCurrentInstance(prev, instance.parent)
+   setCurrentInstance(...prev)
    mountComponent(newInstance, parent, anchor)
 +  handleTeleportRootComponentHmrReload(instance, newInstance)
  }
index 051944443addea692db772ecdb3c7eb850425e17,7a8aea5a0d71778852b4eb97a8b470016c30340e..998143c48026bbf9cdd570ea65d2cb57ec959910
@@@ -3,12 -3,15 +3,16 @@@ export { createVaporApp, createVaporSSR
  export { defineVaporComponent } from './apiDefineComponent'
  export { vaporInteropPlugin } from './vdomInterop'
  export type { VaporDirective } from './directives/custom'
 +export { VaporTeleportImpl as VaporTeleport } from './components/Teleport'
  
  // compiler-use only
 -export { insert, prepend, remove, isFragment, VaporFragment } from './block'
 +export { insert, prepend, remove } from './block'
  export { setInsertionState } from './insertionState'
- export { createComponent, createComponentWithFallback } from './component'
+ export {
+   createComponent,
+   createComponentWithFallback,
+   isVaporComponent,
+ } from './component'
  export { renderEffect } from './renderEffect'
  export { createSlot } from './componentSlots'
  export { template } from './dom/template'
index 227d7933e78eac3ee45a74f7e8deb6e5ec11e2db,ac34e8863d2ab8aada626553ef75863480887014..6da69ee2cf16cc2accee41d46fe72e4e9259cd8e
@@@ -11,64 -11,81 +11,86 @@@ import 
  import { type VaporComponentInstance, isVaporComponent } from './component'
  import { invokeArrayFns } from '@vue/shared'
  
- export function renderEffect(
-   fn: () => void,
-   noLifecycle = false,
- ): ReactiveEffect<void> {
-   const instance = currentInstance as VaporComponentInstance | null
-   const scope = getCurrentScope()
-   if (__DEV__ && !__TEST__ && !scope && !isVaporComponent(instance)) {
-     warn('renderEffect called without active EffectScope or Vapor instance.')
-   }
+ class RenderEffect extends ReactiveEffect {
+   i: VaporComponentInstance | null
+   job: SchedulerJob
+   updateJob: SchedulerJob
+   constructor(public render: () => void) {
+     super()
+     const instance = currentInstance as VaporComponentInstance | null
+     if (__DEV__ && !__TEST__ && !this.subs && !isVaporComponent(instance)) {
+       warn('renderEffect called without active EffectScope or Vapor instance.')
+     }
  
-   // renderEffect is always called after user has registered all hooks
-   const hasUpdateHooks = instance && (instance.bu || instance.u)
-   const renderEffectFn = noLifecycle
-     ? fn
-     : () => {
-         if (__DEV__ && instance) {
-           startMeasure(instance, `renderEffect`)
-         }
-         const prev = currentInstance
-         simpleSetCurrentInstance(instance)
-         if (scope) scope.on()
-         if (hasUpdateHooks && instance.isMounted && !instance.isUpdating) {
-           instance.isUpdating = true
-           instance.bu && invokeArrayFns(instance.bu)
-           fn()
-           queuePostFlushCb(() => {
-             instance.isUpdating = false
-             instance.u && invokeArrayFns(instance.u)
-           })
-         } else {
-           fn()
-         }
-         if (scope) scope.off()
-         simpleSetCurrentInstance(prev, instance)
-         if (__DEV__ && instance) {
-           startMeasure(instance, `renderEffect`)
-         }
+     const job: SchedulerJob = () => {
+       if (this.dirty) {
+         this.run()
        }
+     }
+     this.updateJob = () => {
+       instance!.isUpdating = false
+       instance!.u && invokeArrayFns(instance!.u)
+     }
+     if (instance) {
+       if (__DEV__) {
+         this.onTrack = instance.rtc
+           ? e => invokeArrayFns(instance.rtc!, e)
+           : void 0
+         this.onTrigger = instance.rtg
+           ? e => invokeArrayFns(instance.rtg!, e)
+           : void 0
+       }
+       job.i = instance
+     }
  
-   const effect = new ReactiveEffect(renderEffectFn)
-   const job: SchedulerJob = () => effect.dirty && effect.run()
+     this.job = job
+     this.i = instance
  
-   if (instance) {
-     if (__DEV__) {
-       effect.onTrack = instance.rtc
-         ? e => invokeArrayFns(instance.rtc!, e)
-         : void 0
-       effect.onTrigger = instance.rtg
-         ? e => invokeArrayFns(instance.rtg!, e)
-         : void 0
+     // TODO recurse handling
+   }
+   fn(): void {
+     const instance = this.i
+     const scope = this.subs ? (this.subs.sub as EffectScope) : undefined
+     // renderEffect is always called after user has registered all hooks
+     const hasUpdateHooks = instance && (instance.bu || instance.u)
+     if (__DEV__ && instance) {
+       startMeasure(instance, `renderEffect`)
+     }
+     const prev = setCurrentInstance(instance, scope)
+     if (hasUpdateHooks && instance.isMounted && !instance.isUpdating) {
+       instance.isUpdating = true
+       instance.bu && invokeArrayFns(instance.bu)
+       this.render()
+       queuePostFlushCb(this.updateJob)
+     } else {
+       this.render()
+     }
+     setCurrentInstance(...prev)
+     if (__DEV__ && instance) {
+       startMeasure(instance, `renderEffect`)
      }
-     job.i = instance
-     job.id = instance.uid
    }
  
-   effect.scheduler = () => queueJob(job)
+   notify(): void {
+     const flags = this.flags
+     if (!(flags & EffectFlags.PAUSED)) {
+       queueJob(this.job, this.i ? this.i.uid : undefined)
+     }
+   }
+ }
 -export function renderEffect(fn: () => void, noLifecycle = false): void {
++export function renderEffect(
++  fn: () => void,
++  noLifecycle = false,
++): RenderEffect {
+   const effect = new RenderEffect(fn)
+   if (noLifecycle) {
+     effect.fn = fn
+   }
    effect.run()
-   // TODO recurse handling
 +
 +  return effect
  }
index d5bbc71466b7047bfda470d4126a9278e60fd5e3,1573a306922aacd6813fc8cdfe8f7c7a84ec4f4a..5cc95304c7c36934011a34c6711079fefa3a5b32
@@@ -35,8 -36,9 +36,10 @@@ import type { RawSlots, VaporSlot } fro
  import { renderEffect } from './renderEffect'
  import { createTextNode } from './dom/node'
  import { optimizePropertyLookup } from './dom/prop'
 +import { VaporFragment } from './fragment'
  
+ export const interopKey: unique symbol = Symbol(`interop`)
  // mounting vapor components and slots in vdom
  const vaporInteropImpl: Omit<
    VaporInteropInterface,