]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
wip: save
authordaiwei <daiwei521@126.com>
Sun, 8 Jun 2025 01:04:58 +0000 (09:04 +0800)
committerdaiwei <daiwei521@126.com>
Sun, 8 Jun 2025 02:14:30 +0000 (10:14 +0800)
packages/runtime-core/src/index.ts
packages/runtime-core/src/renderer.ts
packages/runtime-vapor/__tests__/scopeId.spec.ts
packages/runtime-vapor/src/block.ts

index e309554f2f6c3edd517c9b736d06ee1c72594698..527bead3ecc263ebedc55a63443f7f15ac26bc59 100644 (file)
@@ -505,7 +505,11 @@ export { type VaporInteropInterface } from './apiCreateApp'
 /**
  * @internal
  */
-export { type RendererInternals, MoveType } from './renderer'
+export {
+  type RendererInternals,
+  MoveType,
+  getInheritedScopeIds,
+} from './renderer'
 /**
  * @internal
  */
index 5a18d62a8e1b2d6f74bdd814217bf482e4fa8ac2..cdf7462449d935348ad2dbfed0af4497fd1a62e4 100644 (file)
@@ -764,30 +764,9 @@ function baseCreateRenderer(
         hostSetScopeId(el, slotScopeIds[i])
       }
     }
-    let subTree = parentComponent && parentComponent.subTree
-    if (subTree) {
-      if (
-        __DEV__ &&
-        subTree.patchFlag > 0 &&
-        subTree.patchFlag & PatchFlags.DEV_ROOT_FRAGMENT
-      ) {
-        subTree =
-          filterSingleRoot(subTree.children as VNodeArrayChildren) || subTree
-      }
-      if (
-        vnode === subTree ||
-        (isSuspense(subTree.type) &&
-          (subTree.ssContent === vnode || subTree.ssFallback === vnode))
-      ) {
-        const parentVNode = parentComponent!.vnode!
-        setScopeId(
-          el,
-          parentVNode,
-          parentVNode.scopeId,
-          parentVNode.slotScopeIds,
-          parentComponent!.parent,
-        )
-      }
+    const inheritedScopeIds = getInheritedScopeIds(vnode, parentComponent)
+    for (let i = 0; i < inheritedScopeIds.length; i++) {
+      hostSetScopeId(el, inheritedScopeIds[i])
     }
   }
 
@@ -2656,3 +2635,54 @@ function getVaporInterface(
   }
   return res!
 }
+
+/**
+ * shared between vdom and vapor
+ */
+export function getInheritedScopeIds(
+  vnode: VNode,
+  parentComponent: GenericComponentInstance | null,
+): string[] {
+  const inheritedScopeIds: string[] = []
+
+  let currentParent = parentComponent
+  let currentVNode = vnode
+
+  while (currentParent) {
+    let subTree = currentParent.subTree
+    if (!subTree) break
+
+    if (
+      __DEV__ &&
+      subTree.patchFlag > 0 &&
+      subTree.patchFlag & PatchFlags.DEV_ROOT_FRAGMENT
+    ) {
+      subTree =
+        filterSingleRoot(subTree.children as VNodeArrayChildren) || subTree
+    }
+
+    if (
+      currentVNode === subTree ||
+      (isSuspense(subTree.type) &&
+        (subTree.ssContent === currentVNode ||
+          subTree.ssFallback === currentVNode))
+    ) {
+      const parentVNode = currentParent.vnode!
+
+      if (parentVNode.scopeId) {
+        inheritedScopeIds.push(parentVNode.scopeId)
+      }
+
+      if (parentVNode.slotScopeIds) {
+        inheritedScopeIds.push(...parentVNode.slotScopeIds)
+      }
+
+      currentVNode = parentVNode
+      currentParent = currentParent.parent
+    } else {
+      break
+    }
+  }
+
+  return inheritedScopeIds
+}
index 657936352d30064b0057eaa5cead0a155312fc4b..827ea501f2327174ac8064d428c7d2ac03985f2e 100644 (file)
@@ -321,6 +321,50 @@ describe('vdom interop', () => {
     )
   })
 
+  test('vdom parent > vapor > vapor > vdom child', () => {
+    const InnerVdomChild = {
+      __scopeId: 'inner-vdom-child',
+      setup() {
+        return () => h('button')
+      },
+    }
+
+    const VaporChild = defineVaporComponent({
+      __scopeId: 'vapor-child',
+      setup() {
+        return createComponent(InnerVdomChild as any, null, null, true)
+      },
+    })
+
+    const VaporChild2 = defineVaporComponent({
+      __scopeId: 'vapor-child2',
+      setup() {
+        return createComponent(VaporChild as any, null, null, true)
+      },
+    })
+
+    const VdomChild = {
+      __scopeId: 'vdom-child',
+      setup() {
+        return () => h(VaporChild2 as any)
+      },
+    }
+
+    const App = {
+      __scopeId: 'parent',
+      setup() {
+        return () => h(VdomChild)
+      },
+    }
+
+    const root = document.createElement('div')
+    createApp(App).use(vaporInteropPlugin).mount(root)
+
+    expect(root.innerHTML).toBe(
+      `<button inner-vdom-child="" vapor-child="" vapor-child2="" vdom-child="" parent=""></button>`,
+    )
+  })
+
   test('vdom parent > vapor dynamic child', () => {
     const VaporChild = defineVaporComponent({
       __scopeId: 'vapor-child',
@@ -418,7 +462,7 @@ describe('vdom interop', () => {
     )
   })
 
-  test.todo('vapor parent > vdom > vdom > vapor child', () => {
+  test('vapor parent > vdom > vdom > vapor child', () => {
     const InnerVaporChild = defineVaporComponent({
       __scopeId: 'inner-vapor-child',
       setup() {
index c094642dfca1adb37f2e4aec11e55ef2ed43fc37..a67e43543e99fe2a0a4701bdb0954265333154ec 100644 (file)
@@ -8,6 +8,7 @@ import {
 import { createComment, createTextNode } from './dom/node'
 import { EffectScope, pauseTracking, resetTracking } from '@vue/reactivity'
 import { isHydrating } from './dom/hydration'
+import { getInheritedScopeIds } from '@vue/runtime-dom'
 
 export type Block =
   | Node
@@ -213,12 +214,16 @@ export function setComponentScopeId(instance: VaporComponentInstance): void {
     setScopeId(instance.block, scopeId)
   }
 
-  // vdom parent
+  // inherit scopeId from vdom parent
   if (
     parent.subTree &&
     (parent.subTree.component as any) === instance &&
     parent.vnode!.scopeId
   ) {
     setScopeId(instance.block, parent.vnode!.scopeId)
+    const scopeIds = getInheritedScopeIds(parent.vnode!, parent.parent)
+    for (const id of scopeIds) {
+      setScopeId(instance.block, id)
+    }
   }
 }