Skip to content

Commit

Permalink
fix(ssr): properly update currentRenderingInstance state during ssr
Browse files Browse the repository at this point in the history
fix #2863
  • Loading branch information
yyx990803 committed Mar 26, 2021
1 parent 9036f88 commit 8c3c14a
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 8 deletions.
17 changes: 14 additions & 3 deletions packages/runtime-core/src/componentRenderContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,23 @@ import { closeBlock, openBlock } from './vnode'
export let currentRenderingInstance: ComponentInternalInstance | null = null
export let currentScopeId: string | null = null

/**
* Note: rendering calls maybe nested. The function returns the parent rendering
* instance if present, which should be restored after the render is done:
*
* ```js
* const prev = setCurrentRenderingInstance(i)
* // ...render
* setCurrentRenderingInstance(prev)
* ```
*/
export function setCurrentRenderingInstance(
instance: ComponentInternalInstance | null
) {
): ComponentInternalInstance | null {
const prev = currentRenderingInstance
currentRenderingInstance = instance
currentScopeId = (instance && instance.type.__scopeId) || null
return prev
}

/**
Expand All @@ -40,8 +52,7 @@ export function withCtx(
if (!isRenderingCompiledSlot) {
openBlock(true /* null block that disables tracking */)
}
const prevInstance = currentRenderingInstance
setCurrentRenderingInstance(ctx)
const prevInstance = setCurrentRenderingInstance(ctx)
const res = fn(...args)
setCurrentRenderingInstance(prevInstance)
if (!isRenderingCompiledSlot) {
Expand Down
4 changes: 2 additions & 2 deletions packages/runtime-core/src/componentRenderUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ export function renderComponentRoot(
} = instance

let result
setCurrentRenderingInstance(instance)
const prev = setCurrentRenderingInstance(instance)
if (__DEV__) {
accessedAttrs = false
}
Expand Down Expand Up @@ -207,7 +207,7 @@ export function renderComponentRoot(
result = createVNode(Comment)
}

setCurrentRenderingInstance(null)
setCurrentRenderingInstance(prev)
return result
}

Expand Down
34 changes: 33 additions & 1 deletion packages/server-renderer/__tests__/render.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,17 @@ import {
withCtx,
KeepAlive,
Transition,
watchEffect
watchEffect,
createVNode,
resolveDynamicComponent
} from 'vue'
import { escapeHtml } from '@vue/shared'
import { renderToString } from '../src/renderToString'
import { renderToStream as _renderToStream } from '../src/renderToStream'
import { ssrRenderSlot, SSRSlot } from '../src/helpers/ssrRenderSlot'
import { ssrRenderComponent } from '../src/helpers/ssrRenderComponent'
import { Readable } from 'stream'
import { ssrRenderVNode } from '../src'

const promisifyStream = (stream: Readable) => {
return new Promise<string>((resolve, reject) => {
Expand Down Expand Up @@ -824,5 +827,34 @@ function testRender(type: string, render: typeof renderToString) {
})
expect(await render(app)).toBe('<!---->')
})

// #2863
test('assets should be resolved correctly', async () => {
expect(
await render(
createApp({
components: {
A: {
ssrRender(_ctx, _push) {
_push(`<div>A</div>`)
}
},
B: {
render: () => h('div', 'B')
}
},
ssrRender(_ctx, _push, _parent) {
const A: any = resolveComponent('A')
_push(ssrRenderComponent(A, null, null, _parent))
ssrRenderVNode(
_push,
createVNode(resolveDynamicComponent('B'), null, null),
_parent
)
}
})
)
).toBe(`<div>A</div><div>B</div>`)
})
})
}
4 changes: 2 additions & 2 deletions packages/server-renderer/src/render.ts
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ function renderComponentSubTree(
}

// set current rendering instance for asset resolution
setCurrentRenderingInstance(instance)
const prev = setCurrentRenderingInstance(instance)
ssrRender(
instance.proxy,
push,
Expand All @@ -151,7 +151,7 @@ function renderComponentSubTree(
instance.data,
instance.ctx
)
setCurrentRenderingInstance(null)
setCurrentRenderingInstance(prev)
} else if (instance.render && instance.render !== NOOP) {
renderVNode(
push,
Expand Down

0 comments on commit 8c3c14a

Please sign in to comment.