Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 44 additions & 10 deletions Jakefile
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,8 @@ function concatenateFiles(destinationFile, sourceFiles) {
}

var useDebugMode = false;
var host = (process.env.host || process.env.TYPESCRIPT_HOST || "node");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if this can be evaluated here. It may be set by the task...

var compilerFilename = "tsc.js";
/* Compiles a file from a list of sources
* @param outFile: the target file name
* @param sources: an array of the names of the source files
Expand All @@ -134,10 +136,9 @@ var useDebugMode = false;
function compileFile(outFile, sources, prereqs, prefixes, useBuiltCompiler, noOutFile) {
file(outFile, prereqs, function() {
var dir = useBuiltCompiler ? builtLocalDirectory : LKGDirectory;
var compilerFilename = "tsc.js";
var options = "-removeComments --module commonjs -noImplicitAny "; //" -propagateEnumConstants "

var cmd = (process.env.host || process.env.TYPESCRIPT_HOST || "node") + " " + dir + compilerFilename + " " + options + " ";
var cmd = host + " " + dir + compilerFilename + " " + options + " ";
if (useDebugMode) {
cmd = cmd + " " + path.join(harnessDirectory, "external/es5compat.ts") + " " + path.join(harnessDirectory, "external/json2.ts") + " ";
}
Expand Down Expand Up @@ -230,7 +231,7 @@ task("generate-diagnostics", [diagnosticInfoMapTs])


// Local target to build the compiler and services
var tscFile = path.join(builtLocalDirectory, "tsc.js");
var tscFile = path.join(builtLocalDirectory, compilerFilename);
compileFile(tscFile, compilerSources, [builtLocalDirectory, copyright].concat(compilerSources), [copyright], /*useBuiltCompiler:*/ false);

var servicesFile = path.join(builtLocalDirectory, "typescriptServices.js");
Expand Down Expand Up @@ -312,9 +313,9 @@ function exec(cmd, completeHandler) {
complete();
});
ex.addListener("error", function(e, status) {
process.stderr.write(status);
process.stderr.write(e);
complete();
process.stderr.write(status);
process.stderr.write(e);
complete();
})
try{
ex.run();
Expand Down Expand Up @@ -377,9 +378,9 @@ task("runtests", ["tests", builtLocalDirectory], function() {

desc("Generates code coverage data via instanbul")
task("generate-code-coverage", ["tests", builtLocalDirectory], function () {
var cmd = 'istanbul cover node_modules/mocha/bin/_mocha -- -R min -t ' + testTimeout + ' ' + run;
console.log(cmd);
exec(cmd);
var cmd = 'istanbul cover node_modules/mocha/bin/_mocha -- -R min -t ' + testTimeout + ' ' + run;
console.log(cmd);
exec(cmd);
}, { async: true });

// Browser tests
Expand Down Expand Up @@ -464,7 +465,7 @@ compileFile(webhostJsPath, [webhostPath], [tscFile, webhostPath].concat(libraryT

desc("Builds the tsc web host");
task("webhost", [webhostJsPath], function() {
jake.cpR(path.join(builtLocalDirectory, "lib.d.ts"), "tests/webhost/", {silent: true});
jake.cpR(path.join(builtLocalDirectory, "lib.d.ts"), "tests/webhost/", {silent: true});
});

// Perf compiler
Expand All @@ -473,3 +474,36 @@ var perftscJsPath = "built/local/perftsc.js";
compileFile(perftscJsPath, [perftscPath], [tscFile, perftscPath, "tests/perfsys.ts"].concat(libraryTargets), [], true);
desc("Builds augmented version of the compiler for perf tests");
task("perftsc", [perftscJsPath]);

// Instrumented compiler
var loggedIOpath = harnessDirectory + 'loggedIO.ts';
var loggedIOJsPath = builtLocalDirectory + 'loggedIO.js';
file(loggedIOJsPath, [builtLocalDirectory, loggedIOpath], function() {
var temp = builtLocalDirectory + 'temp';
jake.mkdirP(temp);
var options = "--outdir " + temp + ' ' + loggedIOpath;
var cmd = host + " " + LKGDirectory + compilerFilename + " " + options + " ";
console.log(cmd + "\n");
var ex = jake.createExec([cmd]);
ex.addListener("cmdEnd", function() {
fs.renameSync(temp + '/harness/loggedIO.js', loggedIOJsPath);
jake.rmRf(temp);
complete();
});
ex.run();
}, {async: true});

var instrumenterPath = harnessDirectory + 'instrumenter.ts';
var instrumenterJsPath = builtLocalDirectory + 'instrumenter.js';
compileFile(instrumenterJsPath, [instrumenterPath], [tscFile, instrumenterPath], [], true);

desc("Builds an instrumented tsc.js");
task('tsc-instrumented', [loggedIOJsPath, instrumenterJsPath, tscFile], function() {
var cmd = host + ' ' + instrumenterJsPath + ' record iocapture ' + builtLocalDirectory + compilerFilename;
console.log(cmd);
var ex = jake.createExec([cmd]);
ex.addListener("cmdEnd", function() {
complete();
});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here, call complete()

ex.run();
}, { async: true });
10 changes: 6 additions & 4 deletions src/harness/harness.ts
Original file line number Diff line number Diff line change
Expand Up @@ -732,8 +732,10 @@ module Harness {

var filemap: { [name: string]: ts.SourceFile; } = {};
var register = (file: { unitName: string; content: string; }) => {
var filename = Path.switchToForwardSlashes(file.unitName);
filemap[getCanonicalFileName(filename)] = ts.createSourceFile(filename, file.content, options.target, /*version:*/ "0");
if (file.content !== undefined) {
var filename = Path.switchToForwardSlashes(file.unitName);
filemap[getCanonicalFileName(filename)] = ts.createSourceFile(filename, file.content, options.target, /*version:*/ "0");
}
};
inputFiles.forEach(register);
otherFiles.forEach(register);
Expand Down Expand Up @@ -824,7 +826,7 @@ module Harness {
globalErrors.forEach(err => outputErrorText(err));

// 'merge' the lines of each input file with any errors associated with it
inputFiles.forEach(inputFile => {
inputFiles.filter(f => f.content !== undefined).forEach(inputFile => {
// Filter down to the errors in the file
var fileErrors = diagnostics.filter(e => {
var errFn = e.filename;
Expand Down Expand Up @@ -1253,7 +1255,7 @@ module Harness {
}

export function isLibraryFile(filePath: string): boolean {
return filePath.indexOf('lib.d.ts') >= 0 || filePath.indexOf('lib.core.d.ts') >= 0;
return (Path.getFileName(filePath) === 'lib.d.ts') || (Path.getFileName(filePath) === 'lib.core.d.ts');
}

if (Error) (<any>Error).stackTraceLimit = 1;
Expand Down
53 changes: 53 additions & 0 deletions src/harness/instrumenter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
declare var require: any, process: any;
var fs: any = require('fs');
var path: any = require('path');

function instrumentForRecording(fn: string, tscPath: string) {
instrument(tscPath, 'sys = Playback.wrapSystem(sys); sys.startRecord("' + fn + '");', 'sys.endRecord();');
}

function instrumentForReplay(logFilename: string, tscPath: string) {
instrument(tscPath, 'sys = Playback.wrapSystem(sys); sys.startReplay("' + logFilename + '");');
}

function instrument(tscPath: string, prepareCode: string, cleanupCode: string = '') {
var bak = tscPath + '.bak';
fs.exists(bak, (backupExists: boolean) => {
var filename = tscPath;
if (backupExists) {
filename = bak;
}

fs.readFile(filename, 'utf-8', (err: any, tscContent: string) => {
if (err) throw err;

fs.writeFile(bak, tscContent, (err: any) => {
if (err) throw err;

fs.readFile(path.resolve(path.dirname(tscPath) + '/loggedIO.js'), 'utf-8', (err: any, loggerContent: string) => {
if (err) throw err;

var invocationLine = 'ts.executeCommandLine(sys.args);';
var index1 = tscContent.indexOf(invocationLine);
var index2 = index1 + invocationLine.length;
var newContent = tscContent.substr(0, index1) + loggerContent + prepareCode + invocationLine + cleanupCode + tscContent.substr(index2) + '\r\n';
fs.writeFile(tscPath, newContent);
});
});
});
});
}

var isJson = (arg: string) => arg.indexOf(".json") > 0;

var record = process.argv.indexOf('record');
var tscPath = process.argv[process.argv.length - 1];
if (record >= 0) {
console.log('Instrumenting ' + tscPath + ' for recording');
instrumentForRecording(process.argv[record + 1], tscPath);
} else if (process.argv.some(isJson)) {
var filename = process.argv.filter(isJson)[0];
instrumentForReplay(filename, tscPath);
}


52 changes: 43 additions & 9 deletions src/harness/loggedIO.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
/// <reference path="..\..\src\compiler\sys.ts" />
/// <reference path="..\..\src\harness\harness.ts" />
/// <reference path="..\..\src\harness\runnerbase.ts" />

interface FileInformation {
contents: string;
Expand Down Expand Up @@ -93,6 +95,7 @@ module Playback {

function createEmptyLog(): IOLog {
return {
timestamp: (new Date()).toString(),
arguments: [],
currentDirectory: '',
filesRead: [],
Expand All @@ -119,6 +122,8 @@ module Playback {
};
wrapper.startReplayFromData = log => {
replayLog = log;
// Remove non-found files from the log (shouldn't really need them, but we still record them for diganostic purposes)
replayLog.filesRead = replayLog.filesRead.filter(f => f.result.contents !== undefined);
};

wrapper.endReplay = () => {
Expand Down Expand Up @@ -170,22 +175,46 @@ module Playback {
}

function findResultByPath<T>(wrapper: { resolvePath(s: string): string }, logArray: { path: string; result?: T }[], expectedPath: string, defaultValue?: T): T {
var results = logArray.filter(e => pathsAreEquivalent(e.path, expectedPath, wrapper));
if (results.length === 0) {
if (defaultValue === undefined) {
throw new Error('No matching result in log array for path: ' + expectedPath);
} else {
return defaultValue;
var normalizedName = Harness.Path.switchToForwardSlashes(expectedPath).toLowerCase();
// Try to find the result through normal filename
for (var i = 0; i < logArray.length; i++) {
if (Harness.Path.switchToForwardSlashes(logArray[i].path).toLowerCase() === normalizedName) {
return logArray[i].result;
}
}
return results[0].result;
// Fallback, try to resolve the target paths as well
if (replayLog.pathsResolved.length > 0) {
var normalizedResolvedName = wrapper.resolvePath(expectedPath).toLowerCase();
for (var i = 0; i < logArray.length; i++) {
if (wrapper.resolvePath(logArray[i].path).toLowerCase() === normalizedResolvedName) {
return logArray[i].result;
}
}
}
// If we got here, we didn't find a match
if (defaultValue === undefined) {
throw new Error('No matching result in log array for path: ' + expectedPath);
} else {
return defaultValue;
}
}

var pathEquivCache: any = {};
function pathsAreEquivalent(left: string, right: string, wrapper: { resolvePath(s: string): string }) {
var key = left + '-~~-' + right;
function areSame(a: string, b: string) {
return Harness.Path.switchToForwardSlashes(a).toLowerCase() === Harness.Path.switchToForwardSlashes(b).toLowerCase();
}
return areSame(left, right) || areSame(wrapper.resolvePath(left), right) || areSame(left, wrapper.resolvePath(right)) || areSame(wrapper.resolvePath(left), wrapper.resolvePath(right));
function check() {
if (Harness.Path.getFileName(left).toLowerCase() === Harness.Path.getFileName(right).toLowerCase()) {
return areSame(left, right) || areSame(wrapper.resolvePath(left), right) || areSame(left, wrapper.resolvePath(right)) || areSame(wrapper.resolvePath(left), wrapper.resolvePath(right));
}
}
if (pathEquivCache.hasOwnProperty(key)) {
return pathEquivCache[key];
} else {
return pathEquivCache[key] = check();
}
}

function noOpReplay(name: string) {
Expand Down Expand Up @@ -258,7 +287,12 @@ module Playback {
memoize((path) => findResultByFields(replayLog.pathsResolved, { path: path }, !ts.isRootedDiskPath(ts.normalizeSlashes(path)) && replayLog.currentDirectory ? replayLog.currentDirectory + '/' + path : ts.normalizeSlashes(path))));

wrapper.readFile = recordReplay(wrapper.readFile, underlying)(
(path) => callAndRecord(underlying.readFile(path), recordLog.filesRead, { path: path, codepage: 0 }),
(path) => {
var result = underlying.readFile(path);
var logEntry = { path: path, codepage: 0, result: { contents: result, codepage: 0 } };
recordLog.filesRead.push(logEntry);
return result;
},
memoize((path) => findResultByPath(wrapper, replayLog.filesRead, path).contents));

wrapper.writeFile = recordReplay(wrapper.writeFile, underlying)(
Expand Down
2 changes: 1 addition & 1 deletion src/harness/rwcRunner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ module RWC {
}
});

// do not use lib since we shouldnt be reading any files that arent in the ioLog
// do not use lib since we already read it in above
opts.options.noLib = true;

// Emit the results
Expand Down