From c1d0fd979d1a14b6cb1ecadbc9c1d79553dd0548 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Wed, 16 Jul 2014 10:49:11 -0700 Subject: [PATCH] More I/O fixes Support for --charset command line option File read and write errors are propagated into compiler diagnostics emitFiles returns diagnostics in EmitResult --- src/compiler/commandLineParser.ts | 1 + src/compiler/core.ts | 2 +- .../diagnosticInformationMap.generated.ts | 3 +- src/compiler/diagnosticMessages.json | 8 +- src/compiler/emitter.ts | 41 ++++-- src/compiler/parser.ts | 5 +- src/compiler/sys.ts | 121 +++++++++--------- src/compiler/tc.ts | 101 +++++++-------- src/compiler/types.ts | 14 +- src/harness/harness.ts | 2 +- src/harness/loggedIO.ts | 3 +- src/harness/projectsRunner.ts | 2 +- 12 files changed, 157 insertions(+), 146 deletions(-) diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index 87904cc297c..05acd4e17b1 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -14,6 +14,7 @@ module ts { }; var options: CommandLineOption[] = [ + { name: "charset", type: "string" }, { name: "codepage", type: "number" }, { name: "declaration", type: "boolean" }, { name: "diagnostics", type: "boolean" }, diff --git a/src/compiler/core.ts b/src/compiler/core.ts index 561aeefcc6a..6b1b22487e2 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -279,7 +279,7 @@ module ts { } // Returns length of path root (i.e. length of "/", "x:/", "//server/share/") - function getRootLength(path: string): number { + export function getRootLength(path: string): number { if (path.charCodeAt(0) === CharacterCodes.slash) { if (path.charCodeAt(1) !== CharacterCodes.slash) return 1; var p1 = path.indexOf("/", 2); diff --git a/src/compiler/diagnosticInformationMap.generated.ts b/src/compiler/diagnosticInformationMap.generated.ts index 2ca3f70966e..e3c40ad63e1 100644 --- a/src/compiler/diagnosticInformationMap.generated.ts +++ b/src/compiler/diagnosticInformationMap.generated.ts @@ -195,8 +195,7 @@ module ts { Cannot_find_the_common_subdirectory_path_for_the_input_files: { code: 5009, category: DiagnosticCategory.Error, key: "Cannot find the common subdirectory path for the input files." }, Cannot_read_file_0_Colon_1: { code: 5012, category: DiagnosticCategory.Error, key: "Cannot read file '{0}': {1}" }, Unsupported_file_encoding: { code: 5013, category: DiagnosticCategory.NoPrefix, key: "Unsupported file encoding." }, - Could_not_write_file_0: { code: 5033, category: DiagnosticCategory.Error, key: "Could not write file '{0}'." }, - Could_not_create_directory_0: { code: 5035, category: DiagnosticCategory.Error, key: "Could not create directory '{0}'." }, + Could_not_write_file_0_Colon_1: { code: 5033, category: DiagnosticCategory.Error, key: "Could not write file '{0}': {1}" }, Option_mapRoot_cannot_be_specified_without_specifying_sourcemap_option: { code: 5038, category: DiagnosticCategory.Error, key: "Option mapRoot cannot be specified without specifying sourcemap option." }, Option_sourceRoot_cannot_be_specified_without_specifying_sourcemap_option: { code: 5039, category: DiagnosticCategory.Error, key: "Option sourceRoot cannot be specified without specifying sourcemap option." }, Variable_0_implicitly_has_an_1_type: { code: 7005, category: DiagnosticCategory.Error, key: "Variable '{0}' implicitly has an '{1}' type." }, diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 0e40ea4b049..78a2603dca5 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -11,8 +11,6 @@ "category": "Error", "code": 6003 }, - - "Unrecognized escape sequence.": { "category": "Error", @@ -779,14 +777,10 @@ "category": "NoPrefix", "code": 5013 }, - "Could not write file '{0}'.": { + "Could not write file '{0}': {1}": { "category": "Error", "code": 5033 }, - "Could not create directory '{0}'.": { - "category": "Error", - "code": 5035 - }, "Option mapRoot cannot be specified without specifying sourcemap option.": { "category": "Error", "code": 5038 diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 20999a77cd4..38f51e10d8a 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -69,29 +69,33 @@ module ts { }; } - export function emitFiles(resolver: EmitResolver) { + export function emitFiles(resolver: EmitResolver): EmitResult { var program = resolver.getProgram(); var compilerHost = program.getCompilerHost(); var compilerOptions = program.getCompilerOptions(); var shouldEmitDeclarations = resolver.shouldEmitDeclarations(); - var sourceMapDataList: SourceMapData[] = compilerOptions.sourceMap ? [] : undefined; + var diagnostics: Diagnostic[] = []; + forEach(program.getSourceFiles(), sourceFile => { if (emitToOwnOutputFile(sourceFile, compilerOptions)) { var jsFilePath = getOwnEmitOutputFilePath(sourceFile, program, ".js"); - emitJavaScript(resolver, jsFilePath, sourceMapDataList, sourceFile); + emitJavaScript(resolver, jsFilePath, diagnostics, sourceMapDataList, sourceFile); if (shouldEmitDeclarations) { - emitDeclarations(resolver, jsFilePath, sourceFile); + emitDeclarations(resolver, jsFilePath, diagnostics, sourceFile); } } }); if (compilerOptions.out) { - emitJavaScript(resolver, compilerOptions.out, sourceMapDataList); + emitJavaScript(resolver, compilerOptions.out, diagnostics, sourceMapDataList); if (shouldEmitDeclarations) { - emitDeclarations(resolver, compilerOptions.out); + emitDeclarations(resolver, compilerOptions.out, diagnostics); } } - return sourceMapDataList; + return { + errors: diagnostics, + sourceMaps: sourceMapDataList + }; } interface EmitTextWriter extends TextWriter { @@ -174,7 +178,7 @@ module ts { return text.substring(skipTrivia(text, node.pos), node.end); } - function emitJavaScript(resolver: EmitResolver, jsFilePath: string, sourceMapDataList: SourceMapData[], root?: SourceFile) { + function emitJavaScript(resolver: EmitResolver, jsFilePath: string, diagnostics: Diagnostic[], sourceMapDataList: SourceMapData[], root?: SourceFile) { var program = resolver.getProgram(); var compilerHost = program.getCompilerHost(); var compilerOptions = program.getCompilerOptions(); @@ -221,6 +225,12 @@ module ts { /** Sourcemap data that will get encoded */ var sourceMapData: SourceMapData; + function writeFile(filename: string, data: string) { + compilerHost.writeFile(filename, data, hostErrorMessage => { + diagnostics.push(createCompilerDiagnostic(Diagnostics.Could_not_write_file_0_Colon_1, filename, hostErrorMessage)); + }); + } + function initializeEmitterWithSourceMaps() { var sourceMapDir: string; // The directory in which sourcemap will be @@ -442,7 +452,7 @@ module ts { function writeJavaScriptAndSourceMapFile(emitOutput: string) { // Write source map file encodeLastRecordedSourceMapSpan(); - compilerHost.writeFile(sourceMapData.sourceMapFilePath, JSON.stringify({ + writeFile(sourceMapData.sourceMapFilePath, JSON.stringify({ version: 3, file: sourceMapData.sourceMapFile, sourceRoot: sourceMapData.sourceMapSourceRoot, @@ -527,7 +537,7 @@ module ts { } function writeJavaScriptFile(emitOutput: string) { - compilerHost.writeFile(jsFilePath, emitOutput); + writeFile(jsFilePath, emitOutput); } function emitTokenText(tokenKind: SyntaxKind, startPos: number, emitFn?: () => void) { @@ -1835,7 +1845,7 @@ module ts { writeEmittedFiles(writer.getText()); } - function emitDeclarations(resolver: EmitResolver, jsFilePath: string, root?: SourceFile) { + function emitDeclarations(resolver: EmitResolver, jsFilePath: string, diagnostics: Diagnostic[], root?: SourceFile) { var program = resolver.getProgram(); var compilerOptions = program.getCompilerOptions(); var compilerHost = program.getCompilerHost(); @@ -1847,6 +1857,13 @@ module ts { var decreaseIndent = writer.decreaseIndent; var enclosingDeclaration: Node; + + function writeFile(filename: string, data: string) { + compilerHost.writeFile(filename, data, hostErrorMessage => { + diagnostics.push(createCompilerDiagnostic(Diagnostics.Could_not_write_file_0_Colon_1, filename, hostErrorMessage)); + }); + } + function emitLines(nodes: Node[]) { for (var i = 0, n = nodes.length; i < n; i++) { emitNode(nodes[i]); @@ -2310,6 +2327,6 @@ module ts { }); } - compilerHost.writeFile(getModuleNameFromFilename(jsFilePath) + ".d.ts", referencePathsOutput + writer.getText()); + writeFile(getModuleNameFromFilename(jsFilePath) + ".d.ts", referencePathsOutput + writer.getText()); } } diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index d3e942be2fe..f690697cc5c 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -2989,7 +2989,10 @@ module ts { } else { // If we haven't, read the file. - file = host.getSourceFile(filename, options.target); + file = host.getSourceFile(filename, options.target, hostErrorMessage => { + errors.push(createFileDiagnostic(refFile, refStart, refLength, + Diagnostics.Cannot_read_file_0_Colon_1, filename, hostErrorMessage)); + }); if (file) { filesByName[host.getCanonicalFileName(filename)] = file; seenNoDefaultLib = seenNoDefaultLib || file.hasNoDefaultLib; diff --git a/src/compiler/sys.ts b/src/compiler/sys.ts index 7fdcac1795f..1ac5b3bcde1 100644 --- a/src/compiler/sys.ts +++ b/src/compiler/sys.ts @@ -1,11 +1,13 @@ +/// + interface System { args: string[]; newLine: string; useCaseSensitiveFileNames: boolean; write(s: string): void; writeErr(s: string): void; - readFile(fileName: string): string; - writeFile(fileName: string, data: string): boolean; + readFile(fileName: string, encoding?: string): string; + writeFile(fileName: string, data: string): void; resolvePath(path: string): string; fileExists(path: string): boolean; directoryExists(path: string): boolean; @@ -28,61 +30,63 @@ var sys: System = (function () { var fso = new ActiveXObject("Scripting.FileSystemObject"); var fileStream = new ActiveXObject("ADODB.Stream"); + fileStream.Type = 2; + var binaryStream = new ActiveXObject("ADODB.Stream"); + binaryStream.Type = 1; var args: string[] = []; for (var i = 0; i < WScript.Arguments.length; i++) { args[i] = WScript.Arguments.Item(i); } - function readFile(fileName: string): string { - if (fso.FileExists(fileName)) { - fileStream.Open(); - try { - // Load file in binary mode to ensure no byte order mark is added - fileStream.Type = 1; + function readFile(fileName: string, encoding?: string): string { + if (!fso.FileExists(fileName)) { + return undefined; + } + fileStream.Open(); + try { + if (encoding) { + fileStream.Charset = encoding; fileStream.LoadFromFile(fileName); - // Read the first two bytes into a string with no interpretation - fileStream.Type = 2; + } + else { + // Load file and read the first two bytes into a string with no interpretation fileStream.Charset = "x-ansi"; + fileStream.LoadFromFile(fileName); var bom = fileStream.ReadText(2) || ""; // Position must be at 0 before encoding can be changed fileStream.Position = 0; // [0xFF,0xFE] and [0xFE,0xFF] mean utf-16 (little or big endian), otherwise default to utf-8 fileStream.Charset = bom.length >= 2 && (bom.charCodeAt(0) === 0xFF && bom.charCodeAt(1) === 0xFE || bom.charCodeAt(0) === 0xFE && bom.charCodeAt(1) === 0xFF) ? "unicode" : "utf-8"; - // ReadText method always strips byte order mark from resulting string - var result = fileStream.ReadText(); - fileStream.Close(); - return result; - } - catch (e) { - fileStream.Close(); } + // ReadText method always strips byte order mark from resulting string + return fileStream.ReadText(); + } + catch (e) { + throw e.number === -2147024809 ? new Error(ts.Diagnostics.Unsupported_file_encoding.key) : e; + } + finally { + fileStream.Close(); } - return undefined; } - function writeFile(fileName: string, data: string): boolean { + function writeFile(fileName: string, data: string): void { fileStream.Open(); binaryStream.Open(); try { - fileStream.Type = 2; + // Write characters in UTF-8 encoding fileStream.Charset = "utf-8"; fileStream.WriteText(data); - // Skip byte order mark and copy remaining text to binary stream - binaryStream.Type = 1; + // Skip byte order mark and copy remaining data to binary stream fileStream.Position = 3; fileStream.CopyTo(binaryStream); binaryStream.SaveToFile(fileName, 2 /*overwrite*/); - binaryStream.Close(); - fileStream.Close(); - return true; } - catch (e) { + finally { binaryStream.Close(); fileStream.Close(); } - return false; } return { @@ -134,42 +138,37 @@ var sys: System = (function () { // win32\win64 are case insensitive platforms, MacOS (darwin) by default is also case insensitive var useCaseSensitiveFileNames = platform !== "win32" && platform !== "win64" && platform !== "darwin"; - function readFile(fileName: string): string { - if (_fs.existsSync(fileName)) { - try { - var buffer = _fs.readFileSync(fileName); - var len = buffer.length; - if (len >= 2 && buffer[0] === 0xFE && buffer[1] === 0xFF) { - len &= ~1; - for (var i = 0; i < len; i += 2) { - var temp = buffer[i]; - buffer[i] = buffer[i + 1]; - buffer[i + 1] = temp; - } - return buffer.toString("utf16le", 2); - } - if (len >= 2 && buffer[0] === 0xFF && buffer[1] === 0xFE) { - return buffer.toString("utf16le", 2); - } - if (len >= 3 && buffer[0] === 0xEF && buffer[1] === 0xBB && buffer[2] === 0xBF) { - return buffer.toString("utf8", 3); - } - return buffer.toString("utf8"); - } - catch (e) { - } + function readFile(fileName: string, encoding?: string): string { + if (!_fs.existsSync(fileName)) { + return undefined; } - return undefined; + var buffer = _fs.readFileSync(fileName); + var len = buffer.length; + if (len >= 2 && buffer[0] === 0xFE && buffer[1] === 0xFF) { + // Big endian UTF-16 byte order mark detected. Since big endian is not supported by node.js, + // flip all byte pairs and treat as little endian. + len &= ~1; + for (var i = 0; i < len; i += 2) { + var temp = buffer[i]; + buffer[i] = buffer[i + 1]; + buffer[i + 1] = temp; + } + return buffer.toString("utf16le", 2); + } + if (len >= 2 && buffer[0] === 0xFF && buffer[1] === 0xFE) { + // Little endian UTF-16 byte order mark detected + return buffer.toString("utf16le", 2); + } + if (len >= 3 && buffer[0] === 0xEF && buffer[1] === 0xBB && buffer[2] === 0xBF) { + // UTF-8 byte order mark detected + return buffer.toString("utf8", 3); + } + // Default is UTF-8 with no byte order mark + return buffer.toString("utf8"); } - function writeFile(fileName: string, data: string): boolean { - try { - _fs.writeFileSync(fileName, data, "utf8"); - return true; - } - catch (e) { - } - return false; + function writeFile(fileName: string, data: string): void { + _fs.writeFileSync(fileName, data, "utf8"); } return { @@ -222,4 +221,4 @@ var sys: System = (function () { else { return undefined; // Unsupported host } -})(); \ No newline at end of file +})(); diff --git a/src/compiler/tc.ts b/src/compiler/tc.ts index 0c47bc303b8..d683dd8dab4 100644 --- a/src/compiler/tc.ts +++ b/src/compiler/tc.ts @@ -76,8 +76,6 @@ module ts { return count; } - // TODO (drosen): Make localize-friendly - var hasReportedErrors = false; function reportErrors(errors: Diagnostic[]) { for (var i = 0; i < errors.length; i++) { var error = errors[i]; @@ -90,7 +88,6 @@ module ts { else { sys.writeErr(error.messageText + sys.newLine); } - hasReportedErrors = true; } } @@ -116,61 +113,56 @@ module ts { reportDiagnostic(name, (time / 1000).toFixed(2) + "s"); } - function getSourceFile(filename: string, languageVersion: ScriptTarget): SourceFile { - var text = sys.readFile(filename); - return text ? createSourceFile(filename, text, languageVersion) : undefined; - } + function createCompilerHost(options: CompilerOptions): CompilerHost { + var currentDirectory: string; + var existingDirectories: Map = {}; - function writeFile(fileName: string, data: string) { - // TODO: Review this code for performance - - //function ensureDirectoryStructure(directoryName: string) { - // if (directoryName) { - // if (!sys.directoryExists(directoryName)) { - // var parentDirectory = getDirectoryPath(directoryName); - // // If we arent at the root path ensure that the folder exists - // if (parentDirectory !== directoryName) { - // if (ensureDirectoryStructure(parentDirectory)) { - // // If parent directory was present, create the current directory - // try { - // sys.createDirectory(directoryName); - // } - // catch (e) { - // reportErrors([createCompilerDiagnostic(Diagnostics.Could_not_create_directory_0, [directoryName])]); - // return false; - // } - // } - // } - // } - // } - // return true; - //} - //// If parent directory structure is present create the file - //if (ensureDirectoryStructure(getDirectoryPath(normalizePath(fileName)))) { - // try { - // sys.writeFile(fileName, data); - // } - // catch (e) { - // reportErrors([createCompilerDiagnostic(Diagnostics.Could_not_write_file_0, [fileName])]); - // } - //} - if (!sys.writeFile(fileName, data)) { - reportErrors([createCompilerDiagnostic(Diagnostics.Could_not_write_file_0, [fileName])]); + function getSourceFile(filename: string, languageVersion: ScriptTarget, onError?: (message: string) => void): SourceFile { + try { + var text = sys.readFile(filename, options.charset); + } + catch (e) { + if (onError) onError(e.message); + text = ""; + } + return text !== undefined ? createSourceFile(filename, text, languageVersion) : undefined; } - } - var currentDirectory: string; - function getCurrentDictory() { - currentDirectory = currentDirectory || sys.getCurrentDirectory(); - return currentDirectory; - } + function writeFile(fileName: string, data: string, onError?: (message: string) => void) { + + function directoryExists(directoryPath: string): boolean { + if (hasProperty(existingDirectories, directoryPath)) { + return true; + } + if (sys.directoryExists(directoryPath)) { + existingDirectories[directoryPath] = true; + return true; + } + return false; + } + + function ensureDirectoriesExist(directoryPath: string) { + if (directoryPath.length > getRootLength(directoryPath) && !directoryExists(directoryPath)) { + var parentDirectory = getDirectoryPath(directoryPath); + ensureDirectoriesExist(parentDirectory); + sys.createDirectory(directoryPath); + } + } + + try { + ensureDirectoriesExist(getDirectoryPath(normalizePath(fileName))); + sys.writeFile(fileName, data); + } + catch (e) { + if (onError) onError(e.message); + } + } - function createCompilerHost(): CompilerHost { return { getSourceFile: getSourceFile, getDefaultLibFilename: () => combinePaths(getDirectoryPath(normalizePath(sys.getExecutingFilePath())), "lib.d.ts"), writeFile: writeFile, - getCurrentDirectory: getCurrentDictory, + getCurrentDirectory: () => currentDirectory || sys.getCurrentDirectory(), useCaseSensitiveFileNames: () => sys.useCaseSensitiveFileNames, getCanonicalFileName: getCanonicalFileName }; @@ -201,7 +193,7 @@ module ts { } var parseStart = new Date().getTime(); - var program = createProgram(cmds.filenames, cmds.options, createCompilerHost()); + var program = createProgram(cmds.filenames, cmds.options, createCompilerHost(cmds.options)); var bindStart = new Date().getTime(); var errors = program.getDiagnostics(); if (errors.length) { @@ -212,10 +204,11 @@ module ts { else { var checker = program.getTypeChecker(); var checkStart = new Date().getTime(); - errors = checker.getDiagnostics(); + var semanticErrors = checker.getDiagnostics(); var emitStart = new Date().getTime(); - checker.emitFiles(); + var emitErrors = checker.emitFiles().errors; var reportStart = new Date().getTime(); + errors = concatenate(semanticErrors, emitErrors); } reportErrors(errors); @@ -232,7 +225,7 @@ module ts { reportDiagnosticTime("Emit time", reportStart - emitStart); reportDiagnosticTime("Total time", reportStart - parseStart); } - return hasReportedErrors ? 1 : 0; + return errors.length ? 1 : 0; } } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index c63d5ef1242..23ec07d5ad1 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -566,7 +566,12 @@ module ts { /** Raw source map spans that were encoded into the sourceMapMappings*/ sourceMapDecodedMappings: SourceMapSpan[]; } - + + export interface EmitResult { + errors: Diagnostic[]; + sourceMaps: SourceMapData[]; // Array of sourceMapData if compiler emitted sourcemaps + } + export interface TypeChecker { getProgram(): Program; getDiagnostics(sourceFile?: SourceFile): Diagnostic[]; @@ -576,7 +581,7 @@ module ts { getSymbolCount(): number; getTypeCount(): number; checkProgram(): void; - emitFiles(): SourceMapData[]; // returns list of sourceMapData if compiler emitted sourcemaps + emitFiles(): EmitResult; getSymbolOfNode(node: Node): Symbol; getParentOfSymbol(symbol: Symbol): Symbol; getTypeOfSymbol(symbol: Symbol): Type; @@ -896,6 +901,7 @@ module ts { } export interface CompilerOptions { + charset?: string; codepage?: number; declaration?: boolean; diagnostics?: boolean; @@ -1083,10 +1089,10 @@ module ts { } export interface CompilerHost { - getSourceFile(filename: string, languageVersion: ScriptTarget): SourceFile; + getSourceFile(filename: string, languageVersion: ScriptTarget, onError?: (message: string) => void): SourceFile; getDefaultLibFilename(): string; getCancellationToken? (): CancellationToken; - writeFile(filename: string, data: string): void; + writeFile(filename: string, data: string, onError?: (message: string) => void): void; getCurrentDirectory(): string; getCanonicalFileName(fileName: string): string; useCaseSensitiveFileNames(): boolean; diff --git a/src/harness/harness.ts b/src/harness/harness.ts index 312b65a9eeb..80ac9d2d589 100644 --- a/src/harness/harness.ts +++ b/src/harness/harness.ts @@ -738,7 +738,7 @@ module Harness { // only emit if there weren't parse errors var sourceMapData: ts.SourceMapData[]; if (!hadParseErrors) { - sourceMapData = checker.emitFiles(); + sourceMapData = checker.emitFiles().sourceMaps; } var errors: MinimalDiagnostic[] = []; diff --git a/src/harness/loggedIO.ts b/src/harness/loggedIO.ts index 9311178af38..5dfd10dfa02 100644 --- a/src/harness/loggedIO.ts +++ b/src/harness/loggedIO.ts @@ -190,9 +190,8 @@ module Playback { return areSame(left, right) || areSame(wrapper.resolvePath(left), right) || areSame(left, wrapper.resolvePath(right)) || areSame(wrapper.resolvePath(left), wrapper.resolvePath(right)); } - function noOpReplay(name: string): boolean { + function noOpReplay(name: string) { console.log("Swallowed write operation during replay: " + name); - return true; } export function wrapSystem(underlying: System): PlaybackSystem { diff --git a/src/harness/projectsRunner.ts b/src/harness/projectsRunner.ts index df228263e76..3335bf512d9 100644 --- a/src/harness/projectsRunner.ts +++ b/src/harness/projectsRunner.ts @@ -232,7 +232,7 @@ class ProjectRunner extends RunnerBase { if (!errors.length) { var checker = program.getTypeChecker(); errors = checker.getDiagnostics(); - sourceMapData = checker.emitFiles(); + sourceMapData = checker.emitFiles().sourceMaps; // Clean up source map data that will be used in baselining if (sourceMapData) {