diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 7b6d49cf8f9c4..3c7b020e7e842 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -2210,7 +2210,7 @@ m2: ${(this.mapper2 as unknown as DebugTypeMapper).__debugToString().split("\n") // 1. When result is undefined, after checking for a missing "this." // 2. When result is defined function checkAndReportErrorForInvalidInitializer() { - if (propertyWithInvalidInitializer && !(getEmitScriptTarget(compilerOptions) === ScriptTarget.ESNext && useDefineForClassFields)) { + if (propertyWithInvalidInitializer && !(useDefineForClassFields && getEmitScriptTarget(compilerOptions) >= ScriptTarget.ES2022)) { // We have a match, but the reference occurred within a property initializer and the identifier also binds // to a local variable in the constructor where the code will be emitted. Note that this is actually allowed // with ESNext+useDefineForClassFields because the scope semantics are different. diff --git a/src/testRunner/compilerRunner.ts b/src/testRunner/compilerRunner.ts index 1d320d667cf5f..a6c67a17ee186 100644 --- a/src/testRunner/compilerRunner.ts +++ b/src/testRunner/compilerRunner.ts @@ -141,7 +141,8 @@ namespace Harness { "preserveConstEnums", "skipLibCheck", "exactOptionalPropertyTypes", - "useUnknownInCatchVariables" + "useDefineForClassFields", + "useUnknownInCatchVariables", ]; private fileName: string; private justName: string; diff --git a/tests/baselines/reference/classMemberInitializerScoping2(target=es2017,usedefineforclassfields=false).errors.txt b/tests/baselines/reference/classMemberInitializerScoping2(target=es2017,usedefineforclassfields=false).errors.txt new file mode 100644 index 0000000000000..d214ea137164d --- /dev/null +++ b/tests/baselines/reference/classMemberInitializerScoping2(target=es2017,usedefineforclassfields=false).errors.txt @@ -0,0 +1,12 @@ +tests/cases/compiler/classMemberInitializerScoping2.ts(3,9): error TS2301: Initializer of instance member variable 'p' cannot reference identifier 'x' declared in the constructor. + + +==== tests/cases/compiler/classMemberInitializerScoping2.ts (1 errors) ==== + const x = 1 + class C { + p = x + ~ +!!! error TS2301: Initializer of instance member variable 'p' cannot reference identifier 'x' declared in the constructor. + constructor(x: string) { } + } + \ No newline at end of file diff --git a/tests/baselines/reference/classMemberInitializerScoping2(target=es2017,usedefineforclassfields=false).js b/tests/baselines/reference/classMemberInitializerScoping2(target=es2017,usedefineforclassfields=false).js new file mode 100644 index 0000000000000..9591c174fc945 --- /dev/null +++ b/tests/baselines/reference/classMemberInitializerScoping2(target=es2017,usedefineforclassfields=false).js @@ -0,0 +1,15 @@ +//// [classMemberInitializerScoping2.ts] +const x = 1 +class C { + p = x + constructor(x: string) { } +} + + +//// [classMemberInitializerScoping2.js] +const x = 1; +class C { + constructor(x) { + this.p = x; + } +} diff --git a/tests/baselines/reference/classMemberInitializerScoping2(target=es2017,usedefineforclassfields=false).symbols b/tests/baselines/reference/classMemberInitializerScoping2(target=es2017,usedefineforclassfields=false).symbols new file mode 100644 index 0000000000000..78c02088261dd --- /dev/null +++ b/tests/baselines/reference/classMemberInitializerScoping2(target=es2017,usedefineforclassfields=false).symbols @@ -0,0 +1,14 @@ +=== tests/cases/compiler/classMemberInitializerScoping2.ts === +const x = 1 +>x : Symbol(x, Decl(classMemberInitializerScoping2.ts, 0, 5)) + +class C { +>C : Symbol(C, Decl(classMemberInitializerScoping2.ts, 0, 11)) + + p = x +>p : Symbol(C.p, Decl(classMemberInitializerScoping2.ts, 1, 9)) + + constructor(x: string) { } +>x : Symbol(x, Decl(classMemberInitializerScoping2.ts, 3, 16)) +} + diff --git a/tests/baselines/reference/classMemberInitializerScoping2(target=es2017,usedefineforclassfields=false).types b/tests/baselines/reference/classMemberInitializerScoping2(target=es2017,usedefineforclassfields=false).types new file mode 100644 index 0000000000000..20cff56773ba7 --- /dev/null +++ b/tests/baselines/reference/classMemberInitializerScoping2(target=es2017,usedefineforclassfields=false).types @@ -0,0 +1,16 @@ +=== tests/cases/compiler/classMemberInitializerScoping2.ts === +const x = 1 +>x : 1 +>1 : 1 + +class C { +>C : C + + p = x +>p : any +>x : any + + constructor(x: string) { } +>x : string +} + diff --git a/tests/baselines/reference/classMemberInitializerScoping2(target=es2017,usedefineforclassfields=true).errors.txt b/tests/baselines/reference/classMemberInitializerScoping2(target=es2017,usedefineforclassfields=true).errors.txt new file mode 100644 index 0000000000000..d214ea137164d --- /dev/null +++ b/tests/baselines/reference/classMemberInitializerScoping2(target=es2017,usedefineforclassfields=true).errors.txt @@ -0,0 +1,12 @@ +tests/cases/compiler/classMemberInitializerScoping2.ts(3,9): error TS2301: Initializer of instance member variable 'p' cannot reference identifier 'x' declared in the constructor. + + +==== tests/cases/compiler/classMemberInitializerScoping2.ts (1 errors) ==== + const x = 1 + class C { + p = x + ~ +!!! error TS2301: Initializer of instance member variable 'p' cannot reference identifier 'x' declared in the constructor. + constructor(x: string) { } + } + \ No newline at end of file diff --git a/tests/baselines/reference/classMemberInitializerScoping2(target=es2017,usedefineforclassfields=true).js b/tests/baselines/reference/classMemberInitializerScoping2(target=es2017,usedefineforclassfields=true).js new file mode 100644 index 0000000000000..c2f4708c351b5 --- /dev/null +++ b/tests/baselines/reference/classMemberInitializerScoping2(target=es2017,usedefineforclassfields=true).js @@ -0,0 +1,20 @@ +//// [classMemberInitializerScoping2.ts] +const x = 1 +class C { + p = x + constructor(x: string) { } +} + + +//// [classMemberInitializerScoping2.js] +const x = 1; +class C { + constructor(x) { + Object.defineProperty(this, "p", { + enumerable: true, + configurable: true, + writable: true, + value: x + }); + } +} diff --git a/tests/baselines/reference/classMemberInitializerScoping2(target=es2017,usedefineforclassfields=true).symbols b/tests/baselines/reference/classMemberInitializerScoping2(target=es2017,usedefineforclassfields=true).symbols new file mode 100644 index 0000000000000..78c02088261dd --- /dev/null +++ b/tests/baselines/reference/classMemberInitializerScoping2(target=es2017,usedefineforclassfields=true).symbols @@ -0,0 +1,14 @@ +=== tests/cases/compiler/classMemberInitializerScoping2.ts === +const x = 1 +>x : Symbol(x, Decl(classMemberInitializerScoping2.ts, 0, 5)) + +class C { +>C : Symbol(C, Decl(classMemberInitializerScoping2.ts, 0, 11)) + + p = x +>p : Symbol(C.p, Decl(classMemberInitializerScoping2.ts, 1, 9)) + + constructor(x: string) { } +>x : Symbol(x, Decl(classMemberInitializerScoping2.ts, 3, 16)) +} + diff --git a/tests/baselines/reference/classMemberInitializerScoping2(target=es2017,usedefineforclassfields=true).types b/tests/baselines/reference/classMemberInitializerScoping2(target=es2017,usedefineforclassfields=true).types new file mode 100644 index 0000000000000..20cff56773ba7 --- /dev/null +++ b/tests/baselines/reference/classMemberInitializerScoping2(target=es2017,usedefineforclassfields=true).types @@ -0,0 +1,16 @@ +=== tests/cases/compiler/classMemberInitializerScoping2.ts === +const x = 1 +>x : 1 +>1 : 1 + +class C { +>C : C + + p = x +>p : any +>x : any + + constructor(x: string) { } +>x : string +} + diff --git a/tests/baselines/reference/classMemberInitializerScoping2(target=esnext,usedefineforclassfields=false).errors.txt b/tests/baselines/reference/classMemberInitializerScoping2(target=esnext,usedefineforclassfields=false).errors.txt new file mode 100644 index 0000000000000..d214ea137164d --- /dev/null +++ b/tests/baselines/reference/classMemberInitializerScoping2(target=esnext,usedefineforclassfields=false).errors.txt @@ -0,0 +1,12 @@ +tests/cases/compiler/classMemberInitializerScoping2.ts(3,9): error TS2301: Initializer of instance member variable 'p' cannot reference identifier 'x' declared in the constructor. + + +==== tests/cases/compiler/classMemberInitializerScoping2.ts (1 errors) ==== + const x = 1 + class C { + p = x + ~ +!!! error TS2301: Initializer of instance member variable 'p' cannot reference identifier 'x' declared in the constructor. + constructor(x: string) { } + } + \ No newline at end of file diff --git a/tests/baselines/reference/classMemberInitializerScoping2(target=esnext,usedefineforclassfields=false).js b/tests/baselines/reference/classMemberInitializerScoping2(target=esnext,usedefineforclassfields=false).js new file mode 100644 index 0000000000000..9591c174fc945 --- /dev/null +++ b/tests/baselines/reference/classMemberInitializerScoping2(target=esnext,usedefineforclassfields=false).js @@ -0,0 +1,15 @@ +//// [classMemberInitializerScoping2.ts] +const x = 1 +class C { + p = x + constructor(x: string) { } +} + + +//// [classMemberInitializerScoping2.js] +const x = 1; +class C { + constructor(x) { + this.p = x; + } +} diff --git a/tests/baselines/reference/classMemberInitializerScoping2(target=esnext,usedefineforclassfields=false).symbols b/tests/baselines/reference/classMemberInitializerScoping2(target=esnext,usedefineforclassfields=false).symbols new file mode 100644 index 0000000000000..78c02088261dd --- /dev/null +++ b/tests/baselines/reference/classMemberInitializerScoping2(target=esnext,usedefineforclassfields=false).symbols @@ -0,0 +1,14 @@ +=== tests/cases/compiler/classMemberInitializerScoping2.ts === +const x = 1 +>x : Symbol(x, Decl(classMemberInitializerScoping2.ts, 0, 5)) + +class C { +>C : Symbol(C, Decl(classMemberInitializerScoping2.ts, 0, 11)) + + p = x +>p : Symbol(C.p, Decl(classMemberInitializerScoping2.ts, 1, 9)) + + constructor(x: string) { } +>x : Symbol(x, Decl(classMemberInitializerScoping2.ts, 3, 16)) +} + diff --git a/tests/baselines/reference/classMemberInitializerScoping2(target=esnext,usedefineforclassfields=false).types b/tests/baselines/reference/classMemberInitializerScoping2(target=esnext,usedefineforclassfields=false).types new file mode 100644 index 0000000000000..20cff56773ba7 --- /dev/null +++ b/tests/baselines/reference/classMemberInitializerScoping2(target=esnext,usedefineforclassfields=false).types @@ -0,0 +1,16 @@ +=== tests/cases/compiler/classMemberInitializerScoping2.ts === +const x = 1 +>x : 1 +>1 : 1 + +class C { +>C : C + + p = x +>p : any +>x : any + + constructor(x: string) { } +>x : string +} + diff --git a/tests/baselines/reference/classMemberInitializerScoping2(target=esnext,usedefineforclassfields=true).js b/tests/baselines/reference/classMemberInitializerScoping2(target=esnext,usedefineforclassfields=true).js new file mode 100644 index 0000000000000..2d008f66474ab --- /dev/null +++ b/tests/baselines/reference/classMemberInitializerScoping2(target=esnext,usedefineforclassfields=true).js @@ -0,0 +1,14 @@ +//// [classMemberInitializerScoping2.ts] +const x = 1 +class C { + p = x + constructor(x: string) { } +} + + +//// [classMemberInitializerScoping2.js] +const x = 1; +class C { + p = x; + constructor(x) { } +} diff --git a/tests/baselines/reference/classMemberInitializerScoping2(target=esnext,usedefineforclassfields=true).symbols b/tests/baselines/reference/classMemberInitializerScoping2(target=esnext,usedefineforclassfields=true).symbols new file mode 100644 index 0000000000000..cf486c1e6f17f --- /dev/null +++ b/tests/baselines/reference/classMemberInitializerScoping2(target=esnext,usedefineforclassfields=true).symbols @@ -0,0 +1,15 @@ +=== tests/cases/compiler/classMemberInitializerScoping2.ts === +const x = 1 +>x : Symbol(x, Decl(classMemberInitializerScoping2.ts, 0, 5)) + +class C { +>C : Symbol(C, Decl(classMemberInitializerScoping2.ts, 0, 11)) + + p = x +>p : Symbol(C.p, Decl(classMemberInitializerScoping2.ts, 1, 9)) +>x : Symbol(x, Decl(classMemberInitializerScoping2.ts, 0, 5)) + + constructor(x: string) { } +>x : Symbol(x, Decl(classMemberInitializerScoping2.ts, 3, 16)) +} + diff --git a/tests/baselines/reference/classMemberInitializerScoping2(target=esnext,usedefineforclassfields=true).types b/tests/baselines/reference/classMemberInitializerScoping2(target=esnext,usedefineforclassfields=true).types new file mode 100644 index 0000000000000..9e045ca57e078 --- /dev/null +++ b/tests/baselines/reference/classMemberInitializerScoping2(target=esnext,usedefineforclassfields=true).types @@ -0,0 +1,16 @@ +=== tests/cases/compiler/classMemberInitializerScoping2.ts === +const x = 1 +>x : 1 +>1 : 1 + +class C { +>C : C + + p = x +>p : number +>x : 1 + + constructor(x: string) { } +>x : string +} + diff --git a/tests/cases/compiler/classMemberInitializerScoping2.ts b/tests/cases/compiler/classMemberInitializerScoping2.ts new file mode 100644 index 0000000000000..583d9f03aae21 --- /dev/null +++ b/tests/cases/compiler/classMemberInitializerScoping2.ts @@ -0,0 +1,8 @@ +// @target: es2017,esnext +// @useDefineForClassFields: true,false + +const x = 1 +class C { + p = x + constructor(x: string) { } +}