Skip to content

Fix RegExp lookbehind direction#673

Merged
frostney merged 3 commits into
mainfrom
issue-612-regexp-lookbehind
May 20, 2026
Merged

Fix RegExp lookbehind direction#673
frostney merged 3 commits into
mainfrom
issue-612-regexp-lookbehind

Conversation

@frostney
Copy link
Copy Markdown
Owner

Summary

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

Commands run:

  • ./build.pas loader
  • upstream test262 test/built-ins/RegExp/lookBehind/*.js with Goccia compatibility flags
  • ./build.pas testrunner
  • ./build/GocciaTestRunner tests/built-ins/RegExp/prototype/exec.js --asi --unsafe-ffi --no-progress
  • ./build/GocciaTestRunner tests/built-ins/RegExp/prototype/exec.js --asi --unsafe-ffi --mode=bytecode --no-progress
  • ./build/GocciaTestRunner tests/built-ins/RegExp --asi --unsafe-ffi --no-progress
  • ./format.pas --check
  • ./fixtures/ffi/build.sh
  • ./build/GocciaTestRunner tests --asi --unsafe-ffi --no-progress

Implement backward-direction matching for lookbehind subpatterns so captures,
backreferences, nested lookaround, and sticky/global matches follow ECMAScript
lookbehind semantics.

Closes #612
@vercel
Copy link
Copy Markdown

vercel Bot commented May 20, 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 20, 2026 9:00am

Request Review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 20, 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: ba1026f2-63b1-488d-a08d-7ef292c3a462

📥 Commits

Reviewing files that changed from the base of the PR and between b1b8de5 and 59f5b6d.

📒 Files selected for processing (3)
  • source/units/Goccia.RegExp.Compiler.pas
  • source/units/Goccia.RegExp.VM.pas
  • tests/built-ins/RegExp/prototype/exec.js

📝 Walkthrough

Walkthrough

This PR implements lookbehind pattern support with captures, back-references, and nested lookaround by introducing backward-mode compilation and execution. The compiler adds a FBackward flag that lookaround groups control, reversing capture slot order and alternative term emission in backward mode. The VM decodes input backward and adjusts opcodes accordingly, with a simplified RX_LOOKBEHIND handler delegating to RunVM with the backward flag.

Changes

Lookbehind captures and bidirectional regex execution

Layer / File(s) Summary
Backward-mode compiler state and term buffering
source/units/Goccia.RegExp.Compiler.pas
Introduces FBackward flag and TRegExpTermCode record to track direction and buffer bytecode during compilation.
Direction-aware string/disjunction emission
source/units/Goccia.RegExp.Compiler.pas
Emit string-disjunction multi-codepoint match sequences in forward or reversed order depending on compiler direction.
Lookahead/lookbehind override compiler direction
source/units/Goccia.RegExp.Compiler.pas
Lookahead and lookbehind group compilation saves/restores FBackward, forcing False for lookahead and True for lookbehind during subpattern compilation.
Direction-aware capture group slot emission
source/units/Goccia.RegExp.Compiler.pas
Named and unnamed capture groups emit RX_SAVE bytecode with start/end slot order depending on whether compiler is in backward mode.
Backward-mode alternative term reversal
source/units/Goccia.RegExp.Compiler.pas
Alternative compilation is direction-aware: forward mode compiles terms sequentially; backward mode buffers each term's bytecode then emits buffered terms in reverse order. EmitBodyAt exits early when body length is non-positive.
VM constant removal
source/units/Goccia.RegExp.VM.pas
Remove MAX_LOOKBEHIND_DISTANCE constant.
Unicode-aware backward code-point reading
source/units/Goccia.RegExp.VM.pas
New ReadInputCodePointBefore helper decodes the code point ending at a position with surrogate-pair handling, returning both code point and width consumed.
RunVM backward-mode parameter and variable setup
source/units/Goccia.RegExp.VM.pas
RunVM gains ABackward parameter (default False); local variables adjusted to support backward comparison logic for backreferences.
Backward-aware character matching opcodes
source/units/Goccia.RegExp.VM.pas
RX_CHAR, RX_CHAR_CLASS, RX_CHAR_CLASS_NEG, and RX_ANY opcodes now select forward or backward code-point reads and adjust InputPos in the matching direction.
Backward-mode backreference and lookaround handling
source/units/Goccia.RegExp.VM.pas
RX_BACKREF computes comparison position and switches code-point reads/InputPos restoration based on execution direction. RX_LOOKAHEAD explicitly passes ABackward=False; RX_LOOKBEHIND simplified to delegate entirely to RunVM with ABackward=True.
Lookbehind capture and execution tests
tests/built-ins/RegExp/prototype/exec.js
Tests validate lookbehind capture order, backreferences within lookbehind, negative lookbehind capture behavior, nested lookaround direction, multiline/word-boundary support, variable-length patterns with global/sticky execution, and a unicode set-string regression.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • frostney/GocciaScript#585: Introduces the compiler+bytecode VM engine architecture that this PR extends with backward-mode support for lookbehind.

Suggested labels

bug, spec compliance, internal

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Fix RegExp lookbehind direction' accurately and concisely summarizes the main change: implementing backward-direction matching for RegExp lookbehind subpatterns.
Description check ✅ Passed The pull request description includes a clear summary of the changes and implementation approach, links to issue #612, and documents comprehensive testing verification across multiple test suites and build checks.
Linked Issues check ✅ Passed The code changes implement all primary objectives from issue #612: backward-direction matching for lookbehind subpatterns, correct capture propagation, backreference support, and nested lookaround handling.
Out of Scope Changes check ✅ Passed All changes are directly related to implementing lookbehind direction handling as required by issue #612; the test additions specifically target lookbehind edge cases and capture scenarios.
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 20, 2026

Benchmark Results

407 benchmarks

Interpreted: 🟢 22 improved · 🔴 129 regressed · 256 unchanged · avg -1.7%
Bytecode: 🟢 32 improved · 🔴 124 regressed · 251 unchanged · avg -1.3%

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

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 20, 2026

Suite Timing

Test Runner (interpreted: 9,736 passed; bytecode: 9,736 passed)
Metric Interpreted Bytecode
Total 9736 9736
Passed 9736 ✅ 9736 ✅
Workers 4 4
Test Duration 3.01s 3.21s
Lex (cumulative) 415.1ms 321.6ms
Parse (cumulative) 291.3ms 285.7ms
Compile (cumulative) 648.2ms
Execute (cumulative) 3.14s 3.62s
Engine Total (cumulative) 3.84s 4.88s
Lex (avg/worker) 103.8ms 80.4ms
Parse (avg/worker) 72.8ms 71.4ms
Compile (avg/worker) 162.0ms
Execute (avg/worker) 784.4ms 905.2ms
Engine Total (avg/worker) 961.0ms 1.22s

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 261.67 MiB 255.98 MiB
GC Peak Live 261.68 MiB 255.99 MiB
GC Allocated During Run 266.12 MiB 260.43 MiB
GC Limit 7.81 GiB 7.81 GiB
GC Collections 1 1
GC Collected Objects 88 88
Heap Start Allocated 157.8 KiB 157.8 KiB
Heap End Allocated 1.49 MiB 1.49 MiB
Heap Delta Allocated 1.34 MiB 1.34 MiB
Heap Delta Free 1.19 MiB 1.19 MiB
Benchmarks (interpreted: 407; bytecode: 407)
Metric Interpreted Bytecode
Total 407 407
Workers 4 4
Duration 2.49min 2.42min

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.69 MiB 3.68 MiB
GC Peak Live 96.66 MiB 77.46 MiB
GC Allocated During Run 14.58 GiB 10.12 GiB
GC Limit 7.81 GiB 7.81 GiB
GC Collections 2,815 2,663
GC Collected Objects 278,803,886 248,382,657
Heap Start Allocated 1.23 MiB 1.23 MiB
Heap End Allocated 1.23 MiB 1.23 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 20, 2026

test262 Conformance

Category Run Passed Δ Pass Failed Pass-rate Δ Rate
built-ins 23,449 16,067 +12 7,377 68.5% +0.1pp
harness 116 72 ±0 44 62.1% ±0pp
intl402 3,324 892 ±0 2,432 26.8% ±0pp
language 23,635 14,203 ±0 9,432 60.1% ±0pp
staging 1,484 571 ±0 910 38.5% ±0pp
total 52,008 31,805 +12 20,195 61.2% ±0pp

Areas closest to 100%

Area Pass rate Δ vs main Passing
built-ins/WeakMap 99.3% ±0pp 140 / 141
built-ins/WeakSet 98.8% ±0pp 84 / 85
language/future-reserved-words 98.1% ±0pp 53 / 54
Per-test deltas (+12 / -0)

Newly passing (12):

  • built-ins/Number/prototype/toExponential/undefined-fractiondigits.js
  • built-ins/RegExp/lookBehind/back-references-to-captures.js
  • built-ins/RegExp/lookBehind/captures-negative.js
  • built-ins/RegExp/lookBehind/captures.js
  • built-ins/RegExp/lookBehind/greedy-loop.js
  • built-ins/RegExp/lookBehind/mutual-recursive.js
  • built-ins/RegExp/lookBehind/nested-lookaround.js
  • built-ins/RegExp/lookBehind/start-of-line.js
  • built-ins/RegExp/lookBehind/sticky.js
  • built-ins/RegExp/lookBehind/variable-length.js
  • built-ins/RegExp/lookBehind/word-boundary.js
  • built-ins/RegExp/named-groups/lookbehind.js

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

@frostney frostney marked this pull request as ready for review May 20, 2026 07:48
@coderabbitai coderabbitai Bot added bug Something isn't working spec compliance Mismatch against official JavaScript/TypeScript specification internal Refactoring, CI, tooling, cleanup labels May 20, 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 2355-2390: CompileAlternative currently reverses only top-level
terms but multi-code-point class atoms (emitted in EmitClassContents / any
string-sequence emitter) are still emitted in forward order; update the emitter
(e.g., EmitClassContents or the routine that emits string/sequence atoms such as
EmitStringSequence) to check FBackward and, when true, emit the code points of
multi-code-point class strings in reverse order (or build a reversed temporary
buffer) so that class contents honor backward lookbehind; ensure this change
preserves the original OriginalStart/Length bookkeeping used by
CompileAlternative/EmitBodyAt.

In `@tests/built-ins/RegExp/prototype/exec.js`:
- Around line 446-457: The test is meant to verify sticky-mode behavior but the
RegExp assigned to the variable sticky uses the global flag (/g) instead of the
sticky flag; update the regex literal used in the test (the variable sticky in
the test "lookbehind works with variable-length and sticky matches") to use /y
(sticky) rather than /g so exec will honor lastIndex anchoring and properly test
sticky matches.
🪄 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: 28835f3d-d162-4056-8586-486001a74de0

📥 Commits

Reviewing files that changed from the base of the PR and between d0ba771 and b1b8de5.

📒 Files selected for processing (3)
  • source/units/Goccia.RegExp.Compiler.pas
  • source/units/Goccia.RegExp.VM.pas
  • tests/built-ins/RegExp/prototype/exec.js

Comment thread source/units/Goccia.RegExp.Compiler.pas
Comment thread tests/built-ins/RegExp/prototype/exec.js
frostney added 2 commits May 20, 2026 09:53
- Emit unicode set string atoms backward inside lookbehind bodies.
- Exercise sticky lookbehind with the sticky flag and explicit lastIndex.
@frostney frostney merged commit a1a0ad5 into main May 20, 2026
14 checks passed
@frostney frostney deleted the issue-612-regexp-lookbehind branch May 20, 2026 09:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

RegExp lookbehind: captures, back-references, and nested lookaround

1 participant