Repository: babel/babel (TypeScript)

Issue:
[Bug]: commonjs lazy transform produces invalid output with multiple ns imports for same module
### 💻

- [X] Would you like to work on a fix?

### How are you using Babel?

Programmatic API (`babel.transform`, `babel.parse`)

### Input code

```js
import * as a from "mod";
import * as b from "mod";

later(() => [a, b])
```

### Configuration file name

_No response_

### Configuration

```js
const out = transformSync(input, {
  configFile: false,
  plugins: [[await load(`transform-modules-commonjs`), { lazy: true }]],
});
```

### Current and expected behavior

Current:
```js
"use strict";

function a() {
  const data = _interopRequireWildcard(require("mod"));
  a = function () {
    return data;
  };
  return data;
}
var b = a();
function _getRequireWildcardCache(nodeInterop) { ... }
later(() => [a(), b()]);
```

Expected (note the `b` declaration):
```js
"use strict";

function a() {
  const data = _interopRequireWildcard(require("mod"));
  a = function () {
    return data;
  };
  return data;
}
var b = a;
function _getRequireWildcardCache(nodeInterop) { ... }
later(() => [a(), b()]);
```

### Environment

Current main

### Possible solution

_No response_

### Additional context

_No response_


Hints:
Still happens with https://github.com/babel/babel/pull/15878, also with `import defer`.

This bug blocks #15878 and https://github.com/babel/babel/pull/15898.

Patch:
diff --git a/packages/babel-helper-module-transforms/src/index.ts b/packages/babel-helper-module-transforms/src/index.ts
--- a/packages/babel-helper-module-transforms/src/index.ts
+++ b/packages/babel-helper-module-transforms/src/index.ts
@@ -211,8 +211,7 @@ export function buildNamespaceInitStatements(
 ) {
   const statements = [];
 
-  let srcNamespace: t.Node = identifier(sourceMetadata.name);
-  if (sourceMetadata.lazy) srcNamespace = callExpression(srcNamespace, []);
+  const srcNamespaceId = identifier(sourceMetadata.name);
 
   for (const localName of sourceMetadata.importsNamespace) {
     if (localName === sourceMetadata.name) continue;
@@ -221,10 +220,15 @@ export function buildNamespaceInitStatements(
     statements.push(
       template.statement`var NAME = SOURCE;`({
         NAME: localName,
-        SOURCE: cloneNode(srcNamespace),
+        SOURCE: cloneNode(srcNamespaceId),
       }),
     );
   }
+
+  const srcNamespace = sourceMetadata.lazy
+    ? callExpression(srcNamespaceId, [])
+    : srcNamespaceId;
+
   if (constantReexports) {
     statements.push(...buildReexportsFromMeta(metadata, sourceMetadata, true));
   }


Test patch:
diff --git a/packages/babel-plugin-transform-modules-commonjs/test/fixtures/lazy-dep/import-namespace-and-named/input.mjs b/packages/babel-plugin-transform-modules-commonjs/test/fixtures/lazy-dep/import-namespace-and-named/input.mjs
new file mode 100644
--- /dev/null
+++ b/packages/babel-plugin-transform-modules-commonjs/test/fixtures/lazy-dep/import-namespace-and-named/input.mjs
@@ -0,0 +1,4 @@
+import * as foo from "foo";
+import { bar } from "foo";
+
+console.log(foo, bar);
diff --git a/packages/babel-plugin-transform-modules-commonjs/test/fixtures/lazy-dep/import-namespace-and-named/output.js b/packages/babel-plugin-transform-modules-commonjs/test/fixtures/lazy-dep/import-namespace-and-named/output.js
new file mode 100644
--- /dev/null
+++ b/packages/babel-plugin-transform-modules-commonjs/test/fixtures/lazy-dep/import-namespace-and-named/output.js
@@ -0,0 +1,10 @@
+"use strict";
+
+function foo() {
+  const data = babelHelpers.interopRequireWildcard(require("foo"));
+  foo = function () {
+    return data;
+  };
+  return data;
+}
+console.log(foo(), foo().bar);
diff --git a/packages/babel-plugin-transform-modules-commonjs/test/fixtures/lazy-dep/import-namespace-multiple/input.mjs b/packages/babel-plugin-transform-modules-commonjs/test/fixtures/lazy-dep/import-namespace-multiple/input.mjs
new file mode 100644
--- /dev/null
+++ b/packages/babel-plugin-transform-modules-commonjs/test/fixtures/lazy-dep/import-namespace-multiple/input.mjs
@@ -0,0 +1,4 @@
+import * as foo from "foo";
+import * as foo2 from "foo";
+
+console.log(foo, foo2);
diff --git a/packages/babel-plugin-transform-modules-commonjs/test/fixtures/lazy-dep/import-namespace-multiple/output.js b/packages/babel-plugin-transform-modules-commonjs/test/fixtures/lazy-dep/import-namespace-multiple/output.js
new file mode 100644
--- /dev/null
+++ b/packages/babel-plugin-transform-modules-commonjs/test/fixtures/lazy-dep/import-namespace-multiple/output.js
@@ -0,0 +1,11 @@
+"use strict";
+
+function foo() {
+  const data = babelHelpers.interopRequireWildcard(require("foo"));
+  foo = function () {
+    return data;
+  };
+  return data;
+}
+var foo2 = foo;
+console.log(foo(), foo2());