Skip to content

Commit b1837c8

Browse files
Addressed some CR feedback.
1 parent 5437b3d commit b1837c8

File tree

3 files changed

+41
-24
lines changed

3 files changed

+41
-24
lines changed

src/compiler/emitter.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2211,7 +2211,7 @@ module ts {
22112211

22122212
function getDoubleQuotedStringTextOfLiteral(node: LiteralExpression): string {
22132213
var result = escapeString(node.text);
2214-
result = replaceNonAsciiCharacters(result);
2214+
result = escapeNonAsciiCharacters(result);
22152215

22162216
return '"' + result + '"';
22172217
}

src/compiler/scanner.ts

Lines changed: 30 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -609,20 +609,26 @@ module ts {
609609
return +(text.substring(start, pos));
610610
}
611611

612+
/**
613+
* Scans the given number of hexadecimal digits in the text,
614+
* returning -1 if the given number is unavailable.
615+
*/
612616
function scanExactNumberOfHexDigits(count: number): number {
613-
return scanHexDigits(/*minCount*/ count, /*maxCount*/ count);
617+
return scanHexDigits(/*minCount*/ count, /*scanAsManyAsPossible*/ false);
614618
}
615619

620+
/**
621+
* Scans as many hexadecimal digits as are available in the text,
622+
* returning -1 if the given number of digits was unavailable.
623+
*/
616624
function scanMinimumNumberOfHexDigits(count: number): number {
617-
return scanHexDigits(/*minCount*/ count, /*maxCount*/ undefined);
625+
return scanHexDigits(/*minCount*/ count, /*scanAsManyAsPossible*/ true);
618626
}
619627

620-
function scanHexDigits(minCount: number, maxCount?: number): number {
621-
var maxCountSpecified = maxCount !== undefined;
622-
628+
function scanHexDigits(minCount: number, scanAsManyAsPossible: boolean): number {
623629
var digits = 0;
624630
var value = 0;
625-
while (!maxCountSpecified || digits < maxCount) {
631+
while (digits < minCount || scanAsManyAsPossible) {
626632
var ch = text.charCodeAt(pos);
627633
if (ch >= CharacterCodes._0 && ch <= CharacterCodes._9) {
628634
value = value * 16 + ch - CharacterCodes._0;
@@ -777,22 +783,19 @@ module ts {
777783
case CharacterCodes.doubleQuote:
778784
return "\"";
779785
case CharacterCodes.u:
786+
// '\u{DDDDDDDD}'
780787
if (pos < len && text.charCodeAt(pos) === CharacterCodes.openBrace) {
781788
hasExtendedUnicodeEscape = true;
782789
pos++;
783790
return scanExtendedUnicodeEscape();
784791
}
785792

786-
// fall through
793+
// '\uDDDD'
794+
return scanHexadecimalEscape(/*numDigits*/ 4)
795+
787796
case CharacterCodes.x:
788-
var escapedValue = scanExactNumberOfHexDigits(ch === CharacterCodes.x ? 2 : 4);
789-
if (escapedValue >= 0) {
790-
return String.fromCharCode(escapedValue);
791-
}
792-
else {
793-
error(Diagnostics.Hexadecimal_digit_expected);
794-
return ""
795-
}
797+
// '\xDD'
798+
return scanHexadecimalEscape(/*numDigits*/ 2)
796799

797800
// when encountering a LineContinuation (i.e. a backslash and a line terminator sequence),
798801
// the line terminator is interpreted to be "the empty code unit sequence".
@@ -810,6 +813,18 @@ module ts {
810813
}
811814
}
812815

816+
function scanHexadecimalEscape(numDigits: number): string {
817+
var escapedValue = scanExactNumberOfHexDigits(numDigits);
818+
819+
if (escapedValue >= 0) {
820+
return String.fromCharCode(escapedValue);
821+
}
822+
else {
823+
error(Diagnostics.Hexadecimal_digit_expected);
824+
return ""
825+
}
826+
}
827+
813828
function scanExtendedUnicodeEscape(): string {
814829
var escapedValue = scanMinimumNumberOfHexDigits(1);
815830
var isInvalidExtendedEscape = false;

src/compiler/utilities.ts

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1130,7 +1130,7 @@ module ts {
11301130
newEndN = Math.max(newEnd2, newEnd2 + (newEnd1 - oldEnd2));
11311131
}
11321132

1133-
return createTextChangeRange(createTextSpanFromBounds(oldStartN, oldEndN), /*newLength: */ newEndN - oldStartN);
1133+
return createTextChangeRange(createTextSpanFromBounds(oldStartN, oldEndN), /*newLength*/ newEndN - oldStartN);
11341134
}
11351135

11361136
// @internal
@@ -1213,8 +1213,12 @@ module ts {
12131213
}
12141214
}
12151215

1216-
var backslashOrDoubleQuote = /[\"\\]/g;
1217-
var escapedCharsRegExp = /[\u0000-\u001f\t\v\f\b\r\n\u2028\u2029\u0085]/g;
1216+
// This consists of the first 19 unprintable ASCII characters, canonical escapes, lineSeparator,
1217+
// paragraphSeparator, and nextLine. The latter three are just desirable to suppress new lines in
1218+
// the language service. These characters should be escaped when printing, and if any characters are added,
1219+
// the map below must be updated. Note that this regexp *does not* include the 'delete' character.
1220+
// There is no reason for this other than that JSON.stringify does not handle it either.
1221+
var escapedCharsRegExp = /[\\\"\u0000-\u001f\t\v\f\b\r\n\u2028\u2029\u0085]/g;
12181222
var escapedCharsMap: Map<string> = {
12191223
"\0": "\\0",
12201224
"\t": "\\t",
@@ -1231,13 +1235,11 @@ module ts {
12311235
};
12321236

12331237
/**
1234-
* Based heavily on the abstract 'Quote'/ 'QuoteJSONString' operation from ECMA-262 (24.3.2.2),
1235-
* but augmented for a few select characters.
1238+
* Based heavily on the abstract 'Quote'/'QuoteJSONString' operation from ECMA-262 (24.3.2.2),
1239+
* but augmented for a few select characters (e.g. lineSeparator, paragraphSeparator, nextLine)
12361240
* Note that this doesn't actually wrap the input in double quotes.
12371241
*/
12381242
export function escapeString(s: string): string {
1239-
// Prioritize '"' and '\'
1240-
s = backslashOrDoubleQuote.test(s) ? s.replace(backslashOrDoubleQuote, getReplacement) : s;
12411243
s = escapedCharsRegExp.test(s) ? s.replace(escapedCharsRegExp, getReplacement) : s;
12421244

12431245
return s;
@@ -1254,7 +1256,7 @@ module ts {
12541256
}
12551257

12561258
var nonAsciiCharacters = /[^\u0000-\u007F]/g;
1257-
export function replaceNonAsciiCharacters(s: string): string {
1259+
export function escapeNonAsciiCharacters(s: string): string {
12581260
// Replace non-ASCII characters with '\uNNNN' escapes if any exist.
12591261
// Otherwise just return the original string.
12601262
return nonAsciiCharacters.test(s) ?

0 commit comments

Comments
 (0)