Repository: swc-project/swc (rust)

Issue:
Transpilation of import * as var is undefined in namespace usage
### Describe the bug

Following code is transpiled faulty:
```
import * as I from "./ABC";

/* eslint-disable @typescript-eslint/no-namespace */
export namespace IE {
    export import A = I.A;
    export import C = I.C;
    export import D = I.D;
    ...
}
```
To
```
(function(I1) {
    var A = I.A;
    I1.A = A;
    var C = I.C;
    I1.C = C;
    var D = I.D;
    I1.D = D;
    ...
})(IE || (exports.IE = IE = {}));
```

`VM2679:1 Uncaught ReferenceError: I is not defined`
The var `I` doesnt exist in the transpiled file at all anymore except within the assignation part in the IIFE.


### Input code

_No response_

### Config

```json
{
                    test: /\.ts(x?)$/,
                    use: 
                        {
                            loader: "swc-loader",
                            options: {
                                sync: true,
                                jsc: {
                                    parser: {
                                        syntax: "typescript",
                                        tsx: true,
                                        dynamicImport: true
                                    },
                                    loose: false,
                                    externalHelpers: true,
                                    // Requires v1.2.50 or upper and requires target to be es2016 or upper.
                                    keepClassNames: false,

                                },
                                module: {
                                    type: "commonjs",
                                    strictMode: false,
                                    lazy: true
                                }
                            }
                        }
                }
```


### Playground link

_No response_

### Expected behavior

The import * as VAR variable should still be defined, as it is used in the namespace code. But it seems to be gone.

### Actual behavior

The var is not existing causing is not defined error.

### Version

1.2.173

### Additional context

_No response_

Pull request:
fix(swc/transforms): preserve referenced imports for namespace
- fix(swc/transform): preserve import references to namespace reexports
- test(swc/transforms): update test cases

<!-- Note: CI script will automatically rebase your PR so please do not rebase unless required -->

<!-- Thanks for submitting a pull request! Please provide enough information so that others can review your pull request. -->

**Description:**

This PR attempts to fix #4481 which loses reference to imports if reference occurred in namespace as reexports. When module_items manually visit importdecl visitor hasn't completed to visit inner idents to update references, in result import gets stripped eagerly. PR changes logic to ensure reference if namespace scoped ident reference is non type-only reexports.

**BREAKING CHANGE:**

<!--
If this PR introduces a breaking change, it must contain a notice for it to be included in the CHANGELOG. Add description or remove entirely if not breaking.

You may need to update `MIGRATION.md` for the breaking changes.
-->

**Related issue (if exists):**

#4481


Patch:
diff --git a/crates/swc_ecma_transforms_typescript/src/strip.rs b/crates/swc_ecma_transforms_typescript/src/strip.rs
index fe20b946f8..1faaa70624 100644
--- a/crates/swc_ecma_transforms_typescript/src/strip.rs
+++ b/crates/swc_ecma_transforms_typescript/src/strip.rs
@@ -1658,6 +1658,17 @@ where
                     match name {
                         TsEntityName::Ident(ref i) => {
                             entry.maybe_dependency = Some(i.clone());
+                            // Eagerly update referenced idents for the concrete exports
+                            // resolves https://github.com/swc-project/swc/issues/4481, if we
+                            // know reference exists & reexports.
+                            // when referenced idents are scoped in ts namespace, its references
+                            // is updated _after_ visiting import decl which strips out imports
+                            // already.
+                            if n.is_export && !n.is_type_only {
+                                let entry =
+                                    self.scope.referenced_idents.entry(i.to_id()).or_default();
+                                entry.has_concrete = true;
+                            }
                             break;
                         }
                         TsEntityName::TsQualifiedName(ref q) => name = &q.left,


Test patch:
diff --git a/crates/swc_ecma_transforms_typescript/tests/fixture/issue-4481/1/input.ts b/crates/swc_ecma_transforms_typescript/tests/fixture/issue-4481/1/input.ts
new file mode 100644
index 0000000000..e6627c31f0
--- /dev/null
+++ b/crates/swc_ecma_transforms_typescript/tests/fixture/issue-4481/1/input.ts
@@ -0,0 +1,7 @@
+import * as I from "./ABC";
+
+export namespace IE {
+    export import A = I.A;
+    export import C = I.C;
+    export import D = I.D;
+}
diff --git a/crates/swc_ecma_transforms_typescript/tests/fixture/issue-4481/1/output.js b/crates/swc_ecma_transforms_typescript/tests/fixture/issue-4481/1/output.js
new file mode 100644
index 0000000000..81389fb785
--- /dev/null
+++ b/crates/swc_ecma_transforms_typescript/tests/fixture/issue-4481/1/output.js
@@ -0,0 +1,10 @@
+import * as I from "./ABC";
+export var IE;
+(function(IE1) {
+    var A = I.A;
+    IE1.A = A;
+    var C = I.C;
+    IE1.C = C;
+    var D = I.D;
+    IE1.D = D;
+})(IE || (IE = {}));
\ No newline at end of file