Skip to content

Allow var/function declarations to shadow built-in globals in script mode#577

Merged
frostney merged 5 commits into
mainfrom
issue-521-var-function-shadow-builtins
May 8, 2026
Merged

Allow var/function declarations to shadow built-in globals in script mode#577
frostney merged 5 commits into
mainfrom
issue-521-var-function-shadow-builtins

Conversation

@frostney
Copy link
Copy Markdown
Owner

@frostney frostney commented May 8, 2026

Summary

  • Allow top-level var, function, and var-destructuring declarations to shadow built-in globals (Array, NaN, Infinity, undefined, etc.) in script mode, per ES2026 §16.1.7 GlobalDeclarationInstantiation.
  • Previously all such redeclarations were rejected with a SyntaxError regardless of declaration kind or script-vs-module mode. Now only let/const/class redeclarations of built-in globals are blocked.
  • Adds a BuiltIn flag to TLexicalBinding so the engine can distinguish engine-registered bindings from user declarations. All built-in registration sites pass True at the call site. User-injected globals (RegisterGlobal) are intentionally not marked built-in.
  • CheckTopLevelRedeclarations skips var/function declarations when the existing binding is built-in; CheckPatternRedeclarations receives the IsVar flag so var-destructuring patterns get the same exemption.
  • DefineVariableBinding removes the built-in lexical binding at runtime (preserving the original value for bare var NaN;-style declarations without initializers) so the var binding becomes visible through GetBinding. The built-in check is guarded by skGlobal to skip the probe for function/module-scoped vars.
  • All TLexicalBinding creation sites (PredeclareLexicalBinding, DefineLexicalBinding materialization branch, DefineVariableBinding first-declaration branch) explicitly initialize the BuiltIn field.
  • Closes Engine: var/function declarations cannot shadow built-in globals (Array, NaN, Infinity, undefined) in script mode #521, closes var destructuring declarations should be exempt from built-in global redeclaration check #580

Testing

  • Verified no regressions and confirmed the new feature or bugfix in end-to-end JavaScript/TypeScript tests
    • 8901/8906 tests pass (5 pre-existing FFI fixture failures)
    • New tests cover var shadowing (NaN, Infinity, undefined, Array), function shadowing (Array, Object, Error), function-scoped var NaN = 42, and let/const block-scope shadowing
    • Verified in both interpreter and bytecode modes
  • Updated documentation
  • Optional: Verified no regressions and confirmed the new feature or bugfix in native Pascal tests (if AST, scope, evaluator, or value types changed)
  • Optional: Verified no benchmark regressions or confirmed benchmark coverage for the change

…mode (#521)

Per ES2026 §16.1.7, top-level var and function declarations may shadow
built-in globals (Array, NaN, Infinity, undefined, etc.) in script mode.
Previously all such redeclarations were rejected with SyntaxError.

Add a BuiltIn flag to TLexicalBinding so the engine can distinguish
engine-registered bindings from user declarations. CheckTopLevelRedeclarations
now skips var/function declarations when the existing binding is built-in,
and DefineVariableBinding removes the built-in lexical binding at runtime
so the var binding becomes visible through GetBinding.

Closes #521

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

vercel Bot commented May 8, 2026

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

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

Request Review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 8, 2026

Review Change Stack

📝 Walkthrough

Walkthrough

This PR implements built-in global shadowing support by adding a BuiltIn flag to lexical bindings, extending TGocciaScope.DefineLexicalBinding to accept ABuiltIn and exposing IsBuiltInBinding, updating variable binding and redeclaration checks to allow script-mode var/function shadowing of built-ins, marking builtin registrations accordingly, and adding tests verifying shadowing rules.

Changes

Built-in Global Shadowing Support

Layer / File(s) Summary
Lexical Binding Metadata
source/units/Goccia.Scope.BindingMap.pas
TLexicalBinding record gains a new BuiltIn: Boolean field to mark whether a binding represents a built-in global.
Scope API Signatures
source/units/Goccia.Scope.pas
DefineLexicalBinding signature extended with ABuiltIn: Boolean = False; new IsBuiltInBinding helper added.
Scope Implementation
source/units/Goccia.Scope.pas
DefineLexicalBinding persists the BuiltIn flag; PredeclareLexicalBinding initializes BuiltIn := False; IsBuiltInBinding implemented.
Variable Shadowing Logic
source/units/Goccia.Scope.pas
DefineVariableBinding computes EffectiveValue to reuse built-in when no initializer or use declared initializer when present; removes built-in binding when shadowing applies and creates var binding with BuiltIn := False.
Redeclaration Rules
source/units/Goccia.Scope.Redeclaration.pas
CheckTopLevelRedeclarations and pattern redeclaration checks now allow var/function redeclarations to shadow built-in bindings; other redeclaration rules unchanged.
Global Built-in Registration
source/units/Goccia.Builtins.*.pas, source/units/Goccia.Builtins.Globals.pas
Many built-in registration sites updated to call DefineLexicalBinding(..., dtConst/dtLet, True) marking those bindings as built-in.
Engine Constructor Registration
source/units/Goccia.Engine.pas
Engine-registered constructors and injected globals updated to pass ABuiltIn=True.
Type & Runtime Constructor Registration
source/units/Goccia.ObjectModel.Engine.pas, source/units/Goccia.Runtime.pas
Type-defined constructors and runtime constructors (e.g., performance) registered with ABuiltIn=True.
Tests: const Shadowing
tests/language/declarations/const/cannot-shadow-builtin-globals.js
Verifies const cannot shadow built-ins at top level but can inside nested blocks.
Tests: let Shadowing
tests/language/declarations/let/cannot-shadow-builtin-globals.js
Verifies let shadowing in nested blocks with outer scope preserved.
Tests: var Shadowing
tests/language/var/shadow-builtin-globals.js
Verifies top-level var shadowing behavior and preservation of built-ins when uninitialized.
Tests: function Shadowing
tests/language/function-keyword/shadow-builtin-globals.js
Verifies top-level function declarations can shadow built-ins in script mode.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Possibly related issues

  • #580: Adds built-in exemption for var destructuring patterns — related to the redeclaration/destructuring changes in this PR.

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically describes the main change: enabling var/function declarations to shadow built-in globals in script mode, which is the primary objective of this PR.
Linked Issues check ✅ Passed The PR successfully implements the requirements from issue #521: allows var/function to shadow built-ins in script mode, adds BuiltIn flag distinction, updates redeclaration checks to exempt built-ins, preserves let/const restrictions, and includes comprehensive tests covering all shadowing scenarios.
Out of Scope Changes check ✅ Passed All changes are scoped to enabling var/function shadowing of built-in globals. Updates include the BuiltIn flag infrastructure, redeclaration logic, binding registration across all builtin units, and corresponding tests—all directly supporting the linked issue objective.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Description check ✅ Passed The PR description comprehensively addresses all required template sections with clear explanations of changes, implementation details, test coverage, and issue closure references.

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


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

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 8, 2026

Suite Timing

Test Runner (interpreted: 8,940 passed; bytecode: 8,940 passed)
Metric Interpreted Bytecode
Total 8940 8940
Passed 8940 ✅ 8940 ✅
Workers 4 4
Test Duration 1.90s 2.10s
Lex (cumulative) 240.9ms 166.0ms
Parse (cumulative) 251.2ms 271.4ms
Compile (cumulative) 594.4ms
Execute (cumulative) 1.85s 1.85s
Engine Total (cumulative) 2.34s 2.88s
Lex (avg/worker) 60.2ms 41.5ms
Parse (avg/worker) 62.8ms 67.8ms
Compile (avg/worker) 148.6ms
Execute (avg/worker) 462.1ms 462.7ms
Engine Total (avg/worker) 585.2ms 720.6ms

Memory

GC rows aggregate the main thread plus all worker thread-local GCs. Test runner worker shutdown frees thread-local heaps in bulk; that shutdown reclamation is not counted as GC collections or collected objects.

Metric Interpreted Bytecode
GC Live 216.22 MiB 210.77 MiB
GC Peak Live 216.22 MiB 210.78 MiB
GC Allocated During Run 220.03 MiB 214.58 MiB
GC Limit 7.81 GiB 7.81 GiB
GC Collections 1 1
GC Collected Objects 74 74
Heap Start Allocated 146.2 KiB 146.2 KiB
Heap End Allocated 1.37 MiB 1.37 MiB
Heap Delta Allocated 1.23 MiB 1.23 MiB
Heap Delta Free 468.8 KiB 468.8 KiB
Benchmarks (interpreted: 407; bytecode: 407)
Metric Interpreted Bytecode
Total 407 407
Workers 4 4
Duration 2.64min 2.33min

Memory

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

Metric Interpreted Bytecode
GC Live 3.23 MiB 3.23 MiB
GC Peak Live 135.75 MiB 72.44 MiB
GC Allocated During Run 19.83 GiB 9.55 GiB
GC Limit 7.81 GiB 7.81 GiB
GC Collections 2,847 2,644
GC Collected Objects 372,374,180 227,382,344
Heap Start Allocated 1.13 MiB 1.13 MiB
Heap End Allocated 1.13 MiB 1.13 MiB
Heap Delta Allocated 128 B 128 B

Measured on ubuntu-latest x64.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 8, 2026

Benchmark Results

407 benchmarks

Interpreted: 🟢 401 improved · 🔴 4 regressed · 2 unchanged · avg +35.2%
Bytecode: 🟢 66 improved · 🔴 54 regressed · 287 unchanged · avg +0.2%

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

Deterministic profile diff

Deterministic profile diff: no significant changes.

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

- Initialize BuiltIn := False in PredeclareLexicalBinding to avoid
  undefined record field values.
- Restructure CheckTopLevelRedeclarations so var/function declarations
  still error against user-declared lexical bindings (let/const from a
  prior script evaluation) — only built-in bindings are exempt.
- Move function shadowing tests to file level so they exercise the
  CheckTopLevelRedeclarations path.
- Remove eval-based let/const tests (eval is undefined in GocciaScript);
  replace with valid block-scope shadowing tests.
- Use bare `var NaN;` (not `var NaN = 42`) since NaN on globalThis is
  non-writable per §19.1 and strict mode correctly throws TypeError on
  assignment to non-writable properties.

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

github-actions Bot commented May 8, 2026

test262 Conformance

Category Run Passed Δ Pass Failed Pass-rate Δ Rate
built-ins 23,448 14,339 +2 9,108 61.2% ±0pp
harness 116 71 ±0 45 61.2% ±0pp
intl402 3,324 167 ±0 3,157 5.0% ±0pp
language 23,635 12,572 +6 11,063 53.2% ±0pp
staging 1,483 470 +1 1,011 31.7% +0.1pp
total 52,006 27,619 +9 24,384 53.1% ±0pp

Areas closest to 100%

Area Pass rate Δ vs main Passing
built-ins/WeakSet 98.8% ±0pp 84 / 85
built-ins/WeakMap 98.6% ±0pp 139 / 141
language/asi 97.1% ±0pp 99 / 102
Per-test deltas (+9 / -0)

Newly passing (9):

  • built-ins/Number/prototype/toExponential/undefined-fractiondigits.js
  • built-ins/Object/keys/15.2.3.14-2-3.js
  • language/types/number/S8.5_A10_T1.js
  • language/types/number/S8.5_A10_T2.js
  • language/types/number/S8.5_A4_T1.js
  • language/types/number/S8.5_A4_T2.js
  • language/types/undefined/S8.1_A3_T1.js
  • language/types/undefined/S8.1_A3_T2.js
  • staging/sm/misc/redeclare-var-non-writable-property.js

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

frostney and others added 2 commits May 8, 2026 11:59
Bare `var NaN;` at the top level tests the §16.1.7 declaration path.
Function-scoped `var NaN = 42` verifies a local binding is created
with the initializer value (42), independent of the global NaN property.

Top-level `var NaN = 42` correctly throws TypeError because globalThis.NaN
is {writable: false} per §19.1 and strict mode rejects the assignment, but
testing that path via toThrow is blocked by a pre-existing segfault in the
test library when the callback does not throw.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Built-in bindings only exist on the global scope. Skip the TryGetValue
probe in DefineVariableBinding for function/module-scoped vars, which
is the common case during execution.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@frostney frostney marked this pull request as ready for review May 8, 2026 11:16
@coderabbitai coderabbitai Bot added bug Something isn't working spec compliance Mismatch against official JavaScript/TypeScript specification internal Refactoring, CI, tooling, cleanup labels May 8, 2026
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

Caution

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

⚠️ Outside diff range comments (2)
source/units/Goccia.Scope.pas (2)

353-368: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Propagate ABuiltIn when materializing a predeclared binding.

The new parameter is ignored on the not ExistingLexicalBinding.Initialized path, so this branch can only ever produce a non-built-in binding even if the caller explicitly passes ABuiltIn=True.

Suggested fix
     if not ExistingLexicalBinding.Initialized then
     begin
       ExistingLexicalBinding.Value := AValue;
       ExistingLexicalBinding.DeclarationType := ADeclarationType;
       ExistingLexicalBinding.Initialized := True;
+      ExistingLexicalBinding.BuiltIn := ABuiltIn;
       FLexicalBindings.AddOrSetValue(AName, ExistingLexicalBinding);
       Exit;
     end;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@source/units/Goccia.Scope.pas` around lines 353 - 368, The
predeclared-materialization branch in TGocciaScope.DefineLexicalBinding ignores
the ABuiltIn flag so materialized bindings are never marked built-in; update the
branch that handles not ExistingLexicalBinding.Initialized to propagate the
ABuiltIn parameter onto the ExistingLexicalBinding (e.g., set
ExistingLexicalBinding.BuiltIn := ABuiltIn) before re-adding it to
FLexicalBindings so the new binding preserves the caller's built-in status;
ensure you reference the ExistingLexicalBinding/TLexicalBinding fields when
making this change.

423-477: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Add Binding.BuiltIn := False; to first-declaration path in DefineVariableBinding.

The first-declaration branch (lines 470–478) creates a new TLexicalBinding record without initializing the BuiltIn field. In FPC, uninitialized record fields contain garbage values, so later reads can nondeterministically misclassify user var bindings. All other binding creation paths (e.g., lines 345–350, 383–392) explicitly initialize BuiltIn.

Suggested fix
   else
   begin
     // First declaration: create the binding
     Binding.Value := EffectiveValue;
     Binding.DeclarationType := dtVar;
     Binding.Initialized := True;
+    Binding.BuiltIn := False;
     Binding.TypeHint := sltUntyped;
     TargetScope.FVarBindings.AddOrSetValue(AName, Binding);
   end;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@source/units/Goccia.Scope.pas` around lines 423 - 477, DefineVariableBinding
creates a TLexicalBinding on the "first declaration" path but never sets its
BuiltIn flag, leaving it with garbage under FPC; fix by explicitly setting
Binding.BuiltIn := False before adding the binding (i.e., in
TGocciaScope.DefineVariableBinding’s first-declaration branch prior to
TargetScope.FVarBindings.AddOrSetValue), mirroring other binding creation sites
that initialize BuiltIn.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@source/units/Goccia.Engine.pas`:
- Around line 445-446: The injected-global registration currently calls
FInterpreter.GlobalScope.DefineLexicalBinding(AName, AValue, dtConst, True)
marking them as BuiltIn, which causes top-level redeclarations to treat injected
names as engine intrinsics; change the call so injected names are defined
without the BuiltIn flag (pass False or use the overload that does not mark
built-ins) and keep tracking the name with FInjectedGlobals.Add(AName) as before
so injected globals are recorded but not treated as built-ins.

In `@source/units/Goccia.Scope.Redeclaration.pas`:
- Around line 83-88: The top-level built-in-shadow exemption for var
declarations isn't applied to TGocciaDestructuringDeclaration because
CheckTopLevelRedeclarations calls CheckPatternRedeclarations without the IsVar
context; update the call site in CheckTopLevelRedeclarations to pass the
declaration's IsVar flag into CheckPatternRedeclarations (or alternatively
perform the AScope.IsBuiltInBinding(DeclName) && IsVar check in
CheckTopLevelRedeclarations before delegating) so that
CheckPatternRedeclarations can skip built-in bindings when the pattern comes
from a var destructuring (ensure you reference
TGocciaDestructuringDeclaration.IsVar, CheckTopLevelRedeclarations and
CheckPatternRedeclarations to locate the change).

---

Outside diff comments:
In `@source/units/Goccia.Scope.pas`:
- Around line 353-368: The predeclared-materialization branch in
TGocciaScope.DefineLexicalBinding ignores the ABuiltIn flag so materialized
bindings are never marked built-in; update the branch that handles not
ExistingLexicalBinding.Initialized to propagate the ABuiltIn parameter onto the
ExistingLexicalBinding (e.g., set ExistingLexicalBinding.BuiltIn := ABuiltIn)
before re-adding it to FLexicalBindings so the new binding preserves the
caller's built-in status; ensure you reference the
ExistingLexicalBinding/TLexicalBinding fields when making this change.
- Around line 423-477: DefineVariableBinding creates a TLexicalBinding on the
"first declaration" path but never sets its BuiltIn flag, leaving it with
garbage under FPC; fix by explicitly setting Binding.BuiltIn := False before
adding the binding (i.e., in TGocciaScope.DefineVariableBinding’s
first-declaration branch prior to TargetScope.FVarBindings.AddOrSetValue),
mirroring other binding creation sites that initialize BuiltIn.
🪄 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: 7047f63b-4a71-47ca-8bbd-aa95a95ac967

📥 Commits

Reviewing files that changed from the base of the PR and between 2e1fe70 and f4bf3ea.

📒 Files selected for processing (33)
  • source/units/Goccia.Builtins.Benchmark.pas
  • source/units/Goccia.Builtins.CSV.pas
  • source/units/Goccia.Builtins.Console.pas
  • source/units/Goccia.Builtins.DisposableStack.pas
  • source/units/Goccia.Builtins.GlobalBigInt.pas
  • source/units/Goccia.Builtins.GlobalFFI.pas
  • source/units/Goccia.Builtins.GlobalFetch.pas
  • source/units/Goccia.Builtins.GlobalPromise.pas
  • source/units/Goccia.Builtins.GlobalProxy.pas
  • source/units/Goccia.Builtins.GlobalReflect.pas
  • source/units/Goccia.Builtins.GlobalRegExp.pas
  • source/units/Goccia.Builtins.GlobalSymbol.pas
  • source/units/Goccia.Builtins.Globals.pas
  • source/units/Goccia.Builtins.JSON.pas
  • source/units/Goccia.Builtins.JSON5.pas
  • source/units/Goccia.Builtins.JSONL.pas
  • source/units/Goccia.Builtins.Math.pas
  • source/units/Goccia.Builtins.Performance.pas
  • source/units/Goccia.Builtins.TOML.pas
  • source/units/Goccia.Builtins.TSV.pas
  • source/units/Goccia.Builtins.Temporal.pas
  • source/units/Goccia.Builtins.TestingLibrary.pas
  • source/units/Goccia.Builtins.YAML.pas
  • source/units/Goccia.Engine.pas
  • source/units/Goccia.ObjectModel.Engine.pas
  • source/units/Goccia.Runtime.pas
  • source/units/Goccia.Scope.BindingMap.pas
  • source/units/Goccia.Scope.Redeclaration.pas
  • source/units/Goccia.Scope.pas
  • tests/language/declarations/const/cannot-shadow-builtin-globals.js
  • tests/language/declarations/let/cannot-shadow-builtin-globals.js
  • tests/language/function-keyword/shadow-builtin-globals.js
  • tests/language/var/shadow-builtin-globals.js

Comment thread source/units/Goccia.Engine.pas Outdated
Comment thread source/units/Goccia.Scope.Redeclaration.pas
- Injected globals (RegisterGlobal) no longer marked BuiltIn — they are
  user-provided, not engine intrinsics, and should not be shadowable.
- CheckPatternRedeclarations now receives the IsVar flag so var
  destructuring (e.g. `var { NaN } = obj;`) gets the same built-in
  exemption as simple var declarations.  Closes #580.
- DefineLexicalBinding's predeclared-materialization branch now
  propagates ABuiltIn onto the existing binding instead of silently
  dropping it.
- DefineVariableBinding's first-declaration branch explicitly sets
  Binding.BuiltIn := False to avoid uninitialized record fields.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@frostney frostney merged commit 236b6f4 into main May 8, 2026
14 checks passed
@frostney frostney deleted the issue-521-var-function-shadow-builtins branch May 8, 2026 11:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

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

Projects

None yet

1 participant