Summary
Define and implement one consistent, surrogate-safe conversion policy for Python strings crossing the RustPython WASM JavaScript boundary.
RustPython keyword arguments now retain lone surrogates internally using WTF-8, but converting only WASM keyword names would be incomplete: other PyStr → JavaScript paths (including py_serde) can still fail or perform lossy conversion when a string contains an unpaired surrogate.
Rationale
JavaScript strings are UTF-16 and may contain lone surrogate code units. Python str values in RustPython can represent those values through WTF-8. Rust String and several wasm-bindgen conversion paths are not a lossless representation for this data, so ad hoc conversions can replace lone surrogates with U+FFFD or panic.
The whole WASM bridge needs an explicit policy that applies consistently to both directions and all relevant string conversion paths.
Affected areas
crates/wasm/src/convert.rs
- JavaScript object/keyword keys converted into Python
FuncArgs
- Python function keyword keys converted into JavaScript object properties
- general object conversion paths
- Python-string-to-JavaScript serialization via
py_serde / serde_wasm_bindgen
- Any shared WASM helpers used for
PyStr, WTF-8, js_sys::JsString, or JavaScript UTF-16 conversion
Required changes
- Establish and document the intended surrogate policy for Python↔JavaScript string conversion at the WASM boundary.
- Implement shared, UTF-16-aware conversion helpers where needed so JavaScript strings with lone surrogates can enter the Python/WTF-8 representation without loss.
- Make the Python→JavaScript conversion behavior match the policy across keyword names, object/string conversion, and serialization paths.
- Remove or avoid isolated conversions that route surrogate-containing data through Rust
String when that would be lossy or panic.
- Add WASM-focused regression coverage for lone lead and trailing surrogates in relevant key and value conversion paths.
Acceptance criteria
- No PyStr→JS conversion path in the WASM bridge panics solely because a Python string contains a lone surrogate.
- The behavior for lone surrogates is consistent and explicitly defined across kwargs, object properties, and serialized string values.
- JavaScript→Python conversion preserves UTF-16 lone surrogates where the boundary contract requires it.
- Tests cover both directions and demonstrate the agreed behavior for paired and unpaired surrogates.
Backlinks
Requested by @HyoJongPark.
Summary
Define and implement one consistent, surrogate-safe conversion policy for Python strings crossing the RustPython WASM JavaScript boundary.
RustPython keyword arguments now retain lone surrogates internally using WTF-8, but converting only WASM keyword names would be incomplete: other
PyStr→ JavaScript paths (includingpy_serde) can still fail or perform lossy conversion when a string contains an unpaired surrogate.Rationale
JavaScript strings are UTF-16 and may contain lone surrogate code units. Python
strvalues in RustPython can represent those values through WTF-8. RustStringand several wasm-bindgen conversion paths are not a lossless representation for this data, so ad hoc conversions can replace lone surrogates with U+FFFD or panic.The whole WASM bridge needs an explicit policy that applies consistently to both directions and all relevant string conversion paths.
Affected areas
crates/wasm/src/convert.rsFuncArgspy_serde/serde_wasm_bindgenPyStr, WTF-8,js_sys::JsString, or JavaScript UTF-16 conversionRequired changes
Stringwhen that would be lossy or panic.Acceptance criteria
Backlinks
f(**d)rejects str keys containing lone surrogates: TypeError: keywords must be strings #8228Requested by @HyoJongPark.