Skip to content

Commit

Permalink
fix(ssr): fix scopeId inheritance across mixed parent chain
Browse files Browse the repository at this point in the history
fix #3513
  • Loading branch information
yyx990803 committed Mar 30, 2021
1 parent 6cab91d commit 5e54081
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 7 deletions.
27 changes: 26 additions & 1 deletion packages/server-renderer/__tests__/ssrScopeId.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { createApp, mergeProps, withCtx } from 'vue'
import { createApp, h, mergeProps, withCtx } from 'vue'
import { renderToString } from '../src/renderToString'
import { ssrRenderComponent, ssrRenderAttrs, ssrRenderSlot } from '../src'

Expand Down Expand Up @@ -154,4 +154,29 @@ describe('ssr: scopedId runtime behavior', () => {
`</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>`)
})
})
30 changes: 24 additions & 6 deletions packages/server-renderer/src/render.ts
Original file line number Diff line number Diff line change
Expand Up @@ -129,13 +129,31 @@ function renderComponentSubTree(
// 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
Expand Down

0 comments on commit 5e54081

Please sign in to comment.