]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(reactivity-transform): should not rewrite for...in / for...of scope variables
authorEvan You <yyx990803@gmail.com>
Fri, 31 Dec 2021 03:23:50 +0000 (11:23 +0800)
committerEvan You <yyx990803@gmail.com>
Fri, 31 Dec 2021 03:23:50 +0000 (11:23 +0800)
packages/reactivity-transform/__tests__/reactivityTransform.spec.ts
packages/reactivity-transform/src/reactivityTransform.ts

index 5fffcd5d6d236e3983a0719020d71299e29d2c23..c3c90aae57ef6daeda907467e5e85d5a87faa61c 100644 (file)
@@ -127,15 +127,43 @@ test('accessing ref binding', () => {
   assertCode(code)
 })
 
-test('cases that should not append .value', () => {
-  const { code } = transform(`
+describe('cases that should not append .value', () => {
+  test('member expression', () => {
+    const { code } = transform(`
+      let a = $ref(1)
+      console.log(b.a)
+      `)
+    expect(code).not.toMatch(`a.value`)
+  })
+
+  test('function argument', () => {
+    const { code } = transform(`
+      let a = $ref(1)
+      function get(a) {
+        return a + 1
+      }
+      function get2({ a }) {
+        return a + 1
+      }
+      function get3([a]) {
+        return a + 1
+      }
+      `)
+    expect(code).not.toMatch(`a.value`)
+  })
+
+  test('for in/of loops', () => {
+    const { code } = transform(`
     let a = $ref(1)
-    console.log(b.a)
-    function get(a) {
-      return a + 1
+    for (const [a, b] of arr) {
+      console.log(a)
+    }
+    for (let a in arr) {
+      console.log(a)
     }
     `)
-  expect(code).not.toMatch(`a.value`)
+    expect(code).not.toMatch(`a.value`)
+  })
 })
 
 test('mutating ref binding', () => {
index f7a822ff508e9d2f42088e5ffb0cb247c7bb1606..706b09ec5ad77e24a3da0dbae4b675f3d507baaa 100644 (file)
@@ -7,7 +7,8 @@ import {
   ArrayPattern,
   Program,
   VariableDeclarator,
-  Expression
+  Expression,
+  VariableDeclaration
 } from '@babel/types'
 import MagicString, { SourceMap } from 'magic-string'
 import { walk } from 'estree-walker'
@@ -216,40 +217,49 @@ export function transformAST(
   function walkScope(node: Program | BlockStatement, isRoot = false) {
     for (const stmt of node.body) {
       if (stmt.type === 'VariableDeclaration') {
-        if (stmt.declare) continue
-        for (const decl of stmt.declarations) {
-          let refCall
-          const isCall =
-            decl.init &&
-            decl.init.type === 'CallExpression' &&
-            decl.init.callee.type === 'Identifier'
-          if (
-            isCall &&
-            (refCall = isRefCreationCall((decl as any).init.callee.name))
-          ) {
-            processRefDeclaration(refCall, decl.id, decl.init as CallExpression)
-          } else {
-            const isProps =
-              isRoot &&
-              isCall &&
-              (decl as any).init.callee.name === 'defineProps'
-            for (const id of extractIdentifiers(decl.id)) {
-              if (isProps) {
-                // for defineProps destructure, only exclude them since they
-                // are already passed in as knownProps
-                excludedIds.add(id)
-              } else {
-                registerBinding(id)
-              }
-            }
-          }
-        }
+        walkVariableDeclaration(stmt, isRoot)
       } else if (
         stmt.type === 'FunctionDeclaration' ||
         stmt.type === 'ClassDeclaration'
       ) {
         if (stmt.declare || !stmt.id) continue
         registerBinding(stmt.id)
+      } else if (
+        (stmt.type === 'ForOfStatement' || stmt.type === 'ForInStatement') &&
+        stmt.left.type === 'VariableDeclaration'
+      ) {
+        walkVariableDeclaration(stmt.left)
+      }
+    }
+  }
+
+  function walkVariableDeclaration(stmt: VariableDeclaration, isRoot = false) {
+    if (stmt.declare) {
+      return
+    }
+    for (const decl of stmt.declarations) {
+      let refCall
+      const isCall =
+        decl.init &&
+        decl.init.type === 'CallExpression' &&
+        decl.init.callee.type === 'Identifier'
+      if (
+        isCall &&
+        (refCall = isRefCreationCall((decl as any).init.callee.name))
+      ) {
+        processRefDeclaration(refCall, decl.id, decl.init as CallExpression)
+      } else {
+        const isProps =
+          isRoot && isCall && (decl as any).init.callee.name === 'defineProps'
+        for (const id of extractIdentifiers(decl.id)) {
+          if (isProps) {
+            // for defineProps destructure, only exclude them since they
+            // are already passed in as knownProps
+            excludedIds.add(id)
+          } else {
+            registerBinding(id)
+          }
+        }
       }
     }
   }