Skip to content

feat(modules): support TC39 Import Bytes with immutable backing#794

Open
frostney wants to merge 1 commit into
mainfrom
claude/elastic-archimedes-94fa2c
Open

feat(modules): support TC39 Import Bytes with immutable backing#794
frostney wants to merge 1 commit into
mainfrom
claude/elastic-archimedes-94fa2c

Conversation

@frostney

Copy link
Copy Markdown
Owner

Summary

  • Implement the TC39 Import Bytes proposal (Stage 2.7). import x from "./f" with { type: "bytes" } — plus the dynamic import(...) and import.defer forms — loads the resolved file as raw bytes and exposes a synthetic module whose single default export is a Uint8Array backed by an immutable ArrayBuffer.
  • Bytes are preserved exactly: no UTF-8 decoding, no newline normalization, so NUL bytes, non-UTF-8 sequences, and original CRLF/LF are kept verbatim. The attribute selects the loader regardless of file extension/MIME, and modules cache by specifier + type: "bytes" (static and dynamic share one module).
  • The content provider gained a raw-bytes accessor (LoadContentBytes); the filesystem and sandbox providers read exact bytes (stream / VFS ReadAllBytes), never round-tripping through the UTF-8/source-line text path.
  • Enabled by default, not behind a flag. type: "bytes" previously threw SyntaxError: Unsupported import attribute type, so it is purely additive — no working program changes behavior. (This differs from the Stage 2.7 JS ModuleSource provider, which is gated only because it changes existing source-phase resolution — see ADR 0064.)
  • To make the proposal's "immutable ArrayBuffer" guarantee real (the chosen "full compliance now" path), the Immutable ArrayBuffers observable surface was completed rather than staged: added get ArrayBuffer.prototype.immutable, made immutable buffers non-detachable (transfer/transferToFixedLength/transferToImmutable throw on them), and rejected writes through a backing view — indexed [[Set]] (silent no-op after the observable coercion), integer-index defineProperty, and DataView setters (TypedArray mutating methods and Atomics already threw). Recorded in ADR 0070.

Non-goals honored: no new import bytes ... phase syntax; bytes are not routed through import.source (rejected with a clear message); no browser fetch behavior; JSON/text module semantics unchanged.

Follow-up (out of scope, pre-existing): the bytecode VM does not reject named imports that name a missing export — it binds undefined, whereas the interpreter throws has no export named. This affects all module kinds (JS/JSON/text/bytes), not just bytes, and is tracked separately. The bytes-specific guarantee (module declares only default) is verified mode-agnostically in the tests.

Closes #775

Testing

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

Value-type changes (ArrayBuffer/TypedArray/DataView) are covered by the new end-to-end JavaScript tests rather than native Pascal tests, per the project's JS-suite-first testing convention.

Commands run (both execution modes):

./build.pas testrunner && ./build/GocciaTestRunner tests && ./build/GocciaTestRunner tests --mode=bytecode
./format.pas --check

Result: 10842/10842 tests pass in both interpreter and bytecode modes; format.pas --check clean (367 files). New tests: tests/language/modules/bytes-import.js, tests/built-ins/ArrayBuffer/prototype/immutable.js, tests/built-ins/ArrayBuffer/prototype/transferToImmutable.js, tests/built-ins/TypedArray/immutable-buffer.js, tests/built-ins/DataView/immutable-buffer.js.

🤖 Generated with Claude Code

Implement the TC39 Import Bytes proposal (Stage 2.7): `import x from
"./f" with { type: "bytes" }` (static, dynamic, and import.defer) yields a
default-only Uint8Array backed by an immutable ArrayBuffer. Bytes are
preserved exactly (no UTF-8 decoding or newline normalization) and the
attribute selects the loader regardless of file extension/MIME. import.source
of a bytes module is rejected (non-goal); modules cache by specifier + type.

To make the "immutable" guarantee real, complete the Immutable ArrayBuffers
observable surface rather than staging it: add `get ArrayBuffer.prototype.
immutable`, make immutable buffers non-detachable (transfer/transferToFixedLength/
transferToImmutable throw), and reject writes through a backing view — indexed
[[Set]] (silent no-op after coercion), integer-index defineProperty, and
DataView setters (TypedArray methods and Atomics already threw).

Closes #775

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

vercel Bot commented Jun 24, 2026

Copy link
Copy Markdown

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

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
gocciascript-homepage Ignored Ignored Jun 24, 2026 7:00pm

Request Review

@coderabbitai

coderabbitai Bot commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Adds bytes import support through raw-byte module loading, immutable ArrayBuffer-backed default exports, import-attribute routing updates, and related tests and documentation. Also extends ArrayBuffer, DataView, and TypedArray behavior for immutable buffers.

Changes

Import Bytes and Immutable ArrayBuffers

Layer / File(s) Summary
Raw byte loading
source/shared/FileUtils.pas, source/units/Goccia.TextFiles.pas, source/units/Goccia.Modules.ContentProvider.pas, source/units/Goccia.Sandbox.Modules.pas
Adds raw-byte file access APIs and provider overrides so module content can be read as TBytes without UTF-8/text conversion.
Immutable ArrayBuffer semantics
source/units/Goccia.Constants.PropertyNames.pas, source/units/Goccia.Values.ArrayBufferValue.pas, source/units/Goccia.Values.DataViewValue.pas, source/units/Goccia.Values.TypedArrayValue.pas
Adds ArrayBuffer.prototype.immutable, immutable ArrayBuffer construction, and write/transfer guards for ArrayBuffer, DataView, and TypedArray operations.
Bytes module dispatch
source/units/Goccia.AST.Expressions.pas, source/units/Goccia.VM.pas, source/units/Goccia.Modules.Loader.pas
Accepts type: "bytes" through import validation, rejects bytes in source-phase imports, and loads cached synthetic modules with a default-only export from raw bytes.
Runtime coverage
tests/built-ins/ArrayBuffer/prototype/*, tests/built-ins/DataView/*, tests/built-ins/TypedArray/*, tests/language/modules/bytes-import.js
Adds tests for transferToImmutable, immutable-buffer mutation behavior, and bytes-import module semantics, caching, and rejection paths.
Documentation updates
docs/adr/*, docs/language*.md, docs/built-ins-binary-data.md
Documents Import Bytes and Immutable ArrayBuffers across the ADR index, language tables, module docs, and binary-data reference.

Sequence Diagram(s)

sequenceDiagram
  participant TGocciaImportCallExpression
  participant TGocciaVM
  participant LoadBytesModule
  participant TGocciaModuleContentProvider
  participant TGocciaArrayBufferValue
  TGocciaImportCallExpression->>TGocciaVM: validate import attribute type "bytes"
  TGocciaVM->>LoadBytesModule: dispatch bytes import
  LoadBytesModule->>TGocciaModuleContentProvider: LoadContentBytes(resolved path)
  TGocciaModuleContentProvider-->>LoadBytesModule: raw TBytes
  LoadBytesModule->>TGocciaArrayBufferValue: CreateImmutableFromBytes(raw bytes)
  LoadBytesModule->>LoadBytesModule: cache synthetic default-only module
  LoadBytesModule-->>TGocciaImportCallExpression: return bytes module
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related issues

  • #796: The bytes-module named-import rejection and default-only export behavior in this PR match the issue's bytes-module validation objective.

Possibly related PRs

  • frostney/GocciaScript#37: Shares the immutable ArrayBuffer and typed-array behavior that this PR extends for bytes-module exports.
  • frostney/GocciaScript#266: Shares the ArrayBuffer transfer/detachment semantics updated here to reject immutable-buffer transfer operations.
  • frostney/GocciaScript#687: Touches the import-attribute and dynamic import routing code paths updated here for type: "bytes".

Suggested labels

new feature, spec compliance

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title is concise and accurately summarizes the main change: Import Bytes with immutable ArrayBuffer backing.
Description check ✅ Passed The description follows the template with Summary and Testing sections and includes implementation constraints, non-goals, and linked issue context.
Linked Issues check ✅ Passed The changes cover the requested bytes imports, raw-byte loading, immutable ArrayBuffer backing, caching, and named-import rejection.
Out of Scope Changes check ✅ Passed The changes stay focused on bytes imports, immutable ArrayBuffer support, docs, and tests; no unrelated feature appears introduced.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

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

✨ Finishing Touches
⚔️ Resolve merge conflicts
  • Resolve merge conflict in branch claude/elastic-archimedes-94fa2c

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

@github-actions

Copy link
Copy Markdown
Contributor

Suite Timing

Test Runner (interpreted: 10,842 passed; bytecode: 10,842 passed)
Metric Interpreted Bytecode
Total 10842 10842
Passed 10842 ✅ 10842 ✅
Workers 4 4
Test Duration 16.43s 17.23s
Lex (cumulative) 512.0ms 526.8ms
Parse (cumulative) 363.0ms 371.1ms
Compile (cumulative) 767.1ms
Execute (cumulative) 52.2ms 38.43s
Engine Total (cumulative) 927.3ms 40.10s
Lex (avg/worker) 128.0ms 131.7ms
Parse (avg/worker) 90.8ms 92.8ms
Compile (avg/worker) 191.8ms
Execute (avg/worker) 13.1ms 9.61s
Engine Total (avg/worker) 231.8ms 10.02s

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 272.79 MiB 270.56 MiB
GC Peak Live 289.19 MiB 309.48 MiB
GC Allocated During Run 435.18 MiB 426.88 MiB
GC Limit 7.81 GiB 7.81 GiB
GC Collections 188 188
GC Collected Objects 1,281,740 1,253,247
Heap Start Allocated 179.7 KiB 179.7 KiB
Heap End Allocated 3.65 MiB 3.65 MiB
Heap Delta Allocated 3.48 MiB 3.48 MiB
Heap Delta Free 1.71 MiB 1.71 MiB
Benchmarks (interpreted: 430; bytecode: 430)
Metric Interpreted Bytecode
Total 430 430
Workers 4 4
Duration 2.85min 2.88min

Memory

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

Metric Interpreted Bytecode
GC Live 6.09 MiB 6.09 MiB
GC Peak Live 84.45 MiB 71.19 MiB
GC Allocated During Run 13.57 GiB 10.38 GiB
GC Limit 7.81 GiB 7.81 GiB
GC Collections 3,823 3,480
GC Collected Objects 211,090,026 229,259,448
Heap Start Allocated 3.36 MiB 3.36 MiB
Heap End Allocated 3.36 MiB 3.36 MiB
Heap Delta Allocated 128 B 128 B

Measured on ubuntu-latest x64.

@github-actions

Copy link
Copy Markdown
Contributor

Benchmark Results

430 benchmarks

Interpreted: 🟢 19 improved · 🔴 92 regressed · 319 unchanged · avg -1.5%
Bytecode: 🟢 55 improved · 🔴 24 regressed · 351 unchanged · avg +2.0%

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

Deterministic profile diff

Deterministic profile diff: no significant changes.

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

@github-actions

Copy link
Copy Markdown
Contributor

test262 Conformance

🚫 Regression vs cached main baseline. 2 previously-passing test(s) now fail; pass count Δ +47. This run blocks merge — see "Newly failing" below.

Category Run Passed Δ Pass Failed Pass-rate Δ Rate
built-ins 23,643 22,525 +10 1,118 95.3% ±0pp
harness 116 116 ±0 0 100.0% ±0pp
intl402 3,341 3,332 -2 9 99.7% -0.1pp
language 23,711 23,711 +39 0 100.0% +0.2pp
staging 1,482 1,103 ±0 377 74.4% ±0pp
total 52,293 50,787 +47 1,504 97.1% +0.1pp

Areas closest to 100%

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

Newly failing (2):

  • intl402/Temporal/ZonedDateTime/prototype/hoursInDay/dst-less-than-hour.js
  • intl402/Temporal/ZonedDateTime/prototype/hoursInDay/same-date-starts-twice.js

Newly passing (49):

  • built-ins/ArrayBuffer/prototype/immutable/prop-desc.js
  • built-ins/ArrayBuffer/prototype/immutable/this-has-no-arraybufferdata-internal.js
  • built-ins/ArrayBuffer/prototype/immutable/this-is-not-object.js
  • built-ins/ArrayBuffer/prototype/immutable/this-is-sharedarraybuffer.js
  • built-ins/ArrayBuffer/prototype/transfer/this-is-immutable-arraybuffer.js
  • built-ins/ArrayBuffer/prototype/transferToFixedLength/this-is-immutable-arraybuffer.js
  • built-ins/ArrayBuffer/prototype/transferToImmutable/this-is-not-detachable.js
  • built-ins/ArrayBuffer/prototype/transferToImmutable/to-larger.js
  • built-ins/ArrayBuffer/prototype/transferToImmutable/to-same-or-smaller.js
  • built-ins/Number/prototype/toExponential/undefined-fractiondigits.js
  • language/expressions/call/tco-call-args.js
  • language/expressions/call/tco-member-args.js
  • language/expressions/call/tco-non-eval-function-dynamic.js
  • language/expressions/call/tco-non-eval-function.js
  • language/expressions/call/tco-non-eval-global.js
  • language/expressions/call/tco-non-eval-with.js
  • language/expressions/coalesce/tco-pos-null.js
  • language/expressions/coalesce/tco-pos-undefined.js
  • language/expressions/comma/tco-final.js
  • language/expressions/conditional/tco-cond.js
  • language/expressions/conditional/tco-pos.js
  • language/expressions/logical-and/tco-right.js
  • language/expressions/logical-or/tco-right.js
  • language/expressions/tagged-template/tco-call.js
  • language/expressions/tagged-template/tco-member.js
  • language/expressions/tco-pos.js
  • language/import/import-bytes/bytes-from-empty.js
  • language/import/import-bytes/bytes-from-js.js
  • language/import/import-bytes/bytes-from-json.js
  • language/import/import-bytes/bytes-from-png.js
  • language/import/import-bytes/bytes-from-txt.js
  • language/statements/block/tco-stmt-list.js
  • language/statements/block/tco-stmt.js
  • language/statements/do-while/tco-body.js
  • language/statements/for/tco-const-body.js
  • language/statements/for/tco-let-body.js
  • language/statements/for/tco-lhs-body.js
  • language/statements/for/tco-var-body.js
  • language/statements/if/tco-else-body.js
  • language/statements/if/tco-if-body.js
  • language/statements/labeled/tco.js
  • language/statements/return/tco.js
  • language/statements/switch/tco-case-body-dflt.js
  • language/statements/switch/tco-case-body.js
  • language/statements/switch/tco-dftl-body.js
  • language/statements/try/tco-catch-finally.js
  • language/statements/try/tco-catch.js
  • language/statements/try/tco-finally.js
  • language/statements/while/tco-body.js

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

@frostney frostney marked this pull request as ready for review June 24, 2026 21:25
@coderabbitai coderabbitai Bot added new feature New feature or request spec compliance Mismatch against official JavaScript/TypeScript specification labels Jun 24, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

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

Inline comments:
In `@source/units/Goccia.Values.DataViewValue.pas`:
- Around line 498-503: The immutable-buffer write guard in SetViewValue is
running before the index bounds validation, which can surface the wrong error
type for invalid offsets. Move the TGocciaArrayBufferValue.Immutable check to
after the existing RangeError/bounds validation in SetViewValue so out-of-range
offsets still throw the correct RangeError first, while still rejecting writes
to immutable buffers afterward.
🪄 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: 379e7230-42c0-4588-8185-9e77d44a9b4f

📥 Commits

Reviewing files that changed from the base of the PR and between f8f7246 and 0434afd.

⛔ Files ignored due to path filters (1)
  • tests/language/modules/helpers/asset.bin is excluded by !**/*.bin
📒 Files selected for processing (21)
  • docs/adr/0070-import-bytes-with-immutable-backing.md
  • docs/adr/README.md
  • docs/built-ins-binary-data.md
  • docs/language-tables.md
  • docs/language.md
  • source/shared/FileUtils.pas
  • source/units/Goccia.AST.Expressions.pas
  • source/units/Goccia.Constants.PropertyNames.pas
  • source/units/Goccia.Modules.ContentProvider.pas
  • source/units/Goccia.Modules.Loader.pas
  • source/units/Goccia.Sandbox.Modules.pas
  • source/units/Goccia.TextFiles.pas
  • source/units/Goccia.VM.pas
  • source/units/Goccia.Values.ArrayBufferValue.pas
  • source/units/Goccia.Values.DataViewValue.pas
  • source/units/Goccia.Values.TypedArrayValue.pas
  • tests/built-ins/ArrayBuffer/prototype/immutable.js
  • tests/built-ins/ArrayBuffer/prototype/transferToImmutable.js
  • tests/built-ins/DataView/immutable-buffer.js
  • tests/built-ins/TypedArray/immutable-buffer.js
  • tests/language/modules/bytes-import.js

Comment on lines +498 to +503
// Immutable ArrayBuffers proposal: SetViewValue throws when the viewed buffer
// is immutable (the observable numeric coercion above still runs first).
if (FBufferValue is TGocciaArrayBufferValue) and
TGocciaArrayBufferValue(FBufferValue).Immutable then
ThrowTypeError('DataView cannot write to an immutable ArrayBuffer');

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Move immutable-write rejection after index bounds validation.

This guard runs before the RangeError check, so invalid offsets on immutable buffers can throw the wrong error type.

🔧 Proposed fix
-  if (FBufferValue is TGocciaArrayBufferValue) and
-     TGocciaArrayBufferValue(FBufferValue).Immutable then
-    ThrowTypeError('DataView cannot write to an immutable ArrayBuffer');
-
   ViewSize := GetViewByteLength;
   ElementSize := BinaryBytesPerElement(AKind);
   if Int64(Index) + Int64(ElementSize) > Int64(ViewSize) then
     ThrowRangeError(SErrorInvalidDataViewOffset, SSuggestTypedArrayLength);
+
+  if (FBufferValue is TGocciaArrayBufferValue) and
+     TGocciaArrayBufferValue(FBufferValue).Immutable then
+    ThrowTypeError('DataView cannot write to an immutable ArrayBuffer');
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// Immutable ArrayBuffers proposal: SetViewValue throws when the viewed buffer
// is immutable (the observable numeric coercion above still runs first).
if (FBufferValue is TGocciaArrayBufferValue) and
TGocciaArrayBufferValue(FBufferValue).Immutable then
ThrowTypeError('DataView cannot write to an immutable ArrayBuffer');
ViewSize := GetViewByteLength;
ElementSize := BinaryBytesPerElement(AKind);
if Int64(Index) + Int64(ElementSize) > Int64(ViewSize) then
ThrowRangeError(SErrorInvalidDataViewOffset, SSuggestTypedArrayLength);
// Immutable ArrayBuffers proposal: SetViewValue throws when the viewed buffer
// is immutable (the observable numeric coercion above still runs first).
if (FBufferValue is TGocciaArrayBufferValue) and
TGocciaArrayBufferValue(FBufferValue).Immutable then
ThrowTypeError('DataView cannot write to an immutable ArrayBuffer');
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@source/units/Goccia.Values.DataViewValue.pas` around lines 498 - 503, The
immutable-buffer write guard in SetViewValue is running before the index bounds
validation, which can surface the wrong error type for invalid offsets. Move the
TGocciaArrayBufferValue.Immutable check to after the existing RangeError/bounds
validation in SetViewValue so out-of-range offsets still throw the correct
RangeError first, while still rejecting writes to immutable buffers afterward.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

new feature New feature or request spec compliance Mismatch against official JavaScript/TypeScript specification

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support TC39 Import Bytes

1 participant