Browse Source

fix(compiler-sfc): should not rewrite scope variable (#3449)

fix #3445
edison 5 years ago
parent
commit
bbc5fe6a97

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

@@ -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'
 

+ 28 - 0
packages/compiler-sfc/__tests__/compileScript.spec.ts

@@ -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())

+ 33 - 10
packages/compiler-sfc/src/compileScript.ts

@@ -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)
               }
             }
           })