Skip to content

fix(compiler-cli): escape non-ascii characters in ngp string literals - #71415

Open
JeanMeche wants to merge 1 commit into
angular:mainfrom
JeanMeche:fix/ngp-escape-non-ascii-strings
Open

JeanMeche wants to merge 1 commit into
angular:mainfrom
JeanMeche:fix/ngp-escape-non-ascii-strings

Conversation

@JeanMeche

Copy link
Copy Markdown
Member

Summary

Escapes non-ASCII characters as \uXXXX in string literals emitted by ngp's ExpressionPrinter to match TypeScript's escapeNonAsciiString behavior on synthesized string literals, adds an i18n named placeholder test case (// i18n(ph=...)) to the preprocessor goldens, and removes the \uXXXX normalization from ngp_emit_normalizer.

Changes

  • String literal escaping: Updated EmitterVisitor in packages/compiler-cli/preprocessor/src/output_ast_printer.ts to escape control (\u0000-\u001f) and non-ASCII (\u0080-\uffff) code units as \uXXXX in emitted string literals (LiteralExpr, quoted keys in LiteralMapExpr, and string URLs in DynamicImportExpr).
  • Preprocessor goldens: Added LocalizeNamedPlaceholderCmp with {{ valueA // i18n(ph="PH_A") }} and {{ valueB // i18n(ph="PH B") }} to component_localize/source.md and updated component_localize/golden.md, component_localize/golden.opt.md, and utf16_semantics/golden.md.
  • Normalizer cleanup: Removed \uXXXX decoding from normalizeNgpSourceMapSegment and normalizeNgpEmitForComparison in packages/compiler-cli/src/ngtsc/testing/src/ngp_emit_normalizer.ts.

Escape control and non-ASCII code units as `\uXXXX` in string literals emitted by `ExpressionPrinter` to match TypeScript's `escapeNonAsciiString` behavior on synthesized string literals. Add an i18n named placeholder test case (`// i18n(ph=...)`) to the preprocessor goldens and remove the `\uXXXX` normalization from `ngp_emit_normalizer`.
@angular-robot angular-robot Bot added the area: compiler Issues related to `ngc`, Angular's template compiler label Oct 18, 2026
@ngbot ngbot Bot added this to the Backlog milestone Oct 18, 2026
@JeanMeche
JeanMeche requested review from crisbeto and mattrbeck and removed request for crisbeto October 18, 2026 06:47
* Prints `value` as a single-quoted string literal, escaping control and non-ASCII code units
* as `\uXXXX` to match TypeScript's `escapeNonAsciiString` on synthesized string literals.
*/
function escapeStringLiteral(value: string): string {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How was this happening in ngtsc? Is there something we can reuse?


override visitLiteralMapExpr(ast: o.LiteralMapExpr, ctx: EmitterVisitorContext): void {
withSpan(ctx, ast.sourceSpan, () => super.visitLiteralMapExpr(ast, ctx));
withSpan(ctx, ast.sourceSpan, () => {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe instead of overriding the entire method, we can have a method on the super class that lets us customize how keys are escaped?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: compiler Issues related to `ngc`, Angular's template compiler

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants