From 8aa9c86a8b6a323d0288daf71dde70ef1c0a0059 Mon Sep 17 00:00:00 2001 From: Nikolay Borisenko <22616990+nvborisenko@users.noreply.github.com> Date: Mon, 17 Nov 2025 23:05:44 +0300 Subject: [PATCH 01/11] generate partial class --- dotnet/private/BUILD.bazel | 6 ++ dotnet/private/generate_resources.bzl | 48 +++++++++++ dotnet/private/generate_resources_tool.py | 85 +++++++++++++++++++ dotnet/src/webdriver/BUILD.bazel | 49 +++++------ .../webdriver/Internal/ResourceUtilities.cs | 2 +- .../src/webdriver/Selenium.WebDriver.csproj | 27 +----- 6 files changed, 165 insertions(+), 52 deletions(-) create mode 100644 dotnet/private/generate_resources.bzl create mode 100644 dotnet/private/generate_resources_tool.py diff --git a/dotnet/private/BUILD.bazel b/dotnet/private/BUILD.bazel index e69de29bb2d1d..6047c636b12ce 100644 --- a/dotnet/private/BUILD.bazel +++ b/dotnet/private/BUILD.bazel @@ -0,0 +1,6 @@ +load("//dotnet/private:generate_resources.bzl", "resource_utilities") + +py_binary( + name = "generate_resources_tool", + srcs = ["generate_resources_tool.py"], +) diff --git a/dotnet/private/generate_resources.bzl b/dotnet/private/generate_resources.bzl new file mode 100644 index 0000000000000..7eb4bdbf16e24 --- /dev/null +++ b/dotnet/private/generate_resources.bzl @@ -0,0 +1,48 @@ +"""Generate C# partial class with embedded JS resources via a Python tool.""" + +def _resource_utilities_impl(ctx): + """Invoke a Python script to generate ResourceUtilities.cs from input files. + + This rule does not inspect file contents itself; it just wires inputs/outputs + for the generator tool. + """ + + args = ctx.actions.args() + args.add("--output", ctx.outputs.out) + + for src in ctx.files.srcs: + args.add("--input") + # Each --input is "identifier=path" + name = src.basename.rsplit(".", 1)[0] + # Starlark strings are not directly iterable into characters, so use + # a simple replacement-based sanitization: non-identifier characters + # are replaced with '_'. This is conservative but sufficient. + ident = name + ident = ident.replace("-", "_") + ident = ident.replace(".", "_") + ident = ident.replace(" ", "_") + if ident and ident[0].isdigit(): + ident = "_" + ident + args.add("%s=%s" % (ident, src.path)) + + ctx.actions.run( + inputs = ctx.files.srcs, + outputs = [ctx.outputs.out], + executable = ctx.executable._tool, + arguments = [args], + mnemonic = "GenerateResourceUtilities", + progress_message = "Generating C# ResourceUtilities partial class", + ) + +resource_utilities = rule( + implementation = _resource_utilities_impl, + attrs = { + "srcs": attr.label_list(allow_files = True), + "out": attr.output(mandatory = True), + "_tool": attr.label( + default = Label("//dotnet/private:generate_resources_tool"), + executable = True, + cfg = "exec", + ), + }, +) \ No newline at end of file diff --git a/dotnet/private/generate_resources_tool.py b/dotnet/private/generate_resources_tool.py new file mode 100644 index 0000000000000..9ad613efb18ae --- /dev/null +++ b/dotnet/private/generate_resources_tool.py @@ -0,0 +1,85 @@ +#!/usr/bin/env python3 +"""Generate C# ResourceUtilities partial class with embedded JS resources. + +Usage: + generate_resources_tool.py --output path/to/ResourceUtilities.g.cs \ + --input Ident1=path/to/file1.js \ + --input Ident2=path/to/file2.js ... + +Each identifier becomes a const string in ResourceUtilities class. +The content is emitted as a C# raw string literal using 5-quotes. +""" + +import argparse +import os +import sys +from typing import List, Tuple + + +def parse_args(argv: List[str]) -> argparse.Namespace: + parser = argparse.ArgumentParser() + parser.add_argument("--output", required=True) + parser.add_argument("--input", action="append", default=[], help="IDENT=path") + return parser.parse_args(argv) + + +def parse_input_spec(spec: str) -> Tuple[str, str]: + if "=" not in spec: + raise ValueError(f"Invalid --input value, expected IDENT=path, got: {spec}") + ident, path = spec.split("=", 1) + ident = ident.strip() + path = path.strip() + if not ident: + raise ValueError(f"Empty identifier in --input value: {spec}") + if not path: + raise ValueError(f"Empty path in --input value: {spec}") + return ident, path + + +def generate(output: str, inputs: List[Tuple[str, str]]) -> None: + props: List[str] = [] + for ident, path in inputs: + with open(path, "r", encoding="utf-8") as f: + content = f.read() + # Use a C# raw string literal with five quotes. For a valid raw + # literal, the content must start on a new line and the closing + # quotes must be on their own line as well. We assume the content + # does not contain a sequence of five consecutive double quotes. + # + # Resulting C# will look like: + # """"" + # + # """"" + literal = '"""""\n' + content + '\n"""""' + props.append( + f" internal const string {ident} = {literal};" + ) + + lines: List[str] = [] + lines.append("// ") + lines.append("namespace OpenQA.Selenium.Internal;") + lines.append("") + lines.append("internal static partial class ResourceUtilities") + lines.append("{") + for p in props: + lines.append(p) + lines.append("}") + lines.append("") + + os.makedirs(os.path.dirname(output), exist_ok=True) + with open(output, "w", encoding="utf-8", newline="\n") as f: + f.write("\n".join(lines)) + + +def main(argv: List[str]) -> int: + args = parse_args(argv) + inputs: List[Tuple[str, str]] = [] + for spec in args.input: + ident, path = parse_input_spec(spec) + inputs.append((ident, path)) + generate(args.output, inputs) + return 0 + + +if __name__ == "__main__": + raise SystemExit(main(sys.argv[1:])) diff --git a/dotnet/src/webdriver/BUILD.bazel b/dotnet/src/webdriver/BUILD.bazel index 7eb83adc81ec4..3d9161ba72e97 100644 --- a/dotnet/src/webdriver/BUILD.bazel +++ b/dotnet/src/webdriver/BUILD.bazel @@ -1,5 +1,6 @@ load("//common:defs.bzl", "copy_file") load("//dotnet:defs.bzl", "csharp_library", "devtools_version_targets", "framework", "generated_assembly_info", "nuget_pack") +load("//dotnet/private:generate_resources.bzl", "resource_utilities") load( "//dotnet:selenium-dotnet-version.bzl", "ASSEMBLY_COMPANY", @@ -25,10 +26,23 @@ generated_assembly_info( version = ASSEMBLY_VERSION, ) +generated_resource_utilities( + name = "resource-utilities", + srcs = [ + "//javascript/atoms/fragments:find-elements.js", + "//javascript/atoms/fragments:is-displayed.js", + "//javascript/cdp-support:mutation-listener.js", + "//javascript/webdriver/atoms:get-attribute.js", + "//third_party/js/selenium:webdriver_json", + ], + out = "ResourceUtilities.g.cs", +) + csharp_library( name = "webdriver-netstandard2.0", srcs = [ ":assembly-info", + ":resource-utilities", ] + glob([ "**/*.cs", ]) + devtools_version_targets(), @@ -38,13 +52,7 @@ csharp_library( ], langversion = "12.0", nullable = "enable", - resources = [ - "//javascript/atoms/fragments:find-elements.js", - "//javascript/atoms/fragments:is-displayed.js", - "//javascript/cdp-support:mutation-listener.js", - "//javascript/webdriver/atoms:get-attribute.js", - "//third_party/js/selenium:webdriver_json", - ], + resources = [], target_frameworks = [ "netstandard2.0", ], @@ -66,6 +74,7 @@ csharp_library( name = "webdriver-net8.0", srcs = [ ":assembly-info", + ":resource-utilities", ] + glob([ "**/*.cs", ]) + devtools_version_targets(), @@ -78,13 +87,7 @@ csharp_library( ], langversion = "12.0", nullable = "enable", - resources = [ - "//javascript/atoms/fragments:find-elements.js", - "//javascript/atoms/fragments:is-displayed.js", - "//javascript/cdp-support:mutation-listener.js", - "//javascript/webdriver/atoms:get-attribute.js", - "//third_party/js/selenium:webdriver_json", - ], + resources = [], target_frameworks = [ "net8.0", ], @@ -99,6 +102,7 @@ csharp_library( name = "webdriver-netstandard2.0-strongnamed", srcs = [ ":assembly-info", + ":resource-utilities", ] + glob([ "**/*.cs", ]) + devtools_version_targets(), @@ -106,13 +110,7 @@ csharp_library( keyfile = "//dotnet:Selenium.snk", langversion = "12.0", nullable = "enable", - resources = [ - "//javascript/atoms/fragments:find-elements.js", - "//javascript/atoms/fragments:is-displayed.js", - "//javascript/cdp-support:mutation-listener.js", - "//javascript/webdriver/atoms:get-attribute.js", - "//third_party/js/selenium:webdriver_json", - ], + resources = [], target_frameworks = [ "netstandard2.0", ], @@ -134,6 +132,7 @@ csharp_library( name = "webdriver-net8.0-strongnamed", srcs = [ ":assembly-info", + ":resource-utilities", ] + glob([ "**/*.cs", ]) + devtools_version_targets(), @@ -144,13 +143,7 @@ csharp_library( keyfile = "//dotnet:Selenium.snk", langversion = "12.0", nullable = "enable", - resources = [ - "//javascript/atoms/fragments:find-elements.js", - "//javascript/atoms/fragments:is-displayed.js", - "//javascript/cdp-support:mutation-listener.js", - "//javascript/webdriver/atoms:get-attribute.js", - "//third_party/js/selenium:webdriver_json", - ], + resources = [], target_frameworks = [ "net8.0", ], diff --git a/dotnet/src/webdriver/Internal/ResourceUtilities.cs b/dotnet/src/webdriver/Internal/ResourceUtilities.cs index 06c04389e5e92..555d9244586aa 100644 --- a/dotnet/src/webdriver/Internal/ResourceUtilities.cs +++ b/dotnet/src/webdriver/Internal/ResourceUtilities.cs @@ -27,7 +27,7 @@ namespace OpenQA.Selenium.Internal; /// /// Encapsulates methods for finding and extracting WebDriver resources. /// -internal static class ResourceUtilities +internal static partial class ResourceUtilities { private static string? productVersion; private static string? platformFamily; diff --git a/dotnet/src/webdriver/Selenium.WebDriver.csproj b/dotnet/src/webdriver/Selenium.WebDriver.csproj index 6cee5f837ea24..96a35f6c73413 100644 --- a/dotnet/src/webdriver/Selenium.WebDriver.csproj +++ b/dotnet/src/webdriver/Selenium.WebDriver.csproj @@ -79,30 +79,11 @@ - - + + - - False - $(AssemblyName).webdriver_prefs.json - - - False - $(AssemblyName).get-attribute.js - - - False - $(AssemblyName).is-displayed.js - - - False - $(AssemblyName).find-elements.js - - - False - $(AssemblyName).mutation-listener.js - + @@ -114,4 +95,4 @@ - \ No newline at end of file + From fbe666de359fbd4a79871a92218435c71b3cc6c8 Mon Sep 17 00:00:00 2001 From: Nikolay Borisenko <22616990+nvborisenko@users.noreply.github.com> Date: Mon, 17 Nov 2025 23:26:15 +0300 Subject: [PATCH 02/11] clean bazel --- dotnet/defs.bzl | 2 ++ dotnet/private/BUILD.bazel | 6 +++--- dotnet/private/generate_resources.bzl | 6 +++--- dotnet/src/webdriver/BUILD.bazel | 4 ++-- 4 files changed, 10 insertions(+), 8 deletions(-) diff --git a/dotnet/defs.bzl b/dotnet/defs.bzl index 827de3f8d904a..14305f2b280a5 100644 --- a/dotnet/defs.bzl +++ b/dotnet/defs.bzl @@ -3,6 +3,7 @@ load("//dotnet:selenium-dotnet-version.bzl", "SUPPORTED_DEVTOOLS_VERSIONS") load("//dotnet/private:dotnet_nunit_test_suite.bzl", _dotnet_nunit_test_suite = "dotnet_nunit_test_suite") load("//dotnet/private:framework.bzl", _framework = "framework") load("//dotnet/private:generate_devtools.bzl", _generate_devtools = "generate_devtools") +load("//dotnet/private:generate_resources.bzl", _generated_resource_utilities = "generated_resource_utilities") load("//dotnet/private:generated_assembly_info.bzl", _generated_assembly_info = "generated_assembly_info") load("//dotnet/private:nuget_pack.bzl", _nuget_pack = "nuget_pack") load("//dotnet/private:nunit_test.bzl", _nunit_test = "nunit_test") @@ -19,6 +20,7 @@ csharp_test = _csharp_test dotnet_nunit_test_suite = _dotnet_nunit_test_suite framework = _framework generate_devtools = _generate_devtools +generated_resource_utilities = _generated_resource_utilities generated_assembly_info = _generated_assembly_info nuget_pack = _nuget_pack nunit_test = _nunit_test diff --git a/dotnet/private/BUILD.bazel b/dotnet/private/BUILD.bazel index 6047c636b12ce..c7f653ad043ee 100644 --- a/dotnet/private/BUILD.bazel +++ b/dotnet/private/BUILD.bazel @@ -1,6 +1,6 @@ -load("//dotnet/private:generate_resources.bzl", "resource_utilities") +load("//dotnet/private:generate_resources.bzl", "generated_resource_utilities") py_binary( - name = "generate_resources_tool", - srcs = ["generate_resources_tool.py"], + name = "generate_resources_tool", + srcs = ["generate_resources_tool.py"], ) diff --git a/dotnet/private/generate_resources.bzl b/dotnet/private/generate_resources.bzl index 7eb4bdbf16e24..c15f599e7708d 100644 --- a/dotnet/private/generate_resources.bzl +++ b/dotnet/private/generate_resources.bzl @@ -1,6 +1,6 @@ """Generate C# partial class with embedded JS resources via a Python tool.""" -def _resource_utilities_impl(ctx): +def _generate_resource_utilities_impl(ctx): """Invoke a Python script to generate ResourceUtilities.cs from input files. This rule does not inspect file contents itself; it just wires inputs/outputs @@ -34,8 +34,8 @@ def _resource_utilities_impl(ctx): progress_message = "Generating C# ResourceUtilities partial class", ) -resource_utilities = rule( - implementation = _resource_utilities_impl, +generated_resource_utilities = rule( + implementation = _generate_resource_utilities_impl, attrs = { "srcs": attr.label_list(allow_files = True), "out": attr.output(mandatory = True), diff --git a/dotnet/src/webdriver/BUILD.bazel b/dotnet/src/webdriver/BUILD.bazel index 3d9161ba72e97..52ee88b6eaceb 100644 --- a/dotnet/src/webdriver/BUILD.bazel +++ b/dotnet/src/webdriver/BUILD.bazel @@ -1,6 +1,6 @@ load("//common:defs.bzl", "copy_file") -load("//dotnet:defs.bzl", "csharp_library", "devtools_version_targets", "framework", "generated_assembly_info", "nuget_pack") -load("//dotnet/private:generate_resources.bzl", "resource_utilities") +load("//dotnet:defs.bzl", "csharp_library", "devtools_version_targets", "framework", "generated_assembly_info", "nuget_pack", "generated_resource_utilities") + load( "//dotnet:selenium-dotnet-version.bzl", "ASSEMBLY_COMPANY", From 486f3085b6b6bd8d29745d7b5e6e5ff27b17e667 Mon Sep 17 00:00:00 2001 From: Nikolay Borisenko <22616990+nvborisenko@users.noreply.github.com> Date: Mon, 17 Nov 2025 23:51:35 +0300 Subject: [PATCH 03/11] Use gen strings in runtime --- .../src/webdriver/Firefox/FirefoxExtension.cs | 24 ++----------------- .../src/webdriver/Firefox/FirefoxProfile.cs | 12 ++++------ dotnet/src/webdriver/JavaScriptEngine.cs | 18 +------------- dotnet/src/webdriver/RelativeBy.cs | 11 +-------- .../src/webdriver/Selenium.WebDriver.csproj | 2 +- dotnet/src/webdriver/WebElement.cs | 21 ++-------------- 6 files changed, 11 insertions(+), 77 deletions(-) diff --git a/dotnet/src/webdriver/Firefox/FirefoxExtension.cs b/dotnet/src/webdriver/Firefox/FirefoxExtension.cs index 11a97c8c01e83..cca710e200e12 100644 --- a/dotnet/src/webdriver/Firefox/FirefoxExtension.cs +++ b/dotnet/src/webdriver/Firefox/FirefoxExtension.cs @@ -22,7 +22,7 @@ using System.Globalization; using System.IO; using System.IO.Compression; -using System.Reflection; +using System.Text; using System.Text.Json.Nodes; using System.Xml; @@ -38,7 +38,6 @@ public class FirefoxExtension private const string JsonManifestFileName = "manifest.json"; private readonly string extensionFileName; - private readonly string extensionResourceId; /// /// Initializes a new instance of the class. @@ -49,27 +48,8 @@ public class FirefoxExtension /// then using the full path to the file, if a full path is provided. /// If is . public FirefoxExtension(string fileName) - : this(fileName, string.Empty) - { - } - - /// - /// Initializes a new instance of the class. - /// - /// The name of the file containing the Firefox extension. - /// The ID of the resource within the assembly containing the extension - /// if the file is not present in the file system. - /// WebDriver attempts to resolve the parameter - /// by looking first for the specified file in the directory of the calling assembly, - /// then using the full path to the file, if a full path is provided. If the file is - /// not found in the file system, WebDriver attempts to locate a resource in the - /// executing assembly with the name specified by the - /// parameter. - /// If or are . - internal FirefoxExtension(string fileName, string resourceId) { this.extensionFileName = fileName ?? throw new ArgumentNullException(nameof(fileName)); - this.extensionResourceId = resourceId ?? throw new ArgumentNullException(nameof(resourceId)); } /// @@ -89,7 +69,7 @@ public void Install(string profileDirectory) // First, expand the .xpi archive into a temporary location. Directory.CreateDirectory(tempFileName); - Stream zipFileStream = ResourceUtilities.GetResourceStream(this.extensionFileName, $"{Assembly.GetExecutingAssembly().GetName().Name}.{this.extensionResourceId}"); + using Stream zipFileStream = new MemoryStream(Encoding.UTF8.GetBytes(ResourceUtilities.webdriver_prefs)); using (ZipArchive extensionZipArchive = new ZipArchive(zipFileStream, ZipArchiveMode.Read)) { extensionZipArchive.ExtractToDirectory(tempFileName); diff --git a/dotnet/src/webdriver/Firefox/FirefoxProfile.cs b/dotnet/src/webdriver/Firefox/FirefoxProfile.cs index 0af71b5d9c014..1e3540cf10efd 100644 --- a/dotnet/src/webdriver/Firefox/FirefoxProfile.cs +++ b/dotnet/src/webdriver/Firefox/FirefoxProfile.cs @@ -23,7 +23,6 @@ using System.Diagnostics.CodeAnalysis; using System.IO; using System.IO.Compression; -using System.Reflection; using System.Text.Json; namespace OpenQA.Selenium.Firefox; @@ -298,15 +297,12 @@ private void UpdateUserPreferences(string profileDirectory) private Preferences ReadDefaultPreferences() { - using (Stream defaultPrefsStream = ResourceUtilities.GetResourceStream("webdriver_prefs.json", $"{Assembly.GetExecutingAssembly().GetName().Name}.webdriver_prefs.json")) - { - using JsonDocument defaultPreferences = JsonDocument.Parse(defaultPrefsStream); + using JsonDocument defaultPreferences = JsonDocument.Parse(ResourceUtilities.webdriver_prefs); - JsonElement immutableDefaultPreferences = defaultPreferences.RootElement.GetProperty("frozen"); - JsonElement editableDefaultPreferences = defaultPreferences.RootElement.GetProperty("mutable"); + JsonElement immutableDefaultPreferences = defaultPreferences.RootElement.GetProperty("frozen"); + JsonElement editableDefaultPreferences = defaultPreferences.RootElement.GetProperty("mutable"); - return new Preferences(immutableDefaultPreferences, editableDefaultPreferences); - } + return new Preferences(immutableDefaultPreferences, editableDefaultPreferences); } /// diff --git a/dotnet/src/webdriver/JavaScriptEngine.cs b/dotnet/src/webdriver/JavaScriptEngine.cs index 3ed08e9fa944c..0f9acf616d4a1 100644 --- a/dotnet/src/webdriver/JavaScriptEngine.cs +++ b/dotnet/src/webdriver/JavaScriptEngine.cs @@ -23,9 +23,7 @@ using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Globalization; -using System.IO; using System.Linq; -using System.Reflection; using System.Text.Json; using System.Threading.Tasks; @@ -142,7 +140,7 @@ public void StopEventMonitoring() public async Task EnableDomMutationMonitoring() { // Execute the script to have it enabled on the currently loaded page. - string script = GetMutationListenerScript(); + string script = ResourceUtilities.mutation_listener; await this.session.Value.Domains.JavaScript.Evaluate(script).ConfigureAwait(false); await this.AddScriptCallbackBinding(MonitorBindingName).ConfigureAwait(false); @@ -409,20 +407,6 @@ private async Task EnableDomains() } } - private static string GetMutationListenerScript() - { - string listenerScript = string.Empty; - using (Stream resourceStream = ResourceUtilities.GetResourceStream("mutation-listener.js", $"{Assembly.GetExecutingAssembly().GetName().Name}.mutation-listener.js")) - { - using (StreamReader resourceReader = new StreamReader(resourceStream)) - { - listenerScript = resourceReader.ReadToEnd(); - } - } - - return listenerScript; - } - private void OnScriptBindingCalled(object? sender, BindingCalledEventArgs e) { if (e.Name == MonitorBindingName) diff --git a/dotnet/src/webdriver/RelativeBy.cs b/dotnet/src/webdriver/RelativeBy.cs index dd6335d76b32c..7e9c9b1f7f414 100644 --- a/dotnet/src/webdriver/RelativeBy.cs +++ b/dotnet/src/webdriver/RelativeBy.cs @@ -22,8 +22,6 @@ using System.Collections.Generic; using System.Collections.ObjectModel; using System.Globalization; -using System.IO; -using System.Reflection; namespace OpenQA.Selenium; @@ -38,14 +36,7 @@ public sealed class RelativeBy : By private static string GetWrappedAtom() { - string atom; - using (Stream atomStream = ResourceUtilities.GetResourceStream("find-elements.js", $"{Assembly.GetExecutingAssembly().GetName().Name}.find-elements.js")) - { - using (StreamReader atomReader = new StreamReader(atomStream)) - { - atom = atomReader.ReadToEnd(); - } - } + string atom = ResourceUtilities.find_elements; return string.Format(CultureInfo.InvariantCulture, "/* findElements */return ({0}).apply(null, arguments);", atom); } diff --git a/dotnet/src/webdriver/Selenium.WebDriver.csproj b/dotnet/src/webdriver/Selenium.WebDriver.csproj index 96a35f6c73413..5d549c6342759 100644 --- a/dotnet/src/webdriver/Selenium.WebDriver.csproj +++ b/dotnet/src/webdriver/Selenium.WebDriver.csproj @@ -79,7 +79,7 @@ - + diff --git a/dotnet/src/webdriver/WebElement.cs b/dotnet/src/webdriver/WebElement.cs index 8a5c66bdad286..dd6c11e973513 100644 --- a/dotnet/src/webdriver/WebElement.cs +++ b/dotnet/src/webdriver/WebElement.cs @@ -27,7 +27,6 @@ using System.IO; using System.IO.Compression; using System.Linq; -using System.Reflection; namespace OpenQA.Selenium; @@ -201,7 +200,7 @@ public virtual bool Displayed get { Dictionary parameters = new Dictionary(); - string atom = GetAtom("is-displayed.js"); + string atom = string.Format(CultureInfo.InvariantCulture, "/* {0} */return ({1}).apply(null, arguments);", "is_displayed", ResourceUtilities.is_displayed); parameters.Add("script", atom); parameters.Add("args", new object[] { ((IWebDriverObjectReference)this).ToDictionary() }); @@ -436,7 +435,7 @@ public virtual ReadOnlyCollection FindElements(string mechanism, st public virtual string? GetAttribute(string attributeName) { Dictionary parameters = new Dictionary(); - string atom = GetAtom("get-attribute.js"); + string atom = string.Format(CultureInfo.InvariantCulture, "/* {0} */return ({1}).apply(null, arguments);", "get_attribute", ResourceUtilities.get_attribute); parameters.Add("script", atom); parameters.Add("args", new object[] { ((IWebDriverObjectReference)this).ToDictionary(), attributeName }); @@ -707,22 +706,6 @@ protected virtual Response Execute(string commandToExecute, Dictionary Date: Tue, 18 Nov 2025 01:16:36 +0300 Subject: [PATCH 04/11] Notice about migrate to .net 10 --- dotnet/private/generate_resources_tool.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/dotnet/private/generate_resources_tool.py b/dotnet/private/generate_resources_tool.py index 9ad613efb18ae..c51fcffcd9efe 100644 --- a/dotnet/private/generate_resources_tool.py +++ b/dotnet/private/generate_resources_tool.py @@ -8,6 +8,11 @@ Each identifier becomes a const string in ResourceUtilities class. The content is emitted as a C# raw string literal using 5-quotes. + +TODO: +It would be nice to convert this small single-file utility to .NET10/C#, +so it would work like `dotnet run generate_resources.cs -- `. +Meaning .NET developers can easily support it. """ import argparse From a3565f36615eb54e20a3fc37ca00db067e15e8a6 Mon Sep 17 00:00:00 2001 From: Nikolay Borisenko <22616990+nvborisenko@users.noreply.github.com> Date: Tue, 18 Nov 2025 01:31:58 +0300 Subject: [PATCH 05/11] GetWrappedAtom in WebElement.cs --- dotnet/src/webdriver/WebElement.cs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/dotnet/src/webdriver/WebElement.cs b/dotnet/src/webdriver/WebElement.cs index dd6c11e973513..ede2383f20790 100644 --- a/dotnet/src/webdriver/WebElement.cs +++ b/dotnet/src/webdriver/WebElement.cs @@ -200,7 +200,7 @@ public virtual bool Displayed get { Dictionary parameters = new Dictionary(); - string atom = string.Format(CultureInfo.InvariantCulture, "/* {0} */return ({1}).apply(null, arguments);", "is_displayed", ResourceUtilities.is_displayed); + string atom = GetWrappedAtom("is_displayed", ResourceUtilities.is_displayed); parameters.Add("script", atom); parameters.Add("args", new object[] { ((IWebDriverObjectReference)this).ToDictionary() }); @@ -435,7 +435,7 @@ public virtual ReadOnlyCollection FindElements(string mechanism, st public virtual string? GetAttribute(string attributeName) { Dictionary parameters = new Dictionary(); - string atom = string.Format(CultureInfo.InvariantCulture, "/* {0} */return ({1}).apply(null, arguments);", "get_attribute", ResourceUtilities.get_attribute); + string atom = GetWrappedAtom("get_attribute", ResourceUtilities.get_attribute); parameters.Add("script", atom); parameters.Add("args", new object[] { ((IWebDriverObjectReference)this).ToDictionary(), attributeName }); @@ -706,6 +706,11 @@ protected virtual Response Execute(string commandToExecute, Dictionary Date: Tue, 18 Nov 2025 01:47:19 +0300 Subject: [PATCH 06/11] Camel case property names --- dotnet/private/generate_resources_tool.py | 34 ++++++++++++++++++- .../src/webdriver/Firefox/FirefoxExtension.cs | 2 +- dotnet/src/webdriver/WebElement.cs | 4 +-- 3 files changed, 36 insertions(+), 4 deletions(-) diff --git a/dotnet/private/generate_resources_tool.py b/dotnet/private/generate_resources_tool.py index c51fcffcd9efe..66813a7d30054 100644 --- a/dotnet/private/generate_resources_tool.py +++ b/dotnet/private/generate_resources_tool.py @@ -21,6 +21,37 @@ from typing import List, Tuple +def to_camel_case(name: str) -> str: + """Convert an identifier like "find-elements" or "webdriver_json" to PascalCase. + + Non-alphanumeric characters are treated as separators; leading digits are preserved + but not used to start a new word. Example: + - "find-elements" -> "FindElements" + - "webdriver_json" -> "WebdriverJson" + - "1st-thing" -> "1stThing" + """ + parts: List[str] = [] + current: List[str] = [] + for ch in name: + if ch.isalnum(): + current.append(ch) + else: + if current: + parts.append("".join(current)) + current = [] + if current: + parts.append("".join(current)) + + if not parts: + return name + + # Capitalize every part (PascalCase) + result: List[str] = [] + for part in parts: + result.append(part[:1].upper() + part[1:]) + return "".join(result) + + def parse_args(argv: List[str]) -> argparse.Namespace: parser = argparse.ArgumentParser() parser.add_argument("--output", required=True) @@ -44,6 +75,7 @@ def parse_input_spec(spec: str) -> Tuple[str, str]: def generate(output: str, inputs: List[Tuple[str, str]]) -> None: props: List[str] = [] for ident, path in inputs: + prop_name = to_camel_case(ident) with open(path, "r", encoding="utf-8") as f: content = f.read() # Use a C# raw string literal with five quotes. For a valid raw @@ -57,7 +89,7 @@ def generate(output: str, inputs: List[Tuple[str, str]]) -> None: # """"" literal = '"""""\n' + content + '\n"""""' props.append( - f" internal const string {ident} = {literal};" + f" internal const string {prop_name} = {literal};" ) lines: List[str] = [] diff --git a/dotnet/src/webdriver/Firefox/FirefoxExtension.cs b/dotnet/src/webdriver/Firefox/FirefoxExtension.cs index cca710e200e12..f93109ff8395c 100644 --- a/dotnet/src/webdriver/Firefox/FirefoxExtension.cs +++ b/dotnet/src/webdriver/Firefox/FirefoxExtension.cs @@ -69,7 +69,7 @@ public void Install(string profileDirectory) // First, expand the .xpi archive into a temporary location. Directory.CreateDirectory(tempFileName); - using Stream zipFileStream = new MemoryStream(Encoding.UTF8.GetBytes(ResourceUtilities.webdriver_prefs)); + using Stream zipFileStream = new MemoryStream(Encoding.UTF8.GetBytes(ResourceUtilities.WebdriverPrefs)); using (ZipArchive extensionZipArchive = new ZipArchive(zipFileStream, ZipArchiveMode.Read)) { extensionZipArchive.ExtractToDirectory(tempFileName); diff --git a/dotnet/src/webdriver/WebElement.cs b/dotnet/src/webdriver/WebElement.cs index ede2383f20790..50c61a2997bb3 100644 --- a/dotnet/src/webdriver/WebElement.cs +++ b/dotnet/src/webdriver/WebElement.cs @@ -200,7 +200,7 @@ public virtual bool Displayed get { Dictionary parameters = new Dictionary(); - string atom = GetWrappedAtom("is_displayed", ResourceUtilities.is_displayed); + string atom = GetWrappedAtom("is_displayed", ResourceUtilities.IsDisplayed); parameters.Add("script", atom); parameters.Add("args", new object[] { ((IWebDriverObjectReference)this).ToDictionary() }); @@ -435,7 +435,7 @@ public virtual ReadOnlyCollection FindElements(string mechanism, st public virtual string? GetAttribute(string attributeName) { Dictionary parameters = new Dictionary(); - string atom = GetWrappedAtom("get_attribute", ResourceUtilities.get_attribute); + string atom = GetWrappedAtom("get_attribute", ResourceUtilities.GetAttribute); parameters.Add("script", atom); parameters.Add("args", new object[] { ((IWebDriverObjectReference)this).ToDictionary(), attributeName }); From 8512fa1bca4c6e7054e8271cf46ca4fdf46ec095 Mon Sep 17 00:00:00 2001 From: Nikolay Borisenko <22616990+nvborisenko@users.noreply.github.com> Date: Tue, 18 Nov 2025 01:48:44 +0300 Subject: [PATCH 07/11] Rename across all projects --- dotnet/src/webdriver/Firefox/FirefoxProfile.cs | 2 +- dotnet/src/webdriver/JavaScriptEngine.cs | 2 +- dotnet/src/webdriver/RelativeBy.cs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/dotnet/src/webdriver/Firefox/FirefoxProfile.cs b/dotnet/src/webdriver/Firefox/FirefoxProfile.cs index 1e3540cf10efd..90b846262768a 100644 --- a/dotnet/src/webdriver/Firefox/FirefoxProfile.cs +++ b/dotnet/src/webdriver/Firefox/FirefoxProfile.cs @@ -297,7 +297,7 @@ private void UpdateUserPreferences(string profileDirectory) private Preferences ReadDefaultPreferences() { - using JsonDocument defaultPreferences = JsonDocument.Parse(ResourceUtilities.webdriver_prefs); + using JsonDocument defaultPreferences = JsonDocument.Parse(ResourceUtilities.WebdriverPrefs); JsonElement immutableDefaultPreferences = defaultPreferences.RootElement.GetProperty("frozen"); JsonElement editableDefaultPreferences = defaultPreferences.RootElement.GetProperty("mutable"); diff --git a/dotnet/src/webdriver/JavaScriptEngine.cs b/dotnet/src/webdriver/JavaScriptEngine.cs index 0f9acf616d4a1..3dea99ba51b71 100644 --- a/dotnet/src/webdriver/JavaScriptEngine.cs +++ b/dotnet/src/webdriver/JavaScriptEngine.cs @@ -140,7 +140,7 @@ public void StopEventMonitoring() public async Task EnableDomMutationMonitoring() { // Execute the script to have it enabled on the currently loaded page. - string script = ResourceUtilities.mutation_listener; + string script = ResourceUtilities.MutationListener; await this.session.Value.Domains.JavaScript.Evaluate(script).ConfigureAwait(false); await this.AddScriptCallbackBinding(MonitorBindingName).ConfigureAwait(false); diff --git a/dotnet/src/webdriver/RelativeBy.cs b/dotnet/src/webdriver/RelativeBy.cs index 7e9c9b1f7f414..1ed946e02bf79 100644 --- a/dotnet/src/webdriver/RelativeBy.cs +++ b/dotnet/src/webdriver/RelativeBy.cs @@ -36,7 +36,7 @@ public sealed class RelativeBy : By private static string GetWrappedAtom() { - string atom = ResourceUtilities.find_elements; + string atom = ResourceUtilities.FindElements; return string.Format(CultureInfo.InvariantCulture, "/* findElements */return ({0}).apply(null, arguments);", atom); } From 147c6813d59aaf66728ac38c43bc39f756f55d52 Mon Sep 17 00:00:00 2001 From: Nikolay Borisenko <22616990+nvborisenko@users.noreply.github.com> Date: Tue, 18 Nov 2025 17:57:25 +0300 Subject: [PATCH 08/11] Provide property name per resource --- dotnet/private/generate_resources.bzl | 29 ++++++++----------- dotnet/private/generate_resources_tool.py | 34 +---------------------- dotnet/src/webdriver/BUILD.bazel | 14 +++++----- 3 files changed, 20 insertions(+), 57 deletions(-) diff --git a/dotnet/private/generate_resources.bzl b/dotnet/private/generate_resources.bzl index c15f599e7708d..a2c7fb1f3562b 100644 --- a/dotnet/private/generate_resources.bzl +++ b/dotnet/private/generate_resources.bzl @@ -3,30 +3,25 @@ def _generate_resource_utilities_impl(ctx): """Invoke a Python script to generate ResourceUtilities.cs from input files. - This rule does not inspect file contents itself; it just wires inputs/outputs - for the generator tool. + The mapping from C# property name to JS file is provided explicitly via the + 'resources' attribute as a dict: { "PropertyName": label }. """ args = ctx.actions.args() args.add("--output", ctx.outputs.out) - for src in ctx.files.srcs: + inputs = [] + for target, name in ctx.attr.resources.items(): + files = target.files.to_list() + if len(files) != 1: + fail("Each resource label must produce exactly one file, got {} for {}".format(len(files), name)) + src = files[0] + inputs.append(src) args.add("--input") - # Each --input is "identifier=path" - name = src.basename.rsplit(".", 1)[0] - # Starlark strings are not directly iterable into characters, so use - # a simple replacement-based sanitization: non-identifier characters - # are replaced with '_'. This is conservative but sufficient. - ident = name - ident = ident.replace("-", "_") - ident = ident.replace(".", "_") - ident = ident.replace(" ", "_") - if ident and ident[0].isdigit(): - ident = "_" + ident - args.add("%s=%s" % (ident, src.path)) + args.add("%s=%s" % (name, src.path)) ctx.actions.run( - inputs = ctx.files.srcs, + inputs = inputs, outputs = [ctx.outputs.out], executable = ctx.executable._tool, arguments = [args], @@ -37,7 +32,7 @@ def _generate_resource_utilities_impl(ctx): generated_resource_utilities = rule( implementation = _generate_resource_utilities_impl, attrs = { - "srcs": attr.label_list(allow_files = True), + "resources": attr.label_keyed_string_dict(allow_files = True), "out": attr.output(mandatory = True), "_tool": attr.label( default = Label("//dotnet/private:generate_resources_tool"), diff --git a/dotnet/private/generate_resources_tool.py b/dotnet/private/generate_resources_tool.py index 66813a7d30054..33491f18ed81d 100644 --- a/dotnet/private/generate_resources_tool.py +++ b/dotnet/private/generate_resources_tool.py @@ -21,37 +21,6 @@ from typing import List, Tuple -def to_camel_case(name: str) -> str: - """Convert an identifier like "find-elements" or "webdriver_json" to PascalCase. - - Non-alphanumeric characters are treated as separators; leading digits are preserved - but not used to start a new word. Example: - - "find-elements" -> "FindElements" - - "webdriver_json" -> "WebdriverJson" - - "1st-thing" -> "1stThing" - """ - parts: List[str] = [] - current: List[str] = [] - for ch in name: - if ch.isalnum(): - current.append(ch) - else: - if current: - parts.append("".join(current)) - current = [] - if current: - parts.append("".join(current)) - - if not parts: - return name - - # Capitalize every part (PascalCase) - result: List[str] = [] - for part in parts: - result.append(part[:1].upper() + part[1:]) - return "".join(result) - - def parse_args(argv: List[str]) -> argparse.Namespace: parser = argparse.ArgumentParser() parser.add_argument("--output", required=True) @@ -74,8 +43,7 @@ def parse_input_spec(spec: str) -> Tuple[str, str]: def generate(output: str, inputs: List[Tuple[str, str]]) -> None: props: List[str] = [] - for ident, path in inputs: - prop_name = to_camel_case(ident) + for prop_name, path in inputs: with open(path, "r", encoding="utf-8") as f: content = f.read() # Use a C# raw string literal with five quotes. For a valid raw diff --git a/dotnet/src/webdriver/BUILD.bazel b/dotnet/src/webdriver/BUILD.bazel index 52ee88b6eaceb..860c0bf34b459 100644 --- a/dotnet/src/webdriver/BUILD.bazel +++ b/dotnet/src/webdriver/BUILD.bazel @@ -28,13 +28,13 @@ generated_assembly_info( generated_resource_utilities( name = "resource-utilities", - srcs = [ - "//javascript/atoms/fragments:find-elements.js", - "//javascript/atoms/fragments:is-displayed.js", - "//javascript/cdp-support:mutation-listener.js", - "//javascript/webdriver/atoms:get-attribute.js", - "//third_party/js/selenium:webdriver_json", - ], + resources = { + "//javascript/atoms/fragments:find-elements.js": "FindElements", + "//javascript/atoms/fragments:is-displayed.js": "IsDisplayed", + "//javascript/cdp-support:mutation-listener.js": "MutationListener", + "//javascript/webdriver/atoms:get-attribute.js": "GetAttribute", + "//third_party/js/selenium:webdriver_json": "WebdriverPrefs", + }, out = "ResourceUtilities.g.cs", ) From edf658832060c8a05c2161fe904548c28b1e6570 Mon Sep 17 00:00:00 2001 From: Nikolay Borisenko <22616990+nvborisenko@users.noreply.github.com> Date: Tue, 18 Nov 2025 18:06:58 +0300 Subject: [PATCH 09/11] Meaningful resource names --- dotnet/src/webdriver/BUILD.bazel | 10 +++++----- dotnet/src/webdriver/Firefox/FirefoxExtension.cs | 2 +- dotnet/src/webdriver/Firefox/FirefoxProfile.cs | 2 +- dotnet/src/webdriver/JavaScriptEngine.cs | 2 +- dotnet/src/webdriver/RelativeBy.cs | 2 +- dotnet/src/webdriver/WebElement.cs | 4 ++-- 6 files changed, 11 insertions(+), 11 deletions(-) diff --git a/dotnet/src/webdriver/BUILD.bazel b/dotnet/src/webdriver/BUILD.bazel index 860c0bf34b459..9b01f9818a382 100644 --- a/dotnet/src/webdriver/BUILD.bazel +++ b/dotnet/src/webdriver/BUILD.bazel @@ -29,11 +29,11 @@ generated_assembly_info( generated_resource_utilities( name = "resource-utilities", resources = { - "//javascript/atoms/fragments:find-elements.js": "FindElements", - "//javascript/atoms/fragments:is-displayed.js": "IsDisplayed", - "//javascript/cdp-support:mutation-listener.js": "MutationListener", - "//javascript/webdriver/atoms:get-attribute.js": "GetAttribute", - "//third_party/js/selenium:webdriver_json": "WebdriverPrefs", + "//javascript/atoms/fragments:find-elements.js": "FindElementsAtom", + "//javascript/atoms/fragments:is-displayed.js": "IsDisplayedAtom", + "//javascript/cdp-support:mutation-listener.js": "MutationListenerAtom", + "//javascript/webdriver/atoms:get-attribute.js": "GetAttributeAtom", + "//third_party/js/selenium:webdriver_json": "WebDriverPrefsJson", }, out = "ResourceUtilities.g.cs", ) diff --git a/dotnet/src/webdriver/Firefox/FirefoxExtension.cs b/dotnet/src/webdriver/Firefox/FirefoxExtension.cs index f93109ff8395c..ddfe9f183e744 100644 --- a/dotnet/src/webdriver/Firefox/FirefoxExtension.cs +++ b/dotnet/src/webdriver/Firefox/FirefoxExtension.cs @@ -69,7 +69,7 @@ public void Install(string profileDirectory) // First, expand the .xpi archive into a temporary location. Directory.CreateDirectory(tempFileName); - using Stream zipFileStream = new MemoryStream(Encoding.UTF8.GetBytes(ResourceUtilities.WebdriverPrefs)); + using Stream zipFileStream = new MemoryStream(Encoding.UTF8.GetBytes(ResourceUtilities.WebDriverPrefsJson)); using (ZipArchive extensionZipArchive = new ZipArchive(zipFileStream, ZipArchiveMode.Read)) { extensionZipArchive.ExtractToDirectory(tempFileName); diff --git a/dotnet/src/webdriver/Firefox/FirefoxProfile.cs b/dotnet/src/webdriver/Firefox/FirefoxProfile.cs index 90b846262768a..7284973d066d2 100644 --- a/dotnet/src/webdriver/Firefox/FirefoxProfile.cs +++ b/dotnet/src/webdriver/Firefox/FirefoxProfile.cs @@ -297,7 +297,7 @@ private void UpdateUserPreferences(string profileDirectory) private Preferences ReadDefaultPreferences() { - using JsonDocument defaultPreferences = JsonDocument.Parse(ResourceUtilities.WebdriverPrefs); + using JsonDocument defaultPreferences = JsonDocument.Parse(ResourceUtilities.WebDriverPrefsJson); JsonElement immutableDefaultPreferences = defaultPreferences.RootElement.GetProperty("frozen"); JsonElement editableDefaultPreferences = defaultPreferences.RootElement.GetProperty("mutable"); diff --git a/dotnet/src/webdriver/JavaScriptEngine.cs b/dotnet/src/webdriver/JavaScriptEngine.cs index 3dea99ba51b71..d44f786a06943 100644 --- a/dotnet/src/webdriver/JavaScriptEngine.cs +++ b/dotnet/src/webdriver/JavaScriptEngine.cs @@ -140,7 +140,7 @@ public void StopEventMonitoring() public async Task EnableDomMutationMonitoring() { // Execute the script to have it enabled on the currently loaded page. - string script = ResourceUtilities.MutationListener; + string script = ResourceUtilities.MutationListenerAtom; await this.session.Value.Domains.JavaScript.Evaluate(script).ConfigureAwait(false); await this.AddScriptCallbackBinding(MonitorBindingName).ConfigureAwait(false); diff --git a/dotnet/src/webdriver/RelativeBy.cs b/dotnet/src/webdriver/RelativeBy.cs index 1ed946e02bf79..fa4d8878da1b9 100644 --- a/dotnet/src/webdriver/RelativeBy.cs +++ b/dotnet/src/webdriver/RelativeBy.cs @@ -36,7 +36,7 @@ public sealed class RelativeBy : By private static string GetWrappedAtom() { - string atom = ResourceUtilities.FindElements; + string atom = ResourceUtilities.FindElementsAtom; return string.Format(CultureInfo.InvariantCulture, "/* findElements */return ({0}).apply(null, arguments);", atom); } diff --git a/dotnet/src/webdriver/WebElement.cs b/dotnet/src/webdriver/WebElement.cs index 50c61a2997bb3..f54f510c701a1 100644 --- a/dotnet/src/webdriver/WebElement.cs +++ b/dotnet/src/webdriver/WebElement.cs @@ -200,7 +200,7 @@ public virtual bool Displayed get { Dictionary parameters = new Dictionary(); - string atom = GetWrappedAtom("is_displayed", ResourceUtilities.IsDisplayed); + string atom = GetWrappedAtom("is_displayed", ResourceUtilities.IsDisplayedAtom); parameters.Add("script", atom); parameters.Add("args", new object[] { ((IWebDriverObjectReference)this).ToDictionary() }); @@ -435,7 +435,7 @@ public virtual ReadOnlyCollection FindElements(string mechanism, st public virtual string? GetAttribute(string attributeName) { Dictionary parameters = new Dictionary(); - string atom = GetWrappedAtom("get_attribute", ResourceUtilities.GetAttribute); + string atom = GetWrappedAtom("get_attribute", ResourceUtilities.GetAttributeAtom); parameters.Add("script", atom); parameters.Add("args", new object[] { ((IWebDriverObjectReference)this).ToDictionary(), attributeName }); From dfdbd787fc42fe01ace0d56cacd02e3f1c9a3ec6 Mon Sep 17 00:00:00 2001 From: Nikolay Borisenko <22616990+nvborisenko@users.noreply.github.com> Date: Tue, 18 Nov 2025 20:31:02 +0300 Subject: [PATCH 10/11] Format? --- dotnet/private/BUILD.bazel | 1 - dotnet/private/generate_resources.bzl | 2 +- dotnet/private/generate_resources_tool.py | 4 +--- dotnet/src/webdriver/BUILD.bazel | 4 ++-- 4 files changed, 4 insertions(+), 7 deletions(-) diff --git a/dotnet/private/BUILD.bazel b/dotnet/private/BUILD.bazel index c7f653ad043ee..513181809463f 100644 --- a/dotnet/private/BUILD.bazel +++ b/dotnet/private/BUILD.bazel @@ -1,5 +1,4 @@ load("//dotnet/private:generate_resources.bzl", "generated_resource_utilities") - py_binary( name = "generate_resources_tool", srcs = ["generate_resources_tool.py"], diff --git a/dotnet/private/generate_resources.bzl b/dotnet/private/generate_resources.bzl index a2c7fb1f3562b..987de7670c70c 100644 --- a/dotnet/private/generate_resources.bzl +++ b/dotnet/private/generate_resources.bzl @@ -40,4 +40,4 @@ generated_resource_utilities = rule( cfg = "exec", ), }, -) \ No newline at end of file +) diff --git a/dotnet/private/generate_resources_tool.py b/dotnet/private/generate_resources_tool.py index 33491f18ed81d..b60ee6f02db92 100644 --- a/dotnet/private/generate_resources_tool.py +++ b/dotnet/private/generate_resources_tool.py @@ -56,9 +56,7 @@ def generate(output: str, inputs: List[Tuple[str, str]]) -> None: # # """"" literal = '"""""\n' + content + '\n"""""' - props.append( - f" internal const string {prop_name} = {literal};" - ) + props.append(f" internal const string {prop_name} = {literal};") lines: List[str] = [] lines.append("// ") diff --git a/dotnet/src/webdriver/BUILD.bazel b/dotnet/src/webdriver/BUILD.bazel index 9b01f9818a382..f2ae15320af30 100644 --- a/dotnet/src/webdriver/BUILD.bazel +++ b/dotnet/src/webdriver/BUILD.bazel @@ -1,5 +1,5 @@ load("//common:defs.bzl", "copy_file") -load("//dotnet:defs.bzl", "csharp_library", "devtools_version_targets", "framework", "generated_assembly_info", "nuget_pack", "generated_resource_utilities") +load("//dotnet:defs.bzl", "csharp_library", "devtools_version_targets", "framework", "generated_assembly_info", "generated_resource_utilities", "nuget_pack") load( "//dotnet:selenium-dotnet-version.bzl", @@ -28,6 +28,7 @@ generated_assembly_info( generated_resource_utilities( name = "resource-utilities", + out = "ResourceUtilities.g.cs", resources = { "//javascript/atoms/fragments:find-elements.js": "FindElementsAtom", "//javascript/atoms/fragments:is-displayed.js": "IsDisplayedAtom", @@ -35,7 +36,6 @@ generated_resource_utilities( "//javascript/webdriver/atoms:get-attribute.js": "GetAttributeAtom", "//third_party/js/selenium:webdriver_json": "WebDriverPrefsJson", }, - out = "ResourceUtilities.g.cs", ) csharp_library( From 93219445749ff7eb81cf1463b171f8b20643b8d0 Mon Sep 17 00:00:00 2001 From: Nikolay Borisenko <22616990+nvborisenko@users.noreply.github.com> Date: Tue, 18 Nov 2025 20:43:19 +0300 Subject: [PATCH 11/11] Format? --- dotnet/private/BUILD.bazel | 1 - dotnet/src/webdriver/BUILD.bazel | 1 - 2 files changed, 2 deletions(-) diff --git a/dotnet/private/BUILD.bazel b/dotnet/private/BUILD.bazel index 513181809463f..03a5687d9cf35 100644 --- a/dotnet/private/BUILD.bazel +++ b/dotnet/private/BUILD.bazel @@ -1,4 +1,3 @@ -load("//dotnet/private:generate_resources.bzl", "generated_resource_utilities") py_binary( name = "generate_resources_tool", srcs = ["generate_resources_tool.py"], diff --git a/dotnet/src/webdriver/BUILD.bazel b/dotnet/src/webdriver/BUILD.bazel index f2ae15320af30..0d57751f521e1 100644 --- a/dotnet/src/webdriver/BUILD.bazel +++ b/dotnet/src/webdriver/BUILD.bazel @@ -1,6 +1,5 @@ load("//common:defs.bzl", "copy_file") load("//dotnet:defs.bzl", "csharp_library", "devtools_version_targets", "framework", "generated_assembly_info", "generated_resource_utilities", "nuget_pack") - load( "//dotnet:selenium-dotnet-version.bzl", "ASSEMBLY_COMPANY",