Repository: babel/babel (TypeScript)

Issue:
[Bug]: transform error when use two loops in one function with @babel/plugin-transform-block-scoping@7.20.9
### 💻

- [ ] Would you like to work on a fix?

### How are you using Babel?

Programmatic API (`babel.transform`, `babel.parse`)

### Input code

```
const test = (data) => {
  for (let i = 0; i < data.length; i++) {
    const x = data[i];
    data.find((item) => item === x);
  }
  for (let i = 0; i < data.length; i++) {
    const x = data[i];
    data.find((item) => item === x);
  }
}
```

### Configuration file name

.babelrc

### Configuration

{
  "presets": [
    "@babel/preset-env"
  ]
}

### Current and expected behavior

current output:
```
"use strict";

var test = function test(data) {
  var _loop = function _loop() {
    var x = data[i];
    data.find(function (item) {
      return item === x;
    });
  };
  for (var i = 0; i < data.length; i++) {
    _loop();
  }
  var _loop2 = function _loop2() {
    var x = data[i];
    data.find(function (item) {
      return item === x;
    });
  };
  for (var _i = 0; _i < data.length; _i++) {
    _loop2();
  }
};
```

the second `var x = data[i];` should be `var x = data[_i];`

### Environment

  System:
    OS: macOS 12.6.2
  Binaries:
    Node: 14.19.0 - /usr/local/bin/node
    Yarn: 1.22.17 - /usr/local/bin/yarn
    npm: 6.14.16 - /usr/local/bin/npm
  npmPackages:
    @babel/cli: ^7.17.6 => 7.17.6 
    @babel/core: ^7.20.7 => 7.20.7 
    @babel/node: ^7.16.8 => 7.16.8 
    @babel/plugin-transform-block-scoping: ^7.20.9 => 7.20.9 
    @babel/preset-env: ^7.16.11 => 7.16.11 

### Possible solution

_No response_

### Additional context

_No response_


Hints:
Hey @Erucy! We really appreciate you taking the time to report an issue. The collaborators on this project attempt to help as many people as possible, but we're a limited number of volunteers, so it's possible this won't be addressed swiftly.

If you need any help, or just have general Babel or JavaScript questions, we have a vibrant [Slack community](https://babeljs.slack.com) that typically always has someone willing to help. You can sign-up [here](https://slack.babeljs.io/) for an invite.
@babel/plugin-transform-block-scoping@7.20.7 is the first affected version
The Same issue happened to me，with the latest version 7.20.11
Also having this issue on 7.20.11
@hanzooo @aaronhargrove-grub Can you provide a repo to reproduce it?
@liuxingbaoyu [This repl](https://babeljs.io/repl/#?browsers=last%202%20versions%2C%0Anot%20dead%2C%0AChrome%20%3E%3D%2045%2C%0ASafari%20%3E%3D%2011%2C%0AFirefox%20%3E%3D%2045%2C&build=&builtIns=entry&corejs=3.21&spec=false&loose=false&code_lz=C4TwDgpgBAyg9gWwgGTnA1gVzFAvFAbwCgooBtASwDsATCADwC4orMEAjCAJwF1mAxNACEAhlwAq4CGR4BuIgF95RAGaYqAY2AU4VKCuFiAFCSgBnYCOARm8JDEvWANKYJQuEM2F1noC5gBKnt5UvgDy7ABWEFpEAJS2iBBBwJhcVJKQhKSmGj7A5kn8ADZW1lQQNACSVAZcCFY6evgeXj4QAHQeNJgaEEZGrZjFwE5QGmkeVMAAaiLFmBBxeAB8hKakeaEFbmJcIiBhKuIAFtQA5mZQCnjjkxDTcwsQ8qSkdVBGxRAF1HT0twADLIoH8GFAADxQPYHI6nC5mDrfKjnYAnEFg-gAaixy2IbzeWwsUDRF1uMMOxzOKLMlFoDDkG0J-X0aFuACkYGEAHIdMBiXxGClw6mXDoGOBxV4E8YssxJACyIjAEUit3xMtIImYEo6IhUZhoKhcmtI7B1aA6ADcaCJDcamaQlI6oN8CvKkKqYsAAOoUNEAYV0NH9TVuZDcFBozAA5B6IFUaDHrjxxX8TKbPvRlrg1vQOlG8Lh8PGlSqonqXXEXQB6GtQeFXChXB5wTDnE6yugkuDuCBgLhwHp9EknaDNsyLJkKJkeVLpPuTkbShRjAg3O2wJKoDDYKVEUxztJ6eMlMoPSo1OoNbS6eQKIA&debug=false&forceAllTransforms=false&shippedProposals=false&circleciRepo=&evaluate=false&fileSize=false&timeTravel=false&sourceType=module&lineWrap=true&presets=env%2Creact%2Ctypescript&prettier=false&targets=&version=7.20.12&externalPlugins=&assumptions=%7B%7D) reproduces the issue. Seems to be tied to the type in the file in our case
![image](https://user-images.githubusercontent.com/30521560/210785359-7e5d6e84-967a-4f3d-8394-46f34119500c.png)
Thank you for your report!
https://babeljs.io/repl/#?browsers=node%204&build=&builtIns=usage&corejs=3.21&spec=false&loose=false&code_lz=C4TwDgpgBAyg9gWwgGTnA1gVzFAvFAbwCgooBtASwDsATCADwC4orMEAjCAJwF1mBDKiDI8A3EQC-4ogDNMVAMbAKcKlBloAQvy4AKHV34gA8jIAqAC2oBzAM4BKQqRKl1cLlF0AbCMCjU6ejwoAAZRf1oGKAAeKAMjU0sbWwA6HyprYAtwgIYAajzHYldXBVVbPyybYPiTcysM20pI-jEXErKqCqhbRAgAWX4wY3YAK2CCKXbXHz8DOAB3YN16R1wAPh6-weGx8RLSeYXde2mJSSJZLR1dMgBGABoAJgeAZh57IA&debug=false&forceAllTransforms=false&shippedProposals=false&circleciRepo=&evaluate=false&fileSize=false&timeTravel=false&sourceType=module&lineWrap=true&presets=env%2Ctypescript&prettier=false&targets=&version=7.20.12&externalPlugins=&assumptions=%7B%7D
Here's a smaller reproducible repl.

There are two problems here.
1. Outdated binding information causes renaming to fail.
2. `index` was incorrectly registered to `scope.globals`.
```ts
type SomeLookup = {
   [index: number]: FooBarType[];
};
```


The real fix should be 1, which seems a bit tricky to fix.
Since our `scope.rename` is actually implemented using `traverseNode`, `rename` will not work properly when it is split into two blocks.
The way I figured it out is to do the renaming before `wrapLoopBody`, but so far I haven't been able to get TDZ to continue working properly.

@nicolo-ribaudo If you plan on doing it too feel free to do it! If not I'll keep trying tomorrow.

Patch:
diff --git a/packages/babel-plugin-transform-block-scoping/src/index.ts b/packages/babel-plugin-transform-block-scoping/src/index.ts
--- a/packages/babel-plugin-transform-block-scoping/src/index.ts
+++ b/packages/babel-plugin-transform-block-scoping/src/index.ts
@@ -87,13 +87,16 @@ export default declare((api, opts: Options) => {
               if (capturedInClosure) {
                 markNeedsBodyWrap();
                 captured.push(name);
-              } else if (headScope.parent.hasBinding(name)) {
+              } else if (
+                headScope.parent.hasBinding(name) ||
+                headScope.parent.hasGlobal(name)
+              ) {
                 // If the binding is not captured, there is no need
                 // of adding it to the closure param. However, rename
                 // it if it shadows an outer binding, because the
                 // closure will be moved to an outer level.
                 const newName = headScope.generateUid(name);
-                headPath.scope.rename(name, newName);
+                headScope.rename(name, newName);
                 name = newName;
               }
 
@@ -203,12 +206,8 @@ function transformBlockScopedVariable(
   }
 
   const blockScope = path.scope;
-  let varScope = blockScope.getFunctionParent();
-  let isProgramScope = false;
-  if (!varScope) {
-    varScope = blockScope.getProgramParent();
-    isProgramScope = true;
-  }
+  const varScope =
+    blockScope.getFunctionParent() || blockScope.getProgramParent();
 
   if (varScope !== blockScope) {
     for (const name of bindingNames) {
@@ -219,8 +218,7 @@ function transformBlockScopedVariable(
         // a nested scope and thus we don't need to assume that it
         // may be declared (but not registered yet) in an upper one.
         blockScope.parent.hasBinding(name, { noUids: true }) ||
-        blockScope.parent.hasGlobal(name) ||
-        (isProgramScope && varScope.hasGlobal(name))
+        blockScope.parent.hasGlobal(name)
       ) {
         newName = blockScope.generateUid(name);
         blockScope.rename(name, newName);


Test patch:
diff --git a/packages/babel-plugin-transform-block-scoping/test/fixtures/regression/rename-with-other-plugins/input.ts b/packages/babel-plugin-transform-block-scoping/test/fixtures/regression/rename-with-other-plugins/input.ts
new file mode 100644
--- /dev/null
+++ b/packages/babel-plugin-transform-block-scoping/test/fixtures/regression/rename-with-other-plugins/input.ts
@@ -0,0 +1,12 @@
+// https://github.com/babel/babel/pull/15361
+
+function fooBar(arrayOfThings) {
+    for (let index = 0; index < arrayOfThings.length; index++) {
+      const thing = arrayOfThings[index];
+      const someMapObj = {};
+      let arrow = (x) => someMapObj;
+      arrow(0)
+    }
+}
+
+fooBar([1,2,3])
diff --git a/packages/babel-plugin-transform-block-scoping/test/fixtures/regression/rename-with-other-plugins/options.json b/packages/babel-plugin-transform-block-scoping/test/fixtures/regression/rename-with-other-plugins/options.json
new file mode 100644
--- /dev/null
+++ b/packages/babel-plugin-transform-block-scoping/test/fixtures/regression/rename-with-other-plugins/options.json
@@ -0,0 +1,3 @@
+{
+  "plugins": ["./plugin.cjs", "transform-typescript", "transform-block-scoping"]
+}
diff --git a/packages/babel-plugin-transform-block-scoping/test/fixtures/regression/rename-with-other-plugins/output.js b/packages/babel-plugin-transform-block-scoping/test/fixtures/regression/rename-with-other-plugins/output.js
new file mode 100644
--- /dev/null
+++ b/packages/babel-plugin-transform-block-scoping/test/fixtures/regression/rename-with-other-plugins/output.js
@@ -0,0 +1,14 @@
+// https://github.com/babel/babel/pull/15361
+
+function fooBar(arrayOfThings) {
+  var _loop = function () {
+    var thing = arrayOfThings[_index];
+    var someMapObj = {};
+    var arrow = x => someMapObj;
+    arrow(0);
+  };
+  for (var _index = 0; _index < arrayOfThings.length; _index++) {
+    _loop();
+  }
+}
+fooBar([1, 2, 3]);
diff --git a/packages/babel-plugin-transform-block-scoping/test/fixtures/regression/rename-with-other-plugins/plugin.cjs b/packages/babel-plugin-transform-block-scoping/test/fixtures/regression/rename-with-other-plugins/plugin.cjs
new file mode 100644
--- /dev/null
+++ b/packages/babel-plugin-transform-block-scoping/test/fixtures/regression/rename-with-other-plugins/plugin.cjs
@@ -0,0 +1,11 @@
+module.exports = function (babel) {
+  const { types: t } = babel;
+
+  return {
+    visitor: {
+      Program(path) {
+        path.scope.addGlobal(t.identifier("index"));
+      },
+    },
+  };
+};