]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(compiler-sfc): should not rewrite scope variable (#3449)
authoredison <daiwei521@126.com>
Thu, 25 Mar 2021 20:16:48 +0000 (04:16 +0800)
committerGitHub <noreply@github.com>
Thu, 25 Mar 2021 20:16:48 +0000 (16:16 -0400)
fix #3445

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

index 59ef9b1b7ee89173062e947b531d6fdeb4bc5a1e..c27f0aeabe2565f2e34fb69e34d50ea243d6fb3e 100644 (file)
@@ -626,6 +626,35 @@ return {  }
 }"
 `;
 
+exports[`SFC compile <script setup> ref: syntax sugar should not rewrite scope variable 1`] = `
+"import { ref as _ref } from 'vue'
+
+export default {
+  expose: [],
+  setup(__props) {
+
+        const a = _ref(1)
+        const b = _ref(1)
+        const d = _ref(1)
+        const e = 1
+        function test() {
+          const a = 2
+          console.log(a)
+          console.log(b.value)
+          let c = { c: 3 }
+          console.log(c)
+          let $d
+          console.log($d)
+          console.log(d.value)
+          console.log(e)
+        }
+      
+return { a, b, d, e, test }
+}
+
+}"
+`;
+
 exports[`SFC compile <script setup> ref: syntax sugar using ref binding in property shorthand 1`] = `
 "import { ref as _ref } from 'vue'
 
index 0594bf26dbfacdd65b219bbceaef62d7f5b46d6e..30cef0fbcd4e956497743fa1404b8c960da33fb0 100644 (file)
@@ -708,6 +708,34 @@ const emit = defineEmit(['a', 'b'])
       assertCode(content)
     })
 
+    test('should not rewrite scope variable', () => {
+      const { content } = compile(`
+      <script setup>
+        ref: a = 1
+        ref: b = 1
+        ref: d = 1
+        const e = 1
+        function test() {
+          const a = 2
+          console.log(a)
+          console.log(b)
+          let c = { c: 3 }
+          console.log(c)
+          let $d
+          console.log($d)
+          console.log(d)
+          console.log(e)
+        }
+      </script>`)
+      expect(content).toMatch('console.log(a)')
+      expect(content).toMatch('console.log(b.value)')
+      expect(content).toMatch('console.log(c)')
+      expect(content).toMatch('console.log($d)')
+      expect(content).toMatch('console.log(d.value)')
+      expect(content).toMatch('console.log(e)')
+      assertCode(content)
+    })
+
     test('object destructure', () => {
       const { content, bindings } = compile(`<script setup>
       ref: n = 1, ({ a, b: c, d = 1, e: f = 2, ...g } = useFoo())
index 74430499df0439f82b34a175c32ac82b67aa9bf7..864fcbbbf7c68b87aa589cc3521c06e6f671f0e7 100644 (file)
@@ -1344,6 +1344,23 @@ function genRuntimeEmits(emits: Set<string>) {
     : ``
 }
 
+function markScopeIdentifier(
+  node: Node & { scopeIds?: Set<string> },
+  child: Identifier,
+  knownIds: Record<string, number>
+) {
+  const { name } = child
+  if (node.scopeIds && node.scopeIds.has(name)) {
+    return
+  }
+  if (name in knownIds) {
+    knownIds[name]++
+  } else {
+    knownIds[name] = 1
+  }
+  ;(node.scopeIds || (node.scopeIds = new Set())).add(name)
+}
+
 /**
  * Walk an AST and find identifiers that are variable references.
  * This is largely the same logic with `transformExpressions` in compiler-core
@@ -1367,6 +1384,21 @@ function walkIdentifiers(
           onIdentifier(node, parent!, parentStack)
         }
       } else if (isFunction(node)) {
+        // #3445
+        // should not rewrite local variables sharing a name with a top-level ref
+        if (node.body.type === 'BlockStatement') {
+          node.body.body.forEach(p => {
+            if (p.type === 'VariableDeclaration') {
+              ;(walk as any)(p, {
+                enter(child: Node) {
+                  if (child.type === 'Identifier') {
+                    markScopeIdentifier(node, child, knownIds)
+                  }
+                }
+              })
+            }
+          })
+        }
         // walk function expressions and add its arguments to known identifiers
         // so that we don't prefix them
         node.params.forEach(p =>
@@ -1384,16 +1416,7 @@ function walkIdentifiers(
                   parent.right === child
                 )
               ) {
-                const { name } = child
-                if (node.scopeIds && node.scopeIds.has(name)) {
-                  return
-                }
-                if (name in knownIds) {
-                  knownIds[name]++
-                } else {
-                  knownIds[name] = 1
-                }
-                ;(node.scopeIds || (node.scopeIds = new Set())).add(name)
+                markScopeIdentifier(node, child, knownIds)
               }
             }
           })