From 18de560402057a2dc52fc43f2c1fc7e55a7f3f20 Mon Sep 17 00:00:00 2001 From: Ryan Cavanaugh Date: Tue, 2 Sep 2014 12:19:58 -0700 Subject: [PATCH] Add jake task for making instrumented tsc --- Jakefile | 40 +++++++++++++++++++++++++--- src/harness/instrumenter.ts | 53 +++++++++++++++++++++++++++++++++++++ src/harness/loggedIO.ts | 9 ++++++- 3 files changed, 98 insertions(+), 4 deletions(-) create mode 100644 src/harness/instrumenter.ts diff --git a/Jakefile b/Jakefile index b803f23eae8..9dfd02e257c 100644 --- a/Jakefile +++ b/Jakefile @@ -123,6 +123,8 @@ function concatenateFiles(destinationFile, sourceFiles) { } var useDebugMode = false; +var host = (process.env.host || process.env.TYPESCRIPT_HOST || "node"); +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 @@ -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") + " "; } @@ -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"); @@ -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], 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); + }); + 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("error", function(e) { + console.log('error running instrumenter'); + console.log(e); + }); + ex.run(); +}, { async: true }); \ No newline at end of file diff --git a/src/harness/instrumenter.ts b/src/harness/instrumenter.ts new file mode 100644 index 00000000000..61f6a8f2ec3 --- /dev/null +++ b/src/harness/instrumenter.ts @@ -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); +} + + diff --git a/src/harness/loggedIO.ts b/src/harness/loggedIO.ts index dbc3cdbec2c..3adb04adf4b 100644 --- a/src/harness/loggedIO.ts +++ b/src/harness/loggedIO.ts @@ -1,4 +1,6 @@ /// +/// +/// interface FileInformation { contents: string; @@ -258,7 +260,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)(