Skip to content

fix(intl): apply Collator comparison options#694

Merged
frostney merged 7 commits into
mainfrom
issue-602-intl-collator-options
Jun 2, 2026
Merged

fix(intl): apply Collator comparison options#694
frostney merged 7 commits into
mainfrom
issue-602-intl-collator-options

Conversation

@frostney
Copy link
Copy Markdown
Owner

@frostney frostney commented Jun 1, 2026

Summary

  • Correct ICU Collator attribute constants for strength and enabled attributes.
  • Thread Intl.Collator's numeric option into ICU comparison and enable UCOL_NUMERIC_COLLATION when requested.
  • Add end-to-end Collator compare coverage for sensitivity and numeric collation behavior.
  • Closes Intl: Collator sensitivity and numeric options not applied #602.

Testing

  • Verified no regressions and confirmed the new feature or bugfix in end-to-end JavaScript/TypeScript tests
    • ./build.pas loader && printf 'console.log(new Intl.Collator("en", {sensitivity: "base"}).compare("a", "A"));\nconsole.log(new Intl.Collator("en", {numeric: true}).compare("2", "10"));\n' | ./build/GocciaScriptLoader
    • ./build.pas testrunner && ./build/GocciaTestRunner tests/built-ins/Intl/Collator/prototype/compare.js
    • ./build/GocciaTestRunner tests/built-ins/Intl/Collator
    • ./fixtures/ffi/build.sh && ./build/GocciaTestRunner tests/built-ins/FFI
    • ./build.pas testrunner && ./build/GocciaTestRunner tests
    • bun scripts/run_test262_suite.ts --suite-dir /tmp/goccia-test262-602 --categories intl402 --filter 'intl402/Collator/**/*sensitivity*' --mode bytecode --jobs 1 --verbose
  • Updated documentation
    • No docs update needed; behavior now matches documented Intl.Collator options.
  • 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

@vercel
Copy link
Copy Markdown

vercel Bot commented Jun 1, 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 Jun 2, 2026 5:21am

Request Review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jun 1, 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: e83d14b5-d0d6-4a8a-a0f2-361ef47cbba9

📥 Commits

Reviewing files that changed from the base of the PR and between e5dcc7b and f8ceba7.

📒 Files selected for processing (3)
  • source/units/Goccia.Builtins.Intl.pas
  • source/units/Goccia.Values.IntlCollator.pas
  • tests/built-ins/Intl/supportedValuesOf.js
💤 Files with no reviewable changes (1)
  • source/units/Goccia.Values.IntlCollator.pas
🚧 Files skipped from review as they are similar to previous changes (2)
  • source/units/Goccia.Builtins.Intl.pas
  • tests/built-ins/Intl/supportedValuesOf.js

📝 Walkthrough

Walkthrough

Adds ICU numeric and case-first collation configuration and Unicode-extension-aware Collator construction; integrates Collator into String.localeCompare; implements stable merge-sort for Array.sort/toSorted; updates supported collation values and adds related tests.

Changes

Collation Options and Unicode Extension Support

Layer / File(s) Summary
ICU Low-Level API Extension
source/shared/IntlICU.pas
TryICUCompareStrings now accepts ANumeric and ACaseFirst, ICU collation constants updated, and implementation sets UCOL_NUMERIC_COLLATION and UCOL_CASE_FIRST before strength/punctuation handling.
IntlCollator unit and helpers
source/units/Goccia.Values.IntlCollator.pas
Adds FICULocale, CompareStrings, helpers to validate/normalize caseFirst and collation aliases, utilities to extract/manipulate -u- keys (kn,kf,co), and constructor logic reconciling options and extensions to build FICULocale.
Intl Builtins and Constructor Argument Handling
source/units/Goccia.Builtins.Intl.pas
New helper to canonicalize Collator locale argument; Collator constructor now uses that helper and coerces options with ToObject; supportedValuesOf('collation') list updated.
String.localeCompare Integration
source/units/Goccia.Values.StringObjectValue.pas
Adds IntlCollator dependency and LocaleCompareArgumentToLocale helper; StringLocaleCompare builds a TGocciaIntlCollator from locale/options and delegates compare to Collator.CompareStrings.
Collation Tests
tests/built-ins/Intl/Collator/*, tests/built-ins/Intl/supportedValuesOf.js, tests/built-ins/String/prototype/localeCompare.js
Tests extended for constructor locale argument types and validation, resolvedOptions() (u-kn/u-kf), sensitivity and numeric compare behavior, supported-values validation, and localeCompare option handling.

Stable Array Sorting

Layer / File(s) Summary
Stable Merge-Sort Implementation
source/units/Goccia.Values.ArrayValue.pas
Introduces StableSortElements and StableSortElementsDefault implementing stable merge-sort that preserves original order on equality.
Array.prototype.sort and toSorted Methods
source/units/Goccia.Values.ArrayValue.pas
ArrayToSorted and ArraySort now use stable merge-sort helpers for comparator-present and comparator-absent paths; undefined handling made deterministic.
Array Sorting Tests
tests/built-ins/Array/prototype/sort.js, tests/built-ins/Array/prototype/toSorted.js
Adds tests asserting stable ordering when comparator returns 0 and that undefined values are placed after defined elements.

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant IntlCollator
  participant UnicodeExt as UnicodeExtensionParser
  participant ICU as ICUCollator
  Client->>IntlCollator: new Intl.Collator(locale, {numeric, caseFirst})
  IntlCollator->>UnicodeExt: extract -u- keys (kn,kf,co)
  UnicodeExt-->>IntlCollator: return key values
  IntlCollator->>IntlCollator: reconcile options vs extensions, build FICULocale
  Client->>IntlCollator: compare(str1, str2)
  IntlCollator->>ICU: TryICUCompareStrings(FICULocale, str1, str2, ASensitivity, AIgnorePunctuation, ANumeric, ACaseFirst)
  ICU-->>IntlCollator: comparison result
  IntlCollator-->>Client: numeric/case-first aware result
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title 'fix(intl): apply Collator comparison options' clearly and concisely describes the main change: applying previously ignored Collator options like sensitivity and numeric to ICU comparisons.
Description check ✅ Passed The PR description follows the template with a clear Summary section, linked issue reference, and comprehensive Testing section with verified test coverage across multiple test suites.
Linked Issues check ✅ Passed The PR addresses all coding requirements from issue #602: corrects ICU strength constants mapping, threads the numeric option through ICU comparison, and enables UCOL_NUMERIC_COLLATION when requested.
Out of Scope Changes check ✅ Passed All changes are directly scoped to fixing Collator options application. Refactoring of locale handling, array sorting stability improvements, and extended test coverage are necessary to support or validate the core fix.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ 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 Jun 1, 2026

Suite Timing

Test Runner (interpreted: 9,875 passed; bytecode: 9,875 passed)
Metric Interpreted Bytecode
Total 9875 9875
Passed 9875 ✅ 9875 ✅
Workers 4 4
Test Duration 3.61s 4.01s
Lex (cumulative) 450.4ms 448.3ms
Parse (cumulative) 311.8ms 312.2ms
Compile (cumulative) 639.4ms
Execute (cumulative) 4.87s 5.83s
Engine Total (cumulative) 5.63s 7.23s
Lex (avg/worker) 112.6ms 112.1ms
Parse (avg/worker) 78.0ms 78.1ms
Compile (avg/worker) 159.8ms
Execute (avg/worker) 1.22s 1.46s
Engine Total (avg/worker) 1.41s 1.81s

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 287.47 MiB 279.88 MiB
GC Peak Live 287.48 MiB 279.89 MiB
GC Allocated During Run 292.01 MiB 284.42 MiB
GC Limit 7.81 GiB 7.81 GiB
GC Collections 1 1
GC Collected Objects 87 87
Heap Start Allocated 160.6 KiB 160.6 KiB
Heap End Allocated 1.54 MiB 1.54 MiB
Heap Delta Allocated 1.38 MiB 1.38 MiB
Heap Delta Free 890.4 KiB 890.4 KiB
Benchmarks (interpreted: 407; bytecode: 407)
Metric Interpreted Bytecode
Total 407 407
Workers 4 4
Duration 2.43min 2.30min

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 118.54 MiB 87.74 MiB
GC Allocated During Run 16.66 GiB 9.47 GiB
GC Limit 7.81 GiB 7.81 GiB
GC Collections 2,816 2,652
GC Collected Objects 265,373,374 212,124,345
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 Jun 1, 2026

Benchmark Results

407 benchmarks

Interpreted: 🟢 348 improved · 🔴 27 regressed · 32 unchanged · avg +10.7%
Bytecode: 🟢 67 improved · 🔴 218 regressed · 122 unchanged · avg -1.8%

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

Deterministic profile diff

arrays

  • 🔴 OP_GET_LOCAL: 1,537 → 1,455 (-5.3%)
  • 🔴 OP_RETURN: 1,417 → 1,376 (-2.9%)
  • Total instructions: 8,866 → 8,702 (-1.8%)

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 Jun 1, 2026

test262 Conformance

Category Run Passed Δ Pass Failed Pass-rate Δ Rate
built-ins 23,449 16,077 +8 7,367 68.6% ±0pp
harness 116 72 ±0 44 62.1% ±0pp
intl402 3,324 998 +13 2,326 30.0% +0.4pp
language 23,635 14,631 ±0 9,004 61.9% ±0pp
staging 1,484 576 +2 906 38.8% +0.1pp
total 52,008 32,354 +23 19,647 62.2% ±0pp

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 (+23 / -0)

Newly passing (23):

  • built-ins/Array/prototype/sort/S15.4.4.11_A1.4_T2.js
  • built-ins/Array/prototype/sort/S15.4.4.11_A2.2_T3.js
  • built-ins/Array/prototype/sort/S15.4.4.11_A3_T2.js
  • built-ins/Array/prototype/sort/stability-11-elements.js
  • built-ins/Array/prototype/sort/stability-2048-elements.js
  • built-ins/Array/prototype/sort/stability-5-elements.js
  • built-ins/Array/prototype/sort/stability-513-elements.js
  • built-ins/Number/prototype/toExponential/undefined-fractiondigits.js
  • intl402/Collator/missing-unicode-ext-value-defaults-to-true.js
  • intl402/Collator/numeric-and-caseFirst.js
  • intl402/Collator/prototype/compare/non-normative-basic.js
  • intl402/Collator/prototype/compare/non-normative-sensitivity.js
  • intl402/Collator/prototype/resolvedOptions/resolved-case-first-unicode-extensions-and-options.js
  • intl402/Collator/prototype/resolvedOptions/resolved-numeric-unicode-extensions-and-options.js
  • intl402/Collator/test-option-localeMatcher.js
  • intl402/Collator/test-option-numeric-and-caseFirst.js
  • intl402/Collator/test-option-sensitivity.js
  • intl402/Collator/test-option-usage.js
  • intl402/Intl/supportedValuesOf/collations.js
  • intl402/String/prototype/localeCompare/default-options-object-prototype.js
  • intl402/String/prototype/localeCompare/throws-same-exceptions-as-Collator.js
  • staging/sm/Array/sort_native_string_nan.js
  • staging/sm/Array/sort_small.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 June 2, 2026 04:33
@coderabbitai coderabbitai Bot added bug Something isn't working spec compliance Mismatch against official JavaScript/TypeScript specification labels Jun 2, 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: 3

🤖 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/units/Goccia.Values.ArrayValue.pas`:
- Around line 896-917: StableSortElementsDefault currently uses DefaultCompare
on the raw values which can place "undefined" before strings; update the default
stable sort path to always treat undefined as greater than any other value so
undefineds are moved to the end. In practice, modify the comparison used inside
StableSortElementsDefault (and the analogous routines at the other occurrences)
to check for an undefined TGocciaValue (use whatever sentinel/variant check
exists for undefined in TGocciaValue/TGocciaValueList) and consider undefined >
any non-undefined value; if both are undefined treat them equal, otherwise defer
to DefaultCompare for non-undefined vs non-undefined comparisons. Ensure the
change is applied to the other same-pattern sorting functions referenced in the
review.

In `@source/units/Goccia.Values.IntlCollator.pas`:
- Around line 485-491: In TGocciaIntlCollatorValue.Create, after reading
'caseFirst' (CaseFirstOptionPresent and Ignored via TryReadStringOption) and
after the existing NUL check, validate Ignored against permitted values using
IsValidCaseFirstValue; if invalid call
ThrowRangeError(Format(SErrorIntlInvalidOption, [Ignored, 'caseFirst'])); only
then assign FCaseFirst := Ignored so IntlCollatorResolvedOptions returns a
validated value (mirror the existing -u-kf handling logic).

In `@source/units/Goccia.Values.StringObjectValue.pas`:
- Around line 1955-1960: TGocciaStringObjectValue.StringLocaleCompare currently
only accepts the third argument when it's already a TGocciaObjectValue, ignoring
primitive option values; change the logic so when AArgs.Length > 2 and the third
argument is not the undefined value you call the runtime ToObject coercion (or
equivalent helper) to convert primitives to an object and assign that to Options
(if it's already a TGocciaObjectValue keep the cast), so that Option property
access follows ECMA‑402 semantics before passing Options into
TGocciaIntlCollatorValue.Create.
🪄 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: 87843f84-7ad2-4a18-b2de-17e0714d2dfe

📥 Commits

Reviewing files that changed from the base of the PR and between 05ab54c and dddd46a.

📒 Files selected for processing (10)
  • source/shared/IntlICU.pas
  • source/units/Goccia.Builtins.Intl.pas
  • source/units/Goccia.Values.ArrayValue.pas
  • source/units/Goccia.Values.IntlCollator.pas
  • source/units/Goccia.Values.StringObjectValue.pas
  • tests/built-ins/Array/prototype/sort.js
  • tests/built-ins/Intl/Collator/constructor.js
  • tests/built-ins/Intl/Collator/prototype/compare.js
  • tests/built-ins/Intl/supportedValuesOf.js
  • tests/built-ins/String/prototype/localeCompare.js
💤 Files with no reviewable changes (1)
  • source/units/Goccia.Builtins.Intl.pas

Comment thread source/units/Goccia.Values.ArrayValue.pas
Comment thread source/units/Goccia.Values.IntlCollator.pas
Comment thread source/units/Goccia.Values.StringObjectValue.pas
@coderabbitai coderabbitai Bot added the internal Refactoring, CI, tooling, cleanup label Jun 2, 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.

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.Builtins.Intl.pas (1)

215-229: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Fix Intl.supportedValuesOf('collation') to not under-report supported collations
source/units/Goccia.Builtins.Intl.pas lists 12 collation identifiers (compat, dict, emoji, eor, phonebk, phonetic, pinyin, searchjl, stroke, trad, unihan, zhuyin), but source/units/Goccia.Values.IntlCollator.pas’s SupportedCollations contains 17 identifiers and also includes big5han, direct, ducet, gb2312, and reformed. Update the supportedValuesOf('collation') output to match (or explicitly document why these five are omitted).

🤖 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.Builtins.Intl.pas` around lines 215 - 229, The collation
list in the Key = 'collation' branch of AddString calls in
Goccia.Builtins.Intl.pas is missing five identifiers present in
Goccia.Values.IntlCollator.pas.SupportedCollations; update the block that
currently adds
'compat','dict','emoji','eor','phonebk','phonetic','pinyin','searchjl','stroke','trad','unihan','zhuyin'
to also AddString('big5han'), AddString('direct'), AddString('ducet'),
AddString('gb2312'), and AddString('reformed') so supportedValuesOf('collation')
matches SupportedCollations (or alternatively add a comment documenting why any
identifiers are intentionally omitted).
🧹 Nitpick comments (1)
source/units/Goccia.Builtins.Intl.pas (1)

708-757: ⚖️ Poor tradeoff

Consider extracting the locale-argument helper to a shared unit.

CollatorLocaleArgumentToLocale duplicates the same logic as LocaleCompareArgumentToLocale in Goccia.Values.StringObjectValue.pas (lines 131–180). Both validate/canonicalize locale arguments with identical type checks and duplicate--u--extension handling.

Since both implementations are identical and this PR is focused on collation options, defer extraction to a future refactor (e.g., move to IntlLocaleResolver or a new shared locale-parsing utility). For now, the duplication is acceptable.

🤖 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.Builtins.Intl.pas` around lines 708 - 757, The
locale-parsing/canonicalization logic in CollatorLocaleArgumentToLocale
duplicates LocaleCompareArgumentToLocale; add a short comment/TODO at the top of
CollatorLocaleArgumentToLocale (and optionally LocaleCompareArgumentToLocale)
noting the duplication and that this logic should be extracted into a shared
IntlLocaleResolver/locale-parsing utility in a future refactor, referencing the
function names CollatorLocaleArgumentToLocale and LocaleCompareArgumentToLocale
so maintainers can find and consolidate the code later.
🤖 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.

Outside diff comments:
In `@source/units/Goccia.Builtins.Intl.pas`:
- Around line 215-229: The collation list in the Key = 'collation' branch of
AddString calls in Goccia.Builtins.Intl.pas is missing five identifiers present
in Goccia.Values.IntlCollator.pas.SupportedCollations; update the block that
currently adds
'compat','dict','emoji','eor','phonebk','phonetic','pinyin','searchjl','stroke','trad','unihan','zhuyin'
to also AddString('big5han'), AddString('direct'), AddString('ducet'),
AddString('gb2312'), and AddString('reformed') so supportedValuesOf('collation')
matches SupportedCollations (or alternatively add a comment documenting why any
identifiers are intentionally omitted).

---

Nitpick comments:
In `@source/units/Goccia.Builtins.Intl.pas`:
- Around line 708-757: The locale-parsing/canonicalization logic in
CollatorLocaleArgumentToLocale duplicates LocaleCompareArgumentToLocale; add a
short comment/TODO at the top of CollatorLocaleArgumentToLocale (and optionally
LocaleCompareArgumentToLocale) noting the duplication and that this logic should
be extracted into a shared IntlLocaleResolver/locale-parsing utility in a future
refactor, referencing the function names CollatorLocaleArgumentToLocale and
LocaleCompareArgumentToLocale so maintainers can find and consolidate the code
later.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: a9e195a1-504b-4623-90be-e9a2be6f5e5d

📥 Commits

Reviewing files that changed from the base of the PR and between dddd46a and e5dcc7b.

📒 Files selected for processing (8)
  • source/units/Goccia.Builtins.Intl.pas
  • source/units/Goccia.Values.ArrayValue.pas
  • source/units/Goccia.Values.IntlCollator.pas
  • source/units/Goccia.Values.StringObjectValue.pas
  • tests/built-ins/Array/prototype/sort.js
  • tests/built-ins/Array/prototype/toSorted.js
  • tests/built-ins/Intl/Collator/constructor.js
  • tests/built-ins/String/prototype/localeCompare.js
✅ Files skipped from review due to trivial changes (1)
  • tests/built-ins/Array/prototype/toSorted.js
🚧 Files skipped from review as they are similar to previous changes (2)
  • tests/built-ins/Intl/Collator/constructor.js
  • source/units/Goccia.Values.IntlCollator.pas

@frostney frostney merged commit 3418795 into main Jun 2, 2026
14 checks passed
@frostney frostney deleted the issue-602-intl-collator-options branch June 2, 2026 05:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working internal Refactoring, CI, tooling, cleanup spec compliance Mismatch against official JavaScript/TypeScript specification

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Intl: Collator sensitivity and numeric options not applied

1 participant