Skip to content

fix(modules): preserve live import bindings across module graphs#999

Merged
frostney merged 6 commits into
mainfrom
codex/fix-live-import-bindings
Jul 23, 2026
Merged

fix(modules): preserve live import bindings across module graphs#999
frostney merged 6 commits into
mainfrom
codex/fix-live-import-bindings

Conversation

@frostney

@frostney frostney commented Jul 21, 2026

Copy link
Copy Markdown
Owner

Summary

  • Add one shared module-scope import-binding seam: named imports are immutable indirect bindings whose reads resolve the target export on every access in both interpreter and bytecode execution.
  • Separate dependency-graph instantiation/linking from source-ordered module-body evaluation. The loader now retains each linked module environment until the reachable graph has installed named and namespace imports, then evaluates dependencies before their parents.
  • Preserve active graph state across expected deferred-module readiness errors and discard only link states created by a failing load.
  • Keep failed and discarded modules alive until loader teardown so successfully evaluated cyclic peers cannot retain dangling live import bindings.
  • Cover two-hop, three-hop, post-mutation live reads, exports of imported names, indirect re-exports, star-re-export namespaces, cycle/TDZ behavior, and a cyclic dependency that reads its parents named and namespace imports during evaluation.
  • Refine the Binding and Import binding glossary and architecture/interpreter documentation.
  • This follows ECMA-262 ES2026 CreateImportBinding, Module Environment Record GetBindingValue, InitializeEnvironment, InnerModuleLinking, InnerModuleEvaluation, and module namespace [[Get]] semantics (TC39 snapshot 0248456c758431e4bb8e5d26333ff1865123c9cd).
  • Scope is intentionally limited to module semantics. It does not change performance policy, collector policy, Math.ceil, or the es-toolkit harness. No ADR was added because this is a specification-mandated correction rather than a hard-to-reverse architectural trade-off.
  • Supports Flip all entry-point defaults to bytecode and prove parity #871 and Delete the tree-walk interpreter (~16k LOC) and collapse the CI mode matrix #875; does not close either broader issue.

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

Validation performed:

  • Cyclic parent-linking regression: named and namespace reads pass in interpreted and bytecode modes while the existing cyclic TDZ assertion remains a ReferenceError.
  • Focused transitive live-binding suite: 8/8 tests, 9 assertions in interpreted mode; 8/8 tests, 9 assertions in bytecode mode.
  • Deferred async-module evaluation regression: 1/1 test, 3 assertions in interpreted mode; 1/1 test, 3 assertions in bytecode mode.
  • Full JavaScript suite: 11,551/11,551 tests, 25,834 assertions across 1,451 files in interpreted mode; the same counts pass in bytecode mode.
  • Pascal tests target built successfully; all 60 native test programs passed.
  • Failed-cycle import-binding lifetime regression: 14/14 module content-provider tests pass, including interpreter and bytecode executors.
  • 429 Pascal files formatted; JavaScript test structure checked across 1,437 files.
  • Markdown lint: 158 files, 0 issues.
  • Documentation symbol, duplication, length, and link checks passed (7 existing fuzzy duplication warnings, 0 exact clones).
  • git diff --check and repository pre-commit hooks passed.

@vercel

vercel Bot commented Jul 21, 2026

Copy link
Copy Markdown

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

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
gocciascript-homepage Ignored Ignored Preview Jul 23, 2026 12:08pm

Request Review

@coderabbitai

coderabbitai Bot commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Module imports now use indirect live bindings resolved against target exports at read time. Module linking creates these bindings and namespace bindings, while scope read paths and GC tracking support them. Tests cover transitive imports, re-exports, namespace reads, hoisted functions, and circular-import behavior.

Changes

Live import bindings

Layer / File(s) Summary
Import binding contract
source/units/Goccia.Modules.pas, source/units/Goccia.Scope.pas
Adds module import binding records, storage maps, and scope APIs for creating and resolving indirect bindings.
Scope creation and live reads
source/units/Goccia.Scope.pas
Creates immutable lexical placeholders, resolves imported values across direct and cached read paths, and includes import bindings in cleanup and reference marking.
Import linking and evaluation
source/units/Goccia.AST.Statements.pas, source/units/Goccia.Modules.Loader.pas
Registers named imports during linking, handles namespace bindings, separates linking from evaluation, and retains failed-cycle modules for surviving bindings.
Behavior coverage and documentation
tests/language/modules/hoisted-function-import-capture/*, fixtures/modules/*, source/units/Goccia.Modules.ContentProvider.Test.pas, CONTEXT.md, docs/*.md
Adds live-binding, re-export, namespace, hoisted-function, failed-cycle, and circular-import tests and updates module documentation.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant ImportDeclaration
  participant ModuleLoader
  participant ImportingScope
  participant TargetModule
  ImportDeclaration->>ModuleLoader: Request module and import specifiers
  ModuleLoader->>TargetModule: Instantiate and link requested module
  ModuleLoader->>ImportingScope: CreateImportBinding(localName, targetModule, exportName)
  ModuleLoader->>TargetModule: Evaluate linked dependencies and module body
  ImportingScope->>TargetModule: Resolve exported value on each read
  TargetModule-->>ImportingScope: Current value or TDZ/unresolved state
Loading

Possibly related PRs

Suggested labels: bug, spec compliance

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
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.
Title check ✅ Passed The title clearly matches the main change: preserving live import bindings across module graphs.
Description check ✅ Passed The description follows the template with Summary and Testing sections and includes implementation notes and validation details.

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

@github-actions

github-actions Bot commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

Web Tooling Benchmark

Workload Status Goccia
acorn pass 0.03 runs/s
babel pass 0.01 runs/s
babel-minify pass 0.09 runs/s
babylon pass 0.04 runs/s
buble pass 0.10 runs/s
chai pass 0.09 runs/s
coffeescript pass 0.01 runs/s
espree pass 0.03 runs/s
esprima pass 0.05 runs/s
jshint pass 0.02 runs/s
lebab pass 0.07 runs/s
postcss pass 0.02 runs/s
prepack pass 0.11 runs/s
prettier pass 0.07 runs/s
source-map pass 0.03 runs/s
terser pass 213 runs/s
typescript pass 0.11 runs/s
uglify-js pass 128 runs/s

18 pinned Web Tooling workloads; 18 workloads produced at least one Goccia sample. Raw results from 1 sample per workload; full stdout/stderr for failures and min/max/CV stay in the web-tooling-report artifact. This lane is Goccia-only by design.

@github-actions

github-actions Bot commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

Benchmark Results

439 benchmarks · PR vs same-runner main build

Interpreted: 🟢 21 improved · 🔴 60 regressed · 358 unchanged · avg -1.0%
Bytecode: 🟢 27 improved · 🔴 59 regressed · 353 unchanged · avg -0.3%

Typical per-run noise (median variance): interpreted ±2.4%, bytecode ±1.6%. Deltas within noise overlap and read as unchanged.

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

Deterministic profile diff

Deterministic profile diff: no significant changes.

Measured on ubuntu-latest x64. Each PR run also builds the main base and benchmarks it back-to-back on the same runner after a warm-up discard, so the ranges compare two runs measured under the same conditions; overlapping min/max ranges are treated as unchanged noise. Percentage deltas are secondary context. See docs/adr/0076.

@github-actions

github-actions Bot commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

Suite Timing

Test Runner (interpreted: 11,551 passed; bytecode: 11,551 passed)
Metric Interpreted Bytecode
Total 11551 11551
Passed 11551 ✅ 11551 ✅
Workers 4 4
Test Duration 16.43s 13.33s
Lex (cumulative) 1.59s 1.41s
Parse (cumulative) 852.2ms 710.5ms
Compile (cumulative) 868.7ms
Execute (cumulative) 308.9ms 11.84s
Engine Total (cumulative) 2.75s 14.83s
Lex (avg/worker) 397.9ms 352.8ms
Parse (avg/worker) 213.0ms 177.6ms
Compile (avg/worker) 217.2ms
Execute (avg/worker) 77.2ms 2.96s
Engine Total (avg/worker) 688.1ms 3.71s

Memory

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

Metric Interpreted Bytecode
GC Live 66.90 MiB 64.20 MiB
GC Peak Live 225.91 MiB 188.98 MiB
GC Allocated During Run 529.15 MiB 458.45 MiB
GC Limit 7.81 GiB 7.81 GiB
GC Collections 226 226
GC Collected Objects 4,401,476 3,854,301
Heap Start Allocated 329.2 KiB 329.2 KiB
Heap End Allocated 2.90 MiB 2.90 MiB
Heap Delta Allocated 2.58 MiB 2.58 MiB
Heap Delta Free 2.54 MiB 2.29 MiB
Benchmarks (interpreted: 439; bytecode: 439)
Metric Interpreted Bytecode
Total 439 439
Workers 4 4
Duration 3.21min 2.97min

Memory

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

Metric Interpreted Bytecode
GC Live 808 B 808 B
GC Peak Live 162.27 MiB 72.76 MiB
GC Allocated During Run 17.78 GiB 9.69 GiB
GC Limit 7.81 GiB 7.81 GiB
GC Collections 5,465 5,592
GC Collected Objects 253,727,898 212,965,605
Heap Start Allocated 1.36 MiB 1.36 MiB
Heap End Allocated 1.37 MiB 1.37 MiB
Heap Delta Allocated 3.2 KiB 3.2 KiB
Boot
Metric Interpreted Bytecode
Boot (median) 7.7ms 7.7ms
Boot (min) 7.3ms 7.5ms

Empty-script (0;) end-to-end process wall-clock for GocciaScriptLoader, min and median over 60 runs after 10 warmups. Includes a fixed process / dynamic-loader floor that does not shrink, so it understates the engine-boot speedup; treat as practical boot time, not pure engine work.

Measured on ubuntu-latest x64.

@github-actions

github-actions Bot commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

JetStream 3 Performance Barometer

Workload Status Goccia main Goccia PR QuickJS Node.js vs QuickJS vs Node.js
hash-map pass 0.57 0.58 13.04 328.18 22.53× 566.77×
ai-astar pass 2.19 2.20 54.43 443.39 24.73× 201.47×
gaussian-blur pass 0.35 0.35 7.47 276.44 21.15× 782.81×
raytrace-public-class-fields pass 0.39 0.40 11.11 194.02 27.91× 487.46×
sync-fs pass 1.06 1.06 31.43 230.74 29.68× 217.88×
lazy-collections pass 2.05 2.05 68.22 153.23 33.24× 74.66×

Geomean reference ratio: QuickJS 26.21×; Node.js 298.60×.

1.00× means aligned; values above 1.00× mean Goccia was proportionally slower after normalizing JetStream’s higher-is-better score. This is a directional barometer across runtimes with different goals, not a product ranking. Raw samples and failure details remain in the jetstream-report artifact.

@github-actions

github-actions Bot commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

AWFY Results

Target Status Goccia main Goccia PR QuickJS 2026-06-04 NodeJS v26.5.0 Δ PR vs main
Bounce pass 25.21ms 24.72ms 1.06ms 1.06ms 🟢 +1.93%
CD pass 226.58ms 223.49ms 10.83ms 9.78ms ~ overlap (+1.36%)
DeltaBlue pass 5.15ms 5.17ms 308.11µs 1.81ms ~ overlap (-0.48%)
Havlak pass 87.10s 86.89s 4017.76ms 176.19ms ~ overlap (+0.24%)
Json pass 375.68ms 375.23ms 14.51ms 4.73ms ~ overlap (+0.12%)
List pass 17.18ms 17.16ms 1.03ms 0.71ms ~ overlap (+0.12%)
Mandelbrot pass 33.16µs 31.71µs 5.06µs 89.74µs 🟢 +4.38%
NBody pass 410.73µs 401.74µs 28.17µs 416.11µs ~ overlap (+2.19%)
Permute pass 47.11ms 46.47ms 1.85ms 0.73ms 🟢 +1.36%
Queens pass 24.59ms 24.85ms 1.27ms 1.07ms ~ overlap (-1.07%)
Richards pass 1046.39ms 1017.24ms 51.88ms 6.97ms 🟢 +2.79%
Sieve pass 13.50ms 13.81ms 0.55ms 0.77ms ~ overlap (-2.31%)
Storage pass 38.02ms 37.56ms 2.91ms 1.01ms 🟢 +1.20%
Towers pass 68.14ms 67.48ms 3.16ms 1.12ms ~ overlap (+0.96%)

Geomean Ratios

Ratio (row / column) Goccia main Goccia PR QuickJS 2026-06-04 NodeJS v26.5.0
Goccia main 1.000 1.009 18.408 21.608
Goccia PR 0.991 1.000 18.237 21.408
QuickJS 2026-06-04 0.054 0.055 1.000 1.174
NodeJS v26.5.0 0.046 0.047 0.852 1.000

14 pinned AWFY benchmarks. Medians from 5 interleaved samples per engine; raw JSON includes min/max/CV and is attached as the awfy-report artifact. Δ compares PR Goccia median against the same-runner main Goccia median; overlapping min/max ranges are treated as unchanged noise. Rows below 0.5ms are timer-floor sensitive.

@github-actions

github-actions Bot commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

test262 Conformance

10 timeout(s) — counted separately from ordinary conformance failures; inspect the full artifact for affected tests.

Category Run Passed Δ Pass Failed Timeouts Δ Timeout Wrap-Infra Pass-rate Δ Rate
built-ins 23,668 23,668 ±0 0 0 ±0 0 100.0% ±0pp
harness 116 116 ±0 0 0 ±0 0 100.0% ±0pp
intl402 3,349 3,340 ±0 8 1 ±0 0 99.7% ±0pp
language 23,713 23,712 ±0 1 0 ±0 0 100.0% ±0pp
staging 1,482 1,387 +1 86 9 -1 0 93.6% +0.1pp
total 52,328 52,223 +1 95 10 -1 0 99.8% ±0pp

Areas closest to 100%

Area Pass rate Δ vs main Passing
language/expressions 100.0% ±0pp 11,101 / 11,102
intl402/Temporal 100.0% ±0pp 2,028 / 2,029
intl402/NumberFormat 99.6% ±0pp 248 / 249
Per-test deltas (+0 / -0 / timeout +0 / -1)

Resolved timeouts (1):

  • staging/sm/extensions/recursion.js

Steady-state failures and timeouts are non-blocking; PASS → non-timeout failure transitions fail the conformance gate. Measured on ubuntu-latest x64, bytecode mode. Areas grouped by the first two test262 path components; minimum 25 attempted tests, areas already at 100% excluded. Δ vs main compares against the most recent cached main baseline.

@frostney
frostney marked this pull request as ready for review July 22, 2026 19:08
@cursor

cursor Bot commented Jul 22, 2026

Copy link
Copy Markdown

Bugbot is not enabled for your account, so this pull request was not reviewed.

Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs.

@coderabbitai coderabbitai Bot added bug Something isn't working spec compliance Mismatch against official JavaScript/TypeScript specification labels Jul 22, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Caution

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

⚠️ Outside diff range comments (1)
source/units/Goccia.Modules.Loader.pas (1)

1193-1231: 🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift

Link parent imports before evaluating cyclic dependencies.

LoadModule(...) evaluates RequestedModule before lines 1218–1231 install this module’s imports. In a cycle, that dependency can call a hoisted function exported by this module; reads of this module’s named or namespace imports then see the predeclared TDZ/undefined placeholder rather than the target’s live binding. Split graph instantiation/linking from evaluation so all imports in the cycle are installed before any module body executes.

Also applies to: 1713-1713

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

In `@source/units/Goccia.Modules.Loader.pas` around lines 1193 - 1231, Update
LinkAndEvaluateRequestedModulesInSourceOrder and the corresponding
module-loading path so LoadModule does not evaluate RequestedModule before this
module’s named and namespace import bindings are installed. Separate dependency
graph instantiation/linking from module-body evaluation, recursively link the
cycle’s parent imports first, then evaluate modules while preserving live
bindings and existing source-order semantics.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@source/units/Goccia.Modules.Loader.pas`:
- Around line 1193-1231: Update LinkAndEvaluateRequestedModulesInSourceOrder and
the corresponding module-loading path so LoadModule does not evaluate
RequestedModule before this module’s named and namespace import bindings are
installed. Separate dependency graph instantiation/linking from module-body
evaluation, recursively link the cycle’s parent imports first, then evaluate
modules while preserving live bindings and existing source-order semantics.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: f96fd107-0158-460f-8402-24ea01a429f4

📥 Commits

Reviewing files that changed from the base of the PR and between c477011 and 8602d10.

📒 Files selected for processing (16)
  • CONTEXT.md
  • docs/architecture.md
  • docs/core-patterns.md
  • docs/interpreter.md
  • source/units/Goccia.AST.Statements.pas
  • source/units/Goccia.Modules.Loader.pas
  • source/units/Goccia.Modules.pas
  • source/units/Goccia.Scope.pas
  • tests/language/modules/hoisted-function-import-capture/helpers/live-bindings-cycle-a.js
  • tests/language/modules/hoisted-function-import-capture/helpers/live-bindings-cycle-b.js
  • tests/language/modules/hoisted-function-import-capture/helpers/live-bindings-leaf.js
  • tests/language/modules/hoisted-function-import-capture/helpers/live-bindings-middle.js
  • tests/language/modules/hoisted-function-import-capture/helpers/live-bindings-outer.js
  • tests/language/modules/hoisted-function-import-capture/helpers/live-bindings-re-export.js
  • tests/language/modules/hoisted-function-import-capture/helpers/live-bindings-star-re-export.js
  • tests/language/modules/hoisted-function-import-capture/transitive-live-bindings.js

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

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

Inline comments:
In `@source/units/Goccia.Modules.Loader.pas`:
- Around line 1267-1276: Update the failure cleanup in the module-loading flow
around LoadState and AModule so failed modules remain alive until all dependent
TGocciaModuleImportBinding references are detached. Ensure TryGetValue and
MarkReferences cannot observe a freed AModule, then dispose the failed module
only after detachment or defer disposal while preserving existing
successful-load cleanup.
🪄 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 Plus

Run ID: f49531f2-1f32-4bf5-9cb0-cdecb6c9f963

📥 Commits

Reviewing files that changed from the base of the PR and between 8602d10 and 42bb9b8.

📒 Files selected for processing (4)
  • fixtures/modules/live-bindings-link-child.js
  • fixtures/modules/live-bindings-link-parent.js
  • source/units/Goccia.Modules.Loader.pas
  • tests/language/modules/hoisted-function-import-capture/transitive-live-bindings.js

Comment thread source/units/Goccia.Modules.Loader.pas

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick comments (2)
source/units/Goccia.Modules.ContentProvider.Test.pas (2)

531-539: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Exception check is too broad to prove the "failed cycle" throw actually fired.

on E: Exception do RaisedExpected := True; matches any exception, so an unrelated failure (e.g. resolution error, missing global) would make the test pass without exercising the intended cyclic-failure path. Other tests in this file (e.g. TestEngineReportsJSONLModuleLineNumbers, lines 617-628) assert on message content for this reason.

♻️ Proposed tightening
         try
           ModuleLoader.LoadModule(FAILED_PATH, ENTRY_PATH);
         except
           on E: Exception do
-            RaisedExpected := True;
+          begin
+            RaisedExpected := Pos('failed cycle', E.Message) > 0;
+            if not RaisedExpected then
+              Fail('Unexpected exception: ' + E.Message);
+          end;
         end;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@source/units/Goccia.Modules.ContentProvider.Test.pas` around lines 531 - 539,
Update the exception handling in the cyclic parent module test around
ModuleLoader.LoadModule to assert that the caught exception contains the
expected cyclic-evaluation failure message, rather than treating every Exception
as success. Preserve the failure assertion when no matching exception is raised,
and follow the message-content assertion pattern used by
TestEngineReportsJSONLModuleLineNumbers.

541-545: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Invoke readImportedValue() and assert 'still live'
The export is only checked for existence and type here. Call it with TGocciaFunctionBase(ExportValue).CallNoArgs(TGocciaUndefinedLiteralValue.UndefinedValue) and assert the returned string so this case exercises the live-binding path.

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

In `@source/units/Goccia.Modules.ContentProvider.Test.pas` around lines 541 - 545,
Extend the test around readImportedValue in the SurvivorModule flow: after
confirming ExportValue is a TGocciaFunctionBase, invoke it via CallNoArgs with
TGocciaUndefinedLiteralValue.UndefinedValue and assert that the returned value
is the string “still live”. Keep the existing export existence, type, and
MarkExportReferences checks.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@source/units/Goccia.Modules.ContentProvider.Test.pas`:
- Around line 531-539: Update the exception handling in the cyclic parent module
test around ModuleLoader.LoadModule to assert that the caught exception contains
the expected cyclic-evaluation failure message, rather than treating every
Exception as success. Preserve the failure assertion when no matching exception
is raised, and follow the message-content assertion pattern used by
TestEngineReportsJSONLModuleLineNumbers.
- Around line 541-545: Extend the test around readImportedValue in the
SurvivorModule flow: after confirming ExportValue is a TGocciaFunctionBase,
invoke it via CallNoArgs with TGocciaUndefinedLiteralValue.UndefinedValue and
assert that the returned value is the string “still live”. Keep the existing
export existence, type, and MarkExportReferences checks.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 5e9d697a-2f9a-4776-8e50-5a4e326177d2

📥 Commits

Reviewing files that changed from the base of the PR and between 42bb9b8 and a639bb0.

📒 Files selected for processing (2)
  • source/units/Goccia.Modules.ContentProvider.Test.pas
  • source/units/Goccia.Modules.Loader.pas
🚧 Files skipped from review as they are similar to previous changes (1)
  • source/units/Goccia.Modules.Loader.pas

@frostney
frostney merged commit 6063729 into main Jul 23, 2026
49 checks passed
@frostney
frostney deleted the codex/fix-live-import-bindings branch July 23, 2026 13:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working spec compliance Mismatch against official JavaScript/TypeScript specification

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant