Skip to content

Preserve UTF-8 in the TOML compliance harness on Windows#187

Closed
frostney wants to merge 1 commit into
mainfrom
fix/windows-toml-compliance-followup
Closed

Preserve UTF-8 in the TOML compliance harness on Windows#187
frostney wants to merge 1 commit into
mainfrom
fix/windows-toml-compliance-followup

Conversation

@frostney
Copy link
Copy Markdown
Owner

@frostney frostney commented Apr 5, 2026

Summary

  • preserve raw TOML suite bytes as UTF-8 in scripts/GocciaTOMLCheck.dpr instead of letting Windows convert them through the local ANSI code page
  • add a TOML parser regression that feeds raw UTF-8 bytes for a Unicode key/value pair
  • document why the TOML compliance harness needs explicit UTF-8 preservation on Windows

Why

The post-merge CI run for main still failed in toml-compliance on x86_64-win64 and i386-win32 after the multiline-LF fix. The remaining 16 failures were all Unicode-related suite cases (quoted-unicode, unicode-escape, multibyte, etc.), plus one invalid encoding case that became a false accept after the bytes were mangled.

The root cause was the standalone compliance harness reading TOML files as UTF-8 bytes and then converting them into a plain string in a way that lost the UTF-8 code page on Windows. That produced mojibake like José and key mismatches in the compliance JSON.

Verification

  • /tmp/goccia-toml-test-bin/Goccia.TOML.Test
  • python3 scripts/run_toml_test_suite.py --harness=/tmp/goccia-toml-harness-bin/GocciaTOMLCheck
  • ./build/TestRunner tests/built-ins/TOML/parse.js
  • ./format.pas --check

Notes

A full local ./build.pas tests currently hits an unrelated linker failure in Goccia.Builtins.TestAssertions.Test.pas on this machine, so verification here was kept to the directly affected TOML targets.

Summary by CodeRabbit

  • Bug Fixes

    • Corrected UTF-8 handling in TOML file parsing to preserve Unicode characters in keys and values, preventing corruption from ANSI code page conversion on Windows.
  • Documentation

    • Added clarification on UTF-8 byte handling for TOML compliance testing.
  • Tests

    • Added test coverage for Unicode preservation in TOML parsing.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 5, 2026

📝 Walkthrough

Walkthrough

The changes fix UTF-8 character handling in TOML parsing by modifying the file loader to explicitly preserve raw UTF-8 bytes through code page assignment, updating the function signature accordingly, adding documentation of Windows-specific behavior, and introducing a test case to verify Unicode key-value preservation.

Changes

Cohort / File(s) Summary
Documentation
docs/testing.md
Added Windows-specific note explaining that TOML suite files preserve UTF-8 code page when passed to the Pascal TOML parser, preventing Unicode corruption from implicit ANSI conversion.
Core UTF-8 Handling
scripts/GocciaTOMLCheck.dpr
Updated LoadUTF8File to return string instead of UTF8String, explicitly applying SetCodePage(..., 65001, False) to interpret file bytes as UTF-8, and adjusted caller to use string directly.
Test Coverage
units/Goccia.TOML.Test.pas
Added test method TestParseDocumentPreservesUTF8BytesForUnicodeKeysAndValues that constructs a TOML document with raw UTF-8 byte sequences for keys and values, verifies parsing preserves them correctly, and validates the parsed Unicode content.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Poem

🐰 A rabbit hops through UTF-8 files with care,
Code pages set to encode without despair,
Where Unicode keys dance and values shine true,
No more ANSI ghosts to mangle your TOML brew! 🔤✨

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Preserve UTF-8 in the TOML compliance harness on Windows' clearly and specifically describes the main change—fixing UTF-8 preservation in the TOML compliance harness to resolve Windows-specific issues.
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.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/windows-toml-compliance-followup

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
units/Goccia.TOML.Test.pas (1)

156-194: Consider adding a paired invalid-UTF-8 rejection regression.

This test covers valid UTF-8 preservation well. Given the same incident included an invalid-encoding false-accept, adding one negative case here would make the protection more complete.

➕ Suggested companion test sketch
+procedure TTOMLParserTests.TestParseDocumentRejectsInvalidUTF8Input;
+const
+  UTF8_CODE_PAGE = 65001;
+var
+  Parser: TGocciaTOMLParser;
+  RawSourceText: RawByteString;
+  SourceText: string;
+begin
+  // Invalid UTF-8 sequence: continuation byte without a valid leading byte
+  RawSourceText := 'key = "' + #$80 + '"' + LineEnding;
+  SetCodePage(RawSourceText, UTF8_CODE_PAGE, False);
+  SourceText := RawSourceText;
+
+  Parser := TGocciaTOMLParser.Create;
+  try
+    ExpectException(procedure begin
+      Parser.ParseDocument(SourceText);
+    end);
+  finally
+    Parser.Free;
+  end;
+end;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@units/Goccia.TOML.Test.pas` around lines 156 - 194, Add a companion negative
regression test to
TTOMLParserTests.TestParseDocumentPreservesUTF8BytesForUnicodeKeysAndValues that
constructs a RawSourceText containing intentionally invalid UTF-8 byte sequences
(e.g. truncated/malformed multi-byte sequences), sets the code page like the
positive test, then calls TGocciaTOMLParser.ParseDocument and asserts the parser
rejects the input (for example by raising the expected exception or returning a
failed parse) instead of accepting a garbled key/value; place the check next to
the existing positive test and reference the same helpers (RawSourceText,
SetCodePage, ParseDocument, GetChildOrFail) to locate where to add the new
negative test.
🤖 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.TOML.Test.pas`:
- Around line 156-194: Add a companion negative regression test to
TTOMLParserTests.TestParseDocumentPreservesUTF8BytesForUnicodeKeysAndValues that
constructs a RawSourceText containing intentionally invalid UTF-8 byte sequences
(e.g. truncated/malformed multi-byte sequences), sets the code page like the
positive test, then calls TGocciaTOMLParser.ParseDocument and asserts the parser
rejects the input (for example by raising the expected exception or returning a
failed parse) instead of accepting a garbled key/value; place the check next to
the existing positive test and reference the same helpers (RawSourceText,
SetCodePage, ParseDocument, GetChildOrFail) to locate where to add the new
negative test.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: f80d76e2-8606-44fc-aa2c-24d37a76450d

📥 Commits

Reviewing files that changed from the base of the PR and between 038c245 and 242d408.

📒 Files selected for processing (3)
  • docs/testing.md
  • scripts/GocciaTOMLCheck.dpr
  • units/Goccia.TOML.Test.pas

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 5, 2026

Benchmark Results

274 benchmarks

Interpreted: 🟢 5 improved · 🔴 188 regressed · 81 unchanged · avg -2.3%
Bytecode: 🟢 49 improved · 🔴 98 regressed · 127 unchanged · avg -0.6%

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

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

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 5, 2026

Suite Timing

Suite Metric Interpreted Bytecode
Tests Total 3661 3661
Tests Passed 3620 ✅ 3661 ✅
Tests Skipped 41 0
Tests Execution 208.0ms 186.3ms
Tests Engine 378.8ms 662.7ms
Benchmarks Total 274 274
Benchmarks Duration 7.57min 6.27min

Measured on ubuntu-latest x64.

@frostney
Copy link
Copy Markdown
Owner Author

frostney commented Apr 5, 2026

Superseded by #188. Closing the earlier Windows TOML follow-up so there is a single active fix PR.

@frostney frostney closed this Apr 5, 2026
@frostney frostney deleted the fix/windows-toml-compliance-followup branch April 9, 2026 08:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant