mirror of
https://github.com/vercel-labs/scriptc.git
synced 2026-10-27 06:43:19 +08:00
Relational string operators (`<`, `<=`, `>`, `>=`) compared the UTF-8
bytes, which is code-point order. Node compares UTF-16 code units, so the
results differed for characters above U+FFFF against U+E000..U+FFFF and
for lone surrogates against surrogate pairs. The default `sort()`
comparator, `util.inspect` with `sorted: true` and dynamic comparisons
already used UTF-16 order; the default comparator of a dynamic array's
`sort()` did not.
Typed comparisons and the dynamic array sort now use `scr_str_cmp_u16`,
and the IR's `strCmp` node no longer has a `utf16` flag. The two orders
agree unless both of the first differing bytes are at least 0xED, so:
- the inline wrapper decides differing first words, or last words of
equal lengths up to 16 bytes, in byte order when neither word has a
byte of at least 0xED (a SWAR test). Other differing words, and the
first bytes of shorter strings, decide by their first differing byte:
in byte order when one of the two is below 0xED, and by plane when both
are lead bytes from 0xEE to 0xF4 (a supplementary character orders
below U+E000..U+FFFF);
- otherwise a proven-ASCII string on either side compares with `memcmp`
(`scr_str_cmp`), and other pairs call `scr_str_cmp_u16_bytes`. It finds
the first differing byte with words up to byte 32, then with 32-byte
SSE2 or NEON blocks where the target has them. The call is marked as
only reading its arguments, so repeated comparisons of one pair merge.
- `scr_str_cmp_u16` itself takes the same `memcmp` path for proven-ASCII
strings.
The native compiler sorts record fields with `<` and checks the order
with `sort()`, so it reported SC9001 for 5888-inspect-sorted.ts, whose
object has the keys "\u{1F600}" and "\uffff". 5888 runs in the
native-frontend self-host check. Adds corpus 6023.