Skip to content

[rb] generate BiDi domain type accessors and union variant factories - #17865

Merged
titusfortner merged 1 commit into
SeleniumHQ:trunkfrom
titusfortner:bidi-ruby-accessors
Aug 3, 2026
Merged

[rb] generate BiDi domain type accessors and union variant factories#17865
titusfortner merged 1 commit into
SeleniumHQ:trunkfrom
titusfortner:bidi-ruby-accessors

Conversation

@titusfortner

Copy link
Copy Markdown
Member

🔗 Related Issues

💥 What does this PR do?

  • Lets Ruby BiDi callers build the protocol types they send without the full BiDi::Protocol::<Domain>:: prefix or repeating a union's discriminator.
  • Each domain object gains short constructors for the types it sends, e.g. web_extension.extension_path(path: '/x') and web_extension.extension_data.path(path: '/x'), plus a vendor accessor for browser-specific variants, web_extension.moz.
  • Only types a caller sends get these; types you only receive back do not.

🔧 Implementation Notes

  • Scoped to send-side types on purpose, so the added surface is only what a caller constructs.
  • Generated from the shared schema, not a hand-maintained list.
  • A union's value type is modeled as its variants, so a concrete variant type-checks where the union is expected.
  • The vendor variant shares the domain's connection; Transport is never a public constructor argument.

🤖 AI assistance

  • AI assisted (complete below)
    • Tool(s): Claude Code
    • What was generated: generator + template changes, regenerated protocol modules and RBS, unit specs
    • I reviewed all AI output and can explain the change

🔄 Types of changes

  • New feature (non-breaking change which adds functionality and tests!)

@selenium-ci selenium-ci added C-rb Ruby Bindings B-devtools Includes everything BiDi or Chrome DevTools related B-support Issue or PR related to support classes labels Aug 3, 2026
@selenium-ci

Copy link
Copy Markdown
Member

Thank you, @titusfortner for this code suggestion.

The support packages contain example code that many users find helpful, but they do not necessarily represent
the best practices for using Selenium, and the Selenium team is not currently merging changes to them.

After reviewing the change, unless it is a critical fix or a feature that is needed for Selenium
to work, we will likely close the PR.

We actively encourage people to add the wrapper and helper code that makes sense for them to their own frameworks.
If you have any questions, please contact us

@qodo-code-review

Copy link
Copy Markdown
Contributor

PR Summary by Qodo

Generate Ruby BiDi domain type accessors and union variant factories

✨ Enhancement 🧪 Tests 🕐 40+ Minutes

Grey Divider

AI Description

• Add domain-scoped constructors for outbound BiDi protocol types (records and unions).
• Generate union variant factories and RBS union value aliases for better type-checking.
• Support vendor domain accessors sharing the same connection, with unit tests for coverage.
Diagram

graph TD
  schema[("BiDi schema") ] --> gen["bidi_generate.rb"] --> tmpl["Ruby/RBS templates"] --> proto["Generated domain API"]
  proto --> unions["Union variant factories"] --> rbs["RBS union aliases"]
  proto --> transport["Transport.connection"] --> vendor["Vendor domain (e.g. moz)"]
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Module-level factory helpers (not domain instance methods)
  • ➕ Avoids adding many instance methods to each Domain subclass
  • ➕ No need for collision detection against Object/Kernel
  • ➖ Worse ergonomics (caller still needs to qualify a module)
  • ➖ Harder to support vendor domains sharing connection in a uniform way
2. Only generate union variant factories (skip domain accessors)
  • ➕ Smaller API surface area
  • ➕ Still removes discriminator repetition for unions
  • ➖ Does not solve the long BiDi::Protocol:::: prefix problem
  • ➖ Call sites still need constant qualification for records

Recommendation: Keep the PR’s approach: schema-driven generation of outbound-only domain accessors plus union variant factories gives the best caller ergonomics while containing surface area. The added collision guard makes the method-expansion safer, and exposing Transport.connection (via a private Domain#connection) is a clean way to support vendor variants without making Transport a public constructor dependency.

Files changed (35) +919 / -94

Enhancement (33) +824 / -94
bluetooth.rbAdd outbound type accessors and union variant factories (Bluetooth) +8/-0

Add outbound type accessors and union variant factories (Bluetooth)

• Adds class-method factories for discriminated union variants (e.g., Accept/Cancel). Adds domain-level short constructors for outbound record types used by Bluetooth commands.

rb/lib/selenium/webdriver/bidi/protocol/bluetooth.rb

browser.rbAdd DownloadBehavior union accessor and factories (Browser) +7/-0

Add DownloadBehavior union accessor and factories (Browser)

• Introduces union variant factories for download behavior and a domain accessor returning the union class for dispatch. Enables callers to build Allowed/Denied variants without naming variant classes directly.

rb/lib/selenium/webdriver/bidi/protocol/browser.rb

browsing_context.rbAdd locator/clip unions factories and outbound constructors (BrowsingContext) +29/-0

Add locator/clip unions factories and outbound constructors (BrowsingContext)

• Adds variant factories for union types like Locator, ClipRectangle, and DownloadEndParams. Adds domain accessors for unions and record constructors, including nested synthetic value types needed for outbound payload construction.

rb/lib/selenium/webdriver/bidi/protocol/browsing_context.rb

domain.rbExpose connection on Domain for vendor sibling construction +4/-0

Expose connection on Domain for vendor sibling construction

• Adds a private Domain#connection helper that returns the underlying websocket connection via the transport. Enables vendor accessors (e.g., moz) to instantiate sibling domain variants without exposing Transport as a public argument.

rb/lib/selenium/webdriver/bidi/protocol/domain.rb

emulation.rbAdd outbound constructors for Emulation types +6/-0

Add outbound constructors for Emulation types

• Adds domain-level short constructors for outbound record types used by emulation commands (geolocation coordinates/errors, network conditions, screen structs).

rb/lib/selenium/webdriver/bidi/protocol/emulation.rb

input.rbAdd union variant factories and outbound constructors (Input) +37/-0

Add union variant factories and outbound constructors (Input)

• Adds variant factories for multiple unions (SourceActions, KeySourceAction, PointerSourceAction, WheelSourceAction, Origin). Adds domain-level accessors to construct outbound actions/parameters and to expose union classes for factory dispatch.

rb/lib/selenium/webdriver/bidi/protocol/input.rb

log.rbAdd Entry union variant factories (Log) +3/-0

Add Entry union variant factories (Log)

• Adds class-method factories for Log::Entry union variants (console/javascript), simplifying outbound construction of log entry records where applicable.

rb/lib/selenium/webdriver/bidi/protocol/log.rb

network.rbAdd union factories and outbound constructors (Network) +19/-0

Add union factories and outbound constructors (Network)

• Adds variant factories for BytesValue, UrlPattern, and ContinueWithAuthParameters discriminated variants. Adds domain-level constructors for outbound types (headers, cookies, auth credentials) and union accessors for dispatch.

rb/lib/selenium/webdriver/bidi/protocol/network.rb

permissions.rbAdd PermissionDescriptor outbound constructor (Permissions) +2/-0

Add PermissionDescriptor outbound constructor (Permissions)

• Adds a domain-level helper to build PermissionDescriptor records for set_permission calls without long constant qualification.

rb/lib/selenium/webdriver/bidi/protocol/permissions.rb

script.rbAdd union variant factories and outbound constructors (Script) +85/-0

Add union variant factories and outbound constructors (Script)

• Adds variant factories for Script unions (EvaluateResult, LocalValue, PrimitiveProtocolValue, RealmInfo, RemoteValue). Adds domain-level constructors/unions accessors for outbound-only types and updates the set of types exposed via accessors accordingly.

rb/lib/selenium/webdriver/bidi/protocol/script.rb

session.rbAdd ProxyConfiguration factories and outbound constructors (Session) +18/-0

Add ProxyConfiguration factories and outbound constructors (Session)

• Adds union variant factories for ProxyConfiguration and adds domain-level accessors for outbound capability and unsubscribe request types. Keeps command wrapper types excluded from accessors.

rb/lib/selenium/webdriver/bidi/protocol/session.rb

storage.rbAdd PartitionDescriptor factories and outbound constructors (Storage) +9/-0

Add PartitionDescriptor factories and outbound constructors (Storage)

• Adds union factories for PartitionDescriptor and adds domain-level constructors for cookie filter/partition/cookie records plus a union accessor for dispatch.

rb/lib/selenium/webdriver/bidi/protocol/storage.rb

user_agent_client_hints.rbAdd outbound constructors for client hints types +3/-0

Add outbound constructors for client hints types

• Adds domain-level constructors for ClientHintsMetadata and BrandVersion records to simplify building outbound payloads.

rb/lib/selenium/webdriver/bidi/protocol/user_agent_client_hints.rb

web_extension.rbAdd ExtensionData union factories, accessors, and vendor accessor (moz) +10/-0

Add ExtensionData union factories, accessors, and vendor accessor (moz)

• Adds class-method factories for ExtensionData variants and domain-level accessors for extension data/path/archive/base64 constructors. Adds a vendor accessor (moz) that builds a WebExtension::Moz domain using the same connection.

rb/lib/selenium/webdriver/bidi/protocol/web_extension.rb

bidi_generate.rbExtend generator IR to emit outbound accessors, union factories, and RBS aliases +220/-14

Extend generator IR to emit outbound accessors, union factories, and RBS aliases

• Introduces directionality (outbound/inbound) tracking on record/union IR nodes, computes which outbound types should be exposed as domain accessors, and adds collision detection against commands/inherited methods. Adds union variant factory generation and emits RBS union value aliases so union-typed fields accept concrete variants.

rb/lib/selenium/webdriver/bidi/support/bidi_generate.rb

module.rb.erbTemplate: emit union variant factories and domain accessors +19/-1

Template: emit union variant factories and domain accessors

• Updates Ruby module template to render per-union variant factory class methods and to emit domain accessors (record constructors, union accessors returning the class, and vendor accessors creating sibling domains).

rb/lib/selenium/webdriver/bidi/support/templates/module.rb.erb

module.rbs.erbTemplate: emit union value type aliases, factory signatures, and accessor signatures +18/-0

Template: emit union value type aliases, factory signatures, and accessor signatures

• Adds RBS type aliases for union value types (snake_cased), emits typed signatures for union variant factories, and adds typed signatures for the generated domain accessors (including unions returning singleton classes and vendor accessors).

rb/lib/selenium/webdriver/bidi/support/templates/module.rbs.erb

transport.rbExpose Transport#connection for internal domain construction +5/-0

Expose Transport#connection for internal domain construction

• Adds attr_reader :connection with documentation clarifying its use for building sibling domains (e.g., vendor variants) without surfacing Transport as a public constructor argument.

rb/lib/selenium/webdriver/bidi/transport.rb

bluetooth.rbsRBS: add union value alias and domain accessor signatures (Bluetooth) +8/-0

RBS: add union value alias and domain accessor signatures (Bluetooth)

• Adds a snake_cased union value alias for HandleRequestDevicePromptParameters and typed signatures for its variant factories. Adds typed signatures for generated domain constructors for outbound record types.

rb/sig/lib/selenium/webdriver/bidi/protocol/bluetooth.rbs

browser.rbsRBS: add union value aliases and DownloadBehavior accessor +12/-5

RBS: add union value aliases and DownloadBehavior accessor

• Adds snake_cased type aliases for unions (e.g., download_behavior) and updates fields/params to use those aliases. Adds variant factory signatures and the domain-level union accessor signature.

rb/sig/lib/selenium/webdriver/bidi/protocol/browser.rbs

browsing_context.rbsRBS: add locator/clip/download_end union aliases and domain accessors +34/-5

RBS: add locator/clip/download_end union aliases and domain accessors

• Adds union value aliases (locator, clip_rectangle, download_end_params) and updates command parameter typing to refer to aliases. Adds signatures for union factories and for generated outbound constructors, including nested value records.

rb/sig/lib/selenium/webdriver/bidi/protocol/browsing_context.rbs

domain.rbsRBS: add private Domain#connection signature +2/-0

RBS: add private Domain#connection signature

• Declares the new private connection method used by vendor accessors to build sibling domain variants over the same websocket connection.

rb/sig/lib/selenium/webdriver/bidi/protocol/domain.rbs

emulation.rbsRBS: add SetGeolocationOverrideParameters union alias and constructors +7/-0

RBS: add SetGeolocationOverrideParameters union alias and constructors

• Adds a union value alias for set_geolocation_override_parameters and typed signatures for generated outbound constructors used by emulation commands.

rb/sig/lib/selenium/webdriver/bidi/protocol/emulation.rbs

input.rbsRBS: model input unions as value aliases and add factories/accessors +48/-11

RBS: model input unions as value aliases and add factories/accessors

• Adds union value aliases (source_actions, key_source_action, pointer_source_action, wheel_source_action, origin) and updates record fields to use them. Adds typed variant factory signatures and domain accessor signatures for building outbound actions.

rb/sig/lib/selenium/webdriver/bidi/protocol/input.rbs

log.rbsRBS: add Entry union alias and variant factory signatures +6/-2

RBS: add Entry union alias and variant factory signatures

• Adds a union value alias for log entry and typed signatures for console/javascript factories, plus updates affected record field types to use the appropriate union alias from Script where needed.

rb/sig/lib/selenium/webdriver/bidi/protocol/log.rbs

network.rbsRBS: add bytes_value/url_pattern/auth union aliases and accessors +35/-16

RBS: add bytes_value/url_pattern/auth union aliases and accessors

• Adds union value aliases (bytes_value, url_pattern, continue_with_auth_parameters) and updates record field types to use them. Adds typed variant factory signatures and domain accessor signatures for outbound record/union construction.

rb/sig/lib/selenium/webdriver/bidi/protocol/network.rbs

permissions.rbsRBS: add PermissionDescriptor accessor signature +1/-0

RBS: add PermissionDescriptor accessor signature

• Adds the typed domain accessor signature for constructing PermissionDescriptor outbound records.

rb/sig/lib/selenium/webdriver/bidi/protocol/permissions.rbs

script.rbsRBS: add multiple union value aliases and factory/accessor signatures (Script) +112/-25

RBS: add multiple union value aliases and factory/accessor signatures (Script)

• Introduces snake_cased value aliases for key Script unions (remote_value, local_value, realm_info, target, etc.) and updates many record fields/params to use those aliases. Adds typed signatures for union variant factories and generated outbound constructors.

rb/sig/lib/selenium/webdriver/bidi/protocol/script.rbs

session.rbsRBS: add proxy/unsubscribe union aliases and generated accessors +21/-2

RBS: add proxy/unsubscribe union aliases and generated accessors

• Adds union value aliases for proxy_configuration and unsubscribe_parameters and updates capability types to use the alias where referenced. Adds typed signatures for union variant factories and domain-level outbound constructors.

rb/sig/lib/selenium/webdriver/bidi/protocol/session.rbs

storage.rbsRBS: add partition_descriptor union alias and outbound constructors +18/-9

RBS: add partition_descriptor union alias and outbound constructors

• Adds a union value alias for partition_descriptor and updates command parameter types accordingly. Adds typed signatures for union factories and the generated domain constructors for cookie/partition records.

rb/sig/lib/selenium/webdriver/bidi/protocol/storage.rbs

user_agent_client_hints.rbsRBS: add outbound constructor signatures for client hints types +2/-0

RBS: add outbound constructor signatures for client hints types

• Adds typed domain accessor signatures for constructing ClientHintsMetadata and BrandVersion records for outbound use.

rb/sig/lib/selenium/webdriver/bidi/protocol/user_agent_client_hints.rbs

web_extension.rbsRBS: add extension_data union alias, factories, accessors, and moz vendor accessor +14/-4

RBS: add extension_data union alias, factories, accessors, and moz vendor accessor

• Adds the extension_data union value alias and typed variant factory signatures. Adds typed domain accessor signatures for constructors and for moz vendor domain creation; updates install signatures to accept the union value alias.

rb/sig/lib/selenium/webdriver/bidi/protocol/web_extension.rbs

transport.rbsRBS: add Transport#connection reader +2/-0

RBS: add Transport#connection reader

• Declares the new connection reader on Transport to match the Ruby implementation and support vendor domain construction plumbing.

rb/sig/lib/selenium/webdriver/bidi/transport.rbs

Tests (2) +95 / -0
protocol_spec.rbAdd unit tests for outbound type accessors, factories, and vendor domains +59/-0

Add unit tests for outbound type accessors, factories, and vendor domains

• Adds coverage asserting unions are exposed as class-returning accessors, records are constructed via short methods, union factories produce correct variants, vendor domains share the connection, and inbound-only / wrapper types are not exposed.

rb/spec/unit/selenium/webdriver/bidi/protocol_spec.rb

bidi_generate_spec.rbAdd generator tests for accessor collision detection +36/-0

Add generator tests for accessor collision detection

• Introduces unit tests for BiDiGenerate.check_accessor_collisions! to prevent schema-driven accessors from shadowing commands, inherited methods, or each other.

rb/spec/unit/selenium/webdriver/bidi/support/bidi_generate_spec.rb

@qodo-code-review

qodo-code-review Bot commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

Code Review by Qodo

🐞 Bugs (1) 📘 Rule violations (0) 📎 Requirement gaps (0) 🎨 UX issues (0) 🔗 Cross-repo conflicts (0) 📜 Skill insights (0)

Grey Divider


Action required

1. Missing Set require 🐞 Bug ≡ Correctness
Description
bidi_generate.rb now uses Set and to_set but never requires Ruby’s set stdlib, so running
the generator can raise NameError: uninitialized constant Set or NoMethodError for to_set
depending on which code path executes first. This can break protocol/RBS regeneration outside
environments that happen to load set indirectly.
Code

rb/lib/selenium/webdriver/bidi/support/bidi_generate.rb[R591-593]

+    def command_wrapper_refs(domain)
+      commands_for(domain).flat_map { |c| [c.dig('params', 'ref'), c.dig('result', 'ref')] }.compact.to_set
+    end
Evidence
The file’s requires include json, erb, and fileutils but not set, while new code paths call
.to_set and instantiate Set.new, which are only available after loading the set stdlib.

rb/lib/selenium/webdriver/bidi/support/bidi_generate.rb[20-24]
rb/lib/selenium/webdriver/bidi/support/bidi_generate.rb[587-603]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`rb/lib/selenium/webdriver/bidi/support/bidi_generate.rb` uses `Set` / `Enumerable#to_set` but does not `require 'set'`, which can cause the generator to crash when invoked in a clean Ruby process.

### Issue Context
The generator is executed via `bazel run //rb/lib/selenium/webdriver:bidi-generate` and should be self-contained with respect to stdlib dependencies.

### Fix
Add `require 'set'` alongside the other top-level requires near the top of `bidi_generate.rb`.

### Fix Focus Areas
- rb/lib/selenium/webdriver/bidi/support/bidi_generate.rb[20-24]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

2. RBS union types renamed ✗ Dismissed 📘 Rule violation ⚙ Maintainability
Description
Several public RBS signatures were changed to use new snake_case union value aliases (e.g.
proxy_configuration, locator) instead of the existing union classes (e.g. ProxyConfiguration,
Locator). This can break downstream users who annotate types against the previous RBS API without
any deprecation path.
Code

rb/sig/lib/selenium/webdriver/bidi/protocol/session.rbs[R28-30]

+          type proxy_configuration = ::Selenium::WebDriver::BiDi::Protocol::Session::AutodetectProxyConfiguration | ::Selenium::WebDriver::BiDi::Protocol::Session::DirectProxyConfiguration | ::Selenium::WebDriver::BiDi::Protocol::Session::ManualProxyConfiguration | ::Selenium::WebDriver::BiDi::Protocol::Session::PacProxyConfiguration | ::Selenium::WebDriver::BiDi::Protocol::Session::SystemProxyConfiguration
+          type unsubscribe_parameters = ::Selenium::WebDriver::BiDi::Protocol::Session::UnsubscribeByAttributesRequest | ::Selenium::WebDriver::BiDi::Protocol::Session::UnsubscribeByIDRequest
+
Evidence
PR Compliance ID 1 requires avoiding breaking public functionality without deprecation. This PR
changes shipped RBS type names used in public method signatures by introducing snake_case union
value aliases (e.g. type proxy_configuration = ...) and then updating method signatures to
reference those new aliases, which can break downstream type annotations relying on the previous RBS
API.

AGENTS.md: Maintain API/ABI Compatibility and Use Deprecation Before Removing Public Functionality
rb/sig/lib/selenium/webdriver/bidi/protocol/session.rbs[28-30]
rb/sig/lib/selenium/webdriver/bidi/protocol/browser.rbs[111-116]
rb/sig/lib/selenium/webdriver/bidi/protocol/browsing_context.rbs[195-214]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Public RBS method signatures were changed from union classes (e.g. `Session::ProxyConfiguration`) to new snake_case union value aliases (e.g. `Session::proxy_configuration`). This is a compatibility risk for downstream typed Ruby users who explicitly annotate using the previous class names.

## Issue Context
The PR introduces `type ... = ...` aliases for union *value* types and updates signatures to use those aliases. To preserve compatibility, consider widening each new alias to also accept the prior union class name (even if uninhabited), or otherwise provide a transition path documented/deprecated.

## Fix Focus Areas
- rb/sig/lib/selenium/webdriver/bidi/protocol/session.rbs[28-30]
- rb/sig/lib/selenium/webdriver/bidi/protocol/browser.rbs[30-33]
- rb/sig/lib/selenium/webdriver/bidi/protocol/browsing_context.rbs[40-43]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

To customize comments, go to the Qodo configuration screen, or learn more in the docs.

Qodo Logo

Comment thread rb/sig/lib/selenium/webdriver/bidi/protocol/session.rbs
Comment thread rb/lib/selenium/webdriver/bidi/support/bidi_generate.rb
@titusfortner
titusfortner merged commit 5b1cde1 into SeleniumHQ:trunk Aug 3, 2026
27 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

B-devtools Includes everything BiDi or Chrome DevTools related B-support Issue or PR related to support classes C-rb Ruby Bindings

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants