Print @as names and external strings as ReScript string literals
Why
The printer wrote the @as name of a constructor with OCaml's %S and the @as name of a field and the strings of an external with String.escaped. Both turn non-ASCII bytes into decimal escapes such as \195\169, which ReScript reads back as other characters: an interface written by createInterface for an applied functor then gave its fields and constructors other runtime names than the implementation (#9142). They are now encoded with String_literal.encode_js_string, which keeps valid UTF-8 and escapes only what a string literal needs.
modifiedDiagnostic @as names of a constructor and a field
module M: { type t = | @as("é") A({@as("prénom") name: string}) | @as("a\"b") B} = { type t = | @as("é") A({@as("prénom") name: int}) | @as("a\"b") B}
diagnostic
Before
After
Actual declaration (as_names_printed_as_written.res:6:3-66):Actual declaration (as_names_printed_as_written.res:6:3-66): type t = @as("\195\169") A({@as("pr\195\169nom") name: int}) | @as("a\"b") B type t = @as("é") A({@as("prénom") name: int}) | @as("a\"b") B
modifiedDiagnostic strings of an external
module M: { @module("ünïcode") @scope("ëxtra") external f: int => int = "f"} = { @module("ünïcode") @scope("ëxtra") external f: string => int = "f"}
diagnostic
Before
After
Actual declaration (external_strings_printed_as_written.res:6:3-7:33):Actual declaration (external_strings_printed_as_written.res:6:3-7:33): @val @module("\195\188n\195\175code") @scope("\195\171xtra") external f: string => int = "f" @val @module("ünïcode") @scope("ëxtra") external f: string => int = "f"
modifiedFormat createInterface for an applied functor
module Make = (X: {type t}) => { type record = {@as("prénom") name: X.t}}module Applied = Make({ type t = string})
rescript
Before the field is named "prénom" when the interface is read back
After
module Applied: {module Applied: { type record = {@as("pr\195\169nom") name: string} type record = {@as("prénom") name: string}}}