/// <summary> /// Given a generated filename gets the source map from the .js file /// </summary> private ReverseSourceMap GetReverseSourceMap(string fileName) { ReverseSourceMap sourceMap; if (!_generatedFileToSourceMap.TryGetValue(fileName, out sourceMap)) { // See if we are using source maps for this file. foreach (var keyValue in _originalFileToSourceMap) { foreach (var source in keyValue.Value.Map.Sources) { var path = GetFileRelativeToFile(keyValue.Key, source); if (CommonUtils.IsSamePath(path, fileName)) { return(_generatedFileToSourceMap[fileName] = new ReverseSourceMap( keyValue.Value.Map, keyValue.Key )); } } } // Fallback to TypeScript specific logic... This might be better for // try and look next to the .js file... string extension; try { extension = Path.GetExtension(fileName); } catch (ArgumentException) { extension = String.Empty; } if (!string.Equals(extension, NodejsConstants.JavaScriptExtension, StringComparison.OrdinalIgnoreCase)) { string baseFile = fileName.Substring(0, fileName.Length - extension.Length); string jsFile = baseFile + NodejsConstants.JavaScriptExtension; if (File.Exists(jsFile) && File.Exists(jsFile + NodejsConstants.MapExtension)) { // we're using source maps... try { using (StreamReader reader = new StreamReader(baseFile + NodejsConstants.JavaScriptExtension + NodejsConstants.MapExtension)) { _generatedFileToSourceMap[fileName] = sourceMap = new ReverseSourceMap( new SourceMap(reader), jsFile ); } } catch (NotSupportedException) { _generatedFileToSourceMap[fileName] = null; } catch (InvalidOperationException) { _generatedFileToSourceMap[fileName] = null; } } else { _generatedFileToSourceMap[fileName] = null; } } } return(sourceMap); }
/// <summary> /// Maps a line number from the original code to the generated JavaScript. /// Line numbers are zero based. /// </summary> internal bool MapToJavaScript(string requestedFileName, int requestedLineNo, int requestedColumnNo, out string fileName, out int lineNo, out int columnNo) { fileName = requestedFileName; lineNo = requestedLineNo; columnNo = requestedColumnNo; ReverseSourceMap sourceMap = GetReverseSourceMap(requestedFileName); if (sourceMap != null) { SourceMapInfo result; if (sourceMap.Mapping.TryMapPointBack(requestedLineNo, requestedColumnNo, out result)) { lineNo = result.Line; columnNo = result.Column; foreach (var source in sourceMap.Mapping.Sources) { // requestedFilename == projectdir\server.ts // sourceMap.JavaScriptFile == projectdir\out\server.js // source == ..\server.ts // var path = GetFileRelativeToFile(sourceMap.JavaScriptFile, source); if (CommonUtils.IsSamePath(path, requestedFileName)) { fileName = sourceMap.JavaScriptFile; return(true); } } try { fileName = Path.Combine(Path.GetDirectoryName(fileName) ?? string.Empty, result.FileName); } catch (ArgumentException) { } catch (PathTooLongException) { } Debug.WriteLine("Mapped breakpoint from {0} {1} to {2} {3}", requestedFileName, requestedLineNo, fileName, lineNo); } return(true); } return(false); }
/// <summary> /// Given a generated filename gets the source map from the .js file /// </summary> private ReverseSourceMap GetReverseSourceMap(string fileName) { ReverseSourceMap sourceMap; if (!_generatedFileToSourceMap.TryGetValue(fileName, out sourceMap)) { // See if we are using source maps for this file. foreach(var keyValue in _originalFileToSourceMap) { foreach (var source in keyValue.Value.Map.Sources) { var path = GetFileRelativeToFile(keyValue.Key, source); if (CommonUtils.IsSamePath(path, fileName)) { return _generatedFileToSourceMap[fileName] = new ReverseSourceMap( keyValue.Value.Map, keyValue.Key ); } } } // Fallback to TypeScript specific logic... This might be better for // try and look next to the .js file... string extension; try { extension = Path.GetExtension(fileName); } catch (ArgumentException) { extension = String.Empty; } if (!string.Equals(extension, NodejsConstants.JavaScriptExtension, StringComparison.OrdinalIgnoreCase)) { string baseFile = fileName.Substring(0, fileName.Length - extension.Length); string jsFile = baseFile + NodejsConstants.JavaScriptExtension; if (File.Exists(jsFile) && File.Exists(jsFile + NodejsConstants.MapExtension)) { // we're using source maps... try { using (StreamReader reader = new StreamReader(baseFile + NodejsConstants.JavaScriptExtension + NodejsConstants.MapExtension)) { _generatedFileToSourceMap[fileName] = sourceMap = new ReverseSourceMap( new SourceMap(reader), jsFile ); } } catch (NotSupportedException) { _generatedFileToSourceMap[fileName] = null; } catch (InvalidOperationException) { _generatedFileToSourceMap[fileName] = null; } } else { _generatedFileToSourceMap[fileName] = null; } } } return sourceMap; }