Skip to content

fix(compiler): do not end interpolation early when a regex literal contains }} - #71926

Closed
xh123637 wants to merge 1 commit into
angular:mainfrom
xh123637:fix/71915-regex-interpolation
Closed

xh123637 wants to merge 1 commit into
angular:mainfrom
xh123637:fix/71915-regex-interpolation

Conversation

@xh123637

Copy link
Copy Markdown

PR Checklist

Please check if your PR fulfills the following requirements:

PR Type

What kind of change does this PR introduce?

  • Bugfix
  • Feature
  • Code style update (formatting, local variables)
  • Refactoring (no functional changes, no api changes)
  • Build related changes
  • CI related changes
  • Documentation content changes
  • angular.dev application / infrastructure changes
  • Other... Please describe:

What is the current behavior?

Issue Number: #71915

An interpolation ends early when a regex literal inside it contains }}, for example {{ /[}}]/u.test('}') }}. The template lexer (_consumeInterpolation in packages/compiler/src/ml_parser/lexer.ts) only tracks quotes and // comments while looking for the closing }}, so the }} inside the regex is mistaken for the end of the interpolation. The expression parser (_getInterpolationEndIndex / _forEachUnquotedChar in packages/compiler/src/expression_parser/parser.ts) has the same gap, which is the path hit by e.g. title interpolations.

What is the new behavior?

Both scanners now skip over regex literals while looking for the end of an interpolation. Whether a / starts a regex literal or is a division operator is decided from the previous significant characters, mirroring isStartOfRegex() in the expression lexer (regex after an operator, (, [, , or : or at the start of the expression; division after a value such as an identifier, a number, ) or ]; ! is treated as a negation vs. a non-null assertion the same way the expression lexer treats it). A regex is only skipped when a closing / is found on the same line, so an unterminated regex keeps its previous behavior instead of swallowing the rest of the template. Division is unaffected: {{ 6 / 2 }}, {{ a / b }} and {{ /a/ / 2 }} still parse as before.

Does this PR introduce a breaking change?

  • No

Other information

Tests run (locally, with the repo's own spec files run under Jasmine via an esbuild bundle, since Bazel was not available in this environment):

  • New tests fail on the unmodified code and pass with the fix: ml_parser/lexer_spec.ts ("should parse interpolation with a regex literal containing }}") and expression_parser/parser_spec.ts ("should parse interpolation with a regex literal containing }}", "should still treat a slash after a value as division in interpolation").
  • Full spec files, 816 specs, 0 failures: packages/compiler/test/ml_parser/lexer_spec.ts, ast_serializer_spec.ts, html_parser_spec.ts, html_whitespaces_spec.ts, inline_comment_spec.ts, packages/compiler/test/expression_parser/ast_spec.ts, lexer_spec.ts, parser_spec.ts, serializer_spec.ts.
  • tsc --noEmit is clean for the two changed source files.
  • The examples from the issue ({{ /[}}]/u.test('}') }} in text and in a title attribute, plus {{ /}}/.test('}}') }} and {{ 6 / 2 }}) parse through HtmlParser and Parser.parseInterpolation with no errors.

@angular-robot angular-robot Bot added the area: compiler Issues related to `ngc`, Angular's template compiler label Nov 10, 2026
@ngbot ngbot Bot added this to the Backlog milestone Nov 10, 2026
@pullapprove
pullapprove Bot requested a review from atscott November 10, 2026 19:41
@JeanMeche

Copy link
Copy Markdown
Member

We do not accept AI slop contributions that are opened without considerations of the project. Thank you for your understanding.

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