|
| 1 | +# 17670. BiDi implementation boundaries |
| 2 | + |
| 3 | +- Status: Proposed |
| 4 | +- Discussion: https://github.com/SeleniumHQ/selenium/pull/17670 |
| 5 | + |
| 6 | +## Context |
| 7 | + |
| 8 | +Bindings use WebDriver BiDi to implement and extend the Selenium API. This record settles what |
| 9 | +users program against: where the supported API ends and the internal BiDi implementation begins. |
| 10 | + |
| 11 | +No binding conforms yet: each exposes BiDi implementation details from the driver object rather |
| 12 | +than keeping them internal. |
| 13 | + |
| 14 | +| Binding | Current behavior | |
| 15 | +|------------|------------------| |
| 16 | +| Java | Driver exposes the raw BiDi connection (`HasBiDi.getBiDi()`); protocol types are public | |
| 17 | +| Python | `driver.network` / `driver.script` are the right high-level names, but return the low-level BiDi modules (`bidi`-namespaced) instead of neutral wrappers | |
| 18 | +| Ruby | Driver exposes a BiDi accessor (`driver.bidi`) | |
| 19 | +| .NET | Driver extension returns a BiDi type (`AsBiDiAsync()` → `IBiDi`) | |
| 20 | +| JavaScript | Driver exposes a BiDi accessor (`driver.getBidi()`) | |
| 21 | + |
| 22 | +All bindings also expose a BiDi-named option to enable the session (`enableBiDi` / `enable_bidi`), |
| 23 | +which can be renamed to be protocol-neutral. |
| 24 | + |
| 25 | +## Decision |
| 26 | + |
| 27 | +BiDi is an implementation mechanism, not a public API. Three decisions follow: |
| 28 | + |
| 29 | +1. **The supported API is protocol-neutral.** It never references BiDi — no BiDi types, and |
| 30 | + nothing that hands a user a BiDi object. Users program against the Selenium API and its |
| 31 | + high-level APIs, under the deprecation policy. |
| 32 | +2. **The BiDi implementation is internal and unsupported.** It faithfully implements the |
| 33 | + commands, events, and modules of the BiDi spec (and could be generated from the CDDL). It |
| 34 | + stays publicly reachable but is not governed by the deprecation policy: the spec is written to |
| 35 | + be stable, but because it is not ours we do not guarantee it. Each binding marks it internal |
| 36 | + by its own convention. |
| 37 | +3. **Low-level access is by composition, never off the driver.** The implementation is reached |
| 38 | + by composing it with the driver — `BiDi::Protocol::Network.new(driver)` — never exposed as a |
| 39 | + member of the driver, because anything reachable off the driver reads implicitly as supported. |
| 40 | + |
| 41 | +Everything else — orchestration, event dispatch, socket listening, transport — is an |
| 42 | +implementation detail, likely private, left to each binding. |
| 43 | + |
| 44 | +Marking a surface *Beta* does not satisfy decision 2 — Beta signals an API becoming supported, |
| 45 | +the opposite of internal. |
| 46 | + |
| 47 | +Illustratively (Ruby): |
| 48 | + |
| 49 | +```ruby |
| 50 | +driver.network.add_request_handler(...) # supported — neutral, returns no BiDi type |
| 51 | +BiDi::Protocol::Network.new(driver).add_intercept(...) # internal — composed with the driver, unsupported |
| 52 | +driver.bidi.network.add_intercept(...) # not allowed — internal exposed as a driver member |
| 53 | +``` |
| 54 | + |
| 55 | +## Considered options |
| 56 | + |
| 57 | +1. Expose the whole protocol as a public API (Rejected) |
| 58 | + * the internal layer faithfully implements a living spec, so we cannot guarantee its stability — it can't be committed to as supported, public API |
| 59 | +2. A supported, separate "mid-level" API for working with the internal BiDi implementation (Rejected) |
| 60 | + * protocol coupling — users build on BiDi-shaped concepts, the same trap CDP created |
| 61 | + * two supported surfaces — a protocol-neutral high-level one and a BiDi-shaped mid-level one — leave users unsure which to reach for |
| 62 | +3. Expose the internal implementation as a driver member, e.g. `driver.bidi.network` (Rejected) |
| 63 | + * a member of the driver reads implicitly as supported; composing the class with the driver instead keeps it distinct |
| 64 | +4. Internal implementation mechanism only, reached by composing with the driver (Accepted) |
| 65 | + |
| 66 | +## Consequences |
| 67 | + |
| 68 | +- Users never need to know which protocol services a command. |
| 69 | +- Existing public surfaces that fail conformance are brought in line per the deprecation policy. |
| 70 | +- Specific supported API behavior is specified in other ADRs. |
0 commit comments