Skip to content

Implement BigInt spec support#343

Merged
frostney merged 7 commits intomainfrom
t3code/implement-bigint-spec
Apr 18, 2026
Merged

Implement BigInt spec support#343
frostney merged 7 commits intomainfrom
t3code/implement-bigint-spec

Conversation

@frostney
Copy link
Copy Markdown
Owner

@frostney frostney commented Apr 18, 2026

Summary

  • Added native BigInt support with parsing, arithmetic, bitwise operations, comparisons, shifts, conversions, and asIntN / asUintN helpers.
  • Wired BigInt into the runtime, lexer, parser, compiler, VM, JSON handling, error messages, and global built-ins.
  • Added BigInt literals, coercion, constructor, prototype-method, arithmetic, bitwise, comparison, and type-error coverage.

- Add BigInteger arithmetic and conversions
- Wire BigInt literals, builtins, and VM handling
- Add parser, evaluator, and test coverage for BigInt
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 18, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 89bb6a47-397c-4997-9b2a-f328b9788d4a

📥 Commits

Reviewing files that changed from the base of the PR and between 47c6110 and a9c4026.

📒 Files selected for processing (1)
  • source/units/Goccia.Values.BigIntObjectValue.pas
🚧 Files skipped from review as they are similar to previous changes (1)
  • source/units/Goccia.Values.BigIntObjectValue.pas

📝 Walkthrough

Walkthrough

Adds ECMAScript BigInt: new limb-backed TBigInteger, BigInt primitive/object wrappers, lexer/parser/bytecode/compiler/VM/evaluator/operator wiring, global BigInt builtin with asIntN/asUintN, error/suggestion strings, tests, docs, and spec updates.

Changes

Cohort / File(s) Summary
Core BigInteger Library
source/shared/BigInteger.pas
New TBigInteger record: limb-backed magnitude, sign, parsing (decimal/hex/bin/oct), formatting, arithmetic (add/sub/mul/div/mod/exp), bitwise (two’s-complement), shifts, AsIntN/AsUintN, conversions, and error handling.
Runtime Value & Object Types
source/units/Goccia.Values.BigIntValue.pas, source/units/Goccia.Values.BigIntObjectValue.pas, source/units/Goccia.Values.BigIntObjectValue.pas
Introduces TGocciaBigIntValue primitive, singletons (0n/1n), shared prototype and methods; TGocciaBigIntObjectValue for boxed BigInt instances and prototype method wiring.
Global Builtin & Engine Registration
source/units/Goccia.Builtins.GlobalBigInt.pas, source/units/Goccia.Engine.pas
Adds global BigInt builtin, BigIntConstructor, static asIntN/asUintN methods, prototype registration, engine member field and lifecycle handling.
Lexer / Token / Parser
source/units/Goccia.Lexer.pas, source/units/Goccia.Token.pas, source/units/Goccia.Parser.pas
Adds gttBigInt token (numeric n suffix), updates regex start context, numeric-separator handling, and parser conversion of bigint lexemes into TBigInteger via From*String methods.
Compiler / Bytecode / Constants
source/units/Goccia.Bytecode.Chunk.pas, source/units/Goccia.Compiler.Expressions.pas
New constant kind bckBigInt and TGocciaFunctionTemplate.AddConstantBigInt; compiler emits BigInt constants into constant pool and OP_LOAD_CONST for bigint entries.
VM, Evaluator & Operators
source/units/Goccia.VM.pas, source/units/Goccia.Evaluator.Arithmetic.pas, source/units/Goccia.Evaluator.Bitwise.pas, source/units/Goccia.Evaluator.pas
BigInt fast paths for arithmetic, bitwise, shifts, comparisons, unary ops; mixed BigInt/Number operations rejected; runtime errors for div/mod-by-zero, negative exponent, unsigned-right-shift with BigInt; VM materializes bigint constants.
Comparison, Equality & Helpers
source/units/Goccia.Evaluator.Comparison.pas, source/units/Goccia.Values.ClassHelper.pas
Strict and SameValue equality extended for BigInt; added CompareBigIntAndNumber helper and BigInt-aware IsEqual branch.
Boxing & Constructor Behavior
source/units/Goccia.Values.ClassValue.pas, source/units/Goccia.Values.Primitives.pas, source/units/Goccia.Builtins.GlobalObject.pas
Primitive boxing now supports BigInt; Object constructor coercion adjusted for primitives/non-primitives; note on BigInt singletons pinned elsewhere.
Constants, Errors & Suggestions
source/units/Goccia.Constants.ConstructorNames.pas, source/units/Goccia.Constants.TypeNames.pas, source/units/Goccia.Error.Messages.pas, source/units/Goccia.Error.Suggestions.pas
Adds CONSTRUCTOR_BIGINT, BIGINT_TYPE_NAME, many SError*/SSuggest* strings for BigInt-specific runtime errors and suggestions.
JSON & Stringification
source/units/Goccia.JSON.pas
TGocciaJSONStringifier now throws on BigInt values (disallow JSON serialization of BigInt).
BigInt Constant Materialization
source/units/Goccia.VM.pas
VM parses bckBigInt constant string via TBigInteger.FromDecimalString and pushes TGocciaBigIntValue during execution.
Tests, Docs & Spec
tests/built-ins/BigInt/*, tests/language/expressions/bigint/*, docs/*, source/units/Goccia.Spec.pas
Adds comprehensive BigInt tests (literals, constructor, coercion, prototype methods, arithmetic, bitwise, comparisons, type errors), docs updates, decision log entry, and ES2020 spec table row.

Sequence Diagram(s)

sequenceDiagram
    participant Source
    participant Lexer
    participant Parser
    participant Compiler
    participant Bytecode

    Source->>Lexer: "42n"
    Note right of Lexer: scan number, ensure no decimal/exponent, consume 'n', strip separators
    Lexer->>Parser: Token(gttBigInt, "42")
    Parser->>Parser: TBigInteger.FromDecimalString("42")
    Parser->>Compiler: TGocciaLiteralExpression(BigInt)
    Compiler->>Compiler: AddConstantBigInt("42")
    Compiler->>Bytecode: Emit OP_LOAD_CONST (bckBigInt)
Loading
sequenceDiagram
    participant Bytecode
    participant VM
    participant ConstPool
    participant Evaluator
    participant Stack

    Bytecode->>VM: OP_LOAD_CONST (index)
    VM->>ConstPool: Fetch constant (bckBigInt -> "42")
    ConstPool->>VM: Return "42"
    VM->>VM: TBigInteger.FromDecimalString("42")
    VM->>Stack: Push TGocciaBigIntValue(42n)

    Note right of Stack: Later OP_ADD (42n + 1n)
    Bytecode->>VM: OP_ADD
    VM->>Evaluator: Both operands BigInt?
    Evaluator->>Evaluator: Call TBigInteger.Add()
    Evaluator->>Stack: Push result BigInt
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Implement BigInt spec support' clearly and concisely summarizes the main change: adding BigInt support to the codebase. It is specific and directly related to the extensive changeset covering BigInt parsing, arithmetic, operations, and integration.
Description check ✅ Passed The description covers the main changes (BigInt support across parsing, arithmetic, bitwise, comparisons, conversions) and mentions testing, but the required checklist items lack specific evidence of completion and documentation updates are not explicitly confirmed as done.
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 labels Apr 18, 2026
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 18, 2026

Suite Timing

Suite Metric Interpreted Bytecode
Tests Total 5789 5789
Tests Passed 5748 ✅ 5789 ✅
Tests Skipped 41 0
Tests Workers 4 4
Tests Test Duration 1.20s 1.00s
Tests Lex (cumulative) 172.4ms 79.3ms
Tests Parse (cumulative) 229.0ms 169.6ms
Tests Compile (cumulative) 113.0ms
Tests Execute (cumulative) 1.19s 1.09s
Tests Engine Total (cumulative) 1.59s 1.45s
Tests Lex (avg/worker) 43.1ms 19.8ms
Tests Parse (avg/worker) 57.3ms 42.4ms
Tests Compile (avg/worker) 28.3ms
Tests Execute (avg/worker) 297.6ms 272.6ms
Tests Engine Total (avg/worker) 398.0ms 363.1ms
Benchmarks Total 386 386
Benchmarks Workers 4 4
Benchmarks Duration 3.08min 2.91min

Measured on ubuntu-latest x64.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 18, 2026

Benchmark Results

386 benchmarks

Interpreted: 🟢 41 improved · 🔴 95 regressed · 250 unchanged · avg -0.1%
Bytecode: 🟢 33 improved · 🔴 135 regressed · 218 unchanged · avg -0.2%

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

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.

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

🧹 Nitpick comments (1)
source/units/Goccia.VM.pas (1)

467-468: VMAddValues correctly calls ToPrimitive; other arithmetic operations don't.

VMAddValues (lines 754-772) properly calls ToPrimitive(ALeft) and ToPrimitive(ARight) before checking for BigInt mixed-type, so the addition example is correct per spec. However, VMSubtractValues, VMMultiplyValues, VMDivideValues, VMModuloValues, and VMPowerValues skip this step and check raw types directly via VMToNumericPair, creating an inconsistency. If object wrapping (ES6 Object(1n)) is later implemented, subtraction and the other operations will fail to coerce boxed BigInts correctly.

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

In `@source/units/Goccia.VM.pas` around lines 467 - 468, VMSubtractValues,
VMMultiplyValues, VMDivideValues, VMModuloValues and VMPowerValues currently
operate on raw operands and skip ToPrimitive, causing incorrect handling of
boxed BigInts; update each of these functions to call ToPrimitive(ALeft) and
ToPrimitive(ARight) (as VMAddValues does) before performing the BigInt
mixed-type check and before calling VMToNumericPair, and then use the same XOR
check (if (ALeft is TGocciaBigIntValue) xor (ARight is TGocciaBigIntValue) then
ThrowTypeError(...)) so boxed BigInt objects are coerced correctly prior to
numeric conversion.
🤖 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.Builtins.GlobalBigInt.pas`:
- Around line 157-167: Replace the raw Trunc(ToNumberLiteral.Value) coercion for
the bits parameter with the standard ToIndex logic: call the existing ToIndex
abstract-op implementation (from Goccia.Values.ArrayBufferValue.pas) on
AArgs.GetElement(0) to produce Bits so undefined/NaN → 0 and
Infinity/negative/too-large values throw RangeError; keep the existing
RequireAtLeast(AArgs, 2, 'BigInt.asIntN', ThrowError) and BigInt type-check
(BigIntArg is TGocciaBigIntValue) and then pass the resulting Bits to
TGocciaBigIntValue(...).Value.AsIntN(Bits); apply the same replacement in
BigInt.asUintN where Trunc(ToNumberLiteral.Value) is used.
- Around line 117-124: Replace the incorrect ThrowTypeError calls with
ThrowRangeError in the Number-to-BigInt conversion branch: where the code checks
TGocciaNumberLiteralValue(Arg).IsNaN or .IsInfinite and where it checks
Frac(NumVal) <> 0, call ThrowRangeError (passing the same formatted
SErrorBigIntNotInteger and SSuggestBigIntNoImplicitConversion arguments) instead
of ThrowTypeError so the BigInt(number) path follows the ECMAScript
NumberToBigInt semantics.
- Around line 129-140: The string-to-BigInt branch must accept non-decimal
integer literal prefixes and throw SyntaxError on parse failure: trim whitespace
from TGocciaStringLiteralValue(Arg).Value, detect prefix 0x/0X → use
TBigInteger.FromHexString, 0o/0O → FromOctalString, 0b/0B → FromBinaryString,
otherwise use TBigInteger.FromDecimalString; on any parsing exception replace
the current ThrowTypeError call with the SyntaxError variant (e.g.,
ThrowSyntaxError) and include the same formatted message/arguments, and only
create TGocciaBigIntValue on successful parse.

In `@source/units/Goccia.Engine.pas`:
- Line 704: TGocciaEngine currently allocates FBuiltinGlobalBigInt with
TGocciaGlobalBigInt.Create but never frees it; update TGocciaEngine.Destroy to
call FBuiltinGlobalBigInt.Free (or FreeAndNil) and ensure it runs
before/alongside other cleanup to avoid use-after-free—locate
FBuiltinGlobalBigInt allocation at the constructor and add the matching free in
the TGocciaEngine.Destroy method to properly release the TGocciaGlobalBigInt
instance.

In `@source/units/Goccia.Evaluator.Arithmetic.pas`:
- Around line 49-55: The arithmetic routines are missing a ToPrimitive(number)
step before BigInt/type checks; update ToNumericPair and the operator handlers
EvaluateSubtraction, EvaluateMultiplication, EvaluateDivision, EvaluateModulo
and EvaluateExponentiation to call ToPrimitive on both operands (with hint
number) first, then perform the BigInt mixed-type checks (CheckBigIntMixedTypes)
and only after that call ALeft.ToNumberLiteral / ARight.ToNumberLiteral so boxed
BigInt objects (e.g. Object(1n)) are unboxed via valueOf() and handled
consistently like EvaluateAddition already does.
- Around line 199-206: Replace the incorrect ThrowTypeError calls that handle
BigInt division-by-zero, modulo-by-zero, and negative-exponent cases with
ThrowRangeError and remove the SSuggestBigIntNoMixedArithmetic suggestion;
specifically locate the branches handling TGocciaBigIntValue (e.g., the division
branch using SErrorBigIntDivisionByZero, the modulo branch, and the
exponentiation branch that detect negative exponents) and change
ThrowTypeError(SError..., SSuggestBigIntNoMixedArithmetic) to
ThrowRangeError(SError...) so the error type matches the ECMAScript spec.

In `@source/units/Goccia.Evaluator.Comparison.pas`:
- Around line 634-642: The NaN guard currently skips both operands whenever any
operand is a TGocciaBigIntValue, allowing unordered comparisons
(CompareBigIntAndNumber returning code 2) to flow through and make >=/<= return
true; change the logic to individually check NaN only on non-BigInt operands
instead of skipping both: for ALeft and ARight separately, if the operand is not
TGocciaBigIntValue and its ToNumberLiteral.IsNaN then set Result := False and
Exit. Update the block around ALeft/ARight checks (the code that now uses if not
((ALeft is TGocciaBigIntValue) or (ARight is TGocciaBigIntValue)) ...) so it
performs two independent guards, one per operand, so CompareBigIntAndNumber /
LessThan / GreaterThan handle unordered cases correctly.
- Around line 540-567: CompareBigIntAndNumber currently converts the BigInt to
Double (via ABigInt.Value.ToDouble) which loses precision; instead implement the
ES2026 exact mathematical comparison: for finite ANumber, compute ANumber's
integer part (trunc toward zero) and whether ANumber has a non‑zero fractional
part, convert that integer part to a TGocciaBigIntValue (or otherwise construct
a BigInt representation) and use the BigInt comparison routine on ABigInt.Value
vs that integer-part BigInt; if the BigInts differ return that result, and if
they are equal then decide by the sign of the fractional part (if fractional
part > 0 then BigInt < Number, if fractional part < 0 then BigInt > Number, else
equal). Update CompareBigIntAndNumber to remove the ToDouble path and use this
integer-part BigInt comparison and fractional check while keeping the existing
NaN/Infinity handling.

In `@source/units/Goccia.JSON.pas`:
- Around line 841-844: The current throw for TGocciaBigIntValue bypasses any
BigInt toJSON hook because ApplyToJSON only probes toJSON for objects via
AValue.Box/MethodTarget; remove the is TGocciaObjectValue type-check and instead
call GetProperty directly on the TGocciaValue (i.e., use
AValue.GetProperty('toJSON')/Method lookup without boxing), since
TGocciaValue.GetProperty is virtual and TGocciaBigIntValue.GetProperty delegates
to its prototype; this ensures GetV(value,'toJSON') runs for BigInt before the
TypeError throw and fixes the bypass described (no changes to ClassHelper.pas
boxing behavior required).

In `@source/units/Goccia.Lexer.pas`:
- Around line 1429-1437: The lexer currently emits gttBigInt lexemes (via Peek,
Advance, HasDecimalOrExponent, HasSeparator and AddToken) preserving non-decimal
prefixes (0x, 0b, 0o) while the parser constructs BigInts using
TBigInteger.FromDecimalString(Token.Lexeme), causing mis-parsing; fix by
normalizing the lexeme to a decimal string before emitting gttBigInt (remove
prefix and convert the hex/bin/octal value to its decimal string after stripping
separators) OR update the parser to detect prefixed lexemes and call a
radix-aware constructor instead (replace
TBigInteger.FromDecimalString(Token.Lexeme) with a branch that parses based on
0x/0b/0o prefixes), ensuring the same decision (normalization or radix-aware
parse) is applied for both code paths mentioned (and the nearby block at lines
~1440-1444).

In `@source/units/Goccia.Values.BigIntValue.pas`:
- Around line 209-212: The code is using Trunc(RadixValue.ToNumberLiteral.Value)
and ThrowTypeError for BigInt.prototype.toString radix checks; replace the raw
truncation with the proper ToIntegerOrInfinity coercion on RadixValue and change
the thrown error to a RangeError. Locate the radix handling around
RadixValue/ToNumberLiteral and replace the Trunc(...) call with
RadixValue.ToIntegerOrInfinity (or the equivalent helper that implements
ToIntegerOrInfinity), then change ThrowTypeError(...) to ThrowRangeError(...)
(keeping a clear message like "toString() radix must be between 2 and 36") so
out-of-range radices produce a RangeError per spec.

In `@source/units/Goccia.VM.pas`:
- Around line 1802-1804: bckBigInt now produces TGocciaBigIntValue which exposes
BigInt operands to bytecode paths, but VM helpers (VMBitwiseAndValues,
VMBitwiseOrValues, VMBitwiseXorValues, VMShiftLeftValues, VMShiftRightValues,
VMUnsignedShiftRightValues, VMBitwiseNotValues and comparison helpers
VMLessThan/VMLessThanOrEqual/VMLargerThan/VMLargerThanOrEqual) still call
ToNumberLiteral and will TypeError for BigInt; update those helpers to first
check for TGocciaBigIntValue (or the concrete BigInt value type) and perform the
correct BigInt operation (use the BigInt value methods like
BitwiseAnd/BitwiseOr/BitwiseXor/ShiftLeft/ShiftRight/UnsignedShiftRight/BitwiseNot
and Compare) or delegate to the existing evaluator routines (EvaluateBitwiseAnd,
EvaluateGreaterThan, etc.) when BigInt operands are present, falling back to the
existing numeric path only when operands are not BigInt.

In `@tests/language/expressions/bigint/bigint-comparison.js`:
- Around line 7-9: Replace literal self-comparisons (1n === 1n, 0n === 0n, 1n
!== 1n, 1n <= 1n, 1n >= 1n) with comparisons between distinct variable bindings
to avoid the Biome noSelfCompare lint error: introduce const bindings like a =
1n, b = 1n (and similarly c = 0n for the zero checks) and update the
expectations to compare a === b, c === cB (or c === d if you create two zero
bindings), a !== b2 (use a different var set where needed), a <= b and a >= b as
appropriate so semantics are preserved while eliminating literal
self-comparisons.

---

Nitpick comments:
In `@source/units/Goccia.VM.pas`:
- Around line 467-468: VMSubtractValues, VMMultiplyValues, VMDivideValues,
VMModuloValues and VMPowerValues currently operate on raw operands and skip
ToPrimitive, causing incorrect handling of boxed BigInts; update each of these
functions to call ToPrimitive(ALeft) and ToPrimitive(ARight) (as VMAddValues
does) before performing the BigInt mixed-type check and before calling
VMToNumericPair, and then use the same XOR check (if (ALeft is
TGocciaBigIntValue) xor (ARight is TGocciaBigIntValue) then ThrowTypeError(...))
so boxed BigInt objects are coerced correctly prior to numeric conversion.
🪄 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: 3d28b19b-66e3-4f89-8e0d-11e5b807e38b

📥 Commits

Reviewing files that changed from the base of the PR and between 440cc40 and ce9807c.

📒 Files selected for processing (28)
  • source/shared/BigInteger.pas
  • source/units/Goccia.Builtins.GlobalBigInt.pas
  • source/units/Goccia.Bytecode.Chunk.pas
  • source/units/Goccia.Compiler.Expressions.pas
  • source/units/Goccia.Constants.ConstructorNames.pas
  • source/units/Goccia.Constants.TypeNames.pas
  • source/units/Goccia.Engine.pas
  • source/units/Goccia.Error.Messages.pas
  • source/units/Goccia.Error.Suggestions.pas
  • source/units/Goccia.Evaluator.Arithmetic.pas
  • source/units/Goccia.Evaluator.Bitwise.pas
  • source/units/Goccia.Evaluator.Comparison.pas
  • source/units/Goccia.Evaluator.pas
  • source/units/Goccia.JSON.pas
  • source/units/Goccia.Lexer.pas
  • source/units/Goccia.Parser.pas
  • source/units/Goccia.Token.pas
  • source/units/Goccia.VM.pas
  • source/units/Goccia.Values.BigIntValue.pas
  • source/units/Goccia.Values.Primitives.pas
  • tests/built-ins/BigInt/coercion.js
  • tests/built-ins/BigInt/constructor.js
  • tests/built-ins/BigInt/prototype-methods.js
  • tests/language/expressions/bigint/bigint-arithmetic.js
  • tests/language/expressions/bigint/bigint-bitwise.js
  • tests/language/expressions/bigint/bigint-comparison.js
  • tests/language/expressions/bigint/bigint-literals.js
  • tests/language/expressions/bigint/bigint-type-errors.js

Comment thread source/shared/BigInteger.pas
Comment thread source/units/Goccia.Builtins.GlobalBigInt.pas
Comment thread source/units/Goccia.Builtins.GlobalBigInt.pas Outdated
Comment thread source/units/Goccia.Builtins.GlobalBigInt.pas
Comment thread source/units/Goccia.Engine.pas
Comment thread source/units/Goccia.JSON.pas
Comment thread source/units/Goccia.Lexer.pas
Comment thread source/units/Goccia.Values.BigIntValue.pas Outdated
Comment thread source/units/Goccia.VM.pas
Comment thread tests/language/expressions/bigint/bigint-comparison.js Outdated
Fix bytecode VM operations that were missing BigInt dispatch (bitwise,
comparison, negation, equality), causing TypeError for all BigInt
operations in bytecode mode. Fix spec compliance issues from review:
use RangeError for division-by-zero/negative-exponent/non-integral
conversion, SyntaxError for invalid string conversion, support
non-decimal string formats in BigInt() constructor, fix cross-type
BigInt/NaN comparison returning true for >= and <=, and free
FBuiltinGlobalBigInt in engine destructor. Update Goccia.spec array,
language tables, built-ins docs, and decision log.

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

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

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

Inline comments:
In `@source/units/Goccia.Evaluator.Arithmetic.pas`:
- Around line 311-315: The code correctly throws ThrowRangeError when
TGocciaBigIntValue(ARight).Value.IsNegative, but the
SErrorBigIntNegativeExponent message text says "Exponent must be positive" which
is misleading because zero is allowed; update the SErrorBigIntNegativeExponent
message to a non‑negative wording such as "Exponent must be non-negative" (or
"Exponent must be >= 0") in the error messages unit so the thrown error
accurately reflects the check in TGocciaBigIntValue exponentiation.

In `@source/units/Goccia.Values.ClassHelper.pas`:
- Around line 36-40: Add unit tests for BigInt strict equality covering positive
cases, negative cases and edge values: create or update a test in
units/*.Test.pas (e.g., a test unit exercising the BigInt value wrapper used in
Goccia.Values.BigIntValue) that constructs TBigInteger-backed values and asserts
strict equality when values are identical (including very large integers) and
asserts inequality when they differ; specifically exercise the equality path
that relies on TBigInteger.Equal() (the code around the BigInt equality
implementation referenced in Goccia.Values.ClassHelper.pas) and include tests
that compare equal magnitude but different sign and very large magnitude values
to ensure correct behavior; finally run the formatter check ./format.pas --check
locally before committing.
🪄 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: 46c9fe8d-9d74-4c04-8a7e-b2c720f5222c

📥 Commits

Reviewing files that changed from the base of the PR and between ce9807c and 000e963.

📒 Files selected for processing (13)
  • docs/built-ins-binary-data.md
  • docs/built-ins.md
  • docs/decision-log.md
  • docs/language-tables.md
  • source/units/Goccia.Builtins.GlobalBigInt.pas
  • source/units/Goccia.Engine.pas
  • source/units/Goccia.Evaluator.Arithmetic.pas
  • source/units/Goccia.Evaluator.Comparison.pas
  • source/units/Goccia.Spec.pas
  • source/units/Goccia.VM.pas
  • source/units/Goccia.Values.BigIntValue.pas
  • source/units/Goccia.Values.ClassHelper.pas
  • tests/language/expressions/bigint/bigint-comparison.js
✅ Files skipped from review due to trivial changes (7)
  • docs/language-tables.md
  • docs/decision-log.md
  • docs/built-ins.md
  • tests/language/expressions/bigint/bigint-comparison.js
  • docs/built-ins-binary-data.md
  • source/units/Goccia.Spec.pas
  • source/units/Goccia.Values.BigIntValue.pas
🚧 Files skipped from review as they are similar to previous changes (1)
  • source/units/Goccia.Evaluator.Comparison.pas

Comment thread source/units/Goccia.Evaluator.Arithmetic.pas
Comment thread source/units/Goccia.Values.ClassHelper.pas
frostney and others added 2 commits April 18, 2026 21:47
Implement BigInt.asIntN and BigInt.asUintN with correct ToIndex
coercion for the bits parameter. Replace ToDouble-based cross-type
BigInt/Number comparison with exact mathematical-value comparison
using TBigInteger.FromDouble, eliminating precision loss beyond 2^53.
Fix BigInt/NaN comparisons for <= and >= returning true instead of
false (stale .ppu cache masked the fix in prior commit).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Change "Exponent must be positive" to "Exponent must be non-negative"
since 0n is a valid exponent (2n ** 0n === 1n).

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

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (3)
tests/built-ins/BigInt/constructor.js (2)

6-10: Add a no-argument constructor test.

Consider adding BigInt() (no args) coverage to lock in the undefined conversion failure path.

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

In `@tests/built-ins/BigInt/constructor.js` around lines 6 - 10, Add a new test
case that asserts calling the BigInt constructor with no arguments throws the
undefined conversion error: create a test like test("BigInt no-args", () => {
expect(() => BigInt()).toThrow(TypeError); }) so the undefined-to-BigInt failure
path is covered alongside the existing BigInt(number) assertions (referencing
BigInt and the existing test names in constructor.js).

26-40: Assert specific error classes for negative paths.

These tests currently verify “throws” but not the error type. Tightening to RangeError/SyntaxError assertions will better protect the spec-compliance behavior this PR adds.

Also applies to: 74-78

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

In `@tests/built-ins/BigInt/constructor.js` around lines 26 - 40, Tests currently
use generic expect(...).toThrow(); tighten assertions to specific error classes:
for BigInt(1.5), BigInt(NaN), and BigInt(Infinity) assert they throw RangeError;
for BigInt("abc") assert it throws SyntaxError. Update the test cases that call
BigInt in this file (e.g., the test blocks with BigInt(1.5), BigInt(NaN),
BigInt(Infinity), BigInt("abc")) and the analogous tests around lines 74-78 to
use .toThrow(RangeError) or .toThrow(SyntaxError) as appropriate.
source/units/Goccia.Builtins.GlobalBigInt.pas (1)

193-201: Prefer centralized error message constants for index failures.

'Invalid index' is duplicated in BigIntToIndex. Consider routing this through a shared error-message constant (and optional suggestion) for consistency with the rest of runtime diagnostics.

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

In `@source/units/Goccia.Builtins.GlobalBigInt.pas` around lines 193 - 201,
Replace the duplicated literal 'Invalid index' in BigIntToIndex with a
centralized error-message constant (e.g. ERR_INVALID_INDEX) defined in this unit
(or a shared runtime/errors unit) and update both ThrowRangeError calls to use
that constant (optionally append the existing suggestion text where other
runtime diagnostics do). Ensure the new constant name is unique and referenced
from the same function (BigIntToIndex) so future index failures use the single
shared message.
🤖 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.Builtins.GlobalBigInt.pas`:
- Around line 193-201: Replace the duplicated literal 'Invalid index' in
BigIntToIndex with a centralized error-message constant (e.g. ERR_INVALID_INDEX)
defined in this unit (or a shared runtime/errors unit) and update both
ThrowRangeError calls to use that constant (optionally append the existing
suggestion text where other runtime diagnostics do). Ensure the new constant
name is unique and referenced from the same function (BigIntToIndex) so future
index failures use the single shared message.

In `@tests/built-ins/BigInt/constructor.js`:
- Around line 6-10: Add a new test case that asserts calling the BigInt
constructor with no arguments throws the undefined conversion error: create a
test like test("BigInt no-args", () => { expect(() =>
BigInt()).toThrow(TypeError); }) so the undefined-to-BigInt failure path is
covered alongside the existing BigInt(number) assertions (referencing BigInt and
the existing test names in constructor.js).
- Around line 26-40: Tests currently use generic expect(...).toThrow(); tighten
assertions to specific error classes: for BigInt(1.5), BigInt(NaN), and
BigInt(Infinity) assert they throw RangeError; for BigInt("abc") assert it
throws SyntaxError. Update the test cases that call BigInt in this file (e.g.,
the test blocks with BigInt(1.5), BigInt(NaN), BigInt(Infinity), BigInt("abc"))
and the analogous tests around lines 74-78 to use .toThrow(RangeError) or
.toThrow(SyntaxError) as appropriate.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 25a9ae2a-3e2c-4811-9279-93391fcacbf2

📥 Commits

Reviewing files that changed from the base of the PR and between 000e963 and 477b560.

📒 Files selected for processing (8)
  • docs/built-ins.md
  • docs/decision-log.md
  • docs/language-tables.md
  • source/units/Goccia.Builtins.GlobalBigInt.pas
  • source/units/Goccia.Evaluator.Comparison.pas
  • source/units/Goccia.VM.pas
  • tests/built-ins/BigInt/constructor.js
  • tests/language/expressions/bigint/bigint-comparison.js
✅ Files skipped from review due to trivial changes (3)
  • docs/language-tables.md
  • docs/built-ins.md
  • docs/decision-log.md
🚧 Files skipped from review as they are similar to previous changes (3)
  • tests/language/expressions/bigint/bigint-comparison.js
  • source/units/Goccia.VM.pas
  • source/units/Goccia.Evaluator.Comparison.pas

Create TGocciaBigIntObjectValue for boxing BigInt primitives via
Object(). Fix Object() to call ToObject/Box for primitive arguments
per ES2026 §20.1.1.1 instead of Instantiate. Add ToPrimitive calls
in subtraction, multiplication, division, modulo, and exponentiation
so boxed BigInts (Object(1n) - 1n) coerce correctly via valueOf().

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

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

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

Inline comments:
In `@source/units/Goccia.Values.BigIntObjectValue.pas`:
- Around line 108-116: The BigInt prototype methods must validate their receiver
types and handle the optional radix: update
TGocciaBigIntObjectValue.BigIntObjectValueOf to throw a TypeError when
AThisValue is neither TGocciaBigIntObjectValue nor TGocciaBigIntValue (instead
of returning arbitrary values), and implement TGocciaBigIntObjectValue.ToString
(or the existing BigInt toString method) to read radix from AArgs[0],
coerce/convert it the same way as Number.prototype.toString (see
Goccia.Values.NumberObjectValue.pas), defaulting to 10, validate radix is an
integer in [2,36] and raise RangeError if out of range, then produce the
radix-based string representation of the BigInt (e.g. 16 => "ff", 2 => "1010");
use the same error throwing pattern and helper utilities used elsewhere for
TypeError/RangeError to keep behavior consistent with ES2026.
🪄 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: 75aa32d6-a891-4743-9358-e301ff25a8b6

📥 Commits

Reviewing files that changed from the base of the PR and between d59f8ea and 3344ded.

📒 Files selected for processing (5)
  • source/units/Goccia.Builtins.GlobalObject.pas
  • source/units/Goccia.Evaluator.Arithmetic.pas
  • source/units/Goccia.Values.BigIntObjectValue.pas
  • source/units/Goccia.Values.ClassHelper.pas
  • source/units/Goccia.Values.ClassValue.pas
✅ Files skipped from review due to trivial changes (1)
  • source/units/Goccia.Builtins.GlobalObject.pas
🚧 Files skipped from review as they are similar to previous changes (1)
  • source/units/Goccia.Evaluator.Arithmetic.pas

Comment thread source/units/Goccia.Values.BigIntObjectValue.pas
frostney and others added 2 commits April 18, 2026 22:24
Move all hardcoded BigInt error strings to Goccia.Error.Messages and
add corresponding suggestions to Goccia.Error.Suggestions. Add
ToPrimitive calls to VM arithmetic functions so boxed BigInt works
in bytecode mode. Add JS tests for String(), Number(), and Object()
primitive conversions including boxed BigInt arithmetic.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
BigIntObjectValue.valueOf now throws TypeError for non-BigInt receivers
instead of returning the arbitrary this value. BigIntObjectValue.toString
validates the receiver, parses the radix argument with range validation
(2-36, RangeError), and produces radix-based string output.

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

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

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

Inline comments:
In `@source/units/Goccia.Values.BigIntValue.pas`:
- Around line 199-201: The BigInt.prototype methods in
Goccia.Values.BigIntValue.pas currently only accept TGocciaBigIntValue
primitives; update the receiver checks in the implementations of
BigInt.prototype.toString, valueOf and toLocaleString so they accept boxed
BigInt objects too by detecting TGocciaBigIntObjectValue and extracting its
.Primitive into a TGocciaBigIntValue (else use the primitive directly),
otherwise call ThrowTypeError as before; reference the pattern already used in
TGocciaBigIntObjectValue.BigIntObjectValueOf and BigIntObjectToString to guide
the exact conditional and extraction logic.
🪄 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: a6ffa2e1-6594-4fda-a4ec-60acc1ac6f9d

📥 Commits

Reviewing files that changed from the base of the PR and between d59f8ea and 47c6110.

📒 Files selected for processing (11)
  • source/units/Goccia.Builtins.GlobalBigInt.pas
  • source/units/Goccia.Builtins.GlobalObject.pas
  • source/units/Goccia.Error.Messages.pas
  • source/units/Goccia.Error.Suggestions.pas
  • source/units/Goccia.Evaluator.Arithmetic.pas
  • source/units/Goccia.VM.pas
  • source/units/Goccia.Values.BigIntObjectValue.pas
  • source/units/Goccia.Values.BigIntValue.pas
  • source/units/Goccia.Values.ClassHelper.pas
  • source/units/Goccia.Values.ClassValue.pas
  • tests/built-ins/BigInt/coercion.js
✅ Files skipped from review due to trivial changes (3)
  • source/units/Goccia.Builtins.GlobalObject.pas
  • tests/built-ins/BigInt/coercion.js
  • source/units/Goccia.Error.Suggestions.pas
🚧 Files skipped from review as they are similar to previous changes (6)
  • source/units/Goccia.Values.ClassHelper.pas
  • source/units/Goccia.Values.ClassValue.pas
  • source/units/Goccia.Evaluator.Arithmetic.pas
  • source/units/Goccia.Error.Messages.pas
  • source/units/Goccia.VM.pas
  • source/units/Goccia.Builtins.GlobalBigInt.pas

Comment thread source/units/Goccia.Values.BigIntValue.pas
@frostney frostney merged commit cd3987f into main Apr 18, 2026
10 checks passed
@frostney frostney deleted the t3code/implement-bigint-spec branch April 18, 2026 21:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

new feature New feature or request spec compliance Mismatch against official JavaScript/TypeScript specification

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant