Skip to content

Define surrogate-safe Python↔JavaScript string conversion at the WASM boundary #8410

Description

@coderabbitai

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

  1. Establish and document the intended surrogate policy for Python↔JavaScript string conversion at the WASM boundary.
  2. Implement shared, UTF-16-aware conversion helpers where needed so JavaScript strings with lone surrogates can enter the Python/WTF-8 representation without loss.
  3. Make the Python→JavaScript conversion behavior match the policy across keyword names, object/string conversion, and serialization paths.
  4. Remove or avoid isolated conversions that route surrogate-containing data through Rust String when that would be lossy or panic.
  5. 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.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions