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; }