From 74c337bc5f2584c50e7e85544fe6c5082f79430b Mon Sep 17 00:00:00 2001
From: John Lusty <54030459+jlusty@users.noreply.github.com>
Date: Wed, 20 Apr 2022 01:47:47 +0100
Subject: [PATCH 1/4] Fix handling of prologue statements when there are
 parameter property declarations If there is a prologue (and no super) in a
 constructor, the prologue won't be skipped when calculating the parameter
 properties, leading to the prologue being included twice

---
 src/compiler/transformers/classFields.ts      | 15 +++---
 ...ameterPropertiesAndPrivateFields.es2015.js | 44 ++++++++++++++++++
 ...rPropertiesAndPrivateFields.es2015.symbols | 41 +++++++++++++++++
 ...terPropertiesAndPrivateFields.es2015.types | 46 +++++++++++++++++++
 ...ameterPropertiesAndPrivateFields.es2015.ts | 15 ++++++
 5 files changed, 155 insertions(+), 6 deletions(-)
 create mode 100644 tests/baselines/reference/constructorWithParameterPropertiesAndPrivateFields.es2015.js
 create mode 100644 tests/baselines/reference/constructorWithParameterPropertiesAndPrivateFields.es2015.symbols
 create mode 100644 tests/baselines/reference/constructorWithParameterPropertiesAndPrivateFields.es2015.types
 create mode 100644 tests/cases/compiler/constructorWithParameterPropertiesAndPrivateFields.es2015.ts

diff --git a/src/compiler/transformers/classFields.ts b/src/compiler/transformers/classFields.ts
index 3ac842e8abab5..808534152e6c3 100644
--- a/src/compiler/transformers/classFields.ts
+++ b/src/compiler/transformers/classFields.ts
@@ -1294,7 +1294,7 @@ namespace ts {
             resumeLexicalEnvironment();
 
             const needsSyntheticConstructor = !constructor && isDerivedClass;
-            let indexOfFirstStatementAfterSuper = 0;
+            let indexOfFirstStatementAfterSuperAndPrologue = 0;
             let prologueStatementCount = 0;
             let superStatementIndex = -1;
             let statements: Statement[] = [];
@@ -1305,13 +1305,16 @@ namespace ts {
 
                 // If there was a super call, visit existing statements up to and including it
                 if (superStatementIndex >= 0) {
-                    indexOfFirstStatementAfterSuper = superStatementIndex + 1;
+                    indexOfFirstStatementAfterSuperAndPrologue = superStatementIndex + 1;
                     statements = [
                         ...statements.slice(0, prologueStatementCount),
-                        ...visitNodes(constructor.body.statements, visitor, isStatement, prologueStatementCount, indexOfFirstStatementAfterSuper - prologueStatementCount),
+                        ...visitNodes(constructor.body.statements, visitor, isStatement, prologueStatementCount, indexOfFirstStatementAfterSuperAndPrologue - prologueStatementCount),
                         ...statements.slice(prologueStatementCount),
                     ];
                 }
+                else if (prologueStatementCount >= 0) {
+                    indexOfFirstStatementAfterSuperAndPrologue = prologueStatementCount;
+                }
             }
 
             if (needsSyntheticConstructor) {
@@ -1354,7 +1357,7 @@ namespace ts {
                         }
                     }
                     if (parameterPropertyDeclarationCount > 0) {
-                        const parameterProperties = visitNodes(constructor.body.statements, visitor, isStatement, indexOfFirstStatementAfterSuper, parameterPropertyDeclarationCount);
+                        const parameterProperties = visitNodes(constructor.body.statements, visitor, isStatement, indexOfFirstStatementAfterSuperAndPrologue, parameterPropertyDeclarationCount);
 
                         // If there was a super() call found, add parameter properties immediately after it
                         if (superStatementIndex >= 0) {
@@ -1373,7 +1376,7 @@ namespace ts {
                             statements = [...parameterProperties, ...statements];
                         }
 
-                        indexOfFirstStatementAfterSuper += parameterPropertyDeclarationCount;
+                        indexOfFirstStatementAfterSuperAndPrologue += parameterPropertyDeclarationCount;
                     }
                 }
             }
@@ -1385,7 +1388,7 @@ namespace ts {
 
             // Add existing statements after the initial prologues and super call
             if (constructor) {
-                addRange(statements, visitNodes(constructor.body!.statements, visitBodyStatement, isStatement, indexOfFirstStatementAfterSuper + prologueStatementCount));
+                addRange(statements, visitNodes(constructor.body!.statements, visitBodyStatement, isStatement, indexOfFirstStatementAfterSuperAndPrologue));
             }
 
             statements = factory.mergeLexicalEnvironment(statements, endLexicalEnvironment());
diff --git a/tests/baselines/reference/constructorWithParameterPropertiesAndPrivateFields.es2015.js b/tests/baselines/reference/constructorWithParameterPropertiesAndPrivateFields.es2015.js
new file mode 100644
index 0000000000000..75fe3dac0b845
--- /dev/null
+++ b/tests/baselines/reference/constructorWithParameterPropertiesAndPrivateFields.es2015.js
@@ -0,0 +1,44 @@
+//// [constructorWithParameterPropertiesAndPrivateFields.es2015.ts]
+// https://github.com/microsoft/TypeScript/issues/48771
+
+class A {
+  readonly #privateField: string;
+
+  constructor(arg: { key: string }, public exposedField: number) {
+    ({ key: this.#privateField } = arg);
+  }
+
+  log() {
+    console.log(this.#privateField);
+    console.log(this.exposedField);
+  }
+}
+
+
+//// [constructorWithParameterPropertiesAndPrivateFields.es2015.js]
+// https://github.com/microsoft/TypeScript/issues/48771
+var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
+    if (kind === "m") throw new TypeError("Private method is not writable");
+    if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
+    if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
+    return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
+};
+var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
+    if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
+    if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
+    return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
+};
+var _A_privateField;
+class A {
+    constructor(arg, exposedField) {
+        this.exposedField = exposedField;
+        var _a;
+        _A_privateField.set(this, void 0);
+        (_a = this, { key: ({ set value(_b) { __classPrivateFieldSet(_a, _A_privateField, _b, "f"); } }).value } = arg);
+    }
+    log() {
+        console.log(__classPrivateFieldGet(this, _A_privateField, "f"));
+        console.log(this.exposedField);
+    }
+}
+_A_privateField = new WeakMap();
diff --git a/tests/baselines/reference/constructorWithParameterPropertiesAndPrivateFields.es2015.symbols b/tests/baselines/reference/constructorWithParameterPropertiesAndPrivateFields.es2015.symbols
new file mode 100644
index 0000000000000..64643c42cdfd0
--- /dev/null
+++ b/tests/baselines/reference/constructorWithParameterPropertiesAndPrivateFields.es2015.symbols
@@ -0,0 +1,41 @@
+=== tests/cases/compiler/constructorWithParameterPropertiesAndPrivateFields.es2015.ts ===
+// https://github.com/microsoft/TypeScript/issues/48771
+
+class A {
+>A : Symbol(A, Decl(constructorWithParameterPropertiesAndPrivateFields.es2015.ts, 0, 0))
+
+  readonly #privateField: string;
+>#privateField : Symbol(A.#privateField, Decl(constructorWithParameterPropertiesAndPrivateFields.es2015.ts, 2, 9))
+
+  constructor(arg: { key: string }, public exposedField: number) {
+>arg : Symbol(arg, Decl(constructorWithParameterPropertiesAndPrivateFields.es2015.ts, 5, 14))
+>key : Symbol(key, Decl(constructorWithParameterPropertiesAndPrivateFields.es2015.ts, 5, 20))
+>exposedField : Symbol(A.exposedField, Decl(constructorWithParameterPropertiesAndPrivateFields.es2015.ts, 5, 35))
+
+    ({ key: this.#privateField } = arg);
+>key : Symbol(key, Decl(constructorWithParameterPropertiesAndPrivateFields.es2015.ts, 6, 6))
+>this.#privateField : Symbol(A.#privateField, Decl(constructorWithParameterPropertiesAndPrivateFields.es2015.ts, 2, 9))
+>this : Symbol(A, Decl(constructorWithParameterPropertiesAndPrivateFields.es2015.ts, 0, 0))
+>arg : Symbol(arg, Decl(constructorWithParameterPropertiesAndPrivateFields.es2015.ts, 5, 14))
+  }
+
+  log() {
+>log : Symbol(A.log, Decl(constructorWithParameterPropertiesAndPrivateFields.es2015.ts, 7, 3))
+
+    console.log(this.#privateField);
+>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
+>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
+>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
+>this.#privateField : Symbol(A.#privateField, Decl(constructorWithParameterPropertiesAndPrivateFields.es2015.ts, 2, 9))
+>this : Symbol(A, Decl(constructorWithParameterPropertiesAndPrivateFields.es2015.ts, 0, 0))
+
+    console.log(this.exposedField);
+>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
+>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
+>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
+>this.exposedField : Symbol(A.exposedField, Decl(constructorWithParameterPropertiesAndPrivateFields.es2015.ts, 5, 35))
+>this : Symbol(A, Decl(constructorWithParameterPropertiesAndPrivateFields.es2015.ts, 0, 0))
+>exposedField : Symbol(A.exposedField, Decl(constructorWithParameterPropertiesAndPrivateFields.es2015.ts, 5, 35))
+  }
+}
+
diff --git a/tests/baselines/reference/constructorWithParameterPropertiesAndPrivateFields.es2015.types b/tests/baselines/reference/constructorWithParameterPropertiesAndPrivateFields.es2015.types
new file mode 100644
index 0000000000000..066b52c5615d7
--- /dev/null
+++ b/tests/baselines/reference/constructorWithParameterPropertiesAndPrivateFields.es2015.types
@@ -0,0 +1,46 @@
+=== tests/cases/compiler/constructorWithParameterPropertiesAndPrivateFields.es2015.ts ===
+// https://github.com/microsoft/TypeScript/issues/48771
+
+class A {
+>A : A
+
+  readonly #privateField: string;
+>#privateField : string
+
+  constructor(arg: { key: string }, public exposedField: number) {
+>arg : { key: string; }
+>key : string
+>exposedField : number
+
+    ({ key: this.#privateField } = arg);
+>({ key: this.#privateField } = arg) : { key: string; }
+>{ key: this.#privateField } = arg : { key: string; }
+>{ key: this.#privateField } : { key: string; }
+>key : string
+>this.#privateField : string
+>this : this
+>arg : { key: string; }
+  }
+
+  log() {
+>log : () => void
+
+    console.log(this.#privateField);
+>console.log(this.#privateField) : void
+>console.log : (...data: any[]) => void
+>console : Console
+>log : (...data: any[]) => void
+>this.#privateField : string
+>this : this
+
+    console.log(this.exposedField);
+>console.log(this.exposedField) : void
+>console.log : (...data: any[]) => void
+>console : Console
+>log : (...data: any[]) => void
+>this.exposedField : number
+>this : this
+>exposedField : number
+  }
+}
+
diff --git a/tests/cases/compiler/constructorWithParameterPropertiesAndPrivateFields.es2015.ts b/tests/cases/compiler/constructorWithParameterPropertiesAndPrivateFields.es2015.ts
new file mode 100644
index 0000000000000..1a0251335e90e
--- /dev/null
+++ b/tests/cases/compiler/constructorWithParameterPropertiesAndPrivateFields.es2015.ts
@@ -0,0 +1,15 @@
+// @target: es2015
+// https://github.com/microsoft/TypeScript/issues/48771
+
+class A {
+  readonly #privateField: string;
+
+  constructor(arg: { key: string }, public exposedField: number) {
+    ({ key: this.#privateField } = arg);
+  }
+
+  log() {
+    console.log(this.#privateField);
+    console.log(this.exposedField);
+  }
+}

From bd2a2ecc319c09299d56cf437e6fdbd27b219aa9 Mon Sep 17 00:00:00 2001
From: John Lusty <54030459+jlusty@users.noreply.github.com>
Date: Wed, 20 Apr 2022 07:43:13 +0100
Subject: [PATCH 2/4] Add second test case

---
 ...ameterPropertiesAndPrivateFields.es2015.js | 30 +++++++++++-
 ...rPropertiesAndPrivateFields.es2015.symbols | 39 ++++++++++++++++
 ...terPropertiesAndPrivateFields.es2015.types | 46 +++++++++++++++++++
 ...ameterPropertiesAndPrivateFields.es2015.ts | 14 ++++++
 4 files changed, 128 insertions(+), 1 deletion(-)

diff --git a/tests/baselines/reference/constructorWithParameterPropertiesAndPrivateFields.es2015.js b/tests/baselines/reference/constructorWithParameterPropertiesAndPrivateFields.es2015.js
index 75fe3dac0b845..19e3379b05abb 100644
--- a/tests/baselines/reference/constructorWithParameterPropertiesAndPrivateFields.es2015.js
+++ b/tests/baselines/reference/constructorWithParameterPropertiesAndPrivateFields.es2015.js
@@ -13,6 +13,20 @@ class A {
     console.log(this.exposedField);
   }
 }
+
+class B {
+  readonly #privateField: string;
+
+  constructor(arg: { key: string }, public exposedField: number) {
+    "prologue";
+    ({ key: this.#privateField } = arg);
+  }
+
+  log() {
+    console.log(this.#privateField);
+    console.log(this.exposedField);
+  }
+}
 
 
 //// [constructorWithParameterPropertiesAndPrivateFields.es2015.js]
@@ -28,7 +42,7 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
     if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
     return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
 };
-var _A_privateField;
+var _A_privateField, _B_privateField;
 class A {
     constructor(arg, exposedField) {
         this.exposedField = exposedField;
@@ -42,3 +56,17 @@ class A {
     }
 }
 _A_privateField = new WeakMap();
+class B {
+    constructor(arg, exposedField) {
+        this.exposedField = exposedField;
+        "prologue";
+        var _a;
+        _B_privateField.set(this, void 0);
+        (_a = this, { key: ({ set value(_b) { __classPrivateFieldSet(_a, _B_privateField, _b, "f"); } }).value } = arg);
+    }
+    log() {
+        console.log(__classPrivateFieldGet(this, _B_privateField, "f"));
+        console.log(this.exposedField);
+    }
+}
+_B_privateField = new WeakMap();
diff --git a/tests/baselines/reference/constructorWithParameterPropertiesAndPrivateFields.es2015.symbols b/tests/baselines/reference/constructorWithParameterPropertiesAndPrivateFields.es2015.symbols
index 64643c42cdfd0..cffef43438aac 100644
--- a/tests/baselines/reference/constructorWithParameterPropertiesAndPrivateFields.es2015.symbols
+++ b/tests/baselines/reference/constructorWithParameterPropertiesAndPrivateFields.es2015.symbols
@@ -39,3 +39,42 @@ class A {
   }
 }
 
+class B {
+>B : Symbol(B, Decl(constructorWithParameterPropertiesAndPrivateFields.es2015.ts, 13, 1))
+
+  readonly #privateField: string;
+>#privateField : Symbol(B.#privateField, Decl(constructorWithParameterPropertiesAndPrivateFields.es2015.ts, 15, 9))
+
+  constructor(arg: { key: string }, public exposedField: number) {
+>arg : Symbol(arg, Decl(constructorWithParameterPropertiesAndPrivateFields.es2015.ts, 18, 14))
+>key : Symbol(key, Decl(constructorWithParameterPropertiesAndPrivateFields.es2015.ts, 18, 20))
+>exposedField : Symbol(B.exposedField, Decl(constructorWithParameterPropertiesAndPrivateFields.es2015.ts, 18, 35))
+
+    "prologue";
+    ({ key: this.#privateField } = arg);
+>key : Symbol(key, Decl(constructorWithParameterPropertiesAndPrivateFields.es2015.ts, 20, 6))
+>this.#privateField : Symbol(B.#privateField, Decl(constructorWithParameterPropertiesAndPrivateFields.es2015.ts, 15, 9))
+>this : Symbol(B, Decl(constructorWithParameterPropertiesAndPrivateFields.es2015.ts, 13, 1))
+>arg : Symbol(arg, Decl(constructorWithParameterPropertiesAndPrivateFields.es2015.ts, 18, 14))
+  }
+
+  log() {
+>log : Symbol(B.log, Decl(constructorWithParameterPropertiesAndPrivateFields.es2015.ts, 21, 3))
+
+    console.log(this.#privateField);
+>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
+>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
+>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
+>this.#privateField : Symbol(B.#privateField, Decl(constructorWithParameterPropertiesAndPrivateFields.es2015.ts, 15, 9))
+>this : Symbol(B, Decl(constructorWithParameterPropertiesAndPrivateFields.es2015.ts, 13, 1))
+
+    console.log(this.exposedField);
+>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
+>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
+>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
+>this.exposedField : Symbol(B.exposedField, Decl(constructorWithParameterPropertiesAndPrivateFields.es2015.ts, 18, 35))
+>this : Symbol(B, Decl(constructorWithParameterPropertiesAndPrivateFields.es2015.ts, 13, 1))
+>exposedField : Symbol(B.exposedField, Decl(constructorWithParameterPropertiesAndPrivateFields.es2015.ts, 18, 35))
+  }
+}
+
diff --git a/tests/baselines/reference/constructorWithParameterPropertiesAndPrivateFields.es2015.types b/tests/baselines/reference/constructorWithParameterPropertiesAndPrivateFields.es2015.types
index 066b52c5615d7..ea034c2b054b5 100644
--- a/tests/baselines/reference/constructorWithParameterPropertiesAndPrivateFields.es2015.types
+++ b/tests/baselines/reference/constructorWithParameterPropertiesAndPrivateFields.es2015.types
@@ -44,3 +44,49 @@ class A {
   }
 }
 
+class B {
+>B : B
+
+  readonly #privateField: string;
+>#privateField : string
+
+  constructor(arg: { key: string }, public exposedField: number) {
+>arg : { key: string; }
+>key : string
+>exposedField : number
+
+    "prologue";
+>"prologue" : "prologue"
+
+    ({ key: this.#privateField } = arg);
+>({ key: this.#privateField } = arg) : { key: string; }
+>{ key: this.#privateField } = arg : { key: string; }
+>{ key: this.#privateField } : { key: string; }
+>key : string
+>this.#privateField : string
+>this : this
+>arg : { key: string; }
+  }
+
+  log() {
+>log : () => void
+
+    console.log(this.#privateField);
+>console.log(this.#privateField) : void
+>console.log : (...data: any[]) => void
+>console : Console
+>log : (...data: any[]) => void
+>this.#privateField : string
+>this : this
+
+    console.log(this.exposedField);
+>console.log(this.exposedField) : void
+>console.log : (...data: any[]) => void
+>console : Console
+>log : (...data: any[]) => void
+>this.exposedField : number
+>this : this
+>exposedField : number
+  }
+}
+
diff --git a/tests/cases/compiler/constructorWithParameterPropertiesAndPrivateFields.es2015.ts b/tests/cases/compiler/constructorWithParameterPropertiesAndPrivateFields.es2015.ts
index 1a0251335e90e..ec0fd2464d255 100644
--- a/tests/cases/compiler/constructorWithParameterPropertiesAndPrivateFields.es2015.ts
+++ b/tests/cases/compiler/constructorWithParameterPropertiesAndPrivateFields.es2015.ts
@@ -13,3 +13,17 @@ class A {
     console.log(this.exposedField);
   }
 }
+
+class B {
+  readonly #privateField: string;
+
+  constructor(arg: { key: string }, public exposedField: number) {
+    "prologue";
+    ({ key: this.#privateField } = arg);
+  }
+
+  log() {
+    console.log(this.#privateField);
+    console.log(this.exposedField);
+  }
+}

From d45098e23bfefa3ad92b5728df41451533ae7689 Mon Sep 17 00:00:00 2001
From: John Lusty <54030459+jlusty@users.noreply.github.com>
Date: Wed, 20 Apr 2022 08:07:27 +0100
Subject: [PATCH 3/4] Update to match old TS version: parameter properties
 after prologue

---
 src/compiler/transformers/classFields.ts      | 22 +++++++------------
 ...ameterPropertiesAndPrivateFields.es2015.js |  4 ++--
 2 files changed, 10 insertions(+), 16 deletions(-)

diff --git a/src/compiler/transformers/classFields.ts b/src/compiler/transformers/classFields.ts
index 808534152e6c3..77e2d76bfdb90 100644
--- a/src/compiler/transformers/classFields.ts
+++ b/src/compiler/transformers/classFields.ts
@@ -1359,22 +1359,16 @@ namespace ts {
                     if (parameterPropertyDeclarationCount > 0) {
                         const parameterProperties = visitNodes(constructor.body.statements, visitor, isStatement, indexOfFirstStatementAfterSuperAndPrologue, parameterPropertyDeclarationCount);
 
-                        // If there was a super() call found, add parameter properties immediately after it
-                        if (superStatementIndex >= 0) {
-                            addRange(statements, parameterProperties);
-                        }
+                        let superAndPrologueStatementCount = prologueStatementCount;
                         // If a synthetic super() call was added, add them just after it
-                        else if (needsSyntheticConstructor) {
-                            statements = [
-                                statements[0],
-                                ...parameterProperties,
-                                ...statements.slice(1),
-                            ];
-                        }
-                        // Since there wasn't a super() call, add them to the top of the constructor
-                        else {
-                            statements = [...parameterProperties, ...statements];
+                        if (needsSyntheticConstructor) {
+                            superAndPrologueStatementCount += 1;
                         }
+                        statements = [
+                            ...statements.slice(0, superAndPrologueStatementCount),
+                            ...parameterProperties,
+                            ...statements.slice(superAndPrologueStatementCount),
+                        ];
 
                         indexOfFirstStatementAfterSuperAndPrologue += parameterPropertyDeclarationCount;
                     }
diff --git a/tests/baselines/reference/constructorWithParameterPropertiesAndPrivateFields.es2015.js b/tests/baselines/reference/constructorWithParameterPropertiesAndPrivateFields.es2015.js
index 19e3379b05abb..9d2e2e71697d2 100644
--- a/tests/baselines/reference/constructorWithParameterPropertiesAndPrivateFields.es2015.js
+++ b/tests/baselines/reference/constructorWithParameterPropertiesAndPrivateFields.es2015.js
@@ -45,8 +45,8 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
 var _A_privateField, _B_privateField;
 class A {
     constructor(arg, exposedField) {
-        this.exposedField = exposedField;
         var _a;
+        this.exposedField = exposedField;
         _A_privateField.set(this, void 0);
         (_a = this, { key: ({ set value(_b) { __classPrivateFieldSet(_a, _A_privateField, _b, "f"); } }).value } = arg);
     }
@@ -58,9 +58,9 @@ class A {
 _A_privateField = new WeakMap();
 class B {
     constructor(arg, exposedField) {
-        this.exposedField = exposedField;
         "prologue";
         var _a;
+        this.exposedField = exposedField;
         _B_privateField.set(this, void 0);
         (_a = this, { key: ({ set value(_b) { __classPrivateFieldSet(_a, _B_privateField, _b, "f"); } }).value } = arg);
     }

From 891cb6f317a5e383baffc1fd7cd40b16d4e159e4 Mon Sep 17 00:00:00 2001
From: John Lusty <54030459+jlusty@users.noreply.github.com>
Date: Wed, 20 Apr 2022 08:31:00 +0100
Subject: [PATCH 4/4] Parametert properties should be added after any prologue

---
 src/compiler/transformers/classFields.ts | 23 ++++++++++++++---------
 1 file changed, 14 insertions(+), 9 deletions(-)

diff --git a/src/compiler/transformers/classFields.ts b/src/compiler/transformers/classFields.ts
index 77e2d76bfdb90..cff2be7fb78b8 100644
--- a/src/compiler/transformers/classFields.ts
+++ b/src/compiler/transformers/classFields.ts
@@ -1359,16 +1359,21 @@ namespace ts {
                     if (parameterPropertyDeclarationCount > 0) {
                         const parameterProperties = visitNodes(constructor.body.statements, visitor, isStatement, indexOfFirstStatementAfterSuperAndPrologue, parameterPropertyDeclarationCount);
 
-                        let superAndPrologueStatementCount = prologueStatementCount;
-                        // If a synthetic super() call was added, add them just after it
-                        if (needsSyntheticConstructor) {
-                            superAndPrologueStatementCount += 1;
+                        // If there was a super() call found, add parameter properties immediately after it
+                        if (superStatementIndex >= 0) {
+                            addRange(statements, parameterProperties);
+                        }
+                        else {
+                            // Add add parameter properties to the top of the constructor after the prologue
+                            let superAndPrologueStatementCount = prologueStatementCount;
+                            // If a synthetic super() call was added, need to account for that
+                            if (needsSyntheticConstructor) superAndPrologueStatementCount++;
+                            statements = [
+                                ...statements.slice(0, superAndPrologueStatementCount),
+                                ...parameterProperties,
+                                ...statements.slice(superAndPrologueStatementCount),
+                            ];
                         }
-                        statements = [
-                            ...statements.slice(0, superAndPrologueStatementCount),
-                            ...parameterProperties,
-                            ...statements.slice(superAndPrologueStatementCount),
-                        ];
 
                         indexOfFirstStatementAfterSuperAndPrologue += parameterPropertyDeclarationCount;
                     }