Disallow super and fix this capturing for computed properties

This commit is contained in:
Jason Freeman 2015-01-19 16:27:58 -08:00
parent e317767966
commit b5349a5038
29 changed files with 625 additions and 7 deletions

View File

@ -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 {

View File

@ -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}'." },

View File

@ -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",

View File

@ -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:

View File

@ -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;

View File

@ -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.
}

View File

@ -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);

View File

@ -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);

View File

@ -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;
}
}

View File

@ -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.
]() { }
}

View File

@ -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);

View File

@ -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.
}

View File

@ -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);

View File

@ -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);

View File

@ -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
};
}
}

View File

@ -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;
})();

View File

@ -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;
}
}

View File

@ -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
};
}
}
}

View File

@ -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);

View File

@ -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);

View File

@ -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;
}
}

View File

@ -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()]() { }
}

View File

@ -0,0 +1,14 @@
// @target: es6
class Base {
bar() {
return 0;
}
}
class C extends Base {
foo() {
var obj = {
[super.bar()]() { }
};
return 0;
}
}

View File

@ -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]
]() { }
}

View File

@ -0,0 +1,6 @@
// @target: es6
class Base {
}
class C extends Base {
[(super(), "prop")]() { }
}

View File

@ -0,0 +1,11 @@
// @target: es6
class Base {
}
class C extends Base {
constructor() {
super();
var obj = {
[(super(), "prop")]() { }
};
}
}

View File

@ -0,0 +1,11 @@
// @target: es6
class C {
bar() {
() => {
var obj = {
[this.bar()]() { } // needs capture
};
}
return 0;
}
}

View File

@ -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")]() { }
};
}
}
}

View File

@ -0,0 +1,16 @@
// @target: es6
class Base {
bar() {
return 0;
}
}
class C extends Base {
foo() {
() => {
var obj = {
[super.bar()]() { } // needs capture
};
}
return 0;
}
}