Skip to content

Fix console.log TypeError on prototype-less objects, add --inspect-depth#578

Merged
frostney merged 11 commits into
mainfrom
issue-536-console-log-null-proto
May 8, 2026
Merged

Fix console.log TypeError on prototype-less objects, add --inspect-depth#578
frostney merged 11 commits into
mainfrom
issue-536-console-log-null-proto

Conversation

@frostney
Copy link
Copy Markdown
Owner

@frostney frostney commented May 8, 2026

Summary

  • Extract shared Goccia.Values.Formatting unit with FormatForDisplay that renders values structurally (like V8/Node util.inspect) without invoking user toString()/valueOf(). This fixes console.log(Object.create(null)) throwing TypeError instead of printing {}.
  • Console (FormatArgs, ConsoleAssert, ConsoleDir, ConsoleTable) and TestingLibrary (FormatForMessage) both delegate to the single shared formatter, eliminating duplicated formatting logic.
  • Remove TGocciaObjectValue.ToDebugString — its only consumer was FormatForMessage, now superseded by FormatForDisplay.
  • Output matches V8/Node/Deno style: spaced braces ({ a: 1 } not {a: 1}), [Object]/[Array] truncation markers at depth limit, empty containers stay compact ({}, []).
  • Add --inspect-depth=N CLI flag and "inspect-depth" config key (default: 5) to control maximum object inspection depth.
  • Depth guard prevents SIGSEGV on circular or deeply nested objects.

Closes #536

Testing

  • Verified no regressions and confirmed the new feature or bugfix in end-to-end JavaScript/TypeScript tests
  • Updated documentation
  • Verified no regressions and confirmed the new feature or bugfix in native Pascal tests (if AST, scope, evaluator, or value types changed)
  • Optional: Verified no benchmark regressions or confirmed benchmark coverage for the change

Extract shared Goccia.Values.Formatting unit with FormatForDisplay that
renders values structurally without invoking user toString/valueOf,
matching V8/Node/Bun/Deno behavior. Console and TestingLibrary both
delegate to this single formatter. Remove ToDebugString from
TGocciaObjectValue since FormatForDisplay subsumes it.

Closes #536

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

vercel Bot commented May 8, 2026

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

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
gocciascript-homepage Ignored Ignored Preview May 8, 2026 2:14pm

Request Review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 8, 2026

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: f5f8360f-8388-47ca-b9e0-e5f5f5cde258

📥 Commits

Reviewing files that changed from the base of the PR and between c316529 and a02f303.

📒 Files selected for processing (1)
  • source/units/Goccia.Values.Formatting.pas

📝 Walkthrough

Walkthrough

Adds a configurable inspect-depth option and new Goccia.Values.Formatting unit (depth-limited value formatter); wires the option into CLI and app init; refactors console and testing code to use FormatForDisplay; removes TGocciaObjectValue.ToDebugString; adds console tests and updates docs/examples.

Changes

Inspect Depth Configuration and Formatting Refactor

Layer / File(s) Summary
Formatting Unit & Data Contracts
source/units/Goccia.Values.Formatting.pas
New unit exports SetInspectDepth and FormatForDisplay for recursive value formatting with depth limiting (DEFAULT_INSPECT_DEPTH = 5). Arrays/objects may render as [Array]/[Object] when depth reached.
CLI Option Declaration
source/shared/CLI.Options.pas
TGocciaEngineOptions gains FInspectDepth and public InspectDepth; option constructed/freed and appended to Options array.
Application Initialization
source/app/Goccia.CLI.Application.pas
Adds Goccia.Values.Formatting to uses; InitializeSingletons calls SetInspectDepth with configured value or DEFAULT_INSPECT_DEPTH.
Console Output Refactor
source/units/Goccia.Builtins.Console.pas
Removes private FormatValue; console formatting paths (FormatArgs, ConsoleDir, ConsoleAssert, ConsoleTable) now use FormatForDisplay.
Testing Library Formatting Updates
source/units/Goccia.Builtins.TestingLibrary.pas
Adds Goccia.Values.Formatting, removes internal FormatForMessage, and updates many matcher failure messages and async rejection formatting to use FormatForDisplay.
ObjectValue Method Removal
source/units/Goccia.Values.ObjectValue.pas, source/units/Goccia.Values.ObjectValue.Test.pas
Removes ToDebugString declaration/implementation; tests updated to use FormatForDisplay; StringBuffer removed from uses.
Tests and Documentation
tests/built-ins/console/log.js, AGENTS.md, docs/build-system.md
Adds console.log tests (prototype-less objects, toString non-invocation, Symbol, circular refs, deep nesting) and documents --inspect-depth / inspect-depth in examples.

Sequence Diagram

sequenceDiagram
  participant UserCLI
  participant AppInit
  participant EngineOptions
  participant Formatting
  UserCLI->>AppInit: start with CLI/config
  AppInit->>EngineOptions: read InspectDepth
  AppInit->>Formatting: SetInspectDepth(value)
  Formatting->>Formatting: set GInspectDepth
  UserCLI->>Formatting: console/test formatting calls -> FormatForDisplay
  Formatting->>UserCLI: formatted string
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • frostney/GocciaScript#350: Also modifies TGocciaConsole built-in and console output wiring; likely related to console output changes.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the two main changes: fixing TypeError on prototype-less objects and adding the --inspect-depth feature.
Description check ✅ Passed The description comprehensively covers the changes, implementation approach, and testing; all key sections from the template are completed with substantive information.
Linked Issues check ✅ Passed The implementation successfully addresses all coding requirements from issue #536: creates a structural formatter (FormatForDisplay) that doesn't invoke user toString(), fixes console.log for prototype-less objects, adds depth guards, and implements the --inspect-depth CLI/config option.
Out of Scope Changes check ✅ Passed All changes directly support the requirements in #536: new Formatting unit, console/testing-library integration, CLI option addition, and supporting test updates are all in-scope.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

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


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

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 8, 2026

Suite Timing

Test Runner (interpreted: 8,954 passed; bytecode: 8,954 passed)
Metric Interpreted Bytecode
Total 8954 8954
Passed 8954 ✅ 8954 ✅
Workers 4 4
Test Duration 2.10s 1.50s
Lex (cumulative) 264.3ms 118.6ms
Parse (cumulative) 258.2ms 186.3ms
Compile (cumulative) 404.0ms
Execute (cumulative) 2.49s 1.43s
Engine Total (cumulative) 3.01s 2.14s
Lex (avg/worker) 66.1ms 29.6ms
Parse (avg/worker) 64.6ms 46.6ms
Compile (avg/worker) 101.0ms
Execute (avg/worker) 622.1ms 358.4ms
Engine Total (avg/worker) 752.7ms 535.6ms

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 216.41 MiB 210.96 MiB
GC Peak Live 216.42 MiB 210.96 MiB
GC Allocated During Run 220.23 MiB 214.77 MiB
GC Limit 7.81 GiB 7.81 GiB
GC Collections 1 1
GC Collected Objects 74 74
Heap Start Allocated 146.4 KiB 146.4 KiB
Heap End Allocated 1.37 MiB 1.37 MiB
Heap Delta Allocated 1.23 MiB 1.23 MiB
Heap Delta Free 468.7 KiB 468.7 KiB
Benchmarks (interpreted: 407; bytecode: 407)
Metric Interpreted Bytecode
Total 407 407
Workers 4 4
Duration 2.56min 2.40min

Memory

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

Metric Interpreted Bytecode
GC Live 3.23 MiB 3.23 MiB
GC Peak Live 119.86 MiB 70.60 MiB
GC Allocated During Run 14.07 GiB 9.43 GiB
GC Limit 7.81 GiB 7.81 GiB
GC Collections 2,823 2,645
GC Collected Objects 263,623,990 227,458,229
Heap Start Allocated 1.13 MiB 1.13 MiB
Heap End Allocated 1.13 MiB 1.13 MiB
Heap Delta Allocated 128 B 128 B

Measured on ubuntu-latest x64.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 8, 2026

Benchmark Results

407 benchmarks

Interpreted: 🟢 15 improved · 🔴 220 regressed · 172 unchanged · avg -2.9%
Bytecode: 🟢 81 improved · 🔴 42 regressed · 284 unchanged · avg +0.4%

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

Deterministic profile diff

Deterministic profile diff: no significant changes.

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

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 8, 2026

test262 Conformance

Category Run Passed Δ Pass Failed Pass-rate Δ Rate
built-ins 23,449 14,340 +1 9,108 61.2% ±0pp
harness 116 71 ±0 45 61.2% ±0pp
intl402 3,324 167 ±0 3,157 5.0% ±0pp
language 23,635 12,572 ±0 11,063 53.2% ±0pp
staging 1,483 471 ±0 1,010 31.8% ±0pp
total 52,007 27,621 +1 24,383 53.1% ±0pp

Areas closest to 100%

Area Pass rate Δ vs main Passing
built-ins/WeakSet 98.8% ±0pp 84 / 85
built-ins/WeakMap 98.6% ±0pp 139 / 141
language/asi 97.1% ±0pp 99 / 102
Per-test deltas (+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 and others added 5 commits May 8, 2026 12:11
Prevent SIGSEGV on circular or deeply nested objects by capping
recursion at 5 levels, rendering {...} / [...] at the limit.
Remove now-unused Goccia.Values.SymbolValue import from TestingLibrary.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Rename the generic DoFormat helper to FormatRecursive for clarity per
the project's explicitness convention. Switch FormatObject from
GetEnumerablePropertyNames + per-key GetProperty to
GetEnumerablePropertyEntries, avoiding N redundant hash lookups.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Match V8/Node/Deno output style:
- Truncation markers: [Object] and [Array] instead of {...} and [...]
- Spaced output: { a: 1 } instead of {a: 1} (empty objects stay {})
- Configurable depth via --inspect-depth CLI flag and goccia.json
  (default: 5, stored in module-level var, set in InitializeSingletons)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Empty arrays now render as [] (matching Node) instead of [  ].
Add --inspect-depth to the run commands reference.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@frostney frostney changed the title Fix console.log TypeError on prototype-less objects Fix console.log TypeError on prototype-less objects, add --inspect-depth May 8, 2026
@frostney frostney marked this pull request as ready for review May 8, 2026 12:19
@coderabbitai coderabbitai Bot added bug Something isn't working documentation Improvements or additions to documentation new feature New feature or request labels May 8, 2026
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
source/units/Goccia.Values.Formatting.pas (1)

114-115: 💤 Low value

Consider escaping single quotes in nested string values.

When a nested string contains a single quote (e.g., "it's"), the current output will be 'it's', which visually breaks the quoting. Consider escaping inner quotes as \' for clearer output: 'it\'s'.

This is a minor display issue and can be deferred if the current behavior is acceptable for console output.

Optional escaping improvement
  else if ANested and (AValue is TGocciaStringLiteralValue) then
-    Result := '''' + AValue.ToStringLiteral.Value + ''''
+    Result := '''' + StringReplace(AValue.ToStringLiteral.Value, '''', '\''', [rfReplaceAll]) + ''''

Note: This would require adding StrUtils to the uses clause for StringReplace.

🤖 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.Values.Formatting.pas` around lines 114 - 115, The branch
that generates nested string output in Goccia.Values.Formatting (the else-if
handling ANested and AValue is TGocciaStringLiteralValue) must escape single
quotes inside the string literal before surrounding it with outer quotes; update
the logic that uses AValue.ToStringLiteral.Value to run a replace of ' with \'
(e.g. via StringReplace) and then return the quoted escaped value, and add
StrUtils to the uses clause so StringReplace is available.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@source/units/Goccia.Builtins.TestingLibrary.pas`:
- Around line 307-310: FormatForMessage currently calls FormatForDisplay and
returns quoted/display-formatted strings which breaks matcher logic (used in
toMatch, toContain, toHaveLength). Update FormatForMessage so it preserves raw
string semantics for string-typed TGocciaValue (return the underlying unquoted
string or length-sensitive representation) and only uses FormatForDisplay for
non-string types (or create a separate FormatForMatcher helper and switch
callers to it). Modify the implementation of FormatForMessage (and replace
usages in matcher code paths) to ensure substring and length checks operate on
the raw string value rather than the quoted/display format.

---

Nitpick comments:
In `@source/units/Goccia.Values.Formatting.pas`:
- Around line 114-115: The branch that generates nested string output in
Goccia.Values.Formatting (the else-if handling ANested and AValue is
TGocciaStringLiteralValue) must escape single quotes inside the string literal
before surrounding it with outer quotes; update the logic that uses
AValue.ToStringLiteral.Value to run a replace of ' with \' (e.g. via
StringReplace) and then return the quoted escaped value, and add StrUtils to the
uses clause so StringReplace is available.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 1b53fb1a-a2b8-4637-86ee-89a19c9c7626

📥 Commits

Reviewing files that changed from the base of the PR and between 236b6f4 and 9669b42.

📒 Files selected for processing (10)
  • AGENTS.md
  • docs/build-system.md
  • source/app/Goccia.CLI.Application.pas
  • source/shared/CLI.Options.pas
  • source/units/Goccia.Builtins.Console.pas
  • source/units/Goccia.Builtins.TestingLibrary.pas
  • source/units/Goccia.Values.Formatting.pas
  • source/units/Goccia.Values.ObjectValue.Test.pas
  • source/units/Goccia.Values.ObjectValue.pas
  • tests/built-ins/console/log.js
💤 Files with no reviewable changes (1)
  • source/units/Goccia.Values.ObjectValue.pas

Comment thread source/units/Goccia.Builtins.TestingLibrary.pas Outdated
Replace with existing First flag — after the loop, not First is
equivalent to HasEntries. One fewer local to track.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@coderabbitai coderabbitai Bot added the internal Refactoring, CI, tooling, cleanup label May 8, 2026
Remove the trivial one-line wrapper and replace all 73 callsites in
TestingLibrary with direct FormatForDisplay calls. FormatThrowValueDetail
is kept — it has real logic (stack/message extraction from error objects).

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

frostney commented May 8, 2026

@coderabbitai full review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 8, 2026

✅ Actions performed

Full review triggered.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

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.Builtins.TestingLibrary.pas (1)

311-324: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Avoid reading arbitrary message/stack properties while formatting thrown values.

This helper still calls GetProperty(PROP_MESSAGE/PROP_STACK) on any thrown object. For non-error objects, that can execute user accessors while building the failure text, and a throwing getter will mask the original exception. Restrict the special case to real error objects (HasErrorData) or fall back to FormatForDisplay if property access fails.

💡 Minimal hardening
 function FormatThrowValueDetail(const AValue: TGocciaValue): string;
 var
   MsgValue, StackValue: TGocciaValue;
 begin
-  if AValue is TGocciaObjectValue then
+  if (AValue is TGocciaObjectValue) and TGocciaObjectValue(AValue).HasErrorData then
   begin
-    MsgValue := TGocciaObjectValue(AValue).GetProperty(PROP_MESSAGE);
-    StackValue := TGocciaObjectValue(AValue).GetProperty(PROP_STACK);
+    try
+      MsgValue := TGocciaObjectValue(AValue).GetProperty(PROP_MESSAGE);
+      StackValue := TGocciaObjectValue(AValue).GetProperty(PROP_STACK);
+    except
+      Exit(FormatForDisplay(AValue));
+    end;
     if Assigned(StackValue) and (StackValue is TGocciaStringLiteralValue) and
        (TGocciaStringLiteralValue(StackValue).Value <> '') then
       Result := TGocciaStringLiteralValue(StackValue).Value
     else if Assigned(MsgValue) and (MsgValue is TGocciaStringLiteralValue) then
       Result := TGocciaStringLiteralValue(MsgValue).Value
     else
       Result := FormatForDisplay(AValue);
   end
   else
     Result := FormatForDisplay(AValue);
 end;
🤖 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.Builtins.TestingLibrary.pas` around lines 311 - 324, The
code calls TGocciaObjectValue.GetProperty(PROP_MESSAGE/PROP_STACK) for any
thrown object which can execute user getters and mask the original exception;
update the block that handles TGocciaObjectValue (in this file/function) to only
attempt reading PROP_MESSAGE/PROP_STACK for bona fide error objects (e.g. when
TGocciaObjectValue.HasErrorData returns true) and/or wrap each GetProperty call
in a try..except that on exception falls back to FormatForDisplay(AValue);
ensure you still prefer stack then message when safe but always return
FormatForDisplay if property access fails or HasErrorData is false.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@source/units/Goccia.Values.Formatting.pas`:
- Around line 31-34: SetInspectDepth currently only enforces a minimum and can
be set arbitrarily large; change it to clamp ADepth between 1 and a reasonable
upper bound (e.g. INSPECT_DEPTH_MAX) before assigning to GInspectDepth.
Introduce a constant (INSPECT_DEPTH_MAX) near the existing declarations and
update procedure SetInspectDepth to use Min(Max(1, ADepth), INSPECT_DEPTH_MAX)
(referencing SetInspectDepth and GInspectDepth) so very large --inspect-depth
values cannot bypass the recursion guard.
- Around line 111-113: The current branch that handles nested
TGocciaStringLiteralValue in the formatting routine returns '''' +
AValue.ToStringLiteral.Value + '''' without escaping interior characters; update
the branch that checks "ANested and (AValue is TGocciaStringLiteralValue)" to
escape single quotes, backslashes and control characters in the string content
before surrounding with single quotes (use or add a small helper such as
EscapeForSingleQuoted or reuse an existing ToEscapedString/ToStringLiteral
method on TGocciaStringLiteralValue), ensuring the function that formats values
(the routine containing that branch) calls the escape helper on
AValue.ToStringLiteral.Value and then returns the quoted escaped result.

---

Outside diff comments:
In `@source/units/Goccia.Builtins.TestingLibrary.pas`:
- Around line 311-324: The code calls
TGocciaObjectValue.GetProperty(PROP_MESSAGE/PROP_STACK) for any thrown object
which can execute user getters and mask the original exception; update the block
that handles TGocciaObjectValue (in this file/function) to only attempt reading
PROP_MESSAGE/PROP_STACK for bona fide error objects (e.g. when
TGocciaObjectValue.HasErrorData returns true) and/or wrap each GetProperty call
in a try..except that on exception falls back to FormatForDisplay(AValue);
ensure you still prefer stack then message when safe but always return
FormatForDisplay if property access fails or HasErrorData is false.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 97365227-5ccc-4421-82c4-19c6f6da6727

📥 Commits

Reviewing files that changed from the base of the PR and between 236b6f4 and 8672d67.

📒 Files selected for processing (10)
  • AGENTS.md
  • docs/build-system.md
  • source/app/Goccia.CLI.Application.pas
  • source/shared/CLI.Options.pas
  • source/units/Goccia.Builtins.Console.pas
  • source/units/Goccia.Builtins.TestingLibrary.pas
  • source/units/Goccia.Values.Formatting.pas
  • source/units/Goccia.Values.ObjectValue.Test.pas
  • source/units/Goccia.Values.ObjectValue.pas
  • tests/built-ins/console/log.js
💤 Files with no reviewable changes (1)
  • source/units/Goccia.Values.ObjectValue.pas

Comment thread source/units/Goccia.Values.Formatting.pas
Comment thread source/units/Goccia.Values.Formatting.pas
frostney and others added 3 commits May 8, 2026 14:12
A very large --inspect-depth on a circular object could overflow the
native call stack. Cap at 64 which is far beyond practical use while
keeping recursion safe.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Use single quotes by default, double quotes when the string contains
a single quote, backticks when it contains both. Matches V8/Node
util.inspect output exactly.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@frostney frostney merged commit f163437 into main May 8, 2026
14 checks passed
@frostney frostney deleted the issue-536-console-log-null-proto branch May 8, 2026 14:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working documentation Improvements or additions to documentation internal Refactoring, CI, tooling, cleanup new feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

console.log on prototype-less object throws TypeError

1 participant