Skip to content

Deduplicate JSON string escaping helpers#305

Merged
frostney merged 3 commits into
mainfrom
t3code/fix-issue-303
Apr 15, 2026
Merged

Deduplicate JSON string escaping helpers#305
frostney merged 3 commits into
mainfrom
t3code/fix-issue-303

Conversation

@frostney
Copy link
Copy Markdown
Owner

@frostney frostney commented Apr 14, 2026

Summary

  • Added Goccia.JSON.Utils to centralize JSON string escaping and quoting helpers.
  • Replaced duplicated EscapeJSONString/QuoteJSONString implementations in the test runner, JSON5/TOML checks, script loader JSON, profiler report, source map, and core JSON code.
  • Kept escaping behavior consistent across call sites while reducing maintenance overhead.

Fixes #303

Testing

  • Not run (not requested).
  • Concrete check: reviewed the updated call sites to confirm they now import Goccia.JSON.Utils and no longer define local escaping helpers.
  • Concrete check: verified the new unit preserves escaping for quotes, backslashes, solidus, control characters, and \uXXXX fallback for other C0 controls.

- Add shared JSON escape/quote utilities
- Replace local escape implementations in runners, profiler, source maps, and JSON code
- Keep JSON5/TOML check output consistent
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 14, 2026

📝 Walkthrough

Walkthrough

Centralizes JSON string escaping by adding units/Goccia.JSON.Utils and removing local EscapeJSONString/QuoteJSONString implementations across multiple programs and units; callers now use the new utility functions.

Changes

Cohort / File(s) Summary
New JSON Utilities Unit
units/Goccia.JSON.Utils.pas
Adds public EscapeJSONString and QuoteJSONString functions implementing JSON escaping (quotes, backslash, solidus, C0 short escapes, \u00XX for other C0 chars).
Core JSON / SourceMap
units/Goccia.JSON.pas, units/Goccia.SourceMap.pas
Removed class-local EscapeJSONString methods/declarations and added Goccia.JSON.Utils to uses; existing serialization now relies on centralized escape functions.
Script & Check Programs
TestRunner.dpr, scripts/GocciaJSON5Check.dpr, scripts/GocciaTOMLCheck.dpr
Removed local EscapeJSONString/QuoteJSONString helpers and added Goccia.JSON.Utils to uses; call sites unchanged but implementation moved out-of-file.
Profiler & ScriptLoader
units/Goccia.Profiler.Report.pas, units/Goccia.ScriptLoader.JSON.pas
Deleted in-unit JSON escaping/quoting helpers and added Goccia.JSON.Utils to implementation uses; JSON builders now use the shared utilities.
Tests
units/Goccia.JSON.Utils.Test.pas
New test program and TJSONUtilsTests suite covering escaping behavior (double-quote, backslash, solidus, C0 short escapes, \uXXXX for other C0, multibyte preservation, quoting wrapper).

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related issues

Possibly related PRs

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Description check ❓ Inconclusive The pull request description partially follows the template but lacks complete information in required sections. Add explicit confirmation of testing with JavaScript/TypeScript end-to-end tests, documentation updates, and Pascal test execution status in the Testing section checkboxes.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The pull request title accurately and concisely summarizes the main objective—deduplicating JSON string escaping helpers across multiple files into a centralized utility module.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

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


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

@coderabbitai coderabbitai Bot added the internal Refactoring, CI, tooling, cleanup label Apr 14, 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.

🧹 Nitpick comments (1)
units/Goccia.JSON.Utils.pas (1)

26-60: Add direct coverage for the shared escaper.

This is now a single point of failure for several JSON emitters. A small focused matrix around ", \, /, #0, #31, and multibyte UTF-8 would make regressions much easier to catch.

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

In `@units/Goccia.JSON.Utils.pas` around lines 26 - 60, Add direct unit tests that
exercise EscapeJSONString and QuoteJSONString: create focused tests that pass
strings containing the characters '"' , '\' , '/' , `#0` (Chr(0)), `#31` (Chr(31))
and a multibyte UTF-8 sequence (e.g., non-ASCII runes) to verify proper escaping
and quoting. For each case assert EscapeJSONString returns the expected escaped
body and QuoteJSONString wraps that result in double quotes; include at least
one test combining multiple special chars to validate buffering logic and one
test ensuring non-control multibyte characters are preserved (not escaped as \u
unless below codepoint 32). Use the function names EscapeJSONString and
QuoteJSONString to locate coverage gaps and add tests to the same test unit as
other JSON utils.
🤖 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.JSON.Utils.pas`:
- Around line 26-60: Add direct unit tests that exercise EscapeJSONString and
QuoteJSONString: create focused tests that pass strings containing the
characters '"' , '\' , '/' , `#0` (Chr(0)), `#31` (Chr(31)) and a multibyte UTF-8
sequence (e.g., non-ASCII runes) to verify proper escaping and quoting. For each
case assert EscapeJSONString returns the expected escaped body and
QuoteJSONString wraps that result in double quotes; include at least one test
combining multiple special chars to validate buffering logic and one test
ensuring non-control multibyte characters are preserved (not escaped as \u
unless below codepoint 32). Use the function names EscapeJSONString and
QuoteJSONString to locate coverage gaps and add tests to the same test unit as
other JSON utils.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 1d26699a-9af0-4f3e-9405-d0c12c5e04ce

📥 Commits

Reviewing files that changed from the base of the PR and between 957cf8a and b647abb.

📒 Files selected for processing (8)
  • TestRunner.dpr
  • scripts/GocciaJSON5Check.dpr
  • scripts/GocciaTOMLCheck.dpr
  • units/Goccia.JSON.Utils.pas
  • units/Goccia.JSON.pas
  • units/Goccia.Profiler.Report.pas
  • units/Goccia.ScriptLoader.JSON.pas
  • units/Goccia.SourceMap.pas

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 14, 2026

Suite Timing

Suite Metric Interpreted Bytecode
Tests Total 5358 5358
Tests Passed 5317 ✅ 5358 ✅
Tests Skipped 41 0
Tests Test Duration 405.4ms 363.7ms
Tests Lex 110.6ms 69.9ms
Tests Parse 142.1ms 135.0ms
Tests Compile 85.3ms
Tests Execute 425.4ms 398.7ms
Tests Engine Total 678.0ms 689.0ms
Benchmarks Total 364 364
Benchmarks Duration 9.78min 8.32min

Measured on ubuntu-latest x64.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 14, 2026

Benchmark Results

364 benchmarks

Interpreted: 🟢 19 improved · 🔴 230 regressed · 115 unchanged · avg -2.4%
Bytecode: 🟢 130 improved · 🔴 63 regressed · 171 unchanged · avg +0.5%

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

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.

- Cover escaping for quotes, backslashes, solidus, and control chars
- Verify multibyte UTF-8 passthrough and quoted output wrapping
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.JSON.Utils.Test.pas (1)

91-101: Align multibyte UTF-8 comment with actual assertions.

Line 93 mentions U+1F600 coverage, but the test body only checks U+00E9 cases. Either add an emoji assertion or trim the comment.

Suggested update
 procedure TJSONUtilsTests.TestPreservesMultibyteUTF8;
 var
   EAcute: string;
+  GrinningFace: string;
 begin
   EAcute := #$C3#$A9; // UTF-8 for U+00E9 (e with acute accent)
+  GrinningFace := #$F0#$9F#$98#$80; // UTF-8 for U+1F600 (grinning face)
   Expect<string>(EscapeJSONString(EAcute)).ToBe(EAcute);
   Expect<string>(EscapeJSONString('caf' + EAcute)).ToBe('caf' + EAcute);
+  Expect<string>(EscapeJSONString(GrinningFace)).ToBe(GrinningFace);
 end;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@units/Goccia.JSON.Utils.Test.pas` around lines 91 - 101, The comment for
TJSONUtilsTests.TestPreservesMultibyteUTF8 mentions U+1F600 but the test only
asserts U+00E9; update the test to match the comment or simplify the comment:
either add a four-byte UTF‑8 assertion by creating a GrinningEmoji variable
(e.g., Grinning := #$F0#$9F#$98#$80) and assert
Expect<string>(EscapeJSONString(Grinning)).ToBe(Grinning) and
Expect<string>(EscapeJSONString('face' + Grinning)).ToBe('face' + Grinning),
referencing EscapeJSONString and EAcute as examples, or remove the U+1F600
mention from the comment so it only documents the U+00E9 checks in
TestPreservesMultibyteUTF8.
🤖 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.JSON.Utils.Test.pas`:
- Around line 91-101: The comment for TJSONUtilsTests.TestPreservesMultibyteUTF8
mentions U+1F600 but the test only asserts U+00E9; update the test to match the
comment or simplify the comment: either add a four-byte UTF‑8 assertion by
creating a GrinningEmoji variable (e.g., Grinning := #$F0#$9F#$98#$80) and
assert Expect<string>(EscapeJSONString(Grinning)).ToBe(Grinning) and
Expect<string>(EscapeJSONString('face' + Grinning)).ToBe('face' + Grinning),
referencing EscapeJSONString and EAcute as examples, or remove the U+1F600
mention from the comment so it only documents the U+00E9 checks in
TestPreservesMultibyteUTF8.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 101a8537-8e01-4b6a-9260-132c4518892e

📥 Commits

Reviewing files that changed from the base of the PR and between b647abb and 91ee59a.

📒 Files selected for processing (1)
  • units/Goccia.JSON.Utils.Test.pas

- Verify EscapeJSONString preserves 4-byte UTF-8 sequences
- Cover plain emoji and mixed ASCII/emoji input
@frostney frostney merged commit e56e896 into main Apr 15, 2026
55 checks passed
@frostney frostney deleted the t3code/fix-issue-303 branch April 15, 2026 06:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

internal Refactoring, CI, tooling, cleanup

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Consolidate EscapeJSONString into shared helper and fix incomplete control-character escaping

1 participant