From b15304fc9ec38e062ad554157677ca0b270319c0 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Fri, 19 Sep 2014 15:09:04 -0700 Subject: [PATCH 1/4] add explict serialization logic for source maps to avoid using JSON --- src/compiler/emitter.ts | 32 ++++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 6b18ad4c133..e86758c48db 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -588,17 +588,33 @@ module ts { recordSourceMapSpan(comment.end); } + function serializeStringArray(list: string[]): string { + if (list && list.length) { + return "\"" + list.join("\",\"") + "\""; + } + return ""; + //var output = ""; + //for (var i = 0, n = list.length; i < n; i++) { + // if (i) output += ","; + // output += "\"" + list[i] + "\""; + //} + //return output; + } + + function serializeSourceMapContents(version: number, file: string, sourceRoot: string, sources: string[], names: string[], mappings: string) { + return "{\"version\":" + version + ",\"file\":\"" + file + "\",\"sourceRoot\":\"" + sourceRoot + "\",\"sources\":[" + serializeStringArray(sources) + "],\"names\":[" + serializeStringArray(names) + "],\"mappings\":\"" + mappings + "\"}"; + } + function writeJavaScriptAndSourceMapFile(emitOutput: string, writeByteOrderMark: boolean) { // Write source map file encodeLastRecordedSourceMapSpan(); - writeFile(sourceMapData.sourceMapFilePath, JSON.stringify({ - version: 3, - file: sourceMapData.sourceMapFile, - sourceRoot: sourceMapData.sourceMapSourceRoot, - sources: sourceMapData.sourceMapSources, - names: sourceMapData.sourceMapNames, - mappings: sourceMapData.sourceMapMappings - }), /*writeByteOrderMark*/ false); + writeFile(sourceMapData.sourceMapFilePath, serializeSourceMapContents( + 3, + sourceMapData.sourceMapFile, + sourceMapData.sourceMapSourceRoot, + sourceMapData.sourceMapSources, + sourceMapData.sourceMapNames, + sourceMapData.sourceMapMappings), /*writeByteOrderMark*/ false); sourceMapDataList.push(sourceMapData); // Write sourcemap url to the js file and write the js file From c0b507ad084b85e20c9859784a244b5d700b955e Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Fri, 19 Sep 2014 15:17:11 -0700 Subject: [PATCH 2/4] remove commented out code --- src/compiler/emitter.ts | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index e86758c48db..2d9c34893b9 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -593,12 +593,6 @@ module ts { return "\"" + list.join("\",\"") + "\""; } return ""; - //var output = ""; - //for (var i = 0, n = list.length; i < n; i++) { - // if (i) output += ","; - // output += "\"" + list[i] + "\""; - //} - //return output; } function serializeSourceMapContents(version: number, file: string, sourceRoot: string, sources: string[], names: string[], mappings: string) { From 804a3a5a57f80225209ed084b0fa403656b04a35 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Mon, 22 Sep 2014 11:50:31 -0700 Subject: [PATCH 3/4] Properly escape strings when serializing source maps --- src/compiler/emitter.ts | 39 ++++++++++++++++++++++++++++++++------- 1 file changed, 32 insertions(+), 7 deletions(-) diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 2d9c34893b9..af1190d27b9 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -588,15 +588,40 @@ module ts { recordSourceMapSpan(comment.end); } - function serializeStringArray(list: string[]): string { - if (list && list.length) { - return "\"" + list.join("\",\"") + "\""; - } - return ""; - } + var escapedCharsRegExp = /[\t\v\f\b\0\r\n\"\u2028\u2029\u0085]/g; + var escapedCharsMap: Map = { + "\t": "\\t", + "\v": "\\v", + "\f": "\\f", + "\b": "\\b", + "\0": "\\0", + "\r": "\\r", + "\n": "\\n", + "\"": "\\\"", + "\u2028": "\\u2028", // lineSeparator + "\u2029": "\\u2029", // paragraphSeparator + "\u0085": "\\u0085" // nextLine + }; function serializeSourceMapContents(version: number, file: string, sourceRoot: string, sources: string[], names: string[], mappings: string) { - return "{\"version\":" + version + ",\"file\":\"" + file + "\",\"sourceRoot\":\"" + sourceRoot + "\",\"sources\":[" + serializeStringArray(sources) + "],\"names\":[" + serializeStringArray(names) + "],\"mappings\":\"" + mappings + "\"}"; + return "{\"version\":" + version + ",\"file\":\"" + escapeString(file) + "\",\"sourceRoot\":\"" + escapeString(sourceRoot) + "\",\"sources\":[" + serializeStringArray(sources) + "],\"names\":[" + serializeStringArray(names) + "],\"mappings\":\"" + escapeString(mappings) + "\"}"; + + /** This does not support the full escape characters, it only supports the subset that can be used in file names + * or string literals. If the information encoded in the map changes, this needs to be revisited. */ + function escapeString(s: string): string { + return escapedCharsRegExp.test(s) ? s.replace(escapedCharsRegExp, c => { + return escapedCharsMap[c] || c; + }) : s; + } + + function serializeStringArray(list: string[]): string { + var output = ""; + for (var i = 0, n = list.length; i < n; i++) { + if (i) output += ","; + output += "\"" + escapeString(list[i]) + "\""; + } + return output; + } } function writeJavaScriptAndSourceMapFile(emitOutput: string, writeByteOrderMark: boolean) { From 4465fe1890d445f787fca4f31ceb680878676ae0 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Mon, 22 Sep 2014 12:47:26 -0700 Subject: [PATCH 4/4] respond to code review comments --- src/compiler/emitter.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index af1190d27b9..397ae1791a8 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -617,7 +617,9 @@ module ts { function serializeStringArray(list: string[]): string { var output = ""; for (var i = 0, n = list.length; i < n; i++) { - if (i) output += ","; + if (i) { + output += ","; + } output += "\"" + escapeString(list[i]) + "\""; } return output;