Skip to content

Support array-like arguments for apply and Reflect#244

Merged
frostney merged 4 commits into
mainfrom
fix/create-list-from-array-like
Apr 9, 2026
Merged

Support array-like arguments for apply and Reflect#244
frostney merged 4 commits into
mainfrom
fix/create-list-from-array-like

Conversation

@frostney
Copy link
Copy Markdown
Owner

@frostney frostney commented Apr 9, 2026

Summary

  • Added a shared CreateListFromArrayLike helper to convert arrays and array-like objects into argument lists.
  • Updated Function.prototype.apply, Reflect.apply, and Reflect.construct to accept array-like argumentsList values.
  • Preserved fast paths for small arrays while extending the general path to handle object-like inputs and missing indices.
  • Added coverage for empty inputs, sparse array-like objects, string length values, and invalid non-object arguments.

Fixes #231

Testing

  • Added JavaScript tests under tests/built-ins/Function/prototype/apply.js.
  • Extended JavaScript tests under tests/built-ins/Reflect/apply.js.
  • Extended JavaScript tests under tests/built-ins/Reflect/construct.js.

- Add shared CreateListFromArrayLike helper
- Accept array-like arguments in Function.prototype.apply, Reflect.apply, and Reflect.construct
- Expand end-to-end tests for array-like and invalid inputs
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 9, 2026

📝 Walkthrough

Walkthrough

Implements CreateListFromArrayLike and updates Function.prototype.apply, Reflect.apply, and Reflect.construct to accept array-like argument lists; adds/expands tests covering array-like inputs, edge cases, and invalid argumentsList values.

Changes

Cohort / File(s) Summary
Tests: Function & Reflect
tests/built-ins/Function/prototype/apply.js, tests/built-ins/Reflect/apply.js, tests/built-ins/Reflect/construct.js
Added new tests and expanded coverage to validate array-like argumentsList handling, empty/missing indices, string/zero length, null/undefined, and non-object error cases.
Array-Like Conversion Utility
units/Goccia.Arguments.ArrayLike.pas
New unit exposing CreateListFromArrayLike(AValue, AMethodName) implementing ES CreateListFromArrayLike: requires object, reads/normalizes length (ToNumber/ToUint32 semantics), iterates numeric indices, returns TGocciaArgumentsCollection, throws TypeError for non-objects.
Reflect builtins
units/Goccia.Builtins.GlobalReflect.pas
Replaced array-only argument handling with CreateListFromArrayLike usage in Reflect.apply and Reflect.construct; simplified instance assignment in Reflect.construct.
Function.prototype.apply implementation
units/Goccia.Values.FunctionBase.pas
Refactored FunctionApply to use CreateListFromArrayLike for non-array argArray, kept small-array fast-paths for TGocciaArrayValue (0–3 elements), standardized TypeError throwing, and centralized CallArgs allocation/cleanup.
Dependencies / Error helpers
units/Goccia.Values.FunctionBase.pas (imports)
Added dependencies on Goccia.Arguments.ArrayLike and Goccia.Values.ErrorHelper to support array-like conversion and canonical TypeError throwing.

Sequence Diagram(s)

sequenceDiagram
  participant Caller as JS Caller
  participant Builtin as Function/Reflect builtin
  participant Converter as CreateListFromArrayLike
  participant Target as Target function/constructor

  Caller->>Builtin: invoke apply/construct(target, thisArg/newTarget, argumentsList)
  Builtin->>Builtin: validate target (isFunction / isConstructor)
  alt argumentsList is null/undefined or omitted
    Builtin->>Target: Call/Construct with no args
    Target-->>Builtin: result
  else argumentsList is TGocciaArrayValue (fast-path)
    Builtin->>Target: fast-path Call/Construct with 0..3 args
    Target-->>Builtin: result
  else array-like object
    Builtin->>Converter: CreateListFromArrayLike(argumentsList, methodName)
    Converter-->>Builtin: TGocciaArgumentsCollection
    Builtin->>Target: Call/Construct with constructed args
    Target-->>Builtin: result
  end
  Builtin-->>Caller: return result
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: adding support for array-like arguments in apply and Reflect methods.
Description check ✅ Passed The description covers the main changes, includes the fixed issue number, and lists test files added/extended, though testing checkboxes are not marked.
Linked Issues check ✅ Passed The code changes fully implement CreateListFromArrayLike semantics for Reflect.apply, Reflect.construct, and Function.prototype.apply to accept array-like objects as required by issue #231.
Out of Scope Changes check ✅ Passed All changes are directly related to implementing array-like argument support for apply and Reflect APIs as specified in issue #231; no unrelated modifications detected.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

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


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

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

🤖 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/Function/prototype/apply.js`:
- Around line 45-68: Add two tests to cover absent and non-numeric length
handling in Function.prototype.apply: one where an array-like value is a plain
{} (no length) and one where length is a non-numeric string like "foo"; both
should behave as zero-length argument lists when calling a function (e.g., use a
function fn = () => "no-args" or fn = (...args) => args.length and assert
apply(undefined, {}) yields zero-args / "no-args" and apply(undefined, { length:
"foo" }) also yields zero-args). Place these alongside the existing tests (refer
to the existing test cases and test names such as "works with array-like
objects" and "works with array-like object with string length") so the suite
prevents regressions in ToLength handling shared with
Reflect.apply/Reflect.construct.

In `@units/Goccia.Arguments.ArrayLike.pas`:
- Around line 52-58: LengthProp returned by ArrayObj.GetProperty can be nil and
must be treated like undefined before dereferencing; update the logic in the
block that sets Len so it first checks "if LengthProp = nil or (LengthProp is
TGocciaUndefinedLiteralValue) or (LengthProp is TGocciaNullLiteralValue) then
Len := 0 else Len := Trunc(LengthProp.ToNumberLiteral.Value)". Use the existing
LengthProp symbol and TGocciaUndefinedLiteralValue/TGocciaNullLiteralValue type
checks to locate the code and ensure ToNumberLiteral.Value is only accessed when
LengthProp is non-nil.
- Around line 58-61: The current use of Trunc on
LengthProp.ToNumberLiteral.Value (assigning to Len) throws on NaN/±Infinity and
out-of-range values; update the ToLength logic so you first read the numeric
value (e.g., value := LengthProp.ToNumberLiteral.Value) and then: if
IsNan(value) or (value = 0) or IsNegativeInfinite(value) set Len := 0; else if
IsPositiveInfinite(value) set Len := 9007199254740991 (2^53-1); otherwise
truncate toward zero and clamp the result to the 0..9007199254740991 range
before assigning to Len. Use IsNan/IsInfinite checks instead of calling Trunc
directly and ensure the constant 9007199254740991 (MaxSafeInteger) is used.
🪄 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: 98a4fd08-5dab-4283-be33-083ecae50e43

📥 Commits

Reviewing files that changed from the base of the PR and between aa89efe and 0c978a0.

📒 Files selected for processing (6)
  • tests/built-ins/Function/prototype/apply.js
  • tests/built-ins/Reflect/apply.js
  • tests/built-ins/Reflect/construct.js
  • units/Goccia.Arguments.ArrayLike.pas
  • units/Goccia.Builtins.GlobalReflect.pas
  • units/Goccia.Values.FunctionBase.pas

Comment thread tests/built-ins/Function/prototype/apply.js
Comment thread units/Goccia.Arguments.ArrayLike.pas Outdated
Comment thread units/Goccia.Arguments.ArrayLike.pas Outdated
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 9, 2026

Benchmark Results

274 benchmarks

Interpreted: 🟢 207 improved · 🔴 18 regressed · 49 unchanged · avg +4.8%
Bytecode: 🟢 165 improved · 🔴 24 regressed · 85 unchanged · avg +3.2%

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

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

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 9, 2026

Suite Timing

Suite Metric Interpreted Bytecode
Tests Total 4090 4090
Tests Passed 4049 ✅ 4090 ✅
Tests Skipped 41 0
Tests Test Duration 294.0ms 269.9ms
Tests Lex 84.0ms 54.5ms
Tests Parse 107.2ms 105.3ms
Tests Compile 60.3ms
Tests Execute 309.0ms 300.4ms
Tests Engine Total 500.1ms 520.5ms
Benchmarks Total 274 274
Benchmarks Duration 7.68min 6.30min

Measured on ubuntu-latest x64.

…istFromArrayLike

Address CodeRabbit review feedback:
- Guard against nil from GetProperty before dereferencing LengthProp
- Use IsNan/range checks before Trunc to avoid EInvalidOp on NaN/Infinity
- Add tests for absent length ({}) and non-numeric string length ({length:"foo"})

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.

🧹 Nitpick comments (1)
units/Goccia.Arguments.ArrayLike.pas (1)

51-53: Minor doc inconsistency: comment says "cap at 2^53−1" but code caps at MaxInt.

The comment references ES spec's 2^53−1 limit, but line 66-67 uses MaxInt. This is a practical and correct limitation since Len: Integer cannot exceed MaxInt anyway, and allocating billions of arguments is infeasible. Consider updating the comment to reflect the actual behavior.

📝 Suggested documentation fix
   // ES2026 §7.3.18 step 2: Let len be ? LengthOfArrayLike(obj)
   // ES2026 §7.3.3 LengthOfArrayLike: ToLength(? Get(obj, "length"))
-  // ES2026 §7.1.22 ToLength: NaN/negative → 0, cap at 2^53−1
+  // ES2026 §7.1.22 ToLength: NaN/negative → 0, cap at MaxInt (practical limit)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@units/Goccia.Arguments.ArrayLike.pas` around lines 51 - 53, The comment in
units/Goccia.Arguments.ArrayLike.pas incorrectly states the ES spec cap as
"2^53−1" while the implementation for LengthOfArrayLike (ToLength → Len:
Integer) actually uses MaxInt; update the comment to reflect the real behavior
by noting that ToLength is conceptually capped at 2^53−1 per the ES spec but
this implementation further restricts length to the platform Integer limit
(MaxInt) and that extremely large allocations are infeasible — reference the
LengthOfArrayLike/ToLength explanation and the Len: Integer/MaxInt behavior in
the comment so readers understand the practical cap.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@units/Goccia.Arguments.ArrayLike.pas`:
- Around line 51-53: The comment in units/Goccia.Arguments.ArrayLike.pas
incorrectly states the ES spec cap as "2^53−1" while the implementation for
LengthOfArrayLike (ToLength → Len: Integer) actually uses MaxInt; update the
comment to reflect the real behavior by noting that ToLength is conceptually
capped at 2^53−1 per the ES spec but this implementation further restricts
length to the platform Integer limit (MaxInt) and that extremely large
allocations are infeasible — reference the LengthOfArrayLike/ToLength
explanation and the Len: Integer/MaxInt behavior in the comment so readers
understand the practical cap.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: e6857eef-26af-49b4-b999-f5d2f1444773

📥 Commits

Reviewing files that changed from the base of the PR and between 0c978a0 and d505af7.

📒 Files selected for processing (2)
  • tests/built-ins/Function/prototype/apply.js
  • units/Goccia.Arguments.ArrayLike.pas
✅ Files skipped from review due to trivial changes (1)
  • tests/built-ins/Function/prototype/apply.js

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

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

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

Inline comments:
In `@units/Goccia.Arguments.ArrayLike.pas`:
- Around line 74-75: Before calling
TGocciaArgumentsCollection.CreateWithCapacity, enforce a safe upper bound on Len
(which is script-controlled) and raise a RangeError if it exceeds that ceiling;
compute a boundedCount = Min(Len, MAX_SAFE_ARGS) (choose a constant like
MAX_SAFE_ARGS) and use boundedCount in the call to CreateWithCapacity, and if
Len > MAX_SAFE_ARGS raise a RangeError (or equivalent) before any allocation to
avoid pathological OOM/DoS.
🪄 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: 665fb80a-ec82-4532-b98e-2bffb1812de4

📥 Commits

Reviewing files that changed from the base of the PR and between d505af7 and 47681f1.

📒 Files selected for processing (1)
  • units/Goccia.Arguments.ArrayLike.pas

Comment thread units/Goccia.Arguments.ArrayLike.pas
…tFromArrayLike

Script-controlled length values (e.g. { length: 2e9 }) would allocate
multi-GB collections before iterating. Cap at MAX_ARGUMENTS_LIST_LENGTH
(2^20) and throw RangeError if exceeded.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@frostney frostney added the spec compliance Mismatch against official JavaScript/TypeScript specification label Apr 9, 2026
@frostney frostney merged commit a2e0d0e into main Apr 9, 2026
9 checks passed
@frostney frostney deleted the fix/create-list-from-array-like branch April 9, 2026 13:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

spec compliance Mismatch against official JavaScript/TypeScript specification

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Implement CreateListFromArrayLike semantics for Reflect.apply, Reflect.construct, and Function.prototype.apply

1 participant