Skip to content

Commit bba41a8

Browse files
author
Arthur Ozga
committed
avoid ascii escaping literal text
1 parent d8f29a5 commit bba41a8

8 files changed

+25
-20
lines changed

src/compiler/checker.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2385,7 +2385,7 @@ namespace ts {
23852385
return createTypeReferenceNode(name, /*typeArguments*/ undefined);
23862386
}
23872387
if (type.flags & (TypeFlags.StringLiteral)) {
2388-
return createLiteralTypeNode((createLiteral((<LiteralType>type).text)));
2388+
return createLiteralTypeNode(setEmitFlags(createLiteral((<LiteralType>type).text), EmitFlags.NoAsciiEscaping));
23892389
}
23902390
if (type.flags & (TypeFlags.NumberLiteral)) {
23912391
return createLiteralTypeNode((createNumericLiteral((<LiteralType>type).text)));
@@ -2783,7 +2783,9 @@ namespace ts {
27832783
let returnTypeNode: TypeNode;
27842784
if (signature.typePredicate) {
27852785
const typePredicate = signature.typePredicate;
2786-
const parameterName = typePredicate.kind === TypePredicateKind.Identifier ? createIdentifier((<IdentifierTypePredicate>typePredicate).parameterName) : createThisTypeNode();
2786+
const parameterName = typePredicate.kind === TypePredicateKind.Identifier ?
2787+
setEmitFlags(createIdentifier((<IdentifierTypePredicate>typePredicate).parameterName), EmitFlags.NoAsciiEscaping) :
2788+
createThisTypeNode();
27872789
const typeNode = typeToTypeNodeHelper(typePredicate.type, context);
27882790
returnTypeNode = createTypePredicateNode(parameterName, typeNode);
27892791
}
@@ -2894,7 +2896,7 @@ namespace ts {
28942896
}
28952897

28962898
const symbolName = getNameOfSymbol(symbol, context);
2897-
const identifier = createIdentifier(symbolName, typeParameterNodes);
2899+
const identifier = setEmitFlags(createIdentifier(symbolName, typeParameterNodes), EmitFlags.NoAsciiEscaping);
28982900

28992901
return index > 0 ? createQualifiedName(createEntityNameFromSymbolChain(chain, index - 1), identifier) : identifier;
29002902
}

src/compiler/emitter.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2653,7 +2653,9 @@ namespace ts {
26532653
if (node.kind === SyntaxKind.StringLiteral && (<StringLiteral>node).textSourceNode) {
26542654
const textSourceNode = (<StringLiteral>node).textSourceNode;
26552655
if (isIdentifier(textSourceNode)) {
2656-
return "\"" + escapeNonAsciiCharacters(escapeString(getTextOfNode(textSourceNode))) + "\"";
2656+
return getEmitFlags(node) & EmitFlags.NoAsciiEscaping ?
2657+
`"${escapeString(getTextOfNode(textSourceNode))}"` :
2658+
`"${escapeNonAsciiCharacters(escapeString(getTextOfNode(textSourceNode)))}"`;
26572659
}
26582660
else {
26592661
return getLiteralTextOfNode(textSourceNode);

src/compiler/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3985,6 +3985,7 @@ namespace ts {
39853985
NoHoisting = 1 << 21, // Do not hoist this declaration in --module system
39863986
HasEndOfDeclarationMarker = 1 << 22, // Declaration has an associated NotEmittedStatement to mark the end of the declaration
39873987
Iterator = 1 << 23, // The expression to a `yield*` should be treated as an Iterator when down-leveling, not an Iterable.
3988+
NoAsciiEscaping = 1 << 24, // When synthesizing nodes that lack an original node or textSourceNode, we want to write the text on the node with ASCII escaping substitutions.
39883989
}
39893990

39903991
export interface EmitHelper {

src/compiler/utilities.ts

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -328,30 +328,29 @@ namespace ts {
328328
return getSourceTextOfNodeFromSourceFile(sourceFile, node);
329329
}
330330

331+
const escapeText = getEmitFlags(node) & EmitFlags.NoAsciiEscaping ?
332+
(text: string) => escapeString(text) :
333+
(text: string) => escapeNonAsciiCharacters(escapeString(text));
331334
// If we can't reach the original source text, use the canonical form if it's a number,
332-
// or an escaped quoted form of the original text if it's string-like.
335+
// or a (possibly escaped) quoted form of the original text if it's string-like.
333336
switch (node.kind) {
334337
case SyntaxKind.StringLiteral:
335-
return getQuotedEscapedLiteralText('"', node.text, '"');
338+
return '"' + escapeText(node.text) + '"';
336339
case SyntaxKind.NoSubstitutionTemplateLiteral:
337-
return getQuotedEscapedLiteralText("`", node.text, "`");
340+
return "`" + escapeText(node.text) + "`";
338341
case SyntaxKind.TemplateHead:
339-
return getQuotedEscapedLiteralText("`", node.text, "${");
342+
return "`" + escapeText(node.text) + "${";
340343
case SyntaxKind.TemplateMiddle:
341-
return getQuotedEscapedLiteralText("}", node.text, "${");
344+
return "}" + escapeText(node.text) + "${";
342345
case SyntaxKind.TemplateTail:
343-
return getQuotedEscapedLiteralText("}", node.text, "`");
346+
return "}" + escapeText(node.text) + "`";
344347
case SyntaxKind.NumericLiteral:
345348
return node.text;
346349
}
347350

348351
Debug.fail(`Literal kind '${node.kind}' not accounted for.`);
349352
}
350353

351-
function getQuotedEscapedLiteralText(leftQuote: string, text: string, rightQuote: string) {
352-
return leftQuote + escapeNonAsciiCharacters(escapeString(text)) + rightQuote;
353-
}
354-
355354
// Add an extra underscore to identifiers that start with two underscores to avoid issues with magic names like '__proto__'
356355
export function escapeIdentifier(identifier: string): string {
357356
return identifier.length >= 2 && identifier.charCodeAt(0) === CharacterCodes._ && identifier.charCodeAt(1) === CharacterCodes._ ? "_" + identifier : identifier;
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
var = "Ü­ਲĭ";
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
/// <reference path='fourslash.ts' />
22

33
//// interface I<X> {
4-
//// [x: string]: X;
4+
//// [Ƚ: string]: X;
55
//// }
66
////
77
//// class C implements I<number> {[| |]}
88

99
verify.rangeAfterCodeFix(`
10-
[x: string]: number;
10+
[Ƚ: string]: number;
1111
`);

tests/cases/fourslash/codeFixClassImplementInterfaceInheritsAbstractMethod.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,12 @@
22

33
//// abstract class C1 { }
44
//// abstract class C2 {
5-
//// abstract f1<T extends number>();
5+
//// abstract fA<T extends number>();
66
//// }
77
//// interface I1 extends C1, C2 { }
88
//// class C3 implements I1 {[| |]}
99

10-
verify.rangeAfterCodeFix(`f1<T extends number>(){
10+
verify.rangeAfterCodeFix(`fA<T extends number>(){
1111
throw new Error("Method not implemented.");
1212
}
1313
`);

tests/cases/fourslash/codeFixClassImplementInterfaceMultipleImplements2.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,15 @@
44
//// x: number;
55
//// }
66
//// interface I2 {
7-
//// y: number;
7+
//// y: "𣋝ઢȴ¬⏊";
88
//// }
99
////
1010
//// class C implements I1,I2 {[|
1111
//// |]x: number;
1212
//// }
1313

1414
verify.rangeAfterCodeFix(`
15-
y: number;
15+
y: "𣋝ઢȴ¬⏊";
1616
`);
1717

1818
verify.not.codeFixAvailable();

0 commit comments

Comments
 (0)