Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit4c09ccd

Browse files
committed
Check that Symbol properties are proper, and support downlevel type checking
1 parent3834edd commit4c09ccd

File tree

32 files changed

+457
-27
lines changed

32 files changed

+457
-27
lines changed

‎src/compiler/checker.ts‎

Lines changed: 48 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,6 @@ module ts {
9696
var globalRegExpType: ObjectType;
9797
var globalTemplateStringsArrayType: ObjectType;
9898
var globalESSymbolType: ObjectType;
99-
var globalESSymbolConstructorType: ObjectType;
10099

101100
var anyArrayType: Type;
102101

@@ -3032,6 +3031,10 @@ module ts {
30323031
return getTypeOfGlobalSymbol(getGlobalTypeSymbol(name), 0);
30333032
}
30343033

3034+
function getGlobalESSymbolConstructorSymbol() {
3035+
return globalESSymbolConstructorSymbol || (globalESSymbolConstructorSymbol = getGlobalValueSymbol("Symbol"));
3036+
}
3037+
30353038
function createArrayType(elementType: Type): Type {
30363039
// globalArrayType will be undefined if we get here during creation of the Array type. This for example happens if
30373040
// user code augments the Array type with call or construct signatures that have an array type as the return type.
@@ -5541,12 +5544,7 @@ module ts {
55415544
error(node, Diagnostics.A_computed_property_name_must_be_of_type_string_number_symbol_or_any);
55425545
}
55435546
else if (isWellKnownSymbolSyntactically(node.expression)) {
5544-
// If it's not ES6, error
5545-
// Check that Symbol corresponds to global symbol, and that property exists, and that it's a symbol
5546-
}
5547-
else {
5548-
// Some syntactic forms require that the property name be a well known symbol.
5549-
// Will move the grammar checks here.
5547+
checkSymbolNameIsProperSymbolReference(<PropertyAccessExpression>node.expression, links.resolvedType, /*reportError*/ true);
55505548
}
55515549
}
55525550

@@ -5795,7 +5793,7 @@ module ts {
57955793

57965794
// See if we can index as a property.
57975795
if (node.argumentExpression) {
5798-
var name = getPropertyNameForIndexedAccess(node.argumentExpression);
5796+
var name = getPropertyNameForIndexedAccess(node.argumentExpression, indexType);
57995797
if (name !== undefined) {
58005798
var prop = getPropertyOfType(objectType, name);
58015799
if (prop) {
@@ -5846,12 +5844,12 @@ module ts {
58465844
* to this symbol, as long as it is a proper symbol reference.
58475845
* Otherwise, returns undefined.
58485846
*/
5849-
function getPropertyNameForIndexedAccess(indexArgumentExpression: Expression): string {
5847+
function getPropertyNameForIndexedAccess(indexArgumentExpression: Expression, indexArgumentType: Type): string {
58505848
if (indexArgumentExpression.kind === SyntaxKind.StringLiteral || indexArgumentExpression.kind === SyntaxKind.NumericLiteral) {
58515849
return (<LiteralExpression>indexArgumentExpression).text;
58525850
}
5853-
if (languageVersion >= ScriptTarget.ES6 &&isWellKnownSymbolSyntactically(indexArgumentExpression)) {
5854-
if (checkSymbolNameIsProperSymbolReference(<PropertyAccessExpression>indexArgumentExpression, /*reportError*/ false)) {
5851+
if (isWellKnownSymbolSyntactically(indexArgumentExpression)) {
5852+
if (checkSymbolNameIsProperSymbolReference(<PropertyAccessExpression>indexArgumentExpression,indexArgumentType,/*reportError*/ false)) {
58555853
var rightHandSideName = (<Identifier>(<PropertyAccessExpression>indexArgumentExpression).name).text;
58565854
return getPropertyNameForKnownSymbolName(rightHandSideName);
58575855
}
@@ -5862,31 +5860,52 @@ module ts {
58625860

58635861
/**
58645862
* A proper symbol reference requires the following:
5865-
* 1. The language version is at least ES6
5866-
* 2. The expression is of the form Symbol.<identifier>
5867-
* 3. Symbol in this context resolves to the global Symbol object
5868-
* 4. The property access denotes a property that is present on the global Symbol object
5869-
* 5. The property on the global Symbol object is of the primitive type symbol.
5863+
* 1. The expression is of the form Symbol.<identifier>
5864+
* 2. Symbol in this context resolves to the global Symbol object
5865+
* 3. The property access denotes a property that is present on the global Symbol object
5866+
* 4. The property on the global Symbol object is of the primitive type symbol.
58705867
*/
5871-
function checkSymbolNameIsProperSymbolReference(wellKnownSymbolName: PropertyAccessExpression, reportError: boolean): boolean {
5872-
if (languageVersion < ScriptTarget.ES6) {
5868+
function checkSymbolNameIsProperSymbolReference(wellKnownSymbolName: PropertyAccessExpression, propertyNameType: Type, reportError: boolean): boolean {
5869+
if (propertyNameType === unknownType) {
5870+
// There is already an error, so no need to report one.
58735871
return false;
58745872
}
58755873

58765874
Debug.assert(isWellKnownSymbolSyntactically(wellKnownSymbolName));
5875+
5876+
// Make sure the property type is the primitive symbol type
5877+
if ((propertyNameType.flags & TypeFlags.ESSymbol) === 0) {
5878+
if (reportError) {
5879+
error(wellKnownSymbolName, Diagnostics.A_computed_property_name_of_the_form_0_must_be_of_type_symbol, getTextOfNode(wellKnownSymbolName));
5880+
}
5881+
return false;
5882+
}
5883+
58775884
// The name is Symbol.<someName>, so make sure Symbol actually resolves to the
58785885
// global Symbol object
58795886
var leftHandSide = (<PropertyAccessExpression>wellKnownSymbolName).expression;
5887+
// Look up the global symbol, but don't report an error, since checking the actual expression
5888+
// would have reported an error.
58805889
var leftHandSideSymbol = resolveName(wellKnownSymbolName, (<Identifier>leftHandSide).text,
58815890
SymbolFlags.Value, /*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined);
5882-
if (leftHandSideSymbol !== globalESSymbolConstructorSymbol) {
5891+
if (!leftHandSideSymbol) {
58835892
return false;
58845893
}
58855894

5886-
// Make sure the property type is the primitive symbol type
5887-
var rightHandSideName = (<Identifier>(<PropertyAccessExpression>wellKnownSymbolName).name).text;
5888-
var esSymbolConstructorPropertyType = getTypeOfPropertyOfType(globalESSymbolConstructorType, rightHandSideName);
5889-
return !!(esSymbolConstructorPropertyType && esSymbolConstructorPropertyType.flags & TypeFlags.ESSymbol);
5895+
var globalESSymbol = getGlobalESSymbolConstructorSymbol();
5896+
if (!globalESSymbol) {
5897+
// Already errored when we tried to look up the symbol
5898+
return false;
5899+
}
5900+
5901+
if (leftHandSideSymbol !== globalESSymbol) {
5902+
if (reportError) {
5903+
error(leftHandSide, Diagnostics.Symbol_reference_does_not_refer_to_the_global_Symbol_constructor_object);
5904+
}
5905+
return false;
5906+
}
5907+
5908+
return true;
58905909
}
58915910

58925911
function resolveUntypedCall(node: CallLikeExpression): Signature {
@@ -10391,13 +10410,15 @@ module ts {
1039110410
globalTemplateStringsArrayType = getGlobalType("TemplateStringsArray");
1039210411
globalESSymbolType = getGlobalType("Symbol");
1039310412
globalESSymbolConstructorSymbol = getGlobalValueSymbol("Symbol");
10394-
globalESSymbolConstructorType = getTypeOfSymbol(globalESSymbolConstructorSymbol);
1039510413
}
1039610414
else {
1039710415
globalTemplateStringsArrayType = unknownType;
10398-
globalESSymbolType = unknownType;
10399-
globalESSymbolConstructorSymbol = unknownSymbol;
10400-
globalESSymbolConstructorType = unknownType;
10416+
10417+
// Consider putting Symbol interface in lib.d.ts. On the plus side, putting it in lib.d.ts would make it
10418+
// extensible for Polyfilling Symbols. But putting it into lib.d.ts could also break users that have
10419+
// a global Symbol already, particularly if it is a class.
10420+
globalESSymbolType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined);
10421+
globalESSymbolConstructorSymbol = undefined;
1040110422
}
1040210423

1040310424
anyArrayType = createArrayType(anyType);

‎src/compiler/diagnosticInformationMap.generated.ts‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -306,6 +306,8 @@ module ts {
306306
A_computed_property_name_cannot_reference_a_type_parameter_from_its_containing_type:{code:2467,category:DiagnosticCategory.Error,key:"A computed property name cannot reference a type parameter from its containing type."},
307307
Cannot_find_global_value_0:{code:2468,category:DiagnosticCategory.Error,key:"Cannot find global value '{0}'."},
308308
The_0_operator_cannot_be_applied_to_a_value_of_type_symbol:{code:2469,category:DiagnosticCategory.Error,key:"The '{0}' operator cannot be applied to a value of type 'symbol'."},
309+
Symbol_reference_does_not_refer_to_the_global_Symbol_constructor_object:{code:2470,category:DiagnosticCategory.Error,key:"'Symbol' reference does not refer to the global Symbol constructor object."},
310+
A_computed_property_name_of_the_form_0_must_be_of_type_symbol:{code:2471,category:DiagnosticCategory.Error,key:"A computed property name of the form '{0}' must be of type 'symbol'."},
309311
Import_declaration_0_is_using_private_name_1:{code:4000,category:DiagnosticCategory.Error,key:"Import declaration '{0}' is using private name '{1}'."},
310312
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}'."},
311313
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}'."},

‎src/compiler/diagnosticMessages.json‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1217,6 +1217,14 @@
12171217
"category":"Error",
12181218
"code":2469
12191219
},
1220+
"'Symbol' reference does not refer to the global Symbol constructor object.": {
1221+
"category":"Error",
1222+
"code":2470
1223+
},
1224+
"A computed property name of the form '{0}' must be of type 'symbol'.": {
1225+
"category":"Error",
1226+
"code":2471
1227+
},
12201228

12211229
"Import declaration '{0}' is using private name '{1}'.": {
12221230
"category":"Error",
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
tests/cases/conformance/Symbols/ES5SymbolProperty1.ts(7,5): error TS1167: Computed property names are only available when targeting ECMAScript 6 and higher.
2+
tests/cases/conformance/Symbols/ES5SymbolProperty1.ts(7,6): error TS2471: A computed property name of the form 'Symbol.foo' must be of type 'symbol'.
3+
4+
5+
==== tests/cases/conformance/Symbols/ES5SymbolProperty1.ts (2 errors) ====
6+
interface SymbolConstructor {
7+
foo: string;
8+
}
9+
var Symbol: SymbolConstructor;
10+
11+
var obj = {
12+
[Symbol.foo]: 0
13+
~~~~~~~~~~~~
14+
!!! error TS1167: Computed property names are only available when targeting ECMAScript 6 and higher.
15+
~~~~~~~~~~
16+
!!! error TS2471: A computed property name of the form 'Symbol.foo' must be of type 'symbol'.
17+
}
18+
19+
obj[Symbol.foo];
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
//// [ES5SymbolProperty1.ts]
2+
interfaceSymbolConstructor{
3+
foo:string;
4+
}
5+
varSymbol:SymbolConstructor;
6+
7+
varobj={
8+
[Symbol.foo]:0
9+
}
10+
11+
obj[Symbol.foo];
12+
13+
//// [ES5SymbolProperty1.js]
14+
varSymbol;
15+
varobj={
16+
[Symbol.foo]:0
17+
};
18+
obj[Symbol.foo];
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
tests/cases/conformance/Symbols/ES5SymbolProperty2.ts(5,9): error TS1167: Computed property names are only available when targeting ECMAScript 6 and higher.
2+
tests/cases/conformance/Symbols/ES5SymbolProperty2.ts(5,10): error TS2471: A computed property name of the form 'Symbol.iterator' must be of type 'symbol'.
3+
tests/cases/conformance/Symbols/ES5SymbolProperty2.ts(10,11): error TS2304: Cannot find name 'Symbol'.
4+
5+
6+
==== tests/cases/conformance/Symbols/ES5SymbolProperty2.ts (3 errors) ====
7+
module M {
8+
var Symbol;
9+
10+
export class C {
11+
[Symbol.iterator]() { }
12+
~~~~~~~~~~~~~~~~~
13+
!!! error TS1167: Computed property names are only available when targeting ECMAScript 6 and higher.
14+
~~~~~~~~~~~~~~~
15+
!!! error TS2471: A computed property name of the form 'Symbol.iterator' must be of type 'symbol'.
16+
}
17+
(new C)[Symbol.iterator];
18+
}
19+
20+
(new M.C)[Symbol.iterator];
21+
~~~~~~
22+
!!! error TS2304: Cannot find name 'Symbol'.
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
//// [ES5SymbolProperty2.ts]
2+
moduleM{
3+
varSymbol;
4+
5+
exportclassC{
6+
[Symbol.iterator](){}
7+
}
8+
(newC)[Symbol.iterator];
9+
}
10+
11+
(newM.C)[Symbol.iterator];
12+
13+
//// [ES5SymbolProperty2.js]
14+
varM;
15+
(function(M){
16+
varSymbol;
17+
varC=(function(){
18+
functionC(){
19+
}
20+
C.prototype[Symbol.iterator]=function(){
21+
};
22+
returnC;
23+
})();
24+
M.C=C;
25+
(newC)[Symbol.iterator];
26+
})(M||(M={}));
27+
(newM.C)[Symbol.iterator];
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
tests/cases/conformance/Symbols/ES5SymbolProperty3.ts(4,5): error TS1167: Computed property names are only available when targeting ECMAScript 6 and higher.
2+
tests/cases/conformance/Symbols/ES5SymbolProperty3.ts(4,6): error TS2471: A computed property name of the form 'Symbol.iterator' must be of type 'symbol'.
3+
4+
5+
==== tests/cases/conformance/Symbols/ES5SymbolProperty3.ts (2 errors) ====
6+
var Symbol;
7+
8+
class C {
9+
[Symbol.iterator]() { }
10+
~~~~~~~~~~~~~~~~~
11+
!!! error TS1167: Computed property names are only available when targeting ECMAScript 6 and higher.
12+
~~~~~~~~~~~~~~~
13+
!!! error TS2471: A computed property name of the form 'Symbol.iterator' must be of type 'symbol'.
14+
}
15+
16+
(new C)[Symbol.iterator]
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
//// [ES5SymbolProperty3.ts]
2+
varSymbol;
3+
4+
classC{
5+
[Symbol.iterator](){}
6+
}
7+
8+
(newC)[Symbol.iterator]
9+
10+
//// [ES5SymbolProperty3.js]
11+
varSymbol;
12+
varC=(function(){
13+
functionC(){
14+
}
15+
C.prototype[Symbol.iterator]=function(){
16+
};
17+
returnC;
18+
})();
19+
(newC)[Symbol.iterator];
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
tests/cases/conformance/Symbols/ES5SymbolProperty4.ts(4,5): error TS1167: Computed property names are only available when targeting ECMAScript 6 and higher.
2+
tests/cases/conformance/Symbols/ES5SymbolProperty4.ts(4,6): error TS2471: A computed property name of the form 'Symbol.iterator' must be of type 'symbol'.
3+
4+
5+
==== tests/cases/conformance/Symbols/ES5SymbolProperty4.ts (2 errors) ====
6+
var Symbol: { iterator: string };
7+
8+
class C {
9+
[Symbol.iterator]() { }
10+
~~~~~~~~~~~~~~~~~
11+
!!! error TS1167: Computed property names are only available when targeting ECMAScript 6 and higher.
12+
~~~~~~~~~~~~~~~
13+
!!! error TS2471: A computed property name of the form 'Symbol.iterator' must be of type 'symbol'.
14+
}
15+
16+
(new C)[Symbol.iterator]

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp