Skip to content

Add Test262 bytecode support gaps#341

Merged
frostney merged 4 commits into
mainfrom
t3code/test262-bytecode-gaps
Apr 18, 2026
Merged

Add Test262 bytecode support gaps#341
frostney merged 4 commits into
mainfrom
t3code/test262-bytecode-gaps

Conversation

@frostney
Copy link
Copy Markdown
Owner

Summary

  • Adds bytecode support for several Test262 cases that previously failed, including async tests, spread in new expressions, and additional harness includes.
  • Teaches the compiler and VM to handle constructor spreads by passing array-backed argument packs through OP_CONSTRUCT.
  • Improves parser support for unparenthesized single-parameter arrow functions, including async arrows.
  • Exposes function name and length as own properties on built-in functions, and updates built-ins such as Object.assign, Math.max, and Math.min to report spec-correct arity.
  • Adds shims and syntax-filter support for isNaN, isFinite, Float16Array, arraybuffer-transfer, resizable-arraybuffer, and related Test262 harness pieces.
  • Expands coverage with new tests for built-in function metadata, legacy globals, arrow functions, and constructor spread syntax.

Testing

  • Not run
  • Expected validation: ./build.pas testrunner && ./build/GocciaTestRunner tests --asi
  • Expected validation: ./format.pas --check

- Support async tests, spread constructors, and unparenthesized arrows
- Expose function name/length as own properties
- Add shims and tests for isNaN, isFinite, and spread new expressions
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 18, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: b04e7eff-56c3-4568-959a-2a69608b85f3

📥 Commits

Reviewing files that changed from the base of the PR and between 92a5ca4 and 697a551.

📒 Files selected for processing (4)
  • tests/built-ins/Math/max.js
  • tests/built-ins/Number/isNaN.js
  • tests/built-ins/Object/assign.js
  • tests/built-ins/String/prototype/slice.js
✅ Files skipped from review due to trivial changes (4)
  • tests/built-ins/Number/isNaN.js
  • tests/built-ins/Math/max.js
  • tests/built-ins/String/prototype/slice.js
  • tests/built-ins/Object/assign.js

📝 Walkthrough

Walkthrough

Adds Test262 async test support and harness includes; implements spread-in-new-expression support across parser, compiler, and VM; exposes function name/length as own properties; adds isNaN/isFinite shims and numerous conformance tests (including Float16Array and constructor spread cases).

Changes

Cohort / File(s) Summary
Test262 runner & syntax filter
scripts/run_test262_suite.py, scripts/test262_syntax_filter.py
Detect async flag in test metadata, pass is_async to test wrapping, include doneprintHandle.js/detachArrayBuffer.js as available includes, improve failed-test id parsing, add bigint-literal detection, mark several features supported.
Test262 harness
scripts/test262_harness/detachArrayBuffer.js, scripts/test262_harness/doneprintHandle.js, scripts/test262_harness/testTypedArray.js
Add $262.detachArrayBuffer, $262.createRealm() (throws), $262.gc() (no-op); add $DONE promise helper for async tests; include Float16Array in typed-array precision mapping.
Parser
source/units/Goccia.Parser.pas
Parse unparenthesized single-parameter arrow functions (identifier => body) at assignment-expression level.
Compiler (expressions)
source/units/Goccia.Compiler.Expressions.pas
Refactor spread-argument compilation to accept generic argument lists; detect spread in new expressions and emit OP_CONSTRUCT with high-bit flag to indicate arguments-array path.
VM (construct)
source/units/Goccia.VM.pas
Interpret OP_CONSTRUCT operand C high-bit as spread-array discriminator; add spread path handling, conditional fast-paths, and register/argument-materialization adjustments.
Function metadata & shims
source/units/Goccia.Values.FunctionBase.pas, source/units/Goccia.Shims.pas, source/units/Goccia.Builtins.GlobalObject.pas, source/units/Goccia.Builtins.Math.pas
Expose length and name as own properties via overrides; add isNaN/isFinite shims; change arity registration for Object.assign, Math.max, and Math.min.
Tests — language & built-ins
tests/language/..., tests/built-ins/... (many files)
Add spread-in-new-expression suite; arrow-function (unparenthesized) tests including async cases; add many builtin metadata tests and suites for isNaN and isFinite, plus additional small metadata assertions across built-ins and prototypes.

Sequence Diagram(s)

sequenceDiagram
    participant Runner as Runner (scripts/run_test262_suite.py)
    participant Harness as Harness (test262_harness)
    participant Compiler as Compiler
    participant VM as VM

    Runner->>Compiler: wrap test body (is_async ? async wrapper + await __donePromise)
    Runner->>Harness: ensure includes (`doneprintHandle.js`, `detachArrayBuffer.js`) present
    Runner->>VM: execute wrapped test
    VM->>Harness: test code calls $DONE(error?)
    Harness->>Harness: resolve/reject __donePromise
    VM-->>Runner: report pass/fail
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Add Test262 bytecode support gaps' clearly and concisely summarizes the main objective of this PR—adding bytecode support for Test262 cases that previously failed.
Description check ✅ Passed The PR description covers the key changes (async tests, spread in new expressions, harness support, arrow functions, function metadata, and shims), includes testing expectations, and is aligned with the provided template structure.

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


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

@coderabbitai coderabbitai Bot added new feature New feature or request spec compliance Mismatch against official JavaScript/TypeScript specification internal Refactoring, CI, tooling, cleanup labels Apr 18, 2026
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 18, 2026

Benchmark Results

386 benchmarks

Interpreted: 🟢 241 improved · 🔴 55 regressed · 90 unchanged · avg +3.6%
Bytecode: 🟢 382 improved · 🔴 2 regressed · 2 unchanged · avg +36.3%

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

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

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 18, 2026

Suite Timing

Suite Metric Interpreted Bytecode
Tests Total 5718 5718
Tests Passed 5677 ✅ 5718 ✅
Tests Skipped 41 0
Tests Workers 4 4
Tests Test Duration 801.4ms 901.6ms
Tests Lex (cumulative) 130.7ms 81.2ms
Tests Parse (cumulative) 176.8ms 170.0ms
Tests Compile (cumulative) 111.3ms
Tests Execute (cumulative) 826.3ms 883.2ms
Tests Engine Total (cumulative) 1.13s 1.25s
Tests Lex (avg/worker) 32.7ms 20.3ms
Tests Parse (avg/worker) 44.2ms 42.5ms
Tests Compile (avg/worker) 27.8ms
Tests Execute (avg/worker) 206.6ms 220.8ms
Tests Engine Total (avg/worker) 283.4ms 311.4ms
Benchmarks Total 386 386
Benchmarks Workers 4 4
Benchmarks Duration 3.08min 3.06min

Measured on ubuntu-latest x64.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

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.Values.FunctionBase.pas (1)

136-150: ⚠️ Potential issue | 🟠 Major

GetPropertyWithContext synthesizes properties unconditionally, bypassing user-defined state and breaking configurable semantics.

The implementation returns synthetic values for PROP_LENGTH and PROP_NAME without checking whether the user has previously deleted or redefined these properties. After delete fn.name (removes from FProperties), the method still synthesizes a value instead of respecting the deletion. Similarly, after Object.defineProperty(fn, 'name', {value: 'custom'}) (stores to FProperties), the method synthesizes instead of checking stored properties first. Since ECMAScript requires both properties to be configurable and fully deletable/redefinable, the implementation violates spec compliance by always returning synthetic values regardless of user state changes.

This affects all three methods: GetPropertyWithContext (lines 136–150), HasOwnProperty (lines 162–168), and GetOwnPropertyDescriptor (lines 170–180) must be coordinated to track and respect property state.

Also review line 138 for ES annotation consistency with lines 162–180 per project guidelines.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@source/units/Goccia.Values.FunctionBase.pas` around lines 136 - 150,
GetPropertyWithContext currently synthesizes PROP_LENGTH and PROP_NAME
unconditionally; modify it to first consult the object's own properties/storage
(e.g. check FProperties/HasOwnProperty/GetOwnPropertyDescriptor or call
inherited behaviour) and only synthesize these values when there is no own
property present (i.e., the property hasn't been deleted or redefined). Likewise
ensure HasOwnProperty and GetOwnPropertyDescriptor are coordinated so they
reflect user state (return true/descriptor from FProperties if present,
otherwise behave as synthetic/configurable defaults). Also align the ES
annotation/comment in GetPropertyWithContext with the style used in
HasOwnProperty/GetOwnPropertyDescriptor for consistency.
🧹 Nitpick comments (5)
scripts/test262_syntax_filter.py (1)

287-288: Consider extending BigInt literal detection to cover non-decimal bases.

The current pattern \b\d[\d_]*n\b catches decimal BigInt literals (e.g., 123n, 1_000n) but misses hex (0x1ABn), octal (0o777n), and binary (0b101n) forms. Tests using those would pass the filter and fail at runtime instead of being skipped.

This is a minor gap since most test262 BigInt tests use decimal literals, and failing for the right reason still produces a correct signal.

♻️ Optional: Broader BigInt literal pattern
     ("bigint_literal",
-     re.compile(r"\b\d[\d_]*n\b")),
+     re.compile(r"\b(?:0[xX][\da-fA-F_]+|0[oO][0-7_]+|0[bB][01_]+|\d[\d_]*)n\b")),
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/test262_syntax_filter.py` around lines 287 - 288, The bigint_literal
regex only matches decimal BigInt forms; update the pattern used in the
("bigint_literal", re.compile(...)) tuple to also match hex (0x...), octal
(0o...), and binary (0b...) BigInt literals (e.g. 0x1ABn, 0o777n, 0b101n) by
expanding the regular expression to allow an optional 0[xob] prefix with
appropriate digit classes as well as the decimal form with underscores, so tests
containing non-decimal BigInt literals are correctly detected and filtered.
tests/language/expressions/spread/new-expression.js (2)

128-134: Test doesn't use spread syntax.

new Uint8Array(data) passes the array directly to the constructor (which accepts an array-like), not via spread. This tests TypedArray constructor behavior, not the spread feature.

If spread is intended:

const data = [1, 2, 3, 4];
const ta = new Uint8Array([...data]);
// or use a collector pattern as shown above
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/language/expressions/spread/new-expression.js` around lines 128 - 134,
The test "spread with TypedArray constructor" currently constructs the
TypedArray by passing the array directly to new Uint8Array(data) which doesn't
exercise the spread operator; update the test to construct the TypedArray using
spread (e.g. create the same data const data = [1,2,3,4] and instantiate ta with
new Uint8Array([...data]) or an equivalent collector pattern) so the test
actually verifies spread behavior while keeping the existing assertions on
ta.length and element values.

94-105: Tests don't exercise spread syntax.

These tests pass an array directly to the constructor (new Map(entries), new Set(vals)) rather than using spread (new Map(...entries), new Set(...vals)). Since Map/Set constructors accept iterables as their first argument, these tests validate constructor behavior but not spread compilation.

Consider either:

  • Updating to use spread: new Map([...entries]) or passing spread to a wrapper
  • Moving to a separate test file for constructor iterable support
🔧 If spread is intended, update to actually use spread syntax
  test("spread with Map constructor", () => {
-   const entries = [["a", 1], ["b", 2]];
-   const m = new Map(entries);
+   class MapWrapper {
+     constructor(...entries) {
+       this.map = new Map(entries);
+     }
+   }
+   const entries = [["a", 1], ["b", 2]];
+   const w = new MapWrapper(...entries);
+   expect(w.map.get("a")).toBe(1);
+   expect(w.map.get("b")).toBe(2);
  });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/language/expressions/spread/new-expression.js` around lines 94 - 105,
The tests currently pass the arrays directly to constructors (new Map(entries),
new Set(vals)) so they don't exercise spread syntax; update the tests to use
spread inside an array literal passed to the constructor (e.g., replace new
Map(entries) with new Map([...entries]) and replace new Set(vals) with new
Set([...vals])) so the spread operator is actually used on the source arrays
(variables entries and vals) in the test cases named "spread with Map
constructor" and "spread with Set constructor".
source/units/Goccia.Values.FunctionBase.pas (1)

162-180: Add ES spec annotations above the new spec-facing overrides.

Please annotate these new methods with the standard // ESYYYY §X.Y.Z SpecMethodName(specParams) format for consistency with project conventions.

Based on learnings: Applies to {**/Goccia.Values.*.pas,**/Goccia.Evaluator.pas,**/Goccia.Runtime.*.pas}: “Annotate each function implementing ECMAScript-specified behavior with // ESYYYY §X.Y.Z SpecMethodName(specParams) immediately above the function body...”

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@source/units/Goccia.Values.FunctionBase.pas` around lines 162 - 180, Add the
ES spec annotation comment immediately above the two new overrides: place a
single-line comment in the project's standard format (e.g. "// ES2021 §7.3.5
HasOwnProperty(P)" ) above TGocciaFunctionBase.HasOwnProperty and a matching one
(e.g. "// ES2021 §7.3.6 GetOwnPropertyDescriptor(P)") above
TGocciaFunctionBase.GetOwnPropertyDescriptor; ensure the comment uses the
"ESYYYY §X.Y.Z SpecMethodName(specParams)" pattern and replace the year/section
with the correct ECMAScript section numbers for the corresponding spec methods.
source/units/Goccia.Builtins.Math.pas (1)

110-111: Please run formatter and test commands before merge.

PR notes say validations were not run locally; please run ./format.pas --check and the TestRunner command before merging.

As per coding guidelines "**/*.pas: Execute ./format.pas --check before push or PR to verify code formatting compliance".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@source/units/Goccia.Builtins.Math.pas` around lines 110 - 111, Run the
repository formatter and tests before merging: execute ./format.pas --check (or
./format.pas to fix) to ensure Pascal files like the changes adding
Members.AddMethod(MathMax, 2, gmkStaticMethod) and Members.AddMethod(MathMin, 2,
gmkStaticMethod) comply with formatting guidelines, and then run the TestRunner
command used by the project to validate test suites; fix any formatting or test
failures and re-run until both checks pass.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@scripts/test262_harness/detachArrayBuffer.js`:
- Around line 6-7: Update the TypeError message in the $262.detachArrayBuffer
implementation so it accurately reflects both accepted types: change the error
thrown in the conditional that checks "buffer instanceof ArrayBuffer" and
"buffer instanceof SharedArrayBuffer" to mention "ArrayBuffer or
SharedArrayBuffer" (refer to the throw inside detachArrayBuffer in
detachArrayBuffer.js) so the message matches the actual type check.

In `@source/units/Goccia.Parser.pas`:
- Around line 2145-2167: The single-parameter arrow branch currently accepts an
identifier followed by a line break and =>; update the condition that detects
the arrow (the Check(gttArrow) path when Left is TGocciaIdentifierExpression) to
reject cases where a LineTerminator appears between the identifier and the =>
token (i.e., require the ECMAScript "[no LineTerminator here]" restriction).
Concretely, before consuming the => (Advance) ensure you call the parser's
existing line-terminator check (or add a small helper used elsewhere for
return/throw checks) and only proceed to build TGocciaArrowFunctionExpression
when no LineTerminator exists; otherwise fall through to normal parsing/error.
Also add a negative parser test to tests/language/functions/arrow-functions.js
that asserts a parse-time error for "ident<newline>=> ..." similar to
tests/language/asi/throw-statement.js.

In `@tests/language/functions/arrow-functions.js`:
- Around line 91-92: Remove the unnecessary async from the Promise executor:
change the new Promise(async resolve => resolve(99)) so the executor is
synchronous (e.g., resolve => resolve(99)) to avoid the async-executor
anti-pattern; update the Promise creation that assigns to p and keep the rest of
the test (expect(await p).toBe(99)) unchanged.

---

Outside diff comments:
In `@source/units/Goccia.Values.FunctionBase.pas`:
- Around line 136-150: GetPropertyWithContext currently synthesizes PROP_LENGTH
and PROP_NAME unconditionally; modify it to first consult the object's own
properties/storage (e.g. check
FProperties/HasOwnProperty/GetOwnPropertyDescriptor or call inherited behaviour)
and only synthesize these values when there is no own property present (i.e.,
the property hasn't been deleted or redefined). Likewise ensure HasOwnProperty
and GetOwnPropertyDescriptor are coordinated so they reflect user state (return
true/descriptor from FProperties if present, otherwise behave as
synthetic/configurable defaults). Also align the ES annotation/comment in
GetPropertyWithContext with the style used in
HasOwnProperty/GetOwnPropertyDescriptor for consistency.

---

Nitpick comments:
In `@scripts/test262_syntax_filter.py`:
- Around line 287-288: The bigint_literal regex only matches decimal BigInt
forms; update the pattern used in the ("bigint_literal", re.compile(...)) tuple
to also match hex (0x...), octal (0o...), and binary (0b...) BigInt literals
(e.g. 0x1ABn, 0o777n, 0b101n) by expanding the regular expression to allow an
optional 0[xob] prefix with appropriate digit classes as well as the decimal
form with underscores, so tests containing non-decimal BigInt literals are
correctly detected and filtered.

In `@source/units/Goccia.Builtins.Math.pas`:
- Around line 110-111: Run the repository formatter and tests before merging:
execute ./format.pas --check (or ./format.pas to fix) to ensure Pascal files
like the changes adding Members.AddMethod(MathMax, 2, gmkStaticMethod) and
Members.AddMethod(MathMin, 2, gmkStaticMethod) comply with formatting
guidelines, and then run the TestRunner command used by the project to validate
test suites; fix any formatting or test failures and re-run until both checks
pass.

In `@source/units/Goccia.Values.FunctionBase.pas`:
- Around line 162-180: Add the ES spec annotation comment immediately above the
two new overrides: place a single-line comment in the project's standard format
(e.g. "// ES2021 §7.3.5 HasOwnProperty(P)" ) above
TGocciaFunctionBase.HasOwnProperty and a matching one (e.g. "// ES2021 §7.3.6
GetOwnPropertyDescriptor(P)") above
TGocciaFunctionBase.GetOwnPropertyDescriptor; ensure the comment uses the
"ESYYYY §X.Y.Z SpecMethodName(specParams)" pattern and replace the year/section
with the correct ECMAScript section numbers for the corresponding spec methods.

In `@tests/language/expressions/spread/new-expression.js`:
- Around line 128-134: The test "spread with TypedArray constructor" currently
constructs the TypedArray by passing the array directly to new Uint8Array(data)
which doesn't exercise the spread operator; update the test to construct the
TypedArray using spread (e.g. create the same data const data = [1,2,3,4] and
instantiate ta with new Uint8Array([...data]) or an equivalent collector
pattern) so the test actually verifies spread behavior while keeping the
existing assertions on ta.length and element values.
- Around line 94-105: The tests currently pass the arrays directly to
constructors (new Map(entries), new Set(vals)) so they don't exercise spread
syntax; update the tests to use spread inside an array literal passed to the
constructor (e.g., replace new Map(entries) with new Map([...entries]) and
replace new Set(vals) with new Set([...vals])) so the spread operator is
actually used on the source arrays (variables entries and vals) in the test
cases named "spread with Map constructor" and "spread with Set constructor".
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: c67e3ba8-5209-406a-afe4-f47978c16c42

📥 Commits

Reviewing files that changed from the base of the PR and between 1a77f01 and 5ff335d.

📒 Files selected for processing (17)
  • scripts/run_test262_suite.py
  • scripts/test262_harness/detachArrayBuffer.js
  • scripts/test262_harness/doneprintHandle.js
  • scripts/test262_harness/testTypedArray.js
  • scripts/test262_syntax_filter.py
  • source/units/Goccia.Builtins.GlobalObject.pas
  • source/units/Goccia.Builtins.Math.pas
  • source/units/Goccia.Compiler.Expressions.pas
  • source/units/Goccia.Parser.pas
  • source/units/Goccia.Shims.pas
  • source/units/Goccia.VM.pas
  • source/units/Goccia.Values.FunctionBase.pas
  • tests/built-ins/function-name-length.js
  • tests/built-ins/isFinite.js
  • tests/built-ins/isNaN.js
  • tests/language/expressions/spread/new-expression.js
  • tests/language/functions/arrow-functions.js

Comment thread scripts/test262_harness/detachArrayBuffer.js Outdated
Comment thread source/units/Goccia.Parser.pas Outdated
Comment thread tests/language/functions/arrow-functions.js Outdated
- Fix detachArrayBuffer error message to mention SharedArrayBuffer
- Enforce [no LineTerminator here] before => in single-param arrows
- Remove async Promise executor anti-pattern from arrow tests
- Co-locate name/length tests with their respective builtin test files

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

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
tests/built-ins/Array/prototype/map.js (1)

92-98: Strengthen metadata coverage by asserting length descriptor semantics too.

Line 94 checks length value, but not property attributes. Add length descriptor checks (configurable, enumerable, writable) and guard descriptor existence for clearer failures.

Suggested patch
 test("map has correct name and length", () => {
   expect(Array.prototype.map.name).toBe("map");
   expect(Array.prototype.map.length).toBe(1);
+  expect(Object.prototype.hasOwnProperty.call(Array.prototype.map, "length")).toBe(true);
   const desc = Object.getOwnPropertyDescriptor(Array.prototype.map, "name");
+  const lengthDesc = Object.getOwnPropertyDescriptor(Array.prototype.map, "length");
+  expect(desc).toBeDefined();
+  expect(lengthDesc).toBeDefined();
   expect(desc.configurable).toBe(true);
   expect(desc.enumerable).toBe(false);
+  expect(desc.writable).toBe(false);
+  expect(lengthDesc.configurable).toBe(true);
+  expect(lengthDesc.enumerable).toBe(false);
+  expect(lengthDesc.writable).toBe(false);
 });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/built-ins/Array/prototype/map.js` around lines 92 - 98, Add assertions
that verify the property descriptor for Array.prototype.map.length: retrieve it
with Object.getOwnPropertyDescriptor(Array.prototype.map, "length"), assert the
descriptor exists, and then assert descriptor.configurable === true (or
expected), descriptor.enumerable === false, and descriptor.writable === false
(or expected) so the test covers length property semantics in addition to its
numeric value; update the test block that references Array.prototype.map to
include these checks alongside the existing name and length assertions.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@tests/built-ins/Array/of.js`:
- Around line 49-52: The test currently only checks the values of Array.of.name
and Array.of.length but must assert they are own properties; update the "has
correct name and length" test to also verify ownership by checking
Object.prototype.hasOwnProperty.call(Array.of, "name") and
Object.prototype.hasOwnProperty.call(Array.of, "length") (or use
Object.getOwnPropertyDescriptor(Array.of, "name") / "length" !== undefined) in
addition to the existing value assertions so the test fails if those properties
are inherited rather than own properties.

---

Nitpick comments:
In `@tests/built-ins/Array/prototype/map.js`:
- Around line 92-98: Add assertions that verify the property descriptor for
Array.prototype.map.length: retrieve it with
Object.getOwnPropertyDescriptor(Array.prototype.map, "length"), assert the
descriptor exists, and then assert descriptor.configurable === true (or
expected), descriptor.enumerable === false, and descriptor.writable === false
(or expected) so the test covers length property semantics in addition to its
numeric value; update the test block that references Array.prototype.map to
include these checks alongside the existing name and length assertions.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: c9b55c66-6a8d-4d31-ac87-50f34237d7d7

📥 Commits

Reviewing files that changed from the base of the PR and between 5ff335d and 576527f.

📒 Files selected for processing (17)
  • scripts/test262_harness/detachArrayBuffer.js
  • source/units/Goccia.Parser.pas
  • tests/built-ins/Array/from.js
  • tests/built-ins/Array/of.js
  • tests/built-ins/Array/prototype/filter.js
  • tests/built-ins/Array/prototype/forEach.js
  • tests/built-ins/Array/prototype/map.js
  • tests/built-ins/Array/prototype/reduce.js
  • tests/built-ins/Math/abs.js
  • tests/built-ins/Math/max.js
  • tests/built-ins/Math/min.js
  • tests/built-ins/Math/pow.js
  • tests/built-ins/Number/isNaN.js
  • tests/built-ins/Object/assign.js
  • tests/built-ins/String/prototype/includes.js
  • tests/built-ins/String/prototype/slice.js
  • tests/language/functions/arrow-functions.js
✅ Files skipped from review due to trivial changes (12)
  • tests/built-ins/String/prototype/slice.js
  • tests/built-ins/Array/prototype/forEach.js
  • tests/built-ins/String/prototype/includes.js
  • tests/built-ins/Array/prototype/filter.js
  • tests/built-ins/Array/prototype/reduce.js
  • tests/built-ins/Array/from.js
  • tests/built-ins/Object/assign.js
  • tests/built-ins/Math/pow.js
  • tests/built-ins/Math/max.js
  • tests/built-ins/Number/isNaN.js
  • tests/built-ins/Math/min.js
  • tests/built-ins/Math/abs.js
🚧 Files skipped from review as they are similar to previous changes (3)
  • tests/language/functions/arrow-functions.js
  • scripts/test262_harness/detachArrayBuffer.js
  • source/units/Goccia.Parser.pas

Comment thread tests/built-ins/Array/of.js
frostney and others added 2 commits April 18, 2026 20:06
- Array.of: verify name/length are own properties via getOwnPropertyDescriptor
- Array.prototype.map: add length descriptor checks (configurable, enumerable, writable)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- assert name/length descriptors for several built-ins
- cover Math.max, Number.isNaN, Object.assign, and String.prototype.slice
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

internal Refactoring, CI, tooling, cleanup new feature New feature or request spec compliance Mismatch against official JavaScript/TypeScript specification

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant