mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-06 20:14:01 -06:00
Component commits: 74c337bc5f 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 bd2a2ecc31 Add second test case d45098e23b Update to match old TS version: parameter properties after prologue 891cb6f317 Parametert properties should be added after any prologue Co-authored-by: John Lusty <54030459+jlusty@users.noreply.github.com>
This commit is contained in:
parent
ef0095c944
commit
774f419757
@ -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,26 +1357,25 @@ 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) {
|
||||
addRange(statements, parameterProperties);
|
||||
}
|
||||
// If a synthetic super() call was added, add them just after it
|
||||
else if (needsSyntheticConstructor) {
|
||||
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[0],
|
||||
...statements.slice(0, superAndPrologueStatementCount),
|
||||
...parameterProperties,
|
||||
...statements.slice(1),
|
||||
...statements.slice(superAndPrologueStatementCount),
|
||||
];
|
||||
}
|
||||
// Since there wasn't a super() call, add them to the top of the constructor
|
||||
else {
|
||||
statements = [...parameterProperties, ...statements];
|
||||
}
|
||||
|
||||
indexOfFirstStatementAfterSuper += parameterPropertyDeclarationCount;
|
||||
indexOfFirstStatementAfterSuperAndPrologue += parameterPropertyDeclarationCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1385,7 +1387,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());
|
||||
|
||||
@ -0,0 +1,72 @@
|
||||
//// [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);
|
||||
}
|
||||
}
|
||||
|
||||
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]
|
||||
// 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, _B_privateField;
|
||||
class A {
|
||||
constructor(arg, 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);
|
||||
}
|
||||
log() {
|
||||
console.log(__classPrivateFieldGet(this, _A_privateField, "f"));
|
||||
console.log(this.exposedField);
|
||||
}
|
||||
}
|
||||
_A_privateField = new WeakMap();
|
||||
class B {
|
||||
constructor(arg, 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);
|
||||
}
|
||||
log() {
|
||||
console.log(__classPrivateFieldGet(this, _B_privateField, "f"));
|
||||
console.log(this.exposedField);
|
||||
}
|
||||
}
|
||||
_B_privateField = new WeakMap();
|
||||
@ -0,0 +1,80 @@
|
||||
=== 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))
|
||||
}
|
||||
}
|
||||
|
||||
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))
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,92 @@
|
||||
=== 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
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,29 @@
|
||||
// @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);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user