Skip to content

fix(codegen): escape backticks and ${} in template literal raw values#18101

Closed
CompuIves wants to merge 1 commit intooxc-project:mainfrom
flitsinc:template-literal-escaping
Closed

fix(codegen): escape backticks and ${} in template literal raw values#18101
CompuIves wants to merge 1 commit intooxc-project:mainfrom
flitsinc:template-literal-escaping

Conversation

@CompuIves
Copy link
Contributor

We're using OXC pretty extensively these days for custom transforms, lints and now also for code edits where users make edits in a UI and we update code. I'm a big fan of OXC, it's super fast, easy to use and also works great in the browser!

When manually injecting AST, or e.g. editing AST, I noticed that it's possible to inject backticks in template literals, leading to syntax errors. It seems like we already have escaping logic (single/double quotes, etc) for strings, so I thought it could be valuable to also add escaping to template literals in codegen.

Copilot AI review requested due to automatic review settings January 16, 2026 21:17
@github-actions github-actions bot added A-codegen Area - Code Generation C-bug Category - Bug labels Jan 16, 2026
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR fixes a codegen bug where backticks and template literal interpolation syntax (${}) in template literal raw values could cause syntax errors when generating code. The fix adds proper escaping logic for template literals, handling backticks, ${} sequences, and </script> tags.

Changes:

  • Added print_template_literal_str method to escape special sequences in template literals
  • Added helper function is_preceded_by_odd_backslashes to detect already-escaped characters
  • Updated TemplateLiteral code generation to use the new escaping method
  • Added comprehensive unit tests for the escaping logic

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

File Description
crates/oxc_codegen/src/lib.rs Implements new template literal escaping function with unit tests
crates/oxc_codegen/src/gen.rs Updates TemplateLiteral to use new escaping method instead of script-tag-only escaping
Comments suppressed due to low confidence (1)

crates/oxc_codegen/src/gen.rs:3281

  • TSTemplateLiteralType should also use print_template_literal_str instead of print_str to properly escape backticks, ${}, and </script> sequences, consistent with the runtime TemplateLiteral handling.
            p.print_str(item.value.raw.as_str());

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@codspeed-hq
Copy link

codspeed-hq bot commented Jan 16, 2026

Merging this PR will not alter performance

✅ 42 untouched benchmarks
⏩ 3 skipped benchmarks1


Comparing flitsinc:template-literal-escaping (848f273) with main (b6a065e)

Open in CodSpeed

Footnotes

  1. 3 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

@CompuIves CompuIves force-pushed the template-literal-escaping branch from b3c55d2 to 848f273 Compare January 16, 2026 22:05
@Boshen Boshen self-assigned this Jan 17, 2026
Boshen added a commit that referenced this pull request Jan 17, 2026
…atic template literal creation

Adds a helper method to AstBuilder that creates a TemplateElementValue from a cooked string,
automatically escaping special characters (backticks, ${, backslashes, carriage returns) in the
raw field.

This is useful when programmatically creating template literals. The codegen always expects valid
AST with properly escaped raw values - use this helper instead of manually constructing
TemplateElementValue.

Closes #18101

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Boshen added a commit that referenced this pull request Jan 17, 2026
Add `escape_raw: bool` parameter to `template_element` and
`template_element_with_lone_surrogates` builder methods.

When building template literals programmatically from cooked values,
special characters (backticks, dollar-braces, backslashes, carriage
returns) need to be escaped in the raw field. Setting `escape_raw: true`
automatically handles this escaping.

The parser passes `false` since it receives already-escaped values
from source. Programmatic users should pass `true` when creating
template elements from runtime string values.

Closes #18101

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@Boshen
Copy link
Member

Boshen commented Jan 17, 2026

Superseded by #18121 - instead of escaping in codegen, we add an escape_raw: bool parameter to the template_element builder methods. This makes the escaping explicit and lets users know they need to handle special characters when building template literals programmatically.

Codegen always expects valid AST - users should pass escape_raw: true when creating template elements from runtime string values.

@Boshen Boshen closed this Jan 17, 2026
Boshen added a commit that referenced this pull request Jan 17, 2026
Add `escape_raw: bool` parameter to `template_element` and
`template_element_with_lone_surrogates` builder methods.

When building template literals programmatically from cooked values,
special characters (backticks, dollar-braces, backslashes, carriage
returns) need to be escaped in the raw field. Setting `escape_raw: true`
automatically handles this escaping.

The parser passes `false` since it receives already-escaped values
from source. Programmatic users should pass `true` when creating
template elements from runtime string values.

Closes #18101

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Boshen added a commit that referenced this pull request Jan 17, 2026
Add `escape_raw: bool` parameter to `template_element` and
`template_element_with_lone_surrogates` builder methods.

When building template literals programmatically from cooked values,
special characters (backticks, dollar-braces, backslashes, carriage
returns) need to be escaped in the raw field. Setting `escape_raw: true`
automatically handles this escaping.

The parser passes `false` since it receives already-escaped values
from source. Programmatic users should pass `true` when creating
template elements from runtime string values.

Closes #18101

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
graphite-app bot pushed a commit that referenced this pull request Jan 19, 2026
)

## Summary

- Add `escape_raw: bool` parameter to `template_element` and `template_element_with_lone_surrogates` builder methods
- When `escape_raw: true`, special characters (backticks, `${`, backslashes, carriage returns) are automatically escaped in the raw field
- Parser passes `false` (already-escaped values from source)
- Programmatic users pass `true` (runtime string values need escaping)

This is an alternative approach to #18101 - instead of escaping in codegen, we make the escaping opt-in at the AST builder level.

Closes #18101

## Test plan

- [x] Added test `template_literal_escape_when_building_ast` in codegen tests
- [x] Verified parser still works correctly with `escape_raw: false`

🤖 Generated with [Claude Code](https://claude.com/claude-code)
graphite-app bot pushed a commit that referenced this pull request Jan 19, 2026
)

## Summary

- Add `escape_raw: bool` parameter to `template_element` and `template_element_with_lone_surrogates` builder methods
- When `escape_raw: true`, special characters (backticks, `${`, backslashes, carriage returns) are automatically escaped in the raw field
- Parser passes `false` (already-escaped values from source)
- Programmatic users pass `true` (runtime string values need escaping)

This is an alternative approach to #18101 - instead of escaping in codegen, we make the escaping opt-in at the AST builder level.

Closes #18101

## Test plan

- [x] Added test `template_literal_escape_when_building_ast` in codegen tests
- [x] Verified parser still works correctly with `escape_raw: false`

🤖 Generated with [Claude Code](https://claude.com/claude-code)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-codegen Area - Code Generation C-bug Category - Bug

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants