Repository: swc-project/swc (rust)

Issue:
name conflict between imports and underscore prefixed function-scoped properties
**Describe the bug**

This is a regression - works fine for me in 1.2.74

During transpilation imports are renamed to file name prefixed with underscore. If you define a class property with the same name, it will instead overshadow the import.

This works fine if you define simple variable with the same name - transpiler resolves the conflict by using number as a suffix.

**Input code**

bar.ts
```
export const bar = () => console.log("foo");
```

foo.ts
```
import { bar } from "./bar";

const makeX = () => {
  const _bar = () => bar();
  return { _bar };
}

makeX()._bar();
```

Throws:
```
        this._bar = ()=>(0, _bar).bar()
                                  ^

TypeError: (0 , _bar).bar is not a function
```

**Config**

```json
{
  "env": {
    "targets": {
      "node": "16.8"
    }
  },
  "jsc": {
    "target": "es2019",
    "parser": {
      "syntax": "typescript",
      "tsx": true
    }
  },
  "module": {
    "type": "commonjs"
  },
  "sourceMaps": "inline"
}
```

**Expected behavior**
Generated import names should not conflict with class properties after transpilation.

**Version**
The version of @swc/core: 1.2.84


Pull request:
fix(es/transforms/base): Fix `hygiene`
swc_ecma_transforms_base:
 - `hygiene`: Handle decl-ref conflict. (Closes #2211)

Patch:
diff --git a/Cargo.lock b/Cargo.lock
index 901f9f7c6f..3a212ffbc3 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -2738,7 +2738,7 @@ dependencies = [
 
 [[package]]
 name = "swc_ecma_transforms_base"
-version = "0.31.2"
+version = "0.31.3"
 dependencies = [
  "fxhash",
  "once_cell",
@@ -3401,7 +3401,7 @@ checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6"
 
 [[package]]
 name = "wasm"
-version = "1.2.89"
+version = "1.2.90"
 dependencies = [
  "anyhow",
  "console_error_panic_hook",
diff --git a/ecmascript/transforms/base/Cargo.toml b/ecmascript/transforms/base/Cargo.toml
index 0f8348dcea..961bf16d73 100644
--- a/ecmascript/transforms/base/Cargo.toml
+++ b/ecmascript/transforms/base/Cargo.toml
@@ -6,7 +6,7 @@ edition = "2018"
 license = "Apache-2.0/MIT"
 name = "swc_ecma_transforms_base"
 repository = "https://github.com/swc-project/swc.git"
-version = "0.31.2"
+version = "0.31.3"
 
 [dependencies]
 fxhash = "0.2.1"
diff --git a/ecmascript/transforms/base/src/hygiene/mod.rs b/ecmascript/transforms/base/src/hygiene/mod.rs
index ec2fe5d811..3198f4c831 100644
--- a/ecmascript/transforms/base/src/hygiene/mod.rs
+++ b/ecmascript/transforms/base/src/hygiene/mod.rs
@@ -900,14 +900,14 @@ impl<'a> VisitMut for Hygiene<'a> {
     }
 
     fn visit_mut_var_declarator(&mut self, decl: &mut VarDeclarator) {
-        let old = self.ident_type;
-        self.ident_type = IdentType::Binding;
-        decl.name.visit_mut_with(self);
-        self.ident_type = old;
-
         let old = self.var_kind;
         self.var_kind = None;
         decl.init.visit_mut_with(self);
         self.var_kind = old;
+
+        let old = self.ident_type;
+        self.ident_type = IdentType::Binding;
+        decl.name.visit_mut_with(self);
+        self.ident_type = old;
     }
 }
diff --git a/package.json b/package.json
index c1677404f6..70fe983df2 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
     "name": "@swc/core",
-    "version": "1.2.89",
+    "version": "1.2.90",
     "description": "Super-fast alternative for babel",
     "homepage": "https://swc.rs",
     "main": "./index.js",
diff --git a/wasm/Cargo.toml b/wasm/Cargo.toml
index d984ddd001..4ed362e675 100644
--- a/wasm/Cargo.toml
+++ b/wasm/Cargo.toml
@@ -6,7 +6,7 @@ license = "Apache-2.0 AND MIT"
 name = "wasm"
 publish = false
 repository = "https://github.com/swc-project/swc.git"
-version = "1.2.89"
+version = "1.2.90"
 
 [lib]
 crate-type = ["cdylib"]


Test patch:
diff --git a/ecmascript/minifier/tests/terser/compress/object/property_with_unprintable/output.js b/ecmascript/minifier/tests/terser/compress/object/property_with_unprintable/output.js
index 1200fd350b..cd3b198385 100644
--- a/ecmascript/minifier/tests/terser/compress/object/property_with_unprintable/output.js
+++ b/ecmascript/minifier/tests/terser/compress/object/property_with_unprintable/output.js
@@ -1,10 +1,10 @@
-var foo = {
+var foo1 = {
     "\x00\x01": "foo",
     get "\x00\x01" () {
         return "bar";
     },
-    set "\x00\x01" (foo1){
-        save(foo1);
+    set "\x00\x01" (foo){
+        save(foo);
     },
     *"\x00\x01" () {
         return "foobar";
diff --git a/ecmascript/minifier/tests/terser/compress/object/property_with_unprintable_ascii_only/output.js b/ecmascript/minifier/tests/terser/compress/object/property_with_unprintable_ascii_only/output.js
index 1200fd350b..cd3b198385 100644
--- a/ecmascript/minifier/tests/terser/compress/object/property_with_unprintable_ascii_only/output.js
+++ b/ecmascript/minifier/tests/terser/compress/object/property_with_unprintable_ascii_only/output.js
@@ -1,10 +1,10 @@
-var foo = {
+var foo1 = {
     "\x00\x01": "foo",
     get "\x00\x01" () {
         return "bar";
     },
-    set "\x00\x01" (foo1){
-        save(foo1);
+    set "\x00\x01" (foo){
+        save(foo);
     },
     *"\x00\x01" () {
         return "foobar";
diff --git a/ecmascript/transforms/base/src/hygiene/tests.rs b/ecmascript/transforms/base/src/hygiene/tests.rs
index 734f14e713..e98af538c2 100644
--- a/ecmascript/transforms/base/src/hygiene/tests.rs
+++ b/ecmascript/transforms/base/src/hygiene/tests.rs
@@ -1504,7 +1504,7 @@ fn opt_6() {
 }
 
 #[test]
-fn issue_2211() {
+fn issue_2211_1() {
     test(
         |tester| {
             let mark1 = Mark::fresh(Mark::root());
@@ -1531,14 +1531,54 @@ fn issue_2211() {
             Ok(stmts)
         },
         "
-        var _bar1 = require('./bar');
+        var _bar = require('./bar');
         const makeX = ()=>{
-            const _bar = ()=>(0, _bar1).bar()
+            const _bar1 = ()=>(0, _bar).bar()
             ;
             return {
-                _bar
+                _bar: _bar1
             };
         };
         ",
     );
 }
+
+#[test]
+fn issue_2211_2() {
+    test(
+        |tester| {
+            let mark1 = Mark::fresh(Mark::root());
+            let mark2 = Mark::fresh(Mark::root());
+
+            let stmts = tester
+                .parse_stmts(
+                    "actual1.js",
+                    "
+                    var _bar = require('./bar');
+                    const makeX = ()=>{
+                        const _bar = () => _bar();
+
+                        const alfa = () => _bar();
+                      
+                        return { alfa };
+                    };
+                    ",
+                )?
+                .fold_with(&mut OnceMarker::new(&[(
+                    "_bar",
+                    &[mark1, mark2, mark1, mark2],
+                )]));
+            Ok(stmts)
+        },
+        "
+        var _bar = require('./bar');
+        const makeX = ()=>{
+            const _bar1 = () => _bar();
+
+            const alfa = () => _bar1();
+            
+            return { alfa };
+        };
+        ",
+    );
+}
diff --git a/ecmascript/transforms/compat/tests/es2017_async_to_generator.rs b/ecmascript/transforms/compat/tests/es2017_async_to_generator.rs
index 7d0db5e8ac..46d4331779 100644
--- a/ecmascript/transforms/compat/tests/es2017_async_to_generator.rs
+++ b/ecmascript/transforms/compat/tests/es2017_async_to_generator.rs
@@ -386,20 +386,20 @@ class Class {
                   return _this;
               });
               (function() {
-                  var _this = _this1;
+                  var _this2 = _this1;
                   _this1;
                   (function() {
-                      return _this;
+                      return _this2;
                   });
                   function x() {
-                      var _this = this, _this2 = this;
+                      var _this = this, _this3 = this;
                       this;
                       (function() {
                           _this;
                       });
                       (function() {
                           var _ref = _asyncToGenerator(function*() {
-                              _this2;
+                              _this3;
                           });
                           return function() {
                               return _ref.apply(this, arguments);
diff --git a/ecmascript/transforms/module/tests/fixture/commonjs/issue-2211/input.js b/ecmascript/transforms/module/tests/fixture/commonjs/issue-2211/1/input.js
similarity index 100%
rename from ecmascript/transforms/module/tests/fixture/commonjs/issue-2211/input.js
rename to ecmascript/transforms/module/tests/fixture/commonjs/issue-2211/1/input.js
diff --git a/ecmascript/transforms/module/tests/fixture/commonjs/issue-2211/1/output.js b/ecmascript/transforms/module/tests/fixture/commonjs/issue-2211/1/output.js
new file mode 100644
index 0000000000..618b0d7665
--- /dev/null
+++ b/ecmascript/transforms/module/tests/fixture/commonjs/issue-2211/1/output.js
@@ -0,0 +1,10 @@
+"use strict";
+var _bar = require("./bar");
+const makeX = ()=>{
+    const _bar1 = ()=>(0, _bar).bar()
+    ;
+    return {
+        _bar: _bar1
+    };
+};
+makeX()._bar();
diff --git a/ecmascript/transforms/module/tests/fixture/commonjs/issue-2211/2/input.js b/ecmascript/transforms/module/tests/fixture/commonjs/issue-2211/2/input.js
new file mode 100644
index 0000000000..24992f74cc
--- /dev/null
+++ b/ecmascript/transforms/module/tests/fixture/commonjs/issue-2211/2/input.js
@@ -0,0 +1,9 @@
+import { bar } from "./bar";
+
+const makeX = () => {
+    const _bar = () => bar();
+
+    const alfa = () => _bar();
+
+    return { alfa };
+}
\ No newline at end of file
diff --git a/ecmascript/transforms/module/tests/fixture/commonjs/issue-2211/2/output.js b/ecmascript/transforms/module/tests/fixture/commonjs/issue-2211/2/output.js
new file mode 100644
index 0000000000..59179d489e
--- /dev/null
+++ b/ecmascript/transforms/module/tests/fixture/commonjs/issue-2211/2/output.js
@@ -0,0 +1,11 @@
+"use strict";
+var _bar = require("./bar");
+const makeX = ()=>{
+    const _bar1 = ()=>(0, _bar).bar()
+    ;
+    const alfa = ()=>_bar1()
+    ;
+    return {
+        alfa
+    };
+};
diff --git a/ecmascript/transforms/module/tests/fixture/commonjs/issue-2211/output.js b/ecmascript/transforms/module/tests/fixture/commonjs/issue-2211/output.js
deleted file mode 100644
index c287030346..0000000000
--- a/ecmascript/transforms/module/tests/fixture/commonjs/issue-2211/output.js
+++ /dev/null
@@ -1,10 +0,0 @@
-"use strict";
-var _bar1 = require("./bar");
-const makeX = ()=>{
-    const _bar = ()=>(0, _bar1).bar()
-    ;
-    return {
-        _bar
-    };
-};
-makeX()._bar();
diff --git a/ecmascript/transforms/tests/decorators.rs b/ecmascript/transforms/tests/decorators.rs
index 2bf56c20b6..cd24d9f8e9 100644
--- a/ecmascript/transforms/tests/decorators.rs
+++ b/ecmascript/transforms/tests/decorators.rs
@@ -3171,13 +3171,13 @@ export default class {
 "#,
     r#"
     var _class;
-    let _class1 = ((_class = class _class2 {
+    let _class2 = ((_class = class _class1 {
         bar() {
         }
     }) || _class, _applyDecoratedDescriptor(_class.prototype, "bar", [
         foo
     ], Object.getOwnPropertyDescriptor(_class.prototype, "bar"), _class.prototype), _class);
-    export { _class1 as default };
+    export { _class2 as default };
 "#
 );
 
diff --git a/tests/fixture/issue-1160/output/entry.ts b/tests/fixture/issue-1160/output/entry.ts
index 955ab09e0b..e6c28a2afb 100644
--- a/tests/fixture/issue-1160/output/entry.ts
+++ b/tests/fixture/issue-1160/output/entry.ts
@@ -39,7 +39,7 @@ var MyEnum;
     MyEnum["y"] = "yyy";
 })(MyEnum || (MyEnum = {
 }));
-let Xpto = ((_class = class Xpto1 {
+let Xpto1 = ((_class = class Xpto {
     constructor(){
         _initializerDefineProperty(this, "value", _descriptor, this);
     }
diff --git a/tests/fixture/issue-1278/output/index.ts b/tests/fixture/issue-1278/output/index.ts
index 80335ddf9e..1b12c7f0bd 100644
--- a/tests/fixture/issue-1278/output/index.ts
+++ b/tests/fixture/issue-1278/output/index.ts
@@ -39,7 +39,7 @@ function MyDecorator(klass) {
         console.log(klass);
     };
 }
-let MyClass = ((_class = class MyClass1 {
+let MyClass1 = ((_class = class MyClass {
     constructor(){
         _initializerDefineProperty(this, "prop", _descriptor, this);
     }
@@ -52,4 +52,4 @@ let MyClass = ((_class = class MyClass1 {
     writable: true,
     initializer: void 0
 }), _class);
-console.log(new MyClass());
+console.log(new MyClass1());
diff --git a/tests/fixture/issue-1362/case1/output/index.ts b/tests/fixture/issue-1362/case1/output/index.ts
index 0d8bf2028c..e796510db6 100644
--- a/tests/fixture/issue-1362/case1/output/index.ts
+++ b/tests/fixture/issue-1362/case1/output/index.ts
@@ -34,7 +34,7 @@ var _class, _dec, _dec1, _dec2, _dec3, _dec4, _dec5, _dec6;
 var _dec7 = typeof Reflect !== "undefined" && typeof Reflect.metadata === "function" && Reflect.metadata("design:paramtypes", [
     typeof _appService.AppService === "undefined" ? Object : _appService.AppService
 ]), _dec8 = typeof Reflect !== "undefined" && typeof Reflect.metadata === "function" && Reflect.metadata("design:type", Function), _dec9 = (0, _common).Controller();
-let AppController = _class = _dec9(_class = _dec8(_class = _dec7(((_class = class AppController1 {
+let AppController1 = _class = _dec9(_class = _dec8(_class = _dec7(((_class = class AppController {
     async getHello() {
         const result = await this.appService.getHello();
         return result;
@@ -60,4 +60,4 @@ let AppController = _class = _dec9(_class = _dec8(_class = _dec7(((_class = clas
     _dec5,
     _dec6
 ], Object.getOwnPropertyDescriptor(_class.prototype, "create"), _class.prototype), _class)) || _class) || _class) || _class;
-exports.AppController = AppController;
+exports.AppController = AppController1;
diff --git a/tests/fixture/issue-1456/case1/output/index.ts b/tests/fixture/issue-1456/case1/output/index.ts
index 1cb7d827ca..87559c49a0 100644
--- a/tests/fixture/issue-1456/case1/output/index.ts
+++ b/tests/fixture/issue-1456/case1/output/index.ts
@@ -5,8 +5,8 @@ var _dec = typeof Reflect !== "undefined" && typeof Reflect.metadata === "functi
 ]), _dec1 = typeof Reflect !== "undefined" && typeof Reflect.metadata === "function" && Reflect.metadata("design:type", Function), _dec2 = function(target, key) {
     return Inject()(target, undefined, 0);
 };
-let MyClass1 = _class = _dec2(_class = _dec1(_class = _dec((_class = // not work
-class MyClass11 {
+let MyClass11 = _class = _dec2(_class = _dec1(_class = _dec((_class = // not work
+class MyClass1 {
     constructor(param1){
         this.param1 = param1;
     }
@@ -16,7 +16,7 @@ var _dec3 = typeof Reflect !== "undefined" && typeof Reflect.metadata === "funct
 ]), _dec4 = typeof Reflect !== "undefined" && typeof Reflect.metadata === "function" && Reflect.metadata("design:type", Function), _dec5 = function(target, key) {
     return Inject()(target, undefined, 0);
 };
-let MyClass2 = _class1 = _dec5(_class1 = _dec4(_class1 = _dec3((_class1 = class MyClass21 {
+let MyClass21 = _class1 = _dec5(_class1 = _dec4(_class1 = _dec3((_class1 = class MyClass2 {
     constructor(param1){
         this.param1 = param1;
     }
@@ -26,7 +26,7 @@ var _dec6 = typeof Reflect !== "undefined" && typeof Reflect.metadata === "funct
 ]), _dec7 = typeof Reflect !== "undefined" && typeof Reflect.metadata === "function" && Reflect.metadata("design:type", Function), _dec8 = function(target, key) {
     return Inject()(target, undefined, 0);
 };
-let MyClass3 = _class2 = _dec8(_class2 = _dec7(_class2 = _dec6((_class2 = class MyClass31 {
+let MyClass31 = _class2 = _dec8(_class2 = _dec7(_class2 = _dec6((_class2 = class MyClass3 {
     constructor(param1){
         this.param1 = param1;
     }
@@ -36,7 +36,7 @@ var _dec9 = typeof Reflect !== "undefined" && typeof Reflect.metadata === "funct
 ]), _dec10 = typeof Reflect !== "undefined" && typeof Reflect.metadata === "function" && Reflect.metadata("design:type", Function), _dec11 = function(target, key) {
     return Inject()(target, undefined, 0);
 };
-let MyClass4 = _class3 = _dec11(_class3 = _dec10(_class3 = _dec9((_class3 = class MyClass41 {
+let MyClass41 = _class3 = _dec11(_class3 = _dec10(_class3 = _dec9((_class3 = class MyClass4 {
     constructor(param1){
         this.param1 = param1;
     }
@@ -46,7 +46,7 @@ var _dec12 = typeof Reflect !== "undefined" && typeof Reflect.metadata === "func
 ]), _dec13 = typeof Reflect !== "undefined" && typeof Reflect.metadata === "function" && Reflect.metadata("design:type", Function), _dec14 = function(target, key) {
     return Inject()(target, undefined, 0);
 };
-let MyClass5 = _class4 = _dec14(_class4 = _dec13(_class4 = _dec12((_class4 = class MyClass51 {
+let MyClass51 = _class4 = _dec14(_class4 = _dec13(_class4 = _dec12((_class4 = class MyClass5 {
     constructor(param1){
         this.param1 = param1;
     }
@@ -59,7 +59,7 @@ var _dec15 = typeof Reflect !== "undefined" && typeof Reflect.metadata === "func
 }, _dec18 = function(target, key) {
     return Inject()(target, undefined, 0);
 };
-let MyClass6 = _class5 = _dec18(_class5 = _dec17(_class5 = _dec16(_class5 = _dec15((_class5 = class MyClass61 {
+let MyClass61 = _class5 = _dec18(_class5 = _dec17(_class5 = _dec16(_class5 = _dec15((_class5 = class MyClass6 {
     constructor(param1, param2){
         this.param1 = param1;
         this.param2 = param2;
diff --git a/tests/fixture/issue-1456/case2/output/index.ts b/tests/fixture/issue-1456/case2/output/index.ts
index ef010f8dcb..ad2770437c 100644
--- a/tests/fixture/issue-1456/case2/output/index.ts
+++ b/tests/fixture/issue-1456/case2/output/index.ts
@@ -5,8 +5,8 @@ var _dec = typeof Reflect !== "undefined" && typeof Reflect.metadata === "functi
 ]), _dec1 = typeof Reflect !== "undefined" && typeof Reflect.metadata === "function" && Reflect.metadata("design:type", Function), _dec2 = function(target, key) {
     return Inject()(target, undefined, 0);
 };
-let MyClass1 = _class = _dec2(_class = _dec1(_class = _dec((_class = // work
-class MyClass11 {
+let MyClass11 = _class = _dec2(_class = _dec1(_class = _dec((_class = // work
+class MyClass1 {
     constructor(param1){
     }
 }) || _class) || _class) || _class) || _class;
@@ -18,7 +18,7 @@ var _dec3 = typeof Reflect !== "undefined" && typeof Reflect.metadata === "funct
 }, _dec6 = function(target, key) {
     return Inject()(target, undefined, 0);
 };
-let MyClass2 = _class1 = _dec6(_class1 = _dec5(_class1 = _dec4(_class1 = _dec3((_class1 = class MyClass21 {
+let MyClass21 = _class1 = _dec6(_class1 = _dec5(_class1 = _dec4(_class1 = _dec3((_class1 = class MyClass2 {
     constructor(param1, param2){
         this.param1 = param1;
     }
@@ -31,7 +31,7 @@ var _dec7 = typeof Reflect !== "undefined" && typeof Reflect.metadata === "funct
 }, _dec10 = function(target, key) {
     return Inject()(target, undefined, 0);
 };
-let MyClass3 = _class2 = _dec10(_class2 = _dec9(_class2 = _dec8(_class2 = _dec7((_class2 = class MyClass31 {
+let MyClass31 = _class2 = _dec10(_class2 = _dec9(_class2 = _dec8(_class2 = _dec7((_class2 = class MyClass3 {
     constructor(param1, param2){
         this.param2 = param2;
     }
diff --git a/tests/fixture/issue-1507/output/index.ts b/tests/fixture/issue-1507/output/index.ts
index 0712f36302..f8da7d6ec9 100644
--- a/tests/fixture/issue-1507/output/index.ts
+++ b/tests/fixture/issue-1507/output/index.ts
@@ -1,5 +1,6 @@
 import { Entity, BaseEntity } from 'typeorm';
 var _class;
 var _dec = Entity();
-export let Location = _class = _dec((_class = class Location extends BaseEntity {
+let Location1 = _class = _dec((_class = class Location extends BaseEntity {
 }) || _class) || _class;
+export { Location1 as Location };