Fix for issue #442

This commit is contained in:
about-code
2016-10-16 18:43:55 +02:00
parent fc5b2e524d
commit 8a37a162b2
13 changed files with 558 additions and 52 deletions

View File

@@ -13922,6 +13922,50 @@ namespace ts {
}
}
// Static members may conflict with non-configurable non-writable built-in Function.prototype properties
// see https://github.com/microsoft/typescript/issues/442.
function checkClassForStaticPropertyNameConflicts(node: ClassLikeDeclaration) {
const es5_descriptors: PropertyDescriptorMap = {
// see http://www.ecma-international.org/ecma-262/5.1/#sec-15.3.3
// see http://www.ecma-international.org/ecma-262/5.1/#sec-15.3.5
"name": {configurable: false, writable: false},
"length": {configurable: false, writable: false},
"prototype": {configurable: false, writable: false},
// see https://github.com/microsoft/typescript/issues/442
"caller": {configurable: false, writable: false},
"arguments": {configurable: false, writable: false}
};
const post_es5_descriptors: PropertyDescriptorMap = {
// see http://www.ecma-international.org/ecma-262/6.0/#sec-properties-of-the-function-constructor
// see http://www.ecma-international.org/ecma-262/6.0/#sec-function-instances
"name": {configurable: true, writable: false},
"length": {configurable: true, writable: false},
"prototype": {configurable: false, writable: false},
"caller": {configurable: false, writable: false},
"arguments": {configurable: false, writable: false}
};
const message = Diagnostics.Static_property_0_conflicts_with_built_in_property_Function_0_of_constructor_function_1;
const className = getSymbolOfNode(node).name;
for (let member of node.members) {
let isStatic = forEach(member.modifiers, (m:Modifier) => m.kind === SyntaxKind.StaticKeyword);
if (isStatic) {
let memberNameNode = member.name;
let memberName = getPropertyNameForPropertyNameNode(memberNameNode);
let descriptor: PropertyDescriptor = null;
if (languageVersion <= ScriptTarget.ES5) {
descriptor = es5_descriptors.hasOwnProperty(memberName) ? es5_descriptors[memberName] : null;
} else if (languageVersion > ScriptTarget.ES5) {
descriptor = post_es5_descriptors.hasOwnProperty(memberName) ? post_es5_descriptors[memberName] : null;
}
if (descriptor && descriptor.configurable === false && descriptor.writable === false) {
error(memberNameNode, message, memberName, className);
}
}
}
}
function checkObjectTypeForDuplicateDeclarations(node: TypeLiteralNode | InterfaceDeclaration) {
const names = createMap<boolean>();
for (const member of node.members) {
@@ -16423,6 +16467,7 @@ namespace ts {
const staticType = <ObjectType>getTypeOfSymbol(symbol);
checkTypeParameterListsIdentical(node, symbol);
checkClassForDuplicateDeclarations(node);
checkClassForStaticPropertyNameConflicts(node);
const baseTypeNode = getClassExtendsHeritageClauseElement(node);
if (baseTypeNode) {

View File

@@ -1955,6 +1955,10 @@
"category": "Error",
"code": 2691
},
"Static property '{0}' conflicts with built-in property 'Function.{0}' of constructor function '{1}'.": {
"category": "Error",
"code": 2692
},
"Import declaration '{0}' is using private name '{1}'.": {
"category": "Error",
"code": 4000
@@ -2239,7 +2243,6 @@
"category": "Message",
"code": 4090
},
"The current host does not support the '{0}' option.": {
"category": "Error",
"code": 5001

View File

@@ -0,0 +1,10 @@
tests/cases/conformance/classes/propertyMemberDeclarations/propertyNamedPrototype.ts(3,12): error TS2692: Static property 'prototype' conflicts with built-in property 'Function.prototype' of constructor function 'C'.
==== tests/cases/conformance/classes/propertyMemberDeclarations/propertyNamedPrototype.ts (1 errors) ====
class C {
prototype: number; // ok
static prototype: C; // error
~~~~~~~~~
!!! error TS2692: Static property 'prototype' conflicts with built-in property 'Function.prototype' of constructor function 'C'.
}

View File

@@ -1,43 +1,43 @@
tests/cases/compiler/staticMemberOfClassAndPublicMemberOfAnotherClassAssignment.ts(12,1): error TS2322: Type 'C' is not assignable to type 'A'.
Property 'name' is missing in type 'C'.
Property 'prop' is missing in type 'C'.
tests/cases/compiler/staticMemberOfClassAndPublicMemberOfAnotherClassAssignment.ts(13,1): error TS2322: Type 'typeof B' is not assignable to type 'A'.
Property 'name' is missing in type 'typeof B'.
Property 'prop' is missing in type 'typeof B'.
tests/cases/compiler/staticMemberOfClassAndPublicMemberOfAnotherClassAssignment.ts(16,5): error TS2322: Type 'C' is not assignable to type 'B'.
Property 'name' is missing in type 'C'.
Property 'prop' is missing in type 'C'.
tests/cases/compiler/staticMemberOfClassAndPublicMemberOfAnotherClassAssignment.ts(17,1): error TS2322: Type 'typeof B' is not assignable to type 'B'.
Property 'name' is missing in type 'typeof B'.
Property 'prop' is missing in type 'typeof B'.
==== tests/cases/compiler/staticMemberOfClassAndPublicMemberOfAnotherClassAssignment.ts (4 errors) ====
interface A {
name();
prop();
}
class B {
public name() { }
public prop() { }
}
class C {
public static name() { }
public static prop() { }
}
var a: A = new B();
a = new C(); // error name is missing
a = new C(); // error prop is missing
~
!!! error TS2322: Type 'C' is not assignable to type 'A'.
!!! error TS2322: Property 'name' is missing in type 'C'.
a = B; // error name is missing
!!! error TS2322: Property 'prop' is missing in type 'C'.
a = B; // error prop is missing
~
!!! error TS2322: Type 'typeof B' is not assignable to type 'A'.
!!! error TS2322: Property 'name' is missing in type 'typeof B'.
!!! error TS2322: Property 'prop' is missing in type 'typeof B'.
a = C;
var b: B = new C(); // error name is missing
var b: B = new C(); // error prop is missing
~
!!! error TS2322: Type 'C' is not assignable to type 'B'.
!!! error TS2322: Property 'name' is missing in type 'C'.
b = B; // error name is missing
!!! error TS2322: Property 'prop' is missing in type 'C'.
b = B; // error prop is missing
~
!!! error TS2322: Type 'typeof B' is not assignable to type 'B'.
!!! error TS2322: Property 'name' is missing in type 'typeof B'.
!!! error TS2322: Property 'prop' is missing in type 'typeof B'.
b = C;
b = a;

View File

@@ -1,21 +1,21 @@
//// [staticMemberOfClassAndPublicMemberOfAnotherClassAssignment.ts]
interface A {
name();
prop();
}
class B {
public name() { }
public prop() { }
}
class C {
public static name() { }
public static prop() { }
}
var a: A = new B();
a = new C(); // error name is missing
a = B; // error name is missing
a = new C(); // error prop is missing
a = B; // error prop is missing
a = C;
var b: B = new C(); // error name is missing
b = B; // error name is missing
var b: B = new C(); // error prop is missing
b = B; // error prop is missing
b = C;
b = a;
@@ -29,21 +29,21 @@ c = a;
var B = (function () {
function B() {
}
B.prototype.name = function () { };
B.prototype.prop = function () { };
return B;
}());
var C = (function () {
function C() {
}
C.name = function () { };
C.prop = function () { };
return C;
}());
var a = new B();
a = new C(); // error name is missing
a = B; // error name is missing
a = new C(); // error prop is missing
a = B; // error prop is missing
a = C;
var b = new C(); // error name is missing
b = B; // error name is missing
var b = new C(); // error prop is missing
b = B; // error prop is missing
b = C;
b = a;
var c = new B();

View File

@@ -0,0 +1,92 @@
tests/cases/conformance/classes/propertyMemberDeclarations/staticPropertyNameConflictsEs5.ts(4,12): error TS2692: Static property 'name' conflicts with built-in property 'Function.name' of constructor function 'StaticName'.
tests/cases/conformance/classes/propertyMemberDeclarations/staticPropertyNameConflictsEs5.ts(9,12): error TS2692: Static property 'name' conflicts with built-in property 'Function.name' of constructor function 'StaticNameFn'.
tests/cases/conformance/classes/propertyMemberDeclarations/staticPropertyNameConflictsEs5.ts(15,12): error TS2692: Static property 'length' conflicts with built-in property 'Function.length' of constructor function 'StaticLength'.
tests/cases/conformance/classes/propertyMemberDeclarations/staticPropertyNameConflictsEs5.ts(20,12): error TS2692: Static property 'length' conflicts with built-in property 'Function.length' of constructor function 'StaticLengthFn'.
tests/cases/conformance/classes/propertyMemberDeclarations/staticPropertyNameConflictsEs5.ts(26,12): error TS2692: Static property 'prototype' conflicts with built-in property 'Function.prototype' of constructor function 'StaticPrototype'.
tests/cases/conformance/classes/propertyMemberDeclarations/staticPropertyNameConflictsEs5.ts(31,12): error TS2300: Duplicate identifier 'prototype'.
tests/cases/conformance/classes/propertyMemberDeclarations/staticPropertyNameConflictsEs5.ts(31,12): error TS2692: Static property 'prototype' conflicts with built-in property 'Function.prototype' of constructor function 'StaticPrototypeFn'.
tests/cases/conformance/classes/propertyMemberDeclarations/staticPropertyNameConflictsEs5.ts(37,12): error TS2692: Static property 'caller' conflicts with built-in property 'Function.caller' of constructor function 'StaticCaller'.
tests/cases/conformance/classes/propertyMemberDeclarations/staticPropertyNameConflictsEs5.ts(42,12): error TS2692: Static property 'caller' conflicts with built-in property 'Function.caller' of constructor function 'StaticCallerFn'.
tests/cases/conformance/classes/propertyMemberDeclarations/staticPropertyNameConflictsEs5.ts(48,12): error TS2692: Static property 'arguments' conflicts with built-in property 'Function.arguments' of constructor function 'StaticArguments'.
tests/cases/conformance/classes/propertyMemberDeclarations/staticPropertyNameConflictsEs5.ts(53,12): error TS2692: Static property 'arguments' conflicts with built-in property 'Function.arguments' of constructor function 'StaticArgumentsFn'.
==== tests/cases/conformance/classes/propertyMemberDeclarations/staticPropertyNameConflictsEs5.ts (11 errors) ====
// static name
class StaticName {
static name: number; // error
~~~~
!!! error TS2692: Static property 'name' conflicts with built-in property 'Function.name' of constructor function 'StaticName'.
name: string; // ok
}
class StaticNameFn {
static name() {} // error
~~~~
!!! error TS2692: Static property 'name' conflicts with built-in property 'Function.name' of constructor function 'StaticNameFn'.
name() {} // ok
}
class StaticLength {
static length: number; // error
~~~~~~
!!! error TS2692: Static property 'length' conflicts with built-in property 'Function.length' of constructor function 'StaticLength'.
length: string; // ok
}
class StaticLengthFn {
static length() {} // error
~~~~~~
!!! error TS2692: Static property 'length' conflicts with built-in property 'Function.length' of constructor function 'StaticLengthFn'.
length() {} // ok
}
class StaticPrototype {
static prototype: number; // error
~~~~~~~~~
!!! error TS2692: Static property 'prototype' conflicts with built-in property 'Function.prototype' of constructor function 'StaticPrototype'.
prototype: string; // ok
}
class StaticPrototypeFn {
static prototype() {} // error
~~~~~~~~~
!!! error TS2300: Duplicate identifier 'prototype'.
~~~~~~~~~
!!! error TS2692: Static property 'prototype' conflicts with built-in property 'Function.prototype' of constructor function 'StaticPrototypeFn'.
prototype() {} // ok
}
class StaticCaller {
static caller: number; // error
~~~~~~
!!! error TS2692: Static property 'caller' conflicts with built-in property 'Function.caller' of constructor function 'StaticCaller'.
caller: string; // ok
}
class StaticCallerFn {
static caller() {} // error
~~~~~~
!!! error TS2692: Static property 'caller' conflicts with built-in property 'Function.caller' of constructor function 'StaticCallerFn'.
caller() {} // ok
}
class StaticArguments {
static arguments: number; // error
~~~~~~~~~
!!! error TS2692: Static property 'arguments' conflicts with built-in property 'Function.arguments' of constructor function 'StaticArguments'.
arguments: string; // ok
}
class StaticArgumentsFn {
static arguments() {} // error
~~~~~~~~~
!!! error TS2692: Static property 'arguments' conflicts with built-in property 'Function.arguments' of constructor function 'StaticArgumentsFn'.
arguments() {} // ok
}

View File

@@ -0,0 +1,120 @@
//// [staticPropertyNameConflictsEs5.ts]
// static name
class StaticName {
static name: number; // error
name: string; // ok
}
class StaticNameFn {
static name() {} // error
name() {} // ok
}
class StaticLength {
static length: number; // error
length: string; // ok
}
class StaticLengthFn {
static length() {} // error
length() {} // ok
}
class StaticPrototype {
static prototype: number; // error
prototype: string; // ok
}
class StaticPrototypeFn {
static prototype() {} // error
prototype() {} // ok
}
class StaticCaller {
static caller: number; // error
caller: string; // ok
}
class StaticCallerFn {
static caller() {} // error
caller() {} // ok
}
class StaticArguments {
static arguments: number; // error
arguments: string; // ok
}
class StaticArgumentsFn {
static arguments() {} // error
arguments() {} // ok
}
//// [staticPropertyNameConflictsEs5.js]
// static name
var StaticName = (function () {
function StaticName() {
}
return StaticName;
}());
var StaticNameFn = (function () {
function StaticNameFn() {
}
StaticNameFn.name = function () { }; // error
StaticNameFn.prototype.name = function () { }; // ok
return StaticNameFn;
}());
var StaticLength = (function () {
function StaticLength() {
}
return StaticLength;
}());
var StaticLengthFn = (function () {
function StaticLengthFn() {
}
StaticLengthFn.length = function () { }; // error
StaticLengthFn.prototype.length = function () { }; // ok
return StaticLengthFn;
}());
var StaticPrototype = (function () {
function StaticPrototype() {
}
return StaticPrototype;
}());
var StaticPrototypeFn = (function () {
function StaticPrototypeFn() {
}
StaticPrototypeFn.prototype = function () { }; // error
StaticPrototypeFn.prototype.prototype = function () { }; // ok
return StaticPrototypeFn;
}());
var StaticCaller = (function () {
function StaticCaller() {
}
return StaticCaller;
}());
var StaticCallerFn = (function () {
function StaticCallerFn() {
}
StaticCallerFn.caller = function () { }; // error
StaticCallerFn.prototype.caller = function () { }; // ok
return StaticCallerFn;
}());
var StaticArguments = (function () {
function StaticArguments() {
}
return StaticArguments;
}());
var StaticArgumentsFn = (function () {
function StaticArgumentsFn() {
}
StaticArgumentsFn.arguments = function () { }; // error
StaticArgumentsFn.prototype.arguments = function () { }; // ok
return StaticArgumentsFn;
}());

View File

@@ -0,0 +1,80 @@
tests/cases/conformance/classes/propertyMemberDeclarations/staticPropertyNameConflictsEs6.ts(26,12): error TS2692: Static property 'prototype' conflicts with built-in property 'Function.prototype' of constructor function 'StaticPrototype'.
tests/cases/conformance/classes/propertyMemberDeclarations/staticPropertyNameConflictsEs6.ts(31,12): error TS2300: Duplicate identifier 'prototype'.
tests/cases/conformance/classes/propertyMemberDeclarations/staticPropertyNameConflictsEs6.ts(31,12): error TS2692: Static property 'prototype' conflicts with built-in property 'Function.prototype' of constructor function 'StaticPrototypeFn'.
tests/cases/conformance/classes/propertyMemberDeclarations/staticPropertyNameConflictsEs6.ts(37,12): error TS2692: Static property 'caller' conflicts with built-in property 'Function.caller' of constructor function 'StaticCaller'.
tests/cases/conformance/classes/propertyMemberDeclarations/staticPropertyNameConflictsEs6.ts(42,12): error TS2692: Static property 'caller' conflicts with built-in property 'Function.caller' of constructor function 'StaticCallerFn'.
tests/cases/conformance/classes/propertyMemberDeclarations/staticPropertyNameConflictsEs6.ts(48,12): error TS2692: Static property 'arguments' conflicts with built-in property 'Function.arguments' of constructor function 'StaticArguments'.
tests/cases/conformance/classes/propertyMemberDeclarations/staticPropertyNameConflictsEs6.ts(53,12): error TS2692: Static property 'arguments' conflicts with built-in property 'Function.arguments' of constructor function 'StaticArgumentsFn'.
==== tests/cases/conformance/classes/propertyMemberDeclarations/staticPropertyNameConflictsEs6.ts (7 errors) ====
class StaticName {
static name: number; // ok
name: string; // ok
}
class StaticNameFn {
static name() {} // ok
name() {} // ok
}
class StaticLength {
static length: number; // ok
length: string; // ok
}
class StaticLengthFn {
static length() {} // ok
length() {} // ok
}
class StaticPrototype {
static prototype: number; // error
~~~~~~~~~
!!! error TS2692: Static property 'prototype' conflicts with built-in property 'Function.prototype' of constructor function 'StaticPrototype'.
prototype: string; // ok
}
class StaticPrototypeFn {
static prototype() {} // error
~~~~~~~~~
!!! error TS2300: Duplicate identifier 'prototype'.
~~~~~~~~~
!!! error TS2692: Static property 'prototype' conflicts with built-in property 'Function.prototype' of constructor function 'StaticPrototypeFn'.
prototype() {} // ok
}
class StaticCaller {
static caller: number; // // error
~~~~~~
!!! error TS2692: Static property 'caller' conflicts with built-in property 'Function.caller' of constructor function 'StaticCaller'.
caller: string; // ok
}
class StaticCallerFn {
static caller() {} // // error
~~~~~~
!!! error TS2692: Static property 'caller' conflicts with built-in property 'Function.caller' of constructor function 'StaticCallerFn'.
caller() {} // ok
}
class StaticArguments {
static arguments: number; // // error
~~~~~~~~~
!!! error TS2692: Static property 'arguments' conflicts with built-in property 'Function.arguments' of constructor function 'StaticArguments'.
arguments: string; // ok
}
class StaticArgumentsFn {
static arguments() {} // // error
~~~~~~~~~
!!! error TS2692: Static property 'arguments' conflicts with built-in property 'Function.arguments' of constructor function 'StaticArgumentsFn'.
arguments() {} // ok
}

View File

@@ -0,0 +1,89 @@
//// [staticPropertyNameConflictsEs6.ts]
class StaticName {
static name: number; // ok
name: string; // ok
}
class StaticNameFn {
static name() {} // ok
name() {} // ok
}
class StaticLength {
static length: number; // ok
length: string; // ok
}
class StaticLengthFn {
static length() {} // ok
length() {} // ok
}
class StaticPrototype {
static prototype: number; // error
prototype: string; // ok
}
class StaticPrototypeFn {
static prototype() {} // error
prototype() {} // ok
}
class StaticCaller {
static caller: number; // // error
caller: string; // ok
}
class StaticCallerFn {
static caller() {} // // error
caller() {} // ok
}
class StaticArguments {
static arguments: number; // // error
arguments: string; // ok
}
class StaticArgumentsFn {
static arguments() {} // // error
arguments() {} // ok
}
//// [staticPropertyNameConflictsEs6.js]
class StaticName {
}
class StaticNameFn {
static name() { } // ok
name() { } // ok
}
class StaticLength {
}
class StaticLengthFn {
static length() { } // ok
length() { } // ok
}
class StaticPrototype {
}
class StaticPrototypeFn {
static prototype() { } // error
prototype() { } // ok
}
class StaticCaller {
}
class StaticCallerFn {
static caller() { } // // error
caller() { } // ok
}
class StaticArguments {
}
class StaticArgumentsFn {
static arguments() { } // // error
arguments() { } // ok
}

View File

@@ -1,13 +1,19 @@
tests/cases/compiler/staticPrototypeProperty.ts(2,11): error TS2300: Duplicate identifier 'prototype'.
tests/cases/compiler/staticPrototypeProperty.ts(2,11): error TS2692: Static property 'prototype' conflicts with built-in property 'Function.prototype' of constructor function 'C'.
tests/cases/compiler/staticPrototypeProperty.ts(6,11): error TS2692: Static property 'prototype' conflicts with built-in property 'Function.prototype' of constructor function 'C2'.
==== tests/cases/compiler/staticPrototypeProperty.ts (1 errors) ====
==== tests/cases/compiler/staticPrototypeProperty.ts (3 errors) ====
class C {
static prototype() { }
~~~~~~~~~
!!! error TS2300: Duplicate identifier 'prototype'.
~~~~~~~~~
!!! error TS2692: Static property 'prototype' conflicts with built-in property 'Function.prototype' of constructor function 'C'.
}
class C2 {
static prototype;
~~~~~~~~~
!!! error TS2692: Static property 'prototype' conflicts with built-in property 'Function.prototype' of constructor function 'C2'.
}

View File

@@ -1,20 +1,20 @@
interface A {
name();
prop();
}
class B {
public name() { }
public prop() { }
}
class C {
public static name() { }
public static prop() { }
}
var a: A = new B();
a = new C(); // error name is missing
a = B; // error name is missing
a = new C(); // error prop is missing
a = B; // error prop is missing
a = C;
var b: B = new C(); // error name is missing
b = B; // error name is missing
var b: B = new C(); // error prop is missing
b = B; // error prop is missing
b = C;
b = a;

View File

@@ -1,26 +1,56 @@
// @target: es5
// static name
class A {
class StaticName {
static name: number; // error
name: string; // ok
}
class B {
class StaticNameFn {
static name() {} // error
name() {} // ok
}
// static length...
class C {
class StaticLength {
static length: number; // error
length: string; // ok
}
class D {
class StaticLengthFn {
static length() {} // error
length() {} // ok
}
class StaticPrototype {
static prototype: number; // error
prototype: string; // ok
}
class StaticPrototypeFn {
static prototype() {} // error
prototype() {} // ok
}
class StaticCaller {
static caller: number; // error
caller: string; // ok
}
class StaticCallerFn {
static caller() {} // error
caller() {} // ok
}
class StaticArguments {
static arguments: number; // error
arguments: string; // ok
}
class StaticArgumentsFn {
static arguments() {} // error
arguments() {} // ok
}

View File

@@ -1,25 +1,56 @@
// @target: es6
// static name
class A {
static name: string; // ok
class StaticName {
static name: number; // ok
name: string; // ok
}
class B {
static name() {}; // ok
name() {}; // ok
class StaticNameFn {
static name() {} // ok
name() {} // ok
}
// static length
class C {
class StaticLength {
static length: number; // ok
length: string; // ok
}
class D {
class StaticLengthFn {
static length() {} // ok
length() {} // ok
}
class StaticPrototype {
static prototype: number; // error
prototype: string; // ok
}
class StaticPrototypeFn {
static prototype() {} // error
prototype() {} // ok
}
class StaticCaller {
static caller: number; // // error
caller: string; // ok
}
class StaticCallerFn {
static caller() {} // // error
caller() {} // ok
}
class StaticArguments {
static arguments: number; // // error
arguments: string; // ok
}
class StaticArgumentsFn {
static arguments() {} // // error
arguments() {} // ok
}