Skip to content

Support dynamic import call phases#687

Merged
frostney merged 3 commits into
mainfrom
issue-646-dynamic-import-call-syntax
May 29, 2026
Merged

Support dynamic import call phases#687
frostney merged 3 commits into
mainfrom
issue-646-dynamic-import-call-syntax

Conversation

@frostney
Copy link
Copy Markdown
Owner

@frostney frostney commented May 29, 2026

Summary

  • Add parser support for dynamic import trailing commas, import(specifier, options), and import.source(...) / import.defer(...) call spellings.
  • Evaluate dynamic import options for observable side effects while preserving the parsed import-call phase for interpreter and bytecode execution.
  • Implement proposal-phase behavior for import.source(...) as a ModuleSource value without target evaluation and import.defer(...) as a deferred namespace wrapper that resolves the specifier before fulfillment and evaluates when exports are observed.
  • Closes Support dynamic import options and source/defer import-call syntax #646.

Testing

  • Verified no regressions and confirmed the new feature or bugfix in end-to-end JavaScript/TypeScript tests
    • ./build.pas clean testrunner
    • ./build/GocciaTestRunner tests/language/modules/dynamic-import.js
    • ./build/GocciaTestRunner tests/language/modules/dynamic-import.js --mode=bytecode
    • ./build/GocciaTestRunner tests/language/functions/stack-depth-limit.js
    • ./build.pas loaderbare
    • bun scripts/run_test262_suite.ts --suite-dir /tmp/goccia-test262-vXUU7U --filter 'language/expressions/dynamic-import/syntax/valid/nested-with-*' --categories language --mode interpreted --jobs 1 --timeout-ms 10000 --max-tests 0
    • bun scripts/run_test262_suite.ts --suite-dir /tmp/goccia-test262-vXUU7U --filter 'language/expressions/dynamic-import/syntax/valid/nested-with-*' --categories language --mode bytecode --jobs 1 --timeout-ms 10000 --max-tests 0
    • ./fixtures/ffi/build.sh
    • ./build/GocciaTestRunner tests
    • ./format.pas --check
    • git diff --check
  • Updated documentation
  • Optional: Verified no regressions and confirmed the new feature or bugfix in native Pascal tests (if AST, scope, evaluator, or value types changed)
  • Optional: Verified no benchmark regressions or confirmed benchmark coverage for the change

@vercel
Copy link
Copy Markdown

vercel Bot commented May 29, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
gocciascript-homepage Ignored Ignored Preview May 29, 2026 3:52pm

Request Review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 29, 2026

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 014c2228-e279-46f9-9b0d-ef56700dc939

📥 Commits

Reviewing files that changed from the base of the PR and between 68d7579 and 993bce7.

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

📝 Walkthrough

Walkthrough

This PR adds parser and runtime support for dynamic import option syntax and new import call phases. The changes introduce import(specifier, options) forms with optional second argument, import.source(specifier) for loading module source values, and import.defer(specifier) for lazy namespace resolution. New module abstractions carry source text and defer namespace creation until property access. Options are parsed and evaluated for side effects but semantics are not yet consumed.

Changes

Dynamic import options and import phases

Layer / File(s) Summary
Module types and import phases
source/units/Goccia.Modules.pas, source/units/Goccia.Keywords.Contextual.pas
Exported enum TGocciaImportCallPhase (evaluation/source/defer), callback function types, and two value classes: TGocciaModuleSourceValue (carries path + UTF8 source text) and TGocciaDeferredModuleNamespaceObject (lazy namespace resolver that defers module loading until property access). Contextual keyword source added.
Parser support for import call forms
source/units/Goccia.Parser.pas, docs/language.md
New ParseImportCallExpression helper parses import(specifier, options) with optional second argument for all phases; Primary dispatch extended to route import(...) to evaluation phase, import.source(specifier) to source phase, and import.defer(specifier) to defer phase. Documentation examples and trailing-comma/attributes notes added.
AST import call expression and evaluation
source/units/Goccia.AST.Expressions.pas
TGocciaImportCallExpression constructor updated to accept Options and Phase parameters; new public properties expose both. Evaluate method conditionally evaluates options for side effects and routes resolution through phase-specific loaders: LoadModuleSource for source, LoadDeferredModule for defer, LoadModule for evaluation.
Compiler for dynamic import bytecode
source/units/Goccia.Compiler.Expressions.pas
CompileDynamicImport conditionally compiles Options expression into a register and emits OP_DYNAMIC_IMPORT with phase operand from AExpr.Phase instead of hardcoded 0.
Evaluation context and scope callback propagation
source/units/Goccia.Evaluator.Context.pas, source/units/Goccia.Scope.pas, docs/interpreter.md
TGocciaEvaluationContext record gains LoadModuleSource callback field. TGocciaScope adds FLoadModuleSource and FLoadDeferredModule fields with public properties; both are inherited from parent scope during construction. Interpreter docs updated to show new context field.
Interpreter and function context binding
source/units/Goccia.Interpreter.pas, source/units/Goccia.Values.FunctionValue.pas, source/units/Goccia.Values.GeneratorValue.pas
TGocciaInterpreter adds public methods LoadModuleSourceValue and LoadDeferredModuleNamespaceValue that delegate to FModuleLoader; constructor wires them into FGlobalScope and CreateEvaluationContext populates the context hook. Function and generator value types thread LoadModuleSource from closure scope into execution contexts.
Module loader helpers for source and deferred loading
source/units/Goccia.Modules.Loader.pas
LoadModuleSourceValue resolves module path, validates script extension, loads content, and returns TGocciaModuleSourceValue. LoadDeferredModuleNamespaceValue returns cached deferred namespace or creates TGocciaDeferredModuleNamespaceObject for lazy resolution. Both wrap resolver errors. Loader wires LoadModuleSourceValue into evaluation context during module evaluation.
VM bytecode execution for import phases
source/units/Goccia.VM.pas, source/units/Goccia.Executor.Bytecode.pas
TGocciaVM adds FLoadModuleSource and FLoadDeferredModule callback fields with public properties; implements ImportModuleSourceValue and ImportDeferredModuleNamespaceValue helpers. OP_DYNAMIC_IMPORT opcode updated to route icpSource and icpDefer to new helpers, selecting referrer from debug info or current module path; evaluation phase continues via ImportModuleValue. Bytecode executor wires callbacks into VM during initialization.
Test coverage and documentation
tests/language/modules/dynamic-import.js, tests/language/modules/helpers/*, docs/interpreter.md, docs/language.md
Tests verify trailing comma support, option side effects, Promise return types for source/defer, source-phase non-evaluation of module code, defer-phase lazy namespace resolution, and error handling. Helper modules signal evaluation via global flags. Documentation describes callback field and new syntax forms with examples.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • frostney/GocciaScript#282: Implements the core runtime pipeline for import(specifier) (AST → compiler → VM), which this PR builds upon by extending to support options and new phases via additional loader callbacks.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Support dynamic import call phases' accurately captures the main feature: adding support for import() variants with different phases (evaluation, source, defer).
Description check ✅ Passed The PR description provides a comprehensive summary, lists implementation details, notes the linked issue (#646), and includes an extensive testing checklist with verified steps.
Linked Issues check ✅ Passed All coding requirements from issue #646 are met: parser accepts trailing commas, import(specifier, options), import.source/defer forms; options are evaluated for side effects; AST/bytecode/interpreter support added for ModuleSource and deferred namespace behavior.
Out of Scope Changes check ✅ Passed All changes directly support the stated objectives: parser enhancements, AST extensions, compiler/evaluator updates, module type additions, scope propagation, and comprehensive tests for the new import-call phases.
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.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 29, 2026

Benchmark Results

407 benchmarks

Interpreted: 🟢 57 improved · 🔴 222 regressed · 128 unchanged · avg -2.4%
Bytecode: 🟢 23 improved · 🔴 347 regressed · 37 unchanged · avg -8.2%

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

Deterministic profile diff

Deterministic profile diff: no significant changes.

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

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 29, 2026

Suite Timing

Test Runner (interpreted: 9,819 passed; bytecode: 9,819 passed)
Metric Interpreted Bytecode
Total 9819 9819
Passed 9819 ✅ 9819 ✅
Workers 4 4
Test Duration 3.21s 3.71s
Lex (cumulative) 412.3ms 442.4ms
Parse (cumulative) 278.9ms 294.2ms
Compile (cumulative) 632.7ms
Execute (cumulative) 4.21s 4.79s
Engine Total (cumulative) 4.90s 6.16s
Lex (avg/worker) 103.1ms 110.6ms
Parse (avg/worker) 69.7ms 73.6ms
Compile (avg/worker) 158.2ms
Execute (avg/worker) 1.05s 1.20s
Engine Total (avg/worker) 1.23s 1.54s

Memory

GC rows aggregate the main thread plus all worker thread-local GCs. Test runner worker shutdown frees thread-local heaps in bulk; that shutdown reclamation is not counted as GC collections or collected objects.

Metric Interpreted Bytecode
GC Live 285.83 MiB 278.29 MiB
GC Peak Live 285.84 MiB 278.30 MiB
GC Allocated During Run 290.34 MiB 282.80 MiB
GC Limit 7.81 GiB 7.81 GiB
GC Collections 1 1
GC Collected Objects 87 87
Heap Start Allocated 159.7 KiB 159.7 KiB
Heap End Allocated 1.53 MiB 1.53 MiB
Heap Delta Allocated 1.38 MiB 1.38 MiB
Heap Delta Free 446.7 KiB 446.7 KiB
Benchmarks (interpreted: 407; bytecode: 407)
Metric Interpreted Bytecode
Total 407 407
Workers 4 4
Duration 2.36min 2.33min

Memory

GC rows aggregate the main thread plus all worker thread-local GCs. Benchmark runner performs explicit between-file collections, so collection and collected-object counts can be much higher than the test runner.

Metric Interpreted Bytecode
GC Live 3.97 MiB 3.97 MiB
GC Peak Live 110.37 MiB 79.29 MiB
GC Allocated During Run 15.00 GiB 9.56 GiB
GC Limit 7.81 GiB 7.81 GiB
GC Collections 2,810 2,663
GC Collected Objects 238,298,614 216,439,855
Heap Start Allocated 1.27 MiB 1.27 MiB
Heap End Allocated 1.27 MiB 1.27 MiB
Heap Delta Allocated 128 B 128 B

Measured on ubuntu-latest x64.

@frostney frostney force-pushed the issue-646-dynamic-import-call-syntax branch from 0315eb2 to 9b07382 Compare May 29, 2026 06:01
@frostney frostney changed the title Support dynamic import call syntax Support dynamic import call phases May 29, 2026
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 29, 2026

test262 Conformance

Category Run Passed Δ Pass Failed Pass-rate Δ Rate
built-ins 23,449 16,067 +1 7,377 68.5% ±0pp
harness 116 72 ±0 44 62.1% ±0pp
intl402 3,324 957 ±0 2,367 28.8% ±0pp
language 23,635 14,596 +163 9,039 61.8% +0.7pp
staging 1,484 571 ±0 910 38.5% ±0pp
total 52,008 32,263 +164 19,737 62.0% +0.3pp

Areas closest to 100%

Area Pass rate Δ vs main Passing
built-ins/WeakMap 99.3% ±0pp 140 / 141
built-ins/WeakSet 98.8% ±0pp 84 / 85
language/future-reserved-words 98.1% ±0pp 53 / 54
Per-test deltas (+164 / -0)

Newly passing (164):

  • built-ins/Number/prototype/toExponential/undefined-fractiondigits.js
  • language/expressions/dynamic-import/catch/nested-arrow-import-catch-import-defer-specifier-tostring-abrupt-rejects.js
  • language/expressions/dynamic-import/catch/nested-arrow-import-catch-import-source-specifier-tostring-abrupt-rejects.js
  • language/expressions/dynamic-import/catch/nested-async-arrow-function-await-import-defer-specifier-tostring-abrupt-rejects.js
  • language/expressions/dynamic-import/catch/nested-async-arrow-function-await-import-source-specifier-tostring-abrupt-rejects.js
  • language/expressions/dynamic-import/catch/nested-async-arrow-function-return-await-import-defer-specifier-tostring-abrupt-rejects.js
  • language/expressions/dynamic-import/catch/nested-async-arrow-function-return-await-import-source-specifier-tostring-abrupt-rejects.js
  • language/expressions/dynamic-import/catch/nested-async-function-await-import-defer-specifier-tostring-abrupt-rejects.js
  • language/expressions/dynamic-import/catch/nested-async-function-await-import-source-specifier-tostring-abrupt-rejects.js
  • language/expressions/dynamic-import/catch/nested-async-function-import-defer-specifier-tostring-abrupt-rejects.js
  • language/expressions/dynamic-import/catch/nested-async-function-import-source-specifier-tostring-abrupt-rejects.js
  • language/expressions/dynamic-import/catch/nested-async-function-return-await-import-defer-specifier-tostring-abrupt-rejects.js
  • language/expressions/dynamic-import/catch/nested-async-function-return-await-import-source-specifier-tostring-abrupt-rejects.js
  • language/expressions/dynamic-import/catch/nested-async-gen-await-import-defer-specifier-tostring-abrupt-rejects.js
  • language/expressions/dynamic-import/catch/nested-async-gen-await-import-source-specifier-tostring-abrupt-rejects.js
  • language/expressions/dynamic-import/catch/nested-async-gen-return-await-import-defer-specifier-tostring-abrupt-rejects.js
  • language/expressions/dynamic-import/catch/nested-async-gen-return-await-import-source-specifier-tostring-abrupt-rejects.js
  • language/expressions/dynamic-import/catch/nested-block-import-catch-import-defer-specifier-tostring-abrupt-rejects.js
  • language/expressions/dynamic-import/catch/nested-block-import-catch-import-source-specifier-tostring-abrupt-rejects.js
  • language/expressions/dynamic-import/catch/nested-block-labeled-import-defer-specifier-tostring-abrupt-rejects.js
  • language/expressions/dynamic-import/catch/nested-block-labeled-import-source-specifier-tostring-abrupt-rejects.js
  • language/expressions/dynamic-import/catch/nested-do-while-import-defer-specifier-tostring-abrupt-rejects.js
  • language/expressions/dynamic-import/catch/nested-do-while-import-source-specifier-tostring-abrupt-rejects.js
  • language/expressions/dynamic-import/catch/nested-else-import-catch-import-defer-specifier-tostring-abrupt-rejects.js
  • language/expressions/dynamic-import/catch/nested-else-import-catch-import-source-specifier-tostring-abrupt-rejects.js
  • language/expressions/dynamic-import/catch/nested-function-import-catch-import-defer-specifier-tostring-abrupt-rejects.js
  • language/expressions/dynamic-import/catch/nested-function-import-catch-import-source-specifier-tostring-abrupt-rejects.js
  • language/expressions/dynamic-import/catch/nested-if-import-catch-import-defer-specifier-tostring-abrupt-rejects.js
  • language/expressions/dynamic-import/catch/nested-if-import-catch-import-source-specifier-tostring-abrupt-rejects.js
  • language/expressions/dynamic-import/catch/nested-while-import-catch-import-defer-specifier-tostring-abrupt-rejects.js
  • language/expressions/dynamic-import/catch/nested-while-import-catch-import-source-specifier-tostring-abrupt-rejects.js
  • language/expressions/dynamic-import/catch/top-level-import-catch-import-defer-specifier-tostring-abrupt-rejects.js
  • language/expressions/dynamic-import/catch/top-level-import-catch-import-source-specifier-tostring-abrupt-rejects.js
  • language/expressions/dynamic-import/import-attributes/2nd-param-evaluation-abrupt-return.js
  • language/expressions/dynamic-import/import-attributes/2nd-param-evaluation-abrupt-throw.js
  • language/expressions/dynamic-import/import-attributes/2nd-param-evaluation-sequence.js
  • language/expressions/dynamic-import/import-attributes/2nd-param-trailing-comma-reject.js
  • language/expressions/dynamic-import/import-attributes/trailing-comma-reject.js
  • language/expressions/dynamic-import/syntax/valid/nested-arrow-assignment-expression-import-attributes-trailing-comma-first.js
  • language/expressions/dynamic-import/syntax/valid/nested-arrow-assignment-expression-import-attributes-trailing-comma-second.js
  • language/expressions/dynamic-import/syntax/valid/nested-arrow-assignment-expression-import-defer-empty-str-is-valid-assign-expr.js
  • language/expressions/dynamic-import/syntax/valid/nested-arrow-assignment-expression-import-defer-script-code-valid.js
  • language/expressions/dynamic-import/syntax/valid/nested-arrow-assignment-expression-import-source-empty-str-is-valid-assign-expr.js
  • language/expressions/dynamic-import/syntax/valid/nested-arrow-assignment-expression-import-source-script-code-valid.js
  • language/expressions/dynamic-import/syntax/valid/nested-arrow-import-attributes-trailing-comma-first.js
  • language/expressions/dynamic-import/syntax/valid/nested-arrow-import-attributes-trailing-comma-second.js
  • language/expressions/dynamic-import/syntax/valid/nested-arrow-import-defer-empty-str-is-valid-assign-expr.js
  • language/expressions/dynamic-import/syntax/valid/nested-arrow-import-defer-script-code-valid.js
  • language/expressions/dynamic-import/syntax/valid/nested-arrow-import-source-empty-str-is-valid-assign-expr.js
  • language/expressions/dynamic-import/syntax/valid/nested-arrow-import-source-script-code-valid.js
  • language/expressions/dynamic-import/syntax/valid/nested-async-arrow-function-await-import-attributes-trailing-comma-first.js
  • language/expressions/dynamic-import/syntax/valid/nested-async-arrow-function-await-import-attributes-trailing-comma-second.js
  • language/expressions/dynamic-import/syntax/valid/nested-async-arrow-function-await-import-defer-empty-str-is-valid-assign-expr.js
  • language/expressions/dynamic-import/syntax/valid/nested-async-arrow-function-await-import-defer-script-code-valid.js
  • language/expressions/dynamic-import/syntax/valid/nested-async-arrow-function-await-import-source-empty-str-is-valid-assign-expr.js
  • language/expressions/dynamic-import/syntax/valid/nested-async-arrow-function-await-import-source-script-code-valid.js
  • language/expressions/dynamic-import/syntax/valid/nested-async-arrow-function-return-await-import-attributes-trailing-comma-first.js
  • language/expressions/dynamic-import/syntax/valid/nested-async-arrow-function-return-await-import-attributes-trailing-comma-second.js
  • language/expressions/dynamic-import/syntax/valid/nested-async-arrow-function-return-await-import-defer-empty-str-is-valid-assign-expr.js
  • language/expressions/dynamic-import/syntax/valid/nested-async-arrow-function-return-await-import-defer-script-code-valid.js
  • language/expressions/dynamic-import/syntax/valid/nested-async-arrow-function-return-await-import-source-empty-str-is-valid-assign-expr.js
  • language/expressions/dynamic-import/syntax/valid/nested-async-arrow-function-return-await-import-source-script-code-valid.js
  • language/expressions/dynamic-import/syntax/valid/nested-async-function-await-import-attributes-trailing-comma-first.js
  • language/expressions/dynamic-import/syntax/valid/nested-async-function-await-import-attributes-trailing-comma-second.js
  • language/expressions/dynamic-import/syntax/valid/nested-async-function-await-import-defer-empty-str-is-valid-assign-expr.js
  • language/expressions/dynamic-import/syntax/valid/nested-async-function-await-import-defer-script-code-valid.js
  • language/expressions/dynamic-import/syntax/valid/nested-async-function-await-import-source-empty-str-is-valid-assign-expr.js
  • language/expressions/dynamic-import/syntax/valid/nested-async-function-await-import-source-script-code-valid.js
  • language/expressions/dynamic-import/syntax/valid/nested-async-function-import-attributes-trailing-comma-first.js
  • language/expressions/dynamic-import/syntax/valid/nested-async-function-import-attributes-trailing-comma-second.js
  • language/expressions/dynamic-import/syntax/valid/nested-async-function-import-defer-empty-str-is-valid-assign-expr.js
  • language/expressions/dynamic-import/syntax/valid/nested-async-function-import-defer-script-code-valid.js
  • language/expressions/dynamic-import/syntax/valid/nested-async-function-import-source-empty-str-is-valid-assign-expr.js
  • language/expressions/dynamic-import/syntax/valid/nested-async-function-import-source-script-code-valid.js
  • language/expressions/dynamic-import/syntax/valid/nested-async-function-return-await-import-attributes-trailing-comma-first.js
  • language/expressions/dynamic-import/syntax/valid/nested-async-function-return-await-import-attributes-trailing-comma-second.js
  • language/expressions/dynamic-import/syntax/valid/nested-async-function-return-await-import-defer-empty-str-is-valid-assign-expr.js
  • language/expressions/dynamic-import/syntax/valid/nested-async-function-return-await-import-defer-script-code-valid.js
  • language/expressions/dynamic-import/syntax/valid/nested-async-function-return-await-import-source-empty-str-is-valid-assign-expr.js
  • language/expressions/dynamic-import/syntax/valid/nested-async-function-return-await-import-source-script-code-valid.js
  • language/expressions/dynamic-import/syntax/valid/nested-async-gen-await-import-attributes-trailing-comma-first.js
  • language/expressions/dynamic-import/syntax/valid/nested-async-gen-await-import-attributes-trailing-comma-second.js
  • language/expressions/dynamic-import/syntax/valid/nested-async-gen-await-import-defer-empty-str-is-valid-assign-expr.js
  • language/expressions/dynamic-import/syntax/valid/nested-async-gen-await-import-defer-script-code-valid.js
  • language/expressions/dynamic-import/syntax/valid/nested-async-gen-await-import-source-empty-str-is-valid-assign-expr.js
  • language/expressions/dynamic-import/syntax/valid/nested-async-gen-await-import-source-script-code-valid.js
  • language/expressions/dynamic-import/syntax/valid/nested-block-import-attributes-trailing-comma-first.js
  • language/expressions/dynamic-import/syntax/valid/nested-block-import-attributes-trailing-comma-second.js
  • language/expressions/dynamic-import/syntax/valid/nested-block-import-defer-empty-str-is-valid-assign-expr.js
  • language/expressions/dynamic-import/syntax/valid/nested-block-import-defer-script-code-valid.js
  • language/expressions/dynamic-import/syntax/valid/nested-block-import-source-empty-str-is-valid-assign-expr.js
  • language/expressions/dynamic-import/syntax/valid/nested-block-import-source-script-code-valid.js
  • language/expressions/dynamic-import/syntax/valid/nested-block-labeled-import-attributes-trailing-comma-first.js
  • language/expressions/dynamic-import/syntax/valid/nested-block-labeled-import-attributes-trailing-comma-second.js
  • language/expressions/dynamic-import/syntax/valid/nested-block-labeled-import-defer-empty-str-is-valid-assign-expr.js
  • language/expressions/dynamic-import/syntax/valid/nested-block-labeled-import-defer-script-code-valid.js
  • language/expressions/dynamic-import/syntax/valid/nested-block-labeled-import-source-empty-str-is-valid-assign-expr.js
  • language/expressions/dynamic-import/syntax/valid/nested-block-labeled-import-source-script-code-valid.js
  • language/expressions/dynamic-import/syntax/valid/nested-do-while-import-attributes-trailing-comma-first.js
  • language/expressions/dynamic-import/syntax/valid/nested-do-while-import-attributes-trailing-comma-second.js
  • … 64 more

Steady-state failures are non-blocking; regressions vs the cached main baseline (lower total pass count, or any PASS → non-PASS transition) fail the conformance gate. Measured on ubuntu-latest x64, bytecode mode. Areas grouped by the first two test262 path components; minimum 25 attempted tests, areas already at 100% excluded. Δ vs main compares against the most recent cached main baseline.

Parse dynamic import trailing comma/options syntax and preserve import.source/import.defer phases in the AST and bytecode. Evaluate import options for side effects while leaving attribute semantics for later.

Add source-phase module source values and deferred dynamic import namespace wrappers so import.source resolves without evaluating the target module and import.defer delays evaluation until namespace exports are observed. Wire both paths through interpreter and bytecode execution.

Update dynamic import docs and regression coverage for source/defer behavior.

Closes #646
@frostney frostney force-pushed the issue-646-dynamic-import-call-syntax branch from 9b07382 to 68d7579 Compare May 29, 2026 14:27
@frostney frostney marked this pull request as ready for review May 29, 2026 14:42
@coderabbitai coderabbitai Bot added new feature New feature or request spec compliance Mismatch against official JavaScript/TypeScript specification labels May 29, 2026
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

Caution

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

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

149-160: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Initialize DisposalTracker in CreateEvaluationContext.

Line 149 builds a stack record; Result.DisposalTracker is never assigned here, so it can remain undefined and trip downstream Assigned(...) checks.

🩹 Proposed fix
 function TGocciaInterpreter.CreateEvaluationContext: TGocciaEvaluationContext;
 begin
   Result.Scope := FGlobalScope;
   Result.OnError := ThrowError;
   Result.LoadModule := LoadModule;
   Result.LoadModuleSource := LoadModuleSourceValue;
   Result.CurrentFilePath := FFileName;
   Result.CoverageEnabled := Assigned(TGocciaCoverageTracker.Instance)
     and TGocciaCoverageTracker.Instance.Enabled;
   Result.StrictTypes := FStrictTypesEnabled;
   Result.NonStrictMode := FNonStrictModeEnabled;
+  Result.DisposalTracker := nil;
 end;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@source/units/Goccia.Interpreter.pas` around lines 149 - 160, The evaluation
context built in TGocciaInterpreter.CreateEvaluationContext does not set
Result.DisposalTracker, leaving it undefined; update CreateEvaluationContext to
initialize DisposalTracker (e.g. assign a new TGocciaDisposalTracker instance to
Result.DisposalTracker) so subsequent Assigned(...) checks are safe, and ensure
the evaluation context's lifecycle code (where TGocciaEvaluationContext is
freed) takes responsibility for freeing that DisposalTracker to avoid leaks.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@source/units/Goccia.Modules.pas`:
- Around line 163-164: Module returned from FLoadModule(FModulePath,
FImportingFilePath) may be nil but is dereferenced immediately via
Module.GetNamespaceObject; add a nil check after calling FLoadModule and handle
the nil case by raising a script error or returning early instead of proceeding.
Update the block that assigns Module and FNamespaceObject to first assign Module
:= FLoadModule(...), then if Module = nil then raise an appropriate exception or
set an error result (so callers receive a controlled script error), otherwise
call Module.GetNamespaceObject to assign FNamespaceObject; reference
FLoadModule, Module, FNamespaceObject, FModulePath and FImportingFilePath when
making the change.

In `@source/units/Goccia.VM.pas`:
- Around line 10170-10203: The dynamic-import handling currently treats any
unknown phase (variable C) as a normal import, which can silently execute
modules for malformed bytecode; update the cases in the blocks that call
DynImportPromise.Resolve (the branches using
VMRegisterToStringFast(FRegisters[B]).Value and Template.DebugInfo.SourceFile or
FCurrentModuleSourcePath) to explicitly handle only known icpSource and icpDefer
values and, for any other C value, fail closed by rejecting the DynImportPromise
(or raising a VM/Import error) with a clear message including the offending
phase and module name instead of calling ImportModuleValue; ensure both the
Template.DebugInfo branch and the FCurrentModuleSourcePath branch apply the same
reject/raise behavior and reference the same identifying symbols
(DynImportPromise.Resolve, ImportModuleSourceValue,
ImportDeferredModuleNamespaceValue, ImportModuleValue) when locating where to
change the logic.

---

Outside diff comments:
In `@source/units/Goccia.Interpreter.pas`:
- Around line 149-160: The evaluation context built in
TGocciaInterpreter.CreateEvaluationContext does not set Result.DisposalTracker,
leaving it undefined; update CreateEvaluationContext to initialize
DisposalTracker (e.g. assign a new TGocciaDisposalTracker instance to
Result.DisposalTracker) so subsequent Assigned(...) checks are safe, and ensure
the evaluation context's lifecycle code (where TGocciaEvaluationContext is
freed) takes responsibility for freeing that DisposalTracker to avoid leaks.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 9bedb3bf-9970-4200-bef2-fb81734a8dd3

📥 Commits

Reviewing files that changed from the base of the PR and between 4f95508 and 68d7579.

📒 Files selected for processing (18)
  • docs/interpreter.md
  • docs/language.md
  • source/units/Goccia.AST.Expressions.pas
  • source/units/Goccia.Compiler.Expressions.pas
  • source/units/Goccia.Evaluator.Context.pas
  • source/units/Goccia.Executor.Bytecode.pas
  • source/units/Goccia.Interpreter.pas
  • source/units/Goccia.Keywords.Contextual.pas
  • source/units/Goccia.Modules.Loader.pas
  • source/units/Goccia.Modules.pas
  • source/units/Goccia.Parser.pas
  • source/units/Goccia.Scope.pas
  • source/units/Goccia.VM.pas
  • source/units/Goccia.Values.FunctionValue.pas
  • source/units/Goccia.Values.GeneratorValue.pas
  • tests/language/modules/dynamic-import.js
  • tests/language/modules/helpers/deferred-dynamic-import-side-effect.js
  • tests/language/modules/helpers/source-dynamic-import-side-effect.js

Comment thread source/units/Goccia.Modules.pas
Comment thread source/units/Goccia.VM.pas
frostney added 2 commits May 29, 2026 17:50
Guard deferred namespace loader results before dereference.

Reject unsupported bytecode dynamic import phases instead of falling back to ordinary import.
@frostney frostney merged commit c7bf0d4 into main May 29, 2026
14 checks passed
@frostney frostney deleted the issue-646-dynamic-import-call-syntax branch May 29, 2026 16:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support dynamic import options and source/defer import-call syntax

1 participant