mirror of
https://github.com/vercel-labs/scriptc.git
synced 2026-10-20 05:40:17 +08:00
- new Intl.NumberFormat("en-US").format(x), the callable spelling, and x.toLocaleString("en-US") lower to one runtime formatter with default options: decimal notation, 0-3 fraction digits rounded half-up on the SHORTEST round-tripping decimal (ICU's rounding input, probed against Node — format(1.0005) is "1.001" though toFixed(3) answers "1.000"; 1e23 prints the shortest form's zeros, not the exact expansion), "," grouping, "∞"/"NaN" texts, and "-0" for negatives rounding to zero. The en-US/latn symbols are the whole embedded locale surface — no ICU is linked.
- The Ryū digit core factors out of scr_f64_to_str as scr_f64_digits (same bytes; the 1M-double oracle gate stays green) and feeds the formatter; a 30,000-double ad-hoc fuzz across magnitude regimes matched Node byte-for-byte on both backends.
- Every unlowered Intl form fences by NAME with its own reason: the environment-default locale a compiled binary cannot carry (no-locale forms), other locales and the rest of the namespace (DurationFormat, DateTimeFormat, PluralRules, getCanonicalLocales — ICU data the binary does not embed; Node 24's DurationFormat additionally throws V8-internal Temporal errors with embedded source paths, so byte parity there is a version-dependent landmine), options bags, formatter values (the composed form is the lowered shape), and non-number format arguments.
- Differential fixture 2562 pins the rounding discriminators, grouping, ±0/NaN/∞, tiny and huge edges, and both spellings byte-identically vs Node on both backends; the new intl diagnostics fixture pins every named fence, and the Intl hints across the identifier/member/type chokepoints now teach what lowers.
26 lines
1.3 KiB
TypeScript
26 lines
1.3 KiB
TypeScript
// The Intl surface. What lowers: the COMPOSED en-US NumberFormat forms
|
|
// with default options — new Intl.NumberFormat("en-US").format(x) and
|
|
// x.toLocaleString("en-US"). Everything else fences by NAME: the
|
|
// environment-default locale a compiled binary cannot carry, other
|
|
// locales (ICU data the binary does not embed), options bags, formatter
|
|
// VALUES, and the rest of the Intl namespace (DurationFormat,
|
|
// DateTimeFormat, PluralRules, getCanonicalLocales).
|
|
|
|
// The unlowered NumberFormat variants, each with its own reason.
|
|
const noLocale = new Intl.NumberFormat().format(1234.5);
|
|
const otherLocale = new Intl.NumberFormat("de-DE").format(1234.5);
|
|
const withOptions = new Intl.NumberFormat("en-US", { maximumFractionDigits: 2 }).format(1234.5);
|
|
const hoisted = new Intl.NumberFormat("en-US");
|
|
const viaValue = hoisted.format(1234.5);
|
|
|
|
// toLocaleString's unlowered variants.
|
|
const envDefault = (1234.5).toLocaleString();
|
|
const german = (1234.5).toLocaleString("de-DE");
|
|
const grouped = (1234.5).toLocaleString("en-US", { useGrouping: false });
|
|
|
|
// The rest of Intl keeps the ICU story.
|
|
const when = new Intl.DateTimeFormat("en-US").format();
|
|
const dur = new Intl.DurationFormat("en-US").format({ hours: 1, minutes: 23 });
|
|
const rule = new Intl.PluralRules("en-US").select(1);
|
|
const canon = Intl.getCanonicalLocales("en-us");
|