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
}
/**
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) {
} = instance
let result
- setCurrentRenderingInstance(instance)
+ const prev = setCurrentRenderingInstance(instance)
if (__DEV__) {
accessedAttrs = false
}
result = createVNode(Comment)
}
- setCurrentRenderingInstance(null)
+ setCurrentRenderingInstance(prev)
return result
}
withCtx,
KeepAlive,
Transition,
- watchEffect
+ watchEffect,
+ createVNode,
+ resolveDynamicComponent
} from 'vue'
import { escapeHtml } from '@vue/shared'
import { renderToString } from '../src/renderToString'
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) => {
})
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>`)
+ })
})
}
}
// set current rendering instance for asset resolution
- setCurrentRenderingInstance(instance)
+ const prev = setCurrentRenderingInstance(instance)
ssrRender(
instance.proxy,
push,
instance.data,
instance.ctx
)
- setCurrentRenderingInstance(null)
+ setCurrentRenderingInstance(prev)
} else if (instance.render && instance.render !== NOOP) {
renderVNode(
push,