@@ -88,8 +88,16 @@ namespace ts {
88
88
const emitResolver = createResolver();
89
89
const nodeBuilder = createNodeBuilder();
90
90
91
+ const globals = createSymbolTable();
91
92
const undefinedSymbol = createSymbol(SymbolFlags.Property, "undefined" as __String);
92
93
undefinedSymbol.declarations = [];
94
+
95
+ const globalThisSymbol = createSymbol(SymbolFlags.Module, "globalThis" as __String, CheckFlags.Readonly);
96
+ globalThisSymbol.exports = globals;
97
+ globalThisSymbol.valueDeclaration = createNode(SyntaxKind.Identifier) as Identifier;
98
+ (globalThisSymbol.valueDeclaration as Identifier).escapedText = "globalThis" as __String;
99
+ globals.set(globalThisSymbol.escapedName, globalThisSymbol);
100
+
93
101
const argumentsSymbol = createSymbol(SymbolFlags.Property, "arguments" as __String);
94
102
const requireSymbol = createSymbol(SymbolFlags.Property, "require" as __String);
95
103
@@ -310,9 +318,9 @@ namespace ts {
310
318
getAccessibleSymbolChain,
311
319
getTypePredicateOfSignature: getTypePredicateOfSignature as (signature: Signature) => TypePredicate, // TODO: GH#18217
312
320
resolveExternalModuleSymbol,
313
- tryGetThisTypeAt: node => {
321
+ tryGetThisTypeAt: ( node, includeGlobalThis) => {
314
322
node = getParseTreeNode(node);
315
- return node && tryGetThisTypeAt(node);
323
+ return node && tryGetThisTypeAt(node, includeGlobalThis );
316
324
},
317
325
getTypeArgumentConstraint: nodeIn => {
318
326
const node = getParseTreeNode(nodeIn, isTypeNode);
@@ -459,7 +467,6 @@ namespace ts {
459
467
460
468
const enumNumberIndexInfo = createIndexInfo(stringType, /*isReadonly*/ true);
461
469
462
- const globals = createSymbolTable();
463
470
interface DuplicateInfoForSymbol {
464
471
readonly firstFileLocations: Node[];
465
472
readonly secondFileLocations: Node[];
@@ -9711,7 +9718,7 @@ namespace ts {
9711
9718
}
9712
9719
9713
9720
function getLiteralTypeFromProperties(type: Type, include: TypeFlags) {
9714
- return getUnionType(map(getPropertiesOfType(type), t => getLiteralTypeFromProperty(t , include)));
9721
+ return getUnionType(map(getPropertiesOfType(type), p => getLiteralTypeFromProperty(p , include)));
9715
9722
}
9716
9723
9717
9724
function getNonEnumNumberIndexInfo(type: Type) {
@@ -12830,20 +12837,30 @@ namespace ts {
12830
12837
}
12831
12838
return Ternary.False;
12832
12839
12840
+ function isNonGeneric(type: Type) {
12841
+ // If we're already in identity relationship checking, we should use `isRelatedTo`
12842
+ // to catch the `Maybe` from an excessively deep type (which we then assume means
12843
+ // that the type could possibly contain a generic)
12844
+ if (relation === identityRelation) {
12845
+ return isRelatedTo(type, getPermissiveInstantiation(type)) === Ternary.True;
12846
+ }
12847
+ return isTypeIdenticalTo(type, getPermissiveInstantiation(type));
12848
+ }
12849
+
12833
12850
function relateVariances(sourceTypeArguments: ReadonlyArray<Type> | undefined, targetTypeArguments: ReadonlyArray<Type> | undefined, variances: Variance[]) {
12834
12851
if (result = typeArgumentsRelatedTo(sourceTypeArguments, targetTypeArguments, variances, reportErrors)) {
12835
12852
return result;
12836
12853
}
12837
- const isCovariantVoid = targetTypeArguments && hasCovariantVoidArgument(targetTypeArguments, variances);
12838
- varianceCheckFailed = !isCovariantVoid ;
12854
+ const allowStructuralFallback = ( targetTypeArguments && hasCovariantVoidArgument(targetTypeArguments, variances)) || isNonGeneric(source) || isNonGeneric(target );
12855
+ varianceCheckFailed = !allowStructuralFallback ;
12839
12856
// The type arguments did not relate appropriately, but it may be because we have no variance
12840
12857
// information (in which case typeArgumentsRelatedTo defaulted to covariance for all type
12841
12858
// arguments). It might also be the case that the target type has a 'void' type argument for
12842
12859
// a covariant type parameter that is only used in return positions within the generic type
12843
12860
// (in which case any type argument is permitted on the source side). In those cases we proceed
12844
12861
// with a structural comparison. Otherwise, we know for certain the instantiations aren't
12845
12862
// related and we can return here.
12846
- if (variances !== emptyArray && !isCovariantVoid ) {
12863
+ if (variances !== emptyArray && !allowStructuralFallback ) {
12847
12864
// In some cases generic types that are covariant in regular type checking mode become
12848
12865
// invariant in --strictFunctionTypes mode because one or more type parameters are used in
12849
12866
// both co- and contravariant positions. In order to make it easier to diagnose *why* such
@@ -16988,25 +17005,27 @@ namespace ts {
16988
17005
captureLexicalThis(node, container);
16989
17006
}
16990
17007
16991
- const type = tryGetThisTypeAt(node, container);
16992
- if (!type && noImplicitThis) {
16993
- // With noImplicitThis, functions may not reference 'this' if it has type 'any'
16994
- const diag = error(
16995
- node,
16996
- capturedByArrowFunction && container.kind === SyntaxKind.SourceFile ?
16997
- Diagnostics.The_containing_arrow_function_captures_the_global_value_of_this_which_implicitly_has_type_any :
16998
- Diagnostics.this_implicitly_has_type_any_because_it_does_not_have_a_type_annotation);
16999
- if (!isSourceFile(container)) {
17000
- const outsideThis = tryGetThisTypeAt(container);
17001
- if (outsideThis) {
17002
- addRelatedInfo(diag, createDiagnosticForNode(container, Diagnostics.An_outer_value_of_this_is_shadowed_by_this_container));
17008
+ const type = tryGetThisTypeAt(node, /*includeGlobalThis*/ true, container);
17009
+ if (noImplicitThis) {
17010
+ const globalThisType = getTypeOfSymbol(globalThisSymbol);
17011
+ if (type === globalThisType && capturedByArrowFunction) {
17012
+ error(node, Diagnostics.The_containing_arrow_function_captures_the_global_value_of_this);
17013
+ }
17014
+ else if (!type) {
17015
+ // With noImplicitThis, functions may not reference 'this' if it has type 'any'
17016
+ const diag = error(node, Diagnostics.this_implicitly_has_type_any_because_it_does_not_have_a_type_annotation);
17017
+ if (!isSourceFile(container)) {
17018
+ const outsideThis = tryGetThisTypeAt(container);
17019
+ if (outsideThis && outsideThis !== globalThisType) {
17020
+ addRelatedInfo(diag, createDiagnosticForNode(container, Diagnostics.An_outer_value_of_this_is_shadowed_by_this_container));
17021
+ }
17003
17022
}
17004
17023
}
17005
17024
}
17006
17025
return type || anyType;
17007
17026
}
17008
17027
17009
- function tryGetThisTypeAt(node: Node, container = getThisContainer(node, /*includeArrowFunctions*/ false)): Type | undefined {
17028
+ function tryGetThisTypeAt(node: Node, includeGlobalThis = true, container = getThisContainer(node, /*includeArrowFunctions*/ false)): Type | undefined {
17010
17029
const isInJS = isInJSFile(node);
17011
17030
if (isFunctionLike(container) &&
17012
17031
(!isInParameterInitializerBeforeContainingFunction(node) || getThisParameter(container))) {
@@ -17053,6 +17072,16 @@ namespace ts {
17053
17072
return getFlowTypeOfReference(node, type);
17054
17073
}
17055
17074
}
17075
+ if (isSourceFile(container)) {
17076
+ // look up in the source file's locals or exports
17077
+ if (container.commonJsModuleIndicator) {
17078
+ const fileSymbol = getSymbolOfNode(container);
17079
+ return fileSymbol && getTypeOfSymbol(fileSymbol);
17080
+ }
17081
+ else if (includeGlobalThis) {
17082
+ return getTypeOfSymbol(globalThisSymbol);
17083
+ }
17084
+ }
17056
17085
}
17057
17086
17058
17087
function getClassNameFromPrototypeMethod(container: Node) {
@@ -19393,6 +19422,12 @@ namespace ts {
19393
19422
if (isJSLiteralType(leftType)) {
19394
19423
return anyType;
19395
19424
}
19425
+ if (leftType.symbol === globalThisSymbol) {
19426
+ if (noImplicitAny) {
19427
+ error(right, Diagnostics.Element_implicitly_has_an_any_type_because_type_0_has_no_index_signature, typeToString(leftType));
19428
+ }
19429
+ return anyType;
19430
+ }
19396
19431
if (right.escapedText && !checkAndReportErrorForExtendingInterface(node)) {
19397
19432
reportNonexistentProperty(right, leftType.flags & TypeFlags.TypeParameter && (leftType as TypeParameter).isThisType ? apparentType : leftType);
19398
19433
}
0 commit comments