Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions common/bidi/digital-credentials-command.cddl
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
; The Digital Credentials spec defines digitalCredentials.SetVirtualWalletBehavior but no
; DigitalCredentialsCommand aggregate, which is the only way generation discovers a command.
; Delete once the spec adds the aggregate and the pinned webref carries it.
; https://github.com/w3c-fedid/digital-credentials
DigitalCredentialsCommand = (
digitalCredentials.SetVirtualWalletBehavior
)
95 changes: 68 additions & 27 deletions common/bidi/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -852,6 +852,15 @@
"ref": "bluetooth.SimulateDescriptorResponseParameters"
},
"result": null
},
{
"domain": "digitalCredentials",
"method": "digitalCredentials.setVirtualWalletBehavior",
"name": "setVirtualWalletBehavior",
"params": {
"ref": "digitalCredentials.SetVirtualWalletBehaviorParameters"
},
"result": null
}
],
"events": [
Expand Down Expand Up @@ -1077,6 +1086,22 @@
"ref": "bluetooth.GattConnectionAttemptedParameters"
}
},
{
"domain": "bluetooth",
"method": "bluetooth.characteristicEventGenerated",
"name": "characteristicEventGenerated",
"params": {
"ref": "bluetooth.CharacteristicEventGeneratedParameters"
}
},
{
"domain": "bluetooth",
"method": "bluetooth.descriptorEventGenerated",
"name": "descriptorEventGenerated",
"params": {
"ref": "bluetooth.DescriptorEventGeneratedParameters"
}
},
{
"domain": "log",
"method": "log.entryAdded",
Expand Down Expand Up @@ -14764,7 +14789,7 @@
}
],
"specHref": "https://w3c-fedid.github.io/digital-credentials/#cddl-type-digitalcredentials-setvirtualwalletbehaviorparameters",
"outbound": false,
"outbound": true,
"inbound": false
},
"digitalCredentials.SetVirtualWalletBehavior": {
Expand Down Expand Up @@ -16204,30 +16229,6 @@
"outbound": true,
"inbound": false
},
"BluetoothEvent": {
"kind": "union",
"variants": [
"bluetooth.RequestDevicePromptUpdated",
"bluetooth.GattConnectionAttempted"
],
"specHref": "https://bluetooth.spec.whatwg.org/#cddl-type-bluetoothevent",
"selector": {
"by": "method",
"variants": [
{
"value": "bluetooth.requestDevicePromptUpdated",
"ref": "bluetooth.RequestDevicePromptUpdated"
},
{
"value": "bluetooth.gattConnectionAttempted",
"ref": "bluetooth.GattConnectionAttempted"
}
]
},
"objectOnly": true,
"outbound": false,
"inbound": false
},
"bluetooth.RequestDevicePromptUpdated": {
"kind": "record",
"fields": [
Expand Down Expand Up @@ -16414,7 +16415,7 @@
],
"specHref": "https://bluetooth.spec.whatwg.org/#cddl-type-bluetoothcharacteristiceventgeneratedparameters",
"outbound": false,
"inbound": false
"inbound": true
},
"bluetooth.DescriptorEventGenerated": {
"kind": "record",
Expand Down Expand Up @@ -16504,6 +16505,46 @@
],
"specHref": "https://bluetooth.spec.whatwg.org/#cddl-type-bluetoothdescriptoreventgeneratedparameters",
"outbound": false,
"inbound": true
},
"DigitalCredentialsCommand": {
"kind": "alias",
"type": {
"ref": "digitalCredentials.SetVirtualWalletBehavior"
}
},
"BluetoothEvent": {
"kind": "union",
"variants": [
"bluetooth.RequestDevicePromptUpdated",
"bluetooth.GattConnectionAttempted",
"bluetooth.CharacteristicEventGenerated",
"bluetooth.DescriptorEventGenerated"
],
"specHref": "https://bluetooth.spec.whatwg.org/#cddl-type-bluetoothevent",
"selector": {
"by": "method",
"variants": [
{
"value": "bluetooth.requestDevicePromptUpdated",
"ref": "bluetooth.RequestDevicePromptUpdated"
},
{
"value": "bluetooth.gattConnectionAttempted",
"ref": "bluetooth.GattConnectionAttempted"
},
{
"value": "bluetooth.characteristicEventGenerated",
"ref": "bluetooth.CharacteristicEventGenerated"
},
{
"value": "bluetooth.descriptorEventGenerated",
"ref": "bluetooth.DescriptorEventGenerated"
}
]
},
"objectOnly": true,
"outbound": false,
"inbound": false
},
"webExtension.InstallParameters": {
Expand Down Expand Up @@ -17652,7 +17693,7 @@
"synthetic": true,
"owner": "digitalCredentials.SetVirtualWalletBehaviorParameters",
"label": "Response",
"outbound": false,
"outbound": true,
"inbound": false
},
"userAgentClientHints.SetClientHintsOverrideCommandParams": {
Expand Down
10 changes: 10 additions & 0 deletions common/bidi/web-bluetooth-events.cddl
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
; The Web Bluetooth spec defines all four bluetooth events but lists only two in its
; BluetoothEvent aggregate, which is the only way generation discovers an event.
; Delete once the spec lists all four and the pinned webref carries it.
; https://github.com/WebBluetoothCG/web-bluetooth
BluetoothEvent = (
bluetooth.RequestDevicePromptUpdated //
bluetooth.GattConnectionAttempted //
bluetooth.CharacteristicEventGenerated //
bluetooth.DescriptorEventGenerated
)
2 changes: 1 addition & 1 deletion common/webref_cddl.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ see scripts/update_cddl.py for how they are resolved and when the pins advance.
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_file")

# The w3c/webref "main" commit every CDDL grammar and dfns index below is taken from.
_COMMIT = "580ef268abf6917b6d3fc674cc6d80e754b06e2c"
_COMMIT = "a0506ac035dfcb3c1e6c0be9127be0b28f15a534"
_CDDL_BASE_URL = "https://raw.githubusercontent.com/w3c/webref/{commit}/ed/cddl".format(commit = _COMMIT)
_DFNS_BASE_URL = "https://raw.githubusercontent.com/w3c/webref/{commit}/ed/dfns".format(commit = _COMMIT)

Expand Down
7 changes: 5 additions & 2 deletions javascript/selenium-webdriver/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -94,9 +94,12 @@ generate_bidi_library(
dfns_files = BIDI_DFNS_FILES,
enhancements_manifest = "//javascript/selenium-webdriver/private:bidi_enhancements_manifest",
extra_cddl_files = BIDI_EXTENSION_CDDL_FILES,
# The local #1140 extension point (supersedes the upstream closed InstallParameters): spec-
# shaped and browser-neutral, it only opens the map. Stays in the shared schema.
# Spec-shaped, browser-neutral productions that supersede an upstream one by name. Stay
# in the shared schema. #1140 opens the webExtension.install map; the other two complete
# command/event aggregates the specs define members for but never list.
override_cddl_files = [
"//common/bidi:digital-credentials-command.cddl",
"//common/bidi:web-bluetooth-events.cddl",
"//common/bidi:webdriver-bidi-1140.cddl",
],
# The pinned rendered core spec. The schema step extracts its prose section anchors
Expand Down
30 changes: 9 additions & 21 deletions javascript/selenium-webdriver/generate_bidi.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -36,29 +36,11 @@ import { parseArgs } from 'node:util'
// Domain configuration
// ============================================================

// Maps the domain segment in a BiDi method string (e.g. "browsingContext"
// from "browsingContext.activate") to a canonical domain key.
const METHOD_DOMAIN_MAP = {
browser: 'browser',
browsingContext: 'browsingContext',
emulation: 'emulation',
input: 'input',
log: 'log',
network: 'network',
permissions: 'permissions',
script: 'script',
session: 'session',
speculation: 'speculation',
storage: 'storage',
userAgentClientHints: 'userAgentClientHints',
webExtension: 'webExtension',
bluetooth: 'bluetooth',
}

// Maps TypeScript export name prefixes to domain keys.
// Ordered longest-first so the most specific prefix always wins.
const NAME_PREFIX_TO_DOMAIN = [
['UserAgentClientHints', 'userAgentClientHints'],
['DigitalCredentials', 'digitalCredentials'],
['BrowsingContext', 'browsingContext'],
['WebExtension', 'webExtension'],
['Permissions', 'permissions'],
Expand Down Expand Up @@ -90,6 +72,7 @@ const DOMAIN_FILES = {
userAgentClientHints: 'user_agent_client_hints.ts',
webExtension: 'webextension.ts',
bluetooth: 'bluetooth.ts',
digitalCredentials: 'digital_credentials.ts',
common: 'common.ts',
}

Expand All @@ -110,6 +93,7 @@ const DOMAIN_CLASSES = {
userAgentClientHints: 'UserAgentClientHints',
webExtension: 'WebExtension',
bluetooth: 'Bluetooth',
digitalCredentials: 'DigitalCredentials',
}

// ============================================================
Expand Down Expand Up @@ -300,6 +284,11 @@ function generateTypeScript(ast, model, args) {
const specVersion = args['spec-version']
const enhancements = loadEnhancements(args.enhancements)

const unmapped = Object.keys(model).filter((d) => !(d in DOMAIN_FILES))
if (unmapped.length) {
throw new Error(`model domains without a DOMAIN_FILES/DOMAIN_CLASSES entry: ${unmapped.join(', ')}`)
}

console.log('Pass 1: generating types via cddl2ts…')
const rawTypes = transform(ast)
const cleanTypes = postProcessTypes(rawTypes)
Expand Down Expand Up @@ -648,9 +637,8 @@ function parseLeafDef(def) {
const dotIdx = methodStr.indexOf('.')
if (dotIdx === -1) return null

const domainRaw = methodStr.slice(0, dotIdx)
const domain = methodStr.slice(0, dotIdx)
const operationName = methodStr.slice(dotIdx + 1)
const domain = METHOD_DOMAIN_MAP[domainRaw] ?? 'common'

const paramsTypeEntries = Array.isArray(paramsProp.Type) ? paramsProp.Type : [paramsProp.Type]
let paramsCddl = null
Expand Down
1 change: 1 addition & 0 deletions javascript/selenium-webdriver/private/generate_bidi.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ _DOMAIN_TS_FILES = [
"browser.ts",
"browsing_context.ts",
"common.ts",
"digital_credentials.ts",
"emulation.ts",
"input.ts",
"log.ts",
Expand Down
20 changes: 1 addition & 19 deletions javascript/selenium-webdriver/project_bidi_schema.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -78,18 +78,6 @@ import { normalizeAst } from './normalize_bidi_ast.mjs'
// normalizer turns into a `union`. A scan of all spec comments confirms none, so
// no separate constraint representation is carried.

// Methods that parse into the AST but are not wired into the model because the
// upstream spec leaves them out of its command/event aggregate (Bluetooth lists two
// of its four events; Digital Credentials defines no command aggregate at all).
// Allowlisted so they do not fail the build; checkCompleteness() flags an entry
// as stale once it becomes emitted (e.g. after the spec is fixed upstream), so
// this list cannot silently rot.
const KNOWN_INCOMPLETE = new Set([
'bluetooth.characteristicEventGenerated',
'bluetooth.descriptorEventGenerated',
'digitalCredentials.setVirtualWalletBehavior',
])

const PRIMITIVES = {
text: 'string',
tstr: 'string',
Expand Down Expand Up @@ -994,13 +982,7 @@ export function checkCompleteness(rawAst, schema) {
const methodProp = (def.Properties ?? []).flat().find((p) => p?.Name === 'method')
const literal = methodProp && (Array.isArray(methodProp.Type) ? methodProp.Type[0] : methodProp.Type)
if (literal?.Type !== 'literal') continue
if (!emitted.has(literal.Value) && !KNOWN_INCOMPLETE.has(literal.Value))
errors.push(`dropped from schema: ${literal.Value}`)
}
// Self-cleaning: if a known-incomplete method is now emitted, the entry is
// stale and must be removed β€” so the allowlist cannot silently rot.
for (const known of KNOWN_INCOMPLETE) {
if (emitted.has(known)) errors.push(`stale KNOWN_INCOMPLETE entry (now emitted, remove it): ${known}`)
if (!emitted.has(literal.Value)) errors.push(`dropped from schema: ${literal.Value}`)
}
// Every structured type must carry both directionality flags β€” a missing one means
// the pass skipped a node. `(false, false)` is a valid combination (a type in no
Expand Down
21 changes: 0 additions & 21 deletions javascript/selenium-webdriver/project_bidi_schema_test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -619,27 +619,6 @@ describe('checkCompleteness (input vs output, generator-independent)', () => {
const errors = checkCompleteness(astWithExtra, schema)
assert.deepEqual(errors, ['dropped from schema: network.droppedCmd'])
})

it('does not fail for a known-incomplete (allowlisted) drop', () => {
const astWithKnown = [
...AST,
leaf('bluetooth.X', 'bluetooth.characteristicEventGenerated', 'network.SetCacheBehaviorParameters'),
]
assert.deepEqual(checkCompleteness(astWithKnown, projectSchema(AST, MODEL)), [])
})

it('flags an allowlisted method as stale once it is emitted', () => {
const schema = projectSchema(AST, MODEL)
schema.events.push({
domain: 'bluetooth',
method: 'bluetooth.characteristicEventGenerated',
name: 'characteristicEventGenerated',
params: null,
})
assert.deepEqual(checkCompleteness(AST, schema), [
'stale KNOWN_INCOMPLETE entry (now emitted, remove it): bluetooth.characteristicEventGenerated',
])
})
})

describe('specHref (spec-definition links from the webref dfns index)', () => {
Expand Down
1 change: 1 addition & 0 deletions py/private/generate_bidi_protocol.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ _MODULES = [
"bluetooth",
"browser",
"browsing_context",
"digital_credentials",
"emulation",
"input",
"log",
Expand Down
1 change: 1 addition & 0 deletions rb/lib/selenium/webdriver/bidi/protocol.rb
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
require 'selenium/webdriver/bidi/protocol/bluetooth'
require 'selenium/webdriver/bidi/protocol/browser'
require 'selenium/webdriver/bidi/protocol/browsing_context'
require 'selenium/webdriver/bidi/protocol/digital_credentials'
require 'selenium/webdriver/bidi/protocol/emulation'
require 'selenium/webdriver/bidi/protocol/input'
require 'selenium/webdriver/bidi/protocol/log'
Expand Down
8 changes: 6 additions & 2 deletions rb/lib/selenium/webdriver/bidi/protocol/bluetooth.rb
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,9 @@ module Protocol
class Bluetooth < Domain
EVENTS = {
request_device_prompt_updated: 'bluetooth.requestDevicePromptUpdated',
gatt_connection_attempted: 'bluetooth.gattConnectionAttempted'
gatt_connection_attempted: 'bluetooth.gattConnectionAttempted',
characteristic_event_generated: 'bluetooth.characteristicEventGenerated',
descriptor_event_generated: 'bluetooth.descriptorEventGenerated'
}.freeze

SIMULATE_ADAPTER_PARAMETERS_STATE = {
Expand Down Expand Up @@ -325,7 +327,9 @@ def self.false(**) = Bluetooth::HandleRequestDevicePromptParameters::CancelParam

EVENT_TYPES = {
'bluetooth.requestDevicePromptUpdated' => Bluetooth::RequestDevicePromptUpdatedParameters,
'bluetooth.gattConnectionAttempted' => Bluetooth::GattConnectionAttemptedParameters
'bluetooth.gattConnectionAttempted' => Bluetooth::GattConnectionAttemptedParameters,
'bluetooth.characteristicEventGenerated' => Bluetooth::CharacteristicEventGeneratedParameters,
'bluetooth.descriptorEventGenerated' => Bluetooth::DescriptorEventGeneratedParameters
}.freeze

def bluetooth_manufacturer_data(**) = BluetoothManufacturerData.new(**)
Expand Down
Loading
Loading