Skip to content

Handle mixed type-only imports and exports#194

Merged
frostney merged 3 commits into
mainfrom
t3code/types-as-comments-review
Apr 7, 2026
Merged

Handle mixed type-only imports and exports#194
frostney merged 3 commits into
mainfrom
t3code/types-as-comments-review

Conversation

@frostney
Copy link
Copy Markdown
Owner

@frostney frostney commented Apr 7, 2026

Summary

  • Teach the parser to skip type-only specifiers inside mixed import { ... } and export { ... } lists while preserving runtime value bindings.
  • Add support for skipping export interface declarations as type-only syntax.
  • Extend unsupported function-syntax handling so typed/generic signatures are skipped cleanly.
  • Add regression coverage for mixed type/value module bindings, type-only import side effects, and typed unsupported function syntax.
  • Update the language restrictions and design-decision docs to reflect the new behavior.

Testing

  • Added/updated JavaScript regression tests under tests/language/types-as-comments/ for mixed imports/exports and export interface handling.
  • Added parser coverage for typed unsupported function declarations and expressions.

Summary by CodeRabbit

Release Notes

  • Documentation

    • Updated guidance on handling type declarations and mixed import/export syntax
    • Clarified behavior when type-only declarations are used alongside value exports
  • Improvements

    • Enhanced parsing of type-only imports and exports
    • Improved handling of unsupported function syntax with type annotations
  • Tests

    • Added comprehensive test coverage for type-only and mixed declaration scenarios

- Preserve runtime bindings for mixed import/export lists while skipping type-only entries
- Skip exported interfaces and unsupported typed function signatures gracefully
- Add regression tests and docs for types-as-comments behavior
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 7, 2026

Warning

Rate limit exceeded

@frostney has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 6 minutes and 12 seconds before requesting another review.

Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 6 minutes and 12 seconds.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 34360107-ee7c-450f-bd17-2f12ecb6f407

📥 Commits

Reviewing files that changed from the base of the PR and between a29d8d7 and 07ecf6b.

📒 Files selected for processing (5)
  • tests/language/types-as-comments/helpers/type-renamed-export.js
  • tests/language/types-as-comments/helpers/type-value-export.js
  • tests/language/types-as-comments/import-export-type.js
  • tests/language/types-as-comments/unsupported-function-annotations.js
  • units/Goccia.Parser.pas
📝 Walkthrough

Walkthrough

This change implements TypeScript's mixed value/type import and export specifiers (e.g., import { value, type T }) while preserving runtime value bindings. Parser updates add support for skipping type-only specifiers, consolidate unsupported function signature handling, and explicitly skip export interface declarations. Tests and documentation are updated to validate the new behavior.

Changes

Cohort / File(s) Summary
Documentation
docs/design-decisions.md, docs/language-restrictions.md
Updated behavior tables and examples clarifying handling of mixed type/value imports/exports and export interface skipping; no code changes.
Test Helpers
tests/language/types-as-comments/helpers/*
Added four new helper modules: exported-interface.js (interface + const export), mixed-type-export.js (mixed value/type export), type-only-side-effect.js and type-only-only-side-effect.js (global counter side effects for runtime verification).
Test Suite
tests/language/types-as-comments/import-export-type.js, tests/language/types-as-comments/unsupported-function-annotations.js
Updated and added test cases validating mixed import/export behavior, export interface handling, and unsupported typed function expressions/declarations; +22 lines and +24 lines respectively.
Parser Implementation
units/Goccia.Parser.pas
Consolidated unsupported function signature handling into new SkipUnsupportedFunctionSignature method; added type-only specifier detection and skipping in import/export parsing; added export interface skipping producing TGocciaEmptyStatement; +63/-24 lines.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • PR #14: Implements type-only import/export specifier skipping producing TGocciaEmptyStatement, directly aligned with the core feature in this PR.
  • PR #32: Modifies parser handling of unsupported function declarations and expressions, overlapping with the consolidated SkipUnsupportedFunctionSignature refactor.
  • PR #181: Adds string-literal module export name parsing in units/Goccia.Parser.pas, touching the same export specifier parsing areas.

Poem

🐰 A rabbit hops through import chains,
Type-only specifiers flowing like veins,
Skip the types, keep values dear,
Runtime bindings crystal clear!

🚥 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 'Handle mixed type-only imports and exports' directly and specifically describes the main change in the changeset: adding parser support for mixed type-only and value specifiers in import/export statements.
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 t3code/types-as-comments-review

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.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 7, 2026

Suite Timing

Suite Metric Interpreted Bytecode
Tests Total 3701 3701
Tests Passed 3660 ✅ 3701 ✅
Tests Skipped 41 0
Tests Execution 208.9ms 193.7ms
Tests Engine 379.2ms 688.0ms
Benchmarks Total 274 274
Benchmarks Duration 7.27min 6.13min

Measured on ubuntu-latest x64.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 7, 2026

Benchmark Results

274 benchmarks

Interpreted: 🟢 140 improved · 🔴 92 regressed · 42 unchanged · avg +1.9%
Bytecode: 🟢 102 improved · 🔴 39 regressed · 133 unchanged · avg +1.4%

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

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

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
units/Goccia.Parser.pas (1)

2340-2358: ⚠️ Potential issue | 🟠 Major

Add lookahead to disambiguate type before treating a named specifier as type-only.

The code currently treats any leading type token as a type-only modifier, breaking runtime bindings like import { type as kind } from "./m.js" / export { type as kind }. The type keyword is a contextual modifier only when followed by another specifier name; when followed by as, type is the property name itself.

Add a lookahead check: treat type as a modifier only when the next token is a valid specifier name (identifier or string), not as. Apply this same check consistently in both import and export specifier loops.

Also applies to: 2480-2506

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

In `@units/Goccia.Parser.pas` around lines 2340 - 2358, The parser currently
treats any leading KEYWORD_TYPE as a type-only modifier by using
Check(gttIdentifier) and Peek.Lexeme, which wrongly marks cases like `import {
type as kind }` as type-only; change the logic around IsTypeOnlyBinding so you
only treat KEYWORD_TYPE as a modifier when it's followed by a valid specifier
name (gttIdentifier or gttString) rather than the `as` token: perform a
one-token lookahead (inspect Peek and the next token after Peek) and set
IsTypeOnlyBinding true only when Peek is KEYWORD_TYPE AND the following token
type is gttIdentifier or gttString, then Advance() to consume the KEYWORD_TYPE;
update the same check in the export specifier loop mentioned (the code that
mirrors this logic around ConsumeModuleExportName, ImportedNameToken,
Match(gttAs), Consume, and Imports.Add) to use the identical lookahead rule.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@units/Goccia.Parser.pas`:
- Around line 2340-2358: The parser currently treats any leading KEYWORD_TYPE as
a type-only modifier by using Check(gttIdentifier) and Peek.Lexeme, which
wrongly marks cases like `import { type as kind }` as type-only; change the
logic around IsTypeOnlyBinding so you only treat KEYWORD_TYPE as a modifier when
it's followed by a valid specifier name (gttIdentifier or gttString) rather than
the `as` token: perform a one-token lookahead (inspect Peek and the next token
after Peek) and set IsTypeOnlyBinding true only when Peek is KEYWORD_TYPE AND
the following token type is gttIdentifier or gttString, then Advance() to
consume the KEYWORD_TYPE; update the same check in the export specifier loop
mentioned (the code that mirrors this logic around ConsumeModuleExportName,
ImportedNameToken, Match(gttAs), Consume, and Imports.Add) to use the identical
lookahead rule.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 3b9073b9-5df1-4324-87b2-26606ca9b342

📥 Commits

Reviewing files that changed from the base of the PR and between d16da08 and a29d8d7.

📒 Files selected for processing (9)
  • docs/design-decisions.md
  • docs/language-restrictions.md
  • tests/language/types-as-comments/helpers/exported-interface.js
  • tests/language/types-as-comments/helpers/mixed-type-export.js
  • tests/language/types-as-comments/helpers/type-only-only-side-effect.js
  • tests/language/types-as-comments/helpers/type-only-side-effect.js
  • tests/language/types-as-comments/import-export-type.js
  • tests/language/types-as-comments/unsupported-function-annotations.js
  • units/Goccia.Parser.pas

Comment thread units/Goccia.Parser.pas
frostney added 2 commits April 7, 2026 11:06
…ction signatures with object return types\n- add regression coverage for object-literal return annotations\n- keep mixed type-only import/export coverage and docs in sync
- Allow `type` export specifiers to be treated as values when followed by a real binding
- Add regression tests for imported and re-exported `type`-named values
@frostney frostney merged commit 22e9f40 into main Apr 7, 2026
9 checks passed
@frostney frostney deleted the t3code/types-as-comments-review branch April 7, 2026 12:12
@frostney frostney added the bug Something isn't working label Apr 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant