From 37bb78a197a2efe92aa526ccc6dda93a1be60aab Mon Sep 17 00:00:00 2001 From: yangchangtao Date: Mon, 14 Oct 2024 18:54:08 +0800 Subject: [PATCH] fix(ssr): avoid scopeId inheritance when recursing components --- .../__tests__/ssrScopeId.spec.ts | 22 ++++++++++++++++++- packages/server-renderer/src/render.ts | 3 ++- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/packages/server-renderer/__tests__/ssrScopeId.spec.ts b/packages/server-renderer/__tests__/ssrScopeId.spec.ts index 4ceb865fb50..4c369a48402 100644 --- a/packages/server-renderer/__tests__/ssrScopeId.spec.ts +++ b/packages/server-renderer/__tests__/ssrScopeId.spec.ts @@ -1,6 +1,7 @@ -import { createApp, h, mergeProps, withCtx } from 'vue' +import { createApp, createVNode, h, mergeProps, withCtx } from 'vue' import { renderToString } from '../src/renderToString' import { ssrRenderAttrs, ssrRenderComponent, ssrRenderSlot } from '../src' +import { renderVNode } from '../src/render' describe('ssr: scopedId runtime behavior', () => { test('id on component root', async () => { @@ -269,4 +270,23 @@ describe('ssr: scopedId runtime behavior', () => { ``, ) }) + + // #12159 + test('avoid scopeId inheritance when recursing components', async () => { + let count = 2 + + const Comp = { + __scopeId: 'comp', + ssrRender: (ctx: any, push: any, parent: any, attrs: any) => { + if (--count) { + push(ssrRenderComponent(h(Comp), attrs, null, parent)) + } else { + renderVNode(push, createVNode('div', attrs, 'vuejs'), parent) + } + }, + } + + const result = await renderToString(createApp(Comp)) // output: `
` + expect(result).toBe(`
vuejs
`) + }) }) diff --git a/packages/server-renderer/src/render.ts b/packages/server-renderer/src/render.ts index f04080b9c31..5c158a99b29 100644 --- a/packages/server-renderer/src/render.ts +++ b/packages/server-renderer/src/render.ts @@ -19,6 +19,7 @@ import { ShapeFlags, escapeHtml, escapeHtmlComment, + hasOwn, isArray, isFunction, isPromise, @@ -303,7 +304,7 @@ function renderElementVNode( openTag += ssrRenderAttrs(props, tag) } - if (scopeId) { + if (scopeId && (!props || !hasOwn(props, scopeId))) { openTag += ` ${scopeId}` } // inherit parent chain scope id if this is the root node