-import { createApp, mergeProps, withCtx } from 'vue'
+import { createApp, h, mergeProps, withCtx } from 'vue'
import { renderToString } from '../src/renderToString'
import { ssrRenderComponent, ssrRenderAttrs, ssrRenderSlot } from '../src'
`</div>`
)
})
+
+ // #3513
+ test('scopeId inheritance across ssr-compiled andn on-ssr compiled parent chain', async () => {
+ const Child = {
+ ssrRender: (ctx: any, push: any, parent: any, attrs: any) => {
+ push(`<div${ssrRenderAttrs(attrs)}></div>`)
+ }
+ }
+
+ const Middle = {
+ render() {
+ return h(Child)
+ }
+ }
+
+ const Comp = {
+ __scopeId: 'parent',
+ ssrRender: (ctx: any, push: any, parent: any) => {
+ push(ssrRenderComponent(Middle, null, null, parent))
+ }
+ }
+
+ const result = await renderToString(createApp(Comp)) // output: `<div></div>`
+ expect(result).toBe(`<div parent></div>`)
+ })
})
// resolve fallthrough attrs
let attrs =
instance.type.inheritAttrs !== false ? instance.attrs : undefined
+ let hasCloned = false
- // inherited scopeId
- const scopeId = instance.vnode.scopeId
- if (scopeId || slotScopeId) {
- attrs = { ...attrs }
- if (scopeId) attrs[scopeId] = ''
- if (slotScopeId) attrs[slotScopeId.trim()] = ''
+ let cur = instance
+ while (true) {
+ const scopeId = cur.vnode.scopeId
+ if (scopeId) {
+ if (!hasCloned) {
+ attrs = { ...attrs }
+ hasCloned = true
+ }
+ attrs![scopeId] = ''
+ }
+ const parent = cur.parent
+ if (parent && parent.subTree && parent.subTree === cur.vnode) {
+ // parent is a non-SSR compiled component and is rendering this
+ // component as root. inherit its scopeId if present.
+ cur = parent
+ } else {
+ break
+ }
+ }
+
+ if (slotScopeId) {
+ if (!hasCloned) attrs = { ...attrs }
+ attrs![slotScopeId.trim()] = ''
}
// set current rendering instance for asset resolution