fix(compiler-sfc): fix wrong scopeId for nested <script setup> components

This commit is contained in:
Evan You 2021-04-01 18:11:04 -04:00
parent 8c57b9131d
commit 7f7dcc9f7d
3 changed files with 53 additions and 7 deletions

View File

@ -231,12 +231,12 @@ export function generate(
? args.map(arg => `${arg}: any`).join(',') ? args.map(arg => `${arg}: any`).join(',')
: args.join(', ') : args.join(', ')
if (genScopeId) { if (genScopeId && !isSetupInlined) {
if (isSetupInlined) { // root-level _withId wrapping is no longer necessary after 3.0.8 and is
push(`${PURE_ANNOTATION}${WITH_ID}(`) // a noop, it's only kept so that code compiled with 3.0.8+ can run with
} else { // runtime < 3.0.8.
push(`const ${functionName} = ${PURE_ANNOTATION}${WITH_ID}(`) // TODO: consider removing in 3.1
} push(`const ${functionName} = ${PURE_ANNOTATION}${WITH_ID}(`)
} }
if (isSetupInlined || genScopeId) { if (isSetupInlined || genScopeId) {
push(`(${signature}) => {`) push(`(${signature}) => {`)
@ -303,7 +303,7 @@ export function generate(
deindent() deindent()
push(`}`) push(`}`)
if (genScopeId) { if (genScopeId && !isSetupInlined) {
push(`)`) push(`)`)
} }
@ -438,6 +438,7 @@ function genModulePreamble(
// we technically don't need this anymore since `withCtx` already sets the // we technically don't need this anymore since `withCtx` already sets the
// correct scopeId, but this is necessary for backwards compat // correct scopeId, but this is necessary for backwards compat
// TODO: consider removing in 3.1
if (genScopeId) { if (genScopeId) {
push( push(
`const ${WITH_ID} = ${PURE_ANNOTATION}${helper( `const ${WITH_ID} = ${PURE_ANNOTATION}${helper(

View File

@ -272,6 +272,25 @@ return (_ctx, _cache) => {
}" }"
`; `;
exports[`SFC compile <script setup> inlineTemplate mode should not wrap render fn with withId when having scoped styles 1`] = `
"import { toDisplayString as _toDisplayString, openBlock as _openBlock, createBlock as _createBlock, withScopeId as _withScopeId } from \\"vue\\"
const _withId = /*#__PURE__*/_withScopeId(\\"data-v-xxxxxxxx\\")
export default {
expose: [],
setup(__props) {
const msg = 1
return (_ctx, _cache) => {
return (_openBlock(), _createBlock(\\"h1\\", null, _toDisplayString(msg)))
}
}
}"
`;
exports[`SFC compile <script setup> inlineTemplate mode should work 1`] = ` exports[`SFC compile <script setup> inlineTemplate mode should work 1`] = `
"import { toDisplayString as _toDisplayString, createVNode as _createVNode, Fragment as _Fragment, openBlock as _openBlock, createBlock as _createBlock } from \\"vue\\" "import { toDisplayString as _toDisplayString, createVNode as _createVNode, Fragment as _Fragment, openBlock as _openBlock, createBlock as _createBlock } from \\"vue\\"

View File

@ -404,6 +404,32 @@ const myEmit = defineEmit(['foo', 'bar'])
expect(content).toMatch(`ssrInterpolate`) expect(content).toMatch(`ssrInterpolate`)
assertCode(content) assertCode(content)
}) })
// _withId is only generated for backwards compat and is a noop when called
// in module scope.
// when inside setup(), currentInstance will be non-null and _withId will
// no longer be noop and cause scopeId errors.
// TODO: this test should no longer be necessary if we remove _withId
// codegen in 3.1
test('should not wrap render fn with withId when having scoped styles', async () => {
const { content } = compile(
`
<script setup>
const msg = 1
</script>
<template><h1>{{ msg }}</h1></template>
<style scoped>
h1 { color: red; }
</style>
`,
{
inlineTemplate: true
}
)
expect(content).toMatch(`return (_ctx, _cache`)
expect(content).not.toMatch(`_withId(`)
assertCode(content)
})
}) })
describe('with TypeScript', () => { describe('with TypeScript', () => {