Files
Dunqing 3b07d0d52d refactor(ast)!: migrate string literals and templates to JSStr (#26548)
JavaScript strings can contain lone surrogates, which Rust's `str` cannot hold. String literal values and template cooked values stored them in a private U+FFFD escape encoding behind a `lone_surrogates` flag that every consumer had to check.

This migrates `StringLiteral::value` and `TemplateElementValue::cooked` to `JSStr`, which keeps the exact UTF-16 value through parsing, AST consumers, codegen and ESTree/raw transfer. Code that needs Rust text calls `JSStr::as_str()`, which returns `None` for a value with a lone surrogate. Surrogate halves written as separate escapes or concatenated from separate parts are joined. Enum members whose name or value contains a lone surrogate keep their string kind, so lowering no longer emits a reverse mapping for a string alias that could overwrite another member.

Some lint and declaration checks skip lone-surrogate names until #26677, #27095, #26716 and #26717.

## Breaking changes

- `StringLiteral::value` is `JSStr<'a>`, and `TemplateElementValue::cooked` is `Option<JSStr<'a>>`.
- Removed: the `lone_surrogates` fields, the `*_with_lone_surrogates` builder methods, `oxc_parser::Token::lone_surrogates`, and `impl Display for StringLiteral`.
- `ImportAttributeKey::as_arena_str` is renamed to `as_js_str`. `TSEnumMemberName::static_name`, `TemplateLiteral::single_quasi` and `ModuleRunnerTransform::transform` return `JSStr`.
- `oxc_estree::LoneSurrogatesString` wraps an iterator of code points.
- `ModuleExportName::name` panics on a string name with a lone surrogate, which only a built AST can contain.

Part of #26242.

Implemented with AI assistance.
2026-10-14 00:26:15 +00:00
..