Summary
Intl.Segmenter is not implemented — Intl.Segmenter is undefined, so new Intl.Segmenter() throws TypeError: is not a constructor. Perry ships Intl.NumberFormat, Intl.DateTimeFormat, and Intl.Collator (crates/perry-runtime/src/intl.rs) but not Segmenter.
This is the next ink wall after #4873. With the MessageChannel fix in (#4875), React/scheduler init cleanly, but importing ink still crashes at module-init — traced to its ANSI-width deps:
string-width/index.js:16 → const segmenter = new Intl.Segmenter();
wrap-ansi/index.js:31 → const segmenter = new Intl.Segmenter();
Both run at module top-level, so merely importing string-width / wrap-ansi (and therefore ink, react-three-fiber-style CLIs, and most modern width-aware CLI code) dies before any user code. Intl.Segmenter has been the default grapheme-segmentation primitive in string-width@7+ / wrap-ansi@9+ since they dropped the old codepoint-counting path.
Repro
// seg.ts
console.log(typeof Intl.Segmenter); // Perry: "undefined" | Node: "function"
const s = new Intl.Segmenter('en', { granularity: 'grapheme' });
console.log([...s.segment('a👨👩👧b')].map(x => x.segment));
$ perry compile seg.ts -o seg && ./seg
TypeError: is not a constructor
Expected (Node)
function
[ 'a', '👨👩👧', 'b' ]
new Intl.Segmenter(locales?, { granularity: 'grapheme' | 'word' | 'sentence' }) → object with .segment(str) returning an iterable of segment data { segment, index, input, isWordLike? }, plus .resolvedOptions().
Scope / suggested impl
granularity: 'grapheme' is what string-width / wrap-ansi actually use (extended grapheme clusters — emoji ZWJ sequences, combining marks, regional-indicator flags). That's the must-have for ink. word / sentence can follow.
- Rust side: the
unicode-segmentation crate gives grapheme + word iteration directly; a minimal Segmenter over it covers the ink path. Sentence granularity would need a small extra rule set.
- Wire alongside the existing
Intl constructors: crates/perry-runtime/src/intl.rs, the globalThis/Intl tables in crates/perry-runtime/src/object/global_this*.rs, and the codegen builtin/new allowlist in crates/perry-codegen/src/expr/helpers.rs (where MessageChannel et al. live).
Impact
Related
Summary
Intl.Segmenteris not implemented —Intl.Segmenterisundefined, sonew Intl.Segmenter()throwsTypeError: is not a constructor. Perry shipsIntl.NumberFormat,Intl.DateTimeFormat, andIntl.Collator(crates/perry-runtime/src/intl.rs) but notSegmenter.This is the next ink wall after #4873. With the MessageChannel fix in (#4875), React/scheduler init cleanly, but importing
inkstill crashes at module-init — traced to its ANSI-width deps:string-width/index.js:16→const segmenter = new Intl.Segmenter();wrap-ansi/index.js:31→const segmenter = new Intl.Segmenter();Both run at module top-level, so merely importing
string-width/wrap-ansi(and thereforeink, react-three-fiber-style CLIs, and most modern width-aware CLI code) dies before any user code.Intl.Segmenterhas been the default grapheme-segmentation primitive instring-width@7+/wrap-ansi@9+since they dropped the old codepoint-counting path.Repro
Expected (Node)
new Intl.Segmenter(locales?, { granularity: 'grapheme' | 'word' | 'sentence' })→ object with.segment(str)returning an iterable of segment data{ segment, index, input, isWordLike? }, plus.resolvedOptions().Scope / suggested impl
granularity: 'grapheme'is whatstring-width/wrap-ansiactually use (extended grapheme clusters — emoji ZWJ sequences, combining marks, regional-indicator flags). That's the must-have for ink.word/sentencecan follow.unicode-segmentationcrate gives grapheme + word iteration directly; a minimalSegmenterover it covers the ink path. Sentence granularity would need a small extra rule set.Intlconstructors:crates/perry-runtime/src/intl.rs, theglobalThis/Intl tables incrates/perry-runtime/src/object/global_this*.rs, and the codegen builtin/new allowlist incrates/perry-codegen/src/expr/helpers.rs(whereMessageChannelet al. live).Impact
string-width,wrap-ansi,slice-ansi/cli-truncate(transitively) — and thus ink end-to-end (Compileink(React-based TUI framework) end-to-end viaperry.compilePackages#348). After this, ink's next gate is yoga-layout's WASM runtime (the documented out-of-scope rock).string-width.Related
ink(React-based TUI framework) end-to-end viaperry.compilePackages#348 (ink end-to-end smoke test — where this surfaced)new MessageChannel()global constructor unlinked/non-constructible — routes to stdlib symbol, breaks React scheduler init #4873 / fix(hir): globalnew MessageChannel()routes to always-linked runtime constructor (#4873) #4875 (previous ink wall:new MessageChannel())