[dotnet] [bidi] JsonSerializerContext instance per module by nvborisenko · Pull Request #16649 · SeleniumHQ/selenium
User description
Preparation for separate JsonSerializerContext per each Module.
💥 What does this PR do?
- Hide public
DefaultJsonOptions()inBiDiclass - Each module has its own one-time setup context avoiding casting
- Don't share
JsonOptionsacross modules, meaning each module may modify options (like adding custom converters)
🔄 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)
PR Type
Enhancement
Description
-
Refactor JSON context initialization to per-module pattern
-
Hide
GetJsonOptions()as internal method in BiDi class -
Replace
CreateJsonContext()withInitialize()void method -
Simplify module creation by removing JsonOptions parameter passing
-
Each module now manages its own JsonSerializerContext instance
Diagram Walkthrough
flowchart LR
BiDi["BiDi class<br/>GetJsonOptions internal"]
Module["Module base class<br/>Initialize abstract method"]
Modules["All modules<br/>BrowserModule, NetworkModule, etc"]
BiDi -- "calls Initialize" --> Module
Module -- "implements Initialize" --> Modules
Modules -- "creates _jsonContext" --> Modules
File Walkthrough
| Relevant files | |||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Refactoring | 15 files
|
PR Compliance Guide 🔍
Below is a summary of compliance checks for this PR:
| Security Compliance | |
| 🟢 | No security concerns identifiedNo security vulnerabilities detected by AI analysis. Human verification advised for critical code. |
| Ticket Compliance | |
| ⚪ | 🎫 No ticket provided
|
| Codebase Duplication Compliance | |
| ⚪ | Codebase context is not definedFollow the guide to enable codebase context checks. |
| Custom Compliance | |
| 🟢 |
Generic: Meaningful Naming and Self-Documenting CodeObjective: Ensure all identifiers clearly express their purpose and intent, making code Status: Passed
|
Generic: Secure Error HandlingObjective: To prevent the leakage of sensitive system information through error messages while Status: Passed
| |
Generic: Secure Logging PracticesObjective: To ensure logs are useful for debugging and auditing without exposing sensitive Status: Passed
| |
| ⚪ | Generic: Comprehensive Audit TrailsObjective: To create a detailed and reliable record of critical system actions for security analysis Status: Referred Codepublic async Task<ProvideResponseResult> ProvideResponseAsync(Request request, ProvideResponseOptions? options = null) { var @params = new ProvideResponseParameters(request, options?.Body, options?.Cookies, options?.Headers, options?.ReasonPhrase, options?.StatusCode); return await Broker.ExecuteCommandAsync(new ProvideResponseCommand(@params), options, _jsonContext.ProvideResponseCommand, _jsonContext.ProvideResponseResult).ConfigureAwait(false); } public async Task<ContinueWithAuthResult> ContinueWithAuthAsync(Request request, AuthCredentials credentials, ContinueWithAuthCredentialsOptions? options = null) { return await Broker.ExecuteCommandAsync(new ContinueWithAuthCommand(new ContinueWithAuthCredentials(request, credentials)), options, _jsonContext.ContinueWithAuthCommand, _jsonContext.ContinueWithAuthResult).ConfigureAwait(false); } public async Task<ContinueWithAuthResult> ContinueWithAuthAsync(Request request, ContinueWithAuthDefaultCredentialsOptions? options = null) { return await Broker.ExecuteCommandAsync(new ContinueWithAuthCommand(new ContinueWithAuthDefaultCredentials(request)), options, _jsonContext.ContinueWithAuthCommand, _jsonContext.ContinueWithAuthResult).ConfigureAwait(false); } public async Task<ContinueWithAuthResult> ContinueWithAuthAsync(Request request, ContinueWithAuthCancelCredentialsOptions? options = null) { return await Broker.ExecuteCommandAsync(new ContinueWithAuthCommand(new ContinueWithAuthCancelCredentials(request)), options, _jsonContext.ContinueWithAuthCommand, _jsonContext.ContinueWithAuthResult).ConfigureAwait(false); } ... (clipped 50 lines)
|
Generic: Robust Error Handling and Edge Case ManagementObjective: Ensure comprehensive error handling that provides meaningful context and graceful Status: Referred Codepublic static PermissionsModule AsPermissions(this BiDi bidi) { if (bidi is null) { throw new ArgumentNullException(nameof(bidi)); } return Module.Create<PermissionsModule>(bidi); }
| |
Generic: Security-First Input Validation and Data HandlingObjective: Ensure all data inputs are validated, sanitized, and handled securely to prevent Status: Referred Codeprotected abstract void Initialize(JsonSerializerOptions options); public static TModule Create<TModule>(BiDi bidi) where TModule : Module, new() { TModule module = new() { Broker = bidi.Broker, }; module.Initialize(bidi.GetJsonOptions()); return module; }
| |
| |
Compliance status legend
🟢 - Fully Compliant🟡 - Partial Compliant
🔴 - Not Compliant
⚪ - Requires Further Human Verification
🏷️ - Compliance label
PR Code Suggestions ✨
Explore these optional code suggestions:
| Category | Suggestion | Impact |
| General |
Cache JsonSerializerOptions to improve performanceCache the dotnet/src/webdriver/BiDi/BiDi.cs [96-121] +private JsonSerializerOptions? _jsonOptions; + internal JsonSerializerOptions GetJsonOptions() { - return new JsonSerializerOptions + if (_jsonOptions is null) { - PropertyNameCaseInsensitive = true, - PropertyNamingPolicy = JsonNamingPolicy.CamelCase, - DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull, + _jsonOptions = new JsonSerializerOptions + { + PropertyNameCaseInsensitive = true, + PropertyNamingPolicy = JsonNamingPolicy.CamelCase, + DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull, - // BiDi returns special numbers such as "NaN" as strings - // Additionally, -0 is returned as a string "-0" - NumberHandling = JsonNumberHandling.AllowNamedFloatingPointLiterals | JsonNumberHandling.AllowReadingFromString, - Converters = - { - new BrowsingContextConverter(this), - new BrowserUserContextConverter(this), - new CollectorConverter(this), - new InterceptConverter(this), - new HandleConverter(this), - new InternalIdConverter(this), - new PreloadScriptConverter(this), - new RealmConverter(this), - new DateTimeOffsetConverter(), - new WebExtensionConverter(this), - } - }; + // BiDi returns special numbers such as "NaN" as strings + // Additionally, -0 is returned as a string "-0" + NumberHandling = JsonNumberHandling.AllowNamedFloatingPointLiterals | JsonNumberHandling.AllowReadingFromString, + Converters = + { + new BrowsingContextConverter(this), + new BrowserUserContextConverter(this), + new CollectorConverter(this), + new InterceptConverter(this), + new HandleConverter(this), + new InternalIdConverter(this), + new PreloadScriptConverter(this), + new RealmConverter(this), + new DateTimeOffsetConverter(), + new WebExtensionConverter(this), + } + }; + } + + return _jsonOptions; }
Suggestion importance[1-10]: 6__ Why: The suggestion correctly identifies that | Low |
| ||
nvborisenko
changed the title
[dotnet] [bidi] JsonContext instance per module
[dotnet] [bidi] JsonSerializerContext instance per module
Perfect! Now we can think about how to split big BiDiJsonSerializerContext into smaller chunks per module, given that modules are cross-referenced.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters