]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(compiler-sfc): fix wrong scopeId for nested `<script setup>` components
authorEvan You <yyx990803@gmail.com>
Thu, 1 Apr 2021 22:11:04 +0000 (18:11 -0400)
committerEvan You <yyx990803@gmail.com>
Thu, 1 Apr 2021 22:11:04 +0000 (18:11 -0400)
packages/compiler-core/src/codegen.ts
packages/compiler-sfc/__tests__/__snapshots__/compileScript.spec.ts.snap
packages/compiler-sfc/__tests__/compileScript.spec.ts

index 939b3b356adff4a538b244d68acc4667c134fa25..e3dbbc820fc6f55c4b0175384de87c52e39327f8 100644 (file)
@@ -231,12 +231,12 @@ export function generate(
       ? args.map(arg => `${arg}: any`).join(',')
       : args.join(', ')
 
-  if (genScopeId) {
-    if (isSetupInlined) {
-      push(`${PURE_ANNOTATION}${WITH_ID}(`)
-    } else {
-      push(`const ${functionName} = ${PURE_ANNOTATION}${WITH_ID}(`)
-    }
+  if (genScopeId && !isSetupInlined) {
+    // root-level _withId wrapping is no longer necessary after 3.0.8 and is
+    // a noop, it's only kept so that code compiled with 3.0.8+ can run with
+    // runtime < 3.0.8.
+    // TODO: consider removing in 3.1
+    push(`const ${functionName} = ${PURE_ANNOTATION}${WITH_ID}(`)
   }
   if (isSetupInlined || genScopeId) {
     push(`(${signature}) => {`)
@@ -303,7 +303,7 @@ export function generate(
   deindent()
   push(`}`)
 
-  if (genScopeId) {
+  if (genScopeId && !isSetupInlined) {
     push(`)`)
   }
 
@@ -438,6 +438,7 @@ function genModulePreamble(
 
   // we technically don't need this anymore since `withCtx` already sets the
   // correct scopeId, but this is necessary for backwards compat
+  // TODO: consider removing in 3.1
   if (genScopeId) {
     push(
       `const ${WITH_ID} = ${PURE_ANNOTATION}${helper(
index f648f39e8faecbf2ebda529b5293ae10cebdd8cd..7397228fb3b3aa90bdf0a8773ade2c9e84b8d94b 100644 (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`] = `
 "import { toDisplayString as _toDisplayString, createVNode as _createVNode, Fragment as _Fragment, openBlock as _openBlock, createBlock as _createBlock } from \\"vue\\"
 
index 41e3abe8c572f57897fdd7d142312e2e1b9f260f..d74d7448aa965acc0d14a9ced32154f86d046ee1 100644 (file)
@@ -404,6 +404,32 @@ const myEmit = defineEmit(['foo', 'bar'])
       expect(content).toMatch(`ssrInterpolate`)
       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', () => {