dillon1000/react

Commit

[rust-compiler] Represent string values as JsString (WTF-16 aware) (#36731)

Last of the boundary trilogy, after #36729 and #36730 (both merged);
rebased onto main as a standalone 3-commit change.

JS strings are WTF-16: a lone surrogate in source (`"\uD83E"`) is a
legal string value, but Rust `String` is UTF-8 and cannot hold it. The
compiler previously leaned on the napi bridge's `__SURROGATE_XXXX__`
marker encoding end to end, so the core compiler compared, concatenated,
and constant-folded marker text as if it were the actual string value.

`JsString` (in `react_compiler_diagnostics`, our lowest layer) holds the
common well-formed case as a plain UTF-8 `String` with zero overhead and
falls back to UTF-16 code units only for ill-formed values.
`StringLiteral.value` and `PrimitiveValue::String` carry it through the
pipeline; constant folding concatenates via code units so split
surrogate halves re-pair exactly as they do in JS; markers are emitted
only at the napi edge, where the babel bridge requires them (serde_json
can neither parse nor emit a lone `\uXXXX` escape).

The representation is encapsulated behind an opaque struct (private
`Repr` enum, borrowed `JsStringRef` view via `as_ref`) so the
"well-formed values are always UTF-8" invariant that makes the derived
`PartialEq`/`Hash` sound holds by construction, per review feedback.

The marker decoder scans byte-wise (an earlier draft range-sliced at
fixed offsets and panicked on multibyte UTF-8 following `__SURROGATE_`),
validates hex digits, and accepts uppercase only, exactly mirroring what
the bridge emits; lowercase marker-shaped user text survives verbatim.
The HIR debug printer renders unpaired surrogates as `\uXXXX` escapes
byte-identical to the TS printer.

This closes the lone-surrogate divergence on the e2e harness. Verified
on the rebased branch: cargo workspace tests, Rust snap channel
1804/1804, and HIR + Code parity on the lone-surrogate fixture through
the comparison harness.
Browse files
Changed paths14 files
First-parent comparison
M compiler/Cargo.lock ModifiedM compiler/crates/react_compiler/src/entrypoint/imports.rs ModifiedM compiler/crates/react_compiler/src/entrypoint/program.rs ModifiedM compiler/crates/react_compiler_ast/Cargo.toml ModifiedM compiler/crates/react_compiler_ast/src/literals.rs ModifiedA compiler/crates/react_compiler_diagnostics/src/js_string.rs AddedM compiler/crates/react_compiler_diagnostics/src/lib.rs ModifiedM compiler/crates/react_compiler_hir/src/lib.rs ModifiedM compiler/crates/react_compiler_hir/src/print.rs ModifiedM compiler/crates/react_compiler_inference/src/memoize_fbt_and_macro_operands_in_same_scope.rs ModifiedM compiler/crates/react_compiler_lowering/src/build_hir.rs ModifiedM compiler/crates/react_compiler_optimization/src/constant_propagation.rs ModifiedM compiler/crates/react_compiler_reactive_scopes/src/codegen_reactive_function.rs ModifiedM compiler/crates/react_compiler_reactive_scopes/src/propagate_early_returns.rs Modified
Patch

Files changed

Rendering syntax-highlighted changes…