Skip to content

fix(engine): map ShadowRealm eval instantiation errors to SyntaxError#816

Merged
frostney merged 4 commits into
mainfrom
claude/shadowrealm-eval-syntaxerror
Jun 27, 2026
Merged

fix(engine): map ShadowRealm eval instantiation errors to SyntaxError#816
frostney merged 4 commits into
mainfrom
claude/shadowrealm-eval-syntaxerror

Conversation

@frostney

@frostney frostney commented Jun 25, 2026

Copy link
Copy Markdown
Owner

Summary

  • ShadowRealm.prototype.evaluate mapped every error from EvaluateEvalProgram to a caller-realm TypeError, so an EvalDeclarationInstantiation conflict such as r.evaluate("let x; let x;") surfaced as a TypeError instead of the SyntaxError required by proposal-shadowrealm §3.1.3 — static early errors are SyntaxErrors (step 2); only runtime abrupt completions are wrapped as TypeError (step 15).
  • Split EvaluateEvalProgram into PrepareEvalProgram (the static early-error passes plus EvalDeclarationInstantiation, returning the prepared eval context) and RunEvalProgramBody (body evaluation). EvaluateEvalProgram now just chains the two, so the VM direct-eval and $262.evalScript callers are unchanged.
  • ShadowRealm.evaluate runs the two phases separately and distinguishes their errors: a phase-1 TGocciaSyntaxError → caller-realm SyntaxError; everything else — a phase-1 CanDeclareGlobal* TypeError, plus all phase-2 runtime abrupt completions (including a nested-eval runtime SyntaxError) → caller-realm TypeError.
  • Also reports illegal top-level control flow — a return, or an unlabeled break/continue with no enclosing iteration/switch — as a caller-realm SyntaxError. A static ValidateEvalControlFlow pass runs in the pre-execution phase (PrepareEvalProgram); previously these were detected only at runtime (RunEvalProgramBody) and wrapped as TypeError. The walk visits only statements, so it never flags a return/break/continue inside a nested function, and labeled break/continue are left to the parser.
  • Follow-up to the CodeRabbit review on feat(engine): complete built-ins/ShadowRealm test262 conformance (64/64) #814 (now merged).
  • Non-goal: a top-level lexical/var name collision (e.g. let y; var y;) is a separate detection gap and is not addressed here.

Testing

  • Verified no regressions and confirmed the new feature or bugfix in end-to-end JavaScript/TypeScript tests
    • built-ins/ShadowRealm test262 — 64/64 in interpreter and bytecode modes (unchanged from the feat(engine): complete built-ins/ShadowRealm test262 conformance (64/64) #814 baseline)
    • Full repo JS suite — 10946/10946 in both modes
    • New cases in tests/built-ins/ShadowRealm/evaluate.js: duplicate let / const / class and let z; const zSyntaxError (fresh re-eval still succeeds); illegal top-level return / break / continueSyntaxError, with no false positives for control flow inside a nested function or a loop/switch
    • test262 language/eval-code (346/347 interp, 347/347 bytecode) and built-ins/eval (10/10) are identical between baseline and fix — confirming both the shared EvaluateEvalProgram refactor and the ValidateEvalControlFlow pass are behavior-preserving for the direct-eval / $262.evalScript callers (the one eval-code failure is the pre-existing, unrelated direct/super-prop-method.js)
  • Updated documentation — N/A; conformance fix with no API-surface or documented-behavior change
  • Optional: Verified no regressions and confirmed the new feature or bugfix in native Pascal tests (if AST, scope, evaluator, or value types changed) — the evaluator change is exercised by the all-executor JS suite above (the project's primary test mechanism); no separate native Pascal test targets this path
  • Optional: Verified no benchmark regressions — N/A; no hot-path change

ShadowRealm.prototype.evaluate mapped every error from EvaluateEvalProgram to
a caller-realm TypeError, so an EvalDeclarationInstantiation conflict such as
`r.evaluate("let x; let x;")` surfaced as TypeError instead of the SyntaxError
required by proposal-shadowrealm 3.1.3: static early errors are SyntaxErrors,
only runtime abrupt completions are wrapped as TypeError.

Split EvaluateEvalProgram into PrepareEvalProgram (the static early-error
passes plus EvalDeclarationInstantiation) and RunEvalProgramBody (body
evaluation). ShadowRealm.evaluate now runs the two phases separately and maps
a phase-1 TGocciaSyntaxError to a caller-realm SyntaxError, while still
wrapping phase-2 runtime abrupt completions (including a nested-eval runtime
SyntaxError) as TypeError; a CanDeclareGlobal* TypeError from instantiation
stays a TypeError. EvaluateEvalProgram chains the two phases, so the VM
direct-eval and $262.evalScript callers are unchanged.

built-ins/ShadowRealm test262 stays 64/64 in interpreter and bytecode modes;
the full repo JS suite stays green in both modes.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@vercel

vercel Bot commented Jun 25, 2026

Copy link
Copy Markdown

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

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
gocciascript-homepage Ignored Ignored Preview Jun 27, 2026 8:58am

Request Review

@coderabbitai

coderabbitai Bot commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

ShadowRealm evaluate now separates preparation from body execution, with new control-flow validation and updated handling for early syntax errors versus runtime abrupt completions. Tests add coverage for duplicate lexical bindings and illegal top-level control flow.

Changes

ShadowRealm eval flow split

Layer / File(s) Summary
Eval preparation and body execution
source/units/Goccia.Evaluator.pas
Adds PrepareEvalProgram, RunEvalProgramBody, control-flow validation during preparation, and a wrapper EvaluateEvalProgram that chains the phases.
ShadowRealm error mapping
source/units/Goccia.Builtins.GlobalShadowRealm.pas
TGocciaShadowRealmHost.Evaluate now separates early syntax errors from runtime abrupt completions and maps them to caller-realm exceptions.
ShadowRealm evaluate tests
tests/built-ins/ShadowRealm/evaluate.js
Adds SyntaxError coverage for duplicate top-level lexical bindings and illegal top-level return, break, and continue, plus allowed nested cases.

Sequence Diagram(s)

sequenceDiagram
  participant TGocciaShadowRealmHost.Evaluate
  participant PrepareEvalProgram
  participant RunEvalProgramBody
  participant Caller realm
  TGocciaShadowRealmHost.Evaluate->>PrepareEvalProgram: prepare eval program
  alt TGocciaSyntaxError
    TGocciaShadowRealmHost.Evaluate->>Caller realm: ThrowSyntaxError(EarlyErrorMessage)
  else abrupt completion
    TGocciaShadowRealmHost.Evaluate->>Caller realm: ThrowTypeError('ShadowRealm evaluate threw')
  else prepared successfully
    TGocciaShadowRealmHost.Evaluate->>RunEvalProgramBody: run prepared body
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • frostney/GocciaScript#795: Introduces the initial ShadowRealm and ShadowRealm.prototype.evaluate implementation that this PR refines.
  • frostney/GocciaScript#814: Also changes ShadowRealm.evaluate early-error handling and SyntaxError expectations around eval validation.

Suggested labels

bug, spec compliance

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main fix: mapping ShadowRealm eval instantiation errors to the correct SyntaxError.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description check ✅ Passed The PR description follows the template with a clear Summary and Testing section, including the key change, non-goal, and validation notes.

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

@github-actions

github-actions Bot commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

Suite Timing

Test Runner (interpreted: 10,946 passed; bytecode: 10,946 passed)
Metric Interpreted Bytecode
Total 10946 10946
Passed 10946 ✅ 10946 ✅
Workers 4 4
Test Duration 18.83s 18.93s
Lex (cumulative) 487.4ms 529.1ms
Parse (cumulative) 343.4ms 368.0ms
Compile (cumulative) 750.8ms
Execute (cumulative) 63.1ms 44.54s
Engine Total (cumulative) 893.9ms 46.19s
Lex (avg/worker) 121.9ms 132.3ms
Parse (avg/worker) 85.8ms 92.0ms
Compile (avg/worker) 187.7ms
Execute (avg/worker) 15.8ms 11.14s
Engine Total (avg/worker) 223.5ms 11.55s

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 282.54 MiB 279.96 MiB
GC Peak Live 355.51 MiB 310.96 MiB
GC Allocated During Run 527.92 MiB 472.23 MiB
GC Limit 7.81 GiB 7.81 GiB
GC Collections 195 195
GC Collected Objects 2,590,868 2,162,096
Heap Start Allocated 181.0 KiB 181.0 KiB
Heap End Allocated 3.65 MiB 3.65 MiB
Heap Delta Allocated 3.48 MiB 3.48 MiB
Heap Delta Free 1.68 MiB 1.68 MiB
Benchmarks (interpreted: 430; bytecode: 430)
Metric Interpreted Bytecode
Total 430 430
Workers 4 4
Duration 2.85min 2.74min

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 6.09 MiB 6.09 MiB
GC Peak Live 100.91 MiB 69.87 MiB
GC Allocated During Run 15.69 GiB 10.47 GiB
GC Limit 7.81 GiB 7.81 GiB
GC Collections 3,731 3,479
GC Collected Objects 245,533,173 241,127,015
Heap Start Allocated 3.36 MiB 3.36 MiB
Heap End Allocated 3.36 MiB 3.36 MiB
Heap Delta Allocated 128 B 128 B

Measured on ubuntu-latest x64.

@github-actions

github-actions Bot commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

Benchmark Results

430 benchmarks

Interpreted: 🟢 1 improved · 🔴 208 regressed · 221 unchanged · avg -9.4%
Bytecode: 🟢 241 improved · 🔴 6 regressed · 183 unchanged · avg +10.2%

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

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

github-actions Bot commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

test262 Conformance

Category Run Passed Δ Pass Failed Pass-rate Δ Rate
built-ins 23,643 22,609 +1 1,034 95.6% ±0pp
harness 116 116 ±0 0 100.0% ±0pp
intl402 3,341 3,334 ±0 7 99.8% ±0pp
language 23,711 23,711 ±0 0 100.0% ±0pp
staging 1,482 1,109 ±0 373 74.8% ±0pp
total 52,293 50,879 +1 1,414 97.3% ±0pp

Areas closest to 100%

Area Pass rate Δ vs main Passing
built-ins/TypedArray 99.9% ±0pp 1,445 / 1,446
intl402/Temporal 99.9% ±0pp 2,026 / 2,029
built-ins/Object 99.7% ±0pp 3,401 / 3,411
Per-test deltas (+1 / -0)

Newly passing (1):

  • built-ins/Number/prototype/toExponential/undefined-fractiondigits.js

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

@frostney frostney marked this pull request as ready for review June 27, 2026 07:54
@coderabbitai coderabbitai Bot added bug Something isn't working spec compliance Mismatch against official JavaScript/TypeScript specification labels Jun 27, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
source/units/Goccia.Evaluator.pas (1)

2942-2951: 🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift

Move illegal top-level control-flow errors into the prepare phase.

RunEvalProgramBody still raises TGocciaSyntaxError for top-level return/break/continue. Since ShadowRealm now treats all phase-2 TGocciaErrors as runtime abrupt completions, these syntax errors become caller-realm TypeErrors instead of SyntaxErrors. Add/pre-run this validation in PrepareEvalProgram so these cases stay in phase 1.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@source/units/Goccia.Evaluator.pas` around lines 2942 - 2951, Move the illegal
top-level control-flow validation out of RunEvalProgramBody into the phase-1
preparation path so these errors remain SyntaxError/parse-time failures. Update
PrepareEvalProgram to detect cfkReturn, cfkBreak, and cfkContinue before
execution starts, using the existing TGocciaSyntaxError/ThrowSyntaxError paths,
and keep RunEvalProgramBody limited to executing already-validated control flow
cases.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@source/units/Goccia.Evaluator.pas`:
- Around line 2942-2951: Move the illegal top-level control-flow validation out
of RunEvalProgramBody into the phase-1 preparation path so these errors remain
SyntaxError/parse-time failures. Update PrepareEvalProgram to detect cfkReturn,
cfkBreak, and cfkContinue before execution starts, using the existing
TGocciaSyntaxError/ThrowSyntaxError paths, and keep RunEvalProgramBody limited
to executing already-validated control flow cases.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: e5341ce5-dc97-418f-aade-9ce15296c1e2

📥 Commits

Reviewing files that changed from the base of the PR and between 8da9563 and 8603615.

📒 Files selected for processing (3)
  • source/units/Goccia.Builtins.GlobalShadowRealm.pas
  • source/units/Goccia.Evaluator.pas
  • tests/built-ins/ShadowRealm/evaluate.js

frostney and others added 2 commits June 27, 2026 09:54
Top-level `return`, and unlabeled `break`/`continue` with no enclosing
iteration or switch, are Script early errors (SyntaxErrors) — eval code is
never a function body, loop, or switch. The eval-phase split surfaced these
only at runtime, via control-flow propagation in RunEvalProgramBody, which
ShadowRealm.prototype.evaluate wraps as a caller-realm TypeError.

Add ValidateEvalControlFlow to PrepareEvalProgram (the pre-execution phase),
raising a TGocciaSyntaxError directly (as the other eval early-error passes
do) so the error is classified as a static SyntaxError, not a runtime abrupt
completion. The walk visits only statements, so it stops at function/class
boundaries and never flags a return/break/continue inside a nested function;
labeled break/continue are left to the parser, which validates their targets.
RunEvalProgramBody's control-flow arms remain as a defensive backstop.

built-ins/ShadowRealm test262 stays 64/64 in both modes; language/eval-code is
unchanged (the validator now runs for direct eval too); the full repo JS suite
stays green in both modes.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ror' into claude/shadowrealm-eval-syntaxerror
@frostney frostney merged commit f0428b5 into main Jun 27, 2026
14 checks passed
@frostney frostney deleted the claude/shadowrealm-eval-syntaxerror branch June 27, 2026 10:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working spec compliance Mismatch against official JavaScript/TypeScript specification

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant