diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index f1324425367bb..b3cdf4600c67c 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -274,6 +274,7 @@ import { getEmitModuleKind, getEmitModuleResolutionKind, getEmitScriptTarget, + getEmitStandardClassFields, getEnclosingBlockScopeContainer, getEnclosingContainer, getEntityNameFromTypeNode, @@ -1434,6 +1435,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { var moduleKind = getEmitModuleKind(compilerOptions); var legacyDecorators = !!compilerOptions.experimentalDecorators; var useDefineForClassFields = getUseDefineForClassFields(compilerOptions); + var emitStandardClassFields = getEmitStandardClassFields(compilerOptions); var allowSyntheticDefaultImports = getAllowSyntheticDefaultImports(compilerOptions); var strictNullChecks = getStrictOptionValue(compilerOptions, "strictNullChecks"); var strictFunctionTypes = getStrictOptionValue(compilerOptions, "strictFunctionTypes"); @@ -2782,8 +2784,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return !isPropertyImmediatelyReferencedWithinDeclaration(declaration, usage, /*stopAtAnyPropertyDeclaration*/ false); } else if (isParameterPropertyDeclaration(declaration, declaration.parent)) { - // foo = this.bar is illegal in esnext+useDefineForClassFields when bar is a parameter property - return !(getEmitScriptTarget(compilerOptions) === ScriptTarget.ESNext && useDefineForClassFields + // foo = this.bar is illegal in emitStandardClassFields when bar is a parameter property + return !(emitStandardClassFields && getContainingClass(declaration) === getContainingClass(usage) && isUsedInFunctionOrInstanceProperty(usage, declaration)); } @@ -2795,7 +2797,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // 1. inside an export specifier // 2. inside a function // 3. inside an instance property initializer, a reference to a non-instance property - // (except when target: "esnext" and useDefineForClassFields: true and the reference is to a parameter property) + // (except when emitStandardClassFields: true and the reference is to a parameter property) // 4. inside a static property initializer, a reference to a static method in the same class // 5. inside a TS export= declaration (since we will move the export statement during emit to avoid TDZ) // or if usage is in a type context: @@ -2814,7 +2816,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return true; } if (isUsedInFunctionOrInstanceProperty(usage, declaration)) { - if (getEmitScriptTarget(compilerOptions) >= ScriptTarget.ES2022 && useDefineForClassFields + if (emitStandardClassFields && getContainingClass(declaration) && (isPropertyDeclaration(declaration) || isParameterPropertyDeclaration(declaration, declaration.parent))) { return !isPropertyImmediatelyReferencedWithinDeclaration(declaration, usage, /*stopAtAnyPropertyDeclaration*/ true); @@ -2971,7 +2973,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { case SyntaxKind.PropertyDeclaration: // static properties in classes introduce temporary variables if (hasStaticModifier(node)) { - return target < ScriptTarget.ESNext || !useDefineForClassFields; + return !emitStandardClassFields; } return requiresScopeChangeWorker((node as PropertyDeclaration).name); default: @@ -3389,10 +3391,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // 1. When result is undefined, after checking for a missing "this." // 2. When result is defined function checkAndReportErrorForInvalidInitializer() { - if (propertyWithInvalidInitializer && !(useDefineForClassFields && getEmitScriptTarget(compilerOptions) >= ScriptTarget.ES2022)) { + if (propertyWithInvalidInitializer && !emitStandardClassFields) { // 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. + // with emitStandardClassFields because the scope semantics are different. error(errorLocation, errorLocation && propertyWithInvalidInitializer.type && textRangeContainsPositionInclusive(propertyWithInvalidInitializer.type, errorLocation.pos) ? Diagnostics.Type_of_instance_member_variable_0_cannot_reference_identifier_1_declared_in_the_constructor @@ -31739,7 +31741,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { && !(isAccessExpression(node) && isAccessExpression(node.expression)) && !isBlockScopedNameDeclaredBeforeUse(valueDeclaration, right) && !(isMethodDeclaration(valueDeclaration) && getCombinedModifierFlagsCached(valueDeclaration) & ModifierFlags.Static) - && (compilerOptions.useDefineForClassFields || !isPropertyDeclaredInAncestorClass(prop))) { + && (useDefineForClassFields || !isPropertyDeclaredInAncestorClass(prop))) { diagnosticMessage = error(right, Diagnostics.Property_0_is_used_before_its_initialization, declarationName); } else if (valueDeclaration.kind === SyntaxKind.ClassDeclaration && @@ -38429,7 +38431,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { case "length": case "caller": case "arguments": - if (compilerOptions.useDefineForClassFields) { + if (useDefineForClassFields) { break; } // fall through @@ -38634,7 +38636,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // or the containing class declares instance member variables with initializers. const superCallShouldBeRootLevel = - (getEmitScriptTarget(compilerOptions) !== ScriptTarget.ESNext || !useDefineForClassFields) && + !emitStandardClassFields && (some((node.parent as ClassDeclaration).members, isInstancePropertyWithInitializerOrPrivateIdentifierProperty) || some(node.parameters, p => hasSyntacticModifier(p, ModifierFlags.ParameterPropertyModifier))); @@ -42900,7 +42902,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { !legacyDecorators && languageVersion < ScriptTarget.ESNext && classOrConstructorParameterIsDecorated(/*useLegacyDecorators*/ false, node); const willTransformPrivateElementsOrClassStaticBlocks = languageVersion <= ScriptTarget.ES2022; - const willTransformInitializers = !useDefineForClassFields || languageVersion < ScriptTarget.ES2022; + const willTransformInitializers = !emitStandardClassFields; if (willTransformStaticElementsOfDecoratedClass || willTransformPrivateElementsOrClassStaticBlocks) { for (const member of node.members) { if (willTransformStaticElementsOfDecoratedClass && classElementOrClassElementParameterIsDecorated(/*useLegacyDecorators*/ false, member, node)) { diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 251f8a4f16306..320c5e631d860 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -8653,6 +8653,11 @@ export function getUseDefineForClassFields(compilerOptions: CompilerOptions): bo return compilerOptions.useDefineForClassFields === undefined ? getEmitScriptTarget(compilerOptions) >= ScriptTarget.ES2022 : compilerOptions.useDefineForClassFields; } +/** @internal */ +export function getEmitStandardClassFields(compilerOptions: CompilerOptions) { + return compilerOptions.useDefineForClassFields !== false && getEmitScriptTarget(compilerOptions) >= ScriptTarget.ES2022; +} + /** @internal */ export function compilerOptionsAffectSemanticDiagnostics(newOptions: CompilerOptions, oldOptions: CompilerOptions): boolean { return optionsHaveChanges(oldOptions, newOptions, semanticDiagnosticsOptionDeclarations); diff --git a/tests/baselines/reference/assignParameterPropertyToPropertyDeclarationES2022.errors.txt b/tests/baselines/reference/assignParameterPropertyToPropertyDeclarationES2022.errors.txt index 59ee9f7409d20..ac6d34a8470f6 100644 --- a/tests/baselines/reference/assignParameterPropertyToPropertyDeclarationES2022.errors.txt +++ b/tests/baselines/reference/assignParameterPropertyToPropertyDeclarationES2022.errors.txt @@ -2,9 +2,10 @@ assignParameterPropertyToPropertyDeclarationES2022.ts(2,16): error TS2729: Prope assignParameterPropertyToPropertyDeclarationES2022.ts(3,16): error TS2729: Property 'foo' is used before its initialization. assignParameterPropertyToPropertyDeclarationES2022.ts(6,19): error TS2729: Property 'm3' is used before its initialization. assignParameterPropertyToPropertyDeclarationES2022.ts(12,17): error TS2729: Property 'baz' is used before its initialization. +assignParameterPropertyToPropertyDeclarationES2022.ts(13,16): error TS2729: Property 'foo' is used before its initialization. -==== assignParameterPropertyToPropertyDeclarationES2022.ts (4 errors) ==== +==== assignParameterPropertyToPropertyDeclarationES2022.ts (5 errors) ==== class C { qux = this.bar // should error ~~~ @@ -30,6 +31,9 @@ assignParameterPropertyToPropertyDeclarationES2022.ts(12,17): error TS2729: Prop !!! error TS2729: Property 'baz' is used before its initialization. !!! related TS2728 assignParameterPropertyToPropertyDeclarationES2022.ts:13:5: 'baz' is declared here. baz = this.foo; // should error + ~~~ +!!! error TS2729: Property 'foo' is used before its initialization. +!!! related TS2728 assignParameterPropertyToPropertyDeclarationES2022.ts:11:17: 'foo' is declared here. quid = this.baz // ok m2() { this.foo // ok diff --git a/tests/baselines/reference/initializationOrdering1(target=es2021,usedefineforclassfields=false).js b/tests/baselines/reference/initializationOrdering1(target=es2021,usedefineforclassfields=false).js new file mode 100644 index 0000000000000..9f2f51960ca62 --- /dev/null +++ b/tests/baselines/reference/initializationOrdering1(target=es2021,usedefineforclassfields=false).js @@ -0,0 +1,33 @@ +//// [tests/cases/conformance/classes/propertyMemberDeclarations/initializationOrdering1.ts] //// + +//// [initializationOrdering1.ts] +class Helper { + create(): boolean { + return true + } +} + +export class Broken { + constructor(readonly facade: Helper) { + console.log(this.bug) + } + bug = this.facade.create() + +} + +new Broken(new Helper) + +//// [initializationOrdering1.js] +class Helper { + create() { + return true; + } +} +export class Broken { + constructor(facade) { + this.facade = facade; + this.bug = this.facade.create(); + console.log(this.bug); + } +} +new Broken(new Helper); diff --git a/tests/baselines/reference/initializationOrdering1(target=es2021,usedefineforclassfields=false).symbols b/tests/baselines/reference/initializationOrdering1(target=es2021,usedefineforclassfields=false).symbols new file mode 100644 index 0000000000000..be3a543112930 --- /dev/null +++ b/tests/baselines/reference/initializationOrdering1(target=es2021,usedefineforclassfields=false).symbols @@ -0,0 +1,42 @@ +//// [tests/cases/conformance/classes/propertyMemberDeclarations/initializationOrdering1.ts] //// + +=== initializationOrdering1.ts === +class Helper { +>Helper : Symbol(Helper, Decl(initializationOrdering1.ts, 0, 0)) + + create(): boolean { +>create : Symbol(Helper.create, Decl(initializationOrdering1.ts, 0, 14)) + + return true + } +} + +export class Broken { +>Broken : Symbol(Broken, Decl(initializationOrdering1.ts, 4, 1)) + + constructor(readonly facade: Helper) { +>facade : Symbol(Broken.facade, Decl(initializationOrdering1.ts, 7, 16)) +>Helper : Symbol(Helper, Decl(initializationOrdering1.ts, 0, 0)) + + console.log(this.bug) +>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.bug : Symbol(Broken.bug, Decl(initializationOrdering1.ts, 9, 5)) +>this : Symbol(Broken, Decl(initializationOrdering1.ts, 4, 1)) +>bug : Symbol(Broken.bug, Decl(initializationOrdering1.ts, 9, 5)) + } + bug = this.facade.create() +>bug : Symbol(Broken.bug, Decl(initializationOrdering1.ts, 9, 5)) +>this.facade.create : Symbol(Helper.create, Decl(initializationOrdering1.ts, 0, 14)) +>this.facade : Symbol(Broken.facade, Decl(initializationOrdering1.ts, 7, 16)) +>this : Symbol(Broken, Decl(initializationOrdering1.ts, 4, 1)) +>facade : Symbol(Broken.facade, Decl(initializationOrdering1.ts, 7, 16)) +>create : Symbol(Helper.create, Decl(initializationOrdering1.ts, 0, 14)) + +} + +new Broken(new Helper) +>Broken : Symbol(Broken, Decl(initializationOrdering1.ts, 4, 1)) +>Helper : Symbol(Helper, Decl(initializationOrdering1.ts, 0, 0)) + diff --git a/tests/baselines/reference/initializationOrdering1(target=es2021,usedefineforclassfields=false).types b/tests/baselines/reference/initializationOrdering1(target=es2021,usedefineforclassfields=false).types new file mode 100644 index 0000000000000..1444366790e82 --- /dev/null +++ b/tests/baselines/reference/initializationOrdering1(target=es2021,usedefineforclassfields=false).types @@ -0,0 +1,46 @@ +//// [tests/cases/conformance/classes/propertyMemberDeclarations/initializationOrdering1.ts] //// + +=== initializationOrdering1.ts === +class Helper { +>Helper : Helper + + create(): boolean { +>create : () => boolean + + return true +>true : true + } +} + +export class Broken { +>Broken : Broken + + constructor(readonly facade: Helper) { +>facade : Helper + + console.log(this.bug) +>console.log(this.bug) : void +>console.log : (...data: any[]) => void +>console : Console +>log : (...data: any[]) => void +>this.bug : boolean +>this : this +>bug : boolean + } + bug = this.facade.create() +>bug : boolean +>this.facade.create() : boolean +>this.facade.create : () => boolean +>this.facade : Helper +>this : this +>facade : Helper +>create : () => boolean + +} + +new Broken(new Helper) +>new Broken(new Helper) : Broken +>Broken : typeof Broken +>new Helper : Helper +>Helper : typeof Helper + diff --git a/tests/baselines/reference/initializationOrdering1(target=es2021,usedefineforclassfields=true).js b/tests/baselines/reference/initializationOrdering1(target=es2021,usedefineforclassfields=true).js new file mode 100644 index 0000000000000..88209b7c7e023 --- /dev/null +++ b/tests/baselines/reference/initializationOrdering1(target=es2021,usedefineforclassfields=true).js @@ -0,0 +1,43 @@ +//// [tests/cases/conformance/classes/propertyMemberDeclarations/initializationOrdering1.ts] //// + +//// [initializationOrdering1.ts] +class Helper { + create(): boolean { + return true + } +} + +export class Broken { + constructor(readonly facade: Helper) { + console.log(this.bug) + } + bug = this.facade.create() + +} + +new Broken(new Helper) + +//// [initializationOrdering1.js] +class Helper { + create() { + return true; + } +} +export class Broken { + constructor(facade) { + Object.defineProperty(this, "facade", { + enumerable: true, + configurable: true, + writable: true, + value: facade + }); + Object.defineProperty(this, "bug", { + enumerable: true, + configurable: true, + writable: true, + value: this.facade.create() + }); + console.log(this.bug); + } +} +new Broken(new Helper); diff --git a/tests/baselines/reference/initializationOrdering1(target=es2021,usedefineforclassfields=true).symbols b/tests/baselines/reference/initializationOrdering1(target=es2021,usedefineforclassfields=true).symbols new file mode 100644 index 0000000000000..be3a543112930 --- /dev/null +++ b/tests/baselines/reference/initializationOrdering1(target=es2021,usedefineforclassfields=true).symbols @@ -0,0 +1,42 @@ +//// [tests/cases/conformance/classes/propertyMemberDeclarations/initializationOrdering1.ts] //// + +=== initializationOrdering1.ts === +class Helper { +>Helper : Symbol(Helper, Decl(initializationOrdering1.ts, 0, 0)) + + create(): boolean { +>create : Symbol(Helper.create, Decl(initializationOrdering1.ts, 0, 14)) + + return true + } +} + +export class Broken { +>Broken : Symbol(Broken, Decl(initializationOrdering1.ts, 4, 1)) + + constructor(readonly facade: Helper) { +>facade : Symbol(Broken.facade, Decl(initializationOrdering1.ts, 7, 16)) +>Helper : Symbol(Helper, Decl(initializationOrdering1.ts, 0, 0)) + + console.log(this.bug) +>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.bug : Symbol(Broken.bug, Decl(initializationOrdering1.ts, 9, 5)) +>this : Symbol(Broken, Decl(initializationOrdering1.ts, 4, 1)) +>bug : Symbol(Broken.bug, Decl(initializationOrdering1.ts, 9, 5)) + } + bug = this.facade.create() +>bug : Symbol(Broken.bug, Decl(initializationOrdering1.ts, 9, 5)) +>this.facade.create : Symbol(Helper.create, Decl(initializationOrdering1.ts, 0, 14)) +>this.facade : Symbol(Broken.facade, Decl(initializationOrdering1.ts, 7, 16)) +>this : Symbol(Broken, Decl(initializationOrdering1.ts, 4, 1)) +>facade : Symbol(Broken.facade, Decl(initializationOrdering1.ts, 7, 16)) +>create : Symbol(Helper.create, Decl(initializationOrdering1.ts, 0, 14)) + +} + +new Broken(new Helper) +>Broken : Symbol(Broken, Decl(initializationOrdering1.ts, 4, 1)) +>Helper : Symbol(Helper, Decl(initializationOrdering1.ts, 0, 0)) + diff --git a/tests/baselines/reference/initializationOrdering1(target=es2021,usedefineforclassfields=true).types b/tests/baselines/reference/initializationOrdering1(target=es2021,usedefineforclassfields=true).types new file mode 100644 index 0000000000000..1444366790e82 --- /dev/null +++ b/tests/baselines/reference/initializationOrdering1(target=es2021,usedefineforclassfields=true).types @@ -0,0 +1,46 @@ +//// [tests/cases/conformance/classes/propertyMemberDeclarations/initializationOrdering1.ts] //// + +=== initializationOrdering1.ts === +class Helper { +>Helper : Helper + + create(): boolean { +>create : () => boolean + + return true +>true : true + } +} + +export class Broken { +>Broken : Broken + + constructor(readonly facade: Helper) { +>facade : Helper + + console.log(this.bug) +>console.log(this.bug) : void +>console.log : (...data: any[]) => void +>console : Console +>log : (...data: any[]) => void +>this.bug : boolean +>this : this +>bug : boolean + } + bug = this.facade.create() +>bug : boolean +>this.facade.create() : boolean +>this.facade.create : () => boolean +>this.facade : Helper +>this : this +>facade : Helper +>create : () => boolean + +} + +new Broken(new Helper) +>new Broken(new Helper) : Broken +>Broken : typeof Broken +>new Helper : Helper +>Helper : typeof Helper + diff --git a/tests/baselines/reference/initializationOrdering1(target=es2022,usedefineforclassfields=false).js b/tests/baselines/reference/initializationOrdering1(target=es2022,usedefineforclassfields=false).js new file mode 100644 index 0000000000000..9f2f51960ca62 --- /dev/null +++ b/tests/baselines/reference/initializationOrdering1(target=es2022,usedefineforclassfields=false).js @@ -0,0 +1,33 @@ +//// [tests/cases/conformance/classes/propertyMemberDeclarations/initializationOrdering1.ts] //// + +//// [initializationOrdering1.ts] +class Helper { + create(): boolean { + return true + } +} + +export class Broken { + constructor(readonly facade: Helper) { + console.log(this.bug) + } + bug = this.facade.create() + +} + +new Broken(new Helper) + +//// [initializationOrdering1.js] +class Helper { + create() { + return true; + } +} +export class Broken { + constructor(facade) { + this.facade = facade; + this.bug = this.facade.create(); + console.log(this.bug); + } +} +new Broken(new Helper); diff --git a/tests/baselines/reference/initializationOrdering1(target=es2022,usedefineforclassfields=false).symbols b/tests/baselines/reference/initializationOrdering1(target=es2022,usedefineforclassfields=false).symbols new file mode 100644 index 0000000000000..be3a543112930 --- /dev/null +++ b/tests/baselines/reference/initializationOrdering1(target=es2022,usedefineforclassfields=false).symbols @@ -0,0 +1,42 @@ +//// [tests/cases/conformance/classes/propertyMemberDeclarations/initializationOrdering1.ts] //// + +=== initializationOrdering1.ts === +class Helper { +>Helper : Symbol(Helper, Decl(initializationOrdering1.ts, 0, 0)) + + create(): boolean { +>create : Symbol(Helper.create, Decl(initializationOrdering1.ts, 0, 14)) + + return true + } +} + +export class Broken { +>Broken : Symbol(Broken, Decl(initializationOrdering1.ts, 4, 1)) + + constructor(readonly facade: Helper) { +>facade : Symbol(Broken.facade, Decl(initializationOrdering1.ts, 7, 16)) +>Helper : Symbol(Helper, Decl(initializationOrdering1.ts, 0, 0)) + + console.log(this.bug) +>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.bug : Symbol(Broken.bug, Decl(initializationOrdering1.ts, 9, 5)) +>this : Symbol(Broken, Decl(initializationOrdering1.ts, 4, 1)) +>bug : Symbol(Broken.bug, Decl(initializationOrdering1.ts, 9, 5)) + } + bug = this.facade.create() +>bug : Symbol(Broken.bug, Decl(initializationOrdering1.ts, 9, 5)) +>this.facade.create : Symbol(Helper.create, Decl(initializationOrdering1.ts, 0, 14)) +>this.facade : Symbol(Broken.facade, Decl(initializationOrdering1.ts, 7, 16)) +>this : Symbol(Broken, Decl(initializationOrdering1.ts, 4, 1)) +>facade : Symbol(Broken.facade, Decl(initializationOrdering1.ts, 7, 16)) +>create : Symbol(Helper.create, Decl(initializationOrdering1.ts, 0, 14)) + +} + +new Broken(new Helper) +>Broken : Symbol(Broken, Decl(initializationOrdering1.ts, 4, 1)) +>Helper : Symbol(Helper, Decl(initializationOrdering1.ts, 0, 0)) + diff --git a/tests/baselines/reference/initializationOrdering1(target=es2022,usedefineforclassfields=false).types b/tests/baselines/reference/initializationOrdering1(target=es2022,usedefineforclassfields=false).types new file mode 100644 index 0000000000000..1444366790e82 --- /dev/null +++ b/tests/baselines/reference/initializationOrdering1(target=es2022,usedefineforclassfields=false).types @@ -0,0 +1,46 @@ +//// [tests/cases/conformance/classes/propertyMemberDeclarations/initializationOrdering1.ts] //// + +=== initializationOrdering1.ts === +class Helper { +>Helper : Helper + + create(): boolean { +>create : () => boolean + + return true +>true : true + } +} + +export class Broken { +>Broken : Broken + + constructor(readonly facade: Helper) { +>facade : Helper + + console.log(this.bug) +>console.log(this.bug) : void +>console.log : (...data: any[]) => void +>console : Console +>log : (...data: any[]) => void +>this.bug : boolean +>this : this +>bug : boolean + } + bug = this.facade.create() +>bug : boolean +>this.facade.create() : boolean +>this.facade.create : () => boolean +>this.facade : Helper +>this : this +>facade : Helper +>create : () => boolean + +} + +new Broken(new Helper) +>new Broken(new Helper) : Broken +>Broken : typeof Broken +>new Helper : Helper +>Helper : typeof Helper + diff --git a/tests/baselines/reference/initializationOrdering1(target=es2022,usedefineforclassfields=true).errors.txt b/tests/baselines/reference/initializationOrdering1(target=es2022,usedefineforclassfields=true).errors.txt new file mode 100644 index 0000000000000..a69a0dfb78a06 --- /dev/null +++ b/tests/baselines/reference/initializationOrdering1(target=es2022,usedefineforclassfields=true).errors.txt @@ -0,0 +1,22 @@ +initializationOrdering1.ts(11,16): error TS2729: Property 'facade' is used before its initialization. + + +==== initializationOrdering1.ts (1 errors) ==== + class Helper { + create(): boolean { + return true + } + } + + export class Broken { + constructor(readonly facade: Helper) { + console.log(this.bug) + } + bug = this.facade.create() + ~~~~~~ +!!! error TS2729: Property 'facade' is used before its initialization. +!!! related TS2728 initializationOrdering1.ts:8:17: 'facade' is declared here. + + } + + new Broken(new Helper) \ No newline at end of file diff --git a/tests/baselines/reference/initializationOrdering1(target=es2022,usedefineforclassfields=true).js b/tests/baselines/reference/initializationOrdering1(target=es2022,usedefineforclassfields=true).js new file mode 100644 index 0000000000000..205dee2520ab8 --- /dev/null +++ b/tests/baselines/reference/initializationOrdering1(target=es2022,usedefineforclassfields=true).js @@ -0,0 +1,34 @@ +//// [tests/cases/conformance/classes/propertyMemberDeclarations/initializationOrdering1.ts] //// + +//// [initializationOrdering1.ts] +class Helper { + create(): boolean { + return true + } +} + +export class Broken { + constructor(readonly facade: Helper) { + console.log(this.bug) + } + bug = this.facade.create() + +} + +new Broken(new Helper) + +//// [initializationOrdering1.js] +class Helper { + create() { + return true; + } +} +export class Broken { + facade; + constructor(facade) { + this.facade = facade; + console.log(this.bug); + } + bug = this.facade.create(); +} +new Broken(new Helper); diff --git a/tests/baselines/reference/initializationOrdering1(target=es2022,usedefineforclassfields=true).symbols b/tests/baselines/reference/initializationOrdering1(target=es2022,usedefineforclassfields=true).symbols new file mode 100644 index 0000000000000..be3a543112930 --- /dev/null +++ b/tests/baselines/reference/initializationOrdering1(target=es2022,usedefineforclassfields=true).symbols @@ -0,0 +1,42 @@ +//// [tests/cases/conformance/classes/propertyMemberDeclarations/initializationOrdering1.ts] //// + +=== initializationOrdering1.ts === +class Helper { +>Helper : Symbol(Helper, Decl(initializationOrdering1.ts, 0, 0)) + + create(): boolean { +>create : Symbol(Helper.create, Decl(initializationOrdering1.ts, 0, 14)) + + return true + } +} + +export class Broken { +>Broken : Symbol(Broken, Decl(initializationOrdering1.ts, 4, 1)) + + constructor(readonly facade: Helper) { +>facade : Symbol(Broken.facade, Decl(initializationOrdering1.ts, 7, 16)) +>Helper : Symbol(Helper, Decl(initializationOrdering1.ts, 0, 0)) + + console.log(this.bug) +>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.bug : Symbol(Broken.bug, Decl(initializationOrdering1.ts, 9, 5)) +>this : Symbol(Broken, Decl(initializationOrdering1.ts, 4, 1)) +>bug : Symbol(Broken.bug, Decl(initializationOrdering1.ts, 9, 5)) + } + bug = this.facade.create() +>bug : Symbol(Broken.bug, Decl(initializationOrdering1.ts, 9, 5)) +>this.facade.create : Symbol(Helper.create, Decl(initializationOrdering1.ts, 0, 14)) +>this.facade : Symbol(Broken.facade, Decl(initializationOrdering1.ts, 7, 16)) +>this : Symbol(Broken, Decl(initializationOrdering1.ts, 4, 1)) +>facade : Symbol(Broken.facade, Decl(initializationOrdering1.ts, 7, 16)) +>create : Symbol(Helper.create, Decl(initializationOrdering1.ts, 0, 14)) + +} + +new Broken(new Helper) +>Broken : Symbol(Broken, Decl(initializationOrdering1.ts, 4, 1)) +>Helper : Symbol(Helper, Decl(initializationOrdering1.ts, 0, 0)) + diff --git a/tests/baselines/reference/initializationOrdering1(target=es2022,usedefineforclassfields=true).types b/tests/baselines/reference/initializationOrdering1(target=es2022,usedefineforclassfields=true).types new file mode 100644 index 0000000000000..1444366790e82 --- /dev/null +++ b/tests/baselines/reference/initializationOrdering1(target=es2022,usedefineforclassfields=true).types @@ -0,0 +1,46 @@ +//// [tests/cases/conformance/classes/propertyMemberDeclarations/initializationOrdering1.ts] //// + +=== initializationOrdering1.ts === +class Helper { +>Helper : Helper + + create(): boolean { +>create : () => boolean + + return true +>true : true + } +} + +export class Broken { +>Broken : Broken + + constructor(readonly facade: Helper) { +>facade : Helper + + console.log(this.bug) +>console.log(this.bug) : void +>console.log : (...data: any[]) => void +>console : Console +>log : (...data: any[]) => void +>this.bug : boolean +>this : this +>bug : boolean + } + bug = this.facade.create() +>bug : boolean +>this.facade.create() : boolean +>this.facade.create : () => boolean +>this.facade : Helper +>this : this +>facade : Helper +>create : () => boolean + +} + +new Broken(new Helper) +>new Broken(new Helper) : Broken +>Broken : typeof Broken +>new Helper : Helper +>Helper : typeof Helper + diff --git a/tests/baselines/reference/initializationOrdering1(target=esnext,usedefineforclassfields=false).js b/tests/baselines/reference/initializationOrdering1(target=esnext,usedefineforclassfields=false).js new file mode 100644 index 0000000000000..9f2f51960ca62 --- /dev/null +++ b/tests/baselines/reference/initializationOrdering1(target=esnext,usedefineforclassfields=false).js @@ -0,0 +1,33 @@ +//// [tests/cases/conformance/classes/propertyMemberDeclarations/initializationOrdering1.ts] //// + +//// [initializationOrdering1.ts] +class Helper { + create(): boolean { + return true + } +} + +export class Broken { + constructor(readonly facade: Helper) { + console.log(this.bug) + } + bug = this.facade.create() + +} + +new Broken(new Helper) + +//// [initializationOrdering1.js] +class Helper { + create() { + return true; + } +} +export class Broken { + constructor(facade) { + this.facade = facade; + this.bug = this.facade.create(); + console.log(this.bug); + } +} +new Broken(new Helper); diff --git a/tests/baselines/reference/initializationOrdering1(target=esnext,usedefineforclassfields=false).symbols b/tests/baselines/reference/initializationOrdering1(target=esnext,usedefineforclassfields=false).symbols new file mode 100644 index 0000000000000..be3a543112930 --- /dev/null +++ b/tests/baselines/reference/initializationOrdering1(target=esnext,usedefineforclassfields=false).symbols @@ -0,0 +1,42 @@ +//// [tests/cases/conformance/classes/propertyMemberDeclarations/initializationOrdering1.ts] //// + +=== initializationOrdering1.ts === +class Helper { +>Helper : Symbol(Helper, Decl(initializationOrdering1.ts, 0, 0)) + + create(): boolean { +>create : Symbol(Helper.create, Decl(initializationOrdering1.ts, 0, 14)) + + return true + } +} + +export class Broken { +>Broken : Symbol(Broken, Decl(initializationOrdering1.ts, 4, 1)) + + constructor(readonly facade: Helper) { +>facade : Symbol(Broken.facade, Decl(initializationOrdering1.ts, 7, 16)) +>Helper : Symbol(Helper, Decl(initializationOrdering1.ts, 0, 0)) + + console.log(this.bug) +>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.bug : Symbol(Broken.bug, Decl(initializationOrdering1.ts, 9, 5)) +>this : Symbol(Broken, Decl(initializationOrdering1.ts, 4, 1)) +>bug : Symbol(Broken.bug, Decl(initializationOrdering1.ts, 9, 5)) + } + bug = this.facade.create() +>bug : Symbol(Broken.bug, Decl(initializationOrdering1.ts, 9, 5)) +>this.facade.create : Symbol(Helper.create, Decl(initializationOrdering1.ts, 0, 14)) +>this.facade : Symbol(Broken.facade, Decl(initializationOrdering1.ts, 7, 16)) +>this : Symbol(Broken, Decl(initializationOrdering1.ts, 4, 1)) +>facade : Symbol(Broken.facade, Decl(initializationOrdering1.ts, 7, 16)) +>create : Symbol(Helper.create, Decl(initializationOrdering1.ts, 0, 14)) + +} + +new Broken(new Helper) +>Broken : Symbol(Broken, Decl(initializationOrdering1.ts, 4, 1)) +>Helper : Symbol(Helper, Decl(initializationOrdering1.ts, 0, 0)) + diff --git a/tests/baselines/reference/initializationOrdering1(target=esnext,usedefineforclassfields=false).types b/tests/baselines/reference/initializationOrdering1(target=esnext,usedefineforclassfields=false).types new file mode 100644 index 0000000000000..1444366790e82 --- /dev/null +++ b/tests/baselines/reference/initializationOrdering1(target=esnext,usedefineforclassfields=false).types @@ -0,0 +1,46 @@ +//// [tests/cases/conformance/classes/propertyMemberDeclarations/initializationOrdering1.ts] //// + +=== initializationOrdering1.ts === +class Helper { +>Helper : Helper + + create(): boolean { +>create : () => boolean + + return true +>true : true + } +} + +export class Broken { +>Broken : Broken + + constructor(readonly facade: Helper) { +>facade : Helper + + console.log(this.bug) +>console.log(this.bug) : void +>console.log : (...data: any[]) => void +>console : Console +>log : (...data: any[]) => void +>this.bug : boolean +>this : this +>bug : boolean + } + bug = this.facade.create() +>bug : boolean +>this.facade.create() : boolean +>this.facade.create : () => boolean +>this.facade : Helper +>this : this +>facade : Helper +>create : () => boolean + +} + +new Broken(new Helper) +>new Broken(new Helper) : Broken +>Broken : typeof Broken +>new Helper : Helper +>Helper : typeof Helper + diff --git a/tests/baselines/reference/initializationOrdering1(target=esnext,usedefineforclassfields=true).errors.txt b/tests/baselines/reference/initializationOrdering1(target=esnext,usedefineforclassfields=true).errors.txt new file mode 100644 index 0000000000000..a69a0dfb78a06 --- /dev/null +++ b/tests/baselines/reference/initializationOrdering1(target=esnext,usedefineforclassfields=true).errors.txt @@ -0,0 +1,22 @@ +initializationOrdering1.ts(11,16): error TS2729: Property 'facade' is used before its initialization. + + +==== initializationOrdering1.ts (1 errors) ==== + class Helper { + create(): boolean { + return true + } + } + + export class Broken { + constructor(readonly facade: Helper) { + console.log(this.bug) + } + bug = this.facade.create() + ~~~~~~ +!!! error TS2729: Property 'facade' is used before its initialization. +!!! related TS2728 initializationOrdering1.ts:8:17: 'facade' is declared here. + + } + + new Broken(new Helper) \ No newline at end of file diff --git a/tests/baselines/reference/initializationOrdering1(target=esnext,usedefineforclassfields=true).js b/tests/baselines/reference/initializationOrdering1(target=esnext,usedefineforclassfields=true).js new file mode 100644 index 0000000000000..205dee2520ab8 --- /dev/null +++ b/tests/baselines/reference/initializationOrdering1(target=esnext,usedefineforclassfields=true).js @@ -0,0 +1,34 @@ +//// [tests/cases/conformance/classes/propertyMemberDeclarations/initializationOrdering1.ts] //// + +//// [initializationOrdering1.ts] +class Helper { + create(): boolean { + return true + } +} + +export class Broken { + constructor(readonly facade: Helper) { + console.log(this.bug) + } + bug = this.facade.create() + +} + +new Broken(new Helper) + +//// [initializationOrdering1.js] +class Helper { + create() { + return true; + } +} +export class Broken { + facade; + constructor(facade) { + this.facade = facade; + console.log(this.bug); + } + bug = this.facade.create(); +} +new Broken(new Helper); diff --git a/tests/baselines/reference/initializationOrdering1(target=esnext,usedefineforclassfields=true).symbols b/tests/baselines/reference/initializationOrdering1(target=esnext,usedefineforclassfields=true).symbols new file mode 100644 index 0000000000000..be3a543112930 --- /dev/null +++ b/tests/baselines/reference/initializationOrdering1(target=esnext,usedefineforclassfields=true).symbols @@ -0,0 +1,42 @@ +//// [tests/cases/conformance/classes/propertyMemberDeclarations/initializationOrdering1.ts] //// + +=== initializationOrdering1.ts === +class Helper { +>Helper : Symbol(Helper, Decl(initializationOrdering1.ts, 0, 0)) + + create(): boolean { +>create : Symbol(Helper.create, Decl(initializationOrdering1.ts, 0, 14)) + + return true + } +} + +export class Broken { +>Broken : Symbol(Broken, Decl(initializationOrdering1.ts, 4, 1)) + + constructor(readonly facade: Helper) { +>facade : Symbol(Broken.facade, Decl(initializationOrdering1.ts, 7, 16)) +>Helper : Symbol(Helper, Decl(initializationOrdering1.ts, 0, 0)) + + console.log(this.bug) +>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.bug : Symbol(Broken.bug, Decl(initializationOrdering1.ts, 9, 5)) +>this : Symbol(Broken, Decl(initializationOrdering1.ts, 4, 1)) +>bug : Symbol(Broken.bug, Decl(initializationOrdering1.ts, 9, 5)) + } + bug = this.facade.create() +>bug : Symbol(Broken.bug, Decl(initializationOrdering1.ts, 9, 5)) +>this.facade.create : Symbol(Helper.create, Decl(initializationOrdering1.ts, 0, 14)) +>this.facade : Symbol(Broken.facade, Decl(initializationOrdering1.ts, 7, 16)) +>this : Symbol(Broken, Decl(initializationOrdering1.ts, 4, 1)) +>facade : Symbol(Broken.facade, Decl(initializationOrdering1.ts, 7, 16)) +>create : Symbol(Helper.create, Decl(initializationOrdering1.ts, 0, 14)) + +} + +new Broken(new Helper) +>Broken : Symbol(Broken, Decl(initializationOrdering1.ts, 4, 1)) +>Helper : Symbol(Helper, Decl(initializationOrdering1.ts, 0, 0)) + diff --git a/tests/baselines/reference/initializationOrdering1(target=esnext,usedefineforclassfields=true).types b/tests/baselines/reference/initializationOrdering1(target=esnext,usedefineforclassfields=true).types new file mode 100644 index 0000000000000..1444366790e82 --- /dev/null +++ b/tests/baselines/reference/initializationOrdering1(target=esnext,usedefineforclassfields=true).types @@ -0,0 +1,46 @@ +//// [tests/cases/conformance/classes/propertyMemberDeclarations/initializationOrdering1.ts] //// + +=== initializationOrdering1.ts === +class Helper { +>Helper : Helper + + create(): boolean { +>create : () => boolean + + return true +>true : true + } +} + +export class Broken { +>Broken : Broken + + constructor(readonly facade: Helper) { +>facade : Helper + + console.log(this.bug) +>console.log(this.bug) : void +>console.log : (...data: any[]) => void +>console : Console +>log : (...data: any[]) => void +>this.bug : boolean +>this : this +>bug : boolean + } + bug = this.facade.create() +>bug : boolean +>this.facade.create() : boolean +>this.facade.create : () => boolean +>this.facade : Helper +>this : this +>facade : Helper +>create : () => boolean + +} + +new Broken(new Helper) +>new Broken(new Helper) : Broken +>Broken : typeof Broken +>new Helper : Helper +>Helper : typeof Helper + diff --git a/tests/baselines/reference/privateNameBadSuperUseDefineForClassFields(target=es2022).errors.txt b/tests/baselines/reference/privateNameBadSuperUseDefineForClassFields(target=es2022).errors.txt index 26b3664cb6ba0..a887798812842 100644 --- a/tests/baselines/reference/privateNameBadSuperUseDefineForClassFields(target=es2022).errors.txt +++ b/tests/baselines/reference/privateNameBadSuperUseDefineForClassFields(target=es2022).errors.txt @@ -1,21 +1,15 @@ -privateNameBadSuperUseDefineForClassFields.ts(4,3): error TS2376: A 'super' call must be the first statement in the constructor to refer to 'super' or 'this' when a derived class contains initialized properties, parameter properties, or private identifiers. privateNameBadSuperUseDefineForClassFields.ts(5,5): error TS17009: 'super' must be called before accessing 'this' in the constructor of a derived class. -==== privateNameBadSuperUseDefineForClassFields.ts (2 errors) ==== +==== privateNameBadSuperUseDefineForClassFields.ts (1 errors) ==== class B {}; class A extends B { #x; constructor() { - ~~~~~~~~~~~~~~~ this; - ~~~~~~~~~ ~~~~ !!! error TS17009: 'super' must be called before accessing 'this' in the constructor of a derived class. super(); - ~~~~~~~~~~~~ } - ~~~ -!!! error TS2376: A 'super' call must be the first statement in the constructor to refer to 'super' or 'this' when a derived class contains initialized properties, parameter properties, or private identifiers. } \ No newline at end of file diff --git a/tests/cases/conformance/classes/propertyMemberDeclarations/initializationOrdering1.ts b/tests/cases/conformance/classes/propertyMemberDeclarations/initializationOrdering1.ts new file mode 100644 index 0000000000000..fe8afae2d66e2 --- /dev/null +++ b/tests/cases/conformance/classes/propertyMemberDeclarations/initializationOrdering1.ts @@ -0,0 +1,18 @@ +// @target: esnext, es2021, es2022 +// @useDefineForClassFields: true, false + +class Helper { + create(): boolean { + return true + } +} + +export class Broken { + constructor(readonly facade: Helper) { + console.log(this.bug) + } + bug = this.facade.create() + +} + +new Broken(new Helper) \ No newline at end of file