/**
* @internal
*/
-export { type RendererInternals, MoveType } from './renderer'
+export {
+ type RendererInternals,
+ MoveType,
+ getInheritedScopeIds,
+} from './renderer'
/**
* @internal
*/
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])
}
}
}
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
+}
)
})
+ 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',
)
})
- test.todo('vapor parent > vdom > vdom > vapor child', () => {
+ test('vapor parent > vdom > vdom > vapor child', () => {
const InnerVaporChild = defineVaporComponent({
__scopeId: 'inner-vapor-child',
setup() {
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
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)
+ }
}
}