Repository: swc-project/swc (rust)

Issue:
Arrow functions inside of getters/setters on object literals use the wrong `this`
### Describe the bug

Arrow functions inside of getters use the `this` context of the surrounding context, rather than of the getter.

### Input code

```typescript
const myObj = {
  get foo(){
    return () => this;
  },
};

const fn = myObj.foo;

// should be true
console.log(fn() === myObj);
```


### Config

```json
{
  "jsc": {
    "parser": {
      "syntax": "ecmascript",
      "jsx": false
    },
    "target": "es5",
    "loose": false,
    "minify": {
      "compress": false,
      "mangle": false
    },
  },
  "module": {
    "type": "es6"
  },
  "minify": false,
  "isModule": false
}
```


### Playground link (or link to the minimal reproduction)

https://play.swc.rs/?version=1.5.16&code=H4sIAAAAAAAAAy2MQQ6EIBAE7yT8oY%2BQbPQBhv3C%2FkEd1A3LJDAcNsa%2Fi%2BhterqrJo5Z8Pt%2Fxi8cdq2AhQSe2diWgERSUoSxcG%2FIuuXh%2Bh8vrY56aTU1hY%2BVb56uwq3oe%2BSVS5gxEiQVurccqAu8GB8vpXsoO5x3oIfBiwAAAA%3D%3D&config=H4sIAAAAAAAAA2WPSw7CMAxE95wi8potLLgDh7CCW6XKT3aQiKrenTSfAmJj2TPPHnk9KQWLaLiptbRliMhCfMxFkewTvooCpB2KZhMTnIe7yG5NaIWqtDUHEvJMqW7JpeNgQxAaeNec8WbK34E6uMgk8gvuKPrZ0n9cLeDC41nd%2FknKkVr%2BFT7QSDsug5H72Gx3tzcE4cPeFgEAAA%3D%3D

### SWC Info output

_No response_

### Expected behavior

This is bound inside of the getter

```js
var myObj = {
    get foo () {
        var _this = this;
        return function() {
            return _this;
        };
    }
};

// ...
```

### Actual behavior

This is bound outside of the getter

```js
var _this = this;
var myObj = {
    get foo () {
        return function() {
            return _this;
        };
    }
};

// ...
```

### Version

1.5.16 (repros on every version I tried, including all of 1.5.x)

### Additional context

_No response_

Pull request description:
fix(es/es2015): Fix injection location of `this` for getter/setter properties
**Description:**


**Related issue:**

 - Closes #8992

Patch:
diff --git a/crates/swc_ecma_compat_es2015/src/arrow.rs b/crates/swc_ecma_compat_es2015/src/arrow.rs
index 6a36fda8c1..8337405b67 100644
--- a/crates/swc_ecma_compat_es2015/src/arrow.rs
+++ b/crates/swc_ecma_compat_es2015/src/arrow.rs
@@ -181,6 +181,22 @@ impl VisitMut for Arrow {
         }
     }
 
+    fn visit_mut_getter_prop(&mut self, f: &mut GetterProp) {
+        f.key.visit_mut_with(self);
+
+        if let Some(body) = &mut f.body {
+            let old_rep = self.hoister.take();
+
+            body.visit_mut_with(self);
+
+            let decl = mem::replace(&mut self.hoister, old_rep).to_stmt();
+
+            if let Some(stmt) = decl {
+                prepend_stmt(&mut body.stmts, stmt);
+            }
+        }
+    }
+
     fn visit_mut_module_items(&mut self, stmts: &mut Vec<ModuleItem>) {
         stmts.visit_mut_children_with(self);
 
@@ -200,6 +216,23 @@ impl VisitMut for Arrow {
             prepend_stmt(&mut script.body, stmt);
         }
     }
+
+    fn visit_mut_setter_prop(&mut self, f: &mut SetterProp) {
+        f.key.visit_mut_with(self);
+        f.param.visit_mut_with(self);
+
+        if let Some(body) = &mut f.body {
+            let old_rep = self.hoister.take();
+
+            body.visit_mut_with(self);
+
+            let decl = mem::replace(&mut self.hoister, old_rep).to_stmt();
+
+            if let Some(stmt) = decl {
+                prepend_stmt(&mut body.stmts, stmt);
+            }
+        }
+    }
 }
 
 impl InjectVars for Arrow {


Test patch:
diff --git a/crates/swc/tests/fixture/issues-8xxx/8992/input/.swcrc b/crates/swc/tests/fixture/issues-8xxx/8992/input/.swcrc
new file mode 100644
index 0000000000..5d09848c1f
--- /dev/null
+++ b/crates/swc/tests/fixture/issues-8xxx/8992/input/.swcrc
@@ -0,0 +1,19 @@
+{
+    "jsc": {
+        "parser": {
+            "syntax": "ecmascript",
+            "jsx": false
+        },
+        "target": "es5",
+        "loose": false,
+        "minify": {
+            "compress": false,
+            "mangle": false
+        }
+    },
+    "module": {
+        "type": "es6"
+    },
+    "minify": false,
+    "isModule": false
+}
\ No newline at end of file
diff --git a/crates/swc/tests/fixture/issues-8xxx/8992/input/1.js b/crates/swc/tests/fixture/issues-8xxx/8992/input/1.js
new file mode 100644
index 0000000000..6c04f245ab
--- /dev/null
+++ b/crates/swc/tests/fixture/issues-8xxx/8992/input/1.js
@@ -0,0 +1,10 @@
+const myObj = {
+    get foo() {
+        return () => this;
+    },
+};
+
+const fn = myObj.foo;
+
+// should be true
+console.log(fn() === myObj);
\ No newline at end of file
diff --git a/crates/swc/tests/fixture/issues-8xxx/8992/input/2.js b/crates/swc/tests/fixture/issues-8xxx/8992/input/2.js
new file mode 100644
index 0000000000..3f28043c1a
--- /dev/null
+++ b/crates/swc/tests/fixture/issues-8xxx/8992/input/2.js
@@ -0,0 +1,13 @@
+const o1 = {
+    x: "a",
+    foo() {
+        const o2 = {
+            get [(() => this.x)()]() {
+                return 1;
+            },
+        };
+        console.log(o2.a === 1);
+    },
+};
+
+o1.foo();
\ No newline at end of file
diff --git a/crates/swc/tests/fixture/issues-8xxx/8992/output/1.js b/crates/swc/tests/fixture/issues-8xxx/8992/output/1.js
new file mode 100644
index 0000000000..ac5040fa21
--- /dev/null
+++ b/crates/swc/tests/fixture/issues-8xxx/8992/output/1.js
@@ -0,0 +1,10 @@
+var myObj = {
+    get foo () {
+        var _this = this;
+        return function() {
+            return _this;
+        };
+    }
+};
+var fn = myObj.foo;
+console.log(fn() === myObj);
diff --git a/crates/swc/tests/fixture/issues-8xxx/8992/output/2.js b/crates/swc/tests/fixture/issues-8xxx/8992/output/2.js
new file mode 100644
index 0000000000..344af14e5d
--- /dev/null
+++ b/crates/swc/tests/fixture/issues-8xxx/8992/output/2.js
@@ -0,0 +1,19 @@
+var _define_enumerable_properties = require("@swc/helpers/_/_define_enumerable_properties");
+var o1 = {
+    x: "a",
+    foo: function foo() {
+        var _this = this;
+        var _obj, _mutatorMap = {};
+        var o2 = (_obj = {}, _mutatorMap[function() {
+            return _this.x;
+        }()] = _mutatorMap[function() {
+            return _this.x;
+        }()] || {}, _mutatorMap[function() {
+            return _this.x;
+        }()].get = function() {
+            return 1;
+        }, _define_enumerable_properties._(_obj, _mutatorMap), _obj);
+        console.log(o2.a === 1);
+    }
+};
+o1.foo();