Skip to content

Implement import.meta support#265

Merged
frostney merged 6 commits into
mainfrom
t3code/implement-import-meta
Apr 11, 2026
Merged

Implement import.meta support#265
frostney merged 6 commits into
mainfrom
t3code/implement-import-meta

Conversation

@frostney
Copy link
Copy Markdown
Owner

Summary

  • Added parser, AST, evaluator, compiler, and VM support for import.meta expressions.
  • Introduced per-module metadata objects with stable import.meta.url and import.meta.resolve() behavior.
  • Added module tests covering object shape, URL resolution, identity stability, and nested-module behavior.
  • Documented import.meta in the language restrictions and bytecode VM docs, and updated the import/meta suggestion text.

Testing

  • Not run (PR content generated from the diff only).
  • Existing test coverage added in tests/language/modules/import-meta.js and tests/language/modules/helpers/import-meta-child.js.
  • The change also bumps the bytecode format version, so bytecode compatibility should be exercised in the normal build/test pipeline.

- Add parser, evaluator, compiler, and VM support
- Introduce per-module `import.meta` caching with `url` and `resolve()`
- Add language tests and update docs/opcode metadata
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 11, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: cda7a5b8-f29e-4996-b91a-03e28d4a16d1

📥 Commits

Reviewing files that changed from the base of the PR and between 274bdd1 and 455724f.

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

📝 Walkthrough

Walkthrough

Adds ES-style import.meta: parser recognition, new AST node and compiler emitter, OP_IMPORT_META bytecode and VM handler, runtime per-module import.meta objects with url and resolve(), GC pin/cache and engine cleanup, docs and tests; bytecode format bumped to 10.

Changes

Cohort / File(s) Summary
Documentation
AGENTS.md, docs/bytecode-vm.md, docs/language-restrictions.md
Documented new import.meta surface, added IMPORT_META opcode to docs, specified import.meta.url and import.meta.resolve() semantics and test locations.
Tests
tests/language/modules/import-meta.js, tests/language/modules/helpers/import-meta-child.js, tests/language/modules/helpers/import-meta-function.js
New test suite and helpers verifying import.meta identity, null-prototype, url format, resolve() behavior, cross-module isolation, and function-bound resolution.
Parser & Keywords
units/Goccia.Parser.pas, units/Goccia.Keywords.Contextual.pas
Parse import.meta as a meta-property expression; added KEYWORD_META and treat import. sequences as expression statements with a targeted syntax suggestion.
AST
units/Goccia.AST.Expressions.pas
Added TGocciaImportMetaExpression with Evaluate override returning import.meta via runtime helper.
Compiler & Bytecode
units/Goccia.Compiler.Expressions.pas, units/Goccia.Compiler.pas, units/Goccia.Bytecode.pas, units/Goccia.Bytecode.OpCodeNames.pas
New CompileImportMeta() emitter, compiler dispatch for the AST node, added OP_IMPORT_META = 170, opcode-name mapping, and bumped GOCCIA_FORMAT_VERSION to 10.
VM & Runtime
units/Goccia.VM.pas, units/Goccia.ImportMeta.pas, units/Goccia.Engine.pas
VM handler for OP_IMPORT_META selects module source path; new Goccia.ImportMeta unit implements per-file cache, FilePath→file:// URL conversion, resolve() helper, GC pin/unpin tracking, and cache cleanup on engine Destroy.
Constants & Errors
units/Goccia.Constants.PropertyNames.pas, units/Goccia.Error.Suggestions.pas
Added PROP_URL, PROP_RESOLVE constants and SSuggestImportMetaSyntax suggestion string.

Sequence Diagram

sequenceDiagram
    participant Parser as Parser
    participant AST as AST Node
    participant Compiler as Compiler
    participant VM as VM/Executor
    participant MetaCache as ImportMeta Cache

    Parser->>AST: recognize import.meta (TGocciaImportMetaExpression)
    AST-->>Parser: return expression node
    Compiler->>Compiler: dispatch on TGocciaImportMetaExpression
    Compiler->>VM: emit OP_IMPORT_META in bytecode
    VM->>VM: decode OP_IMPORT_META
    VM->>MetaCache: GetOrCreateImportMeta(current module path)
    MetaCache->>MetaCache: normalize path and check cache
    alt Cache Hit
        MetaCache-->>VM: return cached meta object
    else Cache Miss
        MetaCache->>MetaCache: create null-prototype object with url & resolve
        MetaCache->>MetaCache: pin objects in GC (if available)
        MetaCache-->>VM: return new meta object
    end
    VM->>VM: store meta object in result register
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The pull request title 'Implement import.meta support' directly and clearly summarizes the main change—adding comprehensive import.meta functionality including parser, AST, evaluator, compiler, and VM support.
Description check ✅ Passed The description covers the summary and testing sections but lacks explicit test execution confirmation and benchmark verification checkboxes as specified in the template.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

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


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

@coderabbitai coderabbitai Bot added documentation Improvements or additions to documentation new feature New feature or request labels Apr 11, 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

🧹 Nitpick comments (1)
units/Goccia.Compiler.Expressions.pas (1)

2451-2455: Add the ES spec annotation above this implementation.

This new import.meta path introduces ECMAScript-defined behavior in the implementation section, but it is missing the required ES2026 reference comment.

♻️ Suggested change
+// ES2026 §13.3.12 MetaProperty — import.meta
 procedure CompileImportMeta(const ACtx: TGocciaCompilationContext;
   const ADest: UInt8);
 begin
   EmitInstruction(ACtx, EncodeABC(OP_IMPORT_META, ADest, 0, 0));
 end;

As per coding guidelines "When implementing ECMAScript-specified behavior, annotate each function or method with a comment referencing the relevant spec section using the format // ESYYYY §X.Y.Z SpecMethodName(specParams)..."

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

In `@units/Goccia.Compiler.Expressions.pas` around lines 2451 - 2455, Add the
required ECMAScript spec annotation comment above the CompileImportMeta
procedure to reference the spec section for import.meta (e.g., "// ES2026 §X.Y.Z
ImportMeta(...)"); locate the CompileImportMeta procedure and insert the comment
immediately above it so the implementation of import.meta (and use of
OP_IMPORT_META) is annotated per the coding guidelines.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@units/Goccia.ImportMeta.pas`:
- Around line 109-115: The code currently pins MetaObject, ResolveHelper, and
ResolveFunction via TGarbageCollector.Instance.PinObject but only unpins
MetaObject later, leaving ResolveHelper and ResolveFunction permanently pinned;
update the cleanup/unpin logic to call TGarbageCollector.Instance.UnpinObject
for each object previously pinned (MetaObject, ResolveHelper, and the cast
TGCManagedObject(ResolveFunction)) in the same scope where MetaObject is
unpinned, and apply the same fix to the other import.meta creation block (the
second occurrence around the 122–133 region) so that every PinObject has a
matching UnpinObject for those three symbols.

In `@units/Goccia.VM.pas`:
- Around line 5124-5125: OP_IMPORT_META currently calls
GetOrCreateImportMeta(FCurrentModuleSourcePath) which uses the executing module
rather than the defining module; change the argument to use the defining
module's source if available by passing Template.DebugInfo.SourceFile when
present and falling back to FCurrentModuleSourcePath for tests, i.e. call
GetOrCreateImportMeta(Template.DebugInfo.SourceFile or FCurrentModuleSourcePath)
in the OP_IMPORT_META handler so import.meta binds lexically to the function's
defining module.

---

Nitpick comments:
In `@units/Goccia.Compiler.Expressions.pas`:
- Around line 2451-2455: Add the required ECMAScript spec annotation comment
above the CompileImportMeta procedure to reference the spec section for
import.meta (e.g., "// ES2026 §X.Y.Z ImportMeta(...)"); locate the
CompileImportMeta procedure and insert the comment immediately above it so the
implementation of import.meta (and use of OP_IMPORT_META) is annotated per the
coding guidelines.
🪄 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: 5581d68b-d807-414c-a73a-ca2c764e3636

📥 Commits

Reviewing files that changed from the base of the PR and between 259e26b and b6be039.

📒 Files selected for processing (17)
  • AGENTS.md
  • docs/bytecode-vm.md
  • docs/language-restrictions.md
  • tests/language/modules/helpers/import-meta-child.js
  • tests/language/modules/import-meta.js
  • units/Goccia.AST.Expressions.pas
  • units/Goccia.Bytecode.OpCodeNames.pas
  • units/Goccia.Bytecode.pas
  • units/Goccia.Compiler.Expressions.pas
  • units/Goccia.Compiler.pas
  • units/Goccia.Constants.PropertyNames.pas
  • units/Goccia.Engine.pas
  • units/Goccia.Error.Suggestions.pas
  • units/Goccia.ImportMeta.pas
  • units/Goccia.Keywords.Contextual.pas
  • units/Goccia.Parser.pas
  • units/Goccia.VM.pas

Comment thread units/Goccia.ImportMeta.pas
Comment thread units/Goccia.VM.pas Outdated
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 11, 2026

Suite Timing

Suite Metric Interpreted Bytecode
Tests Total 4618 4618
Tests Passed 4577 ✅ 4618 ✅
Tests Skipped 41 0
Tests Test Duration 323.3ms 302.0ms
Tests Lex 87.0ms 58.8ms
Tests Parse 114.5ms 113.3ms
Tests Compile 72.6ms
Tests Execute 338.9ms 333.0ms
Tests Engine Total 540.4ms 577.7ms
Benchmarks Total 364 364
Benchmarks Duration 9.80min 8.90min

Measured on ubuntu-latest x64.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 11, 2026

Benchmark Results

364 benchmarks

Interpreted: 🟢 10 improved · 🔴 261 regressed · 93 unchanged · avg -3.3%
Bytecode: 🟢 95 improved · 🔴 99 regressed · 170 unchanged · avg +0.3%

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

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.

@frostney frostney added the spec compliance Mismatch against official JavaScript/TypeScript specification label Apr 11, 2026
…notation

- Fix GC unpin leak: track all pinned objects (meta object, resolve helper,
  resolve function) and unpin them all during ClearImportMetaCache
- Use Template.DebugInfo.SourceFile for lexical import.meta binding in the
  bytecode VM, with FCurrentModuleSourcePath as fallback for tests without
  debug info — ensures exported functions report their defining module's
  metadata, not the calling module's
- Add ES2026 §13.3.12 spec annotation to CompileImportMeta
- Add test for exported function preserving lexical import.meta binding

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

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@units/Goccia.ImportMeta.pas`:
- Around line 118-123: The pin-tracking logic uses bare numeric literals (3, 2,
8) in the block that manipulates PinnedCount and PinnedObjects; extract these
into named constants (e.g., PIN_ENTRY_SIZE = 3, GROW_MULTIPLIER = 2, MIN_GROW =
8) declared in the implementation section and replace the literals in the check,
SetLength calculation, indexing (PinnedObjects[PinnedCount +
0..PIN_ENTRY_SIZE-1] for MetaObject/ResolveHelper/ResolveFunction) and the
Inc(PinnedCount, 3) call with the constant (Inc(PinnedCount, PIN_ENTRY_SIZE)) so
intent is clear and the growth formula is centralized.
- Around line 75-77: The current resolution always prefixes Specifier with
BaseDirectory, which mis-resolves absolute specifiers; update the resolution in
the import.meta.resolve logic so that if Specifier is an absolute path (detect
via platform-appropriate check for IsAbsolutePath/starting with path separator
or drive letter) you call ExpandFileName(Specifier) directly, otherwise call
ExpandFileName(BaseDirectory + Specifier); keep using ResolvedPath and continue
to return TGocciaStringLiteralValue.Create(FilePathToUrl(ResolvedPath)).
🪄 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: bebe94fe-4f1a-4eb1-888d-681e2bafbeff

📥 Commits

Reviewing files that changed from the base of the PR and between b6be039 and 7ebbbaa.

📒 Files selected for processing (5)
  • tests/language/modules/helpers/import-meta-function.js
  • tests/language/modules/import-meta.js
  • units/Goccia.Compiler.Expressions.pas
  • units/Goccia.ImportMeta.pas
  • units/Goccia.VM.pas
✅ Files skipped from review due to trivial changes (1)
  • tests/language/modules/helpers/import-meta-function.js
🚧 Files skipped from review as they are similar to previous changes (2)
  • units/Goccia.Compiler.Expressions.pas
  • tests/language/modules/import-meta.js

Comment thread units/Goccia.ImportMeta.pas Outdated
Comment thread units/Goccia.ImportMeta.pas Outdated
- Handle absolute specifiers in import.meta.resolve correctly: paths
  starting with / or a drive letter now resolve directly instead of
  being concatenated with the module's base directory
- Extract bare numeric literals in pin-tracking logic into named
  constants (PINNED_OBJECTS_PER_MODULE, PINNED_INITIAL_CAPACITY)
- Add test for absolute path resolution

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

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

♻️ Duplicate comments (1)
units/Goccia.ImportMeta.pas (1)

130-135: ⚠️ Potential issue | 🟡 Minor

Extract the remaining growth multiplier literal into a constant.

The resize formula still hardcodes 2 (PinnedCount * 2 + PINNED_INITIAL_CAPACITY). Please promote it to a named constant for consistency with the other pin-tracking constants.

As per coding guidelines: “Extract bare numeric literals in implementation sections into named constants so the value is defined once and the name conveys intent.”

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

In `@units/Goccia.ImportMeta.pas` around lines 130 - 135, The resize logic for
PinnedObjects uses a hardcoded growth multiplier (the literal 2) — extract that
literal into a named constant (e.g. PINNED_GROWTH_MULTIPLIER) in the
implementation section and replace the expression PinnedCount * 2 +
PINNED_INITIAL_CAPACITY with PinnedCount * PINNED_GROWTH_MULTIPLIER +
PINNED_INITIAL_CAPACITY; update any related comments and ensure the new constant
is used consistently with PinnedCount, PINNED_OBJECTS_PER_MODULE, SetLength and
PINNED_INITIAL_CAPACITY.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@units/Goccia.ImportMeta.pas`:
- Around line 47-57: FilePathToUrl returns raw file paths so characters like
spaces, #, ?, and % break URL parsing; after computing AbsolutePath (via
ExpandFileName and normalizing slashes on Windows with StringReplace) you must
percent-encode the path portion (encode each path segment, preserving '/'
separators and unreserved chars per RFC3986) and avoid double-encoding
already-percent-encoded sequences; then prepend the platform-appropriate scheme
('file:///' on Windows, 'file://' on others). Implement this inside
FilePathToUrl so AbsolutePath is URL-encoded before being concatenated into
Result.

---

Duplicate comments:
In `@units/Goccia.ImportMeta.pas`:
- Around line 130-135: The resize logic for PinnedObjects uses a hardcoded
growth multiplier (the literal 2) — extract that literal into a named constant
(e.g. PINNED_GROWTH_MULTIPLIER) in the implementation section and replace the
expression PinnedCount * 2 + PINNED_INITIAL_CAPACITY with PinnedCount *
PINNED_GROWTH_MULTIPLIER + PINNED_INITIAL_CAPACITY; update any related comments
and ensure the new constant is used consistently with PinnedCount,
PINNED_OBJECTS_PER_MODULE, SetLength and PINNED_INITIAL_CAPACITY.
🪄 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: eb5060ee-2c67-4c0b-a807-3b69695c2711

📥 Commits

Reviewing files that changed from the base of the PR and between 7ebbbaa and 6ae31e3.

📒 Files selected for processing (2)
  • tests/language/modules/import-meta.js
  • units/Goccia.ImportMeta.pas
✅ Files skipped from review due to trivial changes (1)
  • tests/language/modules/import-meta.js

Comment thread units/Goccia.ImportMeta.pas
- Add RFC 3986 §2.3 percent-encoding to FilePathToUrl so paths with
  spaces, #, ?, % and other reserved characters produce valid URLs
  (e.g. "file:///path%20with%20spaces/file%231.js")
- Extract the remaining bare literal 2 into PINNED_GROWTH_MULTIPLIER
- Add tests for percent-encoding in resolve and url properties

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

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

♻️ Duplicate comments (1)
units/Goccia.ImportMeta.pas (1)

73-76: ⚠️ Potential issue | 🟠 Major

Handle Windows rooted and UNC paths as absolute in both resolve and URL emission.

Line [102]-[109] only treat / and <drive>: as absolute. Windows rooted (\foo\bar.js) and UNC (\\server\share\file.js) paths can fall into the relative branch and resolve incorrectly.
Line [75] also always prepends file:///, which produces malformed UNC URLs (file://///server/...).

🔧 Proposed fix
 function TGocciaImportMetaResolveHelper.Resolve(
   const AArgs: TGocciaArgumentsCollection;
   const AThisValue: TGocciaValue): TGocciaValue;
 var
   Specifier, BaseDirectory, ResolvedPath: string;
 begin
@@
-  if (Length(Specifier) > 0) and ((Specifier[1] = '/') or
-     (Length(Specifier) >= 2) and (Specifier[2] = ':')) then
+  if (ExtractFileDrive(Specifier) <> '') or
+     ((Specifier <> '') and (Specifier[1] in ['/', '\'])) then
     ResolvedPath := ExpandFileName(Specifier)
   else
   begin
@@
 function FilePathToUrl(const AFilePath: string): string;
 var
   AbsolutePath: string;
 begin
   AbsolutePath := ExpandFileName(AFilePath);
   {$IFDEF MSWINDOWS}
   AbsolutePath := StringReplace(AbsolutePath, '\', '/', [rfReplaceAll]);
-  Result := 'file:///' + PercentEncodePath(AbsolutePath);
+  if (Length(AbsolutePath) >= 2) and (AbsolutePath[1] = '/') and (AbsolutePath[2] = '/') then
+    Result := 'file:' + PercentEncodePath(AbsolutePath) // UNC: //server/share -> file://server/share
+  else
+    Result := 'file:///' + PercentEncodePath(AbsolutePath);
   {$ELSE}
   Result := 'file://' + PercentEncodePath(AbsolutePath);
   {$ENDIF}
 end;

Also applies to: 102-109

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

In `@units/Goccia.ImportMeta.pas` around lines 73 - 76, Treat Windows rooted paths
(starting with '\' ) and UNC paths (starting with '\\') as absolute in both the
path resolution logic and URL emission: update the absolute-path check in the
resolver (the code handling '/' and '<drive>:' currently around the block at
lines ~102-109) to also consider paths beginning with '\' and '\\' as absolute,
and in the URL emission code that builds Result := 'file:///' +
PercentEncodePath(AbsolutePath) (using AbsolutePath and PercentEncodePath)
detect UNC paths and emit a correct file URL (e.g., 'file://server/share/...'
for '\\server\share\file' by stripping the leading backslashes and not
prepending an extra slash, and for rooted local paths use 'file:///' +
PercentEncodePath with backslashes normalized to '/'). Ensure backslashes are
normalized to '/' before percent-encoding.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@units/Goccia.ImportMeta.pas`:
- Around line 73-76: Treat Windows rooted paths (starting with '\' ) and UNC
paths (starting with '\\') as absolute in both the path resolution logic and URL
emission: update the absolute-path check in the resolver (the code handling '/'
and '<drive>:' currently around the block at lines ~102-109) to also consider
paths beginning with '\' and '\\' as absolute, and in the URL emission code that
builds Result := 'file:///' + PercentEncodePath(AbsolutePath) (using
AbsolutePath and PercentEncodePath) detect UNC paths and emit a correct file URL
(e.g., 'file://server/share/...' for '\\server\share\file' by stripping the
leading backslashes and not prepending an extra slash, and for rooted local
paths use 'file:///' + PercentEncodePath with backslashes normalized to '/').
Ensure backslashes are normalized to '/' before percent-encoding.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: fc8480a8-f57d-44b2-895c-a45411cfc6d8

📥 Commits

Reviewing files that changed from the base of the PR and between 6ae31e3 and 274bdd1.

📒 Files selected for processing (2)
  • tests/language/modules/import-meta.js
  • units/Goccia.ImportMeta.pas
✅ Files skipped from review due to trivial changes (1)
  • tests/language/modules/import-meta.js

- Detect backslash-rooted (\path) and UNC (\\server\share) specifiers
  as absolute in import.meta.resolve
- Emit correct RFC 8089 §2 UNC file URLs (file://server/share/...)
  instead of the malformed file://///server/share/...

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

Both Windows path issues from the latest review are addressed in c0c1ac3:

  1. Resolver absolute-path check\path and \\server\share are now detected as absolute (added Specifier[1] = '' to the check alongside / and X:)
  2. UNC URL emission — After normalizing backslashes to /, paths starting with // emit file://server/share/... (per RFC 8089 §2) instead of the malformed file://///server/...

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

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

93-94: Normalize ES spec annotations to the required exact signature format

Line 93 and Line 119 use descriptive prose. Please switch these to the required exact format: // ESYYYY §X.Y.Z SpecMethodName(specParams) (and keep step-level annotations in-body where relevant).

As per coding guidelines, **/*.pas: Add ECMAScript spec annotations in the format // ESYYYY §X.Y.Z SpecMethodName(specParams) immediately above function/method bodies implementing ES-specified behavior, using the exact method name and parameter list from the spec's pseudo-code; and **/*.pas: When implementing an ECMAScript-specified feature, add spec annotations above each function body and at key algorithm steps within the body.

Also applies to: 119-120

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

In `@units/Goccia.ImportMeta.pas` around lines 93 - 94, Replace the descriptive
prose spec comments above the implementation(s) with the exact spec-annotation
format; for the Resolve method change the comment to use the canonical spec
method and parameter list like "// ES2026 §13.3.12.1.1
HostGetImportMetaProperties(specifier)" immediately above
TGocciaImportMetaResolveHelper.Resolve, and likewise update the other occurrence
(lines ~119-120) to the exact "// ES2026 §X.Y.Z SpecMethodName(params)" form
that matches the ECMAScript pseudo-code name and parameter list for that
implementation.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@units/Goccia.ImportMeta.pas`:
- Around line 93-94: Replace the descriptive prose spec comments above the
implementation(s) with the exact spec-annotation format; for the Resolve method
change the comment to use the canonical spec method and parameter list like "//
ES2026 §13.3.12.1.1 HostGetImportMetaProperties(specifier)" immediately above
TGocciaImportMetaResolveHelper.Resolve, and likewise update the other occurrence
(lines ~119-120) to the exact "// ES2026 §X.Y.Z SpecMethodName(params)" form
that matches the ECMAScript pseudo-code name and parameter list for that
implementation.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 3903e4db-9587-4ecd-a730-a96e5adf7abf

📥 Commits

Reviewing files that changed from the base of the PR and between 274bdd1 and c0c1ac3.

📒 Files selected for processing (1)
  • units/Goccia.ImportMeta.pas

Align ES2026 annotations with the codebase convention of
"// ESYYYY §X.Y.Z SpecMethodName(specParams)":
- HostGetImportMetaProperties(moduleRecord) for the resolve helper
- ImportMeta : import . meta for the evaluation entry point

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

Spec annotation format fixed in 455724f. All import.meta annotations now use the canonical // ES2026 §X.Y.Z SpecMethodName(specParams) format:

  • HostGetImportMetaProperties(moduleRecord) for the resolve helper and host-property steps
  • ImportMeta : import . meta for the evaluation entry points (matching the spec production)

@frostney frostney merged commit e4e09c5 into main Apr 11, 2026
9 checks passed
@frostney frostney deleted the t3code/implement-import-meta branch April 11, 2026 14:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation new feature New feature or request spec compliance Mismatch against official JavaScript/TypeScript specification

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant