Skip to content

Commit 79d7f37

Browse files
committed
Merge branch 'master' into typesVersions
2 parents aa04ef5 + 13bd478 commit 79d7f37

28 files changed

+351
-58
lines changed

scripts/build/gulp-typescript-oop/protocol.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ function diagnosticFromJson(json, host) {
140140
category: json.category,
141141
code: json.code,
142142
source: json.source,
143-
relatedInformation: json.relatedInformation && json.relatedInformation.map(diagnosticRelatedInformationFromJson, host)
143+
relatedInformation: json.relatedInformation && json.relatedInformation.map(json => diagnosticRelatedInformationFromJson(json, host))
144144
});
145145
}
146146
exports.diagnosticFromJson = diagnosticFromJson;
@@ -169,7 +169,9 @@ function diagnosticRelatedInformationFromJson(json, host) {
169169
file: json.file && sourceFileFromJson(json.file, host),
170170
start: json.start,
171171
length: json.length,
172-
messageText: json.messageText
172+
messageText: json.messageText,
173+
category: json.category,
174+
code: json.code
173175
};
174176
}
175177
exports.diagnosticRelatedInformationFromJson = diagnosticRelatedInformationFromJson;

src/compiler/checker.ts

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13900,6 +13900,18 @@ namespace ts {
1390013900
return flow.id;
1390113901
}
1390213902

13903+
function typeMaybeAssignableTo(source: Type, target: Type) {
13904+
if (!(source.flags & TypeFlags.Union)) {
13905+
return isTypeAssignableTo(source, target);
13906+
}
13907+
for (const t of (<UnionType>source).types) {
13908+
if (isTypeAssignableTo(t, target)) {
13909+
return true;
13910+
}
13911+
}
13912+
return false;
13913+
}
13914+
1390313915
// Remove those constituent types of declaredType to which no constituent type of assignedType is assignable.
1390413916
// For example, when a variable of type number | string | boolean is assigned a value of type number | boolean,
1390513917
// we remove type string.
@@ -13908,8 +13920,12 @@ namespace ts {
1390813920
if (assignedType.flags & TypeFlags.Never) {
1390913921
return assignedType;
1391013922
}
13911-
const reducedType = filterType(declaredType, t => isTypeComparableTo(assignedType, t));
13912-
if (!(reducedType.flags & TypeFlags.Never)) {
13923+
const reducedType = filterType(declaredType, t => typeMaybeAssignableTo(assignedType, t));
13924+
// Our crude heuristic produces an invalid result in some cases: see GH#26130.
13925+
// For now, when that happens, we give up and don't narrow at all. (This also
13926+
// means we'll never narrow for erroneous assignments where the assigned type
13927+
// is not assignable to the declared type.)
13928+
if (isTypeAssignableTo(assignedType, reducedType)) {
1391313929
return reducedType;
1391413930
}
1391513931
}
@@ -19442,11 +19458,13 @@ namespace ts {
1944219458
const callSignatures = getSignaturesOfType(expressionType, SignatureKind.Call);
1944319459
if (callSignatures.length) {
1944419460
const signature = resolveCall(node, callSignatures, candidatesOutArray, isForSignatureHelp);
19445-
if (signature.declaration && !isJavascriptConstructor(signature.declaration) && getReturnTypeOfSignature(signature) !== voidType) {
19446-
error(node, Diagnostics.Only_a_void_function_can_be_called_with_the_new_keyword);
19447-
}
19448-
if (getThisTypeOfSignature(signature) === voidType) {
19449-
error(node, Diagnostics.A_function_that_is_called_with_the_new_keyword_cannot_have_a_this_type_that_is_void);
19461+
if (!noImplicitAny) {
19462+
if (signature.declaration && !isJavascriptConstructor(signature.declaration) && getReturnTypeOfSignature(signature) !== voidType) {
19463+
error(node, Diagnostics.Only_a_void_function_can_be_called_with_the_new_keyword);
19464+
}
19465+
if (getThisTypeOfSignature(signature) === voidType) {
19466+
error(node, Diagnostics.A_function_that_is_called_with_the_new_keyword_cannot_have_a_this_type_that_is_void);
19467+
}
1945019468
}
1945119469
return signature;
1945219470
}

src/compiler/emitter.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2593,14 +2593,14 @@ namespace ts {
25932593
}
25942594

25952595
function emitSyntheticTripleSlashReferencesIfNeeded(node: Bundle) {
2596-
emitTripleSlashDirectives(!!node.hasNoDefaultLib, node.syntheticFileReferences || [], node.syntheticTypeReferences || []);
2596+
emitTripleSlashDirectives(!!node.hasNoDefaultLib, node.syntheticFileReferences || [], node.syntheticTypeReferences || [], node.syntheticLibReferences || []);
25972597
}
25982598

25992599
function emitTripleSlashDirectivesIfNeeded(node: SourceFile) {
2600-
if (node.isDeclarationFile) emitTripleSlashDirectives(node.hasNoDefaultLib, node.referencedFiles, node.typeReferenceDirectives);
2600+
if (node.isDeclarationFile) emitTripleSlashDirectives(node.hasNoDefaultLib, node.referencedFiles, node.typeReferenceDirectives, node.libReferenceDirectives);
26012601
}
26022602

2603-
function emitTripleSlashDirectives(hasNoDefaultLib: boolean, files: ReadonlyArray<FileReference>, types: ReadonlyArray<FileReference>) {
2603+
function emitTripleSlashDirectives(hasNoDefaultLib: boolean, files: ReadonlyArray<FileReference>, types: ReadonlyArray<FileReference>, libs: ReadonlyArray<FileReference>) {
26042604
if (hasNoDefaultLib) {
26052605
write(`/// <reference no-default-lib="true"/>`);
26062606
writeLine();
@@ -2628,6 +2628,10 @@ namespace ts {
26282628
write(`/// <reference types="${directive.fileName}" />`);
26292629
writeLine();
26302630
}
2631+
for (const directive of libs) {
2632+
write(`/// <reference lib="${directive.fileName}" />`);
2633+
writeLine();
2634+
}
26312635
}
26322636

26332637
function emitSourceFileWorker(node: SourceFile) {

src/compiler/program.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1237,6 +1237,7 @@ namespace ts {
12371237
getSourceFile: program.getSourceFile,
12381238
getSourceFileByPath: program.getSourceFileByPath,
12391239
getSourceFiles: program.getSourceFiles,
1240+
getLibFileFromReference: program.getLibFileFromReference,
12401241
isSourceFileFromExternalLibrary,
12411242
writeFile: writeFileCallback || (
12421243
(fileName, data, writeByteOrderMark, onError, sourceFiles) => host.writeFile(fileName, data, writeByteOrderMark, onError, sourceFiles)),

src/compiler/transformers/declarations.ts

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ namespace ts {
3333
let needsScopeFixMarker = false;
3434
let resultHasScopeMarker = false;
3535
let enclosingDeclaration: Node;
36-
let necessaryTypeRefernces: Map<true> | undefined;
36+
let necessaryTypeReferences: Map<true> | undefined;
3737
let lateMarkedStatements: LateVisibilityPaintedStatement[] | undefined;
3838
let lateStatementReplacementMap: Map<VisitResult<LateVisibilityPaintedStatement>>;
3939
let suppressNewDiagnosticContexts: boolean;
@@ -53,6 +53,7 @@ namespace ts {
5353

5454
let currentSourceFile: SourceFile;
5555
let refs: Map<SourceFile>;
56+
let libs: Map<boolean>;
5657
const resolver = context.getEmitResolver();
5758
const options = context.getCompilerOptions();
5859
const newLine = getNewLineCharacter(options);
@@ -63,9 +64,9 @@ namespace ts {
6364
if (!typeReferenceDirectives) {
6465
return;
6566
}
66-
necessaryTypeRefernces = necessaryTypeRefernces || createMap<true>();
67+
necessaryTypeReferences = necessaryTypeReferences || createMap<true>();
6768
for (const ref of typeReferenceDirectives) {
68-
necessaryTypeRefernces.set(ref, true);
69+
necessaryTypeReferences.set(ref, true);
6970
}
7071
}
7172

@@ -163,6 +164,7 @@ namespace ts {
163164
if (node.kind === SyntaxKind.Bundle) {
164165
isBundledEmit = true;
165166
refs = createMap<SourceFile>();
167+
libs = createMap<boolean>();
166168
let hasNoDefaultLib = false;
167169
const bundle = createBundle(map(node.sourceFiles,
168170
sourceFile => {
@@ -177,6 +179,7 @@ namespace ts {
177179
needsScopeFixMarker = false;
178180
resultHasScopeMarker = false;
179181
collectReferences(sourceFile, refs);
182+
collectLibs(sourceFile, libs);
180183
if (isExternalModule(sourceFile)) {
181184
resultHasExternalModuleIndicator = false; // unused in external module bundle emit (all external modules are within module blocks, therefore are known to be modules)
182185
needsDeclare = false;
@@ -200,6 +203,7 @@ namespace ts {
200203
}));
201204
bundle.syntheticFileReferences = [];
202205
bundle.syntheticTypeReferences = getFileReferencesForUsedTypeReferences();
206+
bundle.syntheticLibReferences = getLibReferences();
203207
bundle.hasNoDefaultLib = hasNoDefaultLib;
204208
const outputFilePath = getDirectoryPath(normalizeSlashes(getOutputPathsFor(node, host, /*forceDtsPaths*/ true).declarationFilePath!));
205209
const referenceVisitor = mapReferencesIntoArray(bundle.syntheticFileReferences as FileReference[], outputFilePath);
@@ -219,8 +223,9 @@ namespace ts {
219223
suppressNewDiagnosticContexts = false;
220224
lateMarkedStatements = undefined;
221225
lateStatementReplacementMap = createMap();
222-
necessaryTypeRefernces = undefined;
226+
necessaryTypeReferences = undefined;
223227
refs = collectReferences(currentSourceFile, createMap());
228+
libs = collectLibs(currentSourceFile, createMap());
224229
const references: FileReference[] = [];
225230
const outputFilePath = getDirectoryPath(normalizeSlashes(getOutputPathsFor(node, host, /*forceDtsPaths*/ true).declarationFilePath!));
226231
const referenceVisitor = mapReferencesIntoArray(references, outputFilePath);
@@ -231,12 +236,16 @@ namespace ts {
231236
if (isExternalModule(node) && (!resultHasExternalModuleIndicator || (needsScopeFixMarker && !resultHasScopeMarker))) {
232237
combinedStatements = setTextRange(createNodeArray([...combinedStatements, createExportDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, createNamedExports([]), /*moduleSpecifier*/ undefined)]), combinedStatements);
233238
}
234-
const updated = updateSourceFileNode(node, combinedStatements, /*isDeclarationFile*/ true, references, getFileReferencesForUsedTypeReferences(), node.hasNoDefaultLib);
239+
const updated = updateSourceFileNode(node, combinedStatements, /*isDeclarationFile*/ true, references, getFileReferencesForUsedTypeReferences(), node.hasNoDefaultLib, getLibReferences());
235240
updated.exportedModulesFromDeclarationEmit = exportedModulesFromDeclarationEmit;
236241
return updated;
237242

243+
function getLibReferences() {
244+
return map(arrayFrom(libs.keys()), lib => ({ fileName: lib, pos: -1, end: -1 }));
245+
}
246+
238247
function getFileReferencesForUsedTypeReferences() {
239-
return necessaryTypeRefernces ? mapDefined(arrayFrom(necessaryTypeRefernces.keys()), getFileReferenceForTypeName) : [];
248+
return necessaryTypeReferences ? mapDefined(arrayFrom(necessaryTypeReferences.keys()), getFileReferenceForTypeName) : [];
240249
}
241250

242251
function getFileReferenceForTypeName(typeName: string): FileReference | undefined {
@@ -297,6 +306,16 @@ namespace ts {
297306
return ret;
298307
}
299308

309+
function collectLibs(sourceFile: SourceFile, ret: Map<boolean>) {
310+
forEach(sourceFile.libReferenceDirectives, ref => {
311+
const lib = host.getLibFileFromReference(ref);
312+
if (lib) {
313+
ret.set(ref.fileName.toLocaleLowerCase(), true);
314+
}
315+
});
316+
return ret;
317+
}
318+
300319
function filterBindingPatternInitializers(name: BindingName) {
301320
if (name.kind === SyntaxKind.Identifier) {
302321
return name;

src/compiler/types.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2648,6 +2648,7 @@ namespace ts {
26482648
sourceFiles: ReadonlyArray<SourceFile>;
26492649
/* @internal */ syntheticFileReferences?: ReadonlyArray<FileReference>;
26502650
/* @internal */ syntheticTypeReferences?: ReadonlyArray<FileReference>;
2651+
/* @internal */ syntheticLibReferences?: ReadonlyArray<FileReference>;
26512652
/* @internal */ hasNoDefaultLib?: boolean;
26522653
}
26532654

@@ -5074,6 +5075,7 @@ namespace ts {
50745075

50755076
/* @internal */
50765077
isSourceFileFromExternalLibrary(file: SourceFile): boolean;
5078+
getLibFileFromReference(ref: FileReference): SourceFile | undefined;
50775079

50785080
getCommonSourceDirectory(): string;
50795081
getCanonicalFileName(fileName: string): string;

src/services/documentRegistry.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,7 @@ namespace ts {
184184

185185
const bucket = getBucketForCompilationSettings(key, /*createIfMissing*/ true);
186186
let entry = bucket.get(path);
187-
const scriptTarget = scriptKind === ScriptKind.JSON ? ScriptTarget.JSON : compilationSettings.target;
187+
const scriptTarget = scriptKind === ScriptKind.JSON ? ScriptTarget.JSON : compilationSettings.target || ScriptTarget.ES5;
188188
if (!entry && externalCache) {
189189
const sourceFile = externalCache.getDocument(key, path);
190190
if (sourceFile) {
@@ -199,7 +199,7 @@ namespace ts {
199199

200200
if (!entry) {
201201
// Have never seen this file with these settings. Create a new source file for it.
202-
const sourceFile = createLanguageServiceSourceFile(fileName, scriptSnapshot, scriptTarget!, version, /*setNodeParents*/ false, scriptKind); // TODO: GH#18217
202+
const sourceFile = createLanguageServiceSourceFile(fileName, scriptSnapshot, scriptTarget, version, /*setNodeParents*/ false, scriptKind);
203203
if (externalCache) {
204204
externalCache.setDocument(key, path, sourceFile);
205205
}

src/testRunner/unittests/convertToAsyncFunction.ts

Lines changed: 1 addition & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -319,38 +319,6 @@ interface String { charAt: any; }
319319
interface Array<T> {}`
320320
};
321321

322-
const newLineCharacter = "\n";
323-
const formatOptions: FormatCodeSettings = {
324-
indentSize: 4,
325-
tabSize: 4,
326-
newLineCharacter,
327-
convertTabsToSpaces: true,
328-
indentStyle: IndentStyle.Smart,
329-
insertSpaceAfterConstructor: false,
330-
insertSpaceAfterCommaDelimiter: true,
331-
insertSpaceAfterSemicolonInForStatements: true,
332-
insertSpaceBeforeAndAfterBinaryOperators: true,
333-
insertSpaceAfterKeywordsInControlFlowStatements: true,
334-
insertSpaceAfterFunctionKeywordForAnonymousFunctions: false,
335-
insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis: false,
336-
insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets: false,
337-
insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces: true,
338-
insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces: false,
339-
insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces: false,
340-
insertSpaceBeforeFunctionParenthesis: false,
341-
placeOpenBraceOnNewLineForFunctions: false,
342-
placeOpenBraceOnNewLineForControlBlocks: false,
343-
};
344-
345-
const notImplementedHost: LanguageServiceHost = {
346-
getCompilationSettings: notImplemented,
347-
getScriptFileNames: notImplemented,
348-
getScriptVersion: notImplemented,
349-
getScriptSnapshot: notImplemented,
350-
getDefaultLibFileName: notImplemented,
351-
getCurrentDirectory: notImplemented,
352-
};
353-
354322
function testConvertToAsyncFunction(caption: string, text: string, baselineFolder: string, description: DiagnosticMessage, includeLib?: boolean) {
355323
const t = getTest(text);
356324
const selectionRange = t.ranges.get("selection")!;
@@ -389,7 +357,7 @@ interface Array<T> {}`
389357
cancellationToken: { throwIfCancellationRequested: noop, isCancellationRequested: returnFalse },
390358
preferences: emptyOptions,
391359
host: notImplementedHost,
392-
formatContext: formatting.getFormatContext(formatOptions)
360+
formatContext: formatting.getFormatContext(testFormatOptions)
393361
};
394362

395363
const diagnostics = languageService.getSuggestionDiagnostics(f.path);

src/testRunner/unittests/extractTestHelpers.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ namespace ts {
8686
placeOpenBraceOnNewLineForControlBlocks: false,
8787
};
8888

89-
const notImplementedHost: LanguageServiceHost = {
89+
export const notImplementedHost: LanguageServiceHost = {
9090
getCompilationSettings: notImplemented,
9191
getScriptFileNames: notImplemented,
9292
getScriptVersion: notImplemented,

tests/baselines/reference/assignmentTypeNarrowing.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,12 @@ let a: string[];
2727
for (x of a) {
2828
x; // string
2929
}
30+
31+
// Repro from #26405
32+
33+
type AOrArrA<T> = T | T[];
34+
const arr: AOrArrA<{x?: "ok"}> = [{ x: "ok" }]; // weak type
35+
arr.push({ x: "ok" });
3036

3137

3238
//// [assignmentTypeNarrowing.js]
@@ -51,3 +57,5 @@ for (var _i = 0, a_1 = a; _i < a_1.length; _i++) {
5157
x = a_1[_i];
5258
x; // string
5359
}
60+
var arr = [{ x: "ok" }]; // weak type
61+
arr.push({ x: "ok" });

tests/baselines/reference/assignmentTypeNarrowing.symbols

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,3 +62,23 @@ for (x of a) {
6262
>x : Symbol(x, Decl(assignmentTypeNarrowing.ts, 0, 3))
6363
}
6464

65+
// Repro from #26405
66+
67+
type AOrArrA<T> = T | T[];
68+
>AOrArrA : Symbol(AOrArrA, Decl(assignmentTypeNarrowing.ts, 27, 1))
69+
>T : Symbol(T, Decl(assignmentTypeNarrowing.ts, 31, 13))
70+
>T : Symbol(T, Decl(assignmentTypeNarrowing.ts, 31, 13))
71+
>T : Symbol(T, Decl(assignmentTypeNarrowing.ts, 31, 13))
72+
73+
const arr: AOrArrA<{x?: "ok"}> = [{ x: "ok" }]; // weak type
74+
>arr : Symbol(arr, Decl(assignmentTypeNarrowing.ts, 32, 5))
75+
>AOrArrA : Symbol(AOrArrA, Decl(assignmentTypeNarrowing.ts, 27, 1))
76+
>x : Symbol(x, Decl(assignmentTypeNarrowing.ts, 32, 20))
77+
>x : Symbol(x, Decl(assignmentTypeNarrowing.ts, 32, 35))
78+
79+
arr.push({ x: "ok" });
80+
>arr.push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --))
81+
>arr : Symbol(arr, Decl(assignmentTypeNarrowing.ts, 32, 5))
82+
>push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --))
83+
>x : Symbol(x, Decl(assignmentTypeNarrowing.ts, 33, 10))
84+

tests/baselines/reference/assignmentTypeNarrowing.types

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,3 +96,25 @@ for (x of a) {
9696
>x : string
9797
}
9898

99+
// Repro from #26405
100+
101+
type AOrArrA<T> = T | T[];
102+
>AOrArrA : AOrArrA<T>
103+
104+
const arr: AOrArrA<{x?: "ok"}> = [{ x: "ok" }]; // weak type
105+
>arr : AOrArrA<{ x?: "ok"; }>
106+
>x : "ok"
107+
>[{ x: "ok" }] : { x: "ok"; }[]
108+
>{ x: "ok" } : { x: "ok"; }
109+
>x : "ok"
110+
>"ok" : "ok"
111+
112+
arr.push({ x: "ok" });
113+
>arr.push({ x: "ok" }) : number
114+
>arr.push : (...items: { x?: "ok"; }[]) => number
115+
>arr : { x?: "ok"; }[]
116+
>push : (...items: { x?: "ok"; }[]) => number
117+
>{ x: "ok" } : { x: "ok"; }
118+
>x : "ok"
119+
>"ok" : "ok"
120+

tests/baselines/reference/enumAssignmentCompat3.types

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -252,9 +252,9 @@ abc = merged; // missing 'd'
252252
>merged : Merged.E
253253

254254
merged = abc; // ok
255-
>merged = abc : First.E.a | First.E.b
255+
>merged = abc : First.E
256256
>merged : Merged.E
257-
>abc : First.E.a | First.E.b
257+
>abc : First.E
258258

259259
abc = merged2; // ok
260260
>abc = merged2 : Merged2.E

0 commit comments

Comments
 (0)