Skip to content

Support set-like operands for Set methods#429

Merged
frostney merged 3 commits into
mainfrom
t3code/issue-422-verify-implement
Apr 27, 2026
Merged

Support set-like operands for Set methods#429
frostney merged 3 commits into
mainfrom
t3code/issue-422-verify-implement

Conversation

@frostney
Copy link
Copy Markdown
Owner

@frostney frostney commented Apr 27, 2026

Summary

  • implement ES Set Record handling for Set operation operands
  • allow Set-like objects with size, has(), and keys() across union/intersection/difference/symmetricDifference and subset/superset/disjoint checks
  • add JS regressions and update Set docs

Fixes #422.

@vercel
Copy link
Copy Markdown

vercel Bot commented Apr 27, 2026

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

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
gocciascript-homepage Ignored Ignored Preview Apr 27, 2026 5:50pm

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 27, 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: e895a540-1fbe-4cd3-94ca-4fd71d569a34

📥 Commits

Reviewing files that changed from the base of the PR and between 78d75ec and 92e6f0f.

📒 Files selected for processing (2)
  • source/units/Goccia.Values.Iterator.Generic.pas
  • tests/built-ins/Set/prototype/intersection.js
✅ Files skipped from review due to trivial changes (1)
  • source/units/Goccia.Values.Iterator.Generic.pas
🚧 Files skipped from review as they are similar to previous changes (1)
  • tests/built-ins/Set/prototype/intersection.js

📝 Walkthrough

Walkthrough

Set operation methods (union, intersection, difference, symmetricDifference, isSubsetOf, isSupersetOf, isDisjointFrom) were changed to accept ECMAScript “set-like” objects (having size, callable has(value), and callable keys() returning an iterator). Documentation, error messages, iterator validation, core Set implementation, and tests were updated accordingly.

Changes

Cohort / File(s) Summary
Documentation
docs/built-ins.md, docs/value-system.md
Documented that Set operation methods accept Set or set-like objects (size, has(value), keys()); expanded TGocciaSetValue shared-prototype API to list set operations and set-like input semantics.
Error Messages & Suggestions
source/units/Goccia.Error.Messages.pas, source/units/Goccia.Error.Suggestions.pas
Replaced strict Set-only error with SErrorSetOperationRequiresSetLike; added granular messages for size type/negative, non-callable has/keys, and non-iterator keys(); updated suggestion SSuggestSetOperationArgType.
Core Set implementation
source/units/Goccia.Values.SetValue.pas
Introduced TGocciaSetRecord and helpers (GetSetRecord, SetRecordHas, GetSetRecordKeysIterator, SetDataIndex, RemoveSetItem); refactored Set prototype methods to use GetSetRecord and handle set-like iteration branches; rewrote ContainsValue; added GC temporary-root handling for intermediate iterators/results.
Iterator validation
source/units/Goccia.Values.Iterator.Generic.pas
AdvanceNext and DirectNext now throw a TypeError if next() returns a non-object, using formatted error text; added SysUtils for Format.
Tests — Set operations
tests/built-ins/Set/prototype/union.js, .../intersection.js, .../difference.js, .../symmetricDifference.js, .../isSubsetOf.js, .../isSupersetOf.js, .../isDisjointFrom.js
Added tests that pass set-like objects as operands; added branch coverage for size-based iteration selection; added field-level validation tests for invalid has/keys/size; updated TypeError test descriptions to reference “set-like” inputs.
Tests — Iterator.from
tests/built-ins/Iterator/from.js
Added test asserting that an iterator-like whose next() returns a non-object causes iter.next() to throw TypeError.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant SetOp as Set.prototype.method
    participant GetSetRecord as GetSetRecord\n(validation)
    participant KeysIter as Keys Iterator
    participant ResultSet as Result Set

    Client->>SetOp: call Set.prototype.method(other)
    SetOp->>GetSetRecord: validate other (object, size, has, keys)
    GetSetRecord->>GetSetRecord: coerce/check size\nensure non-negative
    GetSetRecord->>GetSetRecord: ensure has is callable
    GetSetRecord->>GetSetRecord: ensure keys is callable
    GetSetRecord-->>SetOp: return SetRecord(size, has, keys)
    alt iterate using smaller size's keys()
        SetOp->>KeysIter: obtain iterator from SetRecord.keys()
        KeysIter-->>SetOp: iterator
        loop iterate keys
            SetOp->>SetOp: call counterpart.has(key)\ncheck membership/add to ResultSet
            SetOp->>ResultSet: add key / update size
        end
    else iterate own items calling counterpart.has(value)
        loop iterate own items
            SetOp->>GetSetRecord: call SetRecord.has(value)
            SetOp->>ResultSet: add value if absent
        end
    end
    SetOp-->>Client: return ResultSet
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 summarizes the main change: extending Set methods to accept set-like operands instead of only Set instances.
Description check ✅ Passed The PR description covers the key changes (ES Set Record handling, set-like object support for seven methods, docs update, and issue reference) but lacks testing checkbox details and benchmark verification details from the template.
Linked Issues check ✅ Passed The PR implements all three requirements from issue #422: GetSetRecord validation for size/has/keys, replacement of TGocciaSetValue checks in all 7 Set methods, and iterator-based iteration replacing direct FItems access.
Out of Scope Changes check ✅ Passed One change—enhanced iterator result validation in Goccia.Values.Iterator.Generic.pas—is tangential to set-like operands but supports Set methods' use of keys iterators and aligns with issue context.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

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


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

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

github-actions Bot commented Apr 27, 2026

Benchmark Results

386 benchmarks

Interpreted: 🟢 114 improved · 🔴 16 regressed · 256 unchanged · avg +0.9%
Bytecode: 🟢 23 improved · 🔴 316 regressed · 47 unchanged · avg -5.8%

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

Suite Timing

Suite Metric Interpreted Bytecode
Tests Total 8024 8024
Tests Passed 7983 ✅ 8024 ✅
Tests Skipped 41 0
Tests Workers 4 4
Tests Test Duration 1.80s 1.80s
Tests Lex (cumulative) 209.8ms 117.2ms
Tests Parse (cumulative) 307.1ms 282.9ms
Tests Compile (cumulative) 189.2ms
Tests Execute (cumulative) 1.71s 1.72s
Tests Engine Total (cumulative) 2.23s 2.31s
Tests Lex (avg/worker) 52.5ms 29.3ms
Tests Parse (avg/worker) 76.8ms 70.7ms
Tests Compile (avg/worker) 47.3ms
Tests Execute (avg/worker) 427.9ms 429.7ms
Tests Engine Total (avg/worker) 557.1ms 577.0ms
Benchmarks Total 386 386
Benchmarks Workers 4 4
Benchmarks Duration 2.91min 2.72min

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: 1

🧹 Nitpick comments (3)
tests/built-ins/Set/prototype/isDisjointFrom.js (1)

22-61: Make the size-based branch test observable.

The new “other size is smaller” case still passes if the implementation uses has() instead of switching to keys(). If you want this test to guard the branch behavior, make has() fail or assert call counts so the keys() path is exercised.

Suggested test hardening
   test("uses set-like keys when other size is smaller", () => {
     const setLike = {
       size: 1,
-      has(value) {
-        return value === 3 || value === 4;
-      },
+      has() {
+        throw new Error("unexpected has() call");
+      },
       keys() {
         return [3, 4].values();
       },
     };
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/built-ins/Set/prototype/isDisjointFrom.js` around lines 22 - 61, The
test for the "other size is smaller" branch is not observable because
implementations that always call has() still pass; update the test for
Set.prototype.isDisjointFrom so it forces the algorithm to use keys() when the
other.size is smaller—e.g., make the set-like object's has() throw or increment
a counter and assert it is not called (or assert keys() is called) so the
keys()-based path is actually exercised; target the set-like object used in that
test and the isDisjointFrom invocation so the behavior is clearly verified.
tests/built-ins/Set/prototype/difference.js (1)

23-66: Make the size-based branch test observable.

The new branch-specific case still passes if the implementation falls back to the has()-based path. If the goal is to lock down the keys() branch, make has() fail or otherwise assert call counts so the optimized path is actually exercised.

Suggested test hardening
   test("uses set-like keys when other size is smaller", () => {
     const setLike = {
       size: 1,
-      has(value) {
-        return value === 2 || value === 4;
-      },
+      has() {
+        throw new Error("unexpected has() call");
+      },
       keys() {
         return [2, 4, 4].values();
       },
     };
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/built-ins/Set/prototype/difference.js` around lines 23 - 66, The "uses
set-like keys when other size is smaller" test isn't observable because an
implementation can ignore keys() and use has(); change the test's setLike so
has() will fail if called (e.g., throw or increment a spy and assert zero calls)
and keep keys() returning the expected iterator, then assert the result still
contains 1 and 3 and size 2; this forces execution of the keys()-driven branch
in Set.prototype.difference and proves the size-based optimization is exercised.
tests/built-ins/Set/prototype/intersection.js (1)

38-52: Make the “keys path” test branch-discriminating.

Right now the test can still pass if intersection incorrectly uses has() in this branch. Make has() intentionally disagree with keys() so only the keys-iterator path succeeds.

Suggested test hardening
   test("uses set-like keys when other size is smaller", () => {
     const setLike = {
       size: 1,
       has(value) {
-        return value === 2 || value === 4;
+        return false;
       },
       keys() {
         return [2, 4, 4].values();
       },
     };
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/built-ins/Set/prototype/intersection.js` around lines 38 - 52, The test
"uses set-like keys when other size is smaller" should force the codepath to use
the keys() iterator rather than has(): update the setLike object so has()
disagrees with keys() (e.g. make has(value) return true only for 2 while keys()
yields [2, 4, 4]) so an implementation that wrongly uses has() will fail but a
correct intersection(Set.prototype.intersection) that iterates keys() will pass;
adjust the setLike.has and/or keys implementations inside that test to create
this intentional disagreement.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@source/units/Goccia.Values.SetValue.pas`:
- Around line 164-189: AdvanceNext and DirectNext currently treat non-object
results from iterator.next() as "done" but must instead throw a TypeError like
Return does; update both AdvanceNext and DirectNext to validate the value
returned by the invoked next() call and if it is not a TGocciaObjectValue (or is
TGocciaUndefinedLiteralValue) call ThrowTypeError with the same or analogous
error message used in Return (the TypeError path at lines ~171–172) so
non-object next() results raise an error per the spec; locate the calls that
invoke NextMethod in AdvanceNext and DirectNext and add the same object-check +
ThrowTypeError logic used in the Return method.

---

Nitpick comments:
In `@tests/built-ins/Set/prototype/difference.js`:
- Around line 23-66: The "uses set-like keys when other size is smaller" test
isn't observable because an implementation can ignore keys() and use has();
change the test's setLike so has() will fail if called (e.g., throw or increment
a spy and assert zero calls) and keep keys() returning the expected iterator,
then assert the result still contains 1 and 3 and size 2; this forces execution
of the keys()-driven branch in Set.prototype.difference and proves the
size-based optimization is exercised.

In `@tests/built-ins/Set/prototype/intersection.js`:
- Around line 38-52: The test "uses set-like keys when other size is smaller"
should force the codepath to use the keys() iterator rather than has(): update
the setLike object so has() disagrees with keys() (e.g. make has(value) return
true only for 2 while keys() yields [2, 4, 4]) so an implementation that wrongly
uses has() will fail but a correct intersection(Set.prototype.intersection) that
iterates keys() will pass; adjust the setLike.has and/or keys implementations
inside that test to create this intentional disagreement.

In `@tests/built-ins/Set/prototype/isDisjointFrom.js`:
- Around line 22-61: The test for the "other size is smaller" branch is not
observable because implementations that always call has() still pass; update the
test for Set.prototype.isDisjointFrom so it forces the algorithm to use keys()
when the other.size is smaller—e.g., make the set-like object's has() throw or
increment a counter and assert it is not called (or assert keys() is called) so
the keys()-based path is actually exercised; target the set-like object used in
that test and the isDisjointFrom invocation so the behavior is clearly verified.
🪄 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: 9501bf69-7425-444d-8e91-9db6df97e705

📥 Commits

Reviewing files that changed from the base of the PR and between fb7ccd9 and 411ceb2.

📒 Files selected for processing (12)
  • docs/built-ins.md
  • docs/value-system.md
  • source/units/Goccia.Error.Messages.pas
  • source/units/Goccia.Error.Suggestions.pas
  • source/units/Goccia.Values.SetValue.pas
  • tests/built-ins/Set/prototype/difference.js
  • tests/built-ins/Set/prototype/intersection.js
  • tests/built-ins/Set/prototype/isDisjointFrom.js
  • tests/built-ins/Set/prototype/isSubsetOf.js
  • tests/built-ins/Set/prototype/isSupersetOf.js
  • tests/built-ins/Set/prototype/symmetricDifference.js
  • tests/built-ins/Set/prototype/union.js

Comment thread source/units/Goccia.Values.SetValue.pas
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 (2)
tests/built-ins/Set/prototype/intersection.js (1)

38-46: Optional: make has() throw to hard-assert the keys-based branch.

The test already checks output shape, but making has() throw would prove this path does not consult has() when other.size is smaller.

Suggested test hardening
   const setLike = {
     size: 1,
-    has(value) {
-      return value === 2;
-    },
+    has() {
+      throw new Error("has() must not be called in this branch");
+    },
     keys() {
       return [2, 4, 4].values();
     },
   };
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/built-ins/Set/prototype/intersection.js` around lines 38 - 46, Modify
the "uses set-like keys when other size is smaller" test to make the setLike.has
method throw (e.g., throw new Error("has should not be called")) so the test
will fail if the intersection implementation erroneously calls has; keep
setLike.keys() returning [2,4,4].values() and leave the rest of the test
assertions unchanged so the test hard-asserts the keys-based branch is used.
source/units/Goccia.Values.Iterator.Generic.pas (1)

70-96: Remove unreachable fallback branches after the new TypeError guards.

After Line 70 and Line 127 throw on non-object NextResult, the later else paths for non-object results cannot execute. Flattening to a single object path will make both methods easier to maintain.

Also applies to: 127-156

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

In `@source/units/Goccia.Values.Iterator.Generic.pas` around lines 70 - 96, The
code currently guards non-object NextResult with ThrowTypeError but still
contains unreachable fallback else branches; remove the redundant non-object
branches and flatten the logic to assume NextResult is TGocciaObjectValue after
the ThrowTypeError check. Specifically, in the methods handling NextResult
(references: NextResult, TGocciaObjectValue, ThrowTypeError) eliminate the final
"else" branch that sets FDone and returns an undefined result, and consolidate
the remaining logic to fetch PROP_DONE and PROP_VALUE (DoneVal, ValueVal,
PROP_DONE, PROP_VALUE, TGocciaUndefinedLiteralValue), set FDone accordingly, and
return CreateIteratorResult with the appropriate done flag; do the same refactor
for the analogous block around lines 127–156.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@source/units/Goccia.Values.Iterator.Generic.pas`:
- Around line 70-96: The code currently guards non-object NextResult with
ThrowTypeError but still contains unreachable fallback else branches; remove the
redundant non-object branches and flatten the logic to assume NextResult is
TGocciaObjectValue after the ThrowTypeError check. Specifically, in the methods
handling NextResult (references: NextResult, TGocciaObjectValue, ThrowTypeError)
eliminate the final "else" branch that sets FDone and returns an undefined
result, and consolidate the remaining logic to fetch PROP_DONE and PROP_VALUE
(DoneVal, ValueVal, PROP_DONE, PROP_VALUE, TGocciaUndefinedLiteralValue), set
FDone accordingly, and return CreateIteratorResult with the appropriate done
flag; do the same refactor for the analogous block around lines 127–156.

In `@tests/built-ins/Set/prototype/intersection.js`:
- Around line 38-46: Modify the "uses set-like keys when other size is smaller"
test to make the setLike.has method throw (e.g., throw new Error("has should not
be called")) so the test will fail if the intersection implementation
erroneously calls has; keep setLike.keys() returning [2,4,4].values() and leave
the rest of the test assertions unchanged so the test hard-asserts the
keys-based branch is used.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 9f5afb94-503d-458c-b411-4aef1f4b1a24

📥 Commits

Reviewing files that changed from the base of the PR and between 411ceb2 and 78d75ec.

📒 Files selected for processing (6)
  • source/units/Goccia.Values.Iterator.Generic.pas
  • tests/built-ins/Iterator/from.js
  • tests/built-ins/Set/prototype/difference.js
  • tests/built-ins/Set/prototype/intersection.js
  • tests/built-ins/Set/prototype/isDisjointFrom.js
  • tests/built-ins/Set/prototype/union.js
✅ Files skipped from review due to trivial changes (1)
  • tests/built-ins/Set/prototype/isDisjointFrom.js
🚧 Files skipped from review as they are similar to previous changes (2)
  • tests/built-ins/Set/prototype/difference.js
  • tests/built-ins/Set/prototype/union.js

@frostney frostney merged commit bb735ad into main Apr 27, 2026
12 checks passed
@frostney frostney deleted the t3code/issue-422-verify-implement branch April 27, 2026 18:01
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.

Set operation methods should accept set-like objects via GetSetRecord

1 participant