diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 98fcd90b623..1fc3227e5ec 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -4966,7 +4966,10 @@ module ts { } } - if (isCallExpression) { + if (container.kind === SyntaxKind.ComputedPropertyName) { + error(node, Diagnostics.super_cannot_be_referenced_in_a_computed_property_name); + } + else if (isCallExpression) { error(node, Diagnostics.Super_calls_are_not_permitted_outside_constructors_or_in_nested_functions_inside_constructors); } else { diff --git a/src/compiler/diagnosticInformationMap.generated.ts b/src/compiler/diagnosticInformationMap.generated.ts index fb9811b396b..0a8c3a7edfe 100644 --- a/src/compiler/diagnosticInformationMap.generated.ts +++ b/src/compiler/diagnosticInformationMap.generated.ts @@ -301,6 +301,7 @@ module ts { A_binding_pattern_parameter_cannot_be_optional_in_an_implementation_signature: { code: 2463, category: DiagnosticCategory.Error, key: "A binding pattern parameter cannot be optional in an implementation signature." }, A_computed_property_name_must_be_of_type_string_number_or_any: { code: 2464, category: DiagnosticCategory.Error, key: "A computed property name must be of type 'string', 'number', or 'any'." }, this_cannot_be_referenced_in_a_computed_property_name: { code: 2465, category: DiagnosticCategory.Error, key: "'this' cannot be referenced in a computed property name." }, + super_cannot_be_referenced_in_a_computed_property_name: { code: 2466, category: DiagnosticCategory.Error, key: "'super' cannot be referenced in a computed property name." }, Import_declaration_0_is_using_private_name_1: { code: 4000, category: DiagnosticCategory.Error, key: "Import declaration '{0}' is using private name '{1}'." }, Type_parameter_0_of_exported_class_has_or_is_using_private_name_1: { code: 4002, category: DiagnosticCategory.Error, key: "Type parameter '{0}' of exported class has or is using private name '{1}'." }, Type_parameter_0_of_exported_interface_has_or_is_using_private_name_1: { code: 4004, category: DiagnosticCategory.Error, key: "Type parameter '{0}' of exported interface has or is using private name '{1}'." }, diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 940b66c4efc..2d1b4e4daf0 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -1298,6 +1298,10 @@ "category": "Error", "code": 2465 }, + "'super' cannot be referenced in a computed property name.": { + "category": "Error", + "code": 2466 + }, "Import declaration '{0}' is using private name '{1}'.": { "category": "Error", diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index d41b7ea6b24..6c894ad7d9c 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -404,9 +404,16 @@ module ts { // then the computed property is not a 'this' container. // A computed property name in a class needs to be a this container // so that we can error on it. - if (node.parent.parent.kind !== SyntaxKind.ClassDeclaration) { - continue; + if (node.parent.parent.kind === SyntaxKind.ClassDeclaration) { + return node; } + // If this is a computed property, then the parent should not + // make it a this container. The parent might be a property + // in an object literal, like a method or accessor. But in order for + // such a parent to be a this container, the reference must be in + // the *body* of the container. + node = node.parent; + break; case SyntaxKind.ArrowFunction: if (!includeArrowFunctions) { continue; @@ -434,6 +441,21 @@ module ts { node = node.parent; if (!node) return node; switch (node.kind) { + case SyntaxKind.ComputedPropertyName: + // If the grandparent node is an object literal (as opposed to a class), + // then the computed property is not a 'super' container. + // A computed property name in a class needs to be a super container + // so that we can error on it. + if (node.parent.parent.kind === SyntaxKind.ClassDeclaration) { + return node; + } + // If this is a computed property, then the parent should not + // make it a super container. The parent might be a property + // in an object literal, like a method or accessor. But in order for + // such a parent to be a super container, the reference must be in + // the *body* of the container. + node = node.parent; + break; case SyntaxKind.FunctionDeclaration: case SyntaxKind.FunctionExpression: case SyntaxKind.ArrowFunction: diff --git a/tests/baselines/reference/computedPropertyNames22.types b/tests/baselines/reference/computedPropertyNames22.types index 52dff9a4f41..d23546192c0 100644 --- a/tests/baselines/reference/computedPropertyNames22.types +++ b/tests/baselines/reference/computedPropertyNames22.types @@ -10,10 +10,10 @@ class C { >{ [this.bar()]() { } } : {} [this.bar()]() { } ->this.bar() : any ->this.bar : any ->this : any ->bar : any +>this.bar() : number +>this.bar : () => number +>this : C +>bar : () => number }; return 0; diff --git a/tests/baselines/reference/computedPropertyNames24.errors.txt b/tests/baselines/reference/computedPropertyNames24.errors.txt new file mode 100644 index 00000000000..938fb64b82e --- /dev/null +++ b/tests/baselines/reference/computedPropertyNames24.errors.txt @@ -0,0 +1,16 @@ +tests/cases/conformance/es6/computedProperties/computedPropertyNames24.ts(9,6): error TS2466: 'super' cannot be referenced in a computed property name. + + +==== tests/cases/conformance/es6/computedProperties/computedPropertyNames24.ts (1 errors) ==== + class Base { + bar() { + return 0; + } + } + class C extends Base { + // Gets emitted as super, not _super, which is consistent with + // use of super in static properties initializers. + [super.bar()]() { } + ~~~~~ +!!! error TS2466: 'super' cannot be referenced in a computed property name. + } \ No newline at end of file diff --git a/tests/baselines/reference/computedPropertyNames24.js b/tests/baselines/reference/computedPropertyNames24.js new file mode 100644 index 00000000000..2ef2826ee22 --- /dev/null +++ b/tests/baselines/reference/computedPropertyNames24.js @@ -0,0 +1,38 @@ +//// [computedPropertyNames24.ts] +class Base { + bar() { + return 0; + } +} +class C extends Base { + // Gets emitted as super, not _super, which is consistent with + // use of super in static properties initializers. + [super.bar()]() { } +} + +//// [computedPropertyNames24.js] +var __extends = this.__extends || function (d, b) { + for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; + function __() { this.constructor = d; } + __.prototype = b.prototype; + d.prototype = new __(); +}; +var Base = (function () { + function Base() { + } + Base.prototype.bar = function () { + return 0; + }; + return Base; +})(); +var C = (function (_super) { + __extends(C, _super); + function C() { + _super.apply(this, arguments); + } + // Gets emitted as super, not _super, which is consistent with + // use of super in static properties initializers. + C.prototype[super.bar.call(this)] = function () { + }; + return C; +})(Base); diff --git a/tests/baselines/reference/computedPropertyNames25.js b/tests/baselines/reference/computedPropertyNames25.js new file mode 100644 index 00000000000..a15fcb217e7 --- /dev/null +++ b/tests/baselines/reference/computedPropertyNames25.js @@ -0,0 +1,44 @@ +//// [computedPropertyNames25.ts] +class Base { + bar() { + return 0; + } +} +class C extends Base { + foo() { + var obj = { + [super.bar()]() { } + }; + return 0; + } +} + +//// [computedPropertyNames25.js] +var __extends = this.__extends || function (d, b) { + for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; + function __() { this.constructor = d; } + __.prototype = b.prototype; + d.prototype = new __(); +}; +var Base = (function () { + function Base() { + } + Base.prototype.bar = function () { + return 0; + }; + return Base; +})(); +var C = (function (_super) { + __extends(C, _super); + function C() { + _super.apply(this, arguments); + } + C.prototype.foo = function () { + var obj = { + [_super.prototype.bar.call(this)]() { + } + }; + return 0; + }; + return C; +})(Base); diff --git a/tests/baselines/reference/computedPropertyNames25.types b/tests/baselines/reference/computedPropertyNames25.types new file mode 100644 index 00000000000..d8567dc86ad --- /dev/null +++ b/tests/baselines/reference/computedPropertyNames25.types @@ -0,0 +1,31 @@ +=== tests/cases/conformance/es6/computedProperties/computedPropertyNames25.ts === +class Base { +>Base : Base + + bar() { +>bar : () => number + + return 0; + } +} +class C extends Base { +>C : C +>Base : Base + + foo() { +>foo : () => number + + var obj = { +>obj : {} +>{ [super.bar()]() { } } : {} + + [super.bar()]() { } +>super.bar() : number +>super.bar : () => number +>super : Base +>bar : () => number + + }; + return 0; + } +} diff --git a/tests/baselines/reference/computedPropertyNames26.errors.txt b/tests/baselines/reference/computedPropertyNames26.errors.txt new file mode 100644 index 00000000000..bbe51c6a0c8 --- /dev/null +++ b/tests/baselines/reference/computedPropertyNames26.errors.txt @@ -0,0 +1,18 @@ +tests/cases/conformance/es6/computedProperties/computedPropertyNames26.ts(10,12): error TS2466: 'super' cannot be referenced in a computed property name. + + +==== tests/cases/conformance/es6/computedProperties/computedPropertyNames26.ts (1 errors) ==== + class Base { + bar() { + return 0; + } + } + class C extends Base { + // Gets emitted as super, not _super, which is consistent with + // use of super in static properties initializers. + [ + { [super.bar()]: 1 }[0] + ~~~~~ +!!! error TS2466: 'super' cannot be referenced in a computed property name. + ]() { } + } \ No newline at end of file diff --git a/tests/baselines/reference/computedPropertyNames26.js b/tests/baselines/reference/computedPropertyNames26.js new file mode 100644 index 00000000000..96760fc279c --- /dev/null +++ b/tests/baselines/reference/computedPropertyNames26.js @@ -0,0 +1,40 @@ +//// [computedPropertyNames26.ts] +class Base { + bar() { + return 0; + } +} +class C extends Base { + // Gets emitted as super, not _super, which is consistent with + // use of super in static properties initializers. + [ + { [super.bar()]: 1 }[0] + ]() { } +} + +//// [computedPropertyNames26.js] +var __extends = this.__extends || function (d, b) { + for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; + function __() { this.constructor = d; } + __.prototype = b.prototype; + d.prototype = new __(); +}; +var Base = (function () { + function Base() { + } + Base.prototype.bar = function () { + return 0; + }; + return Base; +})(); +var C = (function (_super) { + __extends(C, _super); + function C() { + _super.apply(this, arguments); + } + // Gets emitted as super, not _super, which is consistent with + // use of super in static properties initializers. + C.prototype[{ [super.bar.call(this)]: 1 }[0]] = function () { + }; + return C; +})(Base); diff --git a/tests/baselines/reference/computedPropertyNames27.errors.txt b/tests/baselines/reference/computedPropertyNames27.errors.txt new file mode 100644 index 00000000000..c2872197363 --- /dev/null +++ b/tests/baselines/reference/computedPropertyNames27.errors.txt @@ -0,0 +1,11 @@ +tests/cases/conformance/es6/computedProperties/computedPropertyNames27.ts(4,7): error TS2466: 'super' cannot be referenced in a computed property name. + + +==== tests/cases/conformance/es6/computedProperties/computedPropertyNames27.ts (1 errors) ==== + class Base { + } + class C extends Base { + [(super(), "prop")]() { } + ~~~~~ +!!! error TS2466: 'super' cannot be referenced in a computed property name. + } \ No newline at end of file diff --git a/tests/baselines/reference/computedPropertyNames27.js b/tests/baselines/reference/computedPropertyNames27.js new file mode 100644 index 00000000000..71db977e9b6 --- /dev/null +++ b/tests/baselines/reference/computedPropertyNames27.js @@ -0,0 +1,28 @@ +//// [computedPropertyNames27.ts] +class Base { +} +class C extends Base { + [(super(), "prop")]() { } +} + +//// [computedPropertyNames27.js] +var __extends = this.__extends || function (d, b) { + for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; + function __() { this.constructor = d; } + __.prototype = b.prototype; + d.prototype = new __(); +}; +var Base = (function () { + function Base() { + } + return Base; +})(); +var C = (function (_super) { + __extends(C, _super); + function C() { + _super.apply(this, arguments); + } + C.prototype[(_super.call(this), "prop")] = function () { + }; + return C; +})(Base); diff --git a/tests/baselines/reference/computedPropertyNames28.js b/tests/baselines/reference/computedPropertyNames28.js new file mode 100644 index 00000000000..96c7cd082f1 --- /dev/null +++ b/tests/baselines/reference/computedPropertyNames28.js @@ -0,0 +1,35 @@ +//// [computedPropertyNames28.ts] +class Base { +} +class C extends Base { + constructor() { + super(); + var obj = { + [(super(), "prop")]() { } + }; + } +} + +//// [computedPropertyNames28.js] +var __extends = this.__extends || function (d, b) { + for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; + function __() { this.constructor = d; } + __.prototype = b.prototype; + d.prototype = new __(); +}; +var Base = (function () { + function Base() { + } + return Base; +})(); +var C = (function (_super) { + __extends(C, _super); + function C() { + _super.call(this); + var obj = { + [(_super.call(this), "prop")]() { + } + }; + } + return C; +})(Base); diff --git a/tests/baselines/reference/computedPropertyNames28.types b/tests/baselines/reference/computedPropertyNames28.types new file mode 100644 index 00000000000..2adf52f8c5f --- /dev/null +++ b/tests/baselines/reference/computedPropertyNames28.types @@ -0,0 +1,26 @@ +=== tests/cases/conformance/es6/computedProperties/computedPropertyNames28.ts === +class Base { +>Base : Base +} +class C extends Base { +>C : C +>Base : Base + + constructor() { + super(); +>super() : void +>super : typeof Base + + var obj = { +>obj : {} +>{ [(super(), "prop")]() { } } : {} + + [(super(), "prop")]() { } +>(super(), "prop") : string +>super(), "prop" : string +>super() : void +>super : typeof Base + + }; + } +} diff --git a/tests/baselines/reference/computedPropertyNames29.js b/tests/baselines/reference/computedPropertyNames29.js new file mode 100644 index 00000000000..dc45746c63c --- /dev/null +++ b/tests/baselines/reference/computedPropertyNames29.js @@ -0,0 +1,28 @@ +//// [computedPropertyNames29.ts] +class C { + bar() { + () => { + var obj = { + [this.bar()]() { } // needs capture + }; + } + return 0; + } +} + +//// [computedPropertyNames29.js] +var C = (function () { + function C() { + } + C.prototype.bar = function () { + var _this = this; + (function () { + var obj = { + [_this.bar()]() { + } // needs capture + }; + }); + return 0; + }; + return C; +})(); diff --git a/tests/baselines/reference/computedPropertyNames29.types b/tests/baselines/reference/computedPropertyNames29.types new file mode 100644 index 00000000000..ed4db5862e9 --- /dev/null +++ b/tests/baselines/reference/computedPropertyNames29.types @@ -0,0 +1,25 @@ +=== tests/cases/conformance/es6/computedProperties/computedPropertyNames29.ts === +class C { +>C : C + + bar() { +>bar : () => number + + () => { +>() => { var obj = { [this.bar()]() { } // needs capture }; } : () => void + + var obj = { +>obj : {} +>{ [this.bar()]() { } // needs capture } : {} + + [this.bar()]() { } // needs capture +>this.bar() : number +>this.bar : () => number +>this : C +>bar : () => number + + }; + } + return 0; + } +} diff --git a/tests/baselines/reference/computedPropertyNames30.errors.txt b/tests/baselines/reference/computedPropertyNames30.errors.txt new file mode 100644 index 00000000000..f7b6411f867 --- /dev/null +++ b/tests/baselines/reference/computedPropertyNames30.errors.txt @@ -0,0 +1,21 @@ +tests/cases/conformance/es6/computedProperties/computedPropertyNames30.ts(11,19): error TS2337: Super calls are not permitted outside constructors or in nested functions inside constructors + + +==== tests/cases/conformance/es6/computedProperties/computedPropertyNames30.ts (1 errors) ==== + class Base { + } + class C extends Base { + constructor() { + super(); + () => { + var obj = { + // Ideally, we would capture this. But the reference is + // illegal, and not capturing this is consistent with + //treatment of other similar violations. + [(super(), "prop")]() { } + ~~~~~ +!!! error TS2337: Super calls are not permitted outside constructors or in nested functions inside constructors + }; + } + } + } \ No newline at end of file diff --git a/tests/baselines/reference/computedPropertyNames30.js b/tests/baselines/reference/computedPropertyNames30.js new file mode 100644 index 00000000000..c10ba51316d --- /dev/null +++ b/tests/baselines/reference/computedPropertyNames30.js @@ -0,0 +1,45 @@ +//// [computedPropertyNames30.ts] +class Base { +} +class C extends Base { + constructor() { + super(); + () => { + var obj = { + // Ideally, we would capture this. But the reference is + // illegal, and not capturing this is consistent with + //treatment of other similar violations. + [(super(), "prop")]() { } + }; + } + } +} + +//// [computedPropertyNames30.js] +var __extends = this.__extends || function (d, b) { + for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; + function __() { this.constructor = d; } + __.prototype = b.prototype; + d.prototype = new __(); +}; +var Base = (function () { + function Base() { + } + return Base; +})(); +var C = (function (_super) { + __extends(C, _super); + function C() { + _super.call(this); + (function () { + var obj = { + // Ideally, we would capture this. But the reference is + // illegal, and not capturing this is consistent with + //treatment of other similar violations. + [(_super.call(this), "prop")]() { + } + }; + }); + } + return C; +})(Base); diff --git a/tests/baselines/reference/computedPropertyNames31.js b/tests/baselines/reference/computedPropertyNames31.js new file mode 100644 index 00000000000..bf75ac2be74 --- /dev/null +++ b/tests/baselines/reference/computedPropertyNames31.js @@ -0,0 +1,49 @@ +//// [computedPropertyNames31.ts] +class Base { + bar() { + return 0; + } +} +class C extends Base { + foo() { + () => { + var obj = { + [super.bar()]() { } // needs capture + }; + } + return 0; + } +} + +//// [computedPropertyNames31.js] +var __extends = this.__extends || function (d, b) { + for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; + function __() { this.constructor = d; } + __.prototype = b.prototype; + d.prototype = new __(); +}; +var Base = (function () { + function Base() { + } + Base.prototype.bar = function () { + return 0; + }; + return Base; +})(); +var C = (function (_super) { + __extends(C, _super); + function C() { + _super.apply(this, arguments); + } + C.prototype.foo = function () { + var _this = this; + (function () { + var obj = { + [_super.prototype.bar.call(_this)]() { + } // needs capture + }; + }); + return 0; + }; + return C; +})(Base); diff --git a/tests/baselines/reference/computedPropertyNames31.types b/tests/baselines/reference/computedPropertyNames31.types new file mode 100644 index 00000000000..90e73bc3dcb --- /dev/null +++ b/tests/baselines/reference/computedPropertyNames31.types @@ -0,0 +1,35 @@ +=== tests/cases/conformance/es6/computedProperties/computedPropertyNames31.ts === +class Base { +>Base : Base + + bar() { +>bar : () => number + + return 0; + } +} +class C extends Base { +>C : C +>Base : Base + + foo() { +>foo : () => number + + () => { +>() => { var obj = { [super.bar()]() { } // needs capture }; } : () => void + + var obj = { +>obj : {} +>{ [super.bar()]() { } // needs capture } : {} + + [super.bar()]() { } // needs capture +>super.bar() : number +>super.bar : () => number +>super : Base +>bar : () => number + + }; + } + return 0; + } +} diff --git a/tests/cases/conformance/es6/computedProperties/computedPropertyNames24.ts b/tests/cases/conformance/es6/computedProperties/computedPropertyNames24.ts new file mode 100644 index 00000000000..dc3a9541e11 --- /dev/null +++ b/tests/cases/conformance/es6/computedProperties/computedPropertyNames24.ts @@ -0,0 +1,11 @@ +// @target: es6 +class Base { + bar() { + return 0; + } +} +class C extends Base { + // Gets emitted as super, not _super, which is consistent with + // use of super in static properties initializers. + [super.bar()]() { } +} \ No newline at end of file diff --git a/tests/cases/conformance/es6/computedProperties/computedPropertyNames25.ts b/tests/cases/conformance/es6/computedProperties/computedPropertyNames25.ts new file mode 100644 index 00000000000..bc07847b251 --- /dev/null +++ b/tests/cases/conformance/es6/computedProperties/computedPropertyNames25.ts @@ -0,0 +1,14 @@ +// @target: es6 +class Base { + bar() { + return 0; + } +} +class C extends Base { + foo() { + var obj = { + [super.bar()]() { } + }; + return 0; + } +} \ No newline at end of file diff --git a/tests/cases/conformance/es6/computedProperties/computedPropertyNames26.ts b/tests/cases/conformance/es6/computedProperties/computedPropertyNames26.ts new file mode 100644 index 00000000000..6ef32397f54 --- /dev/null +++ b/tests/cases/conformance/es6/computedProperties/computedPropertyNames26.ts @@ -0,0 +1,13 @@ +// @target: es6 +class Base { + bar() { + return 0; + } +} +class C extends Base { + // Gets emitted as super, not _super, which is consistent with + // use of super in static properties initializers. + [ + { [super.bar()]: 1 }[0] + ]() { } +} \ No newline at end of file diff --git a/tests/cases/conformance/es6/computedProperties/computedPropertyNames27.ts b/tests/cases/conformance/es6/computedProperties/computedPropertyNames27.ts new file mode 100644 index 00000000000..be19acd4729 --- /dev/null +++ b/tests/cases/conformance/es6/computedProperties/computedPropertyNames27.ts @@ -0,0 +1,6 @@ +// @target: es6 +class Base { +} +class C extends Base { + [(super(), "prop")]() { } +} \ No newline at end of file diff --git a/tests/cases/conformance/es6/computedProperties/computedPropertyNames28.ts b/tests/cases/conformance/es6/computedProperties/computedPropertyNames28.ts new file mode 100644 index 00000000000..f9b14c3a75c --- /dev/null +++ b/tests/cases/conformance/es6/computedProperties/computedPropertyNames28.ts @@ -0,0 +1,11 @@ +// @target: es6 +class Base { +} +class C extends Base { + constructor() { + super(); + var obj = { + [(super(), "prop")]() { } + }; + } +} \ No newline at end of file diff --git a/tests/cases/conformance/es6/computedProperties/computedPropertyNames29.ts b/tests/cases/conformance/es6/computedProperties/computedPropertyNames29.ts new file mode 100644 index 00000000000..abf213b4c75 --- /dev/null +++ b/tests/cases/conformance/es6/computedProperties/computedPropertyNames29.ts @@ -0,0 +1,11 @@ +// @target: es6 +class C { + bar() { + () => { + var obj = { + [this.bar()]() { } // needs capture + }; + } + return 0; + } +} \ No newline at end of file diff --git a/tests/cases/conformance/es6/computedProperties/computedPropertyNames30.ts b/tests/cases/conformance/es6/computedProperties/computedPropertyNames30.ts new file mode 100644 index 00000000000..5fba13388f8 --- /dev/null +++ b/tests/cases/conformance/es6/computedProperties/computedPropertyNames30.ts @@ -0,0 +1,16 @@ +// @target: es6 +class Base { +} +class C extends Base { + constructor() { + super(); + () => { + var obj = { + // Ideally, we would capture this. But the reference is + // illegal, and not capturing this is consistent with + //treatment of other similar violations. + [(super(), "prop")]() { } + }; + } + } +} \ No newline at end of file diff --git a/tests/cases/conformance/es6/computedProperties/computedPropertyNames31.ts b/tests/cases/conformance/es6/computedProperties/computedPropertyNames31.ts new file mode 100644 index 00000000000..0ee8a0284a3 --- /dev/null +++ b/tests/cases/conformance/es6/computedProperties/computedPropertyNames31.ts @@ -0,0 +1,16 @@ +// @target: es6 +class Base { + bar() { + return 0; + } +} +class C extends Base { + foo() { + () => { + var obj = { + [super.bar()]() { } // needs capture + }; + } + return 0; + } +} \ No newline at end of file