Skip to content

fix(intl): repair RelativeTimeFormat output#692

Merged
frostney merged 3 commits into
mainfrom
t3code/implement-issue-599
May 30, 2026
Merged

fix(intl): repair RelativeTimeFormat output#692
frostney merged 3 commits into
mainfrom
t3code/implement-issue-599

Conversation

@frostney
Copy link
Copy Markdown
Owner

Summary

  • Repair Intl.RelativeTimeFormat.prototype.format and formatToParts for localized numeric relative output, including numeric: "auto", plural-sensitive units, grouped number parts, negative zero, and non-finite value rejection.
  • Thread RelativeTimeFormat style through the ICU binding, correct ICU relative quarter/year unit constants, and add an ICU plural/number-format backed repair path for the host ICU relative formatter behavior.
  • Tighten RelativeTimeFormat option validation and resolved numbering-system reporting/order.
  • Closes Intl: RelativeTimeFormat produces wrong output and empty formatToParts #599.

Testing

  • Verified no regressions and confirmed the new feature or bugfix in end-to-end JavaScript/TypeScript tests
    • ./build/GocciaTestRunner tests/built-ins/Intl/RelativeTimeFormat --no-progress --exit-on-first-failure
    • bun scripts/run_test262_suite.ts --suite-dir /tmp/goccia-test262-pinned --categories intl402 --filter 'intl402/RelativeTimeFormat/prototype/format/*' --mode bytecode --jobs 1 --output=/tmp/rtf-format.json
    • bun scripts/run_test262_suite.ts --suite-dir /tmp/goccia-test262-pinned --categories intl402 --filter 'intl402/RelativeTimeFormat/prototype/formatToParts/*' --mode bytecode --jobs 1 --output=/tmp/rtf-format-parts.json
    • bun scripts/run_test262_suite.ts --suite-dir /tmp/goccia-test262-pinned --categories intl402 --filter 'intl402/RelativeTimeFormat/prototype/resolvedOptions/*' --mode bytecode --jobs 1 --output=/tmp/rtf-resolved.json
    • bun scripts/run_test262_suite.ts --suite-dir /tmp/goccia-test262-pinned --categories intl402 --filter 'intl402/RelativeTimeFormat/**' --mode bytecode --jobs 1 --output=/tmp/rtf-all.json now passes 67/80; remaining failures are constructor/prototype/locale support outside this formatting fix.
    • ./build.pas testrunner && ./build/GocciaTestRunner tests was run; it still reports the existing FFI fixture load failures for ./fixtures/ffi/libfixture.dylib.
  • Updated documentation
    • No docs update: the public API already documents Intl.RelativeTimeFormat; this fixes conformance of existing behavior.
  • Optional: Verified no regressions and confirmed the new feature or bugfix in native Pascal tests (if AST, scope, evaluator, or value types changed)
  • Optional: Verified no benchmark regressions or confirmed benchmark coverage for the change

- thread RelativeTimeFormat style through ICU bindings
- repair en/pl numeric relative output using ICU plural and number formatting
- validate RelativeTimeFormat options and resolved numbering system order
- add focused RelativeTimeFormat format regressions

Closes #599
@vercel
Copy link
Copy Markdown

vercel Bot commented May 30, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
gocciascript-homepage Ignored Ignored Preview May 30, 2026 11:45am

Request Review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 30, 2026

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: c5d9844a-f237-49c1-a364-432253f33757

📥 Commits

Reviewing files that changed from the base of the PR and between 023b68d and 699ba93.

📒 Files selected for processing (3)
  • source/units/Goccia.Values.IntlRelativeTimeFormat.pas
  • tests/built-ins/Intl/RelativeTimeFormat/prototype/format.js
  • tests/built-ins/Intl/RelativeTimeFormat/prototype/formatToParts.js
🚧 Files skipped from review as they are similar to previous changes (2)
  • tests/built-ins/Intl/RelativeTimeFormat/prototype/formatToParts.js
  • source/units/Goccia.Values.IntlRelativeTimeFormat.pas

📝 Walkthrough

Walkthrough

Adds a narrow relative-time style, threads style into ICU relative-time formatter calls, appends numbering-system tokens to number skeletons, adds locale helpers to parse -u- extensions, reconciles numberingSystem options in NumberFormat and RelativeTimeFormat, refactors RelativeTimeFormat internals and precedence, and expands tests.

Changes

Relative-time style and numbering-system support

Layer / File(s) Summary
Type system and contract updates
source/shared/IntlTypes.pas, source/shared/IntlICU.pas
TIntlRelativeTimeStyle enum extended with irtsNarrow. Added AStyle: TIntlRelativeTimeStyle parameter to TryICUFormatRelativeTime and TryICUFormatRelativeTimeToParts.
ICU relative-time backend
source/shared/IntlICU.pas
Swaps UDAT_RELATIVE_YEARS and UDAT_RELATIVE_QUARTERS constants, adds RelativeTimeStyleToICU helper, updates RelativeTimeUnitToICU, and passes chosen style into ICU formatter open calls.
Number formatting skeleton with numbering system
source/shared/IntlICU.pas
BuildNumberSkeleton appends numbering-system/<id> token when NumberingSystem option is set.
Locale helper utilities for Unicode extensions
source/units/Goccia.Intl.Helpers.pas
Adds LocaleWithoutUnicodeExtension, TryGetUnicodeLocaleExtensionKeyword, and IsSupportedNumberingSystem to parse/strip -u- extensions and validate numbering-system subtags.
NumberFormat numbering-system reconciliation
source/units/Goccia.Values.IntlNumberFormat.pas
Adds LocaleNumberingSystem and logic in constructor to validate explicit numberingSystem, reconcile with locale nu extension, and strip unsupported/mismatched extensions.
RelativeTimeFormat implementation with helpers and option handling
source/units/Goccia.Values.IntlRelativeTimeFormat.pas
Adds many internal helpers (style/numeric mapping, option validation, nu handling), TryReplaceFormattedNumber, rewrites constructor option parsing to reconcile numbering-system and locale, implements locale-pattern formatters (en/pl), refactors format/formatToParts precedence (auto → locale-pattern → ICU → CLDR), and updates resolvedOptions to include numberingSystem.
Test coverage for new features
tests/built-ins/Intl/NumberFormat/prototype/format.js, tests/built-ins/Intl/RelativeTimeFormat/prototype/format.js, tests/built-ins/Intl/RelativeTimeFormat/prototype/formatToParts.js
Adds NumberFormat numberingSystem tests and comprehensive RelativeTimeFormat.format and formatToParts tests covering numeric modes, auto literals, style variants, and numbering-system digit rendering.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~75 minutes

Possibly related issues

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title 'fix(intl): repair RelativeTimeFormat output' accurately and concisely summarizes the main change—repairing RelativeTimeFormat's format and formatToParts methods. It is specific and directly related to the changeset's primary objective.
Description check ✅ Passed The PR description comprehensively covers all required sections: it describes the changes in detail, links the related issue (#599), and includes a thorough Testing section with specific test commands run and results. All key modifications are documented.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 30, 2026

Suite Timing

Test Runner (interpreted: 9,850 passed; bytecode: 9,850 passed)
Metric Interpreted Bytecode
Total 9850 9850
Passed 9850 ✅ 9850 ✅
Workers 4 4
Test Duration 3.71s 3.71s
Lex (cumulative) 468.4ms 441.8ms
Parse (cumulative) 326.9ms 341.6ms
Compile (cumulative) 645.7ms
Execute (cumulative) 4.89s 4.69s
Engine Total (cumulative) 5.69s 6.12s
Lex (avg/worker) 117.1ms 110.4ms
Parse (avg/worker) 81.7ms 85.4ms
Compile (avg/worker) 161.4ms
Execute (avg/worker) 1.22s 1.17s
Engine Total (avg/worker) 1.42s 1.53s

Memory

GC rows aggregate the main thread plus all worker thread-local GCs. Test runner worker shutdown frees thread-local heaps in bulk; that shutdown reclamation is not counted as GC collections or collected objects.

Metric Interpreted Bytecode
GC Live 286.95 MiB 279.38 MiB
GC Peak Live 286.96 MiB 279.39 MiB
GC Allocated During Run 291.49 MiB 283.91 MiB
GC Limit 7.81 GiB 7.81 GiB
GC Collections 1 1
GC Collected Objects 87 87
Heap Start Allocated 160.5 KiB 160.5 KiB
Heap End Allocated 1.54 MiB 1.54 MiB
Heap Delta Allocated 1.38 MiB 1.38 MiB
Heap Delta Free 794.5 KiB 794.5 KiB
Benchmarks (interpreted: 407; bytecode: 407)
Metric Interpreted Bytecode
Total 407 407
Workers 4 4
Duration 2.48min 2.48min

Memory

GC rows aggregate the main thread plus all worker thread-local GCs. Benchmark runner performs explicit between-file collections, so collection and collected-object counts can be much higher than the test runner.

Metric Interpreted Bytecode
GC Live 3.97 MiB 3.97 MiB
GC Peak Live 137.27 MiB 140.96 MiB
GC Allocated During Run 16.73 GiB 18.11 GiB
GC Limit 7.81 GiB 7.81 GiB
GC Collections 2,829 2,701
GC Collected Objects 263,792,539 408,137,555
Heap Start Allocated 1.27 MiB 1.27 MiB
Heap End Allocated 1.27 MiB 1.27 MiB
Heap Delta Allocated 128 B 128 B

Measured on ubuntu-latest x64.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 30, 2026

Benchmark Results

407 benchmarks

Interpreted: 🟢 341 improved · 🔴 21 regressed · 45 unchanged · avg +7.9%
Bytecode: 🟢 407 improved · avg +88.9%

arraybuffer.js — Interp: 🟢 10, 🔴 1, 3 unch. · avg +7.3% · Bytecode: 🟢 14 · avg +98.6%
Benchmark Interpreted Δ Bytecode Δ
create ArrayBuffer(0) 154,524 ops/sec [132,187..155,868] → 170,909 ops/sec [133,294..172,866] ~ overlap (+10.6%) 178,726 ops/sec [176,342..181,435] → 343,062 ops/sec [277,273..366,443] 🟢 +91.9%
create ArrayBuffer(64) 150,421 ops/sec [146,878..152,268] → 161,876 ops/sec [160,286..165,179] 🟢 +7.6% 169,728 ops/sec [167,735..172,670] → 349,628 ops/sec [337,987..353,196] 🟢 +106.0%
create ArrayBuffer(1024) 131,470 ops/sec [130,513..132,876] → 138,571 ops/sec [136,218..140,974] 🟢 +5.4% 148,107 ops/sec [145,769..149,457] → 292,578 ops/sec [291,831..293,120] 🟢 +97.5%
create ArrayBuffer(8192) 77,992 ops/sec [76,747..78,694] → 73,516 ops/sec [71,534..74,498] 🔴 -5.7% 79,096 ops/sec [78,838..79,330] → 144,567 ops/sec [138,362..146,085] 🟢 +82.8%
slice full buffer (64 bytes) 184,321 ops/sec [182,923..186,050] → 210,676 ops/sec [208,990..214,077] 🟢 +14.3% 212,298 ops/sec [208,517..212,720] → 436,700 ops/sec [419,321..440,919] 🟢 +105.7%
slice half buffer (512 of 1024 bytes) 165,846 ops/sec [148,514..171,740] → 183,793 ops/sec [168,844..194,095] ~ overlap (+10.8%) 188,102 ops/sec [185,816..188,582] → 371,408 ops/sec [365,126..374,858] 🟢 +97.5%
slice with negative indices 154,169 ops/sec [150,402..156,737] → 167,323 ops/sec [165,319..172,527] 🟢 +8.5% 209,654 ops/sec [209,093..212,253] → 383,371 ops/sec [376,933..385,087] 🟢 +82.9%
slice empty range 177,556 ops/sec [175,061..180,801] → 191,726 ops/sec [190,183..195,237] 🟢 +8.0% 207,397 ops/sec [202,831..209,385] → 398,908 ops/sec [395,294..405,894] 🟢 +92.3%
byteLength access 400,427 ops/sec [391,468..404,227] → 426,191 ops/sec [416,260..436,044] 🟢 +6.4% 399,557 ops/sec [395,397..405,436] → 842,286 ops/sec [837,239..853,208] 🟢 +110.8%
Symbol.toStringTag access 321,683 ops/sec [316,825..332,669] → 340,442 ops/sec [329,932..344,833] ~ overlap (+5.8%) 294,811 ops/sec [288,083..295,548] → 613,233 ops/sec [604,998..623,529] 🟢 +108.0%
ArrayBuffer.isView 238,777 ops/sec [237,521..239,845] → 267,764 ops/sec [257,758..268,981] 🟢 +12.1% 269,302 ops/sec [265,546..273,852] → 557,269 ops/sec [550,593..570,575] 🟢 +106.9%
clone ArrayBuffer(64) 162,900 ops/sec [159,185..163,107] → 174,872 ops/sec [172,441..177,982] 🟢 +7.3% 194,531 ops/sec [193,058..194,604] → 389,637 ops/sec [387,528..393,161] 🟢 +100.3%
clone ArrayBuffer(1024) 140,422 ops/sec [138,581..141,146] → 149,495 ops/sec [148,634..151,564] 🟢 +6.5% 162,534 ops/sec [162,154..162,817] → 322,787 ops/sec [308,184..325,566] 🟢 +98.6%
clone ArrayBuffer inside object 114,525 ops/sec [114,202..115,764] → 118,944 ops/sec [118,398..119,616] 🟢 +3.9% 123,501 ops/sec [121,872..124,297] → 246,491 ops/sec [244,229..247,904] 🟢 +99.6%
arrays.js — Interp: 🟢 16, 3 unch. · avg +6.6% · Bytecode: 🟢 19 · avg +88.3%
Benchmark Interpreted Δ Bytecode Δ
Array.from length 100 3,129 ops/sec [2,643..3,181] → 3,114 ops/sec [2,750..3,304] ~ overlap (-0.5%) 4,061 ops/sec [3,699..4,119] → 7,608 ops/sec [6,384..8,668] 🟢 +87.3%
Array.from 10 elements 84,229 ops/sec [83,216..86,413] → 92,064 ops/sec [90,652..92,985] 🟢 +9.3% 86,978 ops/sec [86,145..87,447] → 175,427 ops/sec [170,537..178,781] 🟢 +101.7%
Array.of 10 elements 103,854 ops/sec [103,015..105,306] → 117,514 ops/sec [105,888..118,389] 🟢 +13.2% 117,190 ops/sec [116,029..118,341] → 239,147 ops/sec [229,252..240,437] 🟢 +104.1%
spread into new array 127,167 ops/sec [121,703..130,177] → 138,279 ops/sec [137,071..140,368] 🟢 +8.7% 70,734 ops/sec [69,939..70,880] → 138,100 ops/sec [131,378..141,441] 🟢 +95.2%
map over 50 elements 5,082 ops/sec [5,008..5,092] → 5,311 ops/sec [5,191..5,499] 🟢 +4.5% 6,953 ops/sec [6,876..7,049] → 13,798 ops/sec [13,608..14,085] 🟢 +98.4%
filter over 50 elements 4,954 ops/sec [4,869..5,058] → 5,261 ops/sec [5,207..5,325] 🟢 +6.2% 6,947 ops/sec [6,750..7,070] → 12,964 ops/sec [12,352..13,061] 🟢 +86.6%
reduce sum 50 elements 5,205 ops/sec [5,076..5,280] → 5,538 ops/sec [5,392..5,665] 🟢 +6.4% 6,622 ops/sec [6,586..6,703] → 12,257 ops/sec [11,806..12,370] 🟢 +85.1%
forEach over 50 elements 4,909 ops/sec [4,856..4,971] → 5,172 ops/sec [5,122..5,416] 🟢 +5.4% 7,959 ops/sec [6,825..8,122] → 13,653 ops/sec [13,584..13,700] 🟢 +71.5%
find in 50 elements 7,006 ops/sec [6,905..7,095] → 7,417 ops/sec [7,316..7,564] 🟢 +5.9% 10,256 ops/sec [10,207..10,457] → 19,081 ops/sec [18,836..19,167] 🟢 +86.0%
sort 20 elements 2,860 ops/sec [2,840..2,898] → 2,933 ops/sec [2,867..2,988] ~ overlap (+2.5%) 4,579 ops/sec [4,564..4,624] → 8,208 ops/sec [8,096..8,213] 🟢 +79.3%
flat nested array 48,301 ops/sec [46,528..49,543] → 49,909 ops/sec [49,435..50,104] ~ overlap (+3.3%) 49,843 ops/sec [49,180..50,532] → 93,370 ops/sec [92,785..93,918] 🟢 +87.3%
flatMap 23,542 ops/sec [23,419..23,617] → 24,362 ops/sec [24,210..24,708] 🟢 +3.5% 27,615 ops/sec [27,350..27,736] → 51,288 ops/sec [50,459..51,692] 🟢 +85.7%
map inside map (5x5) 5,983 ops/sec [4,807..6,115] → 6,355 ops/sec [6,210..6,414] 🟢 +6.2% 7,491 ops/sec [7,453..7,534] → 13,810 ops/sec [13,530..13,941] 🟢 +84.3%
filter inside map (5x10) 3,906 ops/sec [3,819..4,015] → 4,258 ops/sec [4,172..4,383] 🟢 +9.0% 5,420 ops/sec [5,349..5,483] → 9,525 ops/sec [9,403..9,717] 🟢 +75.7%
reduce inside map (5x10) 4,234 ops/sec [4,171..4,308] → 4,651 ops/sec [4,589..4,688] 🟢 +9.9% 5,340 ops/sec [5,312..5,404] → 10,152 ops/sec [10,046..10,192] 🟢 +90.1%
forEach inside forEach (5x10) 4,034 ops/sec [4,021..4,046] → 4,423 ops/sec [4,384..4,525] 🟢 +9.6% 6,024 ops/sec [5,968..6,077] → 11,589 ops/sec [11,548..11,729] 🟢 +92.4%
find inside some (10x10) 3,138 ops/sec [3,088..3,161] → 3,376 ops/sec [3,337..3,411] 🟢 +7.6% 4,284 ops/sec [4,190..4,314] → 8,234 ops/sec [8,114..8,318] 🟢 +92.2%
map+filter chain nested (5x20) 1,158 ops/sec [1,153..1,164] → 1,258 ops/sec [1,254..1,262] 🟢 +8.7% 1,614 ops/sec [1,588..1,642] → 3,055 ops/sec [2,983..3,103] 🟢 +89.3%
reduce flatten (10x5) 13,665 ops/sec [13,486..14,052] → 14,464 ops/sec [14,239..14,697] 🟢 +5.9% 6,378 ops/sec [6,336..6,403] → 11,789 ops/sec [11,419..12,111] 🟢 +84.8%
async-await.js — Interp: 🟢 5, 1 unch. · avg +8.6% · Bytecode: 🟢 6 · avg +94.8%
Benchmark Interpreted Δ Bytecode Δ
single await 135,020 ops/sec [114,759..144,160] → 152,880 ops/sec [123,646..160,079] ~ overlap (+13.2%) 140,482 ops/sec [95,235..144,095] → 277,725 ops/sec [255,317..281,872] 🟢 +97.7%
multiple awaits 67,495 ops/sec [66,855..68,446] → 74,439 ops/sec [71,737..75,153] 🟢 +10.3% 63,726 ops/sec [63,159..64,154] → 125,438 ops/sec [119,727..128,097] 🟢 +96.8%
await non-Promise value 270,469 ops/sec [268,561..272,379] → 295,880 ops/sec [292,853..298,200] 🟢 +9.4% 340,743 ops/sec [332,316..344,828] → 658,909 ops/sec [653,242..680,076] 🟢 +93.4%
await with try/catch 109,890 ops/sec [103,957..111,777] → 117,464 ops/sec [116,783..118,403] 🟢 +6.9% 139,943 ops/sec [137,776..141,796] → 271,199 ops/sec [263,457..276,448] 🟢 +93.8%
await Promise.all 22,487 ops/sec [22,052..22,983] → 24,238 ops/sec [23,306..24,883] 🟢 +7.8% 21,188 ops/sec [20,971..21,373] → 40,477 ops/sec [33,818..41,865] 🟢 +91.0%
nested async function call 76,700 ops/sec [61,819..77,748] → 79,872 ops/sec [78,603..80,646] 🟢 +4.1% 87,116 ops/sec [85,954..87,281] → 170,728 ops/sec [163,855..176,573] 🟢 +96.0%
async-generators.js — Interp: 🟢 1, 1 unch. · avg +9.9% · Bytecode: 🟢 2 · avg +98.5%
Benchmark Interpreted Δ Bytecode Δ
for-await-of over async generator 2,137 ops/sec [1,685..2,154] → 2,323 ops/sec [1,939..2,372] ~ overlap (+8.7%) 2,328 ops/sec [2,293..2,359] → 4,486 ops/sec [4,372..4,583] 🟢 +92.7%
async generator with await in body 19,663 ops/sec [19,318..19,862] → 21,839 ops/sec [21,731..21,917] 🟢 +11.1% 19,949 ops/sec [19,629..20,070] → 40,755 ops/sec [40,164..40,961] 🟢 +104.3%
base64.js — Interp: 🟢 3, 🔴 7 · avg -0.1% · Bytecode: 🟢 10 · avg +111.9%
Benchmark Interpreted Δ Bytecode Δ
short ASCII (13 chars) 3,090 ops/sec [3,083..3,112] → 3,442 ops/sec [3,379..3,456] 🟢 +11.4% 2,857 ops/sec [2,803..2,881] → 6,195 ops/sec [6,129..6,262] 🟢 +116.9%
medium ASCII (450 chars) 112 ops/sec [107..119] → 124 ops/sec [123..125] 🟢 +10.8% 110 ops/sec [109..112] → 217 ops/sec [196..235] 🟢 +96.7%
Latin-1 characters 4,473 ops/sec [4,362..4,590] → 4,979 ops/sec [4,918..5,032] 🟢 +11.3% 4,378 ops/sec [4,348..4,391] → 8,996 ops/sec [8,561..9,079] 🟢 +105.5%
short base64 (20 chars) 687 ops/sec [678..690] → 654 ops/sec [648..661] 🔴 -4.8% 684 ops/sec [681..690] → 1,419 ops/sec [1,396..1,480] 🟢 +107.5%
medium base64 (600 chars) 25 ops/sec [25..25] → 24 ops/sec [24..24] 🔴 -5.5% 25 ops/sec [25..26] → 52 ops/sec [52..52] 🟢 +104.3%
Latin-1 output 1,071 ops/sec [1,060..1,074] → 1,010 ops/sec [993..1,037] 🔴 -5.7% 1,061 ops/sec [1,057..1,063] → 2,334 ops/sec [2,302..2,343] 🟢 +119.9%
forgiving (no padding) 1,695 ops/sec [1,666..1,708] → 1,608 ops/sec [1,593..1,628] 🔴 -5.1% 1,685 ops/sec [1,673..1,689] → 3,741 ops/sec [3,664..3,778] 🟢 +121.9%
with whitespace 653 ops/sec [646..660] → 615 ops/sec [610..627] 🔴 -5.9% 647 ops/sec [638..652] → 1,405 ops/sec [1,335..1,444] 🟢 +117.1%
atob(btoa(short)) 568 ops/sec [567..570] → 543 ops/sec [539..555] 🔴 -4.5% 563 ops/sec [558..571] → 1,198 ops/sec [1,177..1,207] 🟢 +112.9%
atob(btoa(medium)) 21 ops/sec [20..21] → 20 ops/sec [20..20] 🔴 -3.4% 20 ops/sec [20..20] → 44 ops/sec [43..44] 🟢 +116.4%
classes.js — Interp: 🟢 27, 4 unch. · avg +8.0% · Bytecode: 🟢 31 · avg +77.5%
Benchmark Interpreted Δ Bytecode Δ
simple class new 54,590 ops/sec [54,005..54,909] → 60,893 ops/sec [59,902..61,048] 🟢 +11.5% 66,255 ops/sec [40,339..67,004] → 126,531 ops/sec [123,619..127,564] 🟢 +91.0%
class with defaults 42,721 ops/sec [42,356..42,776] → 46,871 ops/sec [46,552..48,295] 🟢 +9.7% 43,574 ops/sec [43,187..43,905] → 82,839 ops/sec [81,759..83,829] 🟢 +90.1%
50 instances via Array.from 1,824 ops/sec [1,822..1,830] → 2,004 ops/sec [1,970..2,021] 🟢 +9.9% 2,141 ops/sec [2,126..2,156] → 4,351 ops/sec [4,109..4,365] 🟢 +103.3%
instance method call 25,244 ops/sec [24,972..25,473] → 29,868 ops/sec [29,353..30,054] 🟢 +18.3% 31,945 ops/sec [31,640..32,177] → 64,692 ops/sec [64,223..65,078] 🟢 +102.5%
static method call 41,423 ops/sec [41,148..41,805] → 49,042 ops/sec [48,648..49,121] 🟢 +18.4% 70,964 ops/sec [70,080..71,179] → 139,631 ops/sec [139,522..141,034] 🟢 +96.8%
single-level inheritance 21,299 ops/sec [20,978..21,596] → 25,039 ops/sec [24,932..25,321] 🟢 +17.6% 24,762 ops/sec [24,501..25,011] → 49,419 ops/sec [48,419..50,073] 🟢 +99.6%
two-level inheritance 18,673 ops/sec [18,122..18,874] → 21,883 ops/sec [21,494..22,204] 🟢 +17.2% 20,959 ops/sec [20,661..21,565] → 39,098 ops/sec [37,645..40,470] 🟢 +86.5%
private field access 29,141 ops/sec [29,044..29,440] → 31,223 ops/sec [30,635..33,294] 🟢 +7.1% 24,468 ops/sec [24,362..24,748] → 44,967 ops/sec [43,798..45,097] 🟢 +83.8%
private methods 32,748 ops/sec [32,617..32,955] → 34,998 ops/sec [34,827..35,203] 🟢 +6.9% 27,537 ops/sec [27,304..27,922] → 51,106 ops/sec [50,834..51,147] 🟢 +85.6%
getter/setter access 28,331 ops/sec [28,220..28,494] → 31,100 ops/sec [30,806..31,593] 🟢 +9.8% 37,676 ops/sec [36,329..38,013] → 68,173 ops/sec [66,865..69,517] 🟢 +80.9%
class decorator (identity) 38,437 ops/sec [38,122..38,691] → 41,253 ops/sec [41,007..41,662] 🟢 +7.3% 39,507 ops/sec [39,295..39,955] → 74,815 ops/sec [74,274..75,066] 🟢 +89.4%
class decorator (wrapping) 22,369 ops/sec [22,121..22,462] → 24,200 ops/sec [23,763..24,344] 🟢 +8.2% 22,188 ops/sec [21,862..22,596] → 40,782 ops/sec [40,317..42,955] 🟢 +83.8%
identity method decorator 27,842 ops/sec [27,480..28,412] → 30,099 ops/sec [29,575..30,972] 🟢 +8.1% 32,228 ops/sec [31,247..33,459] → 59,215 ops/sec [56,501..60,948] 🟢 +83.7%
wrapping method decorator 22,816 ops/sec [22,626..22,821] → 25,091 ops/sec [24,497..25,714] 🟢 +10.0% 25,035 ops/sec [24,172..25,727] → 45,576 ops/sec [42,588..50,662] 🟢 +82.0%
stacked method decorators (x3) 15,672 ops/sec [15,161..15,835] → 16,600 ops/sec [16,566..16,804] 🟢 +5.9% 16,605 ops/sec [16,565..16,674] → 27,995 ops/sec [27,137..29,043] 🟢 +68.6%
identity field decorator 31,595 ops/sec [31,417..31,766] → 32,119 ops/sec [28,929..34,705] ~ overlap (+1.7%) 31,791 ops/sec [31,255..33,102] → 52,402 ops/sec [50,829..55,414] 🟢 +64.8%
field initializer decorator 26,112 ops/sec [25,415..27,214] → 27,171 ops/sec [26,803..28,016] ~ overlap (+4.1%) 27,849 ops/sec [27,236..29,035] → 45,433 ops/sec [44,744..47,204] 🟢 +63.1%
getter decorator (identity) 25,796 ops/sec [25,507..26,289] → 27,454 ops/sec [27,163..28,190] 🟢 +6.4% 23,947 ops/sec [23,830..24,291] → 40,097 ops/sec [38,741..42,052] 🟢 +67.4%
setter decorator (identity) 21,920 ops/sec [21,746..22,066] → 23,273 ops/sec [23,096..23,743] 🟢 +6.2% 20,052 ops/sec [19,984..20,261] → 34,220 ops/sec [33,817..34,483] 🟢 +70.7%
static method decorator 28,573 ops/sec [28,470..28,652] → 31,501 ops/sec [30,475..31,727] 🟢 +10.2% 34,538 ops/sec [34,092..34,867] → 57,074 ops/sec [55,451..59,856] 🟢 +65.3%
static field decorator 35,554 ops/sec [33,286..35,658] → 36,574 ops/sec [36,121..37,246] 🟢 +2.9% 37,727 ops/sec [36,209..38,611] → 63,736 ops/sec [58,319..68,224] 🟢 +68.9%
private method decorator 23,260 ops/sec [22,767..23,724] → 24,404 ops/sec [24,139..24,947] 🟢 +4.9% 25,636 ops/sec [24,954..26,367] → 43,432 ops/sec [42,344..45,143] 🟢 +69.4%
private field decorator 25,719 ops/sec [25,478..25,990] → 26,611 ops/sec [22,681..27,436] ~ overlap (+3.5%) 23,525 ops/sec [23,207..24,956] → 39,015 ops/sec [37,818..41,010] 🟢 +65.8%
plain auto-accessor (no decorator) 43,789 ops/sec [43,465..44,817] → 45,798 ops/sec [45,073..46,837] 🟢 +4.6% 39,029 ops/sec [38,610..39,454] → 75,174 ops/sec [70,423..84,741] 🟢 +92.6%
auto-accessor with decorator 24,100 ops/sec [23,638..24,486] → 25,900 ops/sec [25,308..26,967] 🟢 +7.5% 22,318 ops/sec [22,075..22,775] → 36,843 ops/sec [36,457..40,330] 🟢 +65.1%
decorator writing metadata 19,402 ops/sec [19,198..19,688] → 19,908 ops/sec [19,611..20,089] ~ overlap (+2.6%) 21,270 ops/sec [20,787..22,355] → 35,013 ops/sec [33,795..36,736] 🟢 +64.6%
static getter read 49,255 ops/sec [49,087..49,463] → 50,303 ops/sec [49,514..51,024] 🟢 +2.1% 64,817 ops/sec [63,727..65,605] → 102,928 ops/sec [98,355..104,474] 🟢 +58.8%
static getter/setter pair 37,521 ops/sec [37,184..38,093] → 39,324 ops/sec [38,776..39,459] 🟢 +4.8% 47,070 ops/sec [46,028..48,933] → 79,639 ops/sec [78,459..81,860] 🟢 +69.2%
inherited static getter 32,000 ops/sec [31,337..32,299] → 34,430 ops/sec [33,823..34,636] 🟢 +7.6% 39,331 ops/sec [38,396..41,430] → 60,195 ops/sec [57,678..61,467] 🟢 +53.0%
inherited static setter 34,696 ops/sec [34,389..34,890] → 36,453 ops/sec [35,977..36,740] 🟢 +5.1% 39,568 ops/sec [38,938..40,534] → 64,265 ops/sec [63,309..65,243] 🟢 +62.4%
inherited static getter with this binding 27,292 ops/sec [27,191..27,333] → 29,662 ops/sec [29,285..30,007] 🟢 +8.7% 31,108 ops/sec [30,887..32,863] → 53,569 ops/sec [51,698..54,771] 🟢 +72.2%
closures.js — Interp: 🟢 11 · avg +10.2% · Bytecode: 🟢 11 · avg +92.0%
Benchmark Interpreted Δ Bytecode Δ
closure over single variable 44,361 ops/sec [43,443..44,546] → 46,500 ops/sec [45,490..47,644] 🟢 +4.8% 130,301 ops/sec [128,871..130,589] → 254,874 ops/sec [250,388..255,928] 🟢 +95.6%
closure over multiple variables 44,075 ops/sec [43,124..46,969] → 48,635 ops/sec [47,578..48,806] 🟢 +10.3% 114,829 ops/sec [112,971..114,971] → 219,514 ops/sec [214,851..229,373] 🟢 +91.2%
nested closures 48,317 ops/sec [47,933..49,570] → 53,923 ops/sec [52,327..54,114] 🟢 +11.6% 114,468 ops/sec [111,486..114,953] → 223,008 ops/sec [222,267..225,777] 🟢 +94.8%
function as argument 32,317 ops/sec [31,556..32,815] → 35,743 ops/sec [34,602..36,590] 🟢 +10.6% 111,171 ops/sec [110,897..112,291] → 219,026 ops/sec [214,786..227,136] 🟢 +97.0%
function returning function 42,321 ops/sec [41,753..43,054] → 46,917 ops/sec [46,357..48,598] 🟢 +10.9% 127,099 ops/sec [125,091..129,182] → 250,522 ops/sec [240,809..253,233] 🟢 +97.1%
compose two functions 25,918 ops/sec [25,419..26,259] → 28,350 ops/sec [28,234..28,570] 🟢 +9.4% 74,838 ops/sec [73,464..75,372] → 140,143 ops/sec [133,561..143,530] 🟢 +87.3%
fn.call 58,224 ops/sec [57,624..58,457] → 64,982 ops/sec [64,403..65,750] 🟢 +11.6% 82,587 ops/sec [82,104..83,135] → 160,837 ops/sec [157,538..166,155] 🟢 +94.7%
fn.apply 45,330 ops/sec [44,811..45,881] → 50,155 ops/sec [50,106..50,265] 🟢 +10.6% 80,652 ops/sec [79,926..81,502] → 151,091 ops/sec [149,332..153,695] 🟢 +87.3%
fn.bind 49,203 ops/sec [48,942..49,326] → 54,739 ops/sec [54,489..54,885] 🟢 +11.3% 110,817 ops/sec [110,255..111,072] → 207,389 ops/sec [194,954..209,967] 🟢 +87.1%
recursive sum to 50 3,724 ops/sec [3,715..3,774] → 4,075 ops/sec [4,043..4,141] 🟢 +9.4% 15,513 ops/sec [9,472..15,598] → 29,748 ops/sec [29,035..30,763] 🟢 +91.8%
recursive tree traversal 6,741 ops/sec [6,689..6,803] → 7,520 ops/sec [7,281..7,546] 🟢 +11.6% 13,336 ops/sec [13,207..13,545] → 25,021 ops/sec [24,874..25,168] 🟢 +87.6%
collections.js — Interp: 🟢 11, 1 unch. · avg +11.1% · Bytecode: 🟢 12 · avg +96.6%
Benchmark Interpreted Δ Bytecode Δ
add 50 elements 2,592 ops/sec [2,580..2,634] → 2,911 ops/sec [2,820..2,952] 🟢 +12.3% 2,780 ops/sec [2,777..2,783] → 5,547 ops/sec [5,429..5,661] 🟢 +99.5%
has lookup (50 elements) 42,403 ops/sec [41,547..43,650] → 46,566 ops/sec [44,777..46,911] 🟢 +9.8% 45,928 ops/sec [44,771..46,155] → 90,507 ops/sec [89,245..91,259] 🟢 +97.1%
delete elements 22,755 ops/sec [22,411..23,388] → 26,142 ops/sec [25,223..26,445] 🟢 +14.9% 24,022 ops/sec [23,711..24,421] → 46,897 ops/sec [46,097..47,540] 🟢 +95.2%
forEach iteration 4,996 ops/sec [4,944..5,059] → 5,516 ops/sec [5,395..5,773] 🟢 +10.4% 7,511 ops/sec [7,240..7,690] → 14,459 ops/sec [14,251..14,728] 🟢 +92.5%
spread to array 13,711 ops/sec [13,628..13,868] → 15,190 ops/sec [14,929..15,354] 🟢 +10.8% 98,635 ops/sec [95,675..102,119] → 186,474 ops/sec [182,050..188,066] 🟢 +89.1%
deduplicate array 18,861 ops/sec [18,426..19,506] → 21,190 ops/sec [20,839..21,643] 🟢 +12.3% 32,843 ops/sec [31,970..33,005] → 64,150 ops/sec [63,927..64,216] 🟢 +95.3%
set 50 entries 2,057 ops/sec [2,034..2,078] → 2,236 ops/sec [2,195..2,271] 🟢 +8.7% 2,255 ops/sec [2,231..2,274] → 4,487 ops/sec [4,382..4,640] 🟢 +99.0%
get lookup (50 entries) 42,437 ops/sec [42,191..43,306] → 47,797 ops/sec [47,077..48,400] 🟢 +12.6% 42,093 ops/sec [41,259..44,446] → 85,495 ops/sec [83,724..87,071] 🟢 +103.1%
has check 61,838 ops/sec [60,610..63,336] → 68,181 ops/sec [65,324..69,714] 🟢 +10.3% 63,598 ops/sec [62,504..64,942] → 128,658 ops/sec [120,984..138,672] 🟢 +102.3%
delete entries 22,781 ops/sec [22,051..23,518] → 26,177 ops/sec [26,053..26,195] 🟢 +14.9% 23,024 ops/sec [22,950..23,509] → 46,250 ops/sec [45,372..47,012] 🟢 +100.9%
forEach iteration 5,072 ops/sec [4,961..5,142] → 5,565 ops/sec [5,116..5,653] ~ overlap (+9.7%) 7,633 ops/sec [7,590..7,690] → 15,320 ops/sec [14,651..15,729] 🟢 +100.7%
keys/values/entries 3,888 ops/sec [3,730..3,919] → 4,162 ops/sec [4,079..4,317] 🟢 +7.0% 13,708 ops/sec [13,603..13,833] → 25,293 ops/sec [24,662..25,538] 🟢 +84.5%
csv.js — Interp: 🟢 10, 3 unch. · avg +8.2% · Bytecode: 🟢 13 · avg +89.3%
Benchmark Interpreted Δ Bytecode Δ
parse simple 3-column CSV 43,402 ops/sec [42,173..43,629] → 46,155 ops/sec [45,494..46,937] 🟢 +6.3% 44,074 ops/sec [43,962..44,574] → 86,833 ops/sec [85,511..87,843] 🟢 +97.0%
parse 10-row CSV 11,818 ops/sec [11,776..11,875] → 12,523 ops/sec [12,478..12,670] 🟢 +6.0% 11,989 ops/sec [11,850..12,148] → 22,902 ops/sec [22,231..23,557] 🟢 +91.0%
parse 100-row CSV 1,840 ops/sec [1,818..1,920] → 1,942 ops/sec [1,932..1,951] 🟢 +5.5% 1,836 ops/sec [1,823..1,865] → 3,521 ops/sec [3,496..3,590] 🟢 +91.8%
parse CSV with quoted fields 65,515 ops/sec [64,543..66,053] → 70,902 ops/sec [63,963..72,583] ~ overlap (+8.2%) 66,766 ops/sec [65,791..67,853] → 124,417 ops/sec [122,138..131,210] 🟢 +86.3%
parse without headers (array of arrays) 5,745 ops/sec [5,666..5,778] → 6,018 ops/sec [5,931..6,115] 🟢 +4.7% 5,751 ops/sec [5,644..5,981] → 10,727 ops/sec [10,649..10,870] 🟢 +86.5%
parse with semicolon delimiter 8,679 ops/sec [8,517..8,905] → 9,132 ops/sec [8,635..9,324] ~ overlap (+5.2%) 8,687 ops/sec [8,605..8,723] → 16,335 ops/sec [16,082..16,595] 🟢 +88.0%
stringify array of objects 65,591 ops/sec [65,268..66,280] → 74,810 ops/sec [73,752..75,540] 🟢 +14.1% 67,632 ops/sec [66,970..68,576] → 135,272 ops/sec [129,321..139,939] 🟢 +100.0%
stringify array of arrays 24,060 ops/sec [23,965..24,097] → 27,551 ops/sec [27,284..27,603] 🟢 +14.5% 24,213 ops/sec [23,431..24,654] → 46,397 ops/sec [46,184..46,931] 🟢 +91.6%
stringify with values needing escaping 50,288 ops/sec [49,877..51,072] → 56,928 ops/sec [55,867..58,718] 🟢 +13.2% 51,780 ops/sec [50,881..52,342] → 104,453 ops/sec [101,645..108,463] 🟢 +101.7%
reviver converts numbers 1,171 ops/sec [1,146..1,191] → 1,282 ops/sec [1,241..1,333] 🟢 +9.4% 1,245 ops/sec [1,232..1,261] → 2,395 ops/sec [2,337..2,462] 🟢 +92.3%
reviver filters empty to null 9,163 ops/sec [9,038..9,238] → 9,830 ops/sec [9,661..10,205] 🟢 +7.3% 10,805 ops/sec [10,537..11,137] → 20,141 ops/sec [19,442..20,861] 🟢 +86.4%
parse then stringify 7,648 ops/sec [7,589..7,736] → 8,008 ops/sec [6,990..8,521] ~ overlap (+4.7%) 7,960 ops/sec [7,927..7,988] → 13,698 ops/sec [13,275..14,244] 🟢 +72.1%
stringify then parse 7,475 ops/sec [7,342..7,611] → 8,060 ops/sec [7,958..8,251] 🟢 +7.8% 7,680 ops/sec [7,589..7,783] → 13,523 ops/sec [13,161..13,839] 🟢 +76.1%
destructuring.js — Interp: 🟢 20, 2 unch. · avg +8.3% · Bytecode: 🟢 22 · avg +87.4%
Benchmark Interpreted Δ Bytecode Δ
simple array destructuring 161,909 ops/sec [161,321..163,030] → 169,467 ops/sec [152,771..179,207] ~ overlap (+4.7%) 107,647 ops/sec [106,709..110,884] → 205,895 ops/sec [198,824..206,647] 🟢 +91.3%
with rest element 110,705 ops/sec [109,121..111,366] → 120,458 ops/sec [117,015..123,727] 🟢 +8.8% 80,635 ops/sec [79,135..82,988] → 156,128 ops/sec [154,474..158,044] 🟢 +93.6%
with defaults 158,936 ops/sec [158,300..159,435] → 176,655 ops/sec [169,317..183,105] 🟢 +11.1% 115,309 ops/sec [114,997..115,448] → 216,552 ops/sec [215,010..217,120] 🟢 +87.8%
skip elements 169,671 ops/sec [168,873..170,387] → 184,769 ops/sec [183,867..185,627] 🟢 +8.9% 116,824 ops/sec [116,119..118,241] → 218,783 ops/sec [217,086..224,919] 🟢 +87.3%
nested array destructuring 80,494 ops/sec [80,045..81,419] → 88,566 ops/sec [87,765..91,188] 🟢 +10.0% 39,670 ops/sec [39,431..39,959] → 75,026 ops/sec [74,220..75,703] 🟢 +89.1%
swap variables 192,047 ops/sec [189,941..192,932] → 200,848 ops/sec [199,646..208,277] 🟢 +4.6% 141,356 ops/sec [140,785..142,540] → 267,799 ops/sec [265,213..269,262] 🟢 +89.4%
simple object destructuring 123,197 ops/sec [117,845..125,187] → 131,947 ops/sec [130,097..135,421] 🟢 +7.1% 106,276 ops/sec [105,307..107,352] → 197,617 ops/sec [196,099..199,492] 🟢 +85.9%
with defaults 144,534 ops/sec [141,414..147,761] → 155,855 ops/sec [150,009..158,470] 🟢 +7.8% 164,905 ops/sec [164,144..165,160] → 309,793 ops/sec [305,610..312,258] 🟢 +87.9%
with renaming 135,027 ops/sec [124,328..137,892] → 142,693 ops/sec [137,407..147,776] ~ overlap (+5.7%) 114,756 ops/sec [114,100..115,536] → 212,610 ops/sec [211,091..215,647] 🟢 +85.3%
nested object destructuring 67,677 ops/sec [66,743..70,533] → 72,064 ops/sec [70,586..72,244] 🟢 +6.5% 58,444 ops/sec [58,102..58,969] → 111,858 ops/sec [110,718..112,013] 🟢 +91.4%
rest properties 51,646 ops/sec [50,223..51,786] → 53,497 ops/sec [53,088..54,332] 🟢 +3.6% 54,808 ops/sec [54,264..55,353] → 105,173 ops/sec [102,505..106,352] 🟢 +91.9%
object parameter 39,392 ops/sec [39,118..39,731] → 41,869 ops/sec [41,676..43,052] 🟢 +6.3% 50,423 ops/sec [49,452..50,760] → 95,133 ops/sec [94,729..96,017] 🟢 +88.7%
array parameter 50,301 ops/sec [49,004..50,404] → 54,248 ops/sec [52,628..56,200] 🟢 +7.8% 52,737 ops/sec [52,000..54,017] → 99,776 ops/sec [98,242..102,945] 🟢 +89.2%
mixed destructuring in map 9,642 ops/sec [9,399..9,740] → 10,488 ops/sec [10,247..10,799] 🟢 +8.8% 11,734 ops/sec [11,564..11,959] → 21,899 ops/sec [21,045..23,786] 🟢 +86.6%
forEach with array destructuring 23,143 ops/sec [22,586..23,443] → 25,570 ops/sec [24,717..25,864] 🟢 +10.5% 18,990 ops/sec [18,391..19,344] → 34,557 ops/sec [33,858..34,849] 🟢 +82.0%
map with array destructuring 23,455 ops/sec [22,126..24,260] → 26,098 ops/sec [25,926..26,260] 🟢 +11.3% 18,399 ops/sec [17,709..18,559] → 32,412 ops/sec [31,692..33,341] 🟢 +76.2%
filter with array destructuring 23,844 ops/sec [22,600..24,168] → 26,879 ops/sec [26,610..27,308] 🟢 +12.7% 19,171 ops/sec [19,056..19,351] → 34,925 ops/sec [32,292..35,124] 🟢 +82.2%
reduce with array destructuring 25,721 ops/sec [24,920..26,747] → 27,818 ops/sec [27,162..28,446] 🟢 +8.2% 18,915 ops/sec [18,264..19,762] → 34,986 ops/sec [34,561..35,330] 🟢 +85.0%
map with object destructuring 21,480 ops/sec [20,987..21,809] → 23,090 ops/sec [22,724..23,532] 🟢 +7.5% 25,360 ops/sec [25,186..25,579] → 47,412 ops/sec [46,915..48,387] 🟢 +87.0%
map with nested destructuring 18,453 ops/sec [18,200..18,684] → 20,580 ops/sec [19,791..21,469] 🟢 +11.5% 23,918 ops/sec [23,324..24,599] → 46,110 ops/sec [45,841..46,237] 🟢 +92.8%
map with rest in destructuring 14,398 ops/sec [14,238..14,602] → 15,763 ops/sec [15,256..16,259] 🟢 +9.5% 9,719 ops/sec [9,556..9,982] → 17,409 ops/sec [16,741..18,517] 🟢 +79.1%
map with defaults in destructuring 17,336 ops/sec [17,044..17,815] → 19,117 ops/sec [18,660..19,235] 🟢 +10.3% 20,124 ops/sec [19,885..20,392] → 38,837 ops/sec [38,079..40,210] 🟢 +93.0%
fibonacci.js — Interp: 🟢 8 · avg +10.2% · Bytecode: 🟢 8 · avg +95.2%
Benchmark Interpreted Δ Bytecode Δ
recursive fib(15) 101 ops/sec [99..105] → 110 ops/sec [110..111] 🟢 +8.8% 429 ops/sec [428..433] → 841 ops/sec [832..854] 🟢 +96.2%
recursive fib(20) 9 ops/sec [9..9] → 10 ops/sec [10..10] 🟢 +10.6% 39 ops/sec [39..39] → 76 ops/sec [74..77] 🟢 +93.7%
recursive fib(15) typed 102 ops/sec [101..103] → 112 ops/sec [110..116] 🟢 +9.1% 442 ops/sec [435..449] → 851 ops/sec [794..864] 🟢 +92.5%
recursive fib(20) typed 9 ops/sec [9..9] → 10 ops/sec [10..10] 🟢 +12.7% 40 ops/sec [39..40] → 76 ops/sec [74..77] 🟢 +91.1%
iterative fib(20) via reduce 4,313 ops/sec [4,257..4,519] → 4,831 ops/sec [4,644..5,093] 🟢 +12.0% 7,379 ops/sec [7,335..7,384] → 14,218 ops/sec [14,016..14,332] 🟢 +92.7%
iterator fib(20) 3,289 ops/sec [3,268..3,302] → 3,620 ops/sec [3,425..3,702] 🟢 +10.1% 4,770 ops/sec [4,687..4,878] → 9,509 ops/sec [9,305..9,651] 🟢 +99.4%
iterator fib(20) via Iterator.from + take 4,294 ops/sec [4,269..4,309] → 4,772 ops/sec [4,735..4,810] 🟢 +11.1% 5,232 ops/sec [5,182..5,281] → 10,383 ops/sec [10,031..10,465] 🟢 +98.5%
iterator fib(20) last value via reduce 3,334 ops/sec [3,252..3,343] → 3,582 ops/sec [3,541..3,613] 🟢 +7.4% 3,933 ops/sec [3,870..3,987] → 7,781 ops/sec [7,672..7,838] 🟢 +97.8%
float16array.js — Interp: 🟢 29, 3 unch. · avg +7.7% · Bytecode: 🟢 32 · avg +73.7%
Benchmark Interpreted Δ Bytecode Δ
new Float16Array(0) 115,211 ops/sec [113,822..117,895] → 122,967 ops/sec [120,007..127,200] 🟢 +6.7% 127,961 ops/sec [123,990..130,463] → 238,032 ops/sec [235,165..239,189] 🟢 +86.0%
new Float16Array(100) 110,314 ops/sec [109,693..111,171] → 116,497 ops/sec [113,238..119,149] 🟢 +5.6% 123,263 ops/sec [122,548..124,732] → 228,085 ops/sec [220,322..229,436] 🟢 +85.0%
new Float16Array(1000) 95,957 ops/sec [95,469..96,602] → 96,936 ops/sec [96,649..98,800] 🟢 +1.0% 101,767 ops/sec [100,656..102,234] → 182,986 ops/sec [180,534..188,010] 🟢 +79.8%
Float16Array.from([...100]) 3,673 ops/sec [3,626..3,812] → 3,713 ops/sec [3,661..3,815] ~ overlap (+1.1%) 3,651 ops/sec [3,589..3,798] → 6,681 ops/sec [6,307..6,788] 🟢 +83.0%
Float16Array.of(1.5, 2.5, 3.5, 4.5, 5.5) 112,861 ops/sec [110,973..115,521] → 119,600 ops/sec [118,700..120,411] 🟢 +6.0% 94,605 ops/sec [90,351..95,179] → 163,571 ops/sec [158,844..166,109] 🟢 +72.9%
new Float16Array(float64Array) 30,032 ops/sec [29,506..30,905] → 34,445 ops/sec [33,402..34,982] 🟢 +14.7% 31,334 ops/sec [30,844..32,427] → 58,204 ops/sec [57,489..59,200] 🟢 +85.8%
sequential write 100 elements 954 ops/sec [943..957] → 1,020 ops/sec [1,008..1,047] 🟢 +6.9% 2,073 ops/sec [2,062..2,087] → 3,115 ops/sec [2,603..3,414] 🟢 +50.3%
sequential read 100 elements 1,073 ops/sec [1,065..1,080] → 1,122 ops/sec [1,118..1,146] 🟢 +4.6% 2,337 ops/sec [2,308..2,416] → 3,943 ops/sec [3,849..4,007] 🟢 +68.7%
write special values (NaN, Inf, -0) 31,949 ops/sec [31,739..32,228] → 35,390 ops/sec [35,155..35,755] 🟢 +10.8% 41,953 ops/sec [39,896..44,133] → 71,671 ops/sec [68,536..75,200] 🟢 +70.8%
Float16Array write 968 ops/sec [954..972] → 1,016 ops/sec [1,004..1,016] 🟢 +5.0% 2,017 ops/sec [2,012..2,025] → 3,433 ops/sec [3,361..3,608] 🟢 +70.2%
Float32Array write 966 ops/sec [960..971] → 1,017 ops/sec [1,010..1,022] 🟢 +5.3% 2,055 ops/sec [2,015..2,107] → 3,382 ops/sec [3,368..3,390] 🟢 +64.6%
Float64Array write 974 ops/sec [961..986] → 1,024 ops/sec [1,021..1,042] 🟢 +5.2% 2,033 ops/sec [1,970..2,053] → 3,538 ops/sec [3,498..3,625] 🟢 +74.0%
Float16Array read 1,036 ops/sec [1,010..1,056] → 1,084 ops/sec [1,082..1,087] 🟢 +4.7% 2,125 ops/sec [2,074..2,141] → 3,802 ops/sec [3,529..3,883] 🟢 +78.9%
Float32Array read 1,068 ops/sec [1,046..1,082] → 1,134 ops/sec [1,122..1,138] 🟢 +6.1% 2,133 ops/sec [2,116..2,147] → 3,837 ops/sec [3,767..3,938] 🟢 +79.8%
Float64Array read 1,051 ops/sec [1,042..1,085] → 1,127 ops/sec [1,119..1,139] 🟢 +7.2% 2,173 ops/sec [2,116..2,211] → 4,035 ops/sec [3,743..4,119] 🟢 +85.7%
fill(1.5) 4,072 ops/sec [4,055..4,096] → 4,758 ops/sec [4,694..4,802] 🟢 +16.9% 4,115 ops/sec [4,090..4,130] → 7,539 ops/sec [7,424..7,819] 🟢 +83.2%
slice() 30,957 ops/sec [30,696..31,287] → 34,519 ops/sec [34,400..34,722] 🟢 +11.5% 31,924 ops/sec [31,587..32,997] → 55,008 ops/sec [51,539..56,154] 🟢 +72.3%
map(x => x * 2) 1,967 ops/sec [1,947..2,005] → 2,184 ops/sec [2,173..2,191] 🟢 +11.0% 2,529 ops/sec [2,507..2,539] → 4,649 ops/sec [4,631..4,691] 🟢 +83.8%
filter(x => x > 25) 2,000 ops/sec [1,989..2,010] → 2,149 ops/sec [2,113..2,196] 🟢 +7.5% 2,669 ops/sec [2,658..2,808] → 4,921 ops/sec [4,778..4,991] 🟢 +84.4%
reduce (sum) 1,956 ops/sec [1,922..1,990] → 2,171 ops/sec [2,155..2,200] 🟢 +11.0% 2,374 ops/sec [2,346..2,382] → 4,230 ops/sec [4,155..4,263] 🟢 +78.1%
sort() 10,280 ops/sec [10,183..10,425] → 10,413 ops/sec [10,322..10,544] ~ overlap (+1.3%) 10,492 ops/sec [10,443..10,499] → 13,009 ops/sec [12,513..13,738] 🟢 +24.0%
indexOf() 27,813 ops/sec [27,736..28,238] → 31,212 ops/sec [30,773..31,390] 🟢 +12.2% 28,488 ops/sec [28,287..28,736] → 46,877 ops/sec [45,520..48,002] 🟢 +64.6%
reverse() 33,900 ops/sec [33,793..34,003] → 38,346 ops/sec [37,846..39,948] 🟢 +13.1% 34,992 ops/sec [34,538..35,203] → 61,972 ops/sec [60,567..62,062] 🟢 +77.1%
toReversed() 25,450 ops/sec [25,151..25,695] → 26,835 ops/sec [26,464..27,127] 🟢 +5.4% 26,086 ops/sec [25,903..26,454] → 38,216 ops/sec [36,047..39,347] 🟢 +46.5%
toSorted() 368 ops/sec [365..377] → 380 ops/sec [373..384] ~ overlap (+3.2%) 373 ops/sec [368..377] → 474 ops/sec [459..516] 🟢 +27.0%
create view over existing buffer 129,769 ops/sec [128,969..131,105] → 140,037 ops/sec [138,065..141,132] 🟢 +7.9% 142,841 ops/sec [140,820..145,044] → 263,115 ops/sec [258,938..268,325] 🟢 +84.2%
subarray() 148,086 ops/sec [147,153..150,078] → 160,973 ops/sec [159,156..163,187] 🟢 +8.7% 158,595 ops/sec [156,945..159,238] → 293,388 ops/sec [290,619..304,306] 🟢 +85.0%
set() from array 121,561 ops/sec [118,779..123,036] → 135,513 ops/sec [134,761..137,774] 🟢 +11.5% 133,906 ops/sec [129,830..135,399] → 262,393 ops/sec [259,246..269,869] 🟢 +96.0%
for-of loop 1,884 ops/sec [1,850..1,901] → 2,007 ops/sec [1,973..2,040] 🟢 +6.5% 7,487 ops/sec [7,394..7,558] → 12,048 ops/sec [11,798..12,292] 🟢 +60.9%
spread into array 7,062 ops/sec [6,952..7,340] → 7,669 ops/sec [7,532..7,912] 🟢 +8.6% 26,417 ops/sec [25,912..27,473] → 45,785 ops/sec [45,388..46,046] 🟢 +73.3%
f16round(1.337) 242,764 ops/sec [236,632..248,224] → 267,284 ops/sec [262,927..278,570] 🟢 +10.1% 219,933 ops/sec [217,712..222,098] → 428,711 ops/sec [421,178..443,607] 🟢 +94.9%
f16round over 100 values 1,391 ops/sec [1,385..1,394] → 1,506 ops/sec [1,478..1,531] 🟢 +8.3% 2,677 ops/sec [2,665..2,712] → 5,016 ops/sec [4,974..5,084] 🟢 +87.4%
for-of.js — Interp: 🟢 7 · avg +4.4% · Bytecode: 🟢 7 · avg +94.5%
Benchmark Interpreted Δ Bytecode Δ
for...of with 10-element array 17,714 ops/sec [17,531..17,909] → 18,528 ops/sec [18,048..19,028] 🟢 +4.6% 103,140 ops/sec [102,374..105,129] → 202,872 ops/sec [193,437..205,876] 🟢 +96.7%
for...of with 100-element array 1,999 ops/sec [1,973..2,026] → 2,070 ops/sec [2,066..2,085] 🟢 +3.5% 13,971 ops/sec [13,734..14,153] → 27,616 ops/sec [26,694..28,041] 🟢 +97.7%
for...of with string (10 chars) 13,141 ops/sec [12,987..13,272] → 13,884 ops/sec [13,611..14,076] 🟢 +5.6% 30,348 ops/sec [30,033..30,519] → 58,172 ops/sec [55,619..61,403] 🟢 +91.7%
for...of with Set (10 elements) 17,800 ops/sec [17,681..17,988] → 18,572 ops/sec [18,431..18,989] 🟢 +4.3% 100,799 ops/sec [99,148..102,358] → 197,016 ops/sec [194,849..200,846] 🟢 +95.5%
for...of with Map entries (10 entries) 12,167 ops/sec [12,104..12,306] → 12,793 ops/sec [12,639..12,874] 🟢 +5.1% 15,074 ops/sec [14,598..15,858] → 29,327 ops/sec [28,831..29,557] 🟢 +94.6%
for...of with destructuring 15,004 ops/sec [14,954..15,084] → 15,744 ops/sec [15,538..16,058] 🟢 +4.9% 19,653 ops/sec [19,380..20,118] → 38,096 ops/sec [37,659..38,261] 🟢 +93.8%
for-await-of with sync array 16,636 ops/sec [16,578..16,722] → 17,102 ops/sec [16,889..17,217] 🟢 +2.8% 14,383 ops/sec [14,365..14,443] → 27,526 ops/sec [26,402..28,661] 🟢 +91.4%
generators.js — Interp: 🟢 4 · avg +10.0% · Bytecode: 🟢 4 · avg +82.8%
Benchmark Interpreted Δ Bytecode Δ
manual next over object generator 822 ops/sec [804..830] → 909 ops/sec [898..933] 🟢 +10.6% 904 ops/sec [890..915] → 1,697 ops/sec [1,632..1,699] 🟢 +87.8%
for...of over object generator 1,238 ops/sec [1,220..1,269] → 1,353 ops/sec [1,311..1,383] 🟢 +9.3% 1,733 ops/sec [1,708..1,764] → 3,165 ops/sec [3,104..3,206] 🟢 +82.6%
yield delegation 1,249 ops/sec [1,233..1,253] → 1,379 ops/sec [1,350..1,405] 🟢 +10.5% 1,756 ops/sec [1,741..1,760] → 3,126 ops/sec [3,081..3,185] 🟢 +78.0%
class generator method 1,253 ops/sec [1,236..1,286] → 1,373 ops/sec [1,342..1,445] 🟢 +9.5% 1,739 ops/sec [1,701..1,763] → 3,180 ops/sec [3,157..3,226] 🟢 +82.9%
iterators.js — Interp: 🟢 42 · avg +8.8% · Bytecode: 🟢 42 · avg +84.6%
Benchmark Interpreted Δ Bytecode Δ
Iterator.from({next}).toArray() — 20 elements 4,007 ops/sec [4,002..4,077] → 4,270 ops/sec [4,123..4,349] 🟢 +6.6% 5,069 ops/sec [5,026..5,271] → 10,013 ops/sec [9,717..10,056] 🟢 +97.5%
Iterator.from({next}).toArray() — 50 elements 1,688 ops/sec [1,637..1,701] → 1,858 ops/sec [1,845..1,871] 🟢 +10.1% 2,214 ops/sec [2,183..2,221] → 4,297 ops/sec [3,994..4,404] 🟢 +94.1%
spread pre-wrapped iterator — 20 elements 4,007 ops/sec [3,959..4,031] → 4,352 ops/sec [4,291..4,432] 🟢 +8.6% 5,266 ops/sec [5,246..5,326] → 10,118 ops/sec [9,775..10,533] 🟢 +92.1%
Iterator.from({next}).forEach — 50 elements 1,225 ops/sec [1,193..1,275] → 1,351 ops/sec [1,308..1,371] 🟢 +10.3% 1,680 ops/sec [1,664..1,698] → 3,197 ops/sec [3,169..3,290] 🟢 +90.3%
Iterator.from({next}).reduce — 50 elements 1,227 ops/sec [1,222..1,268] → 1,394 ops/sec [1,360..1,402] 🟢 +13.6% 1,637 ops/sec [1,622..1,648] → 3,068 ops/sec [2,992..3,092] 🟢 +87.5%
wrap array iterator 70,291 ops/sec [53,519..71,242] → 78,190 ops/sec [77,882..78,729] 🟢 +11.2% 74,934 ops/sec [67,225..75,238] → 138,559 ops/sec [137,987..139,560] 🟢 +84.9%
wrap plain {next()} object 2,790 ops/sec [2,770..2,809] → 3,004 ops/sec [2,991..3,031] 🟢 +7.7% 3,690 ops/sec [3,582..3,719] → 6,793 ops/sec [6,517..7,175] 🟢 +84.1%
map + toArray (50 elements) 1,230 ops/sec [1,220..1,237] → 1,364 ops/sec [1,336..1,381] 🟢 +10.9% 1,691 ops/sec [1,676..1,696] → 3,055 ops/sec [3,029..3,109] 🟢 +80.7%
filter + toArray (50 elements) 1,230 ops/sec [1,209..1,261] → 1,351 ops/sec [1,318..1,399] 🟢 +9.8% 1,709 ops/sec [1,680..1,726] → 3,025 ops/sec [2,891..3,063] 🟢 +77.0%
take(10) + toArray (50 element source) 7,634 ops/sec [7,491..7,800] → 8,667 ops/sec [8,576..8,774] 🟢 +13.5% 9,550 ops/sec [9,476..9,668] → 18,381 ops/sec [17,966..18,776] 🟢 +92.5%
drop(40) + toArray (50 element source) 1,722 ops/sec [1,691..1,734] → 1,872 ops/sec [1,865..1,890] 🟢 +8.7% 2,248 ops/sec [2,234..2,261] → 4,372 ops/sec [4,193..4,394] 🟢 +94.5%
chained map + filter + take (100 element source) 2,333 ops/sec [2,321..2,344] → 2,570 ops/sec [2,436..2,634] 🟢 +10.2% 3,154 ops/sec [3,050..3,179] → 5,518 ops/sec [5,368..5,615] 🟢 +74.9%
some + every (50 elements) 689 ops/sec [683..702] → 754 ops/sec [741..805] 🟢 +9.5% 968 ops/sec [958..982] → 1,771 ops/sec [1,748..1,794] 🟢 +83.0%
find (50 elements) 1,526 ops/sec [1,519..1,544] → 1,652 ops/sec [1,646..1,682] 🟢 +8.3% 2,054 ops/sec [2,022..2,070] → 3,801 ops/sec [3,687..3,960] 🟢 +85.0%
concat 2 arrays (10 + 10 elements) 66,386 ops/sec [65,946..66,624] → 71,578 ops/sec [70,320..73,110] 🟢 +7.8% 67,784 ops/sec [66,860..68,706] → 128,593 ops/sec [124,630..129,826] 🟢 +89.7%
concat 5 arrays (10 elements each) 39,178 ops/sec [38,836..39,665] → 42,658 ops/sec [42,318..42,888] 🟢 +8.9% 40,271 ops/sec [40,060..40,385] → 75,031 ops/sec [72,737..78,390] 🟢 +86.3%
concat 2 arrays (20 + 20 elements) 55,315 ops/sec [53,897..56,357] → 61,847 ops/sec [60,358..62,765] 🟢 +11.8% 57,343 ops/sec [56,655..57,440] → 106,235 ops/sec [105,050..110,232] 🟢 +85.3%
concat + filter + toArray (20 + 20 elements) 4,936 ops/sec [4,839..4,954] → 5,407 ops/sec [5,347..5,467] 🟢 +9.5% 6,959 ops/sec [6,920..6,978] → 12,428 ops/sec [12,193..12,493] 🟢 +78.6%
concat + map + take (20 + 20 elements, take 10) 15,922 ops/sec [15,653..16,388] → 17,273 ops/sec [17,091..17,467] 🟢 +8.5% 20,277 ops/sec [20,145..20,381] → 37,420 ops/sec [37,075..38,553] 🟢 +84.5%
concat Sets (15 + 15 elements) 63,532 ops/sec [63,043..65,083] → 69,360 ops/sec [67,870..71,069] 🟢 +9.2% 64,896 ops/sec [64,192..65,128] → 116,414 ops/sec [115,400..117,223] 🟢 +79.4%
concat strings (13 + 13 characters) 46,391 ops/sec [45,162..46,823] → 50,165 ops/sec [50,028..50,532] 🟢 +8.1% 45,173 ops/sec [44,776..45,923] → 83,511 ops/sec [82,345..85,344] 🟢 +84.9%
zip 2 arrays (10 + 10 elements) 27,500 ops/sec [26,530..27,736] → 29,513 ops/sec [29,295..29,971] 🟢 +7.3% 27,490 ops/sec [26,990..27,767] → 49,914 ops/sec [49,251..50,505] 🟢 +81.6%
zip 3 arrays (10 elements each) 25,745 ops/sec [24,746..26,051] → 26,897 ops/sec [26,347..27,611] 🟢 +4.5% 25,341 ops/sec [24,936..25,852] → 47,600 ops/sec [43,376..48,367] 🟢 +87.8%
zip 2 arrays (20 + 20 elements) 18,417 ops/sec [17,957..18,964] → 19,836 ops/sec [19,747..19,863] 🟢 +7.7% 18,447 ops/sec [18,124..18,869] → 33,335 ops/sec [32,454..33,654] 🟢 +80.7%
zip 2 arrays (50 + 50 elements) 9,329 ops/sec [9,025..9,869] → 10,095 ops/sec [10,051..10,253] 🟢 +8.2% 9,086 ops/sec [9,070..9,107] → 17,547 ops/sec [17,211..17,965] 🟢 +93.1%
zip shortest mode (20 + 10 elements) 27,539 ops/sec [27,076..28,674] → 29,812 ops/sec [29,314..30,029] 🟢 +8.3% 27,728 ops/sec [27,235..27,909] → 50,360 ops/sec [48,719..52,400] 🟢 +81.6%
zip longest mode (10 + 20 elements) 16,495 ops/sec [16,336..16,689] → 17,511 ops/sec [17,480..17,770] 🟢 +6.2% 15,907 ops/sec [15,369..16,166] → 29,008 ops/sec [28,363..29,125] 🟢 +82.4%
zip strict mode (20 + 20 elements) 17,905 ops/sec [17,269..18,444] → 18,941 ops/sec [18,595..19,292] 🟢 +5.8% 17,378 ops/sec [17,044..17,448] → 31,602 ops/sec [30,694..32,801] 🟢 +81.8%
zip + map + toArray (20 + 20 elements) 6,571 ops/sec [6,474..6,897] → 7,176 ops/sec [7,040..7,249] 🟢 +9.2% 4,797 ops/sec [4,762..4,841] → 8,898 ops/sec [8,790..9,079] 🟢 +85.5%
zip + filter + toArray (20 + 20 elements) 6,543 ops/sec [6,518..6,562] → 7,002 ops/sec [6,788..7,058] 🟢 +7.0% 4,950 ops/sec [4,849..5,021] → 8,932 ops/sec [8,910..8,970] 🟢 +80.4%
zip Sets (15 + 15 elements) 22,788 ops/sec [22,441..24,252] → 25,122 ops/sec [24,738..25,418] 🟢 +10.2% 22,342 ops/sec [21,798..22,542] → 40,134 ops/sec [39,755..40,448] 🟢 +79.6%
zipKeyed 2 keys (10 elements each) 25,638 ops/sec [24,656..26,590] → 28,323 ops/sec [27,795..28,776] 🟢 +10.5% 24,807 ops/sec [24,568..25,628] → 44,965 ops/sec [44,665..45,770] 🟢 +81.3%
zipKeyed 3 keys (20 elements each) 12,165 ops/sec [11,981..12,769] → 13,592 ops/sec [13,315..14,042] 🟢 +11.7% 12,087 ops/sec [11,748..12,145] → 22,590 ops/sec [22,320..22,743] 🟢 +86.9%
zipKeyed longest mode (10 + 20 elements) 14,560 ops/sec [14,238..14,719] → 15,792 ops/sec [15,584..16,069] 🟢 +8.5% 13,534 ops/sec [13,122..13,773] → 24,615 ops/sec [24,441..26,074] 🟢 +81.9%
zipKeyed strict mode (20 + 20 elements) 14,940 ops/sec [14,778..15,202] → 16,663 ops/sec [16,139..16,956] 🟢 +11.5% 14,439 ops/sec [14,248..14,555] → 25,586 ops/sec [24,796..26,164] 🟢 +77.2%
zipKeyed + filter + map (20 elements) 4,398 ops/sec [4,308..4,432] → 4,855 ops/sec [4,837..4,890] 🟢 +10.4% 5,167 ops/sec [5,063..5,224] → 9,521 ops/sec [9,418..9,648] 🟢 +84.3%
array.values().map().filter().toArray() 2,176 ops/sec [2,154..2,189] → 2,398 ops/sec [2,338..2,460] 🟢 +10.2% 3,088 ops/sec [3,008..3,121] → 5,804 ops/sec [5,670..5,858] 🟢 +87.9%
array.values().take(5).toArray() 94,727 ops/sec [93,294..95,691] → 98,894 ops/sec [98,495..99,658] 🟢 +4.4% 92,420 ops/sec [91,563..94,239] → 176,128 ops/sec [170,636..179,857] 🟢 +90.6%
array.values().drop(45).toArray() 77,889 ops/sec [76,796..78,613] → 81,617 ops/sec [80,716..82,105] 🟢 +4.8% 76,804 ops/sec [75,785..78,562] → 139,177 ops/sec [137,257..144,647] 🟢 +81.2%
map.entries() chained helpers 3,428 ops/sec [3,390..3,464] → 3,677 ops/sec [3,628..3,723] 🟢 +7.3% 2,449 ops/sec [2,413..2,512] → 4,326 ops/sec [4,272..4,407] 🟢 +76.6%
set.values() chained helpers 5,178 ops/sec [5,159..5,252] → 5,566 ops/sec [5,531..5,663] 🟢 +7.5% 7,149 ops/sec [7,133..7,209] → 12,717 ops/sec [12,411..12,868] 🟢 +77.9%
string iterator map + toArray 4,674 ops/sec [4,627..4,713] → 5,030 ops/sec [5,003..5,101] 🟢 +7.6% 4,916 ops/sec [4,855..4,980] → 9,227 ops/sec [9,093..9,316] 🟢 +87.7%
json.js — Interp: 🟢 20 · avg +11.9% · Bytecode: 🟢 20 · avg +80.8%
Benchmark Interpreted Δ Bytecode Δ
parse simple object 69,492 ops/sec [68,259..70,710] → 77,014 ops/sec [76,188..78,030] 🟢 +10.8% 68,118 ops/sec [66,441..68,904] → 127,142 ops/sec [124,670..128,244] 🟢 +86.7%
parse nested object 46,305 ops/sec [46,038..46,818] → 51,431 ops/sec [50,133..51,864] 🟢 +11.1% 45,655 ops/sec [45,425..45,897] → 78,906 ops/sec [78,255..79,855] 🟢 +72.8%
parse array of objects 27,425 ops/sec [26,206..27,718] → 30,480 ops/sec [29,349..30,677] 🟢 +11.1% 26,941 ops/sec [26,621..26,998] → 46,741 ops/sec [46,516..46,986] 🟢 +73.5%
parse large flat object 28,273 ops/sec [26,987..29,680] → 31,903 ops/sec [30,445..33,344] 🟢 +12.8% 28,618 ops/sec [27,811..28,986] → 53,116 ops/sec [52,695..53,910] 🟢 +85.6%
parse mixed types 34,053 ops/sec [33,284..34,724] → 37,941 ops/sec [37,471..38,876] 🟢 +11.4% 33,756 ops/sec [33,614..34,546] → 60,575 ops/sec [59,700..61,178] 🟢 +79.5%
stringify simple object 73,973 ops/sec [69,553..74,346] → 79,519 ops/sec [78,921..80,752] 🟢 +7.5% 62,339 ops/sec [61,370..62,609] → 116,118 ops/sec [114,159..117,693] 🟢 +86.3%
stringify nested object 42,183 ops/sec [41,760..43,954] → 47,038 ops/sec [45,384..47,378] 🟢 +11.5% 35,322 ops/sec [34,904..35,348] → 64,175 ops/sec [52,869..65,368] 🟢 +81.7%
stringify array of objects 19,186 ops/sec [19,035..19,476] → 21,420 ops/sec [20,420..22,171] 🟢 +11.6% 18,693 ops/sec [17,782..18,820] → 36,516 ops/sec [35,601..39,409] 🟢 +95.3%
stringify mixed types 28,701 ops/sec [28,338..29,302] → 31,014 ops/sec [30,271..32,599] 🟢 +8.1% 24,138 ops/sec [23,801..24,376] → 43,393 ops/sec [42,073..44,404] 🟢 +79.8%
reviver doubles numbers 12,508 ops/sec [12,438..13,255] → 13,985 ops/sec [13,717..14,264] 🟢 +11.8% 15,397 ops/sec [15,170..15,940] → 27,048 ops/sec [26,844..27,782] 🟢 +75.7%
reviver filters properties 12,081 ops/sec [11,947..12,162] → 13,683 ops/sec [13,410..14,022] 🟢 +13.3% 13,284 ops/sec [13,063..13,583] → 24,196 ops/sec [23,967..24,436] 🟢 +82.2%
reviver on nested object 14,594 ops/sec [14,536..14,855] → 16,515 ops/sec [16,354..16,608] 🟢 +13.2% 16,595 ops/sec [16,287..16,829] → 29,104 ops/sec [28,673..29,254] 🟢 +75.4%
reviver on array 7,678 ops/sec [7,512..7,887] → 8,578 ops/sec [8,216..8,750] 🟢 +11.7% 9,602 ops/sec [9,360..9,781] → 17,064 ops/sec [16,754..17,364] 🟢 +77.7%
replacer function doubles numbers 14,277 ops/sec [13,835..14,676] → 16,343 ops/sec [16,082..16,409] 🟢 +14.5% 17,284 ops/sec [17,195..17,441] → 30,608 ops/sec [30,146..31,187] 🟢 +77.1%
replacer function excludes properties 19,429 ops/sec [19,198..19,503] → 21,506 ops/sec [20,852..21,944] 🟢 +10.7% 21,201 ops/sec [20,979..21,330] → 38,525 ops/sec [37,991..39,306] 🟢 +81.7%
array replacer (allowlist) 43,899 ops/sec [43,688..44,480] → 48,350 ops/sec [48,141..49,016] 🟢 +10.1% 37,465 ops/sec [36,797..37,535] → 66,081 ops/sec [65,389..66,739] 🟢 +76.4%
stringify with 2-space indent 36,843 ops/sec [35,906..37,915] → 41,853 ops/sec [39,984..42,483] 🟢 +13.6% 34,272 ops/sec [33,865..34,707] → 60,383 ops/sec [59,395..61,133] 🟢 +76.2%
stringify with tab indent 37,602 ops/sec [36,123..38,646] → 41,795 ops/sec [41,395..42,710] 🟢 +11.1% 33,376 ops/sec [32,798..33,870] → 61,345 ops/sec [59,445..62,796] 🟢 +83.8%
parse then stringify 21,990 ops/sec [21,855..22,174] → 25,681 ops/sec [25,005..26,111] 🟢 +16.8% 22,656 ops/sec [22,146..23,094] → 41,984 ops/sec [41,649..43,081] 🟢 +85.3%
stringify then parse 13,089 ops/sec [12,811..13,216] → 14,965 ops/sec [14,579..16,057] 🟢 +14.3% 13,371 ops/sec [13,131..13,676] → 24,637 ops/sec [24,212..25,499] 🟢 +84.3%
jsx.jsx — Interp: 🟢 19, 2 unch. · avg +7.8% · Bytecode: 🟢 21 · avg +90.2%
Benchmark Interpreted Δ Bytecode Δ
simple element 81,122 ops/sec [80,789..81,978] → 87,063 ops/sec [86,071..87,992] 🟢 +7.3% 92,589 ops/sec [91,545..94,332] → 182,848 ops/sec [177,484..188,755] 🟢 +97.5%
self-closing element 83,967 ops/sec [83,163..84,897] → 90,935 ops/sec [88,984..91,098] 🟢 +8.3% 99,911 ops/sec [98,208..100,592] → 193,394 ops/sec [183,120..203,381] 🟢 +93.6%
element with string attribute 70,469 ops/sec [69,603..70,888] → 75,235 ops/sec [74,506..76,606] 🟢 +6.8% 75,267 ops/sec [73,838..77,319] → 144,668 ops/sec [141,193..148,362] 🟢 +92.2%
element with multiple attributes 60,599 ops/sec [60,056..61,256] → 64,876 ops/sec [64,487..65,155] 🟢 +7.1% 55,074 ops/sec [54,346..55,856] → 105,338 ops/sec [102,830..110,669] 🟢 +91.3%
element with expression attribute 66,048 ops/sec [64,787..66,382] → 70,731 ops/sec [69,554..71,259] 🟢 +7.1% 76,919 ops/sec [75,468..78,515] → 151,110 ops/sec [144,980..155,156] 🟢 +96.5%
text child 81,090 ops/sec [79,691..82,690] → 87,945 ops/sec [87,622..88,595] 🟢 +8.5% 94,719 ops/sec [94,578..95,441] → 178,966 ops/sec [171,357..182,714] 🟢 +88.9%
expression child 78,584 ops/sec [77,968..79,258] → 87,049 ops/sec [84,557..87,935] 🟢 +10.8% 87,976 ops/sec [86,924..89,462] → 171,256 ops/sec [169,611..174,172] 🟢 +94.7%
mixed text and expression 74,665 ops/sec [72,090..76,962] → 81,357 ops/sec [72,840..83,532] ~ overlap (+9.0%) 80,961 ops/sec [80,067..82,655] → 155,929 ops/sec [141,980..156,754] 🟢 +92.6%
nested elements (3 levels) 30,786 ops/sec [30,685..31,674] → 33,985 ops/sec [33,315..34,839] 🟢 +10.4% 35,020 ops/sec [33,876..36,604] → 66,417 ops/sec [65,370..68,371] 🟢 +89.7%
sibling children 23,105 ops/sec [23,048..23,170] → 25,580 ops/sec [25,339..26,245] 🟢 +10.7% 25,996 ops/sec [25,520..26,770] → 52,273 ops/sec [48,329..52,954] 🟢 +101.1%
component element 60,613 ops/sec [59,902..61,234] → 65,223 ops/sec [64,410..65,947] 🟢 +7.6% 69,915 ops/sec [68,827..71,503] → 137,269 ops/sec [134,211..138,562] 🟢 +96.3%
component with children 36,823 ops/sec [36,511..37,146] → 40,422 ops/sec [40,362..40,527] 🟢 +9.8% 41,567 ops/sec [40,771..42,472] → 80,866 ops/sec [78,930..81,511] 🟢 +94.5%
dotted component 51,988 ops/sec [51,328..53,202] → 54,849 ops/sec [54,463..56,726] 🟢 +5.5% 55,567 ops/sec [55,047..57,011] → 109,876 ops/sec [106,584..112,177] 🟢 +97.7%
empty fragment 84,025 ops/sec [83,023..87,182] → 91,234 ops/sec [89,676..93,863] 🟢 +8.6% 103,294 ops/sec [99,409..105,058] → 193,367 ops/sec [190,481..212,226] 🟢 +87.2%
fragment with children 23,521 ops/sec [23,232..23,869] → 25,529 ops/sec [25,167..26,405] 🟢 +8.5% 26,520 ops/sec [25,817..26,947] → 47,838 ops/sec [46,666..48,434] 🟢 +80.4%
spread attributes 44,569 ops/sec [44,263..44,993] → 47,802 ops/sec [46,486..48,742] 🟢 +7.3% 42,725 ops/sec [42,245..43,716] → 77,816 ops/sec [76,295..78,560] 🟢 +82.1%
spread with overrides 39,734 ops/sec [38,681..40,202] → 43,095 ops/sec [42,550..43,294] 🟢 +8.5% 38,147 ops/sec [37,650..38,537] → 72,126 ops/sec [71,381..73,136] 🟢 +89.1%
shorthand props 61,847 ops/sec [61,383..63,626] → 67,093 ops/sec [66,161..69,258] 🟢 +8.5% 63,451 ops/sec [61,847..63,675] → 116,331 ops/sec [115,387..116,782] 🟢 +83.3%
nav bar structure 11,364 ops/sec [11,205..11,606] → 11,610 ops/sec [11,513..12,048] ~ overlap (+2.2%) 11,919 ops/sec [11,887..12,044] → 22,111 ops/sec [21,662..22,339] 🟢 +85.5%
card component tree 13,305 ops/sec [12,997..13,498] → 14,178 ops/sec [13,900..14,412] 🟢 +6.6% 13,918 ops/sec [13,440..14,106] → 24,593 ops/sec [24,211..24,801] 🟢 +76.7%
10 list items via Array.from 5,652 ops/sec [5,544..5,716] → 5,925 ops/sec [5,881..6,039] 🟢 +4.8% 5,905 ops/sec [5,659..6,049] → 10,883 ops/sec [10,780..10,933] 🟢 +84.3%
modules.js — Interp: 🟢 7, 2 unch. · avg +8.3% · Bytecode: 🟢 9 · avg +105.0%
Benchmark Interpreted Δ Bytecode Δ
call imported function 144,582 ops/sec [142,466..147,313] → 163,383 ops/sec [162,131..164,002] 🟢 +13.0% 497,937 ops/sec [493,081..511,413] → 985,634 ops/sec [929,605..1,066,829] 🟢 +97.9%
call two imported functions 82,218 ops/sec [80,595..83,183] → 92,724 ops/sec [88,683..94,590] 🟢 +12.8% 326,573 ops/sec [322,520..328,594] → 635,299 ops/sec [603,244..651,215] 🟢 +94.5%
read imported constant 483,119 ops/sec [455,538..492,669] → 501,512 ops/sec [493,493..522,876] 🟢 +3.8% 1,150,665 ops/sec [1,138,482..1,167,786] → 2,385,940 ops/sec [2,279,152..2,481,346] 🟢 +107.4%
read imported string 485,239 ops/sec [474,105..502,962] → 497,358 ops/sec [471,511..517,879] ~ overlap (+2.5%) 1,151,610 ops/sec [1,131,260..1,155,641] → 2,386,823 ops/sec [2,320,039..2,395,949] 🟢 +107.3%
read JSON string property 469,889 ops/sec [460,775..478,037] → 505,096 ops/sec [492,339..515,811] 🟢 +7.5% 1,162,946 ops/sec [1,121,304..1,192,994] → 2,358,326 ops/sec [2,313,334..2,440,715] 🟢 +102.8%
read JSON number property 456,418 ops/sec [450,985..475,350] → 505,831 ops/sec [488,966..516,253] 🟢 +10.8% 1,156,146 ops/sec [1,129,092..1,168,055] → 2,416,130 ops/sec [2,356,782..2,419,556] 🟢 +109.0%
read JSON boolean property 463,815 ops/sec [454,987..484,526] → 508,767 ops/sec [495,526..526,815] 🟢 +9.7% 1,152,996 ops/sec [1,135,668..1,164,764] → 2,385,448 ops/sec [2,233,495..2,444,055] 🟢 +106.9%
read JSON array property 466,546 ops/sec [444,997..487,585] → 498,263 ops/sec [484,519..513,415] ~ overlap (+6.8%) 1,153,606 ops/sec [1,133,497..1,190,574] → 2,353,724 ops/sec [2,295,023..2,381,497] 🟢 +104.0%
read multiple JSON properties 278,856 ops/sec [272,686..283,452] → 301,039 ops/sec [295,951..303,689] 🟢 +8.0% 882,235 ops/sec [875,040..946,403] → 1,900,446 ops/sec [1,825,125..1,910,997] 🟢 +115.4%
numbers.js — Interp: 🟢 10, 1 unch. · avg +10.1% · Bytecode: 🟢 11 · avg +90.2%
Benchmark Interpreted Δ Bytecode Δ
integer arithmetic 151,853 ops/sec [146,855..152,502] → 167,545 ops/sec [161,506..173,089] 🟢 +10.3% 509,298 ops/sec [492,296..521,992] → 1,004,644 ops/sec [979,387..1,018,038] 🟢 +97.3%
floating point arithmetic 178,444 ops/sec [174,058..182,014] → 195,203 ops/sec [189,628..202,120] 🟢 +9.4% 254,879 ops/sec [253,491..269,424] → 461,741 ops/sec [459,310..466,755] 🟢 +81.2%
number coercion 70,257 ops/sec [69,320..71,132] → 78,703 ops/sec [70,307..81,117] ~ overlap (+12.0%) 83,657 ops/sec [77,166..85,442] → 170,530 ops/sec [162,113..172,218] 🟢 +103.8%
toFixed 40,706 ops/sec [40,544..40,866] → 45,824 ops/sec [45,338..46,130] 🟢 +12.6% 37,563 ops/sec [36,939..37,879] → 72,137 ops/sec [70,255..72,852] 🟢 +92.0%
toString 63,738 ops/sec [61,844..64,335] → 68,912 ops/sec [68,559..69,475] 🟢 +8.1% 64,535 ops/sec [63,932..65,612] → 119,675 ops/sec [117,379..125,257] 🟢 +85.4%
valueOf 95,900 ops/sec [95,616..98,641] → 102,945 ops/sec [100,036..108,968] 🟢 +7.3% 96,677 ops/sec [95,973..97,876] → 173,155 ops/sec [170,074..173,793] 🟢 +79.1%
toPrecision 36,541 ops/sec [36,102..37,160] → 41,006 ops/sec [39,573..41,683] 🟢 +12.2% 34,854 ops/sec [34,420..34,926] → 62,767 ops/sec [61,994..63,838] 🟢 +80.1%
Number.isNaN 111,392 ops/sec [110,697..111,670] → 122,667 ops/sec [118,611..126,066] 🟢 +10.1% 109,414 ops/sec [107,669..110,033] → 212,593 ops/sec [208,867..228,662] 🟢 +94.3%
Number.isFinite 108,698 ops/sec [107,043..109,822] → 119,772 ops/sec [117,340..122,664] 🟢 +10.2% 94,951 ops/sec [94,275..95,340] → 188,618 ops/sec [186,323..190,240] 🟢 +98.6%
Number.isInteger 113,330 ops/sec [112,691..113,912] → 122,039 ops/sec [121,309..130,570] 🟢 +7.7% 103,791 ops/sec [102,161..104,433] → 198,340 ops/sec [194,079..204,699] 🟢 +91.1%
Number.parseInt and parseFloat 89,060 ops/sec [88,407..91,010] → 98,465 ops/sec [96,651..103,425] 🟢 +10.6% 79,114 ops/sec [78,876..79,681] → 149,643 ops/sec [146,868..151,929] 🟢 +89.2%
objects.js — Interp: 🟢 7 · avg +7.2% · Bytecode: 🟢 7 · avg +90.2%
Benchmark Interpreted Δ Bytecode Δ
create simple object 172,424 ops/sec [170,292..174,876] → 179,934 ops/sec [179,278..184,023] 🟢 +4.4% 151,452 ops/sec [150,823..152,461] → 289,190 ops/sec [287,212..289,412] 🟢 +90.9%
create nested object 91,106 ops/sec [90,081..91,863] → 94,724 ops/sec [94,148..95,736] 🟢 +4.0% 66,508 ops/sec [66,403..66,923] → 127,209 ops/sec [125,898..128,076] 🟢 +91.3%
create 50 objects via Array.from 3,160 ops/sec [3,140..3,206] → 3,434 ops/sec [3,332..3,452] 🟢 +8.7% 2,867 ops/sec [2,856..2,876] → 5,489 ops/sec [5,233..5,498] 🟢 +91.4%
property read 179,668 ops/sec [177,987..181,290] → 203,796 ops/sec [201,624..207,649] 🟢 +13.4% 267,294 ops/sec [264,108..268,094] → 498,175 ops/sec [495,432..506,216] 🟢 +86.4%
Object.keys 114,428 ops/sec [113,920..115,913] → 123,349 ops/sec [121,080..123,832] 🟢 +7.8% 120,831 ops/sec [114,772..125,068] → 229,226 ops/sec [224,072..231,652] 🟢 +89.7%
Object.entries 45,299 ops/sec [45,058..45,417] → 47,829 ops/sec [47,110..49,033] 🟢 +5.6% 45,832 ops/sec [45,430..46,088] → 88,250 ops/sec [87,263..88,938] 🟢 +92.6%
spread operator 73,219 ops/sec [72,802..73,915] → 77,966 ops/sec [76,910..78,802] 🟢 +6.5% 66,731 ops/sec [66,277..66,778] → 126,108 ops/sec [124,009..127,826] 🟢 +89.0%
promises.js — Interp: 🟢 7, 🔴 2, 3 unch. · avg +3.9% · Bytecode: 🟢 12 · avg +87.4%
Benchmark Interpreted Δ Bytecode Δ
Promise.resolve(value) 199,113 ops/sec [194,128..200,739] → 211,458 ops/sec [207,186..216,490] 🟢 +6.2% 197,776 ops/sec [196,531..199,285] → 395,297 ops/sec [374,164..402,807] 🟢 +99.9%
new Promise(resolve => resolve(value)) 72,573 ops/sec [72,072..73,109] → 76,045 ops/sec [74,286..79,457] 🟢 +4.8% 88,841 ops/sec [88,285..89,223] → 173,245 ops/sec [170,591..174,891] 🟢 +95.0%
Promise.reject(reason) 202,329 ops/sec [200,543..203,901] → 215,723 ops/sec [213,856..220,394] 🟢 +6.6% 199,833 ops/sec [197,323..201,196] → 391,160 ops/sec [384,129..406,425] 🟢 +95.7%
resolve + then (1 handler) 73,357 ops/sec [73,025..74,904] → 78,482 ops/sec [76,844..79,985] 🟢 +7.0% 82,903 ops/sec [81,444..84,242] → 158,137 ops/sec [154,975..163,843] 🟢 +90.7%
resolve + then chain (3 deep) 31,243 ops/sec [30,910..32,045] → 32,434 ops/sec [32,136..33,167] 🟢 +3.8% 35,440 ops/sec [34,900..35,769] → 66,227 ops/sec [62,009..66,987] 🟢 +86.9%
resolve + then chain (10 deep) 9,809 ops/sec [9,683..9,991] → 10,779 ops/sec [10,748..10,808] 🟢 +9.9% 11,862 ops/sec [11,690..12,055] → 22,388 ops/sec [21,196..22,729] 🟢 +88.7%
reject + catch + then 43,618 ops/sec [42,884..44,922] → 46,731 ops/sec [46,412..47,077] 🟢 +7.1% 47,687 ops/sec [46,908..48,787] → 91,760 ops/sec [91,485..93,050] 🟢 +92.4%
resolve + finally + then 38,276 ops/sec [36,858..41,190] → 39,792 ops/sec [39,042..40,612] ~ overlap (+4.0%) 40,153 ops/sec [39,531..40,954] → 71,893 ops/sec [67,245..75,140] 🟢 +79.0%
Promise.all (5 resolved) 17,283 ops/sec [17,184..17,381] → 16,466 ops/sec [16,245..16,796] 🔴 -4.7% 14,626 ops/sec [14,307..14,914] → 26,599 ops/sec [26,287..27,161] 🟢 +81.9%
Promise.race (5 resolved) 17,385 ops/sec [17,365..17,705] → 17,305 ops/sec [16,347..18,714] ~ overlap (-0.5%) 15,540 ops/sec [15,327..15,611] → 28,703 ops/sec [28,588..28,798] 🟢 +84.7%
Promise.allSettled (5 mixed) 14,313 ops/sec [14,239..14,488] → 14,080 ops/sec [13,622..14,160] 🔴 -1.6% 12,352 ops/sec [12,269..12,532] → 22,002 ops/sec [21,139..22,350] 🟢 +78.1%
Promise.any (5 mixed) 15,962 ops/sec [15,754..17,126] → 16,723 ops/sec [16,298..16,806] ~ overlap (+4.8%) 15,034 ops/sec [14,161..15,799] → 26,325 ops/sec [24,942..27,043] 🟢 +75.1%
regexp.js — Interp: 🟢 2, 🔴 7, 2 unch. · avg -1.8% · Bytecode: 🟢 11 · avg +100.3%
Benchmark Interpreted Δ Bytecode Δ
regex literal creation 8,339 ops/sec [8,116..8,403] → 7,885 ops/sec [7,811..7,994] 🔴 -5.4% 8,117 ops/sec [8,058..8,294] → 12,717 ops/sec [12,482..12,758] 🟢 +56.7%
new RegExp(pattern, flags) 8,206 ops/sec [8,018..8,235] → 7,951 ops/sec [7,797..7,996] 🔴 -3.1% 8,303 ops/sec [8,233..8,490] → 12,516 ops/sec [12,294..12,945] 🟢 +50.8%
RegExp(existingRegex) returns the same regex 237,222 ops/sec [232,420..239,106] → 264,721 ops/sec [259,945..273,297] 🟢 +11.6% 334,641 ops/sec [326,051..335,103] → 659,298 ops/sec [648,337..668,300] 🟢 +97.0%
test() on a global regex 39,524 ops/sec [38,690..39,864] → 44,192 ops/sec [43,332..45,200] 🟢 +11.8% 40,172 ops/sec [39,956..40,412] → 77,647 ops/sec [74,561..80,334] 🟢 +93.3%
exec() with capture groups 15,575 ops/sec [15,333..16,098] → 14,485 ops/sec [14,460..14,667] 🔴 -7.0% 15,937 ops/sec [15,785..16,146] → 33,644 ops/sec [31,556..35,538] 🟢 +111.1%
toString() 189,264 ops/sec [183,817..193,749] → 209,094 ops/sec [191,520..228,783] ~ overlap (+10.5%) 218,461 ops/sec [217,425..220,494] → 432,191 ops/sec [429,246..440,960] 🟢 +97.8%
match() with global regex 1,713 ops/sec [1,710..1,714] → 1,552 ops/sec [1,532..1,556] 🔴 -9.4% 1,696 ops/sec [1,668..1,726] → 3,762 ops/sec [3,581..3,795] 🟢 +121.7%
matchAll() with capture groups 3,705 ops/sec [3,670..3,724] → 3,678 ops/sec [3,606..3,710] ~ overlap (-0.7%) 3,961 ops/sec [3,939..3,994] → 8,404 ops/sec [8,318..8,502] 🟢 +112.2%
replace() with global regex 1,674 ops/sec [1,640..1,721] → 1,530 ops/sec [1,507..1,548] 🔴 -8.6% 1,671 ops/sec [1,655..1,705] → 3,755 ops/sec [3,580..3,863] 🟢 +124.7%
search() with regex 1,844 ops/sec [1,813..1,893] → 1,633 ops/sec [1,621..1,659] 🔴 -11.5% 1,853 ops/sec [1,836..1,875] → 4,187 ops/sec [4,036..4,341] 🟢 +126.0%
split() with regex separator 1,360 ops/sec [1,346..1,419] → 1,250 ops/sec [1,240..1,302] 🔴 -8.0% 1,356 ops/sec [1,333..1,369] → 2,880 ops/sec [2,863..2,961] 🟢 +112.4%
strings.js — Interp: 🟢 18, 1 unch. · avg +9.7% · Bytecode: 🟢 19 · avg +94.7%
Benchmark Interpreted Δ Bytecode Δ
string concatenation 145,303 ops/sec [144,940..147,425] → 156,512 ops/sec [155,099..157,997] 🟢 +7.7% 768,101 ops/sec [764,972..772,120] → 1,403,281 ops/sec [1,378,963..1,457,891] 🟢 +82.7%
template literal 263,863 ops/sec [254,868..270,549] → 280,245 ops/sec [269,156..298,002] ~ overlap (+6.2%) 509,286 ops/sec [505,104..512,468] → 1,008,252 ops/sec [1,000,437..1,018,153] 🟢 +98.0%
string repeat 162,862 ops/sec [161,996..164,348] → 186,365 ops/sec [175,007..188,706] 🟢 +14.4% 180,627 ops/sec [179,292..180,992] → 347,966 ops/sec [330,923..356,454] 🟢 +92.6%
split and join 26,495 ops/sec [25,704..27,381] → 31,120 ops/sec [30,596..31,978] 🟢 +17.5% 29,628 ops/sec [29,502..29,899] → 56,064 ops/sec [54,725..57,522] 🟢 +89.2%
indexOf and includes 50,104 ops/sec [48,809..50,405] → 59,285 ops/sec [58,413..59,638] 🟢 +18.3% 46,303 ops/sec [46,078..49,849] → 94,080 ops/sec [91,883..95,782] 🟢 +103.2%
toUpperCase and toLowerCase 79,085 ops/sec [77,431..81,046] → 93,009 ops/sec [91,984..94,091] 🟢 +17.6% 83,814 ops/sec [83,418..87,517] → 158,716 ops/sec [155,282..159,981] 🟢 +89.4%
slice and substring 48,566 ops/sec [47,897..50,882] → 56,305 ops/sec [56,042..56,814] 🟢 +15.9% 53,709 ops/sec [52,937..55,232] → 99,761 ops/sec [96,417..103,029] 🟢 +85.7%
trim operations 71,067 ops/sec [67,728..72,408] → 74,555 ops/sec [74,272..76,390] 🟢 +4.9% 78,177 ops/sec [77,727..80,356] → 147,162 ops/sec [146,724..147,742] 🟢 +88.2%
replace and replaceAll 49,807 ops/sec [48,625..50,135] → 54,494 ops/sec [53,935..56,665] 🟢 +9.4% 50,199 ops/sec [46,830..50,631] → 92,765 ops/sec [86,526..97,070] 🟢 +84.8%
startsWith and endsWith 47,086 ops/sec [46,648..47,277] → 49,493 ops/sec [49,188..51,894] 🟢 +5.1% 41,680 ops/sec [40,268..42,836] → 81,421 ops/sec [76,196..83,769] 🟢 +95.3%
padStart and padEnd 68,556 ops/sec [68,263..70,183] → 74,476 ops/sec [73,499..75,066] 🟢 +8.6% 67,681 ops/sec [66,284..68,789] → 128,997 ops/sec [123,370..136,495] 🟢 +90.6%
identity tag, no substitutions 153,426 ops/sec [148,652..155,797] → 168,365 ops/sec [165,881..170,671] 🟢 +9.7% 427,754 ops/sec [424,837..433,910] → 870,623 ops/sec [831,208..892,961] 🟢 +103.5%
tag with 1 substitution 31,559 ops/sec [31,337..33,064] → 34,620 ops/sec [34,406..34,725] 🟢 +9.7% 41,285 ops/sec [40,912..41,559] → 82,150 ops/sec [81,113..84,352] 🟢 +99.0%
tag with 3 substitutions 17,573 ops/sec [17,260..17,769] → 18,274 ops/sec [18,099..18,508] 🟢 +4.0% 23,741 ops/sec [23,254..24,019] → 47,610 ops/sec [47,423..47,981] 🟢 +100.5%
tag with 6 substitutions 10,241 ops/sec [10,160..10,263] → 10,872 ops/sec [10,745..11,100] 🟢 +6.2% 14,075 ops/sec [13,927..14,231] → 28,229 ops/sec [27,884..28,620] 🟢 +100.6%
String.raw, no substitutions 218,741 ops/sec [216,269..222,543] → 228,758 ops/sec [225,620..236,935] 🟢 +4.6% 209,707 ops/sec [203,890..210,862] → 415,670 ops/sec [408,040..435,493] 🟢 +98.2%
String.raw, 2 substitutions 152,502 ops/sec [150,390..154,138] → 167,001 ops/sec [166,283..168,728] 🟢 +9.5% 135,645 ops/sec [134,964..136,617] → 271,622 ops/sec [257,321..280,591] 🟢 +100.2%
tag accessing .raw array 61,122 ops/sec [60,524..61,755] → 67,474 ops/sec [66,276..68,194] 🟢 +10.4% 74,031 ops/sec [72,683..74,185] → 143,514 ops/sec [141,527..146,018] 🟢 +93.9%
method as tag (this binding) 23,553 ops/sec [22,829..23,702] → 24,731 ops/sec [24,520..24,909] 🟢 +5.0% 31,845 ops/sec [31,146..32,196] → 64,670 ops/sec [63,396..65,605] 🟢 +103.1%
tsv.js — Interp: 🟢 4, 5 unch. · avg +6.1% · Bytecode: 🟢 9 · avg +92.3%
Benchmark Interpreted Δ Bytecode Δ
parse simple 3-column TSV 43,856 ops/sec [42,829..45,010] → 45,004 ops/sec [42,893..46,280] ~ overlap (+2.6%) 41,841 ops/sec [41,474..42,670] → 84,250 ops/sec [82,210..86,797] 🟢 +101.4%
parse 10-row TSV 11,641 ops/sec [11,427..11,974] → 11,879 ops/sec [11,742..12,259] ~ overlap (+2.0%) 11,299 ops/sec [11,060..11,357] → 22,272 ops/sec [21,666..22,306] 🟢 +97.1%
parse 100-row TSV 1,866 ops/sec [1,823..1,871] → 1,866 ops/sec [1,822..1,926] ~ overlap (+0.0%) 1,726 ops/sec [1,699..1,759] → 3,352 ops/sec [3,286..3,576] 🟢 +94.2%
parse TSV with backslash-escaped fields 8,757 ops/sec [8,600..9,192] → 9,200 ops/sec [8,889..9,374] ~ overlap (+5.1%) 8,805 ops/sec [8,509..8,913] → 16,228 ops/sec [16,108..16,420] 🟢 +84.3%
parse without headers (array of arrays) 5,698 ops/sec [5,669..5,976] → 6,052 ops/sec [5,776..6,185] ~ overlap (+6.2%) 5,380 ops/sec [5,340..5,413] → 10,662 ops/sec [10,559..10,932] 🟢 +98.2%
stringify array of objects 39,825 ops/sec [39,121..41,081] → 44,813 ops/sec [43,635..45,238] 🟢 +12.5% 41,639 ops/sec [41,061..41,757] → 78,551 ops/sec [76,463..79,804] 🟢 +88.6%
stringify array of arrays 11,728 ops/sec [11,514..11,872] → 13,146 ops/sec [12,982..13,228] 🟢 +12.1% 11,621 ops/sec [11,524..11,766] → 21,994 ops/sec [21,820..22,264] 🟢 +89.3%
stringify with values needing escaping 32,120 ops/sec [31,662..32,856] → 35,663 ops/sec [35,233..36,178] 🟢 +11.0% 32,572 ops/sec [32,305..32,586] → 60,335 ops/sec [59,532..66,153] 🟢 +85.2%
parse then stringify 6,836 ops/sec [6,799..6,908] → 7,036 ops/sec [6,977..7,098] 🟢 +2.9% 6,570 ops/sec [6,507..6,686] → 12,650 ops/sec [12,203..12,749] 🟢 +92.6%
typed-arrays.js — Interp: 🟢 20, 2 unch. · avg +18.6% · Bytecode: 🟢 22 · avg +75.9%
Benchmark Interpreted Δ Bytecode Δ
new Int32Array(0) 116,089 ops/sec [113,771..117,709] → 125,847 ops/sec [125,022..127,484] 🟢 +8.4% 128,349 ops/sec [126,285..129,621] → 241,575 ops/sec [233,977..242,753] 🟢 +88.2%
new Int32Array(100) 109,654 ops/sec [108,248..110,444] → 119,976 ops/sec [118,335..120,730] 🟢 +9.4% 122,242 ops/sec [119,414..123,164] → 223,901 ops/sec [219,980..226,659] 🟢 +83.2%
new Int32Array(1000) 82,465 ops/sec [81,960..82,712] → 85,214 ops/sec [82,198..86,837] ~ overlap (+3.3%) 88,190 ops/sec [87,477..88,450] → 157,159 ops/sec [155,947..162,313] 🟢 +78.2%
new Float64Array(100) 105,090 ops/sec [104,815..105,809] → 113,429 ops/sec [112,680..116,319] 🟢 +7.9% 113,869 ops/sec [112,232..114,306] → 209,278 ops/sec [204,443..214,023] 🟢 +83.8%
Int32Array.from([...]) 3,738 ops/sec [3,686..3,859] → 4,155 ops/sec [4,015..4,218] 🟢 +11.1% 3,632 ops/sec [3,571..3,674] → 6,691 ops/sec [6,590..6,732] 🟢 +84.2%
Int32Array.of(1, 2, 3, 4, 5) 116,424 ops/sec [113,956..119,168] → 124,893 ops/sec [122,394..125,546] 🟢 +7.3% 127,162 ops/sec [126,738..128,444] → 227,359 ops/sec [226,594..229,573] 🟢 +78.8%
sequential write 100 elements 1,029 ops/sec [1,000..1,066] → 1,079 ops/sec [1,075..1,111] 🟢 +4.9% 2,400 ops/sec [2,358..2,412] → 4,093 ops/sec [3,860..4,405] 🟢 +70.6%
sequential read 100 elements 1,091 ops/sec [1,074..1,114] → 1,149 ops/sec [1,125..1,167] 🟢 +5.3% 2,403 ops/sec [2,377..2,504] → 4,221 ops/sec [4,141..4,299] 🟢 +75.6%
Float64Array write 100 elements 977 ops/sec [953..988] → 1,024 ops/sec [1,017..1,031] 🟢 +4.8% 2,045 ops/sec [2,022..2,050] → 3,578 ops/sec [3,494..3,619] 🟢 +75.0%
fill(42) 4,329 ops/sec [4,292..4,340] → 4,942 ops/sec [4,918..4,948] 🟢 +14.2% 4,293 ops/sec [4,211..4,342] → 8,178 ops/sec [8,128..8,204] 🟢 +90.5%
slice() 33,881 ops/sec [33,137..35,165] → 37,843 ops/sec [37,336..38,079] 🟢 +11.7% 35,352 ops/sec [34,357..35,926] → 86,631 ops/sec [86,126..86,829] 🟢 +145.1%
map(x => x * 2) 2,110 ops/sec [2,013..2,150] → 2,327 ops/sec [2,294..2,386] 🟢 +10.3% 4,294 ops/sec [3,816..4,312] → 8,446 ops/sec [8,300..8,641] 🟢 +96.7%
filter(x => x > 50) 2,087 ops/sec [2,046..2,159] → 2,363 ops/sec [2,318..2,405] 🟢 +13.3% 4,610 ops/sec [4,583..4,635] → 8,780 ops/sec [8,578..9,105] 🟢 +90.4%
reduce (sum) 2,059 ops/sec [2,044..2,063] → 2,299 ops/sec [2,227..2,354] 🟢 +11.7% 4,078 ops/sec [4,055..4,098] → 8,098 ops/sec [8,001..8,179] 🟢 +98.6%
sort() 20,756 ops/sec [20,505..21,175] → 23,280 ops/sec [22,822..23,556] 🟢 +12.2% 35,512 ops/sec [35,219..35,891] → 48,350 ops/sec [37,452..49,304] 🟢 +36.2%
indexOf() 32,519 ops/sec [32,071..55,720] → 37,824 ops/sec [37,180..38,292] ~ overlap (+16.3%) 55,752 ops/sec [55,598..56,198] → 63,988 ops/sec [63,109..65,148] 🟢 +14.8%
reverse() 37,070 ops/sec [36,212..37,715] → 42,641 ops/sec [42,166..42,840] 🟢 +15.0% 65,372 ops/sec [63,757..65,617] → 69,362 ops/sec [69,037..69,662] 🟢 +6.1%
create view over existing buffer 129,396 ops/sec [128,326..130,999] → 143,840 ops/sec [141,802..145,858] 🟢 +11.2% 235,174 ops/sec [228,930..236,192] → 277,753 ops/sec [272,204..278,756] 🟢 +18.1%
subarray() 148,890 ops/sec [145,386..150,184] → 159,809 ops/sec [157,437..162,050] 🟢 +7.3% 258,778 ops/sec [257,353..260,014] → 497,164 ops/sec [491,385..499,551] 🟢 +92.1%
set() from array 123,631 ops/sec [122,265..125,227] → 220,404 ops/sec [218,334..222,123] 🟢 +78.3% 229,765 ops/sec [228,836..230,427] → 428,435 ops/sec [411,292..428,964] 🟢 +86.5%
for-of loop 1,891 ops/sec [1,879..1,947] → 3,368 ops/sec [3,341..3,372] 🟢 +78.1% 14,521 ops/sec [14,380..14,641] → 29,000 ops/sec [27,967..29,651] 🟢 +99.7%
spread into array 7,203 ops/sec [7,052..7,291] → 12,026 ops/sec [11,987..12,057] 🟢 +67.0% 43,001 ops/sec [42,538..43,386] → 76,453 ops/sec [74,907..78,585] 🟢 +77.8%
uint8array-encoding.js — Interp: 🟢 11, 🔴 2, 5 unch. · avg +2.6% · Bytecode: 🟢 18 · avg +95.2%
Benchmark Interpreted Δ Bytecode Δ
short (5 bytes) 209,699 ops/sec [206,517..216,439] → 224,542 ops/sec [219,730..227,447] 🟢 +7.1% 224,406 ops/sec [216,670..227,549] → 443,324 ops/sec [436,075..451,849] 🟢 +97.6%
medium (450 bytes) 138,255 ops/sec [135,657..139,886] → 138,923 ops/sec [136,467..139,308] ~ overlap (+0.5%) 137,231 ops/sec [135,288..138,417] → 271,859 ops/sec [262,919..275,956] 🟢 +98.1%
large (4096 bytes) 34,927 ops/sec [32,625..35,962] → 33,126 ops/sec [32,163..33,370] ~ overlap (-5.2%) 34,361 ops/sec [34,199..34,662] → 63,351 ops/sec [62,626..64,309] 🟢 +84.4%
base64url alphabet 96,713 ops/sec [96,149..96,965] → 98,221 ops/sec [96,796..103,307] ~ overlap (+1.6%) 89,352 ops/sec [88,841..90,302] → 171,727 ops/sec [167,097..174,300] 🟢 +92.2%
omitPadding 130,180 ops/sec [128,958..131,230] → 143,615 ops/sec [139,553..146,151] 🟢 +10.3% 122,728 ops/sec [121,627..123,286] → 241,792 ops/sec [239,106..245,221] 🟢 +97.0%
short (8 chars) 140,056 ops/sec [138,799..143,016] → 153,460 ops/sec [151,054..154,462] 🟢 +9.6% 137,604 ops/sec [137,372..138,089] → 282,573 ops/sec [281,592..283,866] 🟢 +105.4%
medium (600 chars) 70,100 ops/sec [69,095..70,230] → 77,384 ops/sec [76,733..78,178] 🟢 +10.4% 69,777 ops/sec [69,584..69,857] → 139,562 ops/sec [134,785..146,716] 🟢 +100.0%
large (5464 chars) 14,106 ops/sec [13,602..14,167] → 14,544 ops/sec [14,475..15,064] 🟢 +3.1% 13,798 ops/sec [13,748..14,207] → 29,629 ops/sec [28,514..30,471] 🟢 +114.7%
short (5 bytes) 293,403 ops/sec [206,722..331,197] → 225,898 ops/sec [224,244..239,176] ~ overlap (-23.0%) 237,997 ops/sec [235,128..245,023] → 472,351 ops/sec [468,620..483,169] 🟢 +98.5%
medium (450 bytes) 192,079 ops/sec [191,723..194,558] → 203,578 ops/sec [198,479..211,799] 🟢 +6.0% 125,765 ops/sec [123,261..126,228] → 260,914 ops/sec [260,201..265,614] 🟢 +107.5%
large (4096 bytes) 42,932 ops/sec [42,660..43,489] → 42,245 ops/sec [41,908..42,356] 🔴 -1.6% 25,737 ops/sec [25,458..26,793] → 56,070 ops/sec [55,748..56,650] 🟢 +117.9%
short (10 chars) 243,235 ops/sec [241,763..245,488] → 268,942 ops/sec [267,229..270,797] 🟢 +10.6% 152,201 ops/sec [151,192..154,410] → 308,410 ops/sec [307,944..308,779] 🟢 +102.6%
medium (900 chars) 174,628 ops/sec [173,328..175,879] → 180,996 ops/sec [179,806..184,361] 🟢 +3.6% 150,758 ops/sec [103,843..172,681] → 213,041 ops/sec [204,099..216,749] 🟢 +41.3%
large (8192 chars) 52,389 ops/sec [51,873..52,695] → 48,575 ops/sec [48,504..48,939] 🔴 -7.3% 51,567 ops/sec [51,151..51,955] → 101,920 ops/sec [101,055..102,282] 🟢 +97.6%
setFromBase64 (450 bytes) 101,098 ops/sec [100,729..102,036] → 111,391 ops/sec [111,079..111,942] 🟢 +10.2% 104,053 ops/sec [103,324..104,669] → 211,499 ops/sec [210,237..213,872] 🟢 +103.3%
setFromHex (450 bytes) 38,158 ops/sec [37,777..38,583] → 40,029 ops/sec [39,538..40,388] 🟢 +4.9% 38,374 ops/sec [38,084..38,608] → 64,239 ops/sec [63,949..64,633] 🟢 +67.4%
toBase64 → fromBase64 (450 bytes) 80,759 ops/sec [80,502..80,944] → 84,663 ops/sec [84,373..85,440] 🟢 +4.8% 78,563 ops/sec [78,314..79,301] → 154,886 ops/sec [152,894..156,007] 🟢 +97.1%
toHex → fromHex (450 bytes) 104,131 ops/sec [103,441..104,379] → 104,779 ops/sec [103,751..105,528] ~ overlap (+0.6%) 101,537 ops/sec [100,760..103,530] → 193,488 ops/sec [192,219..194,055] 🟢 +90.6%
weak-collections.js — Interp: 🟢 12, 🔴 2, 1 unch. · avg +1.7% · Bytecode: 🟢 15 · avg +112.1%
Benchmark Interpreted Δ Bytecode Δ
constructor from 50 entries 10,185 ops/sec [10,061..10,266] → 11,214 ops/sec [11,024..11,381] 🟢 +10.1% 9,539 ops/sec [9,269..9,889] → 19,737 ops/sec [19,468..19,953] 🟢 +106.9%
set 50 object keys 3,716 ops/sec [3,673..3,720] → 4,093 ops/sec [3,971..4,171] 🟢 +10.1% 4,232 ops/sec [4,214..4,281] → 8,425 ops/sec [8,125..8,539] 🟢 +99.1%
get lookups (50 entries) 58,077 ops/sec [56,755..58,617] → 62,056 ops/sec [60,973..65,888] 🟢 +6.9% 81,311 ops/sec [80,214..81,859] → 159,672 ops/sec [155,087..162,219] 🟢 +96.4%
has checks (50 entries) 76,974 ops/sec [76,057..78,463] → 80,564 ops/sec [79,165..83,820] 🟢 +4.7% 102,793 ops/sec [100,881..103,219] → 199,727 ops/sec [197,981..201,600] 🟢 +94.3%
delete entries 3,569 ops/sec [3,503..3,622] → 3,739 ops/sec [3,650..3,886] 🟢 +4.8% 4,114 ops/sec [4,040..4,132] → 8,018 ops/sec [7,729..8,174] 🟢 +94.9%
non-registered symbol keys 8,761 ops/sec [8,625..8,765] → 9,305 ops/sec [9,060..9,403] 🟢 +6.2% 9,927 ops/sec [9,843..9,967] → 20,412 ops/sec [20,242..20,519] 🟢 +105.6%
getOrInsert 3,561 ops/sec [3,522..3,696] → 3,906 ops/sec [3,864..3,952] 🟢 +9.7% 3,895 ops/sec [3,828..3,917] → 7,664 ops/sec [7,601..7,709] 🟢 +96.8%
getOrInsertComputed 1,863 ops/sec [1,844..1,869] → 2,013 ops/sec [1,976..2,037] 🟢 +8.1% 2,072 ops/sec [2,056..2,090] → 4,096 ops/sec [4,059..4,108] 🟢 +97.7%
forced gc live-key retention 3,717 ops/sec [3,690..3,804] → 4,088 ops/sec [4,007..4,195] 🟢 +10.0% 3,575 ops/sec [3,548..3,607] → 6,759 ops/sec [6,611..6,823] 🟢 +89.0%
constructor from 50 values 13,112 ops/sec [12,742..13,531] → 13,961 ops/sec [13,707..14,121] 🟢 +6.5% 12,460 ops/sec [12,317..12,672] → 25,947 ops/sec [24,973..27,108] 🟢 +108.2%
add 50 object values 3,972 ops/sec [3,927..4,002] → 4,411 ops/sec [4,370..4,445] 🟢 +11.0% 4,509 ops/sec [4,492..4,550] → 15,207 ops/sec [14,348..15,267] 🟢 +237.2%
has checks (50 values) 122,156 ops/sec [110,179..123,564] → 80,623 ops/sec [78,763..82,725] 🔴 -34.0% 138,159 ops/sec [102,983..179,190] → 354,922 ops/sec [352,827..358,249] 🟢 +156.9%
delete values 17,121 ops/sec [17,050..17,201] → 10,957 ops/sec [10,812..11,045] 🔴 -36.0% 18,422 ops/sec [18,032..18,514] → 38,920 ops/sec [34,519..39,228] 🟢 +111.3%
non-registered symbol values 14,497 ops/sec [14,336..14,690] → 15,040 ops/sec [9,566..15,233] ~ overlap (+3.7%) 17,588 ops/sec [17,454..17,670] → 33,423 ops/sec [32,438..34,454] 🟢 +90.0%
forced gc pruning smoke 7,118 ops/sec [7,023..7,210] → 7,380 ops/sec [7,296..7,501] 🟢 +3.7% 7,282 ops/sec [7,263..7,336] → 14,362 ops/sec [13,379..14,576] 🟢 +97.2%

Deterministic profile diff

Deterministic profile diff: no significant changes.

Measured on ubuntu-latest x64. Benchmark ranges compare cached main-branch min/max ops/sec with the PR run; overlapping ranges are treated as unchanged noise. Percentage deltas are secondary context.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 30, 2026

test262 Conformance

Category Run Passed Δ Pass Failed Pass-rate Δ Rate
built-ins 23,449 16,070 +1 7,374 68.5% ±0pp
harness 116 72 ±0 44 62.1% ±0pp
intl402 3,324 985 +26 2,339 29.6% +0.8pp
language 23,635 14,631 ±0 9,004 61.9% ±0pp
staging 1,484 574 ±0 908 38.7% ±0pp
total 52,008 32,332 +27 19,669 62.2% +0.1pp

Areas closest to 100%

Area Pass rate Δ vs main Passing
built-ins/WeakMap 99.3% ±0pp 140 / 141
language/asi 99.0% ±0pp 101 / 102
built-ins/WeakSet 98.8% ±0pp 84 / 85
Per-test deltas (+27 / -0)

Newly passing (27):

  • built-ins/Number/prototype/toExponential/undefined-fractiondigits.js
  • intl402/Intl/supportedValuesOf/numberingSystems-accepted-by-NumberFormat.js
  • intl402/Intl/supportedValuesOf/numberingSystems-accepted-by-RelativeTimeFormat.js
  • intl402/RelativeTimeFormat/constructor/constructor/options-localeMatcher-invalid.js
  • intl402/RelativeTimeFormat/constructor/constructor/options-numberingSystem-invalid.js
  • intl402/RelativeTimeFormat/constructor/constructor/options-numberingSystem-valid.js
  • intl402/RelativeTimeFormat/constructor/constructor/options-numeric-invalid.js
  • intl402/RelativeTimeFormat/constructor/constructor/options-order.js
  • intl402/RelativeTimeFormat/constructor/constructor/options-style-invalid.js
  • intl402/RelativeTimeFormat/constructor/constructor/options-throwing-getters.js
  • intl402/RelativeTimeFormat/prototype/format/en-us-numbering-systems.js
  • intl402/RelativeTimeFormat/prototype/format/en-us-numeric-always.js
  • intl402/RelativeTimeFormat/prototype/format/en-us-numeric-auto.js
  • intl402/RelativeTimeFormat/prototype/format/en-us-style-short.js
  • intl402/RelativeTimeFormat/prototype/format/pl-pl-style-long.js
  • intl402/RelativeTimeFormat/prototype/format/pl-pl-style-narrow.js
  • intl402/RelativeTimeFormat/prototype/format/pl-pl-style-short.js
  • intl402/RelativeTimeFormat/prototype/format/value-non-finite.js
  • intl402/RelativeTimeFormat/prototype/formatToParts/en-us-numeric-always.js
  • intl402/RelativeTimeFormat/prototype/formatToParts/en-us-numeric-auto.js
  • intl402/RelativeTimeFormat/prototype/formatToParts/en-us-style-short.js
  • intl402/RelativeTimeFormat/prototype/formatToParts/pl-pl-style-long.js
  • intl402/RelativeTimeFormat/prototype/formatToParts/pl-pl-style-narrow.js
  • intl402/RelativeTimeFormat/prototype/formatToParts/pl-pl-style-short.js
  • intl402/RelativeTimeFormat/prototype/formatToParts/value-non-finite.js
  • intl402/RelativeTimeFormat/prototype/resolvedOptions/order.js
  • intl402/RelativeTimeFormat/prototype/resolvedOptions/resolved-numbering-system-unicode-extensions-and-options.js

Steady-state failures are non-blocking; regressions vs the cached main baseline (lower total pass count, or any PASS → non-PASS transition) fail the conformance gate. Measured on ubuntu-latest x64, bytecode mode. Areas grouped by the first two test262 path components; minimum 25 attempted tests, areas already at 100% excluded. Δ vs main compares against the most recent cached main baseline.

@frostney frostney marked this pull request as ready for review May 30, 2026 11:10
@coderabbitai coderabbitai Bot added bug Something isn't working spec compliance Mismatch against official JavaScript/TypeScript specification labels May 30, 2026
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
source/units/Goccia.Values.IntlRelativeTimeFormat.pas (1)

472-525: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Don’t short-circuit numeric: "auto" through a numeric-only repair path.

TryFormatRelativeTimeAutoName only knows English long-form literals, while TryFormatRelativeTimeWithLocalePattern* always emits numeric phrases. With the current ordering, numeric: "auto" loses ICU’s locale/style-specific named forms: Polish falls back to numeric output for -1/0/1, and English short/narrow still returns the long literals from TryFormatRelativeTimeAutoName.

💡 Minimal safe direction
-  if (NumericValue = irtnAuto) and
+  if (NumericValue = irtnAuto) and (StyleValue = irtsLong) and
      TryFormatRelativeTimeAutoName(NumValue, RTF.FLocale, UnitValue, Formatted) then
     Result := TGocciaStringLiteralValue.Create(Formatted)
-  else if TryFormatRelativeTimeWithLocalePattern(NumValue, IsPast, RTF.FLocale,
+  else if (NumericValue = irtnAlways) and
+          TryFormatRelativeTimeWithLocalePattern(NumValue, IsPast, RTF.FLocale,
     RTF.FNumberingSystem, UnitValue, StyleValue, Formatted) then
     Result := TGocciaStringLiteralValue.Create(Formatted)
-  if (NumericValue = irtnAuto) and
+  if (NumericValue = irtnAuto) and (StyleValue = irtsLong) and
      TryFormatRelativeTimeAutoName(NumValue, RTF.FLocale, UnitValue, Formatted) then
   begin
     ...
   end;

-  if TryFormatRelativeTimePartsWithLocalePattern(NumValue, IsPast, RTF.FLocale,
+  if (NumericValue = irtnAlways) and
+     TryFormatRelativeTimePartsWithLocalePattern(NumValue, IsPast, RTF.FLocale,
     RTF.FNumberingSystem, UnitValue, StyleValue, Parts) then
     Exit(FormatPartsToArray(Parts));

Also applies to: 794-799, 836-848

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@source/units/Goccia.Values.IntlRelativeTimeFormat.pas` around lines 472 -
525, The code is short-circuiting numeric:"auto" through the numeric-only path
by calling TryFormatRelativeTimeAutoName too early; change the flow so that any
TryFormatRelativeTimeWithLocalePattern* functions are invoked first for
numeric:"auto" and only if they produce no output fall back to
TryFormatRelativeTimeAutoName, and when falling back ensure
TryFormatRelativeTimeAutoName is only used for English long-form cases (locale
starts with 'en' and style == long) to avoid returning English long literals for
other locales or short/narrow styles.
🧹 Nitpick comments (3)
tests/built-ins/Intl/RelativeTimeFormat/prototype/format.js (1)

8-8: ⚡ Quick win

Consider adding Polish locale test coverage.

The implementation adds locale-pattern formatters for both English and Polish (as noted in the review stack context), but the test suite only covers English. Adding a test case for Polish would verify that the Polish-specific formatting logic works correctly.

📝 Example Polish test case
+  test("formats Polish relative time with locale-specific patterns", () => {
+    const rtf = new Intl.RelativeTimeFormat("pl", { numeric: "always" });
+    
+    expect(rtf.format(-1, "day")).toBe("1 dzień temu");
+    expect(rtf.format(-2, "day")).toBe("2 dni temu");
+    expect(rtf.format(1, "day")).toBe("za 1 dzień");
+  });

Note: Verify the exact expected Polish output strings with the implementation.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/built-ins/Intl/RelativeTimeFormat/prototype/format.js` at line 8, Add a
Polish locale test to the Intl.RelativeTimeFormat.prototype.format suite: inside
the existing describe.runIf block for
"Intl.RelativeTimeFormat.prototype.format", create a test that constructs new
Intl.RelativeTimeFormat('pl', { numeric: 'auto' }) and calls its format for a
few units/values (e.g., 1 day, -1 day, 2 hours) asserting the expected Polish
strings; reference the existing test patterns in the file to mirror structure
and assertions so you cover locale-specific pluralization and word forms for
'pl' alongside the existing English cases.
source/units/Goccia.Intl.Helpers.pas (1)

90-99: ⚡ Quick win

Consider documenting that this strips the entire Unicode extension.

LocaleWithoutUnicodeExtension removes everything from -u- onward, not just specific keywords. For example, "en-US-u-ca-gregory-nu-latn" becomes "en-US", losing both the ca and nu extensions. If the intent is to strip all Unicode extensions when reconciling options, this is correct; otherwise, a more selective approach might be needed. Adding a comment clarifying this behavior would help future maintainers.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@source/units/Goccia.Intl.Helpers.pas` around lines 90 - 99, The function
LocaleWithoutUnicodeExtension currently removes everything from the first "-u-"
onward (i.e., it strips the entire Unicode extension, so
"en-US-u-ca-gregory-nu-latn" becomes "en-US"); update the code by adding a
concise comment above LocaleWithoutUnicodeExtension that documents this behavior
(that it strips the entire Unicode extension) and notes the alternative
(implement selective keyword removal if only certain keys like "ca" or "nu"
should be removed) so future maintainers understand the intended behavior and
can change it if needed.
source/units/Goccia.Values.IntlNumberFormat.pas (1)

583-600: ⚖️ Poor tradeoff

Reconciliation logic strips the entire Unicode extension, not just the nu keyword.

When an explicit numberingSystem option is provided (lines 587-589), the code calls LocaleWithoutUnicodeExtension(FLocale) if the locale's nu extension doesn't match (or is absent). This removes the entire -u- extension, which could discard other Unicode extension keywords like -ca- (calendar) or -hc- (hour cycle).

For example:

  • Input: locale = "en-US-u-ca-gregory-nu-latn", options = { numberingSystem: "arab" }
  • Result: FLocale becomes "en-US" (losing both ca and nu)

If this behavior is intentional (to avoid ambiguity when passing the locale to ICU and also using the skeleton numbering-system/arab token), consider adding a comment explaining why the entire extension is stripped. If other extensions should be preserved, a more selective removal approach would be needed.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@source/units/Goccia.Values.IntlNumberFormat.pas` around lines 583 - 600, The
reconciliation currently calls LocaleWithoutUnicodeExtension(FLocale) which
strips the entire -u- extension (losing other keywords like ca/hc); change the
logic so when FNumberingSystem is set but doesn't match the locale's 'nu'
keyword you remove only the 'nu' key from FLocale instead of the whole Unicode
extension. Implement or use a helper that removes just the 'nu' keyword (e.g.,
RemoveUnicodeExtensionKeyword(FLocale, 'nu')) and call that in the branches that
currently invoke LocaleWithoutUnicodeExtension; keep using
TryGetUnicodeLocaleExtensionKeyword, IsSupportedNumberingSystem,
FNumberingSystem and FLocale to detect and update the locale.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@source/shared/IntlICU.pas`:
- Around line 220-221: The constants UDAT_RELATIVE_YEARS and
UDAT_RELATIVE_QUARTERS are inverted relative to ICU4C; update them so
UDAT_RELATIVE_QUARTERS = 6 and UDAT_RELATIVE_YEARS = 7 (or alternatively change
the mapping in RelativeTimeUnitToICU so irtuYear maps to 7 and irtuQuarter maps
to 6) to match ICU4C's URelativeDateTimeUnit values, and verify the enum cases
irtuYear and irtuQuarter in RelativeTimeUnitToICU are producing the corrected
ICU values.

In `@source/units/Goccia.Values.IntlRelativeTimeFormat.pas`:
- Around line 657-708: The constructor currently strips or ignores the requested
numbering system so FNumberingSystem only affects resolvedOptions() but not
actual formatting; ensure the chosen numbering system is applied to both the ICU
path and the fallback number-splitting path: when calling
TryICUFormatRelativeTime* (and other ICU helpers) pass a locale that includes
the -u-nu- extension for FNumberingSystem or otherwise supply FNumberingSystem
to the ICU call so ICU uses that numbering system, and in the fallback splitter
use FNumberingSystem when building number parts (instead of
DefaultNumberFormatOptions/'latn'); update logic around
FLocale/LocaleWithoutUnicodeExtension, TryGetLocaleNumberingSystemExtension, and
DefaultNumberFormatOptions so that FNumberingSystem is consistently used for
formatting, not just in resolvedOptions().

---

Outside diff comments:
In `@source/units/Goccia.Values.IntlRelativeTimeFormat.pas`:
- Around line 472-525: The code is short-circuiting numeric:"auto" through the
numeric-only path by calling TryFormatRelativeTimeAutoName too early; change the
flow so that any TryFormatRelativeTimeWithLocalePattern* functions are invoked
first for numeric:"auto" and only if they produce no output fall back to
TryFormatRelativeTimeAutoName, and when falling back ensure
TryFormatRelativeTimeAutoName is only used for English long-form cases (locale
starts with 'en' and style == long) to avoid returning English long literals for
other locales or short/narrow styles.

---

Nitpick comments:
In `@source/units/Goccia.Intl.Helpers.pas`:
- Around line 90-99: The function LocaleWithoutUnicodeExtension currently
removes everything from the first "-u-" onward (i.e., it strips the entire
Unicode extension, so "en-US-u-ca-gregory-nu-latn" becomes "en-US"); update the
code by adding a concise comment above LocaleWithoutUnicodeExtension that
documents this behavior (that it strips the entire Unicode extension) and notes
the alternative (implement selective keyword removal if only certain keys like
"ca" or "nu" should be removed) so future maintainers understand the intended
behavior and can change it if needed.

In `@source/units/Goccia.Values.IntlNumberFormat.pas`:
- Around line 583-600: The reconciliation currently calls
LocaleWithoutUnicodeExtension(FLocale) which strips the entire -u- extension
(losing other keywords like ca/hc); change the logic so when FNumberingSystem is
set but doesn't match the locale's 'nu' keyword you remove only the 'nu' key
from FLocale instead of the whole Unicode extension. Implement or use a helper
that removes just the 'nu' keyword (e.g., RemoveUnicodeExtensionKeyword(FLocale,
'nu')) and call that in the branches that currently invoke
LocaleWithoutUnicodeExtension; keep using TryGetUnicodeLocaleExtensionKeyword,
IsSupportedNumberingSystem, FNumberingSystem and FLocale to detect and update
the locale.

In `@tests/built-ins/Intl/RelativeTimeFormat/prototype/format.js`:
- Line 8: Add a Polish locale test to the
Intl.RelativeTimeFormat.prototype.format suite: inside the existing
describe.runIf block for "Intl.RelativeTimeFormat.prototype.format", create a
test that constructs new Intl.RelativeTimeFormat('pl', { numeric: 'auto' }) and
calls its format for a few units/values (e.g., 1 day, -1 day, 2 hours) asserting
the expected Polish strings; reference the existing test patterns in the file to
mirror structure and assertions so you cover locale-specific pluralization and
word forms for 'pl' alongside the existing English cases.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 6701716f-97a4-40ee-b32b-0d6f420733cb

📥 Commits

Reviewing files that changed from the base of the PR and between 9b40421 and 023b68d.

📒 Files selected for processing (8)
  • source/shared/IntlICU.pas
  • source/shared/IntlTypes.pas
  • source/units/Goccia.Intl.Helpers.pas
  • source/units/Goccia.Values.IntlNumberFormat.pas
  • source/units/Goccia.Values.IntlRelativeTimeFormat.pas
  • tests/built-ins/Intl/NumberFormat/prototype/format.js
  • tests/built-ins/Intl/RelativeTimeFormat/prototype/format.js
  • tests/built-ins/Intl/RelativeTimeFormat/prototype/formatToParts.js

Comment thread source/shared/IntlICU.pas
Comment thread source/units/Goccia.Values.IntlRelativeTimeFormat.pas
@frostney frostney merged commit 0746535 into main May 30, 2026
14 checks passed
@frostney frostney deleted the t3code/implement-issue-599 branch May 30, 2026 23:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working spec compliance Mismatch against official JavaScript/TypeScript specification

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Intl: RelativeTimeFormat produces wrong output and empty formatToParts

1 participant