Repository: babel/babel (TypeScript)

Issue:
[Bug]: decorators are broken and when applied, they override the preceding value.
### 💻

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

### How are you using Babel?

@babel/cli

### Input code

I've created a test repo with a basic example [here](https://github.com/amirmohsen/decorators-broken). You can also see it below:
```js
function decorateA(target) {
  return class extends target {
    a() {
      console.log("a");
    }
  };
}

function decorateB(target) {
  return class extends target {
    b() {
      console.log("b");
    }
  };
}

@decorateB
@decorateA
class Target {}

const target = new Target();

target.b();

target.a(); // This throws an error: TypeError: target.a is not a function
```
I only checked class decorators. This bug may exist for function decorators as well but I haven't checked.

### Configuration file name

_No response_

### Configuration

```js
module.exports = (api) => {
  api.cache(true);
  return {
    presets: [
      [
        "@babel/preset-env",
        {
          modules: false,
          targets: {
            node: 20,
          },
        },
      ],
    ],
    plugins: [["@babel/plugin-proposal-decorators", { version: "2023-05" }]],
  };
};
```

### Current and expected behavior

Instead of passing the result of one decorator to the next, the original value of the `Target` class gets passed to each decorator and as a result, the last applied decorator result overrides the preceding ones.

### Environment

Babel package versions:
```json
"@babel/cli": "^7.23.4",
"@babel/core": "^7.23.7",
"@babel/plugin-proposal-decorators": "^7.23.7",
"@babel/preset-env": "^7.23.7",
```
Node: `20.9.0`
NPM: `10.1.0`
Yarn: `1.22.19`
Environment: `Ubuntu 20.04.4 LTS (WSL2 on Windows)`

### Possible solution

_No response_

### Additional context

This is a recent bug because I have a project that is using Babel version `7.23.2` and it's working fine. However, the bug doesn't seem to originate in Babel itself because simply reverting to an older version of the packages, doesn't fix anything. I think the problem might originate in a sub-dependency. I haven't had time to investigate further though.


Hints:
Hey @amirmohsen! 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.
Thank you for your report!
This is a regression for us, fixed in https://github.com/babel/babel/pull/16199.

Patch:
diff --git a/packages/babel-helpers/src/helpers-generated.ts b/packages/babel-helpers/src/helpers-generated.ts
--- a/packages/babel-helpers/src/helpers-generated.ts
+++ b/packages/babel-helpers/src/helpers-generated.ts
@@ -43,10 +43,10 @@ export default Object.freeze({
     "7.21.0",
     'import checkInRHS from"checkInRHS";import setFunctionName from"setFunctionName";import toPropertyKey from"toPropertyKey";function applyDecs2301Factory(){function createAddInitializerMethod(e,t){return function(r){!function(e,t){if(e.v)throw new Error("attempted to call addInitializer after decoration was finished")}(t),assertCallable(r,"An initializer"),e.push(r)}}function assertInstanceIfPrivate(e,t){if(!e(t))throw new TypeError("Attempted to access private element on non-instance")}function memberDec(e,t,r,n,a,i,s,o,c){var u;switch(a){case 1:u="accessor";break;case 2:u="method";break;case 3:u="getter";break;case 4:u="setter";break;default:u="field"}var l,f,p={kind:u,name:s?"#"+t:toPropertyKey(t),static:i,private:s},d={v:!1};if(0!==a&&(p.addInitializer=createAddInitializerMethod(n,d)),s||0!==a&&2!==a)if(2===a)l=function(e){return assertInstanceIfPrivate(c,e),r.value};else{var h=0===a||1===a;(h||3===a)&&(l=s?function(e){return assertInstanceIfPrivate(c,e),r.get.call(e)}:function(e){return r.get.call(e)}),(h||4===a)&&(f=s?function(e,t){assertInstanceIfPrivate(c,e),r.set.call(e,t)}:function(e,t){r.set.call(e,t)})}else l=function(e){return e[t]},0===a&&(f=function(e,r){e[t]=r});var v=s?c.bind():function(e){return t in e};p.access=l&&f?{get:l,set:f,has:v}:l?{get:l,has:v}:{set:f,has:v};try{return e(o,p)}finally{d.v=!0}}function assertCallable(e,t){if("function"!=typeof e)throw new TypeError(t+" must be a function")}function assertValidReturnValue(e,t){var r=typeof t;if(1===e){if("object"!==r||null===t)throw new TypeError("accessor decorators must return an object with get, set, or init properties or void 0");void 0!==t.get&&assertCallable(t.get,"accessor.get"),void 0!==t.set&&assertCallable(t.set,"accessor.set"),void 0!==t.init&&assertCallable(t.init,"accessor.init")}else if("function"!==r)throw new TypeError((0===e?"field":10===e?"class":"method")+" decorators must return a function or void 0")}function curryThis2(e){return function(t){e(this,t)}}function applyMemberDec(e,t,r,n,a,i,s,o,c){var u,l,f,p,d,h,v,y,g=r[0];if(s?(0===a||1===a?(u={get:(d=r[3],function(){return d(this)}),set:curryThis2(r[4])},f="get"):3===a?(u={get:r[3]},f="get"):4===a?(u={set:r[3]},f="set"):u={value:r[3]},0!==a&&(1===a&&setFunctionName(u.set,"#"+n,"set"),setFunctionName(u[f||"value"],"#"+n,f))):0!==a&&(u=Object.getOwnPropertyDescriptor(t,n)),1===a?p={get:u.get,set:u.set}:2===a?p=u.value:3===a?p=u.get:4===a&&(p=u.set),"function"==typeof g)void 0!==(h=memberDec(g,n,u,o,a,i,s,p,c))&&(assertValidReturnValue(a,h),0===a?l=h:1===a?(l=h.init,v=h.get||p.get,y=h.set||p.set,p={get:v,set:y}):p=h);else for(var m=g.length-1;m>=0;m--){var b;void 0!==(h=memberDec(g[m],n,u,o,a,i,s,p,c))&&(assertValidReturnValue(a,h),0===a?b=h:1===a?(b=h.init,v=h.get||p.get,y=h.set||p.set,p={get:v,set:y}):p=h,void 0!==b&&(void 0===l?l=b:"function"==typeof l?l=[l,b]:l.push(b)))}if(0===a||1===a){if(void 0===l)l=function(e,t){return t};else if("function"!=typeof l){var I=l;l=function(e,t){for(var r=t,n=0;n<I.length;n++)r=I[n].call(e,r);return r}}else{var w=l;l=function(e,t){return w.call(e,t)}}e.push(l)}0!==a&&(1===a?(u.get=p.get,u.set=p.set):2===a?u.value=p:3===a?u.get=p:4===a&&(u.set=p),s?1===a?(e.push((function(e,t){return p.get.call(e,t)})),e.push((function(e,t){return p.set.call(e,t)}))):2===a?e.push(p):e.push((function(e,t){return p.call(e,t)})):Object.defineProperty(t,n,u))}function applyMemberDecs(e,t,r){for(var n,a,i,s=[],o=new Map,c=new Map,u=0;u<t.length;u++){var l=t[u];if(Array.isArray(l)){var f,p,d=l[1],h=l[2],v=l.length>3,y=d>=5,g=r;if(y?(f=e,0!=(d-=5)&&(p=a=a||[]),v&&!i&&(i=function(t){return checkInRHS(t)===e}),g=i):(f=e.prototype,0!==d&&(p=n=n||[])),0!==d&&!v){var m=y?c:o,b=m.get(h)||0;if(!0===b||3===b&&4!==d||4===b&&3!==d)throw new Error("Attempted to decorate a public method/accessor that has the same name as a previously decorated public method/accessor. This is not currently supported by the decorators plugin. Property name was: "+h);!b&&d>2?m.set(h,d):m.set(h,!0)}applyMemberDec(s,f,l,h,d,y,v,p,g)}}return pushInitializers(s,n),pushInitializers(s,a),s}function pushInitializers(e,t){t&&e.push((function(e){for(var r=0;r<t.length;r++)t[r].call(e);return e}))}return function(e,t,r,n){return{e:applyMemberDecs(e,t,n),get c(){return function(e,t){if(t.length>0){for(var r=[],n=e,a=e.name,i=t.length-1;i>=0;i--){var s={v:!1};try{var o=t[i](n,{kind:"class",name:a,addInitializer:createAddInitializerMethod(r,s)})}finally{s.v=!0}void 0!==o&&(assertValidReturnValue(10,o),n=o)}return[n,function(){for(var e=0;e<r.length;e++)r[e].call(n)}]}}(e,r)}}}}export default function applyDecs2301(e,t,r,n){return(applyDecs2301=applyDecs2301Factory())(e,t,r,n)}',
   ),
-  // size: 3267, gzip size: 1611
+  // size: 3275, gzip size: 1615
   applyDecs2305: helper(
     "7.21.0",
-    'import checkInRHS from"checkInRHS";import setFunctionName from"setFunctionName";import toPropertyKey from"toPropertyKey";export default function applyDecs2305(e,t,r,n,o,a){function i(e,t,r){return function(n,o){return r&&r(n),e[t].call(n,o)}}function c(e,t){for(var r=0;r<e.length;r++)e[r].call(t);return t}function s(e,t,r,n){if("function"!=typeof e&&(n||void 0!==e))throw new TypeError(t+" must "+(r||"be")+" a function"+(n?"":" or undefined"));return e}function applyDec(e,t,r,n,o,a,c,u,l,f,p,d,h){function m(e){if(!h(e))throw new TypeError("Attempted to access private element on non-instance")}var y,v,g=t[0],b=t[3],w=!u;if(!w){r||Array.isArray(g)||(g=[g]);var S={},A=[],P=3===o?"get":4===o||d?"set":"value";f?(p||d?S={get:setFunctionName((function(){return b(this)}),n,"get"),set:function(e){t[4](this,e)}}:S[P]=b,p||setFunctionName(S[P],n,2===o?"":P)):p||(S=Object.getOwnPropertyDescriptor(e,n))}for(var j=g.length-1;j>=0;j-=r?2:1){var D=g[j],E=r?g[j-1]:void 0,I={},O={kind:["field","accessor","method","getter","setter","class"][o],name:n,metadata:a,addInitializer:function(e,t){if(e.v)throw new Error("attempted to call addInitializer after decoration was finished");s(t,"An initializer","be",!0),c.push(t)}.bind(null,I)};try{if(w)v=D.call(E,e,O);else{var k,F;O.static=l,O.private=f,f||!p&&2!==o?2===o?k=function(e){return m(e),S.value}:((o<2||3===o)&&(k=i(S,"get",f&&m)),(o<2||4===o)&&(F=i(S,"set",f&&m))):(k=function(e){return e[n]},p&&(F=function(e,t){e[n]=t}));var N=O.access={has:f?h.bind():function(e){return n in e}};if(k&&(N.get=k),F&&(N.set=F),v=D.call(E,d?{get:S.get,set:S.set}:S[P],O),d){if("object"==typeof v&&v)(y=s(v.get,"accessor.get"))&&(S.get=y),(y=s(v.set,"accessor.set"))&&(S.set=y),(y=s(v.init,"accessor.init"))&&A.push(y);else if(void 0!==v)throw new TypeError("accessor decorators must return an object with get, set, or init properties or void 0")}else s(v,(p?"field":"method")+" decorators","return")&&(p?A.push(v):S[P]=v)}}finally{I.v=!0}}return(p||d)&&u.push((function(e,t){for(var r=A.length-1;r>=0;r--)t=A[r].call(e,t);return t})),p||w||(f?d?u.push(i(S,"get"),i(S,"set")):u.push(2===o?S[P]:i.call.bind(S[P])):Object.defineProperty(e,n,S)),v}function u(e,t){return Object.defineProperty(e,Symbol.metadata||Symbol.for("Symbol.metadata"),{configurable:!0,enumerable:!0,value:t})}if(arguments.length>=6)var l=a[Symbol.metadata||Symbol.for("Symbol.metadata")];var f=Object.create(null==l?null:l),p=function(e,t,r,n){var o,a,i=[],s=function(t){return checkInRHS(t)===e},u=new Map;function l(e){e&&i.push(c.bind(null,e))}for(var f=0;f<t.length;f++){var p=t[f];if(Array.isArray(p)){var d=p[1],h=p[2],m=p.length>3,y=16&d,v=!!(8&d),g=0==(d&=7),b=h+"/"+v;if(!g&&!m){var w=u.get(b);if(!0===w||3===w&&4!==d||4===w&&3!==d)throw new Error("Attempted to decorate a public method/accessor that has the same name as a previously decorated public method/accessor. This is not currently supported by the decorators plugin. Property name was: "+h);u.set(b,!(d>2)||d)}applyDec(v?e:e.prototype,p,y,m?"#"+h:toPropertyKey(h),d,n,v?a=a||[]:o=o||[],i,v,m,g,1===d,v&&m?s:r)}}return l(o),l(a),i}(e,t,o,f);return r.length||u(e,f),{e:p,get c(){var t=[];return r.length&&[u(s(applyDec(e,[r],n,e.name,5,f,t),"class decorators","return")||e,f),c.bind(null,t,e)]}}}',
+    'import checkInRHS from"checkInRHS";import setFunctionName from"setFunctionName";import toPropertyKey from"toPropertyKey";export default function applyDecs2305(e,t,r,n,o,a){function i(e,t,r){return function(n,o){return r&&r(n),e[t].call(n,o)}}function c(e,t){for(var r=0;r<e.length;r++)e[r].call(t);return t}function s(e,t,r,n){if("function"!=typeof e&&(n||void 0!==e))throw new TypeError(t+" must "+(r||"be")+" a function"+(n?"":" or undefined"));return e}function applyDec(e,t,r,n,o,a,c,u,l,f,p,d,h){function m(e){if(!h(e))throw new TypeError("Attempted to access private element on non-instance")}var y,v=t[0],g=t[3],b=!u;if(!b){r||Array.isArray(v)||(v=[v]);var w={},S=[],A=3===o?"get":4===o||d?"set":"value";f?(p||d?w={get:setFunctionName((function(){return g(this)}),n,"get"),set:function(e){t[4](this,e)}}:w[A]=g,p||setFunctionName(w[A],n,2===o?"":A)):p||(w=Object.getOwnPropertyDescriptor(e,n))}for(var P=e,j=v.length-1;j>=0;j-=r?2:1){var D=v[j],E=r?v[j-1]:void 0,I={},O={kind:["field","accessor","method","getter","setter","class"][o],name:n,metadata:a,addInitializer:function(e,t){if(e.v)throw new Error("attempted to call addInitializer after decoration was finished");s(t,"An initializer","be",!0),c.push(t)}.bind(null,I)};try{if(b)(y=s(D.call(E,P,O),"class decorators","return"))&&(P=y);else{var k,F;O.static=l,O.private=f,f||!p&&2!==o?2===o?k=function(e){return m(e),w.value}:((o<2||3===o)&&(k=i(w,"get",f&&m)),(o<2||4===o)&&(F=i(w,"set",f&&m))):(k=function(e){return e[n]},p&&(F=function(e,t){e[n]=t}));var N=O.access={has:f?h.bind():function(e){return n in e}};if(k&&(N.get=k),F&&(N.set=F),P=D.call(E,d?{get:w.get,set:w.set}:w[A],O),d){if("object"==typeof P&&P)(y=s(P.get,"accessor.get"))&&(w.get=y),(y=s(P.set,"accessor.set"))&&(w.set=y),(y=s(P.init,"accessor.init"))&&S.push(y);else if(void 0!==P)throw new TypeError("accessor decorators must return an object with get, set, or init properties or void 0")}else s(P,(p?"field":"method")+" decorators","return")&&(p?S.push(P):w[A]=P)}}finally{I.v=!0}}return(p||d)&&u.push((function(e,t){for(var r=S.length-1;r>=0;r--)t=S[r].call(e,t);return t})),p||b||(f?d?u.push(i(w,"get"),i(w,"set")):u.push(2===o?w[A]:i.call.bind(w[A])):Object.defineProperty(e,n,w)),P}function u(e,t){return Object.defineProperty(e,Symbol.metadata||Symbol.for("Symbol.metadata"),{configurable:!0,enumerable:!0,value:t})}if(arguments.length>=6)var l=a[Symbol.metadata||Symbol.for("Symbol.metadata")];var f=Object.create(null==l?null:l),p=function(e,t,r,n){var o,a,i=[],s=function(t){return checkInRHS(t)===e},u=new Map;function l(e){e&&i.push(c.bind(null,e))}for(var f=0;f<t.length;f++){var p=t[f];if(Array.isArray(p)){var d=p[1],h=p[2],m=p.length>3,y=16&d,v=!!(8&d),g=0==(d&=7),b=h+"/"+v;if(!g&&!m){var w=u.get(b);if(!0===w||3===w&&4!==d||4===w&&3!==d)throw new Error("Attempted to decorate a public method/accessor that has the same name as a previously decorated public method/accessor. This is not currently supported by the decorators plugin. Property name was: "+h);u.set(b,!(d>2)||d)}applyDec(v?e:e.prototype,p,y,m?"#"+h:toPropertyKey(h),d,n,v?a=a||[]:o=o||[],i,v,m,g,1===d,v&&m?s:r)}}return l(o),l(a),i}(e,t,o,f);return r.length||u(e,f),{e:p,get c(){var t=[];return r.length&&[u(applyDec(e,[r],n,e.name,5,f,t),f),c.bind(null,t,e)]}}}',
   ),
   // size: 544, gzip size: 300
   asyncGeneratorDelegate: helper(
diff --git a/packages/babel-helpers/src/helpers/applyDecs2305.ts b/packages/babel-helpers/src/helpers/applyDecs2305.ts
--- a/packages/babel-helpers/src/helpers/applyDecs2305.ts
+++ b/packages/babel-helpers/src/helpers/applyDecs2305.ts
@@ -306,7 +306,7 @@ export default /* @no-mangle */ function applyDecs2305(
       }
     }
 
-    var newValue;
+    var newValue = Class;
 
     for (var i = decs.length - 1; i >= 0; i -= decoratorsHaveThis ? 2 : 1) {
       var dec = (decs as Function[])[i],
@@ -336,7 +336,15 @@ export default /* @no-mangle */ function applyDecs2305(
 
       try {
         if (isClass) {
-          newValue = dec.call(decThis, Class, ctx);
+          if (
+            (_ = assertCallable(
+              dec.call(decThis, newValue, ctx),
+              "class decorators",
+              "return",
+            ))
+          ) {
+            newValue = _;
+          }
         } else {
           ctx.static = isStatic;
           ctx.private = isPrivate;
@@ -563,19 +571,15 @@ export default /* @no-mangle */ function applyDecs2305(
       return (
         classDecs.length && [
           defineMetadata(
-            assertCallable(
-              applyDec(
-                targetClass,
-                [classDecs],
-                classDecsHaveThis,
-                targetClass.name,
-                PROP_KIND.CLASS,
-                metadata,
-                initializers,
-              ),
-              "class decorators",
-              "return",
-            ) || targetClass,
+            applyDec(
+              targetClass,
+              [classDecs],
+              classDecsHaveThis,
+              targetClass.name,
+              PROP_KIND.CLASS,
+              metadata,
+              initializers,
+            ),
             metadata,
           ),
           runInitializers.bind(null, initializers, targetClass),


Test patch:
diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2023-05-classes--to-es2015/decorator-access-modified-classes/exec.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2023-05-classes--to-es2015/decorator-access-modified-classes/exec.js
new file mode 100644
--- /dev/null
+++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2023-05-classes--to-es2015/decorator-access-modified-classes/exec.js
@@ -0,0 +1,23 @@
+function decorateA(target) {
+  return class extends target {
+    a() {
+      return "a";
+    }
+  };
+}
+
+function decorateB(target) {
+  return class extends target {
+    b() {
+      return "b";
+    }
+  };
+}
+
+@decorateB
+@decorateA
+class Target {}
+
+const target = new Target();
+expect(target.a()).toBe("a");
+expect(target.b()).toBe("b");
diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2023-05-classes/decorator-access-modified-classes/exec.js b/packages/babel-plugin-proposal-decorators/test/fixtures/2023-05-classes/decorator-access-modified-classes/exec.js
new file mode 100644
--- /dev/null
+++ b/packages/babel-plugin-proposal-decorators/test/fixtures/2023-05-classes/decorator-access-modified-classes/exec.js
@@ -0,0 +1,23 @@
+function decorateA(target) {
+  return class extends target {
+    a() {
+      return "a";
+    }
+  };
+}
+
+function decorateB(target) {
+  return class extends target {
+    b() {
+      return "b";
+    }
+  };
+}
+
+@decorateB
+@decorateA
+class Target {}
+
+const target = new Target();
+expect(target.a()).toBe("a");
+expect(target.b()).toBe("b");
diff --git a/packages/babel-plugin-proposal-decorators/test/fixtures/2023-05-classes--to-es2015/ctx/options.json b/packages/babel-plugin-proposal-decorators/test/fixtures/2023-05-classes/decorator-access-modified-classes/options.json
similarity index 100%
rename from packages/babel-plugin-proposal-decorators/test/fixtures/2023-05-classes--to-es2015/ctx/options.json
rename to packages/babel-plugin-proposal-decorators/test/fixtures/2023-05-classes/decorator-access-modified-classes/options.json