Repository navigation
Fix Messagepipe correctness and prepare built-in formatting paths - #2
Merged
Marcisbee merged 7 commits intoOct 28, 2026
Merged
Conversation
Marcisbee
marked this pull request as ready for review
October 27, 2026 22:33
Marcisbee
deleted the
kode/3EkbtGt5-improve-messagepipe-performance-and-corr
branch
October 28, 2026 16:07
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
MessagePipe previously mixed transformers between instances and repeatedly constructed Intl formatters. This change isolates message caches, fixes quoted delimiters, selection/plural behavior, Intl options, relative-time units, and the ESM package entry point.
Built-in pipes prepare literal options once and reuse preparation for up to 16 dynamic primitive-option combinations per pipe. Dynamic arguments still evaluate on every call. Object-valued options retain the generic path. Each prepared number/date/time/plural variant retains at most 100 scalar results, clearing and bypassing its result cache after 100 consecutive misses. Mutable inputs, undefined, and signed zero bypass result caching.
Plural fragments and select choices are prepared once; single-marker plural text uses direct concatenation for strings and numbers. Transformer lookup happens before argument evaluation, preserving JavaScript call order even when getters replace a transformer. Custom transformers receive fresh options, and already-compiled messages observe replacement functions. Invalid Intl options still throw during rendering.
README benchmarks compare equivalent outputs against development-only @messageformat/core 3.4.1. Three independent processes per mode, seven samples each, one million calls per sample after warmup; median across 21 samples. Linux x64/WSL, Ryzen 9 9950X, Node 22.23.2, ICU 78.2, en-GB/UTC:
WowHello {planet}Hello {planet}Interpolation remains effectively tied; this does not establish strict superiority for every message. Repeated-value gains include result caching. The varied mode covers 1,000 interpolation inputs as well as Intl inputs, exceeding result-cache capacity and exercising bypass. Plain text remains a constant return and interpolation a direct concatenation; neither caches rendered strings. Dynamic digits use pipe arguments in MessagePipe and a select between compiled number skeletons in MessageFormat. Both modes validate outputs and alternate measurement order. Reproduce with npm run benchmark and npm run benchmark -- --varied.
A separate paired before/after check for dynamic digits, using seven samples of 100,000 calls, improved median elapsed time from 105.59 ms to 10.76 ms versus the preceding implementation (9.8×).
Validation: 67 tests, lint, builds, declarations, and CommonJS/ESM imports pass. The getter/transformer ordering regression failed before repair. Coverage includes changing options, mutable option coercion, undefined/null selections, replacement transformers, signed zero, raw output, and native Intl comparisons in four locales. Fetched origin/main; no newer changes required incorporation.
Tradeoffs: preparation adds compile-time work. Each dynamic pipe can retain up to 16 variants with 100 results each. The ESM bundle is approximately 6.4 KB minified, versus 2.8 KB at the original baseline. Cold calls, mutable objects, and other messages/runtimes have different costs. Calendar relative-time units use documented fixed durations. Templates remain trusted expressions compiled with Function. The release lint command and package import checks are fixed; no publication or runtime dependencies are included.