Skip to content

await-using tests: add microtask-boundary ordering assertions#298

Merged
frostney merged 3 commits intomainfrom
test/await-using-microtask-ordering
Apr 13, 2026
Merged

await-using tests: add microtask-boundary ordering assertions#298
frostney merged 3 commits intomainfrom
test/await-using-microtask-ordering

Conversation

@frostney
Copy link
Copy Markdown
Owner

Summary

  • Fix AwaitValue to drain the microtask queue on all exit paths (non-promise values, non-thenable objects, already-settled promises), matching ES2026 §27.7.5.3 semantics where every await introduces a microtask boundary
  • Update the await using null and await using undefined tests to assert microtask-boundary ordering — a scheduled microtask runs during block-exit disposal, proving the async yield point is present even when no dispose method is called
  • Verified zero regressions across all 5,325 tests in both interpreter and bytecode modes

Testing

  • ./build.pas clean testrunner && ./build/TestRunner tests --no-progress — 5277 passed (same 7 pre-existing ASI failures)
  • ./build/TestRunner tests --no-progress --mode=bytecode — 5318 passed (same 7 ASI failures)
  • ./build/TestRunner tests/language/explicit-resource-management/await-using.js --no-progress — 6/6 passed
  • ./build/TestRunner tests/language/explicit-resource-management/await-using.js --no-progress --mode=bytecode — 6/6 passed
  • ./format.pas --check — all formatted correctly

Closes #294

🤖 Generated with Claude Code

…ined

AwaitValue now drains the microtask queue on all exit paths (non-promise
values, non-thenable objects, and already-settled promises), matching the
ES2026 §27.7.5.3 semantics where every await introduces a microtask
boundary. This ensures DisposeTrackedResourcesAsync's AwaitValue call for
skipped null/undefined disposables actually yields, preventing a silent
regression where the block-exit await point is dropped.

The two skipped-resource tests now schedule a microtask before the block and
assert that it runs during disposal (before post-block code), verifying the
async boundary is present even when no dispose method is called.

Closes #294

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

coderabbitai Bot commented Apr 13, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 1cf2fb8b-7f00-43e8-bdac-752c917d5cd4

📥 Commits

Reviewing files that changed from the base of the PR and between fbc1079 and 1cfa78e.

📒 Files selected for processing (1)
  • units/Goccia.Builtins.GlobalArray.pas
🚧 Files skipped from review as they are similar to previous changes (1)
  • units/Goccia.Builtins.GlobalArray.pas

📝 Walkthrough

Walkthrough

Drains the microtask queue from additional await/ disposal code paths and updates two tests to assert microtask-ordering at block exit for skipped await using disposables (null and undefined).

Changes

Cohort / File(s) Summary
Tests
tests/language/explicit-resource-management/await-using.js
Replaced boolean reached checks with an order array and microtask scheduling; tests now assert microtask ordering to verify the async boundary when disposables are skipped.
Evaluator
units/Goccia.Evaluator.pas
AwaitValue now drains TGocciaMicrotaskQueue in additional non-async continuation paths: non-thenable TGocciaObjectValue, non-object primitives, and already-settled TGocciaPromiseValue branches before returning/raising.
Builtins (Array.from async)
units/Goccia.Builtins.GlobalArray.pas
Removed local AwaitValue helper and now relies on Goccia.Evaluator’s AwaitValue, moving microtask-drain/settling behavior responsibility into the evaluator; control flow otherwise unchanged.

Sequence Diagram(s)

mermaid
sequenceDiagram
participant Caller
participant AwaitHandler as AwaitValue / ArrayFromAsync
participant MicrotaskQueue as TGocciaMicrotaskQueue
participant Promise
Caller->>AwaitHandler: await value (could be promise/object/primitive/null)
alt value is Promise
AwaitHandler->>MicrotaskQueue: drain microtasks
AwaitHandler->>Promise: inspect state
alt pending
Promise-->>AwaitHandler: pending -> schedule continuation
AwaitHandler->>MicrotaskQueue: drain on continuation
else settled
Promise-->>AwaitHandler: settled value/error
AwaitHandler-->>Caller: return or raise
end
else non-promise (object/primitive/null)
AwaitHandler->>MicrotaskQueue: drain microtasks
AwaitHandler-->>Caller: return value
end

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main change: adding microtask-boundary ordering assertions to await-using tests.
Description check ✅ Passed The description covers the summary, testing verification with specific test counts, and properly closes the linked issue #294.
Linked Issues check ✅ Passed All coding objectives from #294 are met: microtask-boundary ordering tests for null/undefined cases are implemented, async yield point verification is present, and related AwaitValue fixes ensure consistent semantics.
Out of Scope Changes check ✅ Passed Changes to Goccia.Evaluator and Goccia.Builtins.GlobalArray align with PR objectives to fix AwaitValue microtask draining; test file changes directly address issue #294 requirements.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

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


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

@coderabbitai coderabbitai Bot added the spec compliance Mismatch against official JavaScript/TypeScript specification label Apr 13, 2026
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@units/Goccia.Evaluator.pas`:
- Around line 1064-1078: The local AwaitValue function inside Array.fromAsync
currently returns non-promise values directly; update its non-promise branch to
call TGocciaMicrotaskQueue.Instance.DrainQueue (guarded by Assigned) before
returning so it matches the evaluator's AwaitValue behavior per ES2026
§27.7.5.3; locate the AwaitValue implementation in Array.fromAsync and insert
the same DrainQueue call used in the evaluator's non-promise branches
immediately before Result := AValue.
🪄 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: d94ae7c9-d34f-440e-82a1-091b5626a911

📥 Commits

Reviewing files that changed from the base of the PR and between 983138a and 5e79123.

📒 Files selected for processing (2)
  • tests/language/explicit-resource-management/await-using.js
  • units/Goccia.Evaluator.pas

Comment thread units/Goccia.Evaluator.pas
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 13, 2026

Suite Timing

Suite Metric Interpreted Bytecode
Tests Total 5355 5355
Tests Passed 5314 ✅ 5355 ✅
Tests Skipped 41 0
Tests Test Duration 350.9ms 349.1ms
Tests Lex 97.4ms 69.5ms
Tests Parse 123.7ms 139.2ms
Tests Compile 82.4ms
Tests Execute 366.9ms 384.9ms
Tests Engine Total 588.0ms 676.0ms
Benchmarks Total 364 364
Benchmarks Duration 9.78min 8.86min

Measured on ubuntu-latest x64.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 13, 2026

Benchmark Results

364 benchmarks

Interpreted: 🟢 36 improved · 🔴 190 regressed · 138 unchanged · avg -1.2%
Bytecode: 🟢 128 improved · 🔴 135 regressed · 101 unchanged · avg -0.2%

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

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

The local AwaitValue in Array.fromAsync returned non-promise values
directly and only drained for pending promises. Now drains the microtask
queue on all paths (non-promise values and already-settled promises) to
match the evaluator's AwaitValue per ES2026 §27.7.5.3.

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

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@units/Goccia.Builtins.GlobalArray.pas`:
- Around line 367-373: Array.fromAsync's local AwaitValue currently only handles
TGocciaPromiseValue and returns other values directly, which misses thenable
assimilation; update the AwaitValue inside ArrayFromAsync to mirror the
evaluator's logic: after the existing TGocciaPromiseValue check add an else if
AValue is TGocciaObjectValue branch that calls GetProperty(PROP_THEN) on the
object, checks the property is callable and not undefined, and if so constructs
a new Promise that invokes the thenable with resolve/reject handlers (draining
TGocciaMicrotaskQueue.Instance after scheduling), waits for the promise to
settle and returns the resolved value or raises on rejection; ensure you reuse
the same property name PROP_THEN and behavior for microtask draining and error
propagation used elsewhere so thenables are properly assimilated rather than
returned raw.
🪄 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: b7b0c8ee-1063-4594-95d9-ecbdb4397f3f

📥 Commits

Reviewing files that changed from the base of the PR and between 5e79123 and fbc1079.

📒 Files selected for processing (1)
  • units/Goccia.Builtins.GlobalArray.pas

Comment thread units/Goccia.Builtins.GlobalArray.pas Outdated
Remove the duplicated local AwaitValue from ArrayFromAsync and delegate
to Goccia.Evaluator.AwaitValue instead. This picks up thenable
assimilation (objects with callable .then) and all microtask-boundary
semantics from the canonical implementation, eliminating the risk of
the two copies drifting apart.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@frostney frostney merged commit 48c7456 into main Apr 13, 2026
9 checks passed
@frostney frostney deleted the test/await-using-microtask-ordering branch April 13, 2026 18:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

spec compliance Mismatch against official JavaScript/TypeScript specification

Projects

None yet

Development

Successfully merging this pull request may close these issues.

await-using tests: add microtask-boundary ordering assertions for null/undefined skipped resources

1 participant