Summary
Perry has runtime helpers for String.fromCharCode and String.fromCodePoint, and HIR already expands multi-argument valid calls. The remaining edge semantics diverge from Node:
String.fromCharCode should convert each argument with ToUint16, so negative / out-of-range values wrap modulo 65536 instead of returning "".
String.fromCodePoint should throw RangeError for invalid code points, negative values, and non-integers instead of returning "".
- Zero-argument calls should return
"".
Node behavior
Local Node v25.9.0 probe:
fromCharCode:[65,66,67]="ABC":41+42+43
fromCharCode:[128512]="":f600
fromCharCode:[-1]="�":ffff
fromCharCode:[65.9]="A":41
fromCharCode:[]="":
fromCodePoint:[128512,65]="😀A":1f600+41
fromCodePoint:[1114112]=RangeError:Invalid code point 1114112
fromCodePoint:[-1]=RangeError:Invalid code point -1
fromCodePoint:[3.14]=RangeError:Invalid code point 3.14
fromCodePoint:[]="":
Probe shape:
String.fromCharCode(65, 66, 67)
String.fromCharCode(0x1F600)
String.fromCharCode(-1)
String.fromCharCode(65.9)
String.fromCharCode()
String.fromCodePoint(0x1F600, 65)
String.fromCodePoint(0x110000)
String.fromCodePoint(-1)
String.fromCodePoint(3.14)
String.fromCodePoint()
Perry evidence
crates/perry-hir/src/lower/expr_call/module_static.rs handles one-or-more String.fromCharCode(...) / String.fromCodePoint(...) arguments by lowering each argument to a single-code helper and concatenating multi-argument calls.
crates/perry-codegen/src/expr/string_regex_proc.rs lowers both helpers by converting the argument with raw fptosi(DOUBLE -> I32) before calling the runtime helper.
crates/perry-runtime/src/string/char_ops.rs::js_string_from_char_code() returns an empty string for values outside 0..=0xFFFF instead of applying ToUint16 wrapping.
crates/perry-runtime/src/string/char_ops.rs::js_string_from_code_point() returns an empty string for values outside 0..=0x10FFFF / invalid scalar values instead of throwing RangeError.
test-files/test_gap_string_methods.ts covers valid multi-argument fromCodePoint and zero, but not invalid code points or fromCharCode wrapping.
Duplicate check
Searched issues and PRs for:
String.fromCharCode variadic
String.fromCodePoint RangeError
fromCharCode fromCodePoint
- PR search for
fromCharCode OR fromCodePoint OR String.fromCodePoint
No focused tracker showed up. PR #1043 was a WASM-specific fix for String.fromCharCode returning undefined, not these runtime edge semantics.
Expected fix shape
- Implement
ToUint16 semantics for String.fromCharCode, including negative and out-of-range wrapping.
- Make
String.fromCodePoint validate integer code points and throw RangeError for negative, non-integer, and > 0x10FFFF values.
- Avoid raw
fptosi for non-finite / non-integer values where JS coercion or validation must be observable.
- Ensure zero-argument static calls return
"".
- Add regression coverage for wrapping, invalid code points, non-integers, and zero-argument calls.
Summary
Perry has runtime helpers for
String.fromCharCodeandString.fromCodePoint, and HIR already expands multi-argument valid calls. The remaining edge semantics diverge from Node:String.fromCharCodeshould convert each argument withToUint16, so negative / out-of-range values wrap modulo 65536 instead of returning"".String.fromCodePointshould throwRangeErrorfor invalid code points, negative values, and non-integers instead of returning""."".Node behavior
Local Node v25.9.0 probe:
Probe shape:
Perry evidence
crates/perry-hir/src/lower/expr_call/module_static.rshandles one-or-moreString.fromCharCode(...)/String.fromCodePoint(...)arguments by lowering each argument to a single-code helper and concatenating multi-argument calls.crates/perry-codegen/src/expr/string_regex_proc.rslowers both helpers by converting the argument with rawfptosi(DOUBLE -> I32)before calling the runtime helper.crates/perry-runtime/src/string/char_ops.rs::js_string_from_char_code()returns an empty string for values outside0..=0xFFFFinstead of applyingToUint16wrapping.crates/perry-runtime/src/string/char_ops.rs::js_string_from_code_point()returns an empty string for values outside0..=0x10FFFF/ invalid scalar values instead of throwingRangeError.test-files/test_gap_string_methods.tscovers valid multi-argumentfromCodePointand zero, but not invalid code points orfromCharCodewrapping.Duplicate check
Searched issues and PRs for:
String.fromCharCode variadicString.fromCodePoint RangeErrorfromCharCode fromCodePointfromCharCode OR fromCodePoint OR String.fromCodePointNo focused tracker showed up. PR
#1043was a WASM-specific fix forString.fromCharCodereturning undefined, not these runtime edge semantics.Expected fix shape
ToUint16semantics forString.fromCharCode, including negative and out-of-range wrapping.String.fromCodePointvalidate integer code points and throwRangeErrorfor negative, non-integer, and> 0x10FFFFvalues.fptosifor non-finite / non-integer values where JS coercion or validation must be observable."".