Skip to content

Commit 7f7dcc9

Browse files
committed
fix(compiler-sfc): fix wrong scopeId for nested <script setup> components
1 parent 8c57b91 commit 7f7dcc9

File tree

3 files changed

+53
-7
lines changed

3 files changed

+53
-7
lines changed

packages/compiler-core/src/codegen.ts

+8-7
Original file line numberDiff line numberDiff line change
@@ -231,12 +231,12 @@ export function generate(
231231
? args.map(arg => `${arg}: any`).join(',')
232232
: args.join(', ')
233233

234-
if (genScopeId) {
235-
if (isSetupInlined) {
236-
push(`${PURE_ANNOTATION}${WITH_ID}(`)
237-
} else {
238-
push(`const ${functionName} = ${PURE_ANNOTATION}${WITH_ID}(`)
239-
}
234+
if (genScopeId && !isSetupInlined) {
235+
// root-level _withId wrapping is no longer necessary after 3.0.8 and is
236+
// a noop, it's only kept so that code compiled with 3.0.8+ can run with
237+
// runtime < 3.0.8.
238+
// TODO: consider removing in 3.1
239+
push(`const ${functionName} = ${PURE_ANNOTATION}${WITH_ID}(`)
240240
}
241241
if (isSetupInlined || genScopeId) {
242242
push(`(${signature}) => {`)
@@ -303,7 +303,7 @@ export function generate(
303303
deindent()
304304
push(`}`)
305305

306-
if (genScopeId) {
306+
if (genScopeId && !isSetupInlined) {
307307
push(`)`)
308308
}
309309

@@ -438,6 +438,7 @@ function genModulePreamble(
438438

439439
// we technically don't need this anymore since `withCtx` already sets the
440440
// correct scopeId, but this is necessary for backwards compat
441+
// TODO: consider removing in 3.1
441442
if (genScopeId) {
442443
push(
443444
`const ${WITH_ID} = ${PURE_ANNOTATION}${helper(

packages/compiler-sfc/__tests__/__snapshots__/compileScript.spec.ts.snap

+19
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,25 @@ return (_ctx, _cache) => {
272272
}"
273273
`;
274274
275+
exports[`SFC compile <script setup> inlineTemplate mode should not wrap render fn with withId when having scoped styles 1`] = `
276+
"import { toDisplayString as _toDisplayString, openBlock as _openBlock, createBlock as _createBlock, withScopeId as _withScopeId } from \\"vue\\"
277+
const _withId = /*#__PURE__*/_withScopeId(\\"data-v-xxxxxxxx\\")
278+
279+
280+
export default {
281+
expose: [],
282+
setup(__props) {
283+
284+
const msg = 1
285+
286+
return (_ctx, _cache) => {
287+
return (_openBlock(), _createBlock(\\"h1\\", null, _toDisplayString(msg)))
288+
}
289+
}
290+
291+
}"
292+
`;
293+
275294
exports[`SFC compile <script setup> inlineTemplate mode should work 1`] = `
276295
"import { toDisplayString as _toDisplayString, createVNode as _createVNode, Fragment as _Fragment, openBlock as _openBlock, createBlock as _createBlock } from \\"vue\\"
277296

packages/compiler-sfc/__tests__/compileScript.spec.ts

+26
Original file line numberDiff line numberDiff line change
@@ -404,6 +404,32 @@ const myEmit = defineEmit(['foo', 'bar'])
404404
expect(content).toMatch(`ssrInterpolate`)
405405
assertCode(content)
406406
})
407+
408+
// _withId is only generated for backwards compat and is a noop when called
409+
// in module scope.
410+
// when inside setup(), currentInstance will be non-null and _withId will
411+
// no longer be noop and cause scopeId errors.
412+
// TODO: this test should no longer be necessary if we remove _withId
413+
// codegen in 3.1
414+
test('should not wrap render fn with withId when having scoped styles', async () => {
415+
const { content } = compile(
416+
`
417+
<script setup>
418+
const msg = 1
419+
</script>
420+
<template><h1>{{ msg }}</h1></template>
421+
<style scoped>
422+
h1 { color: red; }
423+
</style>
424+
`,
425+
{
426+
inlineTemplate: true
427+
}
428+
)
429+
expect(content).toMatch(`return (_ctx, _cache`)
430+
expect(content).not.toMatch(`_withId(`)
431+
assertCode(content)
432+
})
407433
})
408434

409435
describe('with TypeScript', () => {

0 commit comments

Comments
 (0)