[dotnet] [bidi] Fix context aware event handlers by nvborisenko · Pull Request #16787 · SeleniumHQ/selenium
PR Code Suggestions ✨
Explore these optional code suggestions:
| Category | Suggestion | Impact |
| High-level |
Refactor duplicated logic into helpersTo reduce code duplication, create two private helper methods—one for Examples:dotnet/src/webdriver/BiDi/BrowsingContext/BrowsingContext.cs [136-142]return BiDi.BrowsingContext.OnNavigationStartedAsync(async e => { if (e.Context == this) { await handler(e).ConfigureAwait(false); } }, options.WithContext(this)); dotnet/src/webdriver/BiDi/BrowsingContext/BrowsingContext.cs [147-153]return BiDi.BrowsingContext.OnNavigationStartedAsync(e => { if (e.Context == this) { handler(e); } }, options.WithContext(this)); Solution Walkthrough:Before:public Task<Subscription> OnNavigationStartedAsync(Func<NavigationInfo, Task> handler, ...) { return BiDi.BrowsingContext.OnNavigationStartedAsync(async e => { if (e.Context == this) { await handler(e).ConfigureAwait(false); } }, ...); } public Task<Subscription> OnNavigationStartedAsync(Action<NavigationInfo> handler, ...) { return BiDi.BrowsingContext.OnNavigationStartedAsync(e => { if (e.Context == this) { handler(e); } }, ...); } // ... this pattern is repeated for many other event handlers. After:private Action<T> WrapHandler<T>(Action<T> handler) where T : IHasContext { return e => { if (e.Context == this) handler(e); }; } private Func<T, Task> WrapHandler<T>(Func<T, Task> handler) where T : IHasContext { return async e => { if (e.Context == this) await handler(e).ConfigureAwait(false); }; } public Task<Subscription> OnNavigationStartedAsync(Func<NavigationInfo, Task> handler, ...) { return BiDi.BrowsingContext.OnNavigationStartedAsync(WrapHandler(handler), ...); } public Task<Subscription> OnNavigationStartedAsync(Action<NavigationInfo> handler, ...) { return BiDi.BrowsingContext.OnNavigationStartedAsync(WrapHandler(handler), ...); } // ... all other handlers are simplified similarly. Suggestion importance[1-10]: 9__ Why: The suggestion correctly identifies significant code duplication across all modified methods and proposes an excellent refactoring that would centralize the logic, greatly improving code quality and maintainability. | High |
| Possible issue |
Add exception handling to handlersAdd dotnet/src/webdriver/BiDi/BrowsingContext/BrowsingContext.cs [134-154] public Task<Subscription> OnNavigationStartedAsync(Func<NavigationInfo, Task> handler, ContextSubscriptionOptions? options = null)
{
return BiDi.BrowsingContext.OnNavigationStartedAsync(async e =>
{
if (e.Context == this)
{
- await handler(e).ConfigureAwait(false);
+ try
+ {
+ await handler(e).ConfigureAwait(false);
+ }
+ catch
+ {
+ // Ignore exceptions from user-provided handlers.
+ }
}
}, options.WithContext(this));
}
public Task<Subscription> OnNavigationStartedAsync(Action<NavigationInfo> handler, ContextSubscriptionOptions? options = null)
{
return BiDi.BrowsingContext.OnNavigationStartedAsync(e =>
{
if (e.Context == this)
{
- handler(e);
+ try
+ {
+ handler(e);
+ }
+ catch
+ {
+ // Ignore exceptions from user-provided handlers.
+ }
}
}, options.WithContext(this));
}
Suggestion importance[1-10]: 7__ Why: This suggestion correctly identifies that unhandled exceptions in user-provided event handlers can crash the application. Wrapping the handler calls in a | Medium |
validate handler parameterAdd a null check for the dotnet/src/webdriver/BiDi/BrowsingContext/BrowsingContext.cs [134-135] public Task<Subscription> OnNavigationStartedAsync(Func<NavigationInfo, Task> handler, ContextSubscriptionOptions? options = null)
{
+ if (handler is null)
+ {
+ throw new ArgumentNullException(nameof(handler));
+ }
Suggestion importance[1-10]: 6__ Why: This is a good practice for public APIs to validate arguments and fail early. Adding a | Low | |
| Learned best practice |
Extract shared context-filter helperThe PR repeats the same context-filtering wrapper pattern across many event dotnet/src/webdriver/BiDi/BrowsingContext/BrowsingContext.cs [134-154] +private bool IsForThisContext(BrowsingContext? context) => Equals(context, this); + +private Action<T> FilterForThisContext<T>(Action<T> handler, Func<T, BrowsingContext?> getContext) => + e => { if (IsForThisContext(getContext(e))) handler(e); }; + +private Func<T, Task> FilterForThisContext<T>(Func<T, Task> handler, Func<T, BrowsingContext?> getContext) => + async e => { if (IsForThisContext(getContext(e))) await handler(e).ConfigureAwait(false); }; + public Task<Subscription> OnNavigationStartedAsync(Func<NavigationInfo, Task> handler, ContextSubscriptionOptions? options = null) { - return BiDi.BrowsingContext.OnNavigationStartedAsync(async e => - { - if (e.Context == this) - { - await handler(e).ConfigureAwait(false); - } - }, options.WithContext(this)); + return BiDi.BrowsingContext.OnNavigationStartedAsync( + FilterForThisContext(handler, e => e.Context), + options.WithContext(this)); } public Task<Subscription> OnNavigationStartedAsync(Action<NavigationInfo> handler, ContextSubscriptionOptions? options = null) { - return BiDi.BrowsingContext.OnNavigationStartedAsync(e => - { - if (e.Context == this) - { - handler(e); - } - }, options.WithContext(this)); + return BiDi.BrowsingContext.OnNavigationStartedAsync( + FilterForThisContext(handler, e => e.Context), + options.WithContext(this)); }
Suggestion importance[1-10]: 6__ Why: | Low |
| ||