Merge pull request #367 from Microsoft/theDisintegrationOfThePersistenceOfMemory

Fixed memory leak when using '--watch' flag.
This commit is contained in:
Daniel Rosenwasser 2014-08-06 16:28:27 -07:00
commit 893940cedf
2 changed files with 41 additions and 12 deletions

View file

@ -152,7 +152,31 @@ module ts {
export function mapToArray<T>(map: Map<T>): T[] { export function mapToArray<T>(map: Map<T>): T[] {
var result: T[] = []; var result: T[] = [];
for (var id in map) result.push(map[id]);
for (var id in map) {
result.push(map[id]);
}
return result;
}
/**
* Creates a map from the elements of an array.
*
* @param array the array of input elements.
* @param makeKey a function that produces a key for a given element.
*
* This function makes no effort to avoid collisions; if any two elements produce
* the same key with the given 'makeKey' function, then the element with the higher
* index in the array will be the one associated with the produced key.
*/
export function arrayToMap<T>(array: T[], makeKey: (value: T) => string): Map<T> {
var result: Map<T> = {};
forEach(array, value => {
result[makeKey(value)] = value
});
return result; return result;
} }

View file

@ -245,14 +245,14 @@ module ts {
function addWatchers(program: Program) { function addWatchers(program: Program) {
forEach(program.getSourceFiles(), f => { forEach(program.getSourceFiles(), f => {
var filename = f.filename; var filename = getCanonicalName(f.filename);
watchers[filename] = sys.watchFile(filename, fileUpdated); watchers[filename] = sys.watchFile(filename, fileUpdated);
}); });
} }
function removeWatchers(program: Program) { function removeWatchers(program: Program) {
forEach(program.getSourceFiles(), f => { forEach(program.getSourceFiles(), f => {
var filename = f.filename; var filename = getCanonicalName(f.filename);
if (hasProperty(watchers, filename)) { if (hasProperty(watchers, filename)) {
watchers[filename].close(); watchers[filename].close();
} }
@ -264,8 +264,7 @@ module ts {
// Fired off whenever a file is changed. // Fired off whenever a file is changed.
function fileUpdated(filename: string) { function fileUpdated(filename: string) {
var firstNotification = isEmpty(updatedFiles); var firstNotification = isEmpty(updatedFiles);
updatedFiles[getCanonicalName(filename)] = true;
updatedFiles[filename] = true;
// Only start this off when the first file change comes in, // Only start this off when the first file change comes in,
// so that we can batch up all further changes. // so that we can batch up all further changes.
@ -285,8 +284,10 @@ module ts {
// specified since the last compilation cycle. // specified since the last compilation cycle.
removeWatchers(program); removeWatchers(program);
// Gets us syntactically correct files from the last compilation. // Reuse source files from the last compilation so long as they weren't changed.
var getUnmodifiedSourceFile = program.getSourceFile; var oldSourceFiles = arrayToMap(
filter(program.getSourceFiles(), file => !hasProperty(changedFiles, getCanonicalName(file.filename))),
file => getCanonicalName(file.filename));
// We create a new compiler host for this compilation cycle. // We create a new compiler host for this compilation cycle.
// This new host is effectively the same except that 'getSourceFile' // This new host is effectively the same except that 'getSourceFile'
@ -294,11 +295,11 @@ module ts {
// so long as they were not modified. // so long as they were not modified.
var newCompilerHost = clone(compilerHost); var newCompilerHost = clone(compilerHost);
newCompilerHost.getSourceFile = (fileName, languageVersion, onError) => { newCompilerHost.getSourceFile = (fileName, languageVersion, onError) => {
if (!hasProperty(changedFiles, fileName)) { fileName = getCanonicalName(fileName);
var sourceFile = getUnmodifiedSourceFile(fileName);
if (sourceFile) { var sourceFile = lookUp(oldSourceFiles, fileName);
return sourceFile; if (sourceFile) {
} return sourceFile;
} }
return compilerHost.getSourceFile(fileName, languageVersion, onError); return compilerHost.getSourceFile(fileName, languageVersion, onError);
@ -308,6 +309,10 @@ module ts {
reportDiagnostic(createCompilerDiagnostic(Diagnostics.Compilation_complete_Watching_for_file_changes)); reportDiagnostic(createCompilerDiagnostic(Diagnostics.Compilation_complete_Watching_for_file_changes));
addWatchers(program); addWatchers(program);
} }
function getCanonicalName(fileName: string) {
return compilerHost.getCanonicalFileName(fileName);
}
} }
function compile(commandLine: ParsedCommandLine, compilerHost: CompilerHost) { function compile(commandLine: ParsedCommandLine, compilerHost: CompilerHost) {