diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 7e935b03c19..8fc36b5ac9e 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -59,6 +59,7 @@ module ts { var mergedSymbols: Symbol[] = []; var symbolLinks: SymbolLinks[] = []; var nodeLinks: NodeLinks[] = []; + var potentialThisCollisions: Node[] = []; var diagnostics: Diagnostic[] = []; var diagnosticsModified: boolean = false; @@ -3210,6 +3211,7 @@ module ts { getNodeLinks(node).resolvedSymbol = symbol; checkCollisionWithCapturedSuperVariable(node, node); + checkCollisionWithCapturedThisVariable(node, node); checkCollisionWithIndexVariableInGeneratedCode(node, node); return getTypeOfSymbol(getExportSymbolOfValueSymbolIfExported(symbol)); @@ -4436,6 +4438,7 @@ module ts { } checkCollisionWithCapturedSuperVariable(node, node.name); + checkCollisionWithCapturedThisVariable(node, node.name); checkCollisionWithArgumentsInGeneratedCode(node); if (program.getCompilerOptions().noImplicitAny && !node.type) { switch (node.kind) { @@ -4970,21 +4973,59 @@ module ts { } } - function checkCollisionWithCapturedSuperVariable(node: Node, name: Identifier) { - if (!(name && name.text === "_super")) { - return; + function needCollisionCheckForIdentifier(node: Node, identifier: Identifier, name: string): boolean { + if (!(identifier && identifier.text === name)) { + return false; } if (node.kind === SyntaxKind.Property || node.kind === SyntaxKind.Method || node.kind === SyntaxKind.GetAccessor || node.kind === SyntaxKind.SetAccessor) { - // it is ok to have member named '_super' - member access is always qualified - return; + // it is ok to have member named '_super' or '_this' - member access is always qualified + return false + } + + if (isInAmbientContext(node)) { + // ambient context - no codegen impact + return false; } if (node.kind === SyntaxKind.Parameter && !(node.parent).body) { // just an overload - no codegen impact + return false; + } + + return true; + } + + function checkCollisionWithCapturedThisVariable(node: Node, name: Identifier): void { + if (!needCollisionCheckForIdentifier(node, name, "_this")) { + return; + } + potentialThisCollisions.push(node); + } + + // this function will run after checking the source file so 'CaptureThis' for all nodes + function checkIfThisIsCapturedInEnclosingScope(node: Node): void { + var current = node; + while (current) { + if (getNodeCheckFlags(current) & NodeCheckFlags.CaptureThis) { + var isDeclaration = node.kind !== SyntaxKind.Identifier; + if (isDeclaration) { + error((node).name, Diagnostics.Duplicate_identifier_this_Compiler_uses_variable_declaration_this_to_capture_this_reference); + } + else { + error(node, Diagnostics.Expression_resolves_to_variable_declaration_this_that_compiler_uses_to_capture_this_reference); + } + return; + } + current = current.parent; + } + } + + function checkCollisionWithCapturedSuperVariable(node: Node, name: Identifier) { + if (!needCollisionCheckForIdentifier(node, name, "_super")) { return; } @@ -5029,6 +5070,7 @@ module ts { } checkCollisionWithCapturedSuperVariable(node, node.name); + checkCollisionWithCapturedThisVariable(node, node.name); if (!useTypeFromValueDeclaration) { // TypeScript 1.0 spec (April 2014): 5.1 // Multiple declarations for the same variable name in the same declaration space are permitted, @@ -5298,6 +5340,7 @@ module ts { checkDeclarationModifiers(node); checkTypeNameIsReserved(node.name, Diagnostics.Class_name_cannot_be_0); checkTypeParameters(node.typeParameters); + checkCollisionWithCapturedThisVariable(node, node.name); var symbol = getSymbolOfNode(node); var type = getDeclaredTypeOfSymbol(symbol); var staticType = getTypeOfSymbol(symbol); @@ -5498,6 +5541,7 @@ module ts { function checkEnumDeclaration(node: EnumDeclaration) { checkDeclarationModifiers(node); checkTypeNameIsReserved(node.name, Diagnostics.Enum_name_cannot_be_0); + checkCollisionWithCapturedThisVariable(node, node.name); var enumSymbol = getSymbolOfNode(node); var enumType = getDeclaredTypeOfSymbol(enumSymbol); var autoValue = 0; @@ -5569,6 +5613,7 @@ module ts { function checkModuleDeclaration(node: ModuleDeclaration) { checkDeclarationModifiers(node); + checkCollisionWithCapturedThisVariable(node, node.name); var symbol = getSymbolOfNode(node); if (symbol.flags & SymbolFlags.ValueModule && symbol.declarations.length > 1 && !isInAmbientContext(node)) { var classOrFunc = getFirstNonAmbientClassOrFunctionDeclaration(symbol); @@ -5594,6 +5639,7 @@ module ts { function checkImportDeclaration(node: ImportDeclaration) { checkDeclarationModifiers(node); + checkCollisionWithCapturedThisVariable(node, node.name); var symbol = getSymbolOfNode(node); var target: Symbol; @@ -5751,6 +5797,7 @@ module ts { var links = getNodeLinks(node); if (!(links.flags & NodeCheckFlags.TypeChecked)) { emitExtends = false; + potentialThisCollisions.length = 0; forEach(node.statements, checkSourceElement); if (node.flags & NodeFlags.ExternalModule) { var symbol = getExportAssignmentSymbol(node.symbol); @@ -5759,6 +5806,10 @@ module ts { getSymbolLinks(symbol).referenced = true; } } + if (potentialThisCollisions.length) { + forEach(potentialThisCollisions, checkIfThisIsCapturedInEnclosingScope); + potentialThisCollisions.length = 0; + } if (emitExtends) links.flags |= NodeCheckFlags.EmitExtends; links.flags |= NodeCheckFlags.TypeChecked; } diff --git a/src/compiler/diagnosticInformationMap.generated.ts b/src/compiler/diagnosticInformationMap.generated.ts index d9e35f29086..2c967b40b65 100644 --- a/src/compiler/diagnosticInformationMap.generated.ts +++ b/src/compiler/diagnosticInformationMap.generated.ts @@ -135,7 +135,9 @@ module ts { Return_type_of_constructor_signature_must_be_assignable_to_the_instance_type_of_the_class: { code: 2194, category: DiagnosticCategory.Error, key: "Return type of constructor signature must be assignable to the instance type of the class" }, Ambient_external_module_declaration_cannot_specify_relative_module_name: { code: 2196, category: DiagnosticCategory.Error, key: "Ambient external module declaration cannot specify relative module name." }, Import_declaration_in_an_ambient_external_module_declaration_cannot_reference_external_module_through_relative_external_module_name: { code: 2197, category: DiagnosticCategory.Error, key: "Import declaration in an ambient external module declaration cannot reference external module through relative external module name." }, + Duplicate_identifier_this_Compiler_uses_variable_declaration_this_to_capture_this_reference: { code: 2200, category: DiagnosticCategory.Error, key: "Duplicate identifier '_this'. Compiler uses variable declaration '_this' to capture 'this' reference." }, Duplicate_identifier_super_Compiler_uses_super_to_capture_base_class_reference: { code: 2205, category: DiagnosticCategory.Error, key: "Duplicate identifier '_super'. Compiler uses '_super' to capture base class reference." }, + Expression_resolves_to_variable_declaration_this_that_compiler_uses_to_capture_this_reference: { code: 2206, category: DiagnosticCategory.Error, key: "Expression resolves to variable declaration '_this' that compiler uses to capture 'this' reference." }, Expression_resolves_to_super_that_compiler_uses_to_capture_base_class_reference: { code: 2207, category: DiagnosticCategory.Error, key: "Expression resolves to '_super' that compiler uses to capture base class reference." }, Duplicate_identifier_i_Compiler_uses_i_to_initialize_rest_parameter: { code: 2224, category: DiagnosticCategory.Error, key: "Duplicate identifier '_i'. Compiler uses '_i' to initialize rest parameter." }, Duplicate_identifier_arguments_Compiler_uses_arguments_to_initialize_rest_parameters: { code: 2225, category: DiagnosticCategory.Error, key: "Duplicate identifier 'arguments'. Compiler uses 'arguments' to initialize rest parameters." }, diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 92b8d1a3e0e..55d0ffa2268 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -534,10 +534,18 @@ "category": "Error", "code": 2197 }, + "Duplicate identifier '_this'. Compiler uses variable declaration '_this' to capture 'this' reference.": { + "category": "Error", + "code": 2200 + }, "Duplicate identifier '_super'. Compiler uses '_super' to capture base class reference.": { "category": "Error", "code": 2205 }, + "Expression resolves to variable declaration '_this' that compiler uses to capture 'this' reference.": { + "category": "Error", + "code": 2206 + }, "Expression resolves to '_super' that compiler uses to capture base class reference.": { "category": "Error", "code": 2207 diff --git a/tests/baselines/reference/collisionThisExpressionAndAliasInGlobal.errors.txt b/tests/baselines/reference/collisionThisExpressionAndAliasInGlobal.errors.txt new file mode 100644 index 00000000000..d12256f4199 --- /dev/null +++ b/tests/baselines/reference/collisionThisExpressionAndAliasInGlobal.errors.txt @@ -0,0 +1,8 @@ +==== tests/cases/compiler/collisionThisExpressionAndAliasInGlobal.ts (1 errors) ==== + module a { + export var b = 10; + } + var f = () => this; + import _this = a; // Error + ~~~~~ +!!! Duplicate identifier '_this'. Compiler uses variable declaration '_this' to capture 'this' reference. \ No newline at end of file diff --git a/tests/baselines/reference/collisionThisExpressionAndAmbientClassInGlobal.errors.txt b/tests/baselines/reference/collisionThisExpressionAndAmbientClassInGlobal.errors.txt new file mode 100644 index 00000000000..0c6a7955e13 --- /dev/null +++ b/tests/baselines/reference/collisionThisExpressionAndAmbientClassInGlobal.errors.txt @@ -0,0 +1,7 @@ +==== tests/cases/compiler/collisionThisExpressionAndAmbientClassInGlobal.ts (1 errors) ==== + declare class _this { // no error - as no code generation + } + var f = () => this; + var a = new _this(); // Error + ~~~~~ +!!! Expression resolves to variable declaration '_this' that compiler uses to capture 'this' reference. \ No newline at end of file diff --git a/tests/baselines/reference/collisionThisExpressionAndAmbientVarInGlobal.errors.txt b/tests/baselines/reference/collisionThisExpressionAndAmbientVarInGlobal.errors.txt new file mode 100644 index 00000000000..77439118c9a --- /dev/null +++ b/tests/baselines/reference/collisionThisExpressionAndAmbientVarInGlobal.errors.txt @@ -0,0 +1,6 @@ +==== tests/cases/compiler/collisionThisExpressionAndAmbientVarInGlobal.ts (1 errors) ==== + declare var _this: number; // no error as no code gen + var f = () => this; + _this = 10; // Error + ~~~~~ +!!! Expression resolves to variable declaration '_this' that compiler uses to capture 'this' reference. \ No newline at end of file diff --git a/tests/baselines/reference/collisionThisExpressionAndClassInGlobal.errors.txt b/tests/baselines/reference/collisionThisExpressionAndClassInGlobal.errors.txt new file mode 100644 index 00000000000..e4256953b85 --- /dev/null +++ b/tests/baselines/reference/collisionThisExpressionAndClassInGlobal.errors.txt @@ -0,0 +1,6 @@ +==== tests/cases/compiler/collisionThisExpressionAndClassInGlobal.ts (1 errors) ==== + class _this { + ~~~~~ +!!! Duplicate identifier '_this'. Compiler uses variable declaration '_this' to capture 'this' reference. + } + var f = () => this; \ No newline at end of file diff --git a/tests/baselines/reference/collisionThisExpressionAndEnumInGlobal.errors.txt b/tests/baselines/reference/collisionThisExpressionAndEnumInGlobal.errors.txt new file mode 100644 index 00000000000..8e31ac24291 --- /dev/null +++ b/tests/baselines/reference/collisionThisExpressionAndEnumInGlobal.errors.txt @@ -0,0 +1,8 @@ +==== tests/cases/compiler/collisionThisExpressionAndEnumInGlobal.ts (1 errors) ==== + enum _this { // Error + ~~~~~ +!!! Duplicate identifier '_this'. Compiler uses variable declaration '_this' to capture 'this' reference. + _thisVal1, + _thisVal2, + } + var f = () => this; \ No newline at end of file diff --git a/tests/baselines/reference/collisionThisExpressionAndFunctionInGlobal.errors.txt b/tests/baselines/reference/collisionThisExpressionAndFunctionInGlobal.errors.txt new file mode 100644 index 00000000000..d76412ccad5 --- /dev/null +++ b/tests/baselines/reference/collisionThisExpressionAndFunctionInGlobal.errors.txt @@ -0,0 +1,7 @@ +==== tests/cases/compiler/collisionThisExpressionAndFunctionInGlobal.ts (1 errors) ==== + function _this() { //Error + ~~~~~ +!!! Duplicate identifier '_this'. Compiler uses variable declaration '_this' to capture 'this' reference. + return 10; + } + var f = () => this; \ No newline at end of file diff --git a/tests/baselines/reference/collisionThisExpressionAndLocalVarInAccessors.errors.txt b/tests/baselines/reference/collisionThisExpressionAndLocalVarInAccessors.errors.txt index ae3399f8066..5b84e2b779f 100644 --- a/tests/baselines/reference/collisionThisExpressionAndLocalVarInAccessors.errors.txt +++ b/tests/baselines/reference/collisionThisExpressionAndLocalVarInAccessors.errors.txt @@ -1,4 +1,4 @@ -==== tests/cases/compiler/collisionThisExpressionAndLocalVarInAccessors.ts (4 errors) ==== +==== tests/cases/compiler/collisionThisExpressionAndLocalVarInAccessors.ts (8 errors) ==== class class1 { get a(): number { ~ @@ -6,6 +6,8 @@ var x2 = { doStuff: (callback) => () => { var _this = 2; + ~~~~~ +!!! Duplicate identifier '_this'. Compiler uses variable declaration '_this' to capture 'this' reference. return callback(this); } } @@ -18,6 +20,8 @@ var x2 = { doStuff: (callback) => () => { var _this = 2; + ~~~~~ +!!! Duplicate identifier '_this'. Compiler uses variable declaration '_this' to capture 'this' reference. return callback(this); } } @@ -30,6 +34,8 @@ ~ !!! Accessors are only available when targeting ECMAScript 5 and higher. var _this = 2; + ~~~~~ +!!! Duplicate identifier '_this'. Compiler uses variable declaration '_this' to capture 'this' reference. var x2 = { doStuff: (callback) => () => { return callback(this); @@ -42,6 +48,8 @@ ~ !!! Accessors are only available when targeting ECMAScript 5 and higher. var _this = 2; + ~~~~~ +!!! Duplicate identifier '_this'. Compiler uses variable declaration '_this' to capture 'this' reference. var x2 = { doStuff: (callback) => () => { return callback(this); diff --git a/tests/baselines/reference/collisionThisExpressionAndLocalVarInConstructor.errors.txt b/tests/baselines/reference/collisionThisExpressionAndLocalVarInConstructor.errors.txt new file mode 100644 index 00000000000..17689e7d434 --- /dev/null +++ b/tests/baselines/reference/collisionThisExpressionAndLocalVarInConstructor.errors.txt @@ -0,0 +1,26 @@ +==== tests/cases/compiler/collisionThisExpressionAndLocalVarInConstructor.ts (2 errors) ==== + class class1 { + constructor() { + var x2 = { + doStuff: (callback) => () => { + var _this = 2; + ~~~~~ +!!! Duplicate identifier '_this'. Compiler uses variable declaration '_this' to capture 'this' reference. + return callback(this); + } + } + } + } + + class class2 { + constructor() { + var _this = 2; + ~~~~~ +!!! Duplicate identifier '_this'. Compiler uses variable declaration '_this' to capture 'this' reference. + var x2 = { + doStuff: (callback) => () => { + return callback(this); + } + } + } + } \ No newline at end of file diff --git a/tests/baselines/reference/collisionThisExpressionAndLocalVarInFunction.errors.txt b/tests/baselines/reference/collisionThisExpressionAndLocalVarInFunction.errors.txt new file mode 100644 index 00000000000..171f41fa107 --- /dev/null +++ b/tests/baselines/reference/collisionThisExpressionAndLocalVarInFunction.errors.txt @@ -0,0 +1,10 @@ +==== tests/cases/compiler/collisionThisExpressionAndLocalVarInFunction.ts (1 errors) ==== + var console: { + log(val: any); + } + function x() { + var _this = 5; + ~~~~~ +!!! Duplicate identifier '_this'. Compiler uses variable declaration '_this' to capture 'this' reference. + x => { console.log(this.x); }; + } \ No newline at end of file diff --git a/tests/baselines/reference/collisionThisExpressionAndLocalVarInLambda.errors.txt b/tests/baselines/reference/collisionThisExpressionAndLocalVarInLambda.errors.txt new file mode 100644 index 00000000000..5e734c998ae --- /dev/null +++ b/tests/baselines/reference/collisionThisExpressionAndLocalVarInLambda.errors.txt @@ -0,0 +1,12 @@ +==== tests/cases/compiler/collisionThisExpressionAndLocalVarInLambda.ts (1 errors) ==== + declare function alert(message?: any): void; + + var x = { + doStuff: (callback) => () => { + var _this = 2; + ~~~~~ +!!! Duplicate identifier '_this'. Compiler uses variable declaration '_this' to capture 'this' reference. + return callback(this); + } + } + alert(x.doStuff(x => alert(x))); \ No newline at end of file diff --git a/tests/baselines/reference/collisionThisExpressionAndLocalVarInMethod.errors.txt b/tests/baselines/reference/collisionThisExpressionAndLocalVarInMethod.errors.txt new file mode 100644 index 00000000000..da6a81be808 --- /dev/null +++ b/tests/baselines/reference/collisionThisExpressionAndLocalVarInMethod.errors.txt @@ -0,0 +1,23 @@ +==== tests/cases/compiler/collisionThisExpressionAndLocalVarInMethod.ts (2 errors) ==== + class a { + method1() { + return { + doStuff: (callback) => () => { + var _this = 2; + ~~~~~ +!!! Duplicate identifier '_this'. Compiler uses variable declaration '_this' to capture 'this' reference. + return callback(this); + } + } + } + method2() { + var _this = 2; + ~~~~~ +!!! Duplicate identifier '_this'. Compiler uses variable declaration '_this' to capture 'this' reference. + return { + doStuff: (callback) => () => { + return callback(this); + } + } + } + } \ No newline at end of file diff --git a/tests/baselines/reference/collisionThisExpressionAndLocalVarInProperty.errors.txt b/tests/baselines/reference/collisionThisExpressionAndLocalVarInProperty.errors.txt new file mode 100644 index 00000000000..57a768213a3 --- /dev/null +++ b/tests/baselines/reference/collisionThisExpressionAndLocalVarInProperty.errors.txt @@ -0,0 +1,24 @@ +==== tests/cases/compiler/collisionThisExpressionAndLocalVarInProperty.ts (2 errors) ==== + class class1 { + public prop1 = { + doStuff: (callback) => () => { + var _this = 2; + ~~~~~ +!!! Duplicate identifier '_this'. Compiler uses variable declaration '_this' to capture 'this' reference. + return callback(this); + } + } + } + + class class2 { + constructor() { + var _this = 2; + ~~~~~ +!!! Duplicate identifier '_this'. Compiler uses variable declaration '_this' to capture 'this' reference. + } + public prop1 = { + doStuff: (callback) => () => { + return callback(this); + } + } + } \ No newline at end of file diff --git a/tests/baselines/reference/collisionThisExpressionAndLocalVarWithSuperExperssion.errors.txt b/tests/baselines/reference/collisionThisExpressionAndLocalVarWithSuperExperssion.errors.txt new file mode 100644 index 00000000000..307c829c986 --- /dev/null +++ b/tests/baselines/reference/collisionThisExpressionAndLocalVarWithSuperExperssion.errors.txt @@ -0,0 +1,23 @@ +==== tests/cases/compiler/collisionThisExpressionAndLocalVarWithSuperExperssion.ts (2 errors) ==== + class a { + public foo() { + } + } + class b extends a { + public foo() { + var _this = 10; + ~~~~~ +!!! Duplicate identifier '_this'. Compiler uses variable declaration '_this' to capture 'this' reference. + var f = () => super.foo(); + } + } + class b2 extends a { + public foo() { + var f = () => { + var _this = 10; + ~~~~~ +!!! Duplicate identifier '_this'. Compiler uses variable declaration '_this' to capture 'this' reference. + return super.foo() + } + } + } \ No newline at end of file diff --git a/tests/baselines/reference/collisionThisExpressionAndModuleInGlobal.errors.txt b/tests/baselines/reference/collisionThisExpressionAndModuleInGlobal.errors.txt new file mode 100644 index 00000000000..7bd8fd289b4 --- /dev/null +++ b/tests/baselines/reference/collisionThisExpressionAndModuleInGlobal.errors.txt @@ -0,0 +1,8 @@ +==== tests/cases/compiler/collisionThisExpressionAndModuleInGlobal.ts (1 errors) ==== + module _this { //Error + ~~~~~ +!!! Duplicate identifier '_this'. Compiler uses variable declaration '_this' to capture 'this' reference. + class c { + } + } + var f = () => this; \ No newline at end of file diff --git a/tests/baselines/reference/collisionThisExpressionAndNameResolution.errors.txt b/tests/baselines/reference/collisionThisExpressionAndNameResolution.errors.txt new file mode 100644 index 00000000000..7684f5293bc --- /dev/null +++ b/tests/baselines/reference/collisionThisExpressionAndNameResolution.errors.txt @@ -0,0 +1,15 @@ +==== tests/cases/compiler/collisionThisExpressionAndNameResolution.ts (1 errors) ==== + var console : { + log(message: any); + } + class Foo { + x() { + var _this = 10; // Local var. No this capture in x(), so no conflict. + function inner() { + console.log(_this); // Error as this doesnt not resolve to user defined _this + ~~~~~ +!!! Expression resolves to variable declaration '_this' that compiler uses to capture 'this' reference. + return x => this; // New scope. So should inject new _this capture into function inner + } + } + } \ No newline at end of file diff --git a/tests/baselines/reference/collisionThisExpressionAndParameter.errors.txt b/tests/baselines/reference/collisionThisExpressionAndParameter.errors.txt new file mode 100644 index 00000000000..0e3d5945887 --- /dev/null +++ b/tests/baselines/reference/collisionThisExpressionAndParameter.errors.txt @@ -0,0 +1,110 @@ +==== tests/cases/compiler/collisionThisExpressionAndParameter.ts (8 errors) ==== + class Foo { + x() { + var _this = 10; // Local var. No this capture in x(), so no conflict. + function inner(_this: number) { // Error + ~~~~~ +!!! Duplicate identifier '_this'. Compiler uses variable declaration '_this' to capture 'this' reference. + return x => this; // New scope. So should inject new _this capture into function inner + } + } + y() { + var lamda = (_this: number) => { // Error + ~~~~~ +!!! Duplicate identifier '_this'. Compiler uses variable declaration '_this' to capture 'this' reference. + return x => this; // New scope. So should inject new _this capture + } + } + z(_this: number) { // Error + ~~~~~ +!!! Duplicate identifier '_this'. Compiler uses variable declaration '_this' to capture 'this' reference. + var lambda = () => { + return x => this; // New scope. So should inject new _this capture + } + } + + x1() { + var _this = 10; // Local var. No this capture in x(), so no conflict. + function inner(_this: number) { // No Error + } + } + y1() { + var lamda = (_this: number) => { // No Error + } + } + z1(_this: number) { // No Error + var lambda = () => { + } + } + } + class Foo1 { + constructor(_this: number) { // Error + ~~~~~ +!!! Duplicate identifier '_this'. Compiler uses variable declaration '_this' to capture 'this' reference. + var x2 = { + doStuff: (callback) => () => { + return callback(this); + } + } + } + } + declare var console: { + log(msg: any); + } + + function f1(_this: number) { + ~~~~~ +!!! Duplicate identifier '_this'. Compiler uses variable declaration '_this' to capture 'this' reference. + x => { console.log(this.x); }; + } + + declare class Foo2 { + constructor(_this: number); // no error - no code gen + z(_this: number); // no error - no code gen + } + declare function f2(_this: number); // no error + + class Foo3 { + constructor(_this: string); // no code gen - no error + constructor(_this: number); // no code gen - no error + constructor(_this: any) { // Error + ~~~~~ +!!! Duplicate identifier '_this'. Compiler uses variable declaration '_this' to capture 'this' reference. + var x2 = { + doStuff: (callback) => () => { + return callback(this); + } + } + } + + z(_this: string); // no code gen - no error + z(_this: number); // no code gen - no error + z(_this: any) { // Error + ~~~~~ +!!! Duplicate identifier '_this'. Compiler uses variable declaration '_this' to capture 'this' reference. + var lambda = () => { + return x => this; // New scope. So should inject new _this capture + } + } + } + declare var console: { + log(msg: any); + } + + function f3(_this: number); // no code gen - no error + function f3(_this: string); // no code gen - no error + function f3(_this: any) { + ~~~~~ +!!! Duplicate identifier '_this'. Compiler uses variable declaration '_this' to capture 'this' reference. + x => { console.log(this.x); }; + } + + declare class Foo4 { + constructor(_this: string); // no code gen - no error + constructor(_this: number); // no code gen - no error + z(_this: string); // no code gen - no error + z(_this: number); // no code gen - no error + } + + declare function f4(_this: number); // no code gen - no error + declare function f4(_this: string); // no code gen - no error \ No newline at end of file diff --git a/tests/baselines/reference/collisionThisExpressionAndPropertyNameAsConstuctorParameter.errors.txt b/tests/baselines/reference/collisionThisExpressionAndPropertyNameAsConstuctorParameter.errors.txt new file mode 100644 index 00000000000..bc60fffd80c --- /dev/null +++ b/tests/baselines/reference/collisionThisExpressionAndPropertyNameAsConstuctorParameter.errors.txt @@ -0,0 +1,44 @@ +==== tests/cases/compiler/collisionThisExpressionAndPropertyNameAsConstuctorParameter.ts (4 errors) ==== + class Foo2 { + constructor(_this: number) { //Error + ~~~~~ +!!! Duplicate identifier '_this'. Compiler uses variable declaration '_this' to capture 'this' reference. + var lambda = () => { + return x => this; // New scope. So should inject new _this capture + } + } + } + + class Foo3 { + constructor(private _this: number) { // Error + ~~~~~ +!!! Duplicate identifier '_this'. Compiler uses variable declaration '_this' to capture 'this' reference. + var lambda = () => { + return x => this; // New scope. So should inject new _this capture + } + } + } + + class Foo4 { + constructor(_this: number); // No code gen - no error + constructor(_this: string); // No code gen - no error + constructor(_this: any) { // Error + ~~~~~ +!!! Duplicate identifier '_this'. Compiler uses variable declaration '_this' to capture 'this' reference. + var lambda = () => { + return x => this; // New scope. So should inject new _this capture + } + } + } + + class Foo5 { + constructor(_this: number); // No code gen - no error + constructor(_this: string); // No code gen - no error + constructor(private _this: any) { // Error + ~~~~~ +!!! Duplicate identifier '_this'. Compiler uses variable declaration '_this' to capture 'this' reference. + var lambda = () => { + return x => this; // New scope. So should inject new _this capture + } + } + } \ No newline at end of file diff --git a/tests/baselines/reference/collisionThisExpressionAndVarInGlobal.errors.txt b/tests/baselines/reference/collisionThisExpressionAndVarInGlobal.errors.txt new file mode 100644 index 00000000000..c1c7e43f927 --- /dev/null +++ b/tests/baselines/reference/collisionThisExpressionAndVarInGlobal.errors.txt @@ -0,0 +1,5 @@ +==== tests/cases/compiler/collisionThisExpressionAndVarInGlobal.ts (1 errors) ==== + var _this = 1; + ~~~~~ +!!! Duplicate identifier '_this'. Compiler uses variable declaration '_this' to capture 'this' reference. + var f = () => this; \ No newline at end of file