Skip to content

Commit 9ff02b1

Browse files
committed
Merge branch 'master' of https://github.com/Microsoft/TypeScript into typedefForJsdoc
# Conflicts: # src/services/services.ts
2 parents 79bb4ba + 4d53a21 commit 9ff02b1

File tree

131 files changed

+3848
-1862
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

131 files changed

+3848
-1862
lines changed

.gitignore

+3-2
Original file line numberDiff line numberDiff line change
@@ -46,5 +46,6 @@ coverage/
4646
internal/
4747
**/.DS_Store
4848
.settings
49-
.vscode/*
50-
!.vscode/tasks.json
49+
**/.vs
50+
**/.vscode
51+
!**/.vscode/tasks.json

package.json

+1
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
"build": "npm run build:compiler && npm run build:tests",
4646
"build:compiler": "jake local",
4747
"build:tests": "jake tests",
48+
"start": "node lib/tsc",
4849
"clean": "jake clean",
4950
"jake": "jake",
5051
"lint": "jake lint",

src/compiler/binder.ts

+14-6
Original file line numberDiff line numberDiff line change
@@ -650,6 +650,13 @@ namespace ts {
650650
};
651651
}
652652

653+
function createFlowLoopLabel(): FlowLabel {
654+
return {
655+
kind: FlowKind.LoopLabel,
656+
antecedents: undefined
657+
};
658+
}
659+
653660
function addAntecedent(label: FlowLabel, antecedent: FlowNode): void {
654661
if (antecedent.kind !== FlowKind.Unreachable && !contains(label.antecedents, antecedent)) {
655662
(label.antecedents || (label.antecedents = [])).push(antecedent);
@@ -760,7 +767,7 @@ namespace ts {
760767
}
761768

762769
function bindWhileStatement(node: WhileStatement): void {
763-
const preWhileLabel = createFlowLabel();
770+
const preWhileLabel = createFlowLoopLabel();
764771
const preBodyLabel = createFlowLabel();
765772
const postWhileLabel = createFlowLabel();
766773
addAntecedent(preWhileLabel, currentFlow);
@@ -773,7 +780,7 @@ namespace ts {
773780
}
774781

775782
function bindDoStatement(node: DoStatement): void {
776-
const preDoLabel = createFlowLabel();
783+
const preDoLabel = createFlowLoopLabel();
777784
const preConditionLabel = createFlowLabel();
778785
const postDoLabel = createFlowLabel();
779786
addAntecedent(preDoLabel, currentFlow);
@@ -786,7 +793,7 @@ namespace ts {
786793
}
787794

788795
function bindForStatement(node: ForStatement): void {
789-
const preLoopLabel = createFlowLabel();
796+
const preLoopLabel = createFlowLoopLabel();
790797
const preBodyLabel = createFlowLabel();
791798
const postLoopLabel = createFlowLabel();
792799
bind(node.initializer);
@@ -801,7 +808,7 @@ namespace ts {
801808
}
802809

803810
function bindForInOrForOfStatement(node: ForInStatement | ForOfStatement): void {
804-
const preLoopLabel = createFlowLabel();
811+
const preLoopLabel = createFlowLoopLabel();
805812
const postLoopLabel = createFlowLabel();
806813
addAntecedent(preLoopLabel, currentFlow);
807814
currentFlow = preLoopLabel;
@@ -948,7 +955,7 @@ namespace ts {
948955
}
949956

950957
function bindLabeledStatement(node: LabeledStatement): void {
951-
const preStatementLabel = createFlowLabel();
958+
const preStatementLabel = createFlowLoopLabel();
952959
const postStatementLabel = createFlowLabel();
953960
bind(node.label);
954961
addAntecedent(preStatementLabel, currentFlow);
@@ -1377,7 +1384,8 @@ namespace ts {
13771384
if (inStrictMode &&
13781385
node.originalKeywordKind >= SyntaxKind.FirstFutureReservedWord &&
13791386
node.originalKeywordKind <= SyntaxKind.LastFutureReservedWord &&
1380-
!isIdentifierName(node)) {
1387+
!isIdentifierName(node) &&
1388+
!isInAmbientContext(node)) {
13811389

13821390
// Report error only if there are no parse errors in file
13831391
if (!file.parseDiagnostics.length) {

src/compiler/checker.ts

+151-130
Large diffs are not rendered by default.

src/compiler/declarationEmitter.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1753,7 +1753,7 @@ namespace ts {
17531753
if (!emitSkipped) {
17541754
const declarationOutput = emitDeclarationResult.referencesOutput
17551755
+ getDeclarationOutput(emitDeclarationResult.synchronousDeclarationOutput, emitDeclarationResult.moduleElementDeclarationEmitInfo);
1756-
writeFile(host, emitterDiagnostics, declarationFilePath, declarationOutput, host.getCompilerOptions().emitBOM);
1756+
writeFile(host, emitterDiagnostics, declarationFilePath, declarationOutput, host.getCompilerOptions().emitBOM, sourceFiles);
17571757
}
17581758
return emitSkipped;
17591759

src/compiler/emitter.ts

+1
Original file line numberDiff line numberDiff line change
@@ -1524,6 +1524,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
15241524
switch (parent.kind) {
15251525
case SyntaxKind.ArrayLiteralExpression:
15261526
case SyntaxKind.AsExpression:
1527+
case SyntaxKind.AwaitExpression:
15271528
case SyntaxKind.BinaryExpression:
15281529
case SyntaxKind.CallExpression:
15291530
case SyntaxKind.CaseClause:

src/compiler/sys.ts

+29-110
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,11 @@
33
namespace ts {
44
export type FileWatcherCallback = (fileName: string, removed?: boolean) => void;
55
export type DirectoryWatcherCallback = (directoryName: string) => void;
6+
export interface WatchedFile {
7+
fileName: string;
8+
callback: FileWatcherCallback;
9+
mtime?: Date;
10+
}
611

712
export interface System {
813
args: string[];
@@ -26,12 +31,6 @@ namespace ts {
2631
exit(exitCode?: number): void;
2732
}
2833

29-
interface WatchedFile {
30-
fileName: string;
31-
callback: FileWatcherCallback;
32-
mtime?: Date;
33-
}
34-
3534
export interface FileWatcher {
3635
close(): void;
3736
}
@@ -230,83 +229,7 @@ namespace ts {
230229
const _os = require("os");
231230
const _crypto = require("crypto");
232231

233-
// average async stat takes about 30 microseconds
234-
// set chunk size to do 30 files in < 1 millisecond
235-
function createPollingWatchedFileSet(interval = 2500, chunkSize = 30) {
236-
let watchedFiles: WatchedFile[] = [];
237-
let nextFileToCheck = 0;
238-
let watchTimer: any;
239-
240-
function getModifiedTime(fileName: string): Date {
241-
return _fs.statSync(fileName).mtime;
242-
}
243-
244-
function poll(checkedIndex: number) {
245-
const watchedFile = watchedFiles[checkedIndex];
246-
if (!watchedFile) {
247-
return;
248-
}
249-
250-
_fs.stat(watchedFile.fileName, (err: any, stats: any) => {
251-
if (err) {
252-
watchedFile.callback(watchedFile.fileName);
253-
}
254-
else if (watchedFile.mtime.getTime() !== stats.mtime.getTime()) {
255-
watchedFile.mtime = getModifiedTime(watchedFile.fileName);
256-
watchedFile.callback(watchedFile.fileName, watchedFile.mtime.getTime() === 0);
257-
}
258-
});
259-
}
260-
261-
// this implementation uses polling and
262-
// stat due to inconsistencies of fs.watch
263-
// and efficiency of stat on modern filesystems
264-
function startWatchTimer() {
265-
watchTimer = setInterval(() => {
266-
let count = 0;
267-
let nextToCheck = nextFileToCheck;
268-
let firstCheck = -1;
269-
while ((count < chunkSize) && (nextToCheck !== firstCheck)) {
270-
poll(nextToCheck);
271-
if (firstCheck < 0) {
272-
firstCheck = nextToCheck;
273-
}
274-
nextToCheck++;
275-
if (nextToCheck === watchedFiles.length) {
276-
nextToCheck = 0;
277-
}
278-
count++;
279-
}
280-
nextFileToCheck = nextToCheck;
281-
}, interval);
282-
}
283-
284-
function addFile(fileName: string, callback: FileWatcherCallback): WatchedFile {
285-
const file: WatchedFile = {
286-
fileName,
287-
callback,
288-
mtime: getModifiedTime(fileName)
289-
};
290-
291-
watchedFiles.push(file);
292-
if (watchedFiles.length === 1) {
293-
startWatchTimer();
294-
}
295-
return file;
296-
}
297-
298-
function removeFile(file: WatchedFile) {
299-
watchedFiles = copyListRemovingItem(file, watchedFiles);
300-
}
301-
302-
return {
303-
getModifiedTime: getModifiedTime,
304-
poll: poll,
305-
startWatchTimer: startWatchTimer,
306-
addFile: addFile,
307-
removeFile: removeFile
308-
};
309-
}
232+
const useNonPollingWatchers = process.env["TSC_NONPOLLING_WATCHER"];
310233

311234
function createWatchedFileSet() {
312235
const dirWatchers: Map<DirectoryWatcher> = {};
@@ -389,26 +312,11 @@ namespace ts {
389312
}
390313
}
391314
}
392-
393-
// REVIEW: for now this implementation uses polling.
394-
// The advantage of polling is that it works reliably
395-
// on all os and with network mounted files.
396-
// For 90 referenced files, the average time to detect
397-
// changes is 2*msInterval (by default 5 seconds).
398-
// The overhead of this is .04 percent (1/2500) with
399-
// average pause of < 1 millisecond (and max
400-
// pause less than 1.5 milliseconds); question is
401-
// do we anticipate reference sets in the 100s and
402-
// do we care about waiting 10-20 seconds to detect
403-
// changes for large reference sets? If so, do we want
404-
// to increase the chunk size or decrease the interval
405-
// time dynamically to match the large reference set?
406-
const pollingWatchedFileSet = createPollingWatchedFileSet();
407315
const watchedFileSet = createWatchedFileSet();
408316

409317
function isNode4OrLater(): boolean {
410-
return parseInt(process.version.charAt(1)) >= 4;
411-
}
318+
return parseInt(process.version.charAt(1)) >= 4;
319+
}
412320

413321
const platform: string = _os.platform();
414322
// win32\win64 are case insensitive platforms, MacOS (darwin) by default is also case insensitive
@@ -501,7 +409,7 @@ namespace ts {
501409
const files = _fs.readdirSync(path || ".").sort();
502410
const directories: string[] = [];
503411
for (const current of files) {
504-
// This is necessary because on some file system node fails to exclude
412+
// This is necessary because on some file system node fails to exclude
505413
// "." and "..". See https://github.com/nodejs/node/issues/4002
506414
if (current === "." || current === "..") {
507415
continue;
@@ -535,15 +443,26 @@ namespace ts {
535443
readFile,
536444
writeFile,
537445
watchFile: (fileName, callback) => {
538-
// Node 4.0 stabilized the `fs.watch` function on Windows which avoids polling
539-
// and is more efficient than `fs.watchFile` (ref: https://github.com/nodejs/node/pull/2649
540-
// and https://github.com/Microsoft/TypeScript/issues/4643), therefore
541-
// if the current node.js version is newer than 4, use `fs.watch` instead.
542-
const watchSet = isNode4OrLater() ? watchedFileSet : pollingWatchedFileSet;
543-
const watchedFile = watchSet.addFile(fileName, callback);
544-
return {
545-
close: () => watchSet.removeFile(watchedFile)
546-
};
446+
if (useNonPollingWatchers) {
447+
const watchedFile = watchedFileSet.addFile(fileName, callback);
448+
return {
449+
close: () => watchedFileSet.removeFile(watchedFile)
450+
};
451+
}
452+
else {
453+
_fs.watchFile(fileName, { persistent: true, interval: 250 }, fileChanged);
454+
return {
455+
close: () => _fs.unwatchFile(fileName, fileChanged)
456+
};
457+
}
458+
459+
function fileChanged(curr: any, prev: any) {
460+
if (+curr.mtime <= +prev.mtime) {
461+
return;
462+
}
463+
464+
callback(fileName);
465+
}
547466
},
548467
watchDirectory: (directoryName, callback, recursive) => {
549468
// Node 4.0 `fs.watch` function supports the "recursive" option on both OSX and Windows

src/compiler/tsc.ts

+15-3
Original file line numberDiff line numberDiff line change
@@ -391,9 +391,21 @@ namespace ts {
391391
sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped);
392392
return;
393393
}
394-
if (isWatchSet(configParseResult.options) && !sys.watchFile) {
395-
reportDiagnostic(createCompilerDiagnostic(Diagnostics.The_current_host_does_not_support_the_0_option, "--watch"), /* compilerHost */ undefined);
396-
sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped);
394+
if (isWatchSet(configParseResult.options)) {
395+
if (!sys.watchFile) {
396+
reportDiagnostic(createCompilerDiagnostic(Diagnostics.The_current_host_does_not_support_the_0_option, "--watch"), /* compilerHost */ undefined);
397+
sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped);
398+
}
399+
400+
if (!directoryWatcher && sys.watchDirectory && configFileName) {
401+
const directory = ts.getDirectoryPath(configFileName);
402+
directoryWatcher = sys.watchDirectory(
403+
// When the configFileName is just "tsconfig.json", the watched directory should be
404+
// the current directory; if there is a given "project" parameter, then the configFileName
405+
// is an absolute file name.
406+
directory == "" ? "." : directory,
407+
watchedDirectoryChanged, /*recursive*/ true);
408+
};
397409
}
398410
return configParseResult;
399411
}

src/compiler/types.ts

+5-4
Original file line numberDiff line numberDiff line change
@@ -1551,6 +1551,7 @@ namespace ts {
15511551
Unreachable,
15521552
Start,
15531553
Label,
1554+
LoopLabel,
15541555
Assignment,
15551556
Condition
15561557
}
@@ -2539,19 +2540,19 @@ namespace ts {
25392540
// When options come from a config file, its path is recorded here
25402541
configFilePath?: string;
25412542
/* @internal */
2542-
// Path used to used to compute primary search locations
2543+
// Path used to used to compute primary search locations
25432544
typesRoot?: string;
25442545
types?: string[];
25452546

25462547
list?: string[];
2547-
[option: string]: CompilerOptionsValue;
2548+
[option: string]: CompilerOptionsValue | undefined;
25482549
}
25492550

25502551
export interface TypingOptions {
25512552
enableAutoDiscovery?: boolean;
25522553
include?: string[];
25532554
exclude?: string[];
2554-
[option: string]: string[] | boolean;
2555+
[option: string]: string[] | boolean | undefined;
25552556
}
25562557

25572558
export interface DiscoverTypingsInfo {
@@ -2856,7 +2857,7 @@ namespace ts {
28562857
*/
28572858
resolveModuleNames?(moduleNames: string[], containingFile: string): ResolvedModule[];
28582859
/**
2859-
* This method is a companion for 'resolveModuleNames' and is used to resolve 'types' references to actual type declaration files
2860+
* This method is a companion for 'resolveModuleNames' and is used to resolve 'types' references to actual type declaration files
28602861
*/
28612862
resolveTypeReferenceDirectives?(typeReferenceDirectiveNames: string[], containingFile: string): ResolvedTypeReferenceDirective[];
28622863
}

0 commit comments

Comments
 (0)