Skip to content

Implement Unicode RegExp simple case folding#640

Merged
frostney merged 5 commits into
mainfrom
issue-615-regexp-unicode-case-folding
May 12, 2026
Merged

Implement Unicode RegExp simple case folding#640
frostney merged 5 commits into
mainfrom
issue-615-regexp-unicode-case-folding

Conversation

@frostney
Copy link
Copy Markdown
Owner

Summary

  • Implement Unicode-aware RegExp ignore-case matching with simple/common CaseFolding.txt mappings for /iu and /iv.
  • Extend the generated Unicode resource with CaseFolding/Simple, expand compiled character sets through simple folds, and canonicalize Unicode backreference comparisons.
  • Preserve the ECMAScript non-goal for full folding expansions: ß does not match SS.
  • Closes RegExp: full Unicode case folding for /i and /ui modes #615.

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

Verification run:

  • ./build.pas testrunner && ./build/GocciaTestRunner tests/built-ins/RegExp --asi
  • ./build/GocciaTestRunner tests/built-ins/RegExp --asi --mode=bytecode
  • ./build.pas loader && ./build/GocciaScriptLoader /tmp/goccia-regexp-615-fixed.js --asi
  • ./format.pas --check
  • ./fixtures/ffi/build.sh && ./build/GocciaTestRunner tests --asi --unsafe-ffi

Add generated Unicode CaseFolding.txt simple/common mappings to the RegExp Unicode resource and use them for Unicode-aware ignoreCase matching. This expands compiled character sets for /iu and /iv, canonicalizes Unicode backreference comparisons, and keeps non-Unicode /i behavior separate.

Covers the ECMAScript simple-folding distinction that maps ſ to s, K to k, and ẞ to ß without applying full expansions such as ß to ss.
@vercel
Copy link
Copy Markdown

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

Request Review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 11, 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: 0e988ede-15ab-4bf4-9611-c5d28a301c0a

📥 Commits

Reviewing files that changed from the base of the PR and between 85d2917 and 799365f.

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

📝 Walkthrough

Walkthrough

Implements Unicode simple case folding for RegExp case-insensitive matching: adds UCD parsing and embedded pair caches, exposes folding/canonicalization APIs, refactors compiler char-class emission to apply folding, updates VM backreference comparisons to use Unicode-aware canonicalization, adds tests, and updates docs.

Changes

Unicode Simple Case Folding Implementation

Layer / File(s) Summary
Unicode Data Generation
scripts/generate-unicode-data.js
Adds CaseFolding.txt and UnicodeData.txt downloads; parses simple case-fold and RegExp non-Unicode uppercase pairs; embeds CaseFolding/Simple and CaseMapping/RegExpNonUnicodeUppercase; prints dataset counts.
Unicode Data APIs & Caching
source/units/Goccia.RegExp.UnicodeData.pas
Adds embedded pair keys, cached pair arrays with critical sections, loaders, binary-search lookup, TryGetUnicodeSimpleCaseFold, RegExpCanonicalizeCodePoint, ExpandUnicodeSimpleCaseFolding, ReduceUnicodeSimpleCaseFoldClosed, and ExpandRegExpNonUnicodeCaseFolding; non-embedded build stubs relevant APIs.
Canonicalization & Range Helpers
source/units/Goccia.RegExp.UnicodeData.pas
Implements shared Expand/Reduce logic for range-based folding, non-Unicode uppercase target lookup, and utilities to add/remove singleton fold ranges.
Compiler Types & Conversions
source/units/Goccia.RegExp.Compiler.pas
Adds TRegExpCharRangeArray, BACKREF_UNICODE_FLAG, and helpers CharRangesToUnicodeRanges / UnicodeRangesToCharRanges.
Character-Class Emission
source/units/Goccia.RegExp.Compiler.pas
Refactors EmitCharClassRanges to convert to Unicode ranges, apply folding (Unicode vs non-Unicode), convert back, and emit via new EmitRawCharClassRanges which encodes negated vs non-negated char-class opcodes.
EmitCharMatch & Property Classes
source/units/Goccia.RegExp.Compiler.pas
EmitCharMatch now delegates ignore-case folding to the char-class pipeline; EmitUnicodePropertyClass fast-path folds property-derived ranges for negated+ignore-case+Unicode and emits via raw emitter.
Code-Point Decoding & Atom Emission
source/units/Goccia.RegExp.Compiler.pas
ReadCodePoint UTF‑8 guard simplified to bounds-only; CompileAtom always decodes a full code point and emits via EmitCharMatch.
Compiler Backreference Flagging
source/units/Goccia.RegExp.Compiler.pas
Backreference flag computation updated to include BACKREF_UNICODE_FLAG for ignore-case in Unicode mode.
VM Backreference Comparison
source/units/Goccia.RegExp.VM.pas
Adds Goccia.RegExp.UnicodeData dependency; RX_BACKREF handler extracts BackrefUnicode and canonicalizes both reference and input via RegExpCanonicalizeCodePoint(..., BackrefUnicode, True) for case-insensitive comparison.
Tests & Documentation
tests/built-ins/RegExp/unicode.js, docs/built-ins.md
Adds tests covering /u+i simple folding, exclusion of multi-code-point expansions (e.g., ßSS), folding order vs negated classes and property complements, backreference folding, v+i behavior, and i without u; docs clarify /u + /i uses Unicode simple case folding with single-code-point examples and excludes multi-code-point expansion.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately and clearly summarizes the main objective of the pull request: implementing Unicode RegExp simple case folding.
Description check ✅ Passed The PR description includes all required template sections: a clear summary explaining the implementation, ECMAScript non-goals, issue closure, and comprehensive testing verification with multiple test commands.
Linked Issues check ✅ Passed The PR comprehensively addresses issue #615's objectives: adds CaseFolding/Simple to Unicode resources, implements simple-fold expansion in character sets for /iu and /iv, canonicalizes Unicode backreferences, and preserves the non-goal of full-fold expansions (ß does not match SS).
Out of Scope Changes check ✅ Passed All code changes are directly related to implementing Unicode simple case folding: Unicode data generation, compiler refactoring for case-fold handling, VM backreference canonicalization, and comprehensive test coverage. No unrelated changes detected.

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

Benchmark Results

407 benchmarks

Interpreted: 🟢 55 improved · 🔴 69 regressed · 283 unchanged · avg +0.4%
Bytecode: 🟢 23 improved · 🔴 349 regressed · 35 unchanged · avg -8.7%

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

Suite Timing

Test Runner (interpreted: 9,307 passed; bytecode: 9,307 passed)
Metric Interpreted Bytecode
Total 9307 9307
Passed 9307 ✅ 9307 ✅
Workers 4 4
Test Duration 2.10s 1.70s
Lex (cumulative) 259.9ms 131.3ms
Parse (cumulative) 275.9ms 206.7ms
Compile (cumulative) 413.0ms
Execute (cumulative) 2.26s 1.75s
Engine Total (cumulative) 2.80s 2.50s
Lex (avg/worker) 65.0ms 32.8ms
Parse (avg/worker) 69.0ms 51.7ms
Compile (avg/worker) 103.3ms
Execute (avg/worker) 566.0ms 437.0ms
Engine Total (avg/worker) 699.9ms 624.7ms

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 246.23 MiB 240.62 MiB
GC Peak Live 246.24 MiB 240.63 MiB
GC Allocated During Run 250.17 MiB 244.54 MiB
GC Limit 7.81 GiB 7.81 GiB
GC Collections 1 1
GC Collected Objects 88 88
Heap Start Allocated 150.1 KiB 150.1 KiB
Heap End Allocated 2.54 MiB 2.54 MiB
Heap Delta Allocated 2.40 MiB 2.40 MiB
Heap Delta Free 139.4 KiB 139.4 KiB
Benchmarks (interpreted: 407; bytecode: 407)
Metric Interpreted Bytecode
Total 407 407
Workers 4 4
Duration 2.49min 2.37min

Memory

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

Metric Interpreted Bytecode
GC Live 3.65 MiB 3.64 MiB
GC Peak Live 93.30 MiB 69.98 MiB
GC Allocated During Run 13.79 GiB 9.38 GiB
GC Limit 7.81 GiB 7.81 GiB
GC Collections 2,813 2,626
GC Collected Objects 255,490,361 224,014,180
Heap Start Allocated 2.29 MiB 2.29 MiB
Heap End Allocated 2.29 MiB 2.29 MiB
Heap Delta Allocated 128 B 128 B

Measured on ubuntu-latest x64.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 11, 2026

test262 Conformance

Category Run Passed Δ Pass Failed Pass-rate Δ Rate
built-ins 23,449 14,922 +4 8,520 63.6% ±0pp
harness 116 71 ±0 45 61.2% ±0pp
intl402 3,324 691 ±0 2,633 20.8% ±0pp
language 23,635 12,575 ±0 11,060 53.2% ±0pp
staging 1,484 492 +4 990 33.2% +0.3pp
total 52,008 28,751 +8 23,248 55.3% ±0pp

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

Newly passing (8):

  • built-ins/Number/prototype/toExponential/undefined-fractiondigits.js
  • built-ins/RegExp/regexp-modifiers/add-ignoreCase-affects-slash-lower-w.js
  • built-ins/RegExp/regexp-modifiers/add-ignoreCase-affects-slash-upper-p.js
  • built-ins/RegExp/unicode_full_case_folding.js
  • staging/sm/RegExp/ignoreCase-multiple.js
  • staging/sm/RegExp/ignoreCase-non-latin1-to-latin1.js
  • staging/sm/RegExp/unicode-ignoreCase-ascii.js
  • staging/sm/RegExp/unicode-ignoreCase.js

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

frostney added 2 commits May 11, 2026 09:57
Handle non-Unicode RegExp ignoreCase with generated simple uppercase mappings, filtered by the ECMAScript non-ASCII-to-ASCII guard. Also handle /iu property escapes with complement-before-canonicalization semantics for \P{...}, and decode UTF-8 pattern literals consistently for non-u RegExp source text.
@frostney frostney marked this pull request as ready for review May 11, 2026 15:40
@coderabbitai coderabbitai Bot added new feature New feature or request spec compliance Mismatch against official JavaScript/TypeScript specification labels May 11, 2026
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 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 454-459: The negated-path currently only runs the
complement-before-folding branch when ANegated and FModifier.IgnoreCase and
FUnicode and not FUnicodeSets, which leaves top-level \P{...} in Unicode-sets
mode using the old negate-after-folding logic; change the condition in the block
that creates FoldRanges/ReduceUnicodeSimpleCaseFoldClosed/EmitRawCharClassRanges
so it triggers whenever ANegated and FModifier.IgnoreCase and FUnicode (i.e.,
remove the not FUnicodeSets guard) so the complement-before-folding path is
applied in `/iv` as well; update the relevant code around FoldRanges,
CharRangesToUnicodeRanges, ReduceUnicodeSimpleCaseFoldClosed,
EmitRawCharClassRanges and UnicodeRangesToCharRanges and add a small `/iv`
regression test mirroring the `/iu` cases.

In `@source/units/Goccia.RegExp.UnicodeData.pas`:
- Around line 767-770: The empty stub ExpandRegExpNonUnicodeCaseFolding must
implement the non-embedded ASCII case-fold expansion so ignore-case matching
works when GOCCIA_REGEXP_EMBEDDED_UCD is off: iterate the incoming ARanges
(TUnicodePropertyRangeArray) and for any ASCII letters add their opposite-case
codepoint ranges (e.g., map 'a'-'z' to 'A'-'Z' and vice versa) or expand
single-letter ranges to include the ASCII counterpart, merging/normalizing
overlaps so classes remain sorted/unique; update the routine used by
EmitCharMatch to call this so /i and character-class forms ([a] vs a) behave
identically—note RegExpCanonicalizeCodePoint handles backreferences only, so
keep this ASCII-only expansion here and preserve array normalization semantics
used elsewhere.
🪄 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: afd38f83-f6f2-41e4-96f5-dc59362c3c05

📥 Commits

Reviewing files that changed from the base of the PR and between cc09802 and 85d2917.

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

Comment thread source/units/Goccia.RegExp.Compiler.pas Outdated
Comment thread source/units/Goccia.RegExp.UnicodeData.pas
@frostney frostney merged commit 0ffea3d into main May 12, 2026
14 checks passed
@frostney frostney deleted the issue-615-regexp-unicode-case-folding branch May 12, 2026 06:36
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.

RegExp: full Unicode case folding for /i and /ui modes

1 participant