Skip to content

Add numeric separator support in number literals#258

Merged
frostney merged 6 commits into
mainfrom
t3code/numeric-separators
Apr 10, 2026
Merged

Add numeric separator support in number literals#258
frostney merged 6 commits into
mainfrom
t3code/numeric-separators

Conversation

@frostney
Copy link
Copy Markdown
Owner

Summary

  • Added lexer support for numeric separators in decimal, hex, binary, octal, and scientific-notation literals.
  • Normalized separator-bearing lexemes before emitting number tokens, so runtime numeric values preserve existing behavior.
  • Expanded diagnostics and suggestions for invalid numeric literal forms to mention separator placement rules.
  • Added JavaScript coverage for valid separator cases and syntax-error cases.
  • Updated language restrictions docs to list numeric separators as supported syntax.

Testing

  • Not run.
  • Expected verification: ./build.pas testrunner && ./build/TestRunner tests
  • Expected verification for lexer changes: run the numeric separator test file under tests/language/expressions/numeric-separators.js.

- Accept underscores in decimal, hex, binary, octal, and exponent parts
- Strip separators in the lexer and surface validation suggestions
- Add language coverage for valid and invalid numeric separator forms
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 10, 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: 6f54ddf9-b3a8-4951-8dfc-1db1d9a972f1

📥 Commits

Reviewing files that changed from the base of the PR and between ee4297f and d6092cc.

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

📝 Walkthrough

Walkthrough

Adds ES numeric separators (_) support and validation across decimal, fractional, exponent, hex/bin/oct literals; lexer strips separators and errors on invalid placements; adds tests and CI checks for malformed separators; updates error suggestion resources, numeric-literal docs, and clarifies CHANGELOG.md is overwritten by git-cliff.

Changes

Cohort / File(s) Summary
Documentation
AGENTS.md, docs/language-restrictions.md
Clarified that CHANGELOG.md is overwritten by git-cliff (do not edit manually); documented supported numeric literal forms and explicit numeric-separator support (decimal, fractional, scientific, hex 0x, binary 0b, octal 0o, numeric separators).
Lexer & Resources
units/Goccia.Lexer.pas, units/Goccia.Error.Suggestions.pas
TGocciaLexer.ScanNumber extended to accept/validate _ separators for all supported bases and forms, reject invalid placements (leading/trailing/consecutive/after leading 0/around decimal point), strip separators from emitted gttNumber; added SSuggestNumericSeparator and updated SSuggestNumberFormatValid.
Tests
tests/language/expressions/numeric-separators.js
Added Jest suite (numeric-separators) asserting correct parsing/evaluation of numeric literals with underscores across integer, fractional, exponent, and radix forms; notes invalid placements are rejected at lex/parse time.
CI Workflows
.github/workflows/ci.yml, .github/workflows/pr.yml
Added Check numeric separator rejection step to run ./build/ScriptLoader against malformed separator cases and assert failures with specific diagnostics for various invalid underscore placements.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested labels

new feature

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Description check ❓ Inconclusive The description covers the key changes and provides context, but the testing section is incomplete with 'Not run' and lacks proper checkbox completion. Complete the testing section by checking relevant boxes and confirming which tests were actually run or should be verified before merge.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely summarizes the main change: adding support for numeric separators in number literals across all relevant literal types.
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.

@frostney frostney added the spec compliance Mismatch against official JavaScript/TypeScript specification label Apr 10, 2026
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 `@tests/language/expressions/numeric-separators.js`:
- Around line 91-110: The tests in numeric-separators.js that call eval (e.g.,
the failing cases using eval("1e_10"), eval("1_000_"),
eval("0x_FF"/"0b_10"/"0o_77", eval("1__000"), eval("1_.5")) do not prove parser
syntax errors because eval is excluded at runtime; move these negative cases out
of runtime Jest tests and into parser-facing fixtures or the TestRunner path
that feeds source text to the parser (so the code is parsed rather than
executed). Replace the eval-based expect(() => eval(...)).toThrow() checks with
parser-level test files or harness invocations that assert a parse error for the
same literal inputs, and remove or adjust the runtime tests to avoid relying on
undefined eval.

In `@units/Goccia.Lexer.pas`:
- Around line 668-718: The fractional-part check currently only enters when
PeekNext is a digit, allowing inputs like "1._5" to be tokenized incorrectly;
update the logic around Peek/PeekNext in the fraction handling (the block that
uses Advance, Peek, PeekNext, HasSeparator) so that when a '.' is seen you also
detect and reject a numeric separator immediately following the dot (i.e., if
PeekNext = '_' then raise TGocciaLexerError with the same message/metadata and
SSuggestNumericSeparator), and if PeekNext is a digit proceed as before; ensure
the same numeric-separator validation used elsewhere (the existing
HasSeparator/Advance/check that follows underscores) applies to the fractional
loop so cases like "1._5" produce the error.
🪄 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: e2bfbe1e-842c-4edb-9e25-7f18f9ff49a7

📥 Commits

Reviewing files that changed from the base of the PR and between 010f8ec and 009764e.

📒 Files selected for processing (5)
  • AGENTS.md
  • docs/language-restrictions.md
  • tests/language/expressions/numeric-separators.js
  • units/Goccia.Error.Suggestions.pas
  • units/Goccia.Lexer.pas

Comment thread tests/language/expressions/numeric-separators.js Outdated
Comment thread units/Goccia.Lexer.pas
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 10, 2026

Suite Timing

Suite Metric Interpreted Bytecode
Tests Total 4288 4288
Tests Passed 4247 ✅ 4288 ✅
Tests Skipped 41 0
Tests Test Duration 303.0ms 296.4ms
Tests Lex 81.1ms 58.0ms
Tests Parse 104.5ms 106.8ms
Tests Compile 68.8ms
Tests Execute 317.9ms 327.7ms
Tests Engine Total 503.5ms 561.3ms
Benchmarks Total 306 306
Benchmarks Duration 8.47min 7.27min

Measured on ubuntu-latest x64.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 10, 2026

Benchmark Results

306 benchmarks

Interpreted: 🟢 176 improved · 🔴 85 regressed · 45 unchanged · avg +3.3%
Bytecode: 🟢 153 improved · 🔴 30 regressed · 123 unchanged · avg +2.3%

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

eval is excluded in GocciaScript, so the tests passed because eval is
undefined (ReferenceError), not because the invalid literals were
rejected. Invalid separator placement is a lex-time error that cannot
be exercised from within JS — document the manual verification commands
instead.

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 `@tests/language/expressions/numeric-separators.js`:
- Around line 77-79: The test case using the numeric literal 0_1 inside
test("separator with zero prefix decimal") is invalid under ES2021 and must be
removed from positive runtime tests; delete the expect(0_1).toBe(1) assertion
and instead add or move a lex-time rejection test that verifies the parser
rejects the token 0_1 (e.g., in the lex/parse-time failure suite), so leave
test("separator with zero prefix decimal") either removed or rewritten to assert
a syntax/lex error for the literal 0_1.
🪄 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: fed341a1-eff9-4b2c-b701-d75a36c51f16

📥 Commits

Reviewing files that changed from the base of the PR and between 009764e and f4681da.

📒 Files selected for processing (1)
  • tests/language/expressions/numeric-separators.js

Comment thread tests/language/expressions/numeric-separators.js Outdated
frostney and others added 3 commits April 10, 2026 19:08
1._5 is a syntax error because the dot is parsed as part of the
numeric literal, not as property access. Add an explicit check for
underscore after the decimal point so the lexer rejects it instead
of silently splitting the token.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
ES2021 §12.9.3 defines 0 as a standalone DecimalIntegerLiteral
production — numeric separators are not permitted after it. Reject
0_1 at lex time instead of treating it as decimal 1.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Invalid separator placement is a lex-time error that cannot be tested
from within JS. Add a dedicated "Check numeric separator rejection"
step to both ci.yml and pr.yml that pipes each invalid pattern through
ScriptLoader and asserts exit code 1 with the expected error message.

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

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
units/Goccia.Lexer.pas (1)

593-594: Use the full repo-required spec annotation format.

// ES2021 §12.9.3 NumericLiteral is only a section label; it does not include the exact spec method name and parameter list the repo standard requires, so it is harder to audit against future spec-aligned work.

As per coding guidelines, "Apply ECMAScript spec annotations in the format // ESYYYY §X.Y.Z SpecMethodName(specParams) immediately above each function body implementing spec-defined behavior, with the method name and parameter list matching the spec exactly."

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

In `@units/Goccia.Lexer.pas` around lines 593 - 594, Replace the terse section
label above the TGocciaLexer.ScanNumber procedure with the repo-required full
ECMAScript spec annotation format: include the year, section, the exact spec
method name and parameter list that corresponds to numeric literal scanning
(e.g., use the spec method that defines NumericLiteral parsing), so update the
comment immediately above procedure TGocciaLexer.ScanNumber to follow "// ESYYYY
§X.Y.Z SpecMethodName(specParams)" exactly.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@units/Goccia.Lexer.pas`:
- Around line 593-594: Replace the terse section label above the
TGocciaLexer.ScanNumber procedure with the repo-required full ECMAScript spec
annotation format: include the year, section, the exact spec method name and
parameter list that corresponds to numeric literal scanning (e.g., use the spec
method that defines NumericLiteral parsing), so update the comment immediately
above procedure TGocciaLexer.ScanNumber to follow "// ESYYYY §X.Y.Z
SpecMethodName(specParams)" exactly.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 021bdf93-1b7e-49de-83ff-af829bbb6cc3

📥 Commits

Reviewing files that changed from the base of the PR and between f4681da and 4fcb398.

📒 Files selected for processing (2)
  • tests/language/expressions/numeric-separators.js
  • units/Goccia.Lexer.pas

@coderabbitai coderabbitai Bot added the internal Refactoring, CI, tooling, cleanup label Apr 10, 2026
- Refresh lexer annotation for `NumericLiteral`
- Keeps spec cross-reference aligned with current ECMAScript edition
@coderabbitai coderabbitai Bot added the new feature New feature or request label Apr 10, 2026
@frostney frostney merged commit 9c29942 into main Apr 10, 2026
9 checks passed
@frostney frostney deleted the t3code/numeric-separators branch April 10, 2026 22:04
This was referenced Apr 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant