Browse Source

fix(compiler-core): avoid rewriting scope variables in inline for loops (#7245)

close #7238
edison 2 years ago
parent
commit
a2d810eb40

+ 42 - 0
packages/compiler-core/__tests__/transforms/__snapshots__/transformExpressions.spec.ts.snap

@@ -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\\"]))
+}"
+`;

+ 36 - 0
packages/compiler-core/__tests__/transforms/transformExpressions.spec.ts

@@ -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>`,

+ 13 - 0
packages/compiler-core/src/babelUtils.ts

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