Skip to content

Generate full Unicode property tables for regex \p{} escapes#630

Merged
frostney merged 6 commits into
mainfrom
t3code/task-607
May 11, 2026
Merged

Generate full Unicode property tables for regex \p{} escapes#630
frostney merged 6 commits into
mainfrom
t3code/task-607

Conversation

@frostney
Copy link
Copy Markdown
Owner

Summary

  • Replace the 12 hardcoded ASCII-approximate \p{} property ranges with ICU-first UnicodeSet queries backed by a generated UCD binary resource fallback, expanding support to the full ES2026 §22.2.2.9 property set (General_Category, Script, Script_Extensions, and all binary properties with full alias resolution).
  • Add \p{PropertyName=PropertyValue} syntax parsing (\p{Script=Greek}, \p{gc=Lu}, etc.) and increase MAX_CHAR_RANGES from 512 to 2048 for full Unicode coverage.
  • Follow the established Temporal/Intl pattern: ICU primary via uset_applyPropertyAlias + embedded UCD binary resource fallback + GOCCIA_REGEXP_NO_EMBEDDED_UCD compile-time opt-out.

Closes #607

Testing

  • Verified no regressions and confirmed the new feature or bugfix in end-to-end JavaScript/TypeScript tests
  • Updated documentation
  • 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

Replace the 12 hardcoded ASCII-approximate property ranges with ICU-first
UnicodeSet queries backed by a generated UCD binary resource fallback.
Adds \p{Script=Greek}, \p{General_Category=...}, \p{Emoji}, and all ES2026
§22.2.2.9 properties with full alias resolution.

Closes #607

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@vercel
Copy link
Copy Markdown

vercel Bot commented May 10, 2026

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

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
gocciascript-homepage Ignored Ignored Preview May 10, 2026 11:33pm

Request Review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 10, 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: d3686d8a-d06d-4676-8b0c-580878bc71d9

📥 Commits

Reviewing files that changed from the base of the PR and between 225d85d and 4cf0173.

📒 Files selected for processing (1)
  • source/units/Goccia.RegExp.Compiler.pas

📝 Walkthrough

Walkthrough

Adds ICU-backed and embedded Unicode property range resolution, a Node.js generator that creates a compact UCD resource and Pascal unit, integrates dynamic property lookup into the RegExp compiler (replacing hardcoded maps), and documents the generation/build fallback.

Changes

Unicode Property Data Integration for RegExp

Layer / File(s) Summary
Configuration and Public Types
source/units/Goccia.inc, source/shared/UnicodeICU.pas
Adds GOCCIA_REGEXP_EMBEDDED_UCD compile flag and public TUnicodePropertyRange / TUnicodePropertyRangeArray types.
ICU Dynamic Loading and Property Resolution
source/shared/UnicodeICU.pas
Dynamically loads ICU UnicodeSet symbols under a critical section and implements TryICUGetUnicodePropertyRanges to query ICU and build range arrays.
Embedded Unicode Data Resource Handler
source/units/Goccia.RegExp.UnicodeData.pas
Parses/validates embedded binary resource header, performs binary-search entry lookup by key, decodes fixed-size lo/hi range records, and caches bytes with thread synchronization; stub returns False when not embedded.
Unicode Data Generation Script
scripts/generate-unicode-data.js
CLI script downloads UCD files, parses categories/scripts/emoji, merges and deduplicates ranges into blobs, writes a .res via fpcres, and generates a corresponding .pas unit with metadata.
RegExp Compiler Property Resolution
source/units/Goccia.RegExp.Compiler.pas
Replaces hardcoded Unicode property mapping with dynamic resolution via TryICUGetUnicodePropertyRanges / TryGetUnicodePropertyRanges, supports prop=value and alternate keys (e.g., gc/<name>), and raises on capacity overflow; increases MAX_CHAR_RANGES to 2048.
Build System Documentation
docs/build-system.md
New subsection describing the Generated Unicode Data workflow, fpcres requirement, embedded UCD fallback, and GOCCIA_REGEXP_NO_EMBEDDED_UCD opt-out define.

Sequence Diagram(s)

sequenceDiagram
  participant Compiler as RegExp Compiler
  participant UnicodeICU as UnicodeICU Unit
  participant ICU as ICU Library

  Compiler->>UnicodeICU: TryICUGetUnicodePropertyRanges(property, value)
  UnicodeICU->>UnicodeICU: TryLoadFunctions (one-time, critical section)
  UnicodeICU->>ICU: uset_openEmpty(), uset_applyPropertyAlias(...)
  UnicodeICU->>ICU: uset_getItemCount(), uset_getItem(...)
  ICU-->>UnicodeICU: count and range pairs
  UnicodeICU-->>Compiler: TUnicodePropertyRangeArray
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • frostney/GocciaScript#621: Implements Unicode-set parsing and related RegExp compiler updates; overlaps with property resolution work.
  • frostney/GocciaScript#208: Implements Unicode-mode preprocessing and \p/\P expansion; directly relates to the property lookup APIs added here.
  • frostney/GocciaScript#585: Large RegExp backend changes that intersect at the compiler integration layer modified in this PR.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately and concisely summarizes the main change: generating full Unicode property tables for regex \p{} escapes.
Description check ✅ Passed The description clearly outlines the main change, implementation approach (ICU-first with UCD fallback), and new syntax support. Testing checklist is mostly completed.
Linked Issues check ✅ Passed The PR addresses issue #607 requirements: replaces 12 hardcoded properties with full ES2026 §22.2.2.9 property set, adds Property=Value syntax parsing, and follows the generated-data pattern.
Out of Scope Changes check ✅ Passed All changes are directly in scope: Unicode data generation script, ICU integration unit, compiler updates, fallback resource handling, and documentation are all aligned with issue #607 objectives.

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


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

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 10, 2026

Suite Timing

Test Runner (interpreted: 9,271 passed; bytecode: 9,271 passed)
Metric Interpreted Bytecode
Total 9271 9271
Passed 9271 ✅ 9271 ✅
Workers 4 4
Test Duration 2.20s 2.10s
Lex (cumulative) 260.3ms 161.8ms
Parse (cumulative) 283.5ms 266.2ms
Compile (cumulative) 532.3ms
Execute (cumulative) 2.61s 2.02s
Engine Total (cumulative) 3.15s 2.98s
Lex (avg/worker) 65.1ms 40.4ms
Parse (avg/worker) 70.9ms 66.5ms
Compile (avg/worker) 133.1ms
Execute (avg/worker) 652.6ms 505.3ms
Engine Total (avg/worker) 788.5ms 745.3ms

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 244.87 MiB 239.29 MiB
GC Peak Live 244.87 MiB 239.30 MiB
GC Allocated During Run 248.78 MiB 243.19 MiB
GC Limit 7.81 GiB 7.81 GiB
GC Collections 1 1
GC Collected Objects 88 88
Heap Start Allocated 149.3 KiB 149.3 KiB
Heap End Allocated 2.54 MiB 2.54 MiB
Heap Delta Allocated 2.39 MiB 2.39 MiB
Heap Delta Free 140.0 KiB 140.0 KiB
Benchmarks (interpreted: 407; bytecode: 407)
Metric Interpreted Bytecode
Total 407 407
Workers 4 4
Duration 2.53min 2.44min

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.65 MiB 3.64 MiB
GC Peak Live 109.70 MiB 97.76 MiB
GC Allocated During Run 15.15 GiB 13.43 GiB
GC Limit 7.81 GiB 7.81 GiB
GC Collections 2,817 2,653
GC Collected Objects 280,508,206 319,069,440
Heap Start Allocated 2.29 MiB 2.29 MiB
Heap End Allocated 2.29 MiB 2.29 MiB
Heap Delta Allocated 128 B 128 B

Measured on ubuntu-latest x64.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 10, 2026

Benchmark Results

407 benchmarks

Interpreted: 🟢 40 improved · 🔴 253 regressed · 114 unchanged · avg -2.9%
Bytecode: 🟢 391 improved · 🔴 9 regressed · 7 unchanged · avg +28.4%

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

Deterministic profile diff

Deterministic profile diff: no significant changes.

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

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 10, 2026

test262 Conformance

Category Run Passed Δ Pass Failed Pass-rate Δ Rate
built-ins 23,449 14,919 +293 8,524 63.6% +1.2pp
harness 116 71 ±0 45 61.2% ±0pp
intl402 3,324 691 ±0 2,633 20.8% ±0pp
language 23,635 12,575 ±0 11,060 53.2% ±0pp
staging 1,484 488 ±0 994 32.9% ±0pp
total 52,008 28,744 +293 23,256 55.3% +0.6pp

Areas closest to 100%

Area Pass rate Δ vs main Passing
built-ins/WeakSet 98.8% ±0pp 84 / 85
built-ins/WeakMap 98.6% ±0pp 139 / 141
language/asi 97.1% ±0pp 99 / 102
Per-test deltas (+293 / -0)

Newly passing (293):

  • built-ins/Number/prototype/toExponential/undefined-fractiondigits.js
  • built-ins/RegExp/property-escapes/generated/Any.js
  • built-ins/RegExp/property-escapes/generated/ASCII_Hex_Digit.js
  • built-ins/RegExp/property-escapes/generated/Bidi_Control.js
  • built-ins/RegExp/property-escapes/generated/Bidi_Mirrored.js
  • built-ins/RegExp/property-escapes/generated/Dash.js
  • built-ins/RegExp/property-escapes/generated/Default_Ignorable_Code_Point.js
  • built-ins/RegExp/property-escapes/generated/Deprecated.js
  • built-ins/RegExp/property-escapes/generated/Emoji_Component.js
  • built-ins/RegExp/property-escapes/generated/Emoji_Modifier_Base.js
  • built-ins/RegExp/property-escapes/generated/Emoji_Modifier.js
  • built-ins/RegExp/property-escapes/generated/General_Category_-_Close_Punctuation.js
  • built-ins/RegExp/property-escapes/generated/General_Category_-_Connector_Punctuation.js
  • built-ins/RegExp/property-escapes/generated/General_Category_-_Control.js
  • built-ins/RegExp/property-escapes/generated/General_Category_-_Dash_Punctuation.js
  • built-ins/RegExp/property-escapes/generated/General_Category_-_Enclosing_Mark.js
  • built-ins/RegExp/property-escapes/generated/General_Category_-_Final_Punctuation.js
  • built-ins/RegExp/property-escapes/generated/General_Category_-_Format.js
  • built-ins/RegExp/property-escapes/generated/General_Category_-_Initial_Punctuation.js
  • built-ins/RegExp/property-escapes/generated/General_Category_-_Line_Separator.js
  • built-ins/RegExp/property-escapes/generated/General_Category_-_Modifier_Symbol.js
  • built-ins/RegExp/property-escapes/generated/General_Category_-_Open_Punctuation.js
  • built-ins/RegExp/property-escapes/generated/General_Category_-_Other_Number.js
  • built-ins/RegExp/property-escapes/generated/General_Category_-_Paragraph_Separator.js
  • built-ins/RegExp/property-escapes/generated/General_Category_-_Private_Use.js
  • built-ins/RegExp/property-escapes/generated/General_Category_-_Separator.js
  • built-ins/RegExp/property-escapes/generated/General_Category_-_Space_Separator.js
  • built-ins/RegExp/property-escapes/generated/General_Category_-_Surrogate.js
  • built-ins/RegExp/property-escapes/generated/General_Category_-_Titlecase_Letter.js
  • built-ins/RegExp/property-escapes/generated/Hex_Digit.js
  • built-ins/RegExp/property-escapes/generated/IDS_Binary_Operator.js
  • built-ins/RegExp/property-escapes/generated/IDS_Trinary_Operator.js
  • built-ins/RegExp/property-escapes/generated/Join_Control.js
  • built-ins/RegExp/property-escapes/generated/Logical_Order_Exception.js
  • built-ins/RegExp/property-escapes/generated/Noncharacter_Code_Point.js
  • built-ins/RegExp/property-escapes/generated/Pattern_Syntax.js
  • built-ins/RegExp/property-escapes/generated/Pattern_White_Space.js
  • built-ins/RegExp/property-escapes/generated/Quotation_Mark.js
  • built-ins/RegExp/property-escapes/generated/Radical.js
  • built-ins/RegExp/property-escapes/generated/Regional_Indicator.js
  • built-ins/RegExp/property-escapes/generated/Script_-_Adlam.js
  • built-ins/RegExp/property-escapes/generated/Script_-_Ahom.js
  • built-ins/RegExp/property-escapes/generated/Script_-_Anatolian_Hieroglyphs.js
  • built-ins/RegExp/property-escapes/generated/Script_-_Armenian.js
  • built-ins/RegExp/property-escapes/generated/Script_-_Avestan.js
  • built-ins/RegExp/property-escapes/generated/Script_-_Balinese.js
  • built-ins/RegExp/property-escapes/generated/Script_-_Bamum.js
  • built-ins/RegExp/property-escapes/generated/Script_-_Bassa_Vah.js
  • built-ins/RegExp/property-escapes/generated/Script_-_Batak.js
  • built-ins/RegExp/property-escapes/generated/Script_-_Bengali.js
  • built-ins/RegExp/property-escapes/generated/Script_-_Bhaiksuki.js
  • built-ins/RegExp/property-escapes/generated/Script_-_Bopomofo.js
  • built-ins/RegExp/property-escapes/generated/Script_-_Brahmi.js
  • built-ins/RegExp/property-escapes/generated/Script_-_Braille.js
  • built-ins/RegExp/property-escapes/generated/Script_-_Buginese.js
  • built-ins/RegExp/property-escapes/generated/Script_-_Buhid.js
  • built-ins/RegExp/property-escapes/generated/Script_-_Canadian_Aboriginal.js
  • built-ins/RegExp/property-escapes/generated/Script_-_Carian.js
  • built-ins/RegExp/property-escapes/generated/Script_-_Caucasian_Albanian.js
  • built-ins/RegExp/property-escapes/generated/Script_-_Chakma.js
  • built-ins/RegExp/property-escapes/generated/Script_-_Cham.js
  • built-ins/RegExp/property-escapes/generated/Script_-_Cherokee.js
  • built-ins/RegExp/property-escapes/generated/Script_-_Chorasmian.js
  • built-ins/RegExp/property-escapes/generated/Script_-_Coptic.js
  • built-ins/RegExp/property-escapes/generated/Script_-_Cuneiform.js
  • built-ins/RegExp/property-escapes/generated/Script_-_Cypriot.js
  • built-ins/RegExp/property-escapes/generated/Script_-_Cypro_Minoan.js
  • built-ins/RegExp/property-escapes/generated/Script_-_Cyrillic.js
  • built-ins/RegExp/property-escapes/generated/Script_-_Deseret.js
  • built-ins/RegExp/property-escapes/generated/Script_-_Devanagari.js
  • built-ins/RegExp/property-escapes/generated/Script_-_Dives_Akuru.js
  • built-ins/RegExp/property-escapes/generated/Script_-_Dogra.js
  • built-ins/RegExp/property-escapes/generated/Script_-_Duployan.js
  • built-ins/RegExp/property-escapes/generated/Script_-_Egyptian_Hieroglyphs.js
  • built-ins/RegExp/property-escapes/generated/Script_-_Elbasan.js
  • built-ins/RegExp/property-escapes/generated/Script_-_Elymaic.js
  • built-ins/RegExp/property-escapes/generated/Script_-_Ethiopic.js
  • built-ins/RegExp/property-escapes/generated/Script_-_Garay.js
  • built-ins/RegExp/property-escapes/generated/Script_-_Georgian.js
  • built-ins/RegExp/property-escapes/generated/Script_-_Glagolitic.js
  • built-ins/RegExp/property-escapes/generated/Script_-_Gothic.js
  • built-ins/RegExp/property-escapes/generated/Script_-_Grantha.js
  • built-ins/RegExp/property-escapes/generated/Script_-_Greek.js
  • built-ins/RegExp/property-escapes/generated/Script_-_Gujarati.js
  • built-ins/RegExp/property-escapes/generated/Script_-_Gunjala_Gondi.js
  • built-ins/RegExp/property-escapes/generated/Script_-_Gurmukhi.js
  • built-ins/RegExp/property-escapes/generated/Script_-_Gurung_Khema.js
  • built-ins/RegExp/property-escapes/generated/Script_-_Hangul.js
  • built-ins/RegExp/property-escapes/generated/Script_-_Hanifi_Rohingya.js
  • built-ins/RegExp/property-escapes/generated/Script_-_Hanunoo.js
  • built-ins/RegExp/property-escapes/generated/Script_-_Hatran.js
  • built-ins/RegExp/property-escapes/generated/Script_-_Hebrew.js
  • built-ins/RegExp/property-escapes/generated/Script_-_Hiragana.js
  • built-ins/RegExp/property-escapes/generated/Script_-_Imperial_Aramaic.js
  • built-ins/RegExp/property-escapes/generated/Script_-_Inscriptional_Pahlavi.js
  • built-ins/RegExp/property-escapes/generated/Script_-_Inscriptional_Parthian.js
  • built-ins/RegExp/property-escapes/generated/Script_-_Javanese.js
  • built-ins/RegExp/property-escapes/generated/Script_-_Kaithi.js
  • built-ins/RegExp/property-escapes/generated/Script_-_Katakana.js
  • built-ins/RegExp/property-escapes/generated/Script_-_Kawi.js
  • … 193 more

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 and others added 3 commits May 10, 2026 22:59
Three bugs in generate-unicode-data.js caused fallback failures on Linux:

1. Script aliases not generated — Scripts.txt uses long names (Cyrillic)
   but the alias matcher compared against short names (Cyrl), so no
   aliases were created. Fixed with findAllAliases() that resolves via
   the canonical short name regardless of which form the data file uses.

2. ScriptExtensions base ranges not merged — ScriptExtensions.txt uses
   short names (Latn) but scriptData keys were long names (Latin), so
   the base range lookup returned undefined. Fixed by building a
   short-to-long name map from PropertyValueAliases.txt.

3. ASCII binary property missing — defined via Block property in the UCD,
   not in PropList.txt or DerivedCoreProperties.txt. Added as a hardcoded
   entry (U+0000..U+007F) alongside Any and Assigned.

Entry count: 1033 → 1418 (385 new alias entries).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1. Content-based blob dedup: buildResourceFromEntries now deduplicates
   by base64 content instead of Buffer reference identity, preventing
   silent duplication if addEntry is called twice with identical ranges.

2. Robust short-to-long resolution: parseScriptExtensions resolves
   short script names by checking which alias form exists as a key in
   scriptData, instead of using a fragile length heuristic.

3. Extract CopyICURanges: the four identical range-copy loops in
   GetUnicodePropertyRanges are replaced with a nested procedure.

4. Thread-safe UCD cache: TryReadEmbeddedResource is now guarded by
   a TRTLCriticalSection, matching the ICU.pas initialization pattern.

5. Remove unused SysUtils import from UnicodeICU.pas.

6. Add DerivedBinaryProperties.txt to cover Bidi_Mirrored (ES2026
   Table 67 binary property missing from the previous file set).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Generator:
- Extract parseRange() and forEachUCDLine() helpers, eliminating
  duplicated range-parsing and comment-stripping boilerplate across
  parseUCDRangeFile, parseScriptExtensions, and the alias parsers.
- Unify three near-identical property-registration loops (gc, sc, scx)
  into registerProperty() and make property-name expansion data-driven.

Pascal:
- Extract LoadSymbol() helper in UnicodeICU.pas, replacing five
  repetitions of the ICUGetProcAddress + Assigned guard pattern.
- Replace string-allocating TryGetEntryName + CompareStr in binary
  search with TryCompareEntryName that compares bytes directly against
  the resource buffer, eliminating heap allocation per search step.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@frostney frostney marked this pull request as ready for review May 10, 2026 22:51
@coderabbitai coderabbitai Bot added new feature New feature or request spec compliance Mismatch against official JavaScript/TypeScript specification labels May 10, 2026
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (1)
scripts/generate-unicode-data.js (1)

125-127: ⚡ Quick win

Resolve redirect targets against the current request URL.

Location is allowed to be relative to the request URL, so recursing with the raw header can turn a valid redirect into a download failure. Build the next URL with new URL(response.headers.location, url) before calling downloadFile again. (developer.mozilla.org)

Patch
-      if (response.statusCode >= 300 && response.statusCode < 400 && response.headers.location) {
-        resolve(downloadFile(response.headers.location, redirectCount + 1));
+      if (response.statusCode >= 300 && response.statusCode < 400 && response.headers.location) {
+        const redirectUrl = new URL(response.headers.location, url).toString();
+        resolve(downloadFile(redirectUrl, redirectCount + 1));
         return;
       }
🤖 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 `@scripts/generate-unicode-data.js` around lines 125 - 127, The redirect
handling in downloadFile is passing response.headers.location directly which can
be a relative URL; update the redirect branch inside the https.get callback to
resolve the location against the current request URL (use new
URL(response.headers.location, url).toString() or .href) before recursing to
downloadFile(url, redirectCount + 1) so downloadFile receives an absolute URL;
update the call in the block that references response.headers.location and keep
the redirectCount logic intact.
🤖 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.RegExp.Compiler.pas`:
- Around line 389-394: CopyICURanges currently relies on AddRange which silently
stops when the fixed ARanges buffer is full; before the for-loop in
CopyICURanges check that there is enough capacity to copy all ICURanges (e.g.
compute needed := ARangeCount + Length(ICURanges) and compare against the fixed
buffer max capacity used by ARanges or a constant like MAX_RANGES), and if not,
raise an explicit error/exception or call Abort/Assert to fail loudly; keep
references to ARanges, ARangeCount, ICURanges, AddRange and CopyICURanges when
implementing the capacity check and failing code path.
- Around line 410-429: The Unicode property handling is only expanding ASCII
case pairs and misses Unicode simple case folds when /i and /u are both set;
update EmitCharClassRanges so that after ranges are obtained via
TryICUGetUnicodePropertyRanges, TryGetUnicodePropertyRanges or CopyICURanges
(ICURanges), you perform Unicode simple case folding for each code point in
those ranges (not just ±32 ASCII) and add the folded code points/ranges to the
character class (and mirror behavior for negated \P). Use ICU or your existing
Unicode case-fold table to map each code point to its simple case-fold target(s)
and merge/normalize the resulting ranges before emitting; ensure this logic runs
only when both the Unicode flag and caseless flag are active and reference the
same functions: EmitCharClassRanges, TryICUGetUnicodePropertyRanges,
TryGetUnicodePropertyRanges, CopyICURanges.

---

Nitpick comments:
In `@scripts/generate-unicode-data.js`:
- Around line 125-127: The redirect handling in downloadFile is passing
response.headers.location directly which can be a relative URL; update the
redirect branch inside the https.get callback to resolve the location against
the current request URL (use new URL(response.headers.location, url).toString()
or .href) before recursing to downloadFile(url, redirectCount + 1) so
downloadFile receives an absolute URL; update the call in the block that
references response.headers.location and keep the redirectCount logic intact.
🪄 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: fe7feaa5-180f-4cc9-b89b-6c7f08b0380a

📥 Commits

Reviewing files that changed from the base of the PR and between e9de1f5 and 225d85d.

⛔ Files ignored due to path filters (2)
  • source/generated/Generated.UnicodeData.pas is excluded by !**/generated/**
  • source/generated/Generated.UnicodeData.res is excluded by !**/generated/**
📒 Files selected for processing (7)
  • docs/build-system.md
  • scripts/generate-unicode-data.js
  • source/shared/UnicodeICU.pas
  • source/units/Goccia.RegExp.Compiler.pas
  • source/units/Goccia.RegExp.UnicodeData.pas
  • source/units/Goccia.inc
  • tests/built-ins/RegExp/unicode-properties.js

Comment thread source/units/Goccia.RegExp.Compiler.pas
Comment thread source/units/Goccia.RegExp.Compiler.pas
frostney and others added 2 commits May 11, 2026 00:31
CopyICURanges now raises EConvertError if the ICU/fallback range count
exceeds the fixed buffer capacity, instead of silently truncating via
AddRange's early exit.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@frostney frostney merged commit e1d517a into main May 11, 2026
14 checks passed
@frostney frostney deleted the t3code/task-607 branch May 11, 2026 06:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

new feature New feature or request spec compliance Mismatch against official JavaScript/TypeScript specification

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Generate full Unicode property tables for regex \p{} escapes

1 participant