Skip to content

Add Report issue button to playground#477

Merged
frostney merged 7 commits into
mainfrom
t3code/playground-github-issue-button
Apr 30, 2026
Merged

Add Report issue button to playground#477
frostney merged 7 commits into
mainfrom
t3code/playground-github-issue-button

Conversation

@frostney
Copy link
Copy Markdown
Owner

Summary

  • New "Report issue" button in the playground header opens github.com/frostney/GocciaScript/issues/new in a new tab, pre-filled with a back-link to the current playground state and a markdown table of the active settings (backend, runner, version, ASI, compat var/function).
  • Share-URL building is factored out of the existing share callback into buildShareLink, so the Share button and the new issue link share one source of truth.

Test plan

  • Open the playground, edit some code, click Report issue — verify a new tab opens to issues/new with the playground link, settings table, and "expected/actual" sections pre-filled.
  • Click the playground link from inside the issue body — verify it round-trips the code and configuration back into the playground.
  • Toggle each of backend, runner, version, ASI, and the two compat flags — verify each is reflected in the settings table the next time Report issue is clicked.
  • Click Share — verify it still copies a working share URL (no regression).

🤖 Generated with Claude Code

Adds a "Report issue" button next to Share that opens
github.com/frostney/GocciaScript/issues/new in a new tab, pre-filled
with a link back to the current playground state (via the same
encoded share URL) and a markdown table of the active configuration:
backend, runner, version, ASI, and the var/function compat flags.

The share-URL builder is factored out of the existing share callback
into buildShareLink so both buttons share one source of truth — if
the share payload shape changes, the issue link tracks automatically.

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

vercel Bot commented Apr 30, 2026

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

Project Deployment Actions Updated (UTC)
gocciascript-homepage Ready Ready Preview, Comment Apr 30, 2026 2:30am

Request Review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 30, 2026

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: ceed34dd-45c4-433c-9308-c41b1f6ccfef

📥 Commits

Reviewing files that changed from the base of the PR and between 7f5b841 and 25cb548.

📒 Files selected for processing (5)
  • website/src/components/animated-output.tsx
  • website/src/components/command-tabs.tsx
  • website/src/components/landing.tsx
  • website/src/components/playground.tsx
  • website/src/components/sandbox.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
  • website/src/components/landing.tsx

📝 Walkthrough

Walkthrough

Adds platform-aware Run shortcut labels and visible hints, wires Ctrl/Cmd+Enter submit from editors to Run, prevents overlapping executes with a running guard, adds playground share/report-issue builders, and updates console/typewriter CSS to avoid wrapping and allow horizontal scroll for long commands.

Changes

Cohort / File(s) Summary
Styling & Console
website/src/app/globals.css
Added .pg-run-kbd, .hero-action-kbd. Changed .console-panel and .anim-output-text to white-space: pre. Reworked .anim-output-typed to chain typewriter-expand then typewriter-unclip so long commands can extend and be scrolled horizontally.
Editor submit handling
website/src/components/highlighted-textarea.tsx
Added optional onSubmit?: () => void prop; handle Ctrl/Cmd+Enter to prevent newline and invoke onSubmit.
Run shortcut hook & types
website/src/components/command-tabs.tsx
Added exported RunShortcut type and useRunShortcut() hook that selects macOS vs. Ctrl labels, rendering a deterministic macOS label during SSR then re-detecting on client.
Landing & Animated hints
website/src/components/landing.tsx, website/src/components/animated-output.tsx
Consume useRunShortcut() to set Run button/tooltips and replace hardcoded ⌘+Enter hints with runtime runShortcut.long and visible runShortcut.short.
Playground: share & report
website/src/components/playground.tsx
Added buildShareLink() for share URLs; refactored clipboard share to use it. Added reportIssue() to open a prefilled GitHub issue with current settings and playground link. Toolbar UI: added "Report issue" button and visible Run shortcut hint.
Sandbox & execution flow
website/src/components/sandbox.tsx
Standardized label to "Run". Introduced runningRef re-entry guard set after validation and cleared in finally to block overlapping /api/execute requests. Wired both editors to call execute via onSubmit. Run button now displays shortcut hint and tooltip.

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant Editor as HighlightedTextarea
  participant UI as Sandbox/Playground UI
  participant Server as /api/execute
  participant Output as AnimatedOutput

  User->>Editor: Ctrl/Cmd+Enter (onSubmit)
  Editor->>UI: invoke execute()
  UI->>UI: sync validation/build (sets runningRef)
  UI->>Server: POST /api/execute (request)
  Server-->>UI: execution result
  UI->>Output: render result (typewriter/console CSS)
  UI->>UI: clear runningRef (finally)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • #447: Overlapping edits to playground/sandbox run-button shortcuts and runningRef re-entry guard logic.
  • #445: Related UI and styling updates touching landing, sandbox, playground, and globals.css.
  • #418: Changes to console/typewriter behavior and AnimatedOutput/HighlightedTextarea surfaces.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 40.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main feature addition (Report issue button) and matches the primary objective of the PR, though it doesn't capture the equally significant Run shortcut detection implementation.
Description check ✅ Passed The description covers the Summary and Test plan sections from the template and documents the Report issue feature and Share URL refactoring, but the Testing checkboxes lack verification status marks or explanations.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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


Review rate limit: 0/5 reviews remaining, refill in 54 minutes and 46 seconds.

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

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 30, 2026

Suite Timing

Suite Metric Interpreted Bytecode
Tests Total 8307 8307
Tests Passed 8266 ✅ 8307 ✅
Tests Skipped 41 0
Tests Workers 4 4
Tests Test Duration 1.80s 1.90s
Tests Lex (cumulative) 197.0ms 136.5ms
Tests Parse (cumulative) 334.2ms 354.1ms
Tests Compile (cumulative) 213.4ms
Tests Execute (cumulative) 1.48s 1.47s
Tests Engine Total (cumulative) 2.01s 2.17s
Tests Lex (avg/worker) 49.3ms 34.1ms
Tests Parse (avg/worker) 83.5ms 88.5ms
Tests Compile (avg/worker) 53.3ms
Tests Execute (avg/worker) 369.3ms 367.4ms
Tests Engine Total (avg/worker) 502.1ms 543.4ms
Benchmarks Total 407 407
Benchmarks Workers 4 4
Benchmarks Duration 2.64min 2.40min

Measured on ubuntu-latest x64.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 30, 2026

Benchmark Results

407 benchmarks

Interpreted: 🟢 402 improved · 🔴 4 regressed · 1 unchanged · avg +27.8%
Bytecode: 🟢 47 improved · 🔴 248 regressed · 112 unchanged · avg -3.1%

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

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.

The floating "⌘ + Enter" text in the playground header used to sit
beside the Run button, but the new Report issue / Share buttons now
visually separate the hint from its target. Move the shortcut into
the button itself as a subdued monospace tail (Run ⌘↵) — the hint is
physically welded to the action it describes, matching the pattern
used in command palettes (Linear, Raycast).

Apply the same treatment everywhere a Run-style button appears:

- Playground Run button: drop the floating span, inline the kbd tail.
- Landing hero Run button: inline the kbd tail (smaller variant).
- Sandbox Execute button: inline the kbd tail. Previously the sandbox
  had no ⌘+Enter handler at all, so wire one up via a new optional
  onSubmit prop on HighlightedTextarea — pressing ⌘/Ctrl+Enter inside
  either the script or globals editor now fires Execute.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Aligns the sandbox primary action with the playground and landing-page
buttons that already say Run, so the same verb describes the same code-
execution action everywhere on the site. Updates the button label, the
title= tooltip, and the surrounding prose ("hit Run") accordingly.

Internal identifiers (the execute() callback, the /api/execute endpoint,
and the tool description) are left as-is since renaming them would be
churn unrelated to the user-visible label.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
`.console-panel` and `.anim-output-text` used `white-space: pre-wrap`,
which wraps long output lines at whitespace and silently overflows on
unbreakable tokens (stringified blobs, file paths, long error messages).
Either way the user couldn't see the full line — wrapped lines looked
truncated, and overflowing tokens had no visible scrollbar to access
the rest.

Switching to `white-space: pre` keeps long lines on a single line so
the panel's existing `overflow: auto` surfaces a horizontal scrollbar
when needed. Matches how a real terminal renders output.

Affects all three console panels (playground, sandbox, landing-page
hero) since they share the `.console-panel` class — consistent
terminal-like behavior site-wide.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The first meta line in AnimatedOutput renders inside .anim-output-typed,
which uses `overflow: hidden` + an animated `max-width: 0 → 100%` to
produce the typewriter reveal effect. After the 0.6s animation the
`forwards` fill mode keeps both constraints applied, so a command line
longer than the panel — e.g. the sandbox banner
"GocciaScriptLoader --timeout=500 --globals=context.json" — gets
silently clipped at the panel's right edge with no way to access the
rest. The .console-panel parent never sees the overflow because the
clip happens before it bubbles up, so its overflow: auto can't help.

Chain a `typewriter-unclip` animation at 0.6s delay (matches the
existing `caret-typing-hide` pattern in this file) that snaps
overflow to visible and max-width to none. The reveal effect still
works during 0–0.6s — base CSS `overflow: hidden` is in force — but
once the line is fully typed, the constraints release and a long
command extends past the panel's edge, triggering the panel's
horizontal scrollbar.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@frostney frostney marked this pull request as ready for review April 30, 2026 02:14
@coderabbitai coderabbitai Bot added new feature New feature or request internal Refactoring, CI, tooling, cleanup labels Apr 30, 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)
website/src/components/playground.tsx (1)

1145-1151: ⚡ Quick win

Use a platform-neutral shortcut label in the Run hint.

The UI hint/title currently shows only , but the handler accepts both Meta and Ctrl (Line 1280). Consider a neutral label like Ctrl/⌘+Enter to avoid misleading Windows/Linux users.

Also applies to: 1280-1283

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@website/src/components/playground.tsx` around lines 1145 - 1151, Update the
platform-specific Run hint to a neutral label: change the title string "Run ·
⌘+Enter" and the visible span content "⌘↵" (in the Run button that renders
RunIcon and span with className "pg-run-kbd") to a platform-neutral label such
as "Ctrl/⌘+Enter" (or visible "Ctrl/⌘↵"); also update the other matching
occurrence referenced by the keyboard handler that accepts both Meta and Ctrl
(the keydown handler using Meta/Ctrl around the handleKeyDown/event listener) so
the UI text matches the actual shortcut behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@website/src/components/sandbox.tsx`:
- Around line 739-740: The execute handler can be invoked concurrently via
keyboard submit even when the UI button is disabled; add a re-entry guard inside
execute itself by introducing an internal boolean/ref flag (e.g., executingRef
or isExecuting state) that is checked at the very start of execute and returns
early if already set, then set the flag immediately before running and clear it
in a finally block after the run completes or errors; update any existing places
that set/clear run state (used by the submit button) to rely on this same flag
so Ctrl/⌘+Enter submits are ignored while a run is in flight.

---

Nitpick comments:
In `@website/src/components/playground.tsx`:
- Around line 1145-1151: Update the platform-specific Run hint to a neutral
label: change the title string "Run · ⌘+Enter" and the visible span content "⌘↵"
(in the Run button that renders RunIcon and span with className "pg-run-kbd") to
a platform-neutral label such as "Ctrl/⌘+Enter" (or visible "Ctrl/⌘↵"); also
update the other matching occurrence referenced by the keyboard handler that
accepts both Meta and Ctrl (the keydown handler using Meta/Ctrl around the
handleKeyDown/event listener) so the UI text matches the actual shortcut
behavior.
🪄 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: 59fc1aba-5850-4527-a600-ab781c7451b8

📥 Commits

Reviewing files that changed from the base of the PR and between 06ab386 and b406eb6.

📒 Files selected for processing (5)
  • website/src/app/globals.css
  • website/src/components/highlighted-textarea.tsx
  • website/src/components/landing.tsx
  • website/src/components/playground.tsx
  • website/src/components/sandbox.tsx

Comment thread website/src/components/sandbox.tsx
The Run button is `disabled` while running, but the ⌘/Ctrl+Enter
shortcut on the script and globals editors bypasses that — the
keyboard path goes straight through HighlightedTextarea's onSubmit
into execute(). Without a re-entry guard, a fast double-press fires
two execute() invocations: the first awaits its fetch, control
returns to the event loop, the second press's handler runs, sails
past validation, calls setRunning(true) (idempotent), and starts a
second concurrent /api/execute request that then races the first
into setOutput.

Adopt the same `runningRef = useRef(false)` pattern the playground
already uses (playground.tsx lines 464, 552–554, 736–737):
- Check ref at the top of execute and bail if a run is in flight.
- Set ref *after* the synchronous validation guards (so a validation
  early-return doesn't leak the flag into a stuck state).
- Clear ref in the finally block paired with setRunning(false).

A ref is required because the useCallback closure captures a stale
`running` value across renders — only a ref reads the latest value
synchronously inside the handler.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The keydown handlers all bind on `metaKey || ctrlKey`, so the same
physical combo runs the script on every platform — but the visible
labels were hardcoded to ⌘ everywhere, so users on Linux/Windows
saw a Mac symbol that doesn't match their keyboard. Apply the same
treatment the install page already uses for OS-aware tabs: detect
on the client via navigator.userAgent and re-render with the right
label.

Add a `useRunShortcut()` hook to command-tabs.tsx (next to the
existing `detectOs` / `detectArch` helpers) returning two strings:
`short` for inline button tails ("⌘↵" / "Ctrl+↵") and `long` for
tooltips and prose ("⌘+Enter" / "Ctrl+Enter"). SSR renders the
macOS form so the markup is deterministic, then the client useEffect
swaps to Ctrl on Linux/Windows after hydration — same shape and
trade-off as `<QuickInstall>`.

Wire it through every kbd-hint surface:
- Playground Run button (title + .pg-run-kbd tail)
- Landing hero Run button (title + .hero-action-kbd tail)
- Sandbox Run button (title + .pg-run-kbd tail)
- AnimatedOutput idle hint ("press Run or …")

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@frostney frostney merged commit d819ad6 into main Apr 30, 2026
12 checks passed
@frostney frostney deleted the t3code/playground-github-issue-button branch April 30, 2026 02:50
frostney added a commit that referenced this pull request Apr 30, 2026
Resolves an import-block conflict in `website/src/components/playground.tsx`
where main (#477) added `import { GITHUB_REPO_URL } from "@/lib/github"`
on the same lines this branch added
`import { formatMemorySegments, type MemoryJson } from "@/lib/format-memory"`.
Kept both, alphabetically sorted (format-memory < github).

Other website files (landing.tsx, sandbox.tsx, goccia-api.ts) auto-merged
cleanly: main's `useRunShortcut` import (also from #477) and this branch's
memory-display additions touch independent regions of each file. Verified
with tsc, biome, and bun test (143/143 pass).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

internal Refactoring, CI, tooling, cleanup new feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant