Skip to content

Make fetch asynchronous with fetch manager#396

Merged
frostney merged 4 commits intomainfrom
codex/async-fetch-manager
Apr 24, 2026
Merged

Make fetch asynchronous with fetch manager#396
frostney merged 4 commits intomainfrom
codex/async-fetch-manager

Conversation

@frostney
Copy link
Copy Markdown
Owner

@frostney frostney commented Apr 24, 2026

Summary

  • Add a fetch-specific async manager that runs HTTP requests off-thread and settles promises on the owning runtime thread.
  • Wire await/engine/test/benchmark drains to pump fetch completions while preserving the current synchronous await model.
  • Add async fetch ordering coverage and update runtime/testing docs.

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

Commands run:

  • ./build.pas testrunner loader repl benchmarkrunner bundler
  • ./build.pas tests
  • ./build/Goccia.Values.Primitives.Test
  • ./build/Goccia.Values.FunctionValue.Test
  • ./build/Goccia.Values.ObjectValue.Test
  • ./build/Goccia.Builtins.TestingLibrary.Test
  • ./build/GocciaTestRunner tests --asi --unsafe-ffi --silent --no-progress
  • ./build/GocciaTestRunner tests --asi --unsafe-ffi --mode=bytecode --silent --no-progress
  • ./build/GocciaTestRunner tests/built-ins/fetch/fetch-async.js --asi --unsafe-ffi --no-progress
  • ./build/GocciaTestRunner tests/built-ins/fetch/fetch-async.js --asi --unsafe-ffi --mode=bytecode --no-progress
  • ./build/GocciaBundler examples/basic.js --output=/tmp/goccia-basic.gbc
  • ./format.pas --check
  • git diff --check

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 24, 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: 04f99143-a8e2-493d-994e-0985f7d75dbe

📥 Commits

Reviewing files that changed from the base of the PR and between 2962e18 and d156f63.

📒 Files selected for processing (1)
  • docs/built-ins.md

📝 Walkthrough

Walkthrough

Reworks fetch into an asynchronous model: fetch() now returns a pending Promise immediately, performs HTTP I/O on background fetch worker threads (capped at 16), and posts completions back to the owning runtime thread where Promises are settled and microtask reactions run. Runtime, evaluator, REPL, benchmarks, tests, and docs updated to pump/wait/discard fetch completions at defined sync points; excess concurrent fetches reject immediately with TypeError.

Changes

Cohort / File(s) Summary
Documentation
docs/built-ins.md, docs/decision-log.md, docs/embedding.md, docs/interpreter.md, docs/testing-api.md
Describe new fetch worker model, immediate-pending fetch() Promise, per-runtime worker cap (16) with immediate rejection, microtask drain/pump points, await pumping behavior, and allowed-host wording updates.
New Fetch Manager
source/units/Goccia.FetchManager.pas
Adds singleton fetch manager with worker threads, request IDs, GC rooting of promises, concurrency limiter, completion queue, PumpCompletions, WaitForPromise/WaitForIdle helpers, and DiscardPending logic.
Global Fetch Builtin
source/units/Goccia.Builtins.GlobalFetch.pas
Refactored to delegate HTTP work to TGocciaFetchManager.StartFetch; removed inline synchronous HTTP/response construction and specific EHTTPError branch.
Engine & Evaluator
source/units/Goccia.Engine.pas, source/units/Goccia.Evaluator.pas
Initialize/shutdown fetch manager; replace direct microtask drains with fetch-aware sync (WaitForFetchIdle, DiscardFetchCompletions, DrainMicrotasksAndFetchCompletions); AwaitValue uses fetch-wait for pending promises.
REPL, Benchmarks, Testing Library
source/app/GocciaREPL.dpr, source/units/Goccia.Builtins.Benchmark.pas, source/units/Goccia.Builtins.TestingLibrary.pas
Replace microtask-only drains with WaitForFetchIdle / WaitForFetchPromise / DrainMicrotasksAndFetchCompletions; discard pending fetch completions on error paths; add FetchManager unit dependencies.
Tests
tests/built-ins/fetch/fetch-async.js
New tests asserting fetch returns an observable pending Promise before network completion and that microtasks run before fetch completion handlers.

Sequence Diagram

sequenceDiagram
    participant JS as JavaScript
    participant Engine as GocciaEngine
    participant FM as FetchManager
    participant Worker as FetchWorker
    participant MTQ as MicrotaskQueue
    participant Promise as Promise

    JS->>FM: StartFetch(url, method, headers, promise)
    FM->>Worker: spawn worker thread (off-thread HTTP)
    FM->>Promise: root promise (GC protect)

    Note over Worker: perform HTTP/HEAD/GET synchronously on worker

    JS->>Engine: await fetch(...)
    Engine->>MTQ: drain/pump microtasks as needed
    MTQ-->>Engine: microtasks processed

    Worker->>FM: post completion (response or error)
    Engine->>FM: PumpCompletions()
    FM->>Promise: settle (resolve/reject) on owning thread
    FM->>MTQ: drain microtasks (promise reactions)
    MTQ-->>FM: reactions executed
    FM->>Promise: unroot promise
    FM-->>Engine: completion processed
    Engine-->>JS: await resumes with result
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately reflects the primary change: implementing asynchronous fetch behavior through a dedicated fetch manager component.
Description check ✅ Passed The description addresses all template sections with clear summaries, comprehensive testing confirmation across multiple test scenarios, and detailed commands run.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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


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

@coderabbitai coderabbitai Bot added new feature New feature or request internal Refactoring, CI, tooling, cleanup labels Apr 24, 2026
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 24, 2026

Benchmark Results

386 benchmarks

Interpreted: 🟢 25 improved · 🔴 95 regressed · 266 unchanged · avg -0.8%
Bytecode: 🟢 114 improved · 🔴 47 regressed · 225 unchanged · avg +2.2%

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

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 24, 2026

Suite Timing

Suite Metric Interpreted Bytecode
Tests Total 7761 7761
Tests Passed 7720 ✅ 7761 ✅
Tests Skipped 41 0
Tests Workers 4 4
Tests Test Duration 1.50s 1.61s
Tests Lex (cumulative) 185.1ms 126.5ms
Tests Parse (cumulative) 284.4ms 288.4ms
Tests Compile (cumulative) 195.8ms
Tests Execute (cumulative) 1.47s 1.67s
Tests Engine Total (cumulative) 1.94s 2.28s
Tests Lex (avg/worker) 46.3ms 31.6ms
Tests Parse (avg/worker) 71.1ms 72.1ms
Tests Compile (avg/worker) 48.9ms
Tests Execute (avg/worker) 366.7ms 418.1ms
Tests Engine Total (avg/worker) 484.1ms 570.7ms
Benchmarks Total 386 386
Benchmarks Workers 4 4
Benchmarks Duration 2.95min 2.99min

Measured on ubuntu-latest x64.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

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

Inline comments:
In `@docs/embedding.md`:
- Line 736: The docs mention a nonexistent API symbol ExecuteWithTiming in the
TGocciaEngine microtask/GC description; remove the reference to
ExecuteWithTiming and update the sentence to state that microtasks are drained
automatically after the engine's actual entry points (TGocciaEngine.Execute and
TGocciaEngine.ExecuteProgram) so embedders are not directed to a non‑existent
function.
🪄 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: aebcae81-95cb-441a-8f5e-62458f013519

📥 Commits

Reviewing files that changed from the base of the PR and between a11b6ee and 0fec7d6.

📒 Files selected for processing (13)
  • docs/built-ins.md
  • docs/decision-log.md
  • docs/embedding.md
  • docs/interpreter.md
  • docs/testing-api.md
  • source/app/GocciaREPL.dpr
  • source/units/Goccia.Builtins.Benchmark.pas
  • source/units/Goccia.Builtins.GlobalFetch.pas
  • source/units/Goccia.Builtins.TestingLibrary.pas
  • source/units/Goccia.Engine.pas
  • source/units/Goccia.Evaluator.pas
  • source/units/Goccia.FetchManager.pas
  • tests/built-ins/fetch/fetch-async.js

Comment thread docs/embedding.md Outdated
Comment thread source/units/Goccia.Engine.pas
@coderabbitai coderabbitai Bot added the documentation Improvements or additions to documentation label Apr 24, 2026
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

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

Inline comments:
In `@source/units/Goccia.FetchManager.pas`:
- Around line 47-49: The current implementation spawns a new TGocciaFetchWorker
for every call to fetch(), each reserving FETCH_WORKER_STACK_SIZE (8MB) which
can exhaust threads/VM; modify fetch() / the component that creates
TGocciaFetchWorker so it enforces a per-runtime cap on concurrent workers: add a
bounded semaphore/counter (e.g., MaxFetchWorkers) that must be acquired before
creating a TGocciaFetchWorker and released when the worker finishes, and if the
cap is reached either queue the request behind the semaphore or return a
fast-fail error to the caller (make this behavior configurable); ensure the
semaphore is referenced where TGocciaFetchWorker instances are created and
released on worker termination to prevent leaks.
- Around line 452-464: TGocciaFetchManagerImpl.DiscardPending currently removes
temp roots and clears FPending but leaves FState able to accept late worker
completions; update DiscardPending to isolate the old state so late completions
cannot leak into the next run by rotating/abandoning the state: capture the
current FState into a local variable, replace FState with a fresh/disabled state
(or flip an "abandoned" flag on the old state) so subsequent worker completions
are rejected or ignored, then remove temp roots and clear the old state's
completions (using the captured local) to fully drain/abandon it; ensure methods
that enqueue completions check the state's identity/abandoned flag so late
responses are discarded instead of being applied to the new live FState.
🪄 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: c8f26bc4-ff90-4f34-a524-75e83609bc1d

📥 Commits

Reviewing files that changed from the base of the PR and between 0fec7d6 and b34a725.

📒 Files selected for processing (3)
  • docs/embedding.md
  • docs/interpreter.md
  • source/units/Goccia.FetchManager.pas
🚧 Files skipped from review as they are similar to previous changes (1)
  • docs/embedding.md

Comment thread source/units/Goccia.FetchManager.pas
Comment thread source/units/Goccia.FetchManager.pas Outdated
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
docs/built-ins.md (1)

753-753: Accurate documentation of the new async fetch behavior.

The technical content correctly describes all key aspects of the new fetch implementation: background workers, Promise settlement on the runtime thread, synchronous await via completion pumping, the 16-worker cap, and TypeError rejection when capacity is exceeded.

Optional: Consider breaking up the long sentence for readability

The current sentence packs five distinct concepts into one statement. For improved scannability, consider restructuring as a bulleted list:

-**GocciaScript differences:** Only `GET` and `HEAD` methods. No `Request` object, `AbortSignal`, streaming body, or CORS. Requests run on fetch-specific background workers and settle their Promise on the owning runtime thread; `await fetch(...)` still synchronously waits by pumping fetch completions. Each runtime caps active fetch workers at 16; additional calls reject their returned Promise with `TypeError` until a worker finishes. Requires `--allowed-host` configuration.
+**GocciaScript differences:**
+
+- Only `GET` and `HEAD` methods supported
+- No `Request` object, `AbortSignal`, streaming body, or CORS
+- Requests run on fetch-specific background workers and settle their Promise on the owning runtime thread
+- `await fetch(...)` still synchronously waits by pumping fetch completions
+- Each runtime caps active fetch workers at 16; additional calls reject their returned Promise with `TypeError` until a worker finishes
+- Requires `--allowed-host` configuration
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/built-ins.md` at line 753, The long single sentence under the
"GocciaScript differences" line is packing multiple concepts; split it into a
short introductory sentence and a bulleted list that separately documents: HTTP
method support (only GET and HEAD), absent features (no Request object,
AbortSignal, streaming body, or CORS), runtime behavior (fetch runs on
fetch-specific background workers and Promises settle on the owning runtime
thread with await pumping completions), the concurrency cap (runtime caps active
fetch workers at 16 and additional calls reject with TypeError), and the
configuration requirement (requires --allowed-host); update the paragraph around
the "GocciaScript differences:" header accordingly to improve scannability.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@source/units/Goccia.FetchManager.pas`:
- Around line 326-329: StartFetch currently routes any non-HEAD method to
HTTPGet, causing unsupported methods (POST/PUT/DELETE) to be sent as GET; update
StartFetch to validate FMethod explicitly: handle 'HEAD' with HTTPHead and 'GET'
with HTTPGet, and for any other FMethod set Completion.Response to an error
response (or raise/return an error) with a clear message indicating unsupported
HTTP method (include FMethod in the message) instead of silently falling back to
GET; references: StartFetch, FMethod, HTTPHead, HTTPGet, Completion.Response.

---

Nitpick comments:
In `@docs/built-ins.md`:
- Line 753: The long single sentence under the "GocciaScript differences" line
is packing multiple concepts; split it into a short introductory sentence and a
bulleted list that separately documents: HTTP method support (only GET and
HEAD), absent features (no Request object, AbortSignal, streaming body, or
CORS), runtime behavior (fetch runs on fetch-specific background workers and
Promises settle on the owning runtime thread with await pumping completions),
the concurrency cap (runtime caps active fetch workers at 16 and additional
calls reject with TypeError), and the configuration requirement (requires
--allowed-host); update the paragraph around the "GocciaScript differences:"
header accordingly to improve scannability.
🪄 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: 57a7fd29-e553-469f-b2d0-7d364ffba50b

📥 Commits

Reviewing files that changed from the base of the PR and between b34a725 and 2962e18.

📒 Files selected for processing (2)
  • docs/built-ins.md
  • source/units/Goccia.FetchManager.pas

Comment thread source/units/Goccia.FetchManager.pas
@frostney frostney merged commit 5301d07 into main Apr 24, 2026
10 checks passed
@frostney frostney deleted the codex/async-fetch-manager branch April 24, 2026 19:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation internal Refactoring, CI, tooling, cleanup new feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant