diff --git a/packages/compiler-cli/src/transformers/node_emitter.ts b/packages/compiler-cli/src/transformers/node_emitter.ts index 03503accc0..eafdb60ddf 100644 --- a/packages/compiler-cli/src/transformers/node_emitter.ts +++ b/packages/compiler-cli/src/transformers/node_emitter.ts @@ -150,13 +150,28 @@ function firstAfter(a: T[], predicate: (value: T) => boolean) { // NodeEmitterVisitor type RecordedNode = (T & { __recorded: any; }) | null; +function escapeLiteral(value: string): string { + return value.replace(/(\"|\\)/g, '\\$1').replace(/(\n)|(\r)/g, function(v, n, r) { + return n ? '\\n' : '\\r'; + }); +} + function createLiteral(value: any) { if (value === null) { return ts.createNull(); } else if (value === undefined) { return ts.createIdentifier('undefined'); } else { - return ts.createLiteral(value); + const result = ts.createLiteral(value); + if (ts.isStringLiteral(result) && result.text.indexOf('\\') >= 0) { + // Hack to avoid problems cause indirectly by: + // https://github.com/Microsoft/TypeScript/issues/20192 + // This avoids the string escaping normally performed for a string relying on that + // TypeScript just emits the text raw for a numeric literal. + (result as any).kind = ts.SyntaxKind.NumericLiteral; + result.text = `"${escapeLiteral(result.text)}"`; + } + return result; } } diff --git a/packages/compiler-cli/test/transformers/node_emitter_spec.ts b/packages/compiler-cli/test/transformers/node_emitter_spec.ts index d589402cfb..b728c793f0 100644 --- a/packages/compiler-cli/test/transformers/node_emitter_spec.ts +++ b/packages/compiler-cli/test/transformers/node_emitter_spec.ts @@ -176,6 +176,14 @@ describe('TypeScriptNodeEmitter', () => { ]).toStmt()) .replace(/\s+/gm, '')) .toEqual(`({someKey:1,a:"a","b":"b","*":"star"});`); + + // Regressions #22774 + expect(emitStmt(o.literal('\\0025BC').toStmt())).toEqual('"\\\\0025BC";'); + expect(emitStmt(o.literal('"some value"').toStmt())).toEqual('"\\"some value\\"";'); + expect(emitStmt(o.literal('"some \\0025BC value"').toStmt())) + .toEqual('"\\"some \\\\0025BC value\\"";'); + expect(emitStmt(o.literal('\n \\0025BC \n ').toStmt())).toEqual('"\\n \\\\0025BC \\n ";'); + expect(emitStmt(o.literal('\r \\0025BC \r ').toStmt())).toEqual('"\\r \\\\0025BC \\r ";'); }); it('should support blank literals', () => {