Skip to content
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] Make the devtools SendCommand method AOT-safe #15159

Open
wants to merge 12 commits into
base: trunk
Choose a base branch
from
5 changes: 3 additions & 2 deletions dotnet/src/webdriver/DevTools/DevToolsSession.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
// under the License.
// </copyright>

using OpenQA.Selenium.DevTools.Json;
using OpenQA.Selenium.Internal.Logging;
using System;
using System.Collections.Concurrent;
Expand Down Expand Up @@ -283,7 +284,7 @@ public T GetVersionSpecificDomains<T>() where T : DevToolsSessionDomains

LogTrace("Sending {0} {1}: {2}", message.CommandId, message.CommandName, commandParameters.ToString());

string contents = JsonSerializer.Serialize(message);
string contents = JsonSerializer.Serialize(message, DevToolsJsonOptions.DevToolsSerializerContext.Default.DevToolsCommandData);
this.pendingCommands.TryAdd(message.CommandId, message);
await this.connection.SendData(contents).ConfigureAwait(false);

Expand Down Expand Up @@ -410,7 +411,7 @@ private async Task<int> InitializeProtocol(int requestedProtocolVersion)
rawVersionInfo = await client.GetStringAsync("/json/version").ConfigureAwait(false);
}

var versionInfo = JsonSerializer.Deserialize<DevToolsVersionInfo>(rawVersionInfo);
var versionInfo = JsonSerializer.Deserialize(rawVersionInfo, DevToolsJsonOptions.DevToolsSerializerContext.Default.DevToolsVersionInfo);
this.websocketAddress = versionInfo.WebSocketDebuggerUrl;

if (requestedProtocolVersion == AutoDetectDevToolsProtocolVersion)
Expand Down
6 changes: 1 addition & 5 deletions dotnet/src/webdriver/DevTools/DevToolsVersionInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -66,11 +66,7 @@ public class DevToolsVersionInfo
/// </summary>
[JsonPropertyName("V8-Version")]
[JsonInclude]
public string V8Version
{
get;
internal set;
}
public string V8Version { get; internal set; }

/// <summary>
/// Gets the URL for the WebSocket connection used for communicating via the DevTools Protocol.
Expand Down
8 changes: 7 additions & 1 deletion dotnet/src/webdriver/DevTools/Json/DevToolsJsonOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,13 @@
// </copyright>

using System.Text.Json;
using System.Text.Json.Serialization;

#nullable enable

namespace OpenQA.Selenium.DevTools.Json;

internal static class DevToolsJsonOptions
internal static partial class DevToolsJsonOptions
{
public static JsonSerializerOptions Default { get; } = new JsonSerializerOptions()
{
Expand All @@ -32,4 +33,9 @@ internal static class DevToolsJsonOptions
new StringConverter(),
}
};

[JsonSerializable(typeof(DevToolsCommandData))]
[JsonSerializable(typeof(DevToolsVersionInfo))]
[JsonSerializable(typeof(DomMutationData))]
internal sealed partial class DevToolsSerializerContext : JsonSerializerContext;
}
32 changes: 6 additions & 26 deletions dotnet/src/webdriver/DomMutationData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,58 +26,38 @@ namespace OpenQA.Selenium
/// </summary>
public class DomMutationData
{
private string targetId;
private string attributeName;
private string attributeValue;
private string attributeOriginalValue;

/// <summary>
/// Gets the ID of the element whose value is changing.
/// </summary>
[JsonPropertyName("target")]
[JsonInclude]
public string TargetId
{
get { return this.targetId; }
internal set { this.targetId = value; }
}
public string TargetId { get; internal set; }

/// <summary>
/// Gets the name of the attribute that is changing.
/// </summary>
[JsonPropertyName("name")]
[JsonInclude]
public string AttributeName
{
get { return this.attributeName; }
internal set { this.attributeName = value; }
}
public string AttributeName { get; internal set; }

/// <summary>
/// Gets the value to which the attribute is being changed.
/// </summary>
[JsonPropertyName("value")]
[JsonInclude]
public string AttributeValue
{
get { return this.attributeValue; }
internal set { this.attributeValue = value; }
}
public string AttributeValue { get; internal set; }

/// <summary>
/// Gets the value from which the attribute has been changed.
/// </summary>
[JsonPropertyName("oldValue")]
[JsonInclude]
public string AttributeOriginalValue
{
get { return this.attributeOriginalValue; }
internal set { this.attributeOriginalValue = value; }
}
public string AttributeOriginalValue { get; internal set; }

/// <summary>
/// Stores the element associated with the target ID
/// </summary>
[JsonIgnore]
public IWebElement Element { get; internal set; }

/// <summary>
Expand All @@ -86,7 +66,7 @@ public string AttributeOriginalValue
/// <returns>A string that represents the current object.</returns>
public override string ToString()
{
return string.Format("target: {0}, name: {1}, value: {2}, originalValue: {3}", this.targetId, this.attributeName, this.attributeValue, this.attributeOriginalValue);
return string.Format("target: {0}, name: {1}, value: {2}, originalValue: {3}", this.TargetId, this.AttributeName, this.AttributeValue, this.AttributeOriginalValue);
}
}
}
3 changes: 2 additions & 1 deletion dotnet/src/webdriver/JavaScriptEngine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
// </copyright>

using OpenQA.Selenium.DevTools;
using OpenQA.Selenium.DevTools.Json;
using OpenQA.Selenium.Internal;
using System;
using System.Collections.Generic;
Expand Down Expand Up @@ -398,7 +399,7 @@ private void OnScriptBindingCalled(object sender, BindingCalledEventArgs e)
{
if (e.Name == MonitorBindingName)
{
DomMutationData valueChangeData = JsonSerializer.Deserialize<DomMutationData>(e.Payload);
DomMutationData valueChangeData = JsonSerializer.Deserialize(e.Payload, DevToolsJsonOptions.DevToolsSerializerContext.Default.DomMutationData);
var locator = By.CssSelector($"*[data-__webdriver_id='{valueChangeData.TargetId}']");
valueChangeData.Element = driver.FindElements(locator).FirstOrDefault();

Expand Down
11 changes: 3 additions & 8 deletions dotnet/src/webdriver/Response.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,6 @@ namespace OpenQA.Selenium
/// </summary>
public class Response
{
private static readonly JsonSerializerOptions s_jsonSerializerOptions = new()
{
TypeInfoResolver = ResponseJsonSerializerContext.Default,
Converters = { new ResponseValueJsonConverter() } // we still need it to make `Object` as `Dictionary`
};

/// <summary>
/// Initializes a new instance of the <see cref="Response"/> class
/// </summary>
Expand Down Expand Up @@ -79,7 +73,7 @@ public Response(string? sessionId, object? value, WebDriverResult status)
/// <exception cref="JsonException">If <paramref name="value"/> is not a valid JSON object.</exception>
public static Response FromJson(string value)
{
Dictionary<string, object?> rawResponse = JsonSerializer.Deserialize<Dictionary<string, object?>>(value, s_jsonSerializerOptions)
Dictionary<string, object?> rawResponse = JsonSerializer.Deserialize<Dictionary<string, object?>>(value, ResponseJsonSerializerContext.Default.DictionaryStringObject)
?? throw new WebDriverException("JSON success response returned \"null\" value");

object? contents;
Expand Down Expand Up @@ -178,7 +172,7 @@ public WebDriverResult Status
/// <exception cref="WebDriverException">If the JSON dictionary is not in the expected state, per spec.</exception>
public static Response FromErrorJson(string value)
{
Dictionary<string, object?> deserializedResponse = JsonSerializer.Deserialize<Dictionary<string, object?>>(value, s_jsonSerializerOptions)
Dictionary<string, object?> deserializedResponse = JsonSerializer.Deserialize<Dictionary<string, object?>>(value, ResponseJsonSerializerContext.Default.DictionaryStringObject)
?? throw new WebDriverException("JSON error response returned \"null\" value");

if (!deserializedResponse.TryGetValue("value", out object? valueObject))
Expand Down Expand Up @@ -226,5 +220,6 @@ public override string ToString()
}

[JsonSerializable(typeof(Dictionary<string, object>))]
[JsonSourceGenerationOptions(Converters = [typeof(ResponseValueJsonConverter)])] // we still need it to make `Object` as `Dictionary`
RenderMichael marked this conversation as resolved.
Show resolved Hide resolved
internal sealed partial class ResponseJsonSerializerContext : JsonSerializerContext;
}
Loading