-
-
Notifications
You must be signed in to change notification settings - Fork 8.6k
[dotnet] Enable Option<T> to work when no value is provided #16648
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: trunk
Are you sure you want to change the base?
[dotnet] Enable Option<T> to work when no value is provided #16648
Conversation
PR Compliance Guide 🔍Below is a summary of compliance checks for this PR:
Compliance status legend🟢 - Fully Compliant🟡 - Partial Compliant 🔴 - Not Compliant ⚪ - Requires Further Human Verification 🏷️ - Compliance label |
|||||||||||||||||||||||||||||||||
PR Code Suggestions ✨Explore these optional code suggestions:
|
||||||||||||
| internal sealed class SetViewportCommand(SetViewportParameters @params) | ||
| : Command<SetViewportParameters, SetViewportResult>(@params, "browsingContext.setViewport"); | ||
|
|
||
| internal sealed record SetViewportParameters(BrowsingContext Context, [property: JsonConverter(typeof(OptionalConverter<Viewport?>))] Optional<Viewport?>? Viewport, [property: JsonConverter(typeof(OptionalConverter<double?>))] Optional<double?>? DevicePixelRatio) : Parameters; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought it was better for AOT, like StringEnumConverter where we specify this attribute with explicitly mentioning type (Viewport in this case). Additionally if we recall modules cross-referencing, I like the approach: explicitly specify converters.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I forgot about AOT, honestly. We should really enable AOT analyzers to we have visibility on AOT-unfriendly things.
selenium/dotnet/src/webdriver/Selenium.WebDriver.csproj
Lines 49 to 54 in b446e16
| <!--TODO when AOT is ready https://github.com/SeleniumHQ/selenium/issues/14480--> | |
| <!--<PropertyGroup Condition="$([MSBuild]::IsTargetFrameworkCompatible('$(TargetFramework)', 'net8.0'))"> | |
| <IsAotCompatible>true</IsAotCompatible> | |
| </PropertyGroup>--> | |
But either way, this convertor is nothing more than a reminder: all the logic is in [JsonIgnore(WhenWritingDefault)].
I asked the .NET devs if there's a nice way of doing this dotnet/runtime#122049
|
|
||
| await context.SetViewportAsync(new() { Viewport = new Viewport(250, 300) }); | ||
| await context.SetViewportAsync(new() { Viewport = default }); // Sends nothing | ||
| await context.SetViewportAsync(new() { Viewport = Optional<Viewport?>.None }); // Sends nothing |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What if default? Let's mention this case in test to not forget our target behavior.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Optional<Viewport?>.None == default(Optional<Viewport?>). No difference, I just think it reads better.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
True, I didn't introduce this helper in initial implementation. I propose just to cover default case additionally in the test.
| public sealed class SetViewportOptions : CommandOptions | ||
| { | ||
| public Optional<Viewport?>? Viewport { get; set; } | ||
| [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unnecessary, this class is not serializable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hopefully obsoleted by #16648 (comment)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually not related, the class is non-serializable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Initially I wanted to avoid merging this PR until the discussion I opened is resolved.
But I think it’s valuable to remove the extra ? from the property, so I will clean this PR up to get it merged before the next release.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes yes yes, nullable of nullable looks strange. Please help.
User description
Not sure how CI was passing,
CanSetViewportwas failing locally.When the value was supposed to be unset, we were sending
nullanyways. We remove that here.🔗 Related Issues
💥 What does this PR do?
🔧 Implementation Notes
💡 Additional Considerations
🔄 Types of changes
PR Type
Bug fix
Description
Fix
Optional<T>serialization to properly handle unset valuesReplace custom converter with factory-based approach for better handling
Use
JsonIgnoreattribute to omit unset optional properties from JSONAdd
Optional<T>.Nonestatic property for explicit unset valuesDiagram Walkthrough
File Walkthrough
Optional.cs
Add JsonConverter and None property to Optionaldotnet/src/webdriver/BiDi/Optional.cs
JsonConverterattribute toOptionalstruct for automaticserialization
Noneproperty to represent unset optional values_valuefield to nullableT?to support null valuesValueproperty to return nullableT?T?OptionalConverterFactory.cs
Implement factory-based Optional converterdotnet/src/webdriver/BiDi/Json/Converters/OptionalConverterFactory.cs
Optionaltypesdynamically
OptionalConverterFactorythat creates converters for anyOptionalOptionalConverterwithHandleNullsupportJsonIgnoreusageOptionalConverter.cs
Remove standalone converter classdotnet/src/webdriver/BiDi/Json/Converters/OptionalConverter.cs
OptionalConverterclass (replaced by factorypattern)
OptionalConverterFactory.OptionalConverterSetViewportCommand.cs
Use JsonIgnore instead of custom converterdotnet/src/webdriver/BiDi/BrowsingContext/SetViewportCommand.cs
OptionalConverterattribute withJsonIgnore(Condition =JsonIgnoreCondition.WhenWritingDefault)Optional?to non-nullableOptionalusing OpenQA.Selenium.BiDi.Json.ConvertersstatementBrowsingContextModule.cs
Explicitly use Optional.None for unset valuesdotnet/src/webdriver/BiDi/BrowsingContext/BrowsingContextModule.cs
SetViewportAsyncto explicitly useOptional.Nonefor unsetvalues
options?.Viewport ?? Optional.Noneto ensure proper unsethandling
options?.DevicePixelRatio ?? Optional.Nonefor device pixel ratioBiDiJsonSerializerContext.cs
Register nullable Viewport typedotnet/src/webdriver/BiDi/Json/BiDiJsonSerializerContext.cs
[JsonSerializable(typeof(BrowsingContext.Viewport?))]attributeViewport?type is properly serialized in the contextBrowsingContextTest.cs
Update test to use Optional.Nonedotnet/test/common/BiDi/BrowsingContext/BrowsingContextTest.cs
Optional.Noneinstead ofdefaultfor clarity