-
-
Notifications
You must be signed in to change notification settings - Fork 8.7k
[adr] BiDi is an implementation mechanism, not a public API #17670
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
Open
titusfortner
wants to merge
3
commits into
SeleniumHQ:trunk
Choose a base branch
from
titusfortner:adr1
base: trunk
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+186
β0
Open
Changes from all commits
Commits
Show all changes
3 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| # Index of Decisions | ||
|
|
||
| * 0001 - BiDi is an implementation mechanism, not a public API |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,56 @@ | ||
| # NNNN. Title stating the decision as a fact | ||
|
|
||
| <!-- Good: "Clicks scroll elements into view before interacting" | ||
| Bad: "Click behavior" --> | ||
|
|
||
| - Status: Proposed <!-- Proposed | Accepted | Rejected | Superseded by [NNNN](NNNN-title.md) --> | ||
| - Date: YYYY-MM-DD <!-- date the status last changed --> | ||
| - Discussion: <!-- link to this record's PR; add prior issues/threads under Context --> | ||
|
|
||
| ## Context | ||
|
|
||
| What problem are we solving, and what forces are in tension? W3C spec language, user | ||
| expectations, existing behavior that differs between bindings, implementation constraints. | ||
| Link prior discussions (issues, TLC notes) here as background β but summarize them, since | ||
| this section must make sense without following any links. | ||
|
|
||
| ## Decision | ||
|
|
||
| The decision, stated in language-neutral terms. This is the normative part: what every | ||
| binding MUST do, and what is explicitly left to per-language idiom. Use code sketches per | ||
| language here if the API shape is part of what's being decided. | ||
|
|
||
| ## Considered options | ||
|
|
||
| - **Option A** β what it is; why it was rejected or accepted | ||
| - **Option B** β what it is; why it was rejected or accepted | ||
|
|
||
| <!-- Options must be mutually exclusive answers to the question stated in Context; if two | ||
| options could both be adopted, they are separate decisions and the document should be | ||
| split. Revise this section during review as alternatives are contested or added β the | ||
| merged record, not the PR thread, is the authoritative account of why each rejected | ||
| option was not chosen. --> | ||
|
|
||
| ## Consequences | ||
|
|
||
| What gets easier, what gets harder, what users will notice. Deprecations triggered by this | ||
| decision and their timelines. Follow-up decisions this one makes necessary. | ||
|
|
||
| ## Binding status | ||
|
|
||
| <!-- Update this table as bindings converge on the decision; table updates don't need | ||
| TLC review. "n/a" with a note if the decision doesn't apply to a binding. --> | ||
|
|
||
| | Binding | Status | Notes / tracking link | | ||
| |------------|---------|-----------------------| | ||
| | Java | pending | | | ||
| | Python | pending | | | ||
| | Ruby | pending | | | ||
| | .NET | pending | | | ||
| | JavaScript | pending | | | ||
|
|
||
| ## Appendix (optional) | ||
|
|
||
| Durable supporting material the decision relies on: benchmarks, spec excerpts, survey of | ||
| behavior in other tools. Delete this section if there is none β ephemeral evidence belongs | ||
| in the PR thread instead. |
56 changes: 56 additions & 0 deletions
56
docs/decisions/0001-bidi-is-an-implementation-mechanism.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,56 @@ | ||
| # 0001. BiDi is an implementation mechanism, not a public API | ||
|
|
||
| - Status: Proposed | ||
| - Date: 2026-06-11 | ||
| - Discussion: _PR pending_, https://github.com/SeleniumHQ/selenium/issues/17628 | ||
|
|
||
| ## Context | ||
|
|
||
| Bindings use WebDriver BiDi to implement and extend the Selenium API. This record | ||
| settles BiDi's relationship to the public API: what users program against, and where | ||
| protocol code lives. CDP was managed differently across the bindings, but all of them | ||
| resulted in users needing to understand CDP implementation details to work with it | ||
| to one extent or another. This is happening in BiDi the same way. | ||
|
|
||
| ## Decision | ||
|
|
||
| BiDi is an implementation mechanism, not a public API. New capabilities are exposed as | ||
| high-level, protocol-neutral APIs, idiomatic per language, subject to our standard | ||
| deprecation policy. Everything in a BiDi namespace is internal: still reachable for | ||
| anything not yet wrapped, but not documented and subject to change without warning. | ||
|
|
||
| A binding conforms when: | ||
|
|
||
| 1. The supported API never references BiDi β no types, methods, properties, or entry points. | ||
| 2. BiDi implementation code (including everything generated from CDDL) is visibly internal β marked per language convention as not intended for public consumption. | ||
|
|
||
| This includes removing/renaming: | ||
| * `HasBiDi` interface | ||
| * `bidi_connection`, `bidi`, `getBidi`, `AsBiDiAsync` methods | ||
| * `enable_bidi` methods in options | ||
|
|
||
| ## Considered options | ||
|
|
||
| 1. Expose the whole protocol as a public API (Rejected) | ||
| * not user-friendly syntax | ||
| 2. A supported-but-separate public protocol namespace (Rejected) | ||
| * multiple implementations are confusing | ||
| 3. Allow methods and classes to reference BiDi | ||
| * users shouldn't need to know the underlying implementation mechanism, things should just work without additional ceremony | ||
| 4. Internal implementation mechanism only (Accepted) | ||
|
|
||
| ## Consequences | ||
|
|
||
| - Users never need to know which protocol services a command. | ||
| - Each new capability requires API design work across bindings before it ships. | ||
| - Existing public surfaces that fail the conformance tests are brought in line per the deprecation policy, tracked below. | ||
|
|
||
| ## Binding status | ||
|
|
||
| | Binding | Status | Notes / tracking link | | ||
| |------------|---------|-----------------------| | ||
| | Java | pending | | | ||
| | Python | pending | | | ||
| | Ruby | pending | | | ||
| | .NET | pending | | | ||
| | JavaScript | pending | | | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,71 @@ | ||
| # Design Decisions | ||
|
|
||
| This directory is the log of design decisions that apply across the Selenium project β | ||
| one file per decision, numbered in the order they were proposed. | ||
|
|
||
| Selenium ships the same API in multiple languages. Decisions about user-visible behavior, | ||
| API shape, and cross-binding semantics need to be made once, recorded, and implemented | ||
| consistently everywhere. This log is the canonical record of those decisions: when a | ||
| question comes up in review, the answer should be a link to a file here. | ||
|
|
||
| ## What needs a decision record | ||
|
|
||
| - User-visible behavior that should be consistent across bindings: API naming and shape, | ||
| error types and messages, default timeouts, capability handling | ||
| - WebDriver Classic / BiDi semantics and how the protocol is exposed (or deliberately not exposed) | ||
| - Deprecation and backwards-compatibility commitments | ||
| - Anything the TLC has labeled [`A-needs-decision`](https://github.com/SeleniumHQ/selenium/labels/A-needs-decision) | ||
| and resolved | ||
|
|
||
| ## What doesn't | ||
|
|
||
| - Single-binding internals (a Java maintainer picking a data structure) | ||
| - Build tooling and infrastructure choices | ||
| - Anything cheaply reversible | ||
|
|
||
| When in doubt, ask whether the question is likely to be raised again. If it is, record the decision. | ||
|
|
||
| ## Process | ||
|
|
||
| 1. **Propose.** Anyone may propose: copy [0000-template.md](0000-template.md) to `NNNN-short-title.md` using the | ||
| next unused number, fill it in, and open a PR with `Status: Proposed`. Keep it to about a | ||
| page β if the debate already happened in an issue, the record can be short and link to it. | ||
| 2. **Discuss.** The PR thread is the discussion record. Decisions that need synchronous | ||
| discussion are raised at a TLC meeting; the outcome goes back into the PR. Disagreement | ||
| about the considered options is resolved by revising the document during review, so the | ||
| merged record reflects the debate accurately. The TLC sets its meeting agenda; proposals | ||
| advance as agenda time allows. | ||
| 3. **Decide.** The Selenium Project Lead merges the record once the approval requirements | ||
| below are met and discussion has run its course, with the status updated to `Accepted` β | ||
| merging constitutes acceptance. Proposals the TLC considers and declines are merged as | ||
| `Rejected`; proposals withdrawn or abandoned before TLC consideration are closed and the | ||
| number lapses. | ||
| 4. **Implement.** Each binding tracks its convergence in the decision's binding-status table. | ||
| Updating that table (and only that table) doesn't require TLC review. | ||
|
|
||
| ## Approval | ||
|
|
||
| - TLC members respond to a proposal with a GitHub review: an approval, a "no objection" | ||
| comment review (saw it, deferring to the others), or a request-changes review stating | ||
| what would resolve it. | ||
| - Records are accepted by consensus: a majority of TLC members have responded, none with | ||
| an unresolved objection. Before acceptance, a record must have been open at least one | ||
| week and an agenda item at a TLC meeting β no one should learn of a decision after it | ||
| is made. | ||
| - If substantive edits are made, the author re-requests reviews. | ||
| - An objection that revision cannot resolve β including support for a different considered | ||
| option β is discussed at a TLC meeting. If consensus still fails, the Selenium Project | ||
| Lead decides which position prevails; the record is updated to match, and overruled | ||
| dissent is summarized rather than erased. | ||
|
|
||
| ## Rules | ||
|
|
||
| - **A decision must stand alone.** A reader gets the decision, the rationale, and the rejected | ||
| alternatives without following any links; linked material is background, not required reading. | ||
| - **Accepted decisions are immutable**, except for the status line and the binding-status | ||
| table. Changing a decision means a new record that supersedes the old one β update the old | ||
| record's status to `Superseded by [NNNN](...)`. | ||
| - **Numbers are stable once merged.** They get cited in reviews and issues. If two open PRs | ||
| claim the same number, the later one renames before merge. Gaps in numbering are acceptable. | ||
| - **Durable supporting material goes in the record itself** (an Appendix section at the end). | ||
| Ephemeral evidence and debate stay in the PR thread. |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
Low-level API should be publicly available, it is power. But without warranties, spec is living doc. Not clear how to emphasize it per language. What I see: spec is trying to be not breaking changeable.
In .NET/C# we already funded a plan how to react on breaking changes. I really don't understand why low-level implementation should be
internal.. .NET is ready for changes.