Skip to content

Commit 8a37a16

Browse files
committed
Fix for issue #442
1 parent fc5b2e5 commit 8a37a16

13 files changed

+558
-52
lines changed

src/compiler/checker.ts

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13922,6 +13922,50 @@ namespace ts {
1392213922
}
1392313923
}
1392413924

13925+
// Static members may conflict with non-configurable non-writable built-in Function.prototype properties
13926+
// see https://github.com/microsoft/typescript/issues/442.
13927+
function checkClassForStaticPropertyNameConflicts(node: ClassLikeDeclaration) {
13928+
const es5_descriptors: PropertyDescriptorMap = {
13929+
// see http://www.ecma-international.org/ecma-262/5.1/#sec-15.3.3
13930+
// see http://www.ecma-international.org/ecma-262/5.1/#sec-15.3.5
13931+
"name": {configurable: false, writable: false},
13932+
"length": {configurable: false, writable: false},
13933+
"prototype": {configurable: false, writable: false},
13934+
13935+
// see https://github.com/microsoft/typescript/issues/442
13936+
"caller": {configurable: false, writable: false},
13937+
"arguments": {configurable: false, writable: false}
13938+
};
13939+
const post_es5_descriptors: PropertyDescriptorMap = {
13940+
// see http://www.ecma-international.org/ecma-262/6.0/#sec-properties-of-the-function-constructor
13941+
// see http://www.ecma-international.org/ecma-262/6.0/#sec-function-instances
13942+
"name": {configurable: true, writable: false},
13943+
"length": {configurable: true, writable: false},
13944+
"prototype": {configurable: false, writable: false},
13945+
"caller": {configurable: false, writable: false},
13946+
"arguments": {configurable: false, writable: false}
13947+
};
13948+
const message = Diagnostics.Static_property_0_conflicts_with_built_in_property_Function_0_of_constructor_function_1;
13949+
const className = getSymbolOfNode(node).name;
13950+
13951+
for (let member of node.members) {
13952+
let isStatic = forEach(member.modifiers, (m:Modifier) => m.kind === SyntaxKind.StaticKeyword);
13953+
if (isStatic) {
13954+
let memberNameNode = member.name;
13955+
let memberName = getPropertyNameForPropertyNameNode(memberNameNode);
13956+
let descriptor: PropertyDescriptor = null;
13957+
if (languageVersion <= ScriptTarget.ES5) {
13958+
descriptor = es5_descriptors.hasOwnProperty(memberName) ? es5_descriptors[memberName] : null;
13959+
} else if (languageVersion > ScriptTarget.ES5) {
13960+
descriptor = post_es5_descriptors.hasOwnProperty(memberName) ? post_es5_descriptors[memberName] : null;
13961+
}
13962+
if (descriptor && descriptor.configurable === false && descriptor.writable === false) {
13963+
error(memberNameNode, message, memberName, className);
13964+
}
13965+
}
13966+
}
13967+
}
13968+
1392513969
function checkObjectTypeForDuplicateDeclarations(node: TypeLiteralNode | InterfaceDeclaration) {
1392613970
const names = createMap<boolean>();
1392713971
for (const member of node.members) {
@@ -16423,6 +16467,7 @@ namespace ts {
1642316467
const staticType = <ObjectType>getTypeOfSymbol(symbol);
1642416468
checkTypeParameterListsIdentical(node, symbol);
1642516469
checkClassForDuplicateDeclarations(node);
16470+
checkClassForStaticPropertyNameConflicts(node);
1642616471

1642716472
const baseTypeNode = getClassExtendsHeritageClauseElement(node);
1642816473
if (baseTypeNode) {

src/compiler/diagnosticMessages.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1955,6 +1955,10 @@
19551955
"category": "Error",
19561956
"code": 2691
19571957
},
1958+
"Static property '{0}' conflicts with built-in property 'Function.{0}' of constructor function '{1}'.": {
1959+
"category": "Error",
1960+
"code": 2692
1961+
},
19581962
"Import declaration '{0}' is using private name '{1}'.": {
19591963
"category": "Error",
19601964
"code": 4000
@@ -2239,7 +2243,6 @@
22392243
"category": "Message",
22402244
"code": 4090
22412245
},
2242-
22432246
"The current host does not support the '{0}' option.": {
22442247
"category": "Error",
22452248
"code": 5001
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
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'.
2+
3+
4+
==== tests/cases/conformance/classes/propertyMemberDeclarations/propertyNamedPrototype.ts (1 errors) ====
5+
class C {
6+
prototype: number; // ok
7+
static prototype: C; // error
8+
~~~~~~~~~
9+
!!! error TS2692: Static property 'prototype' conflicts with built-in property 'Function.prototype' of constructor function 'C'.
10+
}

tests/baselines/reference/staticMemberOfClassAndPublicMemberOfAnotherClassAssignment.errors.txt

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,43 @@
11
tests/cases/compiler/staticMemberOfClassAndPublicMemberOfAnotherClassAssignment.ts(12,1): error TS2322: Type 'C' is not assignable to type 'A'.
2-
Property 'name' is missing in type 'C'.
2+
Property 'prop' is missing in type 'C'.
33
tests/cases/compiler/staticMemberOfClassAndPublicMemberOfAnotherClassAssignment.ts(13,1): error TS2322: Type 'typeof B' is not assignable to type 'A'.
4-
Property 'name' is missing in type 'typeof B'.
4+
Property 'prop' is missing in type 'typeof B'.
55
tests/cases/compiler/staticMemberOfClassAndPublicMemberOfAnotherClassAssignment.ts(16,5): error TS2322: Type 'C' is not assignable to type 'B'.
6-
Property 'name' is missing in type 'C'.
6+
Property 'prop' is missing in type 'C'.
77
tests/cases/compiler/staticMemberOfClassAndPublicMemberOfAnotherClassAssignment.ts(17,1): error TS2322: Type 'typeof B' is not assignable to type 'B'.
8-
Property 'name' is missing in type 'typeof B'.
8+
Property 'prop' is missing in type 'typeof B'.
99

1010

1111
==== tests/cases/compiler/staticMemberOfClassAndPublicMemberOfAnotherClassAssignment.ts (4 errors) ====
1212
interface A {
13-
name();
13+
prop();
1414
}
1515
class B {
16-
public name() { }
16+
public prop() { }
1717
}
1818
class C {
19-
public static name() { }
19+
public static prop() { }
2020
}
2121

2222
var a: A = new B();
23-
a = new C(); // error name is missing
23+
a = new C(); // error prop is missing
2424
~
2525
!!! error TS2322: Type 'C' is not assignable to type 'A'.
26-
!!! error TS2322: Property 'name' is missing in type 'C'.
27-
a = B; // error name is missing
26+
!!! error TS2322: Property 'prop' is missing in type 'C'.
27+
a = B; // error prop is missing
2828
~
2929
!!! error TS2322: Type 'typeof B' is not assignable to type 'A'.
30-
!!! error TS2322: Property 'name' is missing in type 'typeof B'.
30+
!!! error TS2322: Property 'prop' is missing in type 'typeof B'.
3131
a = C;
3232

33-
var b: B = new C(); // error name is missing
33+
var b: B = new C(); // error prop is missing
3434
~
3535
!!! error TS2322: Type 'C' is not assignable to type 'B'.
36-
!!! error TS2322: Property 'name' is missing in type 'C'.
37-
b = B; // error name is missing
36+
!!! error TS2322: Property 'prop' is missing in type 'C'.
37+
b = B; // error prop is missing
3838
~
3939
!!! error TS2322: Type 'typeof B' is not assignable to type 'B'.
40-
!!! error TS2322: Property 'name' is missing in type 'typeof B'.
40+
!!! error TS2322: Property 'prop' is missing in type 'typeof B'.
4141
b = C;
4242
b = a;
4343

tests/baselines/reference/staticMemberOfClassAndPublicMemberOfAnotherClassAssignment.js

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,21 @@
11
//// [staticMemberOfClassAndPublicMemberOfAnotherClassAssignment.ts]
22
interface A {
3-
name();
3+
prop();
44
}
55
class B {
6-
public name() { }
6+
public prop() { }
77
}
88
class C {
9-
public static name() { }
9+
public static prop() { }
1010
}
1111

1212
var a: A = new B();
13-
a = new C(); // error name is missing
14-
a = B; // error name is missing
13+
a = new C(); // error prop is missing
14+
a = B; // error prop is missing
1515
a = C;
1616

17-
var b: B = new C(); // error name is missing
18-
b = B; // error name is missing
17+
var b: B = new C(); // error prop is missing
18+
b = B; // error prop is missing
1919
b = C;
2020
b = a;
2121

@@ -29,21 +29,21 @@ c = a;
2929
var B = (function () {
3030
function B() {
3131
}
32-
B.prototype.name = function () { };
32+
B.prototype.prop = function () { };
3333
return B;
3434
}());
3535
var C = (function () {
3636
function C() {
3737
}
38-
C.name = function () { };
38+
C.prop = function () { };
3939
return C;
4040
}());
4141
var a = new B();
42-
a = new C(); // error name is missing
43-
a = B; // error name is missing
42+
a = new C(); // error prop is missing
43+
a = B; // error prop is missing
4444
a = C;
45-
var b = new C(); // error name is missing
46-
b = B; // error name is missing
45+
var b = new C(); // error prop is missing
46+
b = B; // error prop is missing
4747
b = C;
4848
b = a;
4949
var c = new B();
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
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'.
2+
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'.
3+
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'.
4+
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'.
5+
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'.
6+
tests/cases/conformance/classes/propertyMemberDeclarations/staticPropertyNameConflictsEs5.ts(31,12): error TS2300: Duplicate identifier 'prototype'.
7+
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'.
8+
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'.
9+
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'.
10+
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'.
11+
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'.
12+
13+
14+
==== tests/cases/conformance/classes/propertyMemberDeclarations/staticPropertyNameConflictsEs5.ts (11 errors) ====
15+
16+
// static name
17+
class StaticName {
18+
static name: number; // error
19+
~~~~
20+
!!! error TS2692: Static property 'name' conflicts with built-in property 'Function.name' of constructor function 'StaticName'.
21+
name: string; // ok
22+
}
23+
24+
class StaticNameFn {
25+
static name() {} // error
26+
~~~~
27+
!!! error TS2692: Static property 'name' conflicts with built-in property 'Function.name' of constructor function 'StaticNameFn'.
28+
name() {} // ok
29+
}
30+
31+
32+
class StaticLength {
33+
static length: number; // error
34+
~~~~~~
35+
!!! error TS2692: Static property 'length' conflicts with built-in property 'Function.length' of constructor function 'StaticLength'.
36+
length: string; // ok
37+
}
38+
39+
class StaticLengthFn {
40+
static length() {} // error
41+
~~~~~~
42+
!!! error TS2692: Static property 'length' conflicts with built-in property 'Function.length' of constructor function 'StaticLengthFn'.
43+
length() {} // ok
44+
}
45+
46+
47+
class StaticPrototype {
48+
static prototype: number; // error
49+
~~~~~~~~~
50+
!!! error TS2692: Static property 'prototype' conflicts with built-in property 'Function.prototype' of constructor function 'StaticPrototype'.
51+
prototype: string; // ok
52+
}
53+
54+
class StaticPrototypeFn {
55+
static prototype() {} // error
56+
~~~~~~~~~
57+
!!! error TS2300: Duplicate identifier 'prototype'.
58+
~~~~~~~~~
59+
!!! error TS2692: Static property 'prototype' conflicts with built-in property 'Function.prototype' of constructor function 'StaticPrototypeFn'.
60+
prototype() {} // ok
61+
}
62+
63+
64+
class StaticCaller {
65+
static caller: number; // error
66+
~~~~~~
67+
!!! error TS2692: Static property 'caller' conflicts with built-in property 'Function.caller' of constructor function 'StaticCaller'.
68+
caller: string; // ok
69+
}
70+
71+
class StaticCallerFn {
72+
static caller() {} // error
73+
~~~~~~
74+
!!! error TS2692: Static property 'caller' conflicts with built-in property 'Function.caller' of constructor function 'StaticCallerFn'.
75+
caller() {} // ok
76+
}
77+
78+
79+
class StaticArguments {
80+
static arguments: number; // error
81+
~~~~~~~~~
82+
!!! error TS2692: Static property 'arguments' conflicts with built-in property 'Function.arguments' of constructor function 'StaticArguments'.
83+
arguments: string; // ok
84+
}
85+
86+
class StaticArgumentsFn {
87+
static arguments() {} // error
88+
~~~~~~~~~
89+
!!! error TS2692: Static property 'arguments' conflicts with built-in property 'Function.arguments' of constructor function 'StaticArgumentsFn'.
90+
arguments() {} // ok
91+
}
92+

0 commit comments

Comments
 (0)