Skip to content

Implement v flag (UnicodeSets) for RegExp#621

Merged
frostney merged 5 commits into
mainfrom
issue-608-regexp-v-flag
May 9, 2026
Merged

Implement v flag (UnicodeSets) for RegExp#621
frostney merged 5 commits into
mainfrom
issue-608-regexp-v-flag

Conversation

@frostney
Copy link
Copy Markdown
Owner

@frostney frostney commented May 9, 2026

Summary

  • Implement the ES2024 RegExp v flag (unicodeSets) with full set operations and properties-of-strings support.
  • Lexer: Accept v and d flags in regex literals (/pattern/v); update error suggestions.
  • Compiler: Add FUnicodeSets field, range set operation helpers (normalize, intersect, subtract), and a dedicated v-mode character class parser supporting && (intersection), -- (subtraction), nested [...] classes, \q{...} string disjunction, \P{...} (complement) inside classes, and v-mode syntax restrictions on unescaped special characters.
  • Properties of strings: \p{Basic_Emoji}, \p{Emoji_Keycap_Sequence}, \p{RGI_Emoji_Flag_Sequence}, \p{RGI_Emoji_Modifier_Sequence}, \p{RGI_Emoji_Tag_Sequence}, \p{RGI_Emoji_ZWJ_Sequence} — multi-codepoint sequences compiled as split/char alternations using existing bytecode opcodes.
  • String alternatives in character classes are compiled down to RX_SPLIT/RX_CHAR/RX_JUMP sequences, requiring no new VM opcodes.
  • Closes Implement v flag (UnicodeSets) for RegExp #608

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

Add full support for the ES2024 RegExp v flag (unicodeSets), including
set intersection (&&), subtraction (--), nested character classes,
\q{} string disjunction, and properties-of-strings (\p{Basic_Emoji},
\p{Emoji_Keycap_Sequence}, \p{RGI_Emoji_Flag_Sequence}, etc.).

Closes #608

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

vercel Bot commented May 9, 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 9, 2026 11:07pm

Request Review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 9, 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: 8c0b607b-9017-4f7a-90de-b6a9a8622758

📥 Commits

Reviewing files that changed from the base of the PR and between b724d00 and 93f6f88.

📒 Files selected for processing (2)
  • source/units/Goccia.RegExp.Compiler.pas
  • tests/built-ins/RegExp/unicode-sets.js
🚧 Files skipped from review as they are similar to previous changes (2)
  • source/units/Goccia.RegExp.Compiler.pas
  • tests/built-ins/RegExp/unicode-sets.js

📝 Walkthrough

Walkthrough

This PR implements the ECMAScript v flag (UnicodeSets) for RegExp, enabling set operations in character classes (&& intersection, -- subtraction, string disjunctions \q{...}), alongside support for the d flag. Changes span error messages, lexer flag acceptance, compiler data structures, set operation helpers, string property support, class parsing with operators, and a comprehensive test suite.

Changes

Unicode Sets v Flag Feature

Layer / File(s) Summary
Error Messages & Flag Documentation
source/units/Goccia.Error.Suggestions.pas
Updated resource strings SSuggestCloseRegex, SSuggestValidRegexFlags, and SSuggestRegexSuffixFlags to document expanded flag set including d and v.
Lexer Flag Acceptance
source/units/Goccia.Lexer.pas
ScanRegexLiteral now recognizes the d flag as a valid regex flag during lexical analysis.
Compiler Types & Method Declarations
source/units/Goccia.RegExp.Compiler.pas
Introduced TRegExpClassContents/TRegExpStringSequence and new method declarations; added FUnicodeSets compiler state to enable Unicode-sets parsing.
Flag Initialization & Mode Setup
source/units/Goccia.RegExp.Compiler.pas
Updated flag initialization so FUnicodeSets derives from v and FUnicode becomes active when either u or v is present.
Range Normalization & Set Operations
source/units/Goccia.RegExp.Compiler.pas
Added helpers to normalize ranges and apply set operations (intersection, subtraction, complement) to TRegExpClassContents while preserving string sequences.
String Property Support
source/units/Goccia.RegExp.Compiler.pas
Recognizes string-valued Unicode properties and populates TRegExpClassContents with multi-codepoint strings for those properties in Unicode-sets mode.
Class Escape Parsing & String Disjunctions
source/units/Goccia.RegExp.Compiler.pas
Extended escape parsing to support \p{...}/\P{...} with string-property handling and implemented \q{...} string-disjunction parsing in Unicode-sets classes.
Nested Set Operators & Class Union Parsing
source/units/Goccia.RegExp.Compiler.pas
Implemented nested set-operator parsing and class union parsing with && (intersection) and -- (subtraction), nested bracket support, and syntax restrictions.
Class Compilation & Opcode Emission
source/units/Goccia.RegExp.Compiler.pas
Emits RX_CHAR_CLASS(_NEG) for pure-range classes; emits RX_SPLIT/RX_CHAR/RX_JUMP sequences for string alternatives and RX_FAIL when empty.
CompileUnicodeSetsClass Integration
source/units/Goccia.RegExp.Compiler.pas
Added CompileUnicodeSetsClass to parse full Unicode-sets classes (negation, unions, nested ops) and reject negated classes that contain strings.
Comprehensive Test Suite
tests/built-ins/RegExp/unicode-sets.js
Added test file with extensive coverage for v-mode behavior, flags, set operations, \q{...}, string properties, negation, syntax errors, runtime APIs, edge cases, and bytecode-mode consistency.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~75 minutes

Possibly Related PRs

  • frostney/GocciaScript#207: Both PRs modify RegExp flag handling and add/accept the v (Unicode sets) and d flags — including compiler/lexer changes to support v-mode Unicode sets.
  • frostney/GocciaScript#585: Introduces related additions to d/v flag support and lexer/resource-string changes touching similar areas.
  • frostney/GocciaScript#486: Related RegExp and lexer flag handling updates for v/d.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely summarizes the main change: implementing the v flag (UnicodeSets) feature for RegExp, which is the primary objective of the pull request.
Description check ✅ Passed The description includes a detailed summary of changes across lexer, compiler, and properties-of-strings implementation, with the linked issue reference (#608). Testing checklist shows end-to-end tests verified.
Linked Issues check ✅ Passed The PR comprehensively implements all core objectives from #608: v flag acceptance with u-flag exclusivity, set operations (&&, --), nested classes, properties-of-strings, and v-mode syntax restrictions.
Out of Scope Changes check ✅ Passed All changes are directly scoped to the v flag implementation: lexer flag acceptance, compiler set operations, and properties-of-strings support. Error suggestions updates align with the new flags.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

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


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

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 9, 2026

Suite Timing

Test Runner (interpreted: 9,095 passed; bytecode: 9,095 passed)
Metric Interpreted Bytecode
Total 9095 9095
Passed 9095 ✅ 9095 ✅
Workers 4 4
Test Duration 1.90s 2.00s
Lex (cumulative) 254.6ms 152.2ms
Parse (cumulative) 266.3ms 253.7ms
Compile (cumulative) 515.6ms
Execute (cumulative) 2.04s 2.06s
Engine Total (cumulative) 2.56s 2.98s
Lex (avg/worker) 63.7ms 38.0ms
Parse (avg/worker) 66.6ms 63.4ms
Compile (avg/worker) 128.9ms
Execute (avg/worker) 510.9ms 514.5ms
Engine Total (avg/worker) 641.1ms 744.9ms

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 231.09 MiB 225.57 MiB
GC Peak Live 231.09 MiB 225.57 MiB
GC Allocated During Run 234.93 MiB 229.40 MiB
GC Limit 7.81 GiB 7.81 GiB
GC Collections 1 1
GC Collected Objects 74 74
Heap Start Allocated 146.7 KiB 146.7 KiB
Heap End Allocated 1.38 MiB 1.38 MiB
Heap Delta Allocated 1.24 MiB 1.24 MiB
Heap Delta Free 715.2 KiB 715.2 KiB
Benchmarks (interpreted: 407; bytecode: 407)
Metric Interpreted Bytecode
Total 407 407
Workers 4 4
Duration 2.48min 2.36min

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.44 MiB 3.43 MiB
GC Peak Live 118.37 MiB 70.26 MiB
GC Allocated During Run 14.72 GiB 9.57 GiB
GC Limit 7.81 GiB 7.81 GiB
GC Collections 2,811 2,640
GC Collected Objects 273,409,663 225,050,257
Heap Start Allocated 1.14 MiB 1.14 MiB
Heap End Allocated 1.14 MiB 1.14 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 9, 2026

Benchmark Results

407 benchmarks

Interpreted: 🟢 240 improved · 🔴 39 regressed · 128 unchanged · avg +5.3%
Bytecode: 🟢 165 improved · 🔴 13 regressed · 229 unchanged · avg +2.5%

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

test262 Conformance

Category Run Passed Δ Pass Failed Pass-rate Δ Rate
built-ins 23,449 14,607 +121 8,838 62.3% +0.5pp
harness 116 71 ±0 45 61.2% ±0pp
intl402 3,324 167 ±0 3,157 5.0% ±0pp
language 23,635 12,575 ±0 11,060 53.2% ±0pp
staging 1,484 484 ±0 998 32.6% ±0pp
total 52,008 27,904 +121 24,098 53.7% +0.2pp

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

Newly passing (121):

  • built-ins/Number/prototype/toExponential/undefined-fractiondigits.js
  • built-ins/RegExp/CharacterClassEscapes/character-class-digit-class-escape-positive-cases.js
  • built-ins/RegExp/CharacterClassEscapes/character-class-non-digit-class-escape-negative-cases.js
  • built-ins/RegExp/CharacterClassEscapes/character-class-non-digit-class-escape-positive-cases.js
  • built-ins/RegExp/CharacterClassEscapes/character-class-non-whitespace-class-escape-negative-cases.js
  • built-ins/RegExp/CharacterClassEscapes/character-class-non-whitespace-class-escape-positive-cases.js
  • built-ins/RegExp/CharacterClassEscapes/character-class-non-word-class-escape-negative-cases.js
  • built-ins/RegExp/CharacterClassEscapes/character-class-non-word-class-escape-positive-cases.js
  • built-ins/RegExp/CharacterClassEscapes/character-class-whitespace-class-escape-positive-cases.js
  • built-ins/RegExp/CharacterClassEscapes/character-class-word-class-escape-positive-cases.js
  • built-ins/RegExp/prototype/flags/this-val-regexp.js
  • built-ins/RegExp/prototype/hasIndices/this-val-regexp.js
  • built-ins/RegExp/prototype/unicodeSets/this-val-regexp.js
  • built-ins/RegExp/unicodeSets/generated/character-class-difference-character-class-escape.js
  • built-ins/RegExp/unicodeSets/generated/character-class-difference-character-class.js
  • built-ins/RegExp/unicodeSets/generated/character-class-difference-character-property-escape.js
  • built-ins/RegExp/unicodeSets/generated/character-class-difference-character.js
  • built-ins/RegExp/unicodeSets/generated/character-class-difference-property-of-strings-escape.js
  • built-ins/RegExp/unicodeSets/generated/character-class-difference-string-literal.js
  • built-ins/RegExp/unicodeSets/generated/character-class-escape-difference-character-class-escape.js
  • built-ins/RegExp/unicodeSets/generated/character-class-escape-difference-character-class.js
  • built-ins/RegExp/unicodeSets/generated/character-class-escape-difference-character-property-escape.js
  • built-ins/RegExp/unicodeSets/generated/character-class-escape-difference-character.js
  • built-ins/RegExp/unicodeSets/generated/character-class-escape-difference-property-of-strings-escape.js
  • built-ins/RegExp/unicodeSets/generated/character-class-escape-difference-string-literal.js
  • built-ins/RegExp/unicodeSets/generated/character-class-escape-intersection-character-class-escape.js
  • built-ins/RegExp/unicodeSets/generated/character-class-escape-intersection-character-class.js
  • built-ins/RegExp/unicodeSets/generated/character-class-escape-intersection-character-property-escape.js
  • built-ins/RegExp/unicodeSets/generated/character-class-escape-intersection-character.js
  • built-ins/RegExp/unicodeSets/generated/character-class-escape-intersection-property-of-strings-escape.js
  • built-ins/RegExp/unicodeSets/generated/character-class-escape-intersection-string-literal.js
  • built-ins/RegExp/unicodeSets/generated/character-class-escape-union-character-class-escape.js
  • built-ins/RegExp/unicodeSets/generated/character-class-escape-union-character-class.js
  • built-ins/RegExp/unicodeSets/generated/character-class-escape-union-character-property-escape.js
  • built-ins/RegExp/unicodeSets/generated/character-class-escape-union-character.js
  • built-ins/RegExp/unicodeSets/generated/character-class-escape-union-property-of-strings-escape.js
  • built-ins/RegExp/unicodeSets/generated/character-class-escape-union-string-literal.js
  • built-ins/RegExp/unicodeSets/generated/character-class-intersection-character-class-escape.js
  • built-ins/RegExp/unicodeSets/generated/character-class-intersection-character-class.js
  • built-ins/RegExp/unicodeSets/generated/character-class-intersection-character-property-escape.js
  • built-ins/RegExp/unicodeSets/generated/character-class-intersection-character.js
  • built-ins/RegExp/unicodeSets/generated/character-class-intersection-property-of-strings-escape.js
  • built-ins/RegExp/unicodeSets/generated/character-class-intersection-string-literal.js
  • built-ins/RegExp/unicodeSets/generated/character-class-union-character-class-escape.js
  • built-ins/RegExp/unicodeSets/generated/character-class-union-character-class.js
  • built-ins/RegExp/unicodeSets/generated/character-class-union-character-property-escape.js
  • built-ins/RegExp/unicodeSets/generated/character-class-union-character.js
  • built-ins/RegExp/unicodeSets/generated/character-class-union-property-of-strings-escape.js
  • built-ins/RegExp/unicodeSets/generated/character-class-union-string-literal.js
  • built-ins/RegExp/unicodeSets/generated/character-difference-character-class-escape.js
  • built-ins/RegExp/unicodeSets/generated/character-difference-character-class.js
  • built-ins/RegExp/unicodeSets/generated/character-difference-character-property-escape.js
  • built-ins/RegExp/unicodeSets/generated/character-difference-character.js
  • built-ins/RegExp/unicodeSets/generated/character-difference-property-of-strings-escape.js
  • built-ins/RegExp/unicodeSets/generated/character-difference-string-literal.js
  • built-ins/RegExp/unicodeSets/generated/character-intersection-character-class-escape.js
  • built-ins/RegExp/unicodeSets/generated/character-intersection-character-class.js
  • built-ins/RegExp/unicodeSets/generated/character-intersection-character-property-escape.js
  • built-ins/RegExp/unicodeSets/generated/character-intersection-character.js
  • built-ins/RegExp/unicodeSets/generated/character-intersection-property-of-strings-escape.js
  • built-ins/RegExp/unicodeSets/generated/character-intersection-string-literal.js
  • built-ins/RegExp/unicodeSets/generated/character-property-escape-difference-character-class-escape.js
  • built-ins/RegExp/unicodeSets/generated/character-property-escape-difference-character-class.js
  • built-ins/RegExp/unicodeSets/generated/character-property-escape-difference-character-property-escape.js
  • built-ins/RegExp/unicodeSets/generated/character-property-escape-difference-character.js
  • built-ins/RegExp/unicodeSets/generated/character-property-escape-difference-property-of-strings-escape.js
  • built-ins/RegExp/unicodeSets/generated/character-property-escape-difference-string-literal.js
  • built-ins/RegExp/unicodeSets/generated/character-property-escape-intersection-character-class-escape.js
  • built-ins/RegExp/unicodeSets/generated/character-property-escape-intersection-character-class.js
  • built-ins/RegExp/unicodeSets/generated/character-property-escape-intersection-character-property-escape.js
  • built-ins/RegExp/unicodeSets/generated/character-property-escape-intersection-character.js
  • built-ins/RegExp/unicodeSets/generated/character-property-escape-intersection-property-of-strings-escape.js
  • built-ins/RegExp/unicodeSets/generated/character-property-escape-intersection-string-literal.js
  • built-ins/RegExp/unicodeSets/generated/character-property-escape-union-character-class-escape.js
  • built-ins/RegExp/unicodeSets/generated/character-property-escape-union-character-class.js
  • built-ins/RegExp/unicodeSets/generated/character-property-escape-union-character-property-escape.js
  • built-ins/RegExp/unicodeSets/generated/character-property-escape-union-character.js
  • built-ins/RegExp/unicodeSets/generated/character-property-escape-union-property-of-strings-escape.js
  • built-ins/RegExp/unicodeSets/generated/character-property-escape-union-string-literal.js
  • built-ins/RegExp/unicodeSets/generated/character-union-character-class-escape.js
  • built-ins/RegExp/unicodeSets/generated/character-union-character-class.js
  • built-ins/RegExp/unicodeSets/generated/character-union-character-property-escape.js
  • built-ins/RegExp/unicodeSets/generated/character-union-character.js
  • built-ins/RegExp/unicodeSets/generated/character-union-property-of-strings-escape.js
  • built-ins/RegExp/unicodeSets/generated/character-union-string-literal.js
  • built-ins/RegExp/unicodeSets/generated/property-of-strings-escape-difference-character-class-escape.js
  • built-ins/RegExp/unicodeSets/generated/property-of-strings-escape-difference-character-class.js
  • built-ins/RegExp/unicodeSets/generated/property-of-strings-escape-difference-character-property-escape.js
  • built-ins/RegExp/unicodeSets/generated/property-of-strings-escape-difference-character.js
  • built-ins/RegExp/unicodeSets/generated/property-of-strings-escape-difference-property-of-strings-escape.js
  • built-ins/RegExp/unicodeSets/generated/property-of-strings-escape-difference-string-literal.js
  • built-ins/RegExp/unicodeSets/generated/property-of-strings-escape-intersection-character-class-escape.js
  • built-ins/RegExp/unicodeSets/generated/property-of-strings-escape-intersection-character-class.js
  • built-ins/RegExp/unicodeSets/generated/property-of-strings-escape-intersection-character-property-escape.js
  • built-ins/RegExp/unicodeSets/generated/property-of-strings-escape-intersection-character.js
  • built-ins/RegExp/unicodeSets/generated/property-of-strings-escape-intersection-property-of-strings-escape.js
  • built-ins/RegExp/unicodeSets/generated/property-of-strings-escape-intersection-string-literal.js
  • built-ins/RegExp/unicodeSets/generated/property-of-strings-escape-union-character-class-escape.js
  • built-ins/RegExp/unicodeSets/generated/property-of-strings-escape-union-character-class.js
  • built-ins/RegExp/unicodeSets/generated/property-of-strings-escape-union-character-property-escape.js
  • … 21 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 2 commits May 9, 2026 23:35
- Compute complement for nested negated classes ([^...] inside a class)
  so patterns like [[^0-9]&&[a-z]] produce correct results
- Support chained same-kind operators ([a-z&&[a-m]&&[a-f]]) with a
  syntax error when mixing && and -- at the same nesting level
- Remove dead ParseClassOperand method
- Guard \q{} behind FUnicodeSets so it only works in v-mode
- Add 11 new tests: chained ops, nested negation, \q{} in set
  operations, bytecode mode smoke tests

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Extract FilterClassStrings + ApplyClassSetOp to eliminate near-identical
  IntersectClassContents/SubtractClassContents bodies
- Use ComplementContents for \P{} complement instead of inline logic,
  removing ~8KB of unused stack arrays from ParseClassEscape
- Delegate EmitClassContents range emission to EmitCharClassRanges
  instead of duplicating the case-folding expansion
- Remove ~35 duplicate Basic_Emoji ranges already covered by earlier entries
- Replace O(n^2) bubble sort in NormalizeRanges with insertion sort

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@frostney frostney marked this pull request as ready for review May 9, 2026 22:52
@coderabbitai coderabbitai Bot added new feature New feature or request spec compliance Mismatch against official JavaScript/TypeScript specification labels May 9, 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: 4

🤖 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 1298-1306: The loop that emits raw RX_CHAR ops for multi-codepoint
strings bypasses case-folding and should use the existing EmitCharMatch helper;
in the block inside for I := AContents.StringCount - 1 downto 0 do where you set
SplitHoles/SplitCount and call Emit(EncodeOpBx(RX_SPLIT, 0)), replace the inner
for J := 0 to High(AContents.Strings[I].CodePoints) do Emit(EncodeOpBx(RX_CHAR,
Integer(...))) with calls to EmitCharMatch(AContents.Strings[I].CodePoints[J])
(or the appropriate signature of EmitCharMatch) so FModifier.IgnoreCase handling
is applied consistently to these string branches instead of emitting raw RX_CHAR
opcodes.
- Around line 1202-1239: When parsing a potential range endpoint the code
currently allows a prior call to ParseClassEscape to append ranges/strings to
AContents and then reuses those as the range endpoint; instead, detect this
situation in v-mode and throw a SyntaxError: after calling
ParseClassEscape(AContents) (and before using
AContents.Ranges[AContents.RangeCount - 1] as Lo) check if the parser is in
v-mode and if AContents.RangeCount > SavePos or AContents.StringCount > SavePos,
and if so raise an EConvertError/SyntaxError (same message as other regex syntax
errors) instead of treating the escape as a numeric endpoint; apply the same
check for the EscContents code path (after ParseClassEscape(EscContents)) so
character class escapes cannot be used as either Lo or Hi when building a range
with AddClassRange or when using ReadCodePoint.
- Around line 1177-1198: The nested-class parser currently calls
ParseClassUnion() but does not let it consume set operators, causing pending
'&&' or '--' to break out and leave Match(']') to fail; fix by updating
ParseClassUnion (and any helper like ParseClassOperand/ParseClassRange if
needed) to accept an allowSetOperators boolean (or equivalent flag) and
implement handling of '&&' and '--' when that flag is true; then call
ParseClassUnion(EscContents, True) (or pass True) from the nested class branch
inside CompileUnicodeSetsClass/this routine so nested character classes like
[[a-z&&[a-f]]] are parsed with set operators, while preserving current top-level
behavior where necessary, and ensure
MergeClassContents/ComplementContents/NormalizeRanges continue to operate on the
fully-parsed EscContents.
- Around line 761-1005: The GetStringPropertySequences implementation
(TRegExpCompiler.GetStringPropertySequences) currently hardcodes only a small
subset of sequences for properties like 'RGI_Emoji_Flag_Sequence' and
'RGI_Emoji_ZWJ_Sequence', which breaks full Unicode v-flag semantics; replace
the hardcoded lists with a data-driven solution that loads the complete sequence
sets from the authoritative Unicode data (e.g., emoji-sequences.txt / emoji-test
or the UTS `#51` derived list) at build or init time and populates AContents via
AddClassString/AddClassRange (or a helper like LoadEmojiSequences) so all ~334
flag and ~1000+ ZWJ sequences are included; keep the existing property name
checks and error path (EConvertError) but ensure the loading occurs once and is
referenced by GetStringPropertySequences for the named properties.
🪄 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: c6f6d353-8ada-42ad-b0f3-f4f15b223e9f

📥 Commits

Reviewing files that changed from the base of the PR and between f2531ee and b724d00.

📒 Files selected for processing (4)
  • source/units/Goccia.Error.Suggestions.pas
  • source/units/Goccia.Lexer.pas
  • source/units/Goccia.RegExp.Compiler.pas
  • tests/built-ins/RegExp/unicode-sets.js

Comment thread source/units/Goccia.RegExp.Compiler.pas
Comment thread source/units/Goccia.RegExp.Compiler.pas
Comment thread source/units/Goccia.RegExp.Compiler.pas
Comment thread source/units/Goccia.RegExp.Compiler.pas Outdated
frostney and others added 2 commits May 10, 2026 00:01
- Allow set operators (&&, --) inside nested character classes by
  extracting ApplyNestedSetOps and calling it after ParseClassUnion
  in both nested-class and top-level paths
- Reject character class escapes (\d, \w, \s, \p{}, \q{}) as range
  endpoints in v-mode with SyntaxError per ES2024 spec
- Use EmitCharMatch instead of raw RX_CHAR for string sequence
  branches so \q{} and string properties respect /i case-folding
- Add 7 new tests covering nested set ops, class-escape rejection,
  and case-insensitive string matching

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@frostney frostney merged commit ccce182 into main May 9, 2026
14 checks passed
@frostney frostney deleted the issue-608-regexp-v-flag branch May 9, 2026 23:45
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.

Implement v flag (UnicodeSets) for RegExp

1 participant