-
-
Notifications
You must be signed in to change notification settings - Fork 8.4k
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
[dotnet] [bidi] Do not throw when CallFunction or Evaluate return exceptional result (breaking change) #15521
base: trunk
Are you sure you want to change the base?
Conversation
PR Reviewer Guide 🔍Here are some key observations to aid the review process:
|
PR Code Suggestions ✨Explore these optional code suggestions:
|
@@ -29,5 +29,5 @@ public class ScriptEvaluateException(EvaluateResultException evaluateResultExcep | |||
|
|||
public long ColumNumber => _evaluateResultException.ExceptionDetails.ColumnNumber; | |||
|
|||
public override string Message => $"{Text}{Environment.NewLine}{_evaluateResultException.ExceptionDetails.StackTrace}"; | |||
public override string Message => $"{Text}{Environment.NewLine}{string.Join(Environment.NewLine, _evaluateResultException.ExceptionDetails.StackTrace.CallFrames)}"; |
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.
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.
We can even remove ScriptEvaluateException
type. And throw general BiDiException
which takes already formatted string from EvaluateResultError
record type. Then what we need, just improve formatting of EvaluateResultError
to string (https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/record#built-in-formatting-for-display).
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 think a special exception type is necessary, because we can expose the ExceptionDetails
directly. User code can be like:
try
{
var res = await context.Script.EvaluateAsync("maybe throws", false);
}
catch (ScriptEvaluateException ex)
{
Console.WriteLine(ex.EvaluateResultException);
}
I changed the ScriptEvaluateException
to reflect this, let me know what you think.
public abstract record EvaluateResult; | ||
public abstract record EvaluateResult | ||
{ | ||
public EvaluateResultSuccess ThrowOnError() |
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.
Good name?
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.
EnsureSuccess()
or ToSuccess()
or AsSuccess()
is better IMHO. As I know EnsureSuccess()
should not convert, I have no strong opinion.
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.
If we consider #15521 (comment), then I propose RemoteValue AsSuccessResult()
.
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.
How I feel it: .To*()
should allocate new object, As*()
should return a reference.
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 agree with the As*()
naming style. Going with AsSuccessResult()
.
I mentioned in the other comment why I think this should still return an EvaluateResultSuccess
.
However, I do not feel strongly about it, since this is just a helper method anyway (should this be an extension?). In our code, we call EvaluateResultSuccess.Realm
two times, and the remaining 68 times we access .Result
immediately.
While typing this message, I have been convinced. Changing the return to RemoteValue
.
public abstract record EvaluateResult; | ||
public abstract record EvaluateResult | ||
{ | ||
public EvaluateResultSuccess ThrowOnError() |
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 just return RemoteValue
at once?
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.
That is too much magic in my opinion. the two methods which have JS evaluation, EvaluateAsync
and CallFunctionAsync
, both have generic overloads which will de-serialize to the correct type. Otherwise, users have access to the Success type directly. It is trivial to do .Result
if they need the RemoteValue
.
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.
Done.
Not related to this PR, I added a prefix |
|
||
var exceptionResult = (EvaluateResultException)this; | ||
|
||
throw new ScriptEvaluateException(exceptionResult.ExceptionDetails); |
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 really propose to remove this exception type.
- If spec introduces new
PartiallyException
type, we again will be in problematic situation.
How to negotiate: just throw BiDiException
with info about something like "expected success but got 'blah blah'".
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.
All right, and this "blah blah" can be just commandResult.ToString()
(and here the magic of formatting of record
to string helps).
[JsonInclude] | ||
internal string type = "channel"; | ||
[JsonPropertyName("type")] |
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 attribute, in my head we will just rename property rather than support backward compatibility. Because if we will not rename properties according spec (even if it is breaking change), we will become to a chaos where the .NET types mess weakly correlated to spec.
[JsonInclude] | ||
internal string type = "channel"; | ||
[JsonPropertyName("type")] | ||
internal string Type => "channel"; |
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.
Do you know any difference:
internal string Type { get: } = "channel";
Any performance impact?
(minor question, resolve it without answers)
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.
Static is better? If it is true... and it is friendly with json serialization, I propose to introduce this rule.
Description
In an effort for Selenium's raw BiDi to return the exact response from the endpoint, we should not throw exceptions unless the opt-in
ThrowOnError()
method is called.Motivation and Context
Fixes #15414
Types of changes
Checklist
PR Type
Enhancement, Tests
Description
Updated
EvaluateAsync
andCallFunctionAsync
methods to handle exceptional results without throwing exceptions directly.ThrowOnError
method inEvaluateResult
to centralize error handling.EvaluateAsync
andCallFunctionAsync
toEvaluateResult
for consistency.Enhanced error handling by refining
ScriptEvaluateException
to include detailed stack trace information.Adjusted test cases to validate the new
ThrowOnError
behavior and ensure proper handling of exceptional results.EvaluateResultSuccess
and useThrowOnError
for result validation.Improved serialization logic in
ChannelLocalValue
to ensure proper JSON property naming.Changes walkthrough 📝
5 files
Refactored
EvaluateAsync
andCallFunctionAsync
methods for errorhandling
Added
ThrowOnError
method toEvaluateResult
for centralized errorhandling
Improved JSON serialization for `ChannelLocalValue`
Enhanced exception message with detailed stack trace
Removed direct exception throwing in
EvaluateAsync
andCallFunctionAsync
5 files
Updated tests to validate
ThrowOnError
behavior forCallFunctionAsync
Adjusted parameter tests to handle
ThrowOnError
inCallFunctionAsync
Refined remote value tests to use
ThrowOnError
for result validationEnhanced evaluation parameter tests with `ThrowOnError` validation
Updated script command tests to validate `ThrowOnError` behavior