]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(compiler-core): avoid rewriting scope variables in inline for loops (#7245)
authoredison <daiwei521@126.com>
Thu, 9 Nov 2023 09:20:54 +0000 (17:20 +0800)
committerGitHub <noreply@github.com>
Thu, 9 Nov 2023 09:20:54 +0000 (17:20 +0800)
close #7238

packages/compiler-core/__tests__/transforms/__snapshots__/transformExpressions.spec.ts.snap
packages/compiler-core/__tests__/transforms/transformExpressions.spec.ts
packages/compiler-core/src/babelUtils.ts

index 504c866e1281479b65b064db4121694be1322951..434ebcbcf2f4af3d3fe52ff6e6e0cb4a5ce77c88 100644 (file)
@@ -13,3 +13,45 @@ return function render(_ctx, _cache, $props, $setup, $data, $options) {
   return (_openBlock(), _createElementBlock(\\"div\\", null, _toDisplayString($props.props) + \\" \\" + _toDisplayString($setup.setup) + \\" \\" + _toDisplayString($data.data) + \\" \\" + _toDisplayString($options.options) + \\" \\" + _toDisplayString($setup.isNaN), 1 /* TEXT */))
 }"
 `;
+
+exports[`compiler: expression transform > bindingMetadata > should not prefix temp variable of for loop 1`] = `
+"const { openBlock: _openBlock, createElementBlock: _createElementBlock } = Vue
+
+return function render(_ctx, _cache, $props, $setup, $data, $options) {
+  return (_openBlock(), _createElementBlock(\\"div\\", {
+    onClick: () => {
+          for (let i = 0; i < _ctx.list.length; i++) {
+            _ctx.log(i)
+          }         
+        }
+  }, null, 8 /* PROPS */, [\\"onClick\\"]))
+}"
+`;
+
+exports[`compiler: expression transform > bindingMetadata > should not prefix temp variable of for...in 1`] = `
+"const { openBlock: _openBlock, createElementBlock: _createElementBlock } = Vue
+
+return function render(_ctx, _cache, $props, $setup, $data, $options) {
+  return (_openBlock(), _createElementBlock(\\"div\\", {
+    onClick: () => {
+          for (const x in _ctx.list) {
+            _ctx.log(x)
+          }         
+        }
+  }, null, 8 /* PROPS */, [\\"onClick\\"]))
+}"
+`;
+
+exports[`compiler: expression transform > bindingMetadata > should not prefix temp variable of for...of 1`] = `
+"const { openBlock: _openBlock, createElementBlock: _createElementBlock } = Vue
+
+return function render(_ctx, _cache, $props, $setup, $data, $options) {
+  return (_openBlock(), _createElementBlock(\\"div\\", {
+    onClick: () => {
+          for (const x of _ctx.list) {
+            _ctx.log(x)
+          }         
+        }
+  }, null, 8 /* PROPS */, [\\"onClick\\"]))
+}"
+`;
index f8b82396b08602dbfb4671ffa6ad22250651b835..16229113656112940beca1809c2d7c2468ad4adb 100644 (file)
@@ -534,6 +534,42 @@ describe('compiler: expression transform', () => {
       expect(code).toMatchSnapshot()
     })
 
+    test('should not prefix temp variable of for...in', () => {
+      const { code } = compileWithBindingMetadata(
+        `<div @click="() => {
+          for (const x in list) {
+            log(x)
+          }         
+        }"/>`
+      )
+      expect(code).not.toMatch(`_ctx.x`)
+      expect(code).toMatchSnapshot()
+    })
+
+    test('should not prefix temp variable of for...of', () => {
+      const { code } = compileWithBindingMetadata(
+        `<div @click="() => {
+          for (const x of list) {
+            log(x)
+          }         
+        }"/>`
+      )
+      expect(code).not.toMatch(`_ctx.x`)
+      expect(code).toMatchSnapshot()
+    })
+
+    test('should not prefix temp variable of for loop', () => {
+      const { code } = compileWithBindingMetadata(
+        `<div @click="() => {
+          for (let i = 0; i < list.length; i++) {
+            log(i)
+          }         
+        }"/>`
+      )
+      expect(code).not.toMatch(`_ctx.i`)
+      expect(code).toMatchSnapshot()
+    })
+
     test('inline mode', () => {
       const { code } = compileWithBindingMetadata(
         `<div>{{ props }} {{ setup }} {{ setupConst }} {{ data }} {{ options }} {{ isNaN }}</div>`,
index b52ce28990a612bfaf549d6411a656bf06489b8c..1f1e3896a1e07acf7cb45ebfbce86f77ef94c957 100644 (file)
@@ -165,6 +165,19 @@ export function walkBlockDeclarations(
     ) {
       if (stmt.declare || !stmt.id) continue
       onIdent(stmt.id)
+    } else if (
+      stmt.type === 'ForOfStatement' ||
+      stmt.type === 'ForInStatement' ||
+      stmt.type === 'ForStatement'
+    ) {
+      const variable = stmt.type === 'ForStatement' ? stmt.init : stmt.left
+      if (variable && variable.type === 'VariableDeclaration') {
+        for (const decl of variable.declarations) {
+          for (const id of extractIdentifiers(decl.id)) {
+            onIdent(id)
+          }
+        }
+      }
     }
   }
 }