fix(48487): allow using private names as the self-assignment entity name (#48496)

This commit is contained in:
Oleksandr T 2022-04-08 20:48:28 +03:00 committed by GitHub
parent b1fb7293c0
commit 3b2fa50a14
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 216 additions and 7 deletions

View File

@ -2338,18 +2338,13 @@ namespace ts {
if (isPropertyNameLiteral(name) && isPropertyNameLiteral(initializer)) {
return getTextOfIdentifierOrLiteral(name) === getTextOfIdentifierOrLiteral(initializer);
}
if (isIdentifier(name) && isLiteralLikeAccess(initializer) &&
if (isMemberName(name) && isLiteralLikeAccess(initializer) &&
(initializer.expression.kind === SyntaxKind.ThisKeyword ||
isIdentifier(initializer.expression) &&
(initializer.expression.escapedText === "window" ||
initializer.expression.escapedText === "self" ||
initializer.expression.escapedText === "global"))) {
const nameOrArgument = getNameOrArgument(initializer);
if (isPrivateIdentifier(nameOrArgument)) {
Debug.fail("Unexpected PrivateIdentifier in name expression with literal-like access.");
}
return isSameEntityName(name, nameOrArgument);
return isSameEntityName(name, getNameOrArgument(initializer));
}
if (isLiteralLikeAccess(name) && isLiteralLikeAccess(initializer)) {
return getElementOrPropertyAccessName(name) === getElementOrPropertyAccessName(initializer)

View File

@ -0,0 +1,23 @@
//// [typeFromPrivatePropertyAssignment.ts]
type Foo = { foo?: string };
class C {
#a?: Foo;
#b?: Foo;
m() {
const a = this.#a || {};
this.#b = this.#b || {};
}
}
//// [typeFromPrivatePropertyAssignment.js]
class C {
#a;
#b;
m() {
const a = this.#a || {};
this.#b = this.#b || {};
}
}

View File

@ -0,0 +1,32 @@
=== tests/cases/conformance/classes/members/privateNames/typeFromPrivatePropertyAssignment.ts ===
type Foo = { foo?: string };
>Foo : Symbol(Foo, Decl(typeFromPrivatePropertyAssignment.ts, 0, 0))
>foo : Symbol(foo, Decl(typeFromPrivatePropertyAssignment.ts, 0, 12))
class C {
>C : Symbol(C, Decl(typeFromPrivatePropertyAssignment.ts, 0, 28))
#a?: Foo;
>#a : Symbol(C.#a, Decl(typeFromPrivatePropertyAssignment.ts, 2, 9))
>Foo : Symbol(Foo, Decl(typeFromPrivatePropertyAssignment.ts, 0, 0))
#b?: Foo;
>#b : Symbol(C.#b, Decl(typeFromPrivatePropertyAssignment.ts, 3, 13))
>Foo : Symbol(Foo, Decl(typeFromPrivatePropertyAssignment.ts, 0, 0))
m() {
>m : Symbol(C.m, Decl(typeFromPrivatePropertyAssignment.ts, 4, 13))
const a = this.#a || {};
>a : Symbol(a, Decl(typeFromPrivatePropertyAssignment.ts, 7, 13))
>this.#a : Symbol(C.#a, Decl(typeFromPrivatePropertyAssignment.ts, 2, 9))
>this : Symbol(C, Decl(typeFromPrivatePropertyAssignment.ts, 0, 28))
this.#b = this.#b || {};
>this.#b : Symbol(C.#b, Decl(typeFromPrivatePropertyAssignment.ts, 3, 13))
>this : Symbol(C, Decl(typeFromPrivatePropertyAssignment.ts, 0, 28))
>this.#b : Symbol(C.#b, Decl(typeFromPrivatePropertyAssignment.ts, 3, 13))
>this : Symbol(C, Decl(typeFromPrivatePropertyAssignment.ts, 0, 28))
}
}

View File

@ -0,0 +1,35 @@
=== tests/cases/conformance/classes/members/privateNames/typeFromPrivatePropertyAssignment.ts ===
type Foo = { foo?: string };
>Foo : Foo
>foo : string
class C {
>C : C
#a?: Foo;
>#a : Foo
#b?: Foo;
>#b : Foo
m() {
>m : () => void
const a = this.#a || {};
>a : Foo
>this.#a || {} : Foo
>this.#a : Foo
>this : this
>{} : {}
this.#b = this.#b || {};
>this.#b = this.#b || {} : Foo
>this.#b : Foo
>this : this
>this.#b || {} : Foo
>this.#b : Foo
>this : this
>{} : {}
}
}

View File

@ -0,0 +1,29 @@
//// [tests/cases/conformance/classes/members/privateNames/typeFromPrivatePropertyAssignmentJs.ts] ////
//// [typeFromPrivatePropertyAssignmentJs.js]
//// [a.js]
class C {
/** @type {{ foo?: string } | undefined } */
#a;
/** @type {{ foo?: string } | undefined } */
#b;
m() {
const a = this.#a || {};
this.#b = this.#b || {};
}
}
//// [typeFromPrivatePropertyAssignmentJs.js]
//// [a.js]
class C {
/** @type {{ foo?: string } | undefined } */
#a;
/** @type {{ foo?: string } | undefined } */
#b;
m() {
const a = this.#a || {};
this.#b = this.#b || {};
}
}

View File

@ -0,0 +1,30 @@
=== tests/cases/conformance/classes/members/privateNames/typeFromPrivatePropertyAssignmentJs.js ===
No type information for this code.=== tests/cases/conformance/classes/members/privateNames/a.js ===
class C {
>C : Symbol(C, Decl(a.js, 0, 0))
/** @type {{ foo?: string } | undefined } */
#a;
>#a : Symbol(C.#a, Decl(a.js, 0, 9))
/** @type {{ foo?: string } | undefined } */
#b;
>#b : Symbol(C.#b, Decl(a.js, 2, 7))
m() {
>m : Symbol(C.m, Decl(a.js, 4, 7))
const a = this.#a || {};
>a : Symbol(a, Decl(a.js, 6, 13))
>this.#a : Symbol(C.#a, Decl(a.js, 0, 9))
>this : Symbol(C, Decl(a.js, 0, 0))
this.#b = this.#b || {};
>this.#b : Symbol(C.#b, Decl(a.js, 2, 7))
>this : Symbol(C, Decl(a.js, 0, 0))
>this.#b : Symbol(C.#b, Decl(a.js, 2, 7))
>this : Symbol(C, Decl(a.js, 0, 0))
}
}

View File

@ -0,0 +1,35 @@
=== tests/cases/conformance/classes/members/privateNames/typeFromPrivatePropertyAssignmentJs.js ===
No type information for this code.=== tests/cases/conformance/classes/members/privateNames/a.js ===
class C {
>C : C
/** @type {{ foo?: string } | undefined } */
#a;
>#a : { foo?: string; }
/** @type {{ foo?: string } | undefined } */
#b;
>#b : { foo?: string; }
m() {
>m : () => void
const a = this.#a || {};
>a : { foo?: string; }
>this.#a || {} : { foo?: string; }
>this.#a : { foo?: string; }
>this : this
>{} : {}
this.#b = this.#b || {};
>this.#b = this.#b || {} : { foo?: string; }
>this.#b : { foo?: string; }
>this : this
>this.#b || {} : { foo?: string; }
>this.#b : { foo?: string; }
>this : this
>{} : {}
}
}

View File

@ -0,0 +1,13 @@
// @target: esnext
type Foo = { foo?: string };
class C {
#a?: Foo;
#b?: Foo;
m() {
const a = this.#a || {};
this.#b = this.#b || {};
}
}

View File

@ -0,0 +1,17 @@
// @target: esnext
// @allowJs: true
// @checkJs: true
// @outDir: ./out
// @filename: typeFromPrivatePropertyAssignmentJs.js
// @filename: a.js
class C {
/** @type {{ foo?: string } | undefined } */
#a;
/** @type {{ foo?: string } | undefined } */
#b;
m() {
const a = this.#a || {};
this.#b = this.#b || {};
}
}