const root = nodeOps.createElement('div')
render(h(App), root)
expect(serializeInner(root)).toBe(
- `<div parent><div parent child></div></div>`
+ `<div parent><div child parent></div></div>`
)
})
// - scopeId from parent
// - slotted scopeId (with `-s` postfix) from child (the tree owner)
expect(serializeInner(root)).toBe(
- `<div parent child>` +
+ `<div child parent>` +
`<div parent child-s></div>` +
// component inside slot should have:
// - scopeId from template context
// - slotted scopeId from slot owner
// - its own scopeId
- `<span parent child-s child2></span>` +
+ `<span child2 parent child-s></span>` +
`</div>`
)
})
+
+ // #1988
+ test('should inherit scopeId through nested HOCs with inheritAttrs: false', () => {
+ const withParentId = withScopeId('parent')
+ const App = {
+ __scopeId: 'parent',
+ render: withParentId(() => {
+ return h(Child)
+ })
+ }
+
+ function Child() {
+ return h(Child2, { class: 'foo' })
+ }
+
+ function Child2() {
+ return h('div')
+ }
+ Child2.inheritAttrs = false
+
+ const root = nodeOps.createElement('div')
+ render(h(App), root)
+
+ expect(serializeInner(root)).toBe(`<div parent></div>`)
+ })
})
): VNode {
const {
type: Component,
- parent,
vnode,
proxy,
withProxy,
}
}
- // inherit scopeId
- const scopeId = vnode.scopeId
- // vite#536: if subtree root is created from parent slot if would already
- // have the correct scopeId, in this case adding the scopeId will cause
- // it to be removed if the original slot vnode is reused.
- const needScopeId = scopeId && root.scopeId !== scopeId
- const treeOwnerId = parent && parent.type.__scopeId
- const slotScopeId =
- treeOwnerId && treeOwnerId !== scopeId ? treeOwnerId + '-s' : null
- if (needScopeId || slotScopeId) {
- const extras: Data = {}
- if (needScopeId) extras[scopeId!] = ''
- if (slotScopeId) extras[slotScopeId] = ''
- root = cloneVNode(root, extras)
- }
-
// inherit directives
if (vnode.dirs) {
if (__DEV__ && !isElementRoot(root)) {
}
}
// scopeId
- if (scopeId) {
- hostSetScopeId(el, scopeId)
- }
- const treeOwnerId = parentComponent && parentComponent.type.__scopeId
- // vnode's own scopeId and the current patched component's scopeId is
- // different - this is a slot content node.
- if (treeOwnerId && treeOwnerId !== scopeId) {
- hostSetScopeId(el, treeOwnerId + '-s')
- }
+ setScopeId(el, scopeId, vnode, parentComponent)
+ // if (scopeId) {
+ // hostSetScopeId(el, scopeId)
+ // }
+ // if (parentComponent) {
+ // const treeOwnerId = parentComponent.type.__scopeId
+ // // vnode's own scopeId and the current patched component's scopeId is
+ // // different - this is a slot content node.
+ // if (treeOwnerId && treeOwnerId !== scopeId) {
+ // hostSetScopeId(el, treeOwnerId + '-s')
+ // }
+ // const parentScopeId =
+ // vnode === parentComponent.subTree && parentComponent.vnode.scopeId
+ // if (parentScopeId) {
+ // hostSetScopeId(el, parentScopeId)
+ // if (parentComponent.parent) {
+ // const treeOwnerId = parentComponent.parent.type.__scopeId
+ // // vnode's own scopeId and the current patched component's scopeId is
+ // // different - this is a slot content node.
+ // if (treeOwnerId && treeOwnerId !== parentScopeId) {
+ // hostSetScopeId(el, treeOwnerId + '-s')
+ // }
+ // }
+ // }
+ // }
}
if (__DEV__ || __FEATURE_PROD_DEVTOOLS__) {
Object.defineProperty(el, '__vnode', {
}
}
+ const setScopeId = (
+ el: RendererElement,
+ scopeId: string | false | null,
+ vnode: VNode,
+ parentComponent: ComponentInternalInstance | null
+ ) => {
+ if (scopeId) {
+ hostSetScopeId(el, scopeId)
+ }
+ if (parentComponent) {
+ const treeOwnerId = parentComponent.type.__scopeId
+ // vnode's own scopeId and the current patched component's scopeId is
+ // different - this is a slot content node.
+ if (treeOwnerId && treeOwnerId !== scopeId) {
+ hostSetScopeId(el, treeOwnerId + '-s')
+ }
+ if (vnode === parentComponent.subTree) {
+ setScopeId(
+ el,
+ parentComponent.vnode.scopeId,
+ parentComponent.vnode,
+ parentComponent.parent
+ )
+ }
+ }
+ }
+
const mountChildren: MountChildrenFn = (
children,
container,
}
expect(await renderToStream(h(Parent))).toBe(
- `<div data-v-test data-v-child><span data-v-test data-v-child-s>slot</span></div>`
+ `<div data-v-child data-v-test><span data-v-test data-v-child-s>slot</span></div>`
)
})
})
}
expect(await renderToString(h(Parent))).toBe(
- `<div data-v-test data-v-child><span data-v-test data-v-child-s>slot</span></div>`
+ `<div data-v-child data-v-test><span data-v-test data-v-child-s>slot</span></div>`
)
})
})
const comp = instance.type as Component
const { getBuffer, push } = createBuffer()
if (isFunction(comp)) {
- renderVNode(push, renderComponentRoot(instance), instance)
+ renderVNode(
+ push,
+ (instance.subTree = renderComponentRoot(instance)),
+ instance
+ )
} else {
if (!instance.render && !comp.ssrRender && isString(comp.template)) {
comp.ssrRender = ssrCompile(comp.template, instance)
)
setCurrentRenderingInstance(null)
} else if (instance.render) {
- renderVNode(push, renderComponentRoot(instance), instance)
+ renderVNode(
+ push,
+ (instance.subTree = renderComponentRoot(instance)),
+ instance
+ )
} else {
warn(
`Component ${
openTag += ssrRenderAttrs(props, tag)
}
- if (scopeId) {
- openTag += ` ${scopeId}`
- const treeOwnerId = parentComponent && parentComponent.type.__scopeId
- // vnode's own scopeId and the current rendering component's scopeId is
- // different - this is a slot content node.
- if (treeOwnerId && treeOwnerId !== scopeId) {
- openTag += ` ${treeOwnerId}-s`
- }
- }
+ openTag += resolveScopeId(scopeId, vnode, parentComponent)
push(openTag + `>`)
if (!isVoidTag(tag)) {
}
}
+function resolveScopeId(
+ scopeId: string | null,
+ vnode: VNode,
+ parentComponent: ComponentInternalInstance | null
+) {
+ let res = ``
+ if (scopeId) {
+ res = ` ${scopeId}`
+ }
+ if (parentComponent) {
+ const treeOwnerId = parentComponent.type.__scopeId
+ // vnode's own scopeId and the current rendering component's scopeId is
+ // different - this is a slot content node.
+ if (treeOwnerId && treeOwnerId !== scopeId) {
+ res += ` ${treeOwnerId}-s`
+ }
+ if (vnode === parentComponent.subTree) {
+ res += resolveScopeId(
+ parentComponent.vnode.scopeId,
+ parentComponent.vnode,
+ parentComponent.parent
+ )
+ }
+ }
+ return res
+}
+
function applySSRDirectives(
vnode: VNode,
rawProps: VNodeProps | null,