Skip to content

[dotnet] [bidi] Immutable user facing collections#17533

Merged
nvborisenko merged 9 commits into
SeleniumHQ:trunkfrom
nvborisenko:bidi-immutability
May 20, 2026
Merged

[dotnet] [bidi] Immutable user facing collections#17533
nvborisenko merged 9 commits into
SeleniumHQ:trunkfrom
nvborisenko:bidi-immutability

Conversation

@nvborisenko
Copy link
Copy Markdown
Member

@nvborisenko nvborisenko commented May 20, 2026

Use ImmutableArray<T> instead of IEnumerable<T> and IReadOnlyList<T>.

Now it is immutable everywhere by contract. Eliminating the following cases at compilation level:

Before:

List<string> args = ["a", "b"];
bidi.CallFunctionAsync(.... , Args = args);
args.Clear(); // BUG, collection was modified during serialization

After:

List<string> args = ["a", "b"];
bidi.CallFunctionAsync(.... , Args = [..args]); // It is always a copy
args.Clear(); // OK, it it not that collection you put into command

🔗 Related Issues

Contributes to #16095

💥 What does this PR do?

Strict intention of contract.

🤖 AI assistance Thanks to @RenderMichael and @YevgeniyShunevych

  • No substantial AI assistance used
  • AI assisted (complete below)
    • Tool(s):
    • What was generated:
    • I reviewed all AI output and can explain the change

🔄 Types of changes

  • Cleanup (formatting, renaming)
  • Bug fix (backwards compatible)
  • New feature (non-breaking change which adds functionality and tests!)
  • Breaking change (fix or feature that would cause existing functionality to change)

@qodo-code-review
Copy link
Copy Markdown
Contributor

Review Summary by Qodo

Replace mutable collections with ImmutableArray for BiDi API immutability

✨ Enhancement

Grey Divider

Walkthroughs

Description
• Replace mutable collections with ImmutableArray throughout BiDi API
• Enforce immutability contracts at compilation level for user-facing collections
• Prevent accidental collection mutations during serialization and processing
• Update test assertions to use .Length instead of .Count for immutable arrays
Diagram
flowchart LR
  A["IEnumerable/IReadOnlyList"] -->|"Replace with"| B["ImmutableArray"]
  B -->|"Guarantees"| C["Immutability by contract"]
  C -->|"Prevents"| D["Accidental mutations"]
  E["GlobalUsings.cs"] -->|"Add import"| B
  F["Selenium.WebDriver.csproj"] -->|"Add dependency"| G["System.Collections.Immutable"]

Loading

File Changes

1. dotnet/src/webdriver/Properties/GlobalUsings.cs Dependencies +1/-0

Add System.Collections.Immutable global using

dotnet/src/webdriver/Properties/GlobalUsings.cs


2. dotnet/src/webdriver/Selenium.WebDriver.csproj Dependencies +1/-0

Add System.Collections.Immutable NuGet package

dotnet/src/webdriver/Selenium.WebDriver.csproj


3. dotnet/src/webdriver/BiDi/BiDi.cs ✨ Enhancement +3/-3

Replace IEnumerable with ImmutableArray in Subscribe/Stream methods

dotnet/src/webdriver/BiDi/BiDi.cs


View more (78)
4. dotnet/src/webdriver/BiDi/IBiDi.cs ✨ Enhancement +3/-3

Update interface signatures to use ImmutableArray

dotnet/src/webdriver/BiDi/IBiDi.cs


5. dotnet/src/webdriver/BiDi/EventDispatcher.cs ✨ Enhancement +11/-11

Replace IEnumerable with ImmutableArray in event subscription

dotnet/src/webdriver/BiDi/EventDispatcher.cs


6. dotnet/src/webdriver/BiDi/Browser/GetClientWindows.cs ✨ Enhancement +1/-1

Replace IReadOnlyList with ImmutableArray for ClientWindows

dotnet/src/webdriver/BiDi/Browser/GetClientWindows.cs


7. dotnet/src/webdriver/BiDi/Browser/GetUserContexts.cs ✨ Enhancement +1/-1

Replace IReadOnlyList with ImmutableArray for UserContexts

dotnet/src/webdriver/BiDi/Browser/GetUserContexts.cs


8. dotnet/src/webdriver/BiDi/Browser/SetDownloadBehavior.cs ✨ Enhancement +2/-2

Replace IEnumerable with ImmutableArray for UserContexts

dotnet/src/webdriver/BiDi/Browser/SetDownloadBehavior.cs


9. dotnet/src/webdriver/BiDi/BrowsingContext/BrowsingContextInputModule.cs ✨ Enhancement +2/-2

Replace IEnumerable with ImmutableArray for actions and files

dotnet/src/webdriver/BiDi/BrowsingContext/BrowsingContextInputModule.cs


10. dotnet/src/webdriver/BiDi/BrowsingContext/BrowsingContextNetworkModule.cs ✨ Enhancement +1/-1

Replace IEnumerable with ImmutableArray for DataTypes

dotnet/src/webdriver/BiDi/BrowsingContext/BrowsingContextNetworkModule.cs


11. dotnet/src/webdriver/BiDi/BrowsingContext/IBrowsingContextInputModule.cs ✨ Enhancement +2/-2

Update interface to use ImmutableArray for actions/files

dotnet/src/webdriver/BiDi/BrowsingContext/IBrowsingContextInputModule.cs


12. dotnet/src/webdriver/BiDi/BrowsingContext/IBrowsingContextNetworkModule.cs ✨ Enhancement +1/-1

Update interface to use ImmutableArray for DataTypes

dotnet/src/webdriver/BiDi/BrowsingContext/IBrowsingContextNetworkModule.cs


13. dotnet/src/webdriver/BiDi/BrowsingContext/Info.cs ✨ Enhancement +1/-1

Replace IReadOnlyList with ImmutableArray for Children

dotnet/src/webdriver/BiDi/BrowsingContext/Info.cs


14. dotnet/src/webdriver/BiDi/BrowsingContext/ContextCreatedEvent.cs ✨ Enhancement +1/-1

Replace IReadOnlyList with ImmutableArray for Children

dotnet/src/webdriver/BiDi/BrowsingContext/ContextCreatedEvent.cs


15. dotnet/src/webdriver/BiDi/BrowsingContext/ContextDestroyedEvent.cs ✨ Enhancement +1/-1

Replace IReadOnlyList with ImmutableArray for Children

dotnet/src/webdriver/BiDi/BrowsingContext/ContextDestroyedEvent.cs


16. dotnet/src/webdriver/BiDi/BrowsingContext/GetTree.cs ✨ Enhancement +1/-1

Replace IReadOnlyList with ImmutableArray for Contexts

dotnet/src/webdriver/BiDi/BrowsingContext/GetTree.cs


17. dotnet/src/webdriver/BiDi/BrowsingContext/LocateNodes.cs ✨ Enhancement +3/-3

Replace IEnumerable/IReadOnlyList with ImmutableArray

dotnet/src/webdriver/BiDi/BrowsingContext/LocateNodes.cs


18. dotnet/src/webdriver/BiDi/BrowsingContext/Print.cs ✨ Enhancement +2/-2

Replace IEnumerable with ImmutableArray for PageRanges

dotnet/src/webdriver/BiDi/BrowsingContext/Print.cs


19. dotnet/src/webdriver/BiDi/BrowsingContext/SetViewport.cs ✨ Enhancement +2/-2

Replace IEnumerable with ImmutableArray for UserContexts

dotnet/src/webdriver/BiDi/BrowsingContext/SetViewport.cs


20. dotnet/src/webdriver/BiDi/Emulation/SetForcedColorsModeThemeOverride.cs ✨ Enhancement +3/-3

Replace IEnumerable with ImmutableArray for contexts

dotnet/src/webdriver/BiDi/Emulation/SetForcedColorsModeThemeOverride.cs


21. dotnet/src/webdriver/BiDi/Emulation/SetGeolocationOverride.cs ✨ Enhancement +5/-5

Replace IEnumerable with ImmutableArray throughout

dotnet/src/webdriver/BiDi/Emulation/SetGeolocationOverride.cs


22. dotnet/src/webdriver/BiDi/Emulation/SetLocaleOverride.cs ✨ Enhancement +3/-3

Replace IEnumerable with ImmutableArray for contexts

dotnet/src/webdriver/BiDi/Emulation/SetLocaleOverride.cs


23. dotnet/src/webdriver/BiDi/Emulation/SetNetworkConditions.cs ✨ Enhancement +3/-3

Replace IEnumerable with ImmutableArray for contexts

dotnet/src/webdriver/BiDi/Emulation/SetNetworkConditions.cs


24. dotnet/src/webdriver/BiDi/Emulation/SetScreenOrientationOverride.cs ✨ Enhancement +3/-3

Replace IEnumerable with ImmutableArray for contexts

dotnet/src/webdriver/BiDi/Emulation/SetScreenOrientationOverride.cs


25. dotnet/src/webdriver/BiDi/Emulation/SetScreenSettingsOverride.cs ✨ Enhancement +3/-3

Replace IEnumerable with ImmutableArray for contexts

dotnet/src/webdriver/BiDi/Emulation/SetScreenSettingsOverride.cs


26. dotnet/src/webdriver/BiDi/Emulation/SetScriptingEnabled.cs ✨ Enhancement +3/-3

Replace IEnumerable with ImmutableArray for contexts

dotnet/src/webdriver/BiDi/Emulation/SetScriptingEnabled.cs


27. dotnet/src/webdriver/BiDi/Emulation/SetScrollbarTypeOverride.cs ✨ Enhancement +3/-3

Replace IEnumerable with ImmutableArray for contexts

dotnet/src/webdriver/BiDi/Emulation/SetScrollbarTypeOverride.cs


28. dotnet/src/webdriver/BiDi/Emulation/SetTimezoneOverride.cs ✨ Enhancement +3/-3

Replace IEnumerable with ImmutableArray for contexts

dotnet/src/webdriver/BiDi/Emulation/SetTimezoneOverride.cs


29. dotnet/src/webdriver/BiDi/Emulation/SetTouchOverride.cs ✨ Enhancement +3/-3

Replace IEnumerable with ImmutableArray for contexts

dotnet/src/webdriver/BiDi/Emulation/SetTouchOverride.cs


30. dotnet/src/webdriver/BiDi/Emulation/SetUserAgentOverride.cs ✨ Enhancement +3/-3

Replace IEnumerable with ImmutableArray for contexts

dotnet/src/webdriver/BiDi/Emulation/SetUserAgentOverride.cs


31. dotnet/src/webdriver/BiDi/Input/IInputModule.cs ✨ Enhancement +2/-2

Update interface to use ImmutableArray for actions/files

dotnet/src/webdriver/BiDi/Input/IInputModule.cs


32. dotnet/src/webdriver/BiDi/Input/InputModule.cs ✨ Enhancement +2/-2

Replace IEnumerable with ImmutableArray in implementations

dotnet/src/webdriver/BiDi/Input/InputModule.cs


33. dotnet/src/webdriver/BiDi/Input/PerformActions.cs ✨ Enhancement +1/-1

Replace IEnumerable with ImmutableArray for Actions

dotnet/src/webdriver/BiDi/Input/PerformActions.cs


34. dotnet/src/webdriver/BiDi/Input/SetFiles.cs ✨ Enhancement +1/-1

Replace IEnumerable with ImmutableArray for Files

dotnet/src/webdriver/BiDi/Input/SetFiles.cs


35. dotnet/src/webdriver/BiDi/Input/SourceActions.cs ✨ Enhancement +5/-5

Replace IEnumerable with ImmutableArray for all action types

dotnet/src/webdriver/BiDi/Input/SourceActions.cs


36. dotnet/src/webdriver/BiDi/Log/EntryAddedEvent.cs ✨ Enhancement +2/-2

Replace IReadOnlyList with ImmutableArray for Args

dotnet/src/webdriver/BiDi/Log/EntryAddedEvent.cs


37. dotnet/src/webdriver/BiDi/Network/AddDataCollector.cs ✨ Enhancement +4/-4

Replace IEnumerable with ImmutableArray for collections

dotnet/src/webdriver/BiDi/Network/AddDataCollector.cs


38. dotnet/src/webdriver/BiDi/Network/AddIntercept.cs ✨ Enhancement +4/-4

Replace IEnumerable with ImmutableArray for phases/patterns

dotnet/src/webdriver/BiDi/Network/AddIntercept.cs


39. dotnet/src/webdriver/BiDi/Network/AuthRequiredEvent.cs ✨ Enhancement +2/-2

Replace IReadOnlyList with ImmutableArray for Intercepts

dotnet/src/webdriver/BiDi/Network/AuthRequiredEvent.cs


40. dotnet/src/webdriver/BiDi/Network/BaseParameters.cs ✨ Enhancement +1/-1

Replace IReadOnlyList with ImmutableArray for Intercepts

dotnet/src/webdriver/BiDi/Network/BaseParameters.cs


41. dotnet/src/webdriver/BiDi/Network/BeforeRequestSentEvent.cs ✨ Enhancement +2/-2

Replace IReadOnlyList with ImmutableArray for Intercepts

dotnet/src/webdriver/BiDi/Network/BeforeRequestSentEvent.cs


42. dotnet/src/webdriver/BiDi/Network/ContinueRequest.cs ✨ Enhancement +3/-3

Replace IEnumerable with ImmutableArray for headers/cookies

dotnet/src/webdriver/BiDi/Network/ContinueRequest.cs


43. dotnet/src/webdriver/BiDi/Network/ContinueResponse.cs ✨ Enhancement +4/-4

Replace IEnumerable with ImmutableArray for response data

dotnet/src/webdriver/BiDi/Network/ContinueResponse.cs


44. dotnet/src/webdriver/BiDi/Network/FetchErrorEvent.cs ✨ Enhancement +2/-2

Replace IReadOnlyList with ImmutableArray for Intercepts

dotnet/src/webdriver/BiDi/Network/FetchErrorEvent.cs


45. dotnet/src/webdriver/BiDi/Network/INetworkModule.cs ✨ Enhancement +3/-3

Update interface to use ImmutableArray for collections

dotnet/src/webdriver/BiDi/Network/INetworkModule.cs


46. dotnet/src/webdriver/BiDi/Network/NetworkModule.cs ✨ Enhancement +3/-3

Replace IEnumerable with ImmutableArray in implementations

dotnet/src/webdriver/BiDi/Network/NetworkModule.cs


47. dotnet/src/webdriver/BiDi/Network/ProvideResponse.cs ✨ Enhancement +3/-3

Replace IEnumerable with ImmutableArray for response data

dotnet/src/webdriver/BiDi/Network/ProvideResponse.cs


48. dotnet/src/webdriver/BiDi/Network/RequestData.cs ✨ Enhancement +2/-2

Replace IReadOnlyList with ImmutableArray for headers/cookies

dotnet/src/webdriver/BiDi/Network/RequestData.cs


49. dotnet/src/webdriver/BiDi/Network/ResponseCompletedEvent.cs ✨ Enhancement +2/-2

Replace IReadOnlyList with ImmutableArray for Intercepts

dotnet/src/webdriver/BiDi/Network/ResponseCompletedEvent.cs


50. dotnet/src/webdriver/BiDi/Network/ResponseData.cs ✨ Enhancement +2/-2

Replace IReadOnlyList with ImmutableArray for headers/challenges

dotnet/src/webdriver/BiDi/Network/ResponseData.cs


51. dotnet/src/webdriver/BiDi/Network/ResponseStartedEvent.cs ✨ Enhancement +2/-2

Replace IReadOnlyList with ImmutableArray for Intercepts

dotnet/src/webdriver/BiDi/Network/ResponseStartedEvent.cs


52. dotnet/src/webdriver/BiDi/Network/SetCacheBehavior.cs ✨ Enhancement +2/-2

Replace IEnumerable with ImmutableArray for Contexts

dotnet/src/webdriver/BiDi/Network/SetCacheBehavior.cs


53. dotnet/src/webdriver/BiDi/Network/SetExtraHeaders.cs ✨ Enhancement +3/-3

Replace IEnumerable with ImmutableArray for headers

dotnet/src/webdriver/BiDi/Network/SetExtraHeaders.cs


54. dotnet/src/webdriver/BiDi/Script/AddPreloadScript.cs ✨ Enhancement +5/-5

Replace IEnumerable with ImmutableArray for arguments/contexts

dotnet/src/webdriver/BiDi/Script/AddPreloadScript.cs


55. dotnet/src/webdriver/BiDi/Script/CallFunction.cs ✨ Enhancement +2/-2

Replace IEnumerable with ImmutableArray for Arguments

dotnet/src/webdriver/BiDi/Script/CallFunction.cs


56. dotnet/src/webdriver/BiDi/Script/Disown.cs ✨ Enhancement +1/-1

Replace IEnumerable with ImmutableArray for Handles

dotnet/src/webdriver/BiDi/Script/Disown.cs


57. dotnet/src/webdriver/BiDi/Script/GetRealms.cs ✨ Enhancement +1/-1

Replace IReadOnlyList with ImmutableArray for Realms

dotnet/src/webdriver/BiDi/Script/GetRealms.cs


58. dotnet/src/webdriver/BiDi/Script/IScriptModule.cs ✨ Enhancement +1/-1

Update interface to use ImmutableArray for Handles

dotnet/src/webdriver/BiDi/Script/IScriptModule.cs


59. dotnet/src/webdriver/BiDi/Script/LocalValue.cs ✨ Enhancement +10/-10

Replace IEnumerable with ImmutableArray in LocalValue types

dotnet/src/webdriver/BiDi/Script/LocalValue.cs


60. dotnet/src/webdriver/BiDi/Script/NodeProperties.cs ✨ Enhancement +1/-1

Replace IReadOnlyList/IReadOnlyDictionary with Immutable types

dotnet/src/webdriver/BiDi/Script/NodeProperties.cs


61. dotnet/src/webdriver/BiDi/Script/RealmInfo.cs ✨ Enhancement +1/-1

Replace IReadOnlyList with ImmutableArray for Owners

dotnet/src/webdriver/BiDi/Script/RealmInfo.cs


62. dotnet/src/webdriver/BiDi/Script/RealmInfoEvent.cs ✨ Enhancement +1/-1

Replace IReadOnlyList with ImmutableArray for Owners

dotnet/src/webdriver/BiDi/Script/RealmInfoEvent.cs


63. dotnet/src/webdriver/BiDi/Script/RemoteValue.cs ✨ Enhancement +16/-16

Replace IEnumerable/IReadOnlyList with ImmutableArray throughout

dotnet/src/webdriver/BiDi/Script/RemoteValue.cs


64. dotnet/src/webdriver/BiDi/Script/ScriptModule.cs ✨ Enhancement +1/-1

Replace IEnumerable with ImmutableArray for Handles

dotnet/src/webdriver/BiDi/Script/ScriptModule.cs


65. dotnet/src/webdriver/BiDi/Script/StackTrace.cs ✨ Enhancement +1/-1

Replace IReadOnlyList with ImmutableArray for CallFrames

dotnet/src/webdriver/BiDi/Script/StackTrace.cs


66. dotnet/src/webdriver/BiDi/Session/CapabilitiesRequest.cs ✨ Enhancement +1/-1

Replace IEnumerable with ImmutableArray for FirstMatch

dotnet/src/webdriver/BiDi/Session/CapabilitiesRequest.cs


67. dotnet/src/webdriver/BiDi/Session/ISessionModule.cs ✨ Enhancement +2/-2

Update interface to use ImmutableArray for events/subscriptions

dotnet/src/webdriver/BiDi/Session/ISessionModule.cs


68. dotnet/src/webdriver/BiDi/Session/ProxyConfiguration.cs ✨ Enhancement +1/-1

Replace IEnumerable with ImmutableArray for NoProxy

dotnet/src/webdriver/BiDi/Session/ProxyConfiguration.cs


69. dotnet/src/webdriver/BiDi/Session/SessionModule.cs ✨ Enhancement +2/-2

Replace IEnumerable with ImmutableArray in implementations

dotnet/src/webdriver/BiDi/Session/SessionModule.cs


70. dotnet/src/webdriver/BiDi/Session/Subscribe.cs ✨ Enhancement +3/-3

Replace IEnumerable with ImmutableArray for events/contexts

dotnet/src/webdriver/BiDi/Session/Subscribe.cs


71. dotnet/src/webdriver/BiDi/Session/Unsubscribe.cs ✨ Enhancement +1/-1

Replace IEnumerable with ImmutableArray for Subscriptions

dotnet/src/webdriver/BiDi/Session/Unsubscribe.cs


72. dotnet/src/webdriver/BiDi/Storage/GetCookies.cs ✨ Enhancement +1/-1

Replace IReadOnlyList with ImmutableArray for Cookies

dotnet/src/webdriver/BiDi/Storage/GetCookies.cs


73. dotnet/test/webdriver/BiDi/Browser/BrowserTests.cs 🧪 Tests +2/-2

Update test assertions to use Length instead of Count

dotnet/test/webdriver/BiDi/Browser/BrowserTests.cs


74. dotnet/test/webdriver/BiDi/BrowsingContext/BrowsingContextTests.cs 🧪 Tests +6/-5

Update test assertions to use Length and .Value property

dotnet/test/webdriver/BiDi/BrowsingContext/BrowsingContextTests.cs


75. dotnet/test/webdriver/BiDi/Log/LogTests.cs 🧪 Tests +1/-2

Update test assertions to use Length instead of Count

dotnet/test/webdriver/BiDi/Log/LogTests.cs


76. dotnet/test/webdriver/BiDi/Network/NetworkEventsTests.cs 🧪 Tests +2/-2

Update test assertions to use Length instead of Count

dotnet/test/webdriver/BiDi/Network/NetworkEventsTests.cs


77. dotnet/test/webdriver/BiDi/Script/CallFunctionParameterTests.cs 🧪 Tests +6/-6

Update test assertions to access .Value property

dotnet/test/webdriver/BiDi/Script/CallFunctionParameterTests.cs


78. dotnet/test/webdriver/BiDi/Script/EvaluateParametersTests.cs 🧪 Tests +2/-2

Update test assertions to access .Value property

dotnet/test/webdriver/BiDi/Script/EvaluateParametersTests.cs


79. dotnet/test/webdriver/BiDi/Script/LocalValueConversionTests.cs 🧪 Tests +1/-1

Update test assertions to use Length instead of Count

dotnet/test/webdriver/BiDi/Script/LocalValueConversionTests.cs


80. dotnet/test/webdriver/BiDi/Script/ScriptCommandsTests.cs 🧪 Tests +2/-2

Update test assertions to use Length instead of Count

dotnet/test/webdriver/BiDi/Script/ScriptCommandsTests.cs


81. dotnet/test/webdriver/BiDi/Storage/StorageTests.cs 🧪 Tests +3/-3

Update test assertions to use Length instead of Count

dotnet/test/webdriver/BiDi/Storage/StorageTests.cs


Grey Divider

Qodo Logo

@qodo-code-review
Copy link
Copy Markdown
Contributor

qodo-code-review Bot commented May 20, 2026

Code Review by Qodo

🐞 Bugs (1) 📘 Rule violations (1) 📎 Requirement gaps (0)

Grey Divider


Action required

1. IBiDi overloads now ImmutableArray 📘 Rule violation ⚙ Maintainability
Description
Public IBiDi method signatures changed from IEnumerable<EventDescriptor> to
ImmutableArray<EventDescriptor>, which is a breaking API change requiring consumer code updates.
This violates the requirement to preserve user-facing API/ABI compatibility.
Code

dotnet/src/webdriver/BiDi/IBiDi.cs[R64-70]

Evidence
PR Compliance ID 15 requires preserving user-facing API/ABI compatibility. The diff shows the public
IBiDi interface removing the prior IEnumerable<EventDescriptor> overloads and replacing them
with ImmutableArray<EventDescriptor>, which will break existing source code at compile time.

AGENTS.md: Preserve API/ABI compatibility for user-facing code
dotnet/src/webdriver/BiDi/IBiDi.cs[64-70]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Public APIs changed from `IEnumerable` to `ImmutableArray`, which is a source-breaking change for existing consumers.

## Issue Context
The PR replaces multiple public API surface parameters with `ImmutableArray<T>`. While beneficial for immutability, this breaks callers that previously passed `IEnumerable<T>`/`IReadOnlyList<T>`.

## Fix Focus Areas
- dotnet/src/webdriver/BiDi/IBiDi.cs[64-70]

## Suggested approach
- Add back overloads that accept the previous types (e.g., `IEnumerable<EventDescriptor>`), and internally materialize to `ImmutableArray` (e.g., `descriptors.ToImmutableArray()` or `[.. descriptors]`).
- Keep the new `ImmutableArray` overloads as the preferred/fast path.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

2. UserContexts not serialized 🐞 Bug ≡ Correctness
Description
SessionModule.SubscribeAsync builds SubscribeParameters without SubscribeOptions.UserContexts,
and Broker.ExecuteAsync serializes only the params object, so UserContexts is silently ignored
for session.subscribe.
Code

dotnet/src/webdriver/BiDi/Session/SessionModule.cs[R47-51]

Evidence
SubscribeOptions exposes UserContexts, and EventDispatcher passes it into the wire subscribe
call, but SessionModule.SubscribeAsync drops it when building SubscribeParameters. Since
Broker.ExecuteAsync serializes only @params and uses options only for timeout, the
UserContexts value can never reach the wire.

dotnet/src/webdriver/BiDi/Session/Subscribe.cs[22-29]
dotnet/src/webdriver/BiDi/Session/SessionModule.cs[47-52]
dotnet/src/webdriver/BiDi/Broker.cs[68-100]
dotnet/src/webdriver/BiDi/EventDispatcher.cs[174-200]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`Session.SubscribeOptions.UserContexts` is never sent to the remote end because `Broker.ExecuteAsync` serializes only the `@params` object, while `SessionModule.SubscribeAsync` only places `options?.Contexts` into `SubscribeParameters`.

### Issue Context
This creates a silent no-op property (`UserContexts`) and makes it impossible to scope `session.subscribe` by user context even though the API surface suggests it is supported.

### Fix Focus Areas
- dotnet/src/webdriver/BiDi/Session/Subscribe.cs[22-29]
- dotnet/src/webdriver/BiDi/Session/SessionModule.cs[47-52]

### Concrete fix
1. Extend `SubscribeParameters` to include `ImmutableArray<Browser.UserContext>? UserContexts`.
2. Update `SessionModule.SubscribeAsync` to pass `options?.UserContexts` into `SubscribeParameters`.
3. Ensure `SessionJsonSerializerContext` continues to source-generate metadata for `SubscribeParameters` (it already references the type; regenerating should pick up the new property).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Advisory comments

3. Useless ImmutableArray null-check ✓ Resolved 🐞 Bug ⚙ Maintainability
Description
BiDi.SubscribeAsync/StreamAsync call ArgumentNullException.ThrowIfNull(descriptors) even though
ImmutableArray<T> is a value type and cannot be null, so this guard never triggers and can mislead
about validation coverage. Callers passing default/empty arrays will fail later with a different
exception path instead of a clear upfront argument validation.
Code

dotnet/src/webdriver/BiDi/BiDi.cs[R104-107]

Evidence
The public API explicitly uses ImmutableArray<EventDescriptor> for the multi-descriptor overloads,
but the implementation still performs a null-check that cannot fail for a struct parameter.

dotnet/src/webdriver/BiDi/BiDi.cs[104-132]
dotnet/src/webdriver/BiDi/IBiDi.cs[64-70]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`ArgumentNullException.ThrowIfNull(descriptors)` is ineffective for `ImmutableArray<T>` parameters because `ImmutableArray<T>` is a struct (non-nullable value type). This can hide the real validation intention and doesn’t provide a clear exception for empty/default arrays.

### Issue Context
The affected APIs are public entry points (`IBiDi` / `BiDi`) for multi-descriptor subscription/stream creation.

### Fix Focus Areas
- Replace `ThrowIfNull(descriptors)` with explicit validation for *default/empty* immutable arrays (e.g., `descriptors.IsDefaultOrEmpty` or `descriptors.Length == 0`) and throw `ArgumentException` with a clear message.
- Apply the same validation to both `SubscribeAsync(... ImmutableArray<EventDescriptor> ...)` overloads and `StreamAsync(... ImmutableArray<EventDescriptor> ...)`.

- dotnet/src/webdriver/BiDi/BiDi.cs[104-132]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Qodo Logo

Comment thread dotnet/src/webdriver/BiDi/IBiDi.cs
@qodo-code-review
Copy link
Copy Markdown
Contributor

qodo-code-review Bot commented May 20, 2026

Persistent review updated to latest commit 447d91d

@qodo-code-review
Copy link
Copy Markdown
Contributor

qodo-code-review Bot commented May 20, 2026

Persistent review updated to latest commit a46247c

Comment thread dotnet/src/webdriver/BiDi/Script/LocalValue.cs Outdated
Comment thread dotnet/src/webdriver/BiDi/Script/LocalValue.cs Outdated
Comment thread dotnet/src/webdriver/BiDi/Script/LocalValue.cs Outdated
@qodo-code-review
Copy link
Copy Markdown
Contributor

qodo-code-review Bot commented May 20, 2026

Persistent review updated to latest commit 142450a

@qodo-code-review
Copy link
Copy Markdown
Contributor

qodo-code-review Bot commented May 20, 2026

Persistent review updated to latest commit b01a2c0

@qodo-code-review
Copy link
Copy Markdown
Contributor

qodo-code-review Bot commented May 20, 2026

Persistent review updated to latest commit 6ded6c1

@nvborisenko nvborisenko merged commit 751ec74 into SeleniumHQ:trunk May 20, 2026
21 checks passed
@nvborisenko nvborisenko deleted the bidi-immutability branch May 20, 2026 21:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

C-dotnet .NET Bindings

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants