diff --git a/javascript/selenium-webdriver/project_bidi_schema.mjs b/javascript/selenium-webdriver/project_bidi_schema.mjs index ba85e81a2f55b..72e10a93ac7b5 100644 --- a/javascript/selenium-webdriver/project_bidi_schema.mjs +++ b/javascript/selenium-webdriver/project_bidi_schema.mjs @@ -21,15 +21,15 @@ * The normalizer has already removed the awkward CDDL shapes, so this is a * straight mapping into a small vocabulary: * - * type node: { kind: 'record', fields: [field], map?, extensible?, specHref? } + * type node: { kind: 'record', fields: [field], map?, extensible?, preserveExtras?, specHref? } * | { kind: 'enum', values: [string], specHref? } - * | { kind: 'union', variants: [ref], selector, specHref? } + * | { kind: 'union', variants: [ref], selector, objectOnly?, specHref? } * | { kind: 'alias', type, specHref? } * selector: { by, variants: [{ value, ref }], default? } // discriminated * | { ordered: [{ ref, requires: [key] }] } // structural, spec order * | { correlated: true } // resolved by request id, not the payload * field: { name, wire, required, type } - * type ref: { primitive } | { const } | { ref } | { enum } | { list } | { map, extensible? } | { union } + * type ref: { primitive } | { const } | { ref } | { enum, primitive? } | { list } | { map, extensible? } | { union, scalar? } * any ref may also carry `nullable: true` (a `/ null` alternative). On a * record node, `map` is the value type of `* key => value` entries and * `extensible: true` marks an open `* text => any` record. @@ -43,6 +43,20 @@ * points at the editor's draft, so for an older generated artifact the target drifts * from the pinned source; synthetic types (and anything neither source covers) omit it. * + * Three derived signals let a binding validate the wire boundary without re-deriving + * anything itself: + * `objectOnly: true` — a union all of whose arms are object (record) types, so a + * non-object payload is a schema violation, not a scalar arm. + * `preserveExtras: true` — an `extensible` type that can also be *sent* (reachable + * from a command's params), so unknown properties received on + * the wire must be stored and echoed back rather than dropped. + * an inline `enum` ref carries the `primitive` its literals share, so even a scalar + * the normalizer did not hoist to a named enum is typed rather than opaque. + * `scalar` on an inline `union` ref marks a union with a bare-scalar arm (a map entry's + * `RemoteValue / text`) and carries that arm's primitive: a binding collapsing it onto its + * object_only ref arm passes a non-object payload (the string keys) through, but only when + * it matches the primitive — a wrong-typed scalar is still rejected. + * * Types the normalizer synthesized for anonymous CDDL constructs additionally * carry `{ synthetic: true, owner, label }`: `owner` is the type the construct * was lifted out of and `label` is the member name within it, so a binding can @@ -94,6 +108,49 @@ const isRef = (e) => e && typeof e === 'object' && e.Type === 'group' && typeof const isNullAlt = (e) => e === 'null' || (e && typeof e === 'object' && e.Type === 'group' && PRELUDE[e.Value] === 'null') +// The primitive a set of literal values shares (all strings → string, etc.), or +// undefined when they are mixed. Used to type an inline literal choice. +function literalPrimitive(values) { + if (values.every((v) => typeof v === 'string')) return 'string' + if (values.every((v) => typeof v === 'boolean')) return 'boolean' + if (values.every((v) => Number.isInteger(v))) return 'integer' + if (values.every((v) => typeof v === 'number')) return 'number' + return undefined +} + +// An inline literal choice (e.g. `("classic" / "overlay") / null`) the normalizer did +// not hoist to a named enum. Carry the literals' shared primitive so the scalar is +// typed rather than opaque — a binding can then reject a wrong-primitive wire value. +function enumNode(entries) { + const values = entries.map((e) => e.Value) + const node = { enum: values } + const primitive = literalPrimitive(values) + if (primitive) node.primitive = primitive + return node +} + +// The primitive a bare-scalar union arm accepts: a `{ primitive }` arm directly, or the +// value type of a `{ const }` arm. Undefined for an object / list / ref arm. +function scalarArmPrimitive(arm) { + if (arm.primitive !== undefined) return arm.primitive + if (arm.const !== undefined) return literalPrimitive([arm.const]) + return undefined +} + +// An inline union of projected arms. `scalar` marks a union that has a bare-scalar arm (a +// primitive or a const) alongside object arms — e.g. a map entry's `RemoteValue / text` — +// and carries that arm's primitive (or the array of primitives when the scalar arms differ). +// A binding that collapses such a union onto its object (object_only) ref arm must still let +// a non-object payload through here, but only when it matches this primitive — a wrong-typed +// scalar is still a wire error. Derived once, in the schema, rather than re-detected per binding. +function unionNode(arms) { + const node = { union: arms } + const primitives = [...new Set(arms.map(scalarArmPrimitive).filter((p) => p !== undefined))] + if (primitives.length === 1) node.scalar = primitives[0] + else if (primitives.length > 1) node.scalar = primitives + return node +} + function projectRef(type) { const all = typeList(type) // A missing type (undefined/empty input, e.g. a malformed array element or map @@ -104,8 +161,8 @@ function projectRef(type) { const node = entries.length > 1 ? entries.every(isLiteral) - ? { enum: entries.map((e) => e.Value) } - : { union: entries.map(projectEntry) } + ? enumNode(entries) + : unionNode(entries.map(projectEntry)) : projectEntry(entries[0]) if (entries.length < all.length) node.nullable = true // a `null` alternative means the value may be null return node @@ -124,7 +181,7 @@ function projectEntry(e) { // An inline group that only wraps anonymous ref(s) — e.g. a union arm // `{ DateLocalValue }` — is that ref (or a union of them), not a record. const refs = unionMemberRefs(e) - if (refs) return refs.length === 1 ? { ref: refs[0] } : { union: refs.map((r) => ({ ref: r })) } + if (refs) return refs.length === 1 ? { ref: refs[0] } : unionNode(refs.map((r) => ({ ref: r }))) return { record: e.Properties.flat() .filter((p) => p?.Name) @@ -242,6 +299,66 @@ function unionLeaves(ref, types, seen = new Set()) { return [] } +// Whether a union variant is an object (record) type — following aliases and nested +// unions to their leaves. An enum, or an alias to a primitive/list/map (or an inline +// union arm with a scalar member), is not an object. `objectOnly` is true for a union +// only when every variant is one, so a non-object payload is a schema violation there. +function variantIsObject(ref, types, seen = new Set()) { + if (seen.has(ref)) return true // a cycle bottoms out in records; treat as object + seen.add(ref) + const t = types[ref] + if (!t) return false + if (t.kind === 'record') return true + if (t.kind === 'union') return t.variants.every((v) => variantIsObject(v, types, seen)) + if (t.kind === 'alias') { + if (t.type?.ref) return variantIsObject(t.type.ref, types, seen) + if (t.type?.union) return t.type.union.every((a) => a.ref !== undefined && variantIsObject(a.ref, types, seen)) + return false // alias to a primitive / list / map / const + } + return false // enum +} + +// The type-name refs a projected ref node points at, recursing through list / map / +// inline union / inline record. (checkSchema has an equivalent local walk for its own +// referential checks; this module-level one feeds the reachability closure below.) +function refNames(node) { + if (!node) return [] + if (node.ref) return [node.ref] + if (node.list) return refNames(node.list) + if (node.map) return refNames(node.map) + if (node.union) return node.union.flatMap(refNames) + if (node.record) return node.record.flatMap((f) => refNames(f.type)) + return [] +} + +// The type-name refs a type *node* (record / union / alias) points at: a record's +// field and map value types, a union's variants, an alias's target. +function typeRefNames(node) { + if (node.kind === 'record') { + const refs = node.fields.flatMap((f) => refNames(f.type)) + if (node.map) refs.push(...refNames(node.map)) + return refs + } + if (node.kind === 'union') return node.variants + if (node.kind === 'alias') return refNames(node.type) + return [] +} + +// The set of types that can be *sent*: reachable from some command's params, through +// fields, lists, unions, maps, and nested records/aliases. Results and events are not +// roots — a type reached only through them is received-only. `preserveExtras` gates the +// extras store on this, so only a type you can hand back keeps unknown wire properties. +function reSendableTypes(commands, types) { + const reachable = new Set() + const visit = (name) => { + if (!name || reachable.has(name) || !types[name]) return + reachable.add(name) + for (const r of typeRefNames(types[name])) visit(r) + } + for (const c of commands) if (c.params?.ref) visit(c.params.ref) + return reachable +} + // The constant value a record pins on wire key `k`, as `{ value }` (a string or // `null`), or `{ open: true }` when the field exists but is not constant (a base // type acting as the catch-all, e.g. log.GenericLogEntry.type), or null when the @@ -467,6 +584,11 @@ export function projectSchema(ast, model, links = {}) { // Override the result-grouping unions: they are dispatched by request id, so a // payload selector for them is meaningless (and would be empty/ambiguous). for (const name of correlatedUnions(types)) types[name].selector = { correlated: true } + // A first-class union whose every arm is an object rejects a non-object payload + // instead of passing it through. (An alias-union like input.Origin, which carries + // bare-string arms, is intentionally left unflagged so those arms still pass through.) + for (const node of Object.values(types)) + if (node.kind === 'union' && node.variants.every((v) => variantIsObject(v, types))) node.objectOnly = true const commands = [] const events = [] @@ -496,6 +618,13 @@ export function projectSchema(ast, model, links = {}) { } } + // An extensible type keeps unknown wire properties only when it is also re-sendable + // (reachable from a command's params) — a type you receive and can hand back, so its + // extras must round-trip. A received-only extensible type drops them. + const reSendable = reSendableTypes(commands, types) + for (const [name, node] of Object.entries(types)) + if (node.extensible && reSendable.has(name)) node.preserveExtras = true + // Per-domain module links, for a binding that emits one class/namespace per domain. const domains = {} for (const domain of Object.keys(model)) { diff --git a/javascript/selenium-webdriver/project_bidi_schema_test.mjs b/javascript/selenium-webdriver/project_bidi_schema_test.mjs index d007ca7911467..1fc7aeddeeea6 100644 --- a/javascript/selenium-webdriver/project_bidi_schema_test.mjs +++ b/javascript/selenium-webdriver/project_bidi_schema_test.mjs @@ -152,6 +152,7 @@ describe('projectType (list / union / alias defs)', () => { { ref: 'x.Other', requires: ['b'] }, ], }, + objectOnly: true, // both arms are records }) }) it('projects a single-member dispatch choice group as an alias to its ref', () => { @@ -375,6 +376,93 @@ describe('unionSelector', () => { }) }) +describe('schema signals (objectOnly / preserveExtras / enum primitive)', () => { + const rec = (name, typeConst) => group(name, [field('type', [lit(typeConst)])]) + const union = (name, refs) => ({ + Type: 'variable', + Name: name, + IsChoiceAddition: false, + Comments: [], + PropertyType: refs.map(ref), + }) + const enumDef = (name, values) => ({ + Type: 'variable', + Name: name, + IsChoiceAddition: false, + Comments: [], + PropertyType: values.map(lit), + }) + + it('flags a union whose every arm is an object type as objectOnly', () => { + const s = projectSchema([union('x.U', ['x.A', 'x.B']), rec('x.A', 'a'), rec('x.B', 'b')], {}) + assert.equal(s.types['x.U'].objectOnly, true) + assert.deepEqual(checkSchema(s), []) + }) + + it('does not flag a first-class union with an enum (scalar) arm as objectOnly', () => { + const s = projectSchema([union('x.U', ['x.A', 'x.E']), rec('x.A', 'a'), enumDef('x.E', ['one', 'two'])], {}) + assert.equal(s.types['x.E'].kind, 'enum') + assert.equal(s.types['x.U'].objectOnly, undefined) + }) + + it('does not flag a bare-scalar alias-union (input.Origin shape) as objectOnly', () => { + // "viewport" / "pointer" / ElementOrigin — the const arms keep it an alias-union + // that must still pass a bare-string payload through, so it stays unflagged. + const origin = { + Type: 'variable', + Name: 'x.Origin', + IsChoiceAddition: false, + Comments: [], + PropertyType: [lit('viewport'), lit('pointer'), ref('x.Element')], + } + const s = projectSchema([origin, group('x.Element', [field('type', [lit('element')]), field('id', ['text'])])], {}) + assert.equal(s.types['x.Origin'].kind, 'alias') + assert.equal(s.types['x.Origin'].objectOnly, undefined) + }) + + it('marks an extensible type reachable from command params as preserveExtras, but not a result-only one', () => { + const ast = [ + group('x.SetParams', [field('cfg', [ref('x.Config')])]), + group('x.Config', [field('text', ['any'], { n: 0, m: null })]), + group('x.GetResult', [field('info', [ref('x.Info')])]), + group('x.Info', [field('text', ['any'], { n: 0, m: null })]), + ] + const model = { x: { commands: [{ method: 'x.set', name: 'set', params: 'x.SetParams', result: 'x.GetResult' }] } } + const s = projectSchema(ast, model) + assert.equal(s.types['x.Config'].extensible, true) + assert.equal(s.types['x.Config'].preserveExtras, true) // reachable through the command's params + assert.equal(s.types['x.Info'].extensible, true) + assert.equal(s.types['x.Info'].preserveExtras, undefined) // reachable only through the result + assert.deepEqual(checkSchema(s), []) + }) + + it('types an inline (non-hoisted) literal choice with the primitive its literals share', () => { + // A nullable literal choice (`("classic" / "overlay") / null`) the normalizer leaves + // inline — carry `primitive: string` so the scalar is typed rather than opaque. + const s = projectSchema([group('x.R', [field('kind', [lit('classic'), lit('overlay'), 'null'])])], {}) + assert.deepEqual(s.types['x.R'].fields[0].type, { + enum: ['classic', 'overlay'], + primitive: 'string', + nullable: true, + }) + assert.deepEqual(checkSchema(s), []) + }) + + it('flags an inline union with a bare-scalar arm as scalar-tolerant (map key: Ref / text)', () => { + const ast = [ + group('x.R', [field('entry', [ref('x.U'), 'text']), field('objects', [ref('x.A'), ref('x.B')])]), + union('x.U', ['x.A', 'x.B']), + rec('x.A', 'a'), + rec('x.B', 'b'), + ] + const s = projectSchema(ast, {}).types['x.R'].fields + // The `Ref / text` arm makes the union scalar-tolerant, carrying the arm's primitive... + assert.deepEqual(s[0].type, { union: [{ ref: 'x.U' }, { primitive: 'string' }], scalar: 'string' }) + // ...but an all-object union is not flagged (no scalar arm to pass through). + assert.deepEqual(s[1].type, { union: [{ ref: 'x.A' }, { ref: 'x.B' }] }) + }) +}) + describe('checkCompleteness (input vs output, generator-independent)', () => { it('fails when a command/event present in the AST is missing from the schema', () => { const astWithExtra = [ diff --git a/rb/lib/selenium/webdriver/bidi/protocol/bluetooth.rb b/rb/lib/selenium/webdriver/bidi/protocol/bluetooth.rb index baf35f93f411f..8f1fb06bab127 100644 --- a/rb/lib/selenium/webdriver/bidi/protocol/bluetooth.rb +++ b/rb/lib/selenium/webdriver/bidi/protocol/bluetooth.rb @@ -104,7 +104,7 @@ class Bluetooth < Domain # @see https://www.selenium.dev/documentation/warnings/bidi-implementation/ # @see https://webbluetoothcg.github.io/web-bluetooth/#cddl-type-bluetoothrequestdeviceinfo RequestDeviceInfo = Serialization::Record.define( - id: 'id', + id: {wire_key: 'id', primitive: 'string'}, name: {wire_key: 'name', nullable: true, primitive: 'string'} ) @@ -132,14 +132,15 @@ class HandleRequestDevicePromptParameters < Serialization::Union true => 'Bluetooth::HandleRequestDevicePromptParameters::AcceptParameters', false => 'Bluetooth::HandleRequestDevicePromptParameters::CancelParameters' ) + object_only # @api private # @see https://www.selenium.dev/documentation/warnings/bidi-implementation/ AcceptParameters = Serialization::Record.define( accept: {fixed: true}, context: {wire_key: 'context', primitive: 'string'}, - prompt: 'prompt', - device: 'device' + prompt: {wire_key: 'prompt', primitive: 'string'}, + device: {wire_key: 'device', primitive: 'string'} ) # @api private @@ -147,7 +148,7 @@ class HandleRequestDevicePromptParameters < Serialization::Union CancelParameters = Serialization::Record.define( accept: {fixed: false}, context: {wire_key: 'context', primitive: 'string'}, - prompt: 'prompt' + prompt: {wire_key: 'prompt', primitive: 'string'} ) end @@ -218,7 +219,7 @@ class HandleRequestDevicePromptParameters < Serialization::Union SimulateServiceParameters = Serialization::Record.define( context: {wire_key: 'context', primitive: 'string'}, address: {wire_key: 'address', primitive: 'string'}, - uuid: 'uuid', + uuid: {wire_key: 'uuid', primitive: 'string'}, type: {wire_key: 'type', enum: 'Bluetooth::SIMULATE_SERVICE_PARAMETERS_TYPE'} ) @@ -228,8 +229,8 @@ class HandleRequestDevicePromptParameters < Serialization::Union SimulateCharacteristicParameters = Serialization::Record.define( context: {wire_key: 'context', primitive: 'string'}, address: {wire_key: 'address', primitive: 'string'}, - service_uuid: 'serviceUuid', - characteristic_uuid: 'characteristicUuid', + service_uuid: {wire_key: 'serviceUuid', primitive: 'string'}, + characteristic_uuid: {wire_key: 'characteristicUuid', primitive: 'string'}, characteristic_properties: { wire_key: 'characteristicProperties', required: false, @@ -244,8 +245,8 @@ class HandleRequestDevicePromptParameters < Serialization::Union SimulateCharacteristicResponseParameters = Serialization::Record.define( context: {wire_key: 'context', primitive: 'string'}, address: {wire_key: 'address', primitive: 'string'}, - service_uuid: 'serviceUuid', - characteristic_uuid: 'characteristicUuid', + service_uuid: {wire_key: 'serviceUuid', primitive: 'string'}, + characteristic_uuid: {wire_key: 'characteristicUuid', primitive: 'string'}, type: {wire_key: 'type', enum: 'Bluetooth::SIMULATE_CHARACTERISTIC_RESPONSE_PARAMETERS_TYPE'}, code: {wire_key: 'code', primitive: 'integer'}, data: {wire_key: 'data', required: false, list: true} @@ -257,9 +258,9 @@ class HandleRequestDevicePromptParameters < Serialization::Union SimulateDescriptorParameters = Serialization::Record.define( context: {wire_key: 'context', primitive: 'string'}, address: {wire_key: 'address', primitive: 'string'}, - service_uuid: 'serviceUuid', - characteristic_uuid: 'characteristicUuid', - descriptor_uuid: 'descriptorUuid', + service_uuid: {wire_key: 'serviceUuid', primitive: 'string'}, + characteristic_uuid: {wire_key: 'characteristicUuid', primitive: 'string'}, + descriptor_uuid: {wire_key: 'descriptorUuid', primitive: 'string'}, type: {wire_key: 'type', enum: 'Bluetooth::SIMULATE_DESCRIPTOR_PARAMETERS_TYPE'} ) @@ -269,9 +270,9 @@ class HandleRequestDevicePromptParameters < Serialization::Union SimulateDescriptorResponseParameters = Serialization::Record.define( context: {wire_key: 'context', primitive: 'string'}, address: {wire_key: 'address', primitive: 'string'}, - service_uuid: 'serviceUuid', - characteristic_uuid: 'characteristicUuid', - descriptor_uuid: 'descriptorUuid', + service_uuid: {wire_key: 'serviceUuid', primitive: 'string'}, + characteristic_uuid: {wire_key: 'characteristicUuid', primitive: 'string'}, + descriptor_uuid: {wire_key: 'descriptorUuid', primitive: 'string'}, type: {wire_key: 'type', enum: 'Bluetooth::SIMULATE_DESCRIPTOR_RESPONSE_PARAMETERS_TYPE'}, code: {wire_key: 'code', primitive: 'integer'}, data: {wire_key: 'data', required: false, list: true} @@ -282,7 +283,7 @@ class HandleRequestDevicePromptParameters < Serialization::Union # @see https://webbluetoothcg.github.io/web-bluetooth/#cddl-type-bluetoothrequestdevicepromptupdatedparameters RequestDevicePromptUpdatedParameters = Serialization::Record.define( context: {wire_key: 'context', primitive: 'string'}, - prompt: 'prompt', + prompt: {wire_key: 'prompt', primitive: 'string'}, devices: {wire_key: 'devices', ref: 'Bluetooth::RequestDeviceInfo', list: true} ) @@ -300,8 +301,8 @@ class HandleRequestDevicePromptParameters < Serialization::Union CharacteristicEventGeneratedParameters = Serialization::Record.define( context: {wire_key: 'context', primitive: 'string'}, address: {wire_key: 'address', primitive: 'string'}, - service_uuid: 'serviceUuid', - characteristic_uuid: 'characteristicUuid', + service_uuid: {wire_key: 'serviceUuid', primitive: 'string'}, + characteristic_uuid: {wire_key: 'characteristicUuid', primitive: 'string'}, type: {wire_key: 'type', enum: 'Bluetooth::CHARACTERISTIC_EVENT_GENERATED_PARAMETERS_TYPE'}, data: {wire_key: 'data', required: false, list: true} ) @@ -312,9 +313,9 @@ class HandleRequestDevicePromptParameters < Serialization::Union DescriptorEventGeneratedParameters = Serialization::Record.define( context: {wire_key: 'context', primitive: 'string'}, address: {wire_key: 'address', primitive: 'string'}, - service_uuid: 'serviceUuid', - characteristic_uuid: 'characteristicUuid', - descriptor_uuid: 'descriptorUuid', + service_uuid: {wire_key: 'serviceUuid', primitive: 'string'}, + characteristic_uuid: {wire_key: 'characteristicUuid', primitive: 'string'}, + descriptor_uuid: {wire_key: 'descriptorUuid', primitive: 'string'}, type: {wire_key: 'type', enum: 'Bluetooth::DESCRIPTOR_EVENT_GENERATED_PARAMETERS_TYPE'}, data: {wire_key: 'data', required: false, list: true} ) diff --git a/rb/lib/selenium/webdriver/bidi/protocol/browser.rb b/rb/lib/selenium/webdriver/bidi/protocol/browser.rb index 2d69c9cf02152..af8c70a1ac648 100644 --- a/rb/lib/selenium/webdriver/bidi/protocol/browser.rb +++ b/rb/lib/selenium/webdriver/bidi/protocol/browser.rb @@ -46,18 +46,18 @@ class Browser < Domain # @see https://w3c.github.io/webdriver-bidi/#type-browser-ClientWindowInfo ClientWindowInfo = Serialization::Record.define( active: {wire_key: 'active', primitive: 'boolean'}, - client_window: 'clientWindow', - height: 'height', + client_window: {wire_key: 'clientWindow', primitive: 'string'}, + height: {wire_key: 'height', primitive: 'integer'}, state: {wire_key: 'state', enum: 'Browser::CLIENT_WINDOW_INFO_STATE'}, - width: 'width', - x: 'x', - y: 'y' + width: {wire_key: 'width', primitive: 'integer'}, + x: {wire_key: 'x', primitive: 'integer'}, + y: {wire_key: 'y', primitive: 'integer'} ) # @api private # @see https://www.selenium.dev/documentation/warnings/bidi-implementation/ # @see https://w3c.github.io/webdriver-bidi/#type-browser-UserContextInfo - UserContextInfo = Serialization::Record.define(user_context: 'userContext') + UserContextInfo = Serialization::Record.define(user_context: {wire_key: 'userContext', primitive: 'string'}) # @api private # @see https://www.selenium.dev/documentation/warnings/bidi-implementation/ @@ -89,7 +89,9 @@ class Browser < Domain # @api private # @see https://www.selenium.dev/documentation/warnings/bidi-implementation/ # @see https://w3c.github.io/webdriver-bidi/#cddl-type-browserremoveusercontextparameters - RemoveUserContextParameters = Serialization::Record.define(user_context: 'userContext') + RemoveUserContextParameters = Serialization::Record.define( + user_context: {wire_key: 'userContext', primitive: 'string'} + ) # @api private # @see https://www.selenium.dev/documentation/warnings/bidi-implementation/ @@ -100,11 +102,12 @@ class SetClientWindowStateParameters < Serialization::Union normal: 'Browser::SetClientWindowStateParameters::ClientWindowRectState' ) fallback 'Browser::SetClientWindowStateParameters::ClientWindowNamedState' + object_only # @api private # @see https://www.selenium.dev/documentation/warnings/bidi-implementation/ ClientWindowNamedState = Serialization::Record.define( - client_window: 'clientWindow', + client_window: {wire_key: 'clientWindow', primitive: 'string'}, state: {wire_key: 'state', enum: 'Browser::CLIENT_WINDOW_NAMED_STATE_STATE'} ) @@ -112,11 +115,11 @@ class SetClientWindowStateParameters < Serialization::Union # @see https://www.selenium.dev/documentation/warnings/bidi-implementation/ ClientWindowRectState = Serialization::Record.define( state: {fixed: 'normal'}, - client_window: 'clientWindow', - width: {wire_key: 'width', required: false}, - height: {wire_key: 'height', required: false}, - x: {wire_key: 'x', required: false}, - y: {wire_key: 'y', required: false} + client_window: {wire_key: 'clientWindow', primitive: 'string'}, + width: {wire_key: 'width', required: false, primitive: 'integer'}, + height: {wire_key: 'height', required: false, primitive: 'integer'}, + x: {wire_key: 'x', required: false, primitive: 'integer'}, + y: {wire_key: 'y', required: false, primitive: 'integer'} ) end @@ -137,6 +140,7 @@ class DownloadBehavior < Serialization::Union allowed: 'Browser::DownloadBehavior::Allowed', denied: 'Browser::DownloadBehavior::Denied' ) + object_only # @api private # @see https://www.selenium.dev/documentation/warnings/bidi-implementation/ diff --git a/rb/lib/selenium/webdriver/bidi/protocol/browsing_context.rb b/rb/lib/selenium/webdriver/bidi/protocol/browsing_context.rb index 99fb54e962daa..d51de6cf9d2a3 100644 --- a/rb/lib/selenium/webdriver/bidi/protocol/browsing_context.rb +++ b/rb/lib/selenium/webdriver/bidi/protocol/browsing_context.rb @@ -86,12 +86,12 @@ class BrowsingContext < Domain # @see https://w3c.github.io/webdriver-bidi/#type-browsingContext-Info Info = Serialization::Record.define( children: {wire_key: 'children', nullable: true, ref: 'BrowsingContext::Info', list: true}, - client_window: 'clientWindow', - context: 'context', - original_opener: {wire_key: 'originalOpener', nullable: true}, + client_window: {wire_key: 'clientWindow', primitive: 'string'}, + context: {wire_key: 'context', primitive: 'string'}, + original_opener: {wire_key: 'originalOpener', nullable: true, primitive: 'string'}, url: {wire_key: 'url', primitive: 'string'}, - user_context: 'userContext', - parent: {wire_key: 'parent', required: false, nullable: true} + user_context: {wire_key: 'userContext', primitive: 'string'}, + parent: {wire_key: 'parent', required: false, nullable: true, primitive: 'string'} ) # @api private @@ -112,6 +112,7 @@ class Locator < Serialization::Union inner_text: 'BrowsingContext::InnerTextLocator', xpath: 'BrowsingContext::XPathLocator' ) + object_only end # @api private @@ -147,7 +148,7 @@ class Locator < Serialization::Union # @api private # @see https://www.selenium.dev/documentation/warnings/bidi-implementation/ - ContextLocator::Value = Serialization::Record.define(context: 'context') + ContextLocator::Value = Serialization::Record.define(context: {wire_key: 'context', primitive: 'string'}) # @api private # @see https://www.selenium.dev/documentation/warnings/bidi-implementation/ @@ -157,7 +158,7 @@ class Locator < Serialization::Union value: {wire_key: 'value', primitive: 'string'}, ignore_case: {wire_key: 'ignoreCase', required: false, primitive: 'boolean'}, match_type: {wire_key: 'matchType', required: false, enum: 'BrowsingContext::INNER_TEXT_LOCATOR_MATCH_TYPE'}, - max_depth: {wire_key: 'maxDepth', required: false} + max_depth: {wire_key: 'maxDepth', required: false, primitive: 'integer'} ) # @api private @@ -172,34 +173,34 @@ class Locator < Serialization::Union # @see https://www.selenium.dev/documentation/warnings/bidi-implementation/ # @see https://w3c.github.io/webdriver-bidi/#cddl-type-browsingcontextbasenavigationinfo BaseNavigationInfo = Serialization::Record.define( - context: 'context', - navigation: {wire_key: 'navigation', nullable: true}, - timestamp: 'timestamp', + context: {wire_key: 'context', primitive: 'string'}, + navigation: {wire_key: 'navigation', nullable: true, primitive: 'string'}, + timestamp: {wire_key: 'timestamp', primitive: 'integer'}, url: {wire_key: 'url', primitive: 'string'}, - user_context: {wire_key: 'userContext', required: false} + user_context: {wire_key: 'userContext', required: false, primitive: 'string'} ) # @api private # @see https://www.selenium.dev/documentation/warnings/bidi-implementation/ # @see https://w3c.github.io/webdriver-bidi/#type-browsingContext-NavigationInfo NavigationInfo = Serialization::Record.define( - context: 'context', - navigation: {wire_key: 'navigation', nullable: true}, - timestamp: 'timestamp', + context: {wire_key: 'context', primitive: 'string'}, + navigation: {wire_key: 'navigation', nullable: true, primitive: 'string'}, + timestamp: {wire_key: 'timestamp', primitive: 'integer'}, url: {wire_key: 'url', primitive: 'string'}, - user_context: {wire_key: 'userContext', required: false} + user_context: {wire_key: 'userContext', required: false, primitive: 'string'} ) # @api private # @see https://www.selenium.dev/documentation/warnings/bidi-implementation/ # @see https://w3c.github.io/webdriver-bidi/#cddl-type-browsingcontextactivateparameters - ActivateParameters = Serialization::Record.define(context: 'context') + ActivateParameters = Serialization::Record.define(context: {wire_key: 'context', primitive: 'string'}) # @api private # @see https://www.selenium.dev/documentation/warnings/bidi-implementation/ # @see https://w3c.github.io/webdriver-bidi/#cddl-type-browsingcontextcapturescreenshotparameters CaptureScreenshotParameters = Serialization::Record.define( - context: 'context', + context: {wire_key: 'context', primitive: 'string'}, origin: {wire_key: 'origin', required: false, enum: 'BrowsingContext::CAPTURE_SCREENSHOT_PARAMETERS_ORIGIN'}, format: {wire_key: 'format', required: false, ref: 'BrowsingContext::ImageFormat'}, clip: {wire_key: 'clip', required: false, ref: 'BrowsingContext::ClipRectangle'} @@ -222,6 +223,7 @@ class ClipRectangle < Serialization::Union box: 'BrowsingContext::BoxClipRectangle', element: 'BrowsingContext::ElementClipRectangle' ) + object_only end # @api private @@ -252,7 +254,7 @@ class ClipRectangle < Serialization::Union # @see https://www.selenium.dev/documentation/warnings/bidi-implementation/ # @see https://w3c.github.io/webdriver-bidi/#cddl-type-browsingcontextcloseparameters CloseParameters = Serialization::Record.define( - context: 'context', + context: {wire_key: 'context', primitive: 'string'}, prompt_unload: {wire_key: 'promptUnload', required: false, primitive: 'boolean'} ) @@ -261,25 +263,25 @@ class ClipRectangle < Serialization::Union # @see https://w3c.github.io/webdriver-bidi/#cddl-type-browsingcontextcreateparameters CreateParameters = Serialization::Record.define( type: {wire_key: 'type', enum: 'BrowsingContext::CREATE_TYPE'}, - reference_context: {wire_key: 'referenceContext', required: false}, + reference_context: {wire_key: 'referenceContext', required: false, primitive: 'string'}, background: {wire_key: 'background', required: false, primitive: 'boolean'}, - user_context: {wire_key: 'userContext', required: false} + user_context: {wire_key: 'userContext', required: false, primitive: 'string'} ) # @api private # @see https://www.selenium.dev/documentation/warnings/bidi-implementation/ # @see https://w3c.github.io/webdriver-bidi/#cddl-type-browsingcontextcreateresult CreateResult = Serialization::Record.define( - context: 'context', - user_context: {wire_key: 'userContext', required: false} + context: {wire_key: 'context', primitive: 'string'}, + user_context: {wire_key: 'userContext', required: false, primitive: 'string'} ) # @api private # @see https://www.selenium.dev/documentation/warnings/bidi-implementation/ # @see https://w3c.github.io/webdriver-bidi/#cddl-type-browsingcontextgettreeparameters GetTreeParameters = Serialization::Record.define( - max_depth: {wire_key: 'maxDepth', required: false}, - root: {wire_key: 'root', required: false} + max_depth: {wire_key: 'maxDepth', required: false, primitive: 'integer'}, + root: {wire_key: 'root', required: false, primitive: 'string'} ) # @api private @@ -293,7 +295,7 @@ class ClipRectangle < Serialization::Union # @see https://www.selenium.dev/documentation/warnings/bidi-implementation/ # @see https://w3c.github.io/webdriver-bidi/#cddl-type-browsingcontexthandleuserpromptparameters HandleUserPromptParameters = Serialization::Record.define( - context: 'context', + context: {wire_key: 'context', primitive: 'string'}, accept: {wire_key: 'accept', required: false, primitive: 'boolean'}, user_text: {wire_key: 'userText', required: false, primitive: 'string'} ) @@ -302,9 +304,9 @@ class ClipRectangle < Serialization::Union # @see https://www.selenium.dev/documentation/warnings/bidi-implementation/ # @see https://w3c.github.io/webdriver-bidi/#cddl-type-browsingcontextlocatenodesparameters LocateNodesParameters = Serialization::Record.define( - context: 'context', + context: {wire_key: 'context', primitive: 'string'}, locator: {wire_key: 'locator', ref: 'BrowsingContext::Locator'}, - max_node_count: {wire_key: 'maxNodeCount', required: false}, + max_node_count: {wire_key: 'maxNodeCount', required: false, primitive: 'integer'}, serialization_options: { wire_key: 'serializationOptions', required: false, @@ -324,7 +326,7 @@ class ClipRectangle < Serialization::Union # @see https://www.selenium.dev/documentation/warnings/bidi-implementation/ # @see https://w3c.github.io/webdriver-bidi/#cddl-type-browsingcontextnavigateparameters NavigateParameters = Serialization::Record.define( - context: 'context', + context: {wire_key: 'context', primitive: 'string'}, url: {wire_key: 'url', primitive: 'string'}, wait: {wire_key: 'wait', required: false, enum: 'BrowsingContext::READINESS_STATE'} ) @@ -333,7 +335,7 @@ class ClipRectangle < Serialization::Union # @see https://www.selenium.dev/documentation/warnings/bidi-implementation/ # @see https://w3c.github.io/webdriver-bidi/#cddl-type-browsingcontextnavigateresult NavigateResult = Serialization::Record.define( - navigation: {wire_key: 'navigation', nullable: true}, + navigation: {wire_key: 'navigation', nullable: true, primitive: 'string'}, url: {wire_key: 'url', primitive: 'string'} ) @@ -341,7 +343,7 @@ class ClipRectangle < Serialization::Union # @see https://www.selenium.dev/documentation/warnings/bidi-implementation/ # @see https://w3c.github.io/webdriver-bidi/#cddl-type-browsingcontextprintparameters PrintParameters = Serialization::Record.define( - context: 'context', + context: {wire_key: 'context', primitive: 'string'}, background: {wire_key: 'background', required: false, primitive: 'boolean'}, margin: {wire_key: 'margin', required: false, ref: 'BrowsingContext::PrintMarginParameters'}, orientation: { @@ -382,7 +384,7 @@ class ClipRectangle < Serialization::Union # @see https://www.selenium.dev/documentation/warnings/bidi-implementation/ # @see https://w3c.github.io/webdriver-bidi/#cddl-type-browsingcontextreloadparameters ReloadParameters = Serialization::Record.define( - context: 'context', + context: {wire_key: 'context', primitive: 'string'}, ignore_cache: {wire_key: 'ignoreCache', required: false, primitive: 'boolean'}, wait: {wire_key: 'wait', required: false, enum: 'BrowsingContext::READINESS_STATE'} ) @@ -400,7 +402,7 @@ class ClipRectangle < Serialization::Union # @see https://www.selenium.dev/documentation/warnings/bidi-implementation/ # @see https://w3c.github.io/webdriver-bidi/#cddl-type-browsingcontextsetviewportparameters SetViewportParameters = Serialization::Record.define( - context: {wire_key: 'context', required: false}, + context: {wire_key: 'context', required: false, primitive: 'string'}, viewport: {wire_key: 'viewport', required: false, nullable: true, ref: 'BrowsingContext::Viewport'}, device_pixel_ratio: {wire_key: 'devicePixelRatio', required: false, nullable: true, primitive: 'number'}, user_contexts: {wire_key: 'userContexts', required: false, list: true} @@ -409,13 +411,16 @@ class ClipRectangle < Serialization::Union # @api private # @see https://www.selenium.dev/documentation/warnings/bidi-implementation/ # @see https://w3c.github.io/webdriver-bidi/#cddl-type-browsingcontextviewport - Viewport = Serialization::Record.define(width: 'width', height: 'height') + Viewport = Serialization::Record.define( + width: {wire_key: 'width', primitive: 'integer'}, + height: {wire_key: 'height', primitive: 'integer'} + ) # @api private # @see https://www.selenium.dev/documentation/warnings/bidi-implementation/ # @see https://w3c.github.io/webdriver-bidi/#cddl-type-browsingcontextstartscreencastparameters StartScreencastParameters = Serialization::Record.define( - context: 'context', + context: {wire_key: 'context', primitive: 'string'}, mime_type: {wire_key: 'mimeType', required: false, primitive: 'string'}, video: {wire_key: 'video', required: false, ref: 'BrowsingContext::MediaTrackConstraints'}, audio: {wire_key: 'audio', required: false, primitive: 'boolean'} @@ -425,23 +430,25 @@ class ClipRectangle < Serialization::Union # @see https://www.selenium.dev/documentation/warnings/bidi-implementation/ # @see https://w3c.github.io/webdriver-bidi/#cddl-type-browsingcontextmediatrackconstraints MediaTrackConstraints = Serialization::Record.define( - width: {wire_key: 'width', required: false}, - height: {wire_key: 'height', required: false}, - frame_rate: {wire_key: 'frameRate', required: false} + width: {wire_key: 'width', required: false, primitive: 'integer'}, + height: {wire_key: 'height', required: false, primitive: 'integer'}, + frame_rate: {wire_key: 'frameRate', required: false, primitive: 'integer'} ) # @api private # @see https://www.selenium.dev/documentation/warnings/bidi-implementation/ # @see https://w3c.github.io/webdriver-bidi/#cddl-type-browsingcontextstartscreencastresult StartScreencastResult = Serialization::Record.define( - screencast: 'screencast', + screencast: {wire_key: 'screencast', primitive: 'string'}, path: {wire_key: 'path', primitive: 'string'} ) # @api private # @see https://www.selenium.dev/documentation/warnings/bidi-implementation/ # @see https://w3c.github.io/webdriver-bidi/#cddl-type-browsingcontextstopscreencastparameters - StopScreencastParameters = Serialization::Record.define(screencast: 'screencast') + StopScreencastParameters = Serialization::Record.define( + screencast: {wire_key: 'screencast', primitive: 'string'} + ) # @api private # @see https://www.selenium.dev/documentation/warnings/bidi-implementation/ @@ -454,29 +461,32 @@ class ClipRectangle < Serialization::Union # @api private # @see https://www.selenium.dev/documentation/warnings/bidi-implementation/ # @see https://w3c.github.io/webdriver-bidi/#cddl-type-browsingcontexttraversehistoryparameters - TraverseHistoryParameters = Serialization::Record.define(context: 'context', delta: 'delta') + TraverseHistoryParameters = Serialization::Record.define( + context: {wire_key: 'context', primitive: 'string'}, + delta: {wire_key: 'delta', primitive: 'integer'} + ) # @api private # @see https://www.selenium.dev/documentation/warnings/bidi-implementation/ # @see https://w3c.github.io/webdriver-bidi/#cddl-type-browsingcontexthistoryupdatedparameters HistoryUpdatedParameters = Serialization::Record.define( - context: 'context', - timestamp: 'timestamp', + context: {wire_key: 'context', primitive: 'string'}, + timestamp: {wire_key: 'timestamp', primitive: 'integer'}, url: {wire_key: 'url', primitive: 'string'}, - user_context: {wire_key: 'userContext', required: false} + user_context: {wire_key: 'userContext', required: false, primitive: 'string'} ) # @api private # @see https://www.selenium.dev/documentation/warnings/bidi-implementation/ # @see https://w3c.github.io/webdriver-bidi/#cddl-type-browsingcontextdownloadwillbeginparams DownloadWillBeginParams = Serialization::Record.define( - download: 'download', + download: {wire_key: 'download', primitive: 'string'}, suggested_filename: {wire_key: 'suggestedFilename', primitive: 'string'}, - context: 'context', - navigation: {wire_key: 'navigation', nullable: true}, - timestamp: 'timestamp', + context: {wire_key: 'context', primitive: 'string'}, + navigation: {wire_key: 'navigation', nullable: true, primitive: 'string'}, + timestamp: {wire_key: 'timestamp', primitive: 'integer'}, url: {wire_key: 'url', primitive: 'string'}, - user_context: {wire_key: 'userContext', required: false} + user_context: {wire_key: 'userContext', required: false, primitive: 'string'} ) # @api private @@ -488,30 +498,31 @@ class DownloadEndParams < Serialization::Union canceled: 'BrowsingContext::DownloadEndParams::CanceledParams', complete: 'BrowsingContext::DownloadEndParams::CompleteParams' ) + object_only # @api private # @see https://www.selenium.dev/documentation/warnings/bidi-implementation/ CanceledParams = Serialization::Record.define( status: {fixed: 'canceled'}, - download: 'download', - context: 'context', - navigation: {wire_key: 'navigation', nullable: true}, - timestamp: 'timestamp', + download: {wire_key: 'download', primitive: 'string'}, + context: {wire_key: 'context', primitive: 'string'}, + navigation: {wire_key: 'navigation', nullable: true, primitive: 'string'}, + timestamp: {wire_key: 'timestamp', primitive: 'integer'}, url: {wire_key: 'url', primitive: 'string'}, - user_context: {wire_key: 'userContext', required: false} + user_context: {wire_key: 'userContext', required: false, primitive: 'string'} ) # @api private # @see https://www.selenium.dev/documentation/warnings/bidi-implementation/ CompleteParams = Serialization::Record.define( status: {fixed: 'complete'}, - download: 'download', + download: {wire_key: 'download', primitive: 'string'}, filepath: {wire_key: 'filepath', nullable: true, primitive: 'string'}, - context: 'context', - navigation: {wire_key: 'navigation', nullable: true}, - timestamp: 'timestamp', + context: {wire_key: 'context', primitive: 'string'}, + navigation: {wire_key: 'navigation', nullable: true, primitive: 'string'}, + timestamp: {wire_key: 'timestamp', primitive: 'integer'}, url: {wire_key: 'url', primitive: 'string'}, - user_context: {wire_key: 'userContext', required: false} + user_context: {wire_key: 'userContext', required: false, primitive: 'string'} ) end @@ -519,10 +530,10 @@ class DownloadEndParams < Serialization::Union # @see https://www.selenium.dev/documentation/warnings/bidi-implementation/ # @see https://w3c.github.io/webdriver-bidi/#cddl-type-browsingcontextuserpromptclosedparameters UserPromptClosedParameters = Serialization::Record.define( - context: 'context', + context: {wire_key: 'context', primitive: 'string'}, accepted: {wire_key: 'accepted', primitive: 'boolean'}, type: {wire_key: 'type', enum: 'BrowsingContext::USER_PROMPT_TYPE'}, - user_context: {wire_key: 'userContext', required: false}, + user_context: {wire_key: 'userContext', required: false, primitive: 'string'}, user_text: {wire_key: 'userText', required: false, primitive: 'string'} ) @@ -530,11 +541,11 @@ class DownloadEndParams < Serialization::Union # @see https://www.selenium.dev/documentation/warnings/bidi-implementation/ # @see https://w3c.github.io/webdriver-bidi/#cddl-type-browsingcontextuserpromptopenedparameters UserPromptOpenedParameters = Serialization::Record.define( - context: 'context', + context: {wire_key: 'context', primitive: 'string'}, handler: {wire_key: 'handler', enum: 'Session::USER_PROMPT_HANDLER_TYPE'}, message: {wire_key: 'message', primitive: 'string'}, type: {wire_key: 'type', enum: 'BrowsingContext::USER_PROMPT_TYPE'}, - user_context: {wire_key: 'userContext', required: false}, + user_context: {wire_key: 'userContext', required: false, primitive: 'string'}, default_value: {wire_key: 'defaultValue', required: false, primitive: 'string'} ) diff --git a/rb/lib/selenium/webdriver/bidi/protocol/emulation.rb b/rb/lib/selenium/webdriver/bidi/protocol/emulation.rb index 04320d687ebea..4cb7a12aa7407 100644 --- a/rb/lib/selenium/webdriver/bidi/protocol/emulation.rb +++ b/rb/lib/selenium/webdriver/bidi/protocol/emulation.rb @@ -65,6 +65,7 @@ class SetGeolocationOverrideParameters < Serialization::Union 'Emulation::SetGeolocationOverrideParameters::Coordinates' => ['coordinates'], 'Emulation::SetGeolocationOverrideParameters::Error' => ['error'] ) + object_only # @api private # @see https://www.selenium.dev/documentation/warnings/bidi-implementation/ @@ -131,7 +132,10 @@ class SetGeolocationOverrideParameters < Serialization::Union # @api private # @see https://www.selenium.dev/documentation/warnings/bidi-implementation/ # @see https://w3c.github.io/webdriver-bidi/#cddl-type-emulationscreenarea - ScreenArea = Serialization::Record.define(width: 'width', height: 'height') + ScreenArea = Serialization::Record.define( + width: {wire_key: 'width', primitive: 'integer'}, + height: {wire_key: 'height', primitive: 'integer'} + ) # @api private # @see https://www.selenium.dev/documentation/warnings/bidi-implementation/ @@ -181,7 +185,7 @@ class SetGeolocationOverrideParameters < Serialization::Union # @see https://www.selenium.dev/documentation/warnings/bidi-implementation/ # @see https://w3c.github.io/webdriver-bidi/#cddl-type-emulationsetscrollbartypeoverrideparameters SetScrollbarTypeOverrideParameters = Serialization::Record.define( - scrollbar_type: {wire_key: 'scrollbarType', nullable: true}, + scrollbar_type: {wire_key: 'scrollbarType', nullable: true, primitive: 'string'}, contexts: {wire_key: 'contexts', required: false, list: true}, user_contexts: {wire_key: 'userContexts', required: false, list: true} ) @@ -199,7 +203,7 @@ class SetGeolocationOverrideParameters < Serialization::Union # @see https://www.selenium.dev/documentation/warnings/bidi-implementation/ # @see https://w3c.github.io/webdriver-bidi/#cddl-type-emulationsettouchoverrideparameters SetTouchOverrideParameters = Serialization::Record.define( - max_touch_points: {wire_key: 'maxTouchPoints', nullable: true}, + max_touch_points: {wire_key: 'maxTouchPoints', nullable: true, primitive: 'integer'}, contexts: {wire_key: 'contexts', required: false, list: true}, user_contexts: {wire_key: 'userContexts', required: false, list: true} ) diff --git a/rb/lib/selenium/webdriver/bidi/protocol/input.rb b/rb/lib/selenium/webdriver/bidi/protocol/input.rb index e49b48a49f740..bd7ab0b8e306c 100644 --- a/rb/lib/selenium/webdriver/bidi/protocol/input.rb +++ b/rb/lib/selenium/webdriver/bidi/protocol/input.rb @@ -51,7 +51,7 @@ class Input < Domain # @see https://www.selenium.dev/documentation/warnings/bidi-implementation/ # @see https://w3c.github.io/webdriver-bidi/#cddl-type-inputperformactionsparameters PerformActionsParameters = Serialization::Record.define( - context: 'context', + context: {wire_key: 'context', primitive: 'string'}, actions: {wire_key: 'actions', ref: 'Input::SourceActions', list: true} ) @@ -66,6 +66,7 @@ class SourceActions < Serialization::Union pointer: 'Input::PointerSourceActions', wheel: 'Input::WheelSourceActions' ) + object_only end # @api private @@ -96,6 +97,7 @@ class KeySourceAction < Serialization::Union key_down: 'Input::KeyDownAction', key_up: 'Input::KeyUpAction' ) + object_only end # @api private @@ -131,6 +133,7 @@ class PointerSourceAction < Serialization::Union pointer_up: 'Input::PointerUpAction', pointer_move: 'Input::PointerMoveAction' ) + object_only end # @api private @@ -151,6 +154,7 @@ class WheelSourceAction < Serialization::Union pause: 'Input::PauseAction', scroll: 'Input::WheelScrollAction' ) + object_only end # @api private @@ -158,7 +162,7 @@ class WheelSourceAction < Serialization::Union # @see https://w3c.github.io/webdriver-bidi/#cddl-type-inputpauseaction PauseAction = Serialization::Record.define( type: {fixed: 'pause'}, - duration: {wire_key: 'duration', required: false} + duration: {wire_key: 'duration', required: false, primitive: 'integer'} ) # @api private @@ -180,16 +184,19 @@ class WheelSourceAction < Serialization::Union # @api private # @see https://www.selenium.dev/documentation/warnings/bidi-implementation/ # @see https://w3c.github.io/webdriver-bidi/#cddl-type-inputpointerupaction - PointerUpAction = Serialization::Record.define(type: {fixed: 'pointerUp'}, button: 'button') + PointerUpAction = Serialization::Record.define( + type: {fixed: 'pointerUp'}, + button: {wire_key: 'button', primitive: 'integer'} + ) # @api private # @see https://www.selenium.dev/documentation/warnings/bidi-implementation/ # @see https://w3c.github.io/webdriver-bidi/#cddl-type-inputpointerdownaction PointerDownAction = Serialization::Record.define( type: {fixed: 'pointerDown'}, - button: 'button', - width: {wire_key: 'width', required: false}, - height: {wire_key: 'height', required: false}, + button: {wire_key: 'button', primitive: 'integer'}, + width: {wire_key: 'width', required: false, primitive: 'integer'}, + height: {wire_key: 'height', required: false, primitive: 'integer'}, pressure: {wire_key: 'pressure', required: false, primitive: 'integer'}, tangential_pressure: {wire_key: 'tangentialPressure', required: false, primitive: 'integer'}, twist: {wire_key: 'twist', required: false, primitive: 'integer'}, @@ -204,10 +211,10 @@ class WheelSourceAction < Serialization::Union type: {fixed: 'pointerMove'}, x: {wire_key: 'x', primitive: 'number'}, y: {wire_key: 'y', primitive: 'number'}, - duration: {wire_key: 'duration', required: false}, + duration: {wire_key: 'duration', required: false, primitive: 'integer'}, origin: {wire_key: 'origin', required: false, ref: 'Input::Origin'}, - width: {wire_key: 'width', required: false}, - height: {wire_key: 'height', required: false}, + width: {wire_key: 'width', required: false, primitive: 'integer'}, + height: {wire_key: 'height', required: false, primitive: 'integer'}, pressure: {wire_key: 'pressure', required: false, primitive: 'integer'}, tangential_pressure: {wire_key: 'tangentialPressure', required: false, primitive: 'integer'}, twist: {wire_key: 'twist', required: false, primitive: 'integer'}, @@ -220,11 +227,11 @@ class WheelSourceAction < Serialization::Union # @see https://w3c.github.io/webdriver-bidi/#cddl-type-inputwheelscrollaction WheelScrollAction = Serialization::Record.define( type: {fixed: 'scroll'}, - x: 'x', - y: 'y', - delta_x: 'deltaX', - delta_y: 'deltaY', - duration: {wire_key: 'duration', required: false}, + x: {wire_key: 'x', primitive: 'integer'}, + y: {wire_key: 'y', primitive: 'integer'}, + delta_x: {wire_key: 'deltaX', primitive: 'integer'}, + delta_y: {wire_key: 'deltaY', primitive: 'integer'}, + duration: {wire_key: 'duration', required: false, primitive: 'integer'}, origin: {wire_key: 'origin', required: false, ref: 'Input::Origin'} ) @@ -232,8 +239,8 @@ class WheelSourceAction < Serialization::Union # @see https://www.selenium.dev/documentation/warnings/bidi-implementation/ # @see https://w3c.github.io/webdriver-bidi/#cddl-type-inputpointercommonproperties PointerCommonProperties = Serialization::Record.define( - width: {wire_key: 'width', required: false}, - height: {wire_key: 'height', required: false}, + width: {wire_key: 'width', required: false, primitive: 'integer'}, + height: {wire_key: 'height', required: false, primitive: 'integer'}, pressure: {wire_key: 'pressure', required: false, primitive: 'integer'}, tangential_pressure: {wire_key: 'tangentialPressure', required: false, primitive: 'integer'}, twist: {wire_key: 'twist', required: false, primitive: 'integer'}, @@ -254,13 +261,13 @@ class Origin < Serialization::Union # @api private # @see https://www.selenium.dev/documentation/warnings/bidi-implementation/ # @see https://w3c.github.io/webdriver-bidi/#cddl-type-inputreleaseactionsparameters - ReleaseActionsParameters = Serialization::Record.define(context: 'context') + ReleaseActionsParameters = Serialization::Record.define(context: {wire_key: 'context', primitive: 'string'}) # @api private # @see https://www.selenium.dev/documentation/warnings/bidi-implementation/ # @see https://w3c.github.io/webdriver-bidi/#cddl-type-inputsetfilesparameters SetFilesParameters = Serialization::Record.define( - context: 'context', + context: {wire_key: 'context', primitive: 'string'}, element: {wire_key: 'element', ref: 'Script::SharedReference'}, files: {wire_key: 'files', list: true} ) @@ -269,8 +276,8 @@ class Origin < Serialization::Union # @see https://www.selenium.dev/documentation/warnings/bidi-implementation/ # @see https://w3c.github.io/webdriver-bidi/#cddl-type-inputfiledialoginfo FileDialogInfo = Serialization::Record.define( - context: 'context', - user_context: {wire_key: 'userContext', required: false}, + context: {wire_key: 'context', primitive: 'string'}, + user_context: {wire_key: 'userContext', required: false, primitive: 'string'}, element: {wire_key: 'element', required: false, ref: 'Script::SharedReference'}, multiple: {wire_key: 'multiple', primitive: 'boolean'} ) diff --git a/rb/lib/selenium/webdriver/bidi/protocol/log.rb b/rb/lib/selenium/webdriver/bidi/protocol/log.rb index 35b133f3c59fc..bbbd1ee211754 100644 --- a/rb/lib/selenium/webdriver/bidi/protocol/log.rb +++ b/rb/lib/selenium/webdriver/bidi/protocol/log.rb @@ -50,6 +50,7 @@ class Entry < Serialization::Union javascript: 'Log::JavascriptLogEntry' ) fallback 'Log::GenericLogEntry' + object_only end # @api private @@ -59,7 +60,7 @@ class Entry < Serialization::Union level: {wire_key: 'level', enum: 'Log::LEVEL'}, source: {wire_key: 'source', ref: 'Script::Source'}, text: {wire_key: 'text', nullable: true, primitive: 'string'}, - timestamp: 'timestamp', + timestamp: {wire_key: 'timestamp', primitive: 'integer'}, stack_trace: {wire_key: 'stackTrace', required: false, ref: 'Script::StackTrace'} ) @@ -70,7 +71,7 @@ class Entry < Serialization::Union level: {wire_key: 'level', enum: 'Log::LEVEL'}, source: {wire_key: 'source', ref: 'Script::Source'}, text: {wire_key: 'text', nullable: true, primitive: 'string'}, - timestamp: 'timestamp', + timestamp: {wire_key: 'timestamp', primitive: 'integer'}, stack_trace: {wire_key: 'stackTrace', required: false, ref: 'Script::StackTrace'}, type: {wire_key: 'type', primitive: 'string'} ) @@ -83,7 +84,7 @@ class Entry < Serialization::Union level: {wire_key: 'level', enum: 'Log::LEVEL'}, source: {wire_key: 'source', ref: 'Script::Source'}, text: {wire_key: 'text', nullable: true, primitive: 'string'}, - timestamp: 'timestamp', + timestamp: {wire_key: 'timestamp', primitive: 'integer'}, stack_trace: {wire_key: 'stackTrace', required: false, ref: 'Script::StackTrace'}, method_: {wire_key: 'method', primitive: 'string'}, args: {wire_key: 'args', ref: 'Script::RemoteValue', list: true} @@ -97,7 +98,7 @@ class Entry < Serialization::Union level: {wire_key: 'level', enum: 'Log::LEVEL'}, source: {wire_key: 'source', ref: 'Script::Source'}, text: {wire_key: 'text', nullable: true, primitive: 'string'}, - timestamp: 'timestamp', + timestamp: {wire_key: 'timestamp', primitive: 'integer'}, stack_trace: {wire_key: 'stackTrace', required: false, ref: 'Script::StackTrace'} ) diff --git a/rb/lib/selenium/webdriver/bidi/protocol/network.rb b/rb/lib/selenium/webdriver/bidi/protocol/network.rb index cc9b81dd58f5a..326fd994f5eaf 100644 --- a/rb/lib/selenium/webdriver/bidi/protocol/network.rb +++ b/rb/lib/selenium/webdriver/bidi/protocol/network.rb @@ -100,13 +100,13 @@ class Network < Domain # @see https://www.selenium.dev/documentation/warnings/bidi-implementation/ # @see https://w3c.github.io/webdriver-bidi/#type-network-BaseParameters BaseParameters = Serialization::Record.define( - context: {wire_key: 'context', nullable: true}, + context: {wire_key: 'context', nullable: true, primitive: 'string'}, is_blocked: {wire_key: 'isBlocked', primitive: 'boolean'}, - navigation: {wire_key: 'navigation', nullable: true}, - redirect_count: 'redirectCount', + navigation: {wire_key: 'navigation', nullable: true, primitive: 'string'}, + redirect_count: {wire_key: 'redirectCount', primitive: 'integer'}, request: {wire_key: 'request', ref: 'Network::RequestData'}, - timestamp: 'timestamp', - user_context: {wire_key: 'userContext', required: false, nullable: true}, + timestamp: {wire_key: 'timestamp', primitive: 'integer'}, + user_context: {wire_key: 'userContext', required: false, nullable: true, primitive: 'string'}, intercepts: {wire_key: 'intercepts', required: false, list: true} ) @@ -119,6 +119,7 @@ class BytesValue < Serialization::Union string: 'Network::StringValue', base64: 'Network::Base64Value' ) + object_only end # @api private @@ -145,12 +146,11 @@ class BytesValue < Serialization::Union value: {wire_key: 'value', ref: 'Network::BytesValue'}, domain: {wire_key: 'domain', primitive: 'string'}, path: {wire_key: 'path', primitive: 'string'}, - size: 'size', + size: {wire_key: 'size', primitive: 'integer'}, http_only: {wire_key: 'httpOnly', primitive: 'boolean'}, secure: {wire_key: 'secure', primitive: 'boolean'}, same_site: {wire_key: 'sameSite', enum: 'Network::SAME_SITE'}, - expiry: {wire_key: 'expiry', required: false}, - extensible: true + expiry: {wire_key: 'expiry', required: false, primitive: 'integer'} ) # @api private @@ -192,9 +192,9 @@ class BytesValue < Serialization::Union # @see https://www.selenium.dev/documentation/warnings/bidi-implementation/ # @see https://w3c.github.io/webdriver-bidi/#type-network-Initiator Initiator = Serialization::Record.define( - column_number: {wire_key: 'columnNumber', required: false}, - line_number: {wire_key: 'lineNumber', required: false}, - request: {wire_key: 'request', required: false}, + column_number: {wire_key: 'columnNumber', required: false, primitive: 'integer'}, + line_number: {wire_key: 'lineNumber', required: false, primitive: 'integer'}, + request: {wire_key: 'request', required: false, primitive: 'string'}, stack_trace: {wire_key: 'stackTrace', required: false, ref: 'Script::StackTrace'}, type: {wire_key: 'type', required: false, enum: 'Network::INITIATOR_TYPE'} ) @@ -203,13 +203,13 @@ class BytesValue < Serialization::Union # @see https://www.selenium.dev/documentation/warnings/bidi-implementation/ # @see https://w3c.github.io/webdriver-bidi/#type-network-RequestData RequestData = Serialization::Record.define( - request: 'request', + request: {wire_key: 'request', primitive: 'string'}, url: {wire_key: 'url', primitive: 'string'}, method_: {wire_key: 'method', primitive: 'string'}, headers: {wire_key: 'headers', ref: 'Network::Header', list: true}, cookies: {wire_key: 'cookies', ref: 'Network::Cookie', list: true}, - headers_size: 'headersSize', - body_size: {wire_key: 'bodySize', nullable: true}, + headers_size: {wire_key: 'headersSize', primitive: 'integer'}, + body_size: {wire_key: 'bodySize', nullable: true, primitive: 'integer'}, destination: {wire_key: 'destination', primitive: 'string'}, initiator_type: {wire_key: 'initiatorType', nullable: true, primitive: 'string'}, timings: {wire_key: 'timings', ref: 'Network::FetchTimingInfo'} @@ -218,7 +218,7 @@ class BytesValue < Serialization::Union # @api private # @see https://www.selenium.dev/documentation/warnings/bidi-implementation/ # @see https://w3c.github.io/webdriver-bidi/#type-network-ResponseContent - ResponseContent = Serialization::Record.define(size: 'size') + ResponseContent = Serialization::Record.define(size: {wire_key: 'size', primitive: 'integer'}) # @api private # @see https://www.selenium.dev/documentation/warnings/bidi-implementation/ @@ -226,14 +226,14 @@ class BytesValue < Serialization::Union ResponseData = Serialization::Record.define( url: {wire_key: 'url', primitive: 'string'}, protocol: {wire_key: 'protocol', primitive: 'string'}, - status: 'status', + status: {wire_key: 'status', primitive: 'integer'}, status_text: {wire_key: 'statusText', primitive: 'string'}, from_cache: {wire_key: 'fromCache', primitive: 'boolean'}, headers: {wire_key: 'headers', ref: 'Network::Header', list: true}, mime_type: {wire_key: 'mimeType', primitive: 'string'}, - bytes_received: 'bytesReceived', - headers_size: {wire_key: 'headersSize', nullable: true}, - body_size: {wire_key: 'bodySize', nullable: true}, + bytes_received: {wire_key: 'bytesReceived', primitive: 'integer'}, + headers_size: {wire_key: 'headersSize', nullable: true, primitive: 'integer'}, + body_size: {wire_key: 'bodySize', nullable: true, primitive: 'integer'}, content: {wire_key: 'content', ref: 'Network::ResponseContent'}, auth_challenges: {wire_key: 'authChallenges', required: false, ref: 'Network::AuthChallenge', list: true} ) @@ -247,7 +247,7 @@ class BytesValue < Serialization::Union domain: {wire_key: 'domain', required: false, primitive: 'string'}, http_only: {wire_key: 'httpOnly', required: false, primitive: 'boolean'}, expiry: {wire_key: 'expiry', required: false, primitive: 'string'}, - max_age: {wire_key: 'maxAge', required: false}, + max_age: {wire_key: 'maxAge', required: false, primitive: 'integer'}, path: {wire_key: 'path', required: false, primitive: 'string'}, same_site: {wire_key: 'sameSite', required: false, enum: 'Network::SAME_SITE'}, secure: {wire_key: 'secure', required: false, primitive: 'boolean'} @@ -262,6 +262,7 @@ class UrlPattern < Serialization::Union pattern: 'Network::UrlPatternPattern', string: 'Network::UrlPatternString' ) + object_only end # @api private @@ -289,7 +290,7 @@ class UrlPattern < Serialization::Union # @see https://w3c.github.io/webdriver-bidi/#cddl-type-networkadddatacollectorparameters AddDataCollectorParameters = Serialization::Record.define( data_types: {wire_key: 'dataTypes', list: true, enum: 'Network::DATA_TYPE'}, - max_encoded_data_size: 'maxEncodedDataSize', + max_encoded_data_size: {wire_key: 'maxEncodedDataSize', primitive: 'integer'}, collector_type: {wire_key: 'collectorType', required: false, enum: 'Network::COLLECTOR_TYPE'}, contexts: {wire_key: 'contexts', required: false, list: true}, user_contexts: {wire_key: 'userContexts', required: false, list: true} @@ -298,7 +299,7 @@ class UrlPattern < Serialization::Union # @api private # @see https://www.selenium.dev/documentation/warnings/bidi-implementation/ # @see https://w3c.github.io/webdriver-bidi/#cddl-type-networkadddatacollectorresult - AddDataCollectorResult = Serialization::Record.define(collector: 'collector') + AddDataCollectorResult = Serialization::Record.define(collector: {wire_key: 'collector', primitive: 'string'}) # @api private # @see https://www.selenium.dev/documentation/warnings/bidi-implementation/ @@ -312,13 +313,13 @@ class UrlPattern < Serialization::Union # @api private # @see https://www.selenium.dev/documentation/warnings/bidi-implementation/ # @see https://w3c.github.io/webdriver-bidi/#cddl-type-networkaddinterceptresult - AddInterceptResult = Serialization::Record.define(intercept: 'intercept') + AddInterceptResult = Serialization::Record.define(intercept: {wire_key: 'intercept', primitive: 'string'}) # @api private # @see https://www.selenium.dev/documentation/warnings/bidi-implementation/ # @see https://w3c.github.io/webdriver-bidi/#cddl-type-networkcontinuerequestparameters ContinueRequestParameters = Serialization::Record.define( - request: 'request', + request: {wire_key: 'request', primitive: 'string'}, body: {wire_key: 'body', required: false, ref: 'Network::BytesValue'}, cookies: {wire_key: 'cookies', required: false, ref: 'Network::CookieHeader', list: true}, headers: {wire_key: 'headers', required: false, ref: 'Network::Header', list: true}, @@ -330,12 +331,12 @@ class UrlPattern < Serialization::Union # @see https://www.selenium.dev/documentation/warnings/bidi-implementation/ # @see https://w3c.github.io/webdriver-bidi/#cddl-type-networkcontinueresponseparameters ContinueResponseParameters = Serialization::Record.define( - request: 'request', + request: {wire_key: 'request', primitive: 'string'}, cookies: {wire_key: 'cookies', required: false, ref: 'Network::SetCookieHeader', list: true}, credentials: {wire_key: 'credentials', required: false, ref: 'Network::AuthCredentials'}, headers: {wire_key: 'headers', required: false, ref: 'Network::Header', list: true}, reason_phrase: {wire_key: 'reasonPhrase', required: false, primitive: 'string'}, - status_code: {wire_key: 'statusCode', required: false} + status_code: {wire_key: 'statusCode', required: false, primitive: 'integer'} ) # @api private @@ -347,19 +348,20 @@ class ContinueWithAuthParameters < Serialization::Union provide_credentials: 'Network::ContinueWithAuthParameters::Credentials' ) fallback 'Network::ContinueWithAuthParameters::NoCredentials' + object_only # @api private # @see https://www.selenium.dev/documentation/warnings/bidi-implementation/ Credentials = Serialization::Record.define( action: {fixed: 'provideCredentials'}, - request: 'request', + request: {wire_key: 'request', primitive: 'string'}, credentials: {wire_key: 'credentials', ref: 'Network::AuthCredentials'} ) # @api private # @see https://www.selenium.dev/documentation/warnings/bidi-implementation/ NoCredentials = Serialization::Record.define( - request: 'request', + request: {wire_key: 'request', primitive: 'string'}, action: {wire_key: 'action', enum: 'Network::CONTINUE_WITH_AUTH_NO_CREDENTIALS_ACTION'} ) end @@ -369,23 +371,23 @@ class ContinueWithAuthParameters < Serialization::Union # @see https://w3c.github.io/webdriver-bidi/#cddl-type-networkdisowndataparameters DisownDataParameters = Serialization::Record.define( data_type: {wire_key: 'dataType', enum: 'Network::DATA_TYPE'}, - collector: 'collector', - request: 'request' + collector: {wire_key: 'collector', primitive: 'string'}, + request: {wire_key: 'request', primitive: 'string'} ) # @api private # @see https://www.selenium.dev/documentation/warnings/bidi-implementation/ # @see https://w3c.github.io/webdriver-bidi/#cddl-type-networkfailrequestparameters - FailRequestParameters = Serialization::Record.define(request: 'request') + FailRequestParameters = Serialization::Record.define(request: {wire_key: 'request', primitive: 'string'}) # @api private # @see https://www.selenium.dev/documentation/warnings/bidi-implementation/ # @see https://w3c.github.io/webdriver-bidi/#cddl-type-networkgetdataparameters GetDataParameters = Serialization::Record.define( data_type: {wire_key: 'dataType', enum: 'Network::DATA_TYPE'}, - collector: {wire_key: 'collector', required: false}, + collector: {wire_key: 'collector', required: false, primitive: 'string'}, disown: {wire_key: 'disown', required: false, primitive: 'boolean'}, - request: 'request' + request: {wire_key: 'request', primitive: 'string'} ) # @api private @@ -397,23 +399,27 @@ class ContinueWithAuthParameters < Serialization::Union # @see https://www.selenium.dev/documentation/warnings/bidi-implementation/ # @see https://w3c.github.io/webdriver-bidi/#cddl-type-networkprovideresponseparameters ProvideResponseParameters = Serialization::Record.define( - request: 'request', + request: {wire_key: 'request', primitive: 'string'}, body: {wire_key: 'body', required: false, ref: 'Network::BytesValue'}, cookies: {wire_key: 'cookies', required: false, ref: 'Network::SetCookieHeader', list: true}, headers: {wire_key: 'headers', required: false, ref: 'Network::Header', list: true}, reason_phrase: {wire_key: 'reasonPhrase', required: false, primitive: 'string'}, - status_code: {wire_key: 'statusCode', required: false} + status_code: {wire_key: 'statusCode', required: false, primitive: 'integer'} ) # @api private # @see https://www.selenium.dev/documentation/warnings/bidi-implementation/ # @see https://w3c.github.io/webdriver-bidi/#cddl-type-networkremovedatacollectorparameters - RemoveDataCollectorParameters = Serialization::Record.define(collector: 'collector') + RemoveDataCollectorParameters = Serialization::Record.define( + collector: {wire_key: 'collector', primitive: 'string'} + ) # @api private # @see https://www.selenium.dev/documentation/warnings/bidi-implementation/ # @see https://w3c.github.io/webdriver-bidi/#cddl-type-networkremoveinterceptparameters - RemoveInterceptParameters = Serialization::Record.define(intercept: 'intercept') + RemoveInterceptParameters = Serialization::Record.define( + intercept: {wire_key: 'intercept', primitive: 'string'} + ) # @api private # @see https://www.selenium.dev/documentation/warnings/bidi-implementation/ @@ -436,13 +442,13 @@ class ContinueWithAuthParameters < Serialization::Union # @see https://www.selenium.dev/documentation/warnings/bidi-implementation/ # @see https://w3c.github.io/webdriver-bidi/#cddl-type-networkauthrequiredparameters AuthRequiredParameters = Serialization::Record.define( - context: {wire_key: 'context', nullable: true}, + context: {wire_key: 'context', nullable: true, primitive: 'string'}, is_blocked: {wire_key: 'isBlocked', primitive: 'boolean'}, - navigation: {wire_key: 'navigation', nullable: true}, - redirect_count: 'redirectCount', + navigation: {wire_key: 'navigation', nullable: true, primitive: 'string'}, + redirect_count: {wire_key: 'redirectCount', primitive: 'integer'}, request: {wire_key: 'request', ref: 'Network::RequestData'}, - timestamp: 'timestamp', - user_context: {wire_key: 'userContext', required: false, nullable: true}, + timestamp: {wire_key: 'timestamp', primitive: 'integer'}, + user_context: {wire_key: 'userContext', required: false, nullable: true, primitive: 'string'}, intercepts: {wire_key: 'intercepts', required: false, list: true}, response: {wire_key: 'response', ref: 'Network::ResponseData'} ) @@ -451,13 +457,13 @@ class ContinueWithAuthParameters < Serialization::Union # @see https://www.selenium.dev/documentation/warnings/bidi-implementation/ # @see https://w3c.github.io/webdriver-bidi/#cddl-type-networkbeforerequestsentparameters BeforeRequestSentParameters = Serialization::Record.define( - context: {wire_key: 'context', nullable: true}, + context: {wire_key: 'context', nullable: true, primitive: 'string'}, is_blocked: {wire_key: 'isBlocked', primitive: 'boolean'}, - navigation: {wire_key: 'navigation', nullable: true}, - redirect_count: 'redirectCount', + navigation: {wire_key: 'navigation', nullable: true, primitive: 'string'}, + redirect_count: {wire_key: 'redirectCount', primitive: 'integer'}, request: {wire_key: 'request', ref: 'Network::RequestData'}, - timestamp: 'timestamp', - user_context: {wire_key: 'userContext', required: false, nullable: true}, + timestamp: {wire_key: 'timestamp', primitive: 'integer'}, + user_context: {wire_key: 'userContext', required: false, nullable: true, primitive: 'string'}, intercepts: {wire_key: 'intercepts', required: false, list: true}, initiator: {wire_key: 'initiator', required: false, ref: 'Network::Initiator'} ) @@ -466,13 +472,13 @@ class ContinueWithAuthParameters < Serialization::Union # @see https://www.selenium.dev/documentation/warnings/bidi-implementation/ # @see https://w3c.github.io/webdriver-bidi/#cddl-type-networkfetcherrorparameters FetchErrorParameters = Serialization::Record.define( - context: {wire_key: 'context', nullable: true}, + context: {wire_key: 'context', nullable: true, primitive: 'string'}, is_blocked: {wire_key: 'isBlocked', primitive: 'boolean'}, - navigation: {wire_key: 'navigation', nullable: true}, - redirect_count: 'redirectCount', + navigation: {wire_key: 'navigation', nullable: true, primitive: 'string'}, + redirect_count: {wire_key: 'redirectCount', primitive: 'integer'}, request: {wire_key: 'request', ref: 'Network::RequestData'}, - timestamp: 'timestamp', - user_context: {wire_key: 'userContext', required: false, nullable: true}, + timestamp: {wire_key: 'timestamp', primitive: 'integer'}, + user_context: {wire_key: 'userContext', required: false, nullable: true, primitive: 'string'}, intercepts: {wire_key: 'intercepts', required: false, list: true}, error_text: {wire_key: 'errorText', primitive: 'string'} ) @@ -481,13 +487,13 @@ class ContinueWithAuthParameters < Serialization::Union # @see https://www.selenium.dev/documentation/warnings/bidi-implementation/ # @see https://w3c.github.io/webdriver-bidi/#cddl-type-networkresponsecompletedparameters ResponseCompletedParameters = Serialization::Record.define( - context: {wire_key: 'context', nullable: true}, + context: {wire_key: 'context', nullable: true, primitive: 'string'}, is_blocked: {wire_key: 'isBlocked', primitive: 'boolean'}, - navigation: {wire_key: 'navigation', nullable: true}, - redirect_count: 'redirectCount', + navigation: {wire_key: 'navigation', nullable: true, primitive: 'string'}, + redirect_count: {wire_key: 'redirectCount', primitive: 'integer'}, request: {wire_key: 'request', ref: 'Network::RequestData'}, - timestamp: 'timestamp', - user_context: {wire_key: 'userContext', required: false, nullable: true}, + timestamp: {wire_key: 'timestamp', primitive: 'integer'}, + user_context: {wire_key: 'userContext', required: false, nullable: true, primitive: 'string'}, intercepts: {wire_key: 'intercepts', required: false, list: true}, response: {wire_key: 'response', ref: 'Network::ResponseData'} ) @@ -496,13 +502,13 @@ class ContinueWithAuthParameters < Serialization::Union # @see https://www.selenium.dev/documentation/warnings/bidi-implementation/ # @see https://w3c.github.io/webdriver-bidi/#cddl-type-networkresponsestartedparameters ResponseStartedParameters = Serialization::Record.define( - context: {wire_key: 'context', nullable: true}, + context: {wire_key: 'context', nullable: true, primitive: 'string'}, is_blocked: {wire_key: 'isBlocked', primitive: 'boolean'}, - navigation: {wire_key: 'navigation', nullable: true}, - redirect_count: 'redirectCount', + navigation: {wire_key: 'navigation', nullable: true, primitive: 'string'}, + redirect_count: {wire_key: 'redirectCount', primitive: 'integer'}, request: {wire_key: 'request', ref: 'Network::RequestData'}, - timestamp: 'timestamp', - user_context: {wire_key: 'userContext', required: false, nullable: true}, + timestamp: {wire_key: 'timestamp', primitive: 'integer'}, + user_context: {wire_key: 'userContext', required: false, nullable: true, primitive: 'string'}, intercepts: {wire_key: 'intercepts', required: false, list: true}, response: {wire_key: 'response', ref: 'Network::ResponseData'} ) diff --git a/rb/lib/selenium/webdriver/bidi/protocol/script.rb b/rb/lib/selenium/webdriver/bidi/protocol/script.rb index 659531d6f09ac..1147504269a8f 100644 --- a/rb/lib/selenium/webdriver/bidi/protocol/script.rb +++ b/rb/lib/selenium/webdriver/bidi/protocol/script.rb @@ -83,7 +83,7 @@ class Script < Domain # @see https://www.selenium.dev/documentation/warnings/bidi-implementation/ # @see https://w3c.github.io/webdriver-bidi/#cddl-type-scriptchannelproperties ChannelProperties = Serialization::Record.define( - channel: 'channel', + channel: {wire_key: 'channel', primitive: 'string'}, serialization_options: { wire_key: 'serializationOptions', required: false, @@ -101,6 +101,7 @@ class EvaluateResult < Serialization::Union success: 'Script::EvaluateResultSuccess', exception: 'Script::EvaluateResultException' ) + object_only end # @api private @@ -109,7 +110,7 @@ class EvaluateResult < Serialization::Union EvaluateResultSuccess = Serialization::Record.define( type: {fixed: 'success'}, result: {wire_key: 'result', ref: 'Script::RemoteValue'}, - realm: 'realm' + realm: {wire_key: 'realm', primitive: 'string'} ) # @api private @@ -118,16 +119,16 @@ class EvaluateResult < Serialization::Union EvaluateResultException = Serialization::Record.define( type: {fixed: 'exception'}, exception_details: {wire_key: 'exceptionDetails', ref: 'Script::ExceptionDetails'}, - realm: 'realm' + realm: {wire_key: 'realm', primitive: 'string'} ) # @api private # @see https://www.selenium.dev/documentation/warnings/bidi-implementation/ # @see https://w3c.github.io/webdriver-bidi/#type-script-ExceptionDetails ExceptionDetails = Serialization::Record.define( - column_number: 'columnNumber', + column_number: {wire_key: 'columnNumber', primitive: 'integer'}, exception: {wire_key: 'exception', ref: 'Script::RemoteValue'}, - line_number: 'lineNumber', + line_number: {wire_key: 'lineNumber', primitive: 'integer'}, stack_trace: {wire_key: 'stackTrace', ref: 'Script::StackTrace'}, text: {wire_key: 'text', primitive: 'string'} ) @@ -167,6 +168,7 @@ class LocalValue < Serialization::Union set: 'Script::SetLocalValue' ) fallback 'Script::RemoteReference' + object_only end # @api private @@ -190,7 +192,7 @@ class LocalValue < Serialization::Union # @see https://w3c.github.io/webdriver-bidi/#cddl-type-scriptmaplocalvalue MapLocalValue = Serialization::Record.define( type: {fixed: 'map'}, - value: {wire_key: 'value', ref: 'Script::LocalValue', list: true} + value: {wire_key: 'value', ref: 'Script::LocalValue', list: true, scalar: 'string'} ) # @api private @@ -198,7 +200,7 @@ class LocalValue < Serialization::Union # @see https://w3c.github.io/webdriver-bidi/#cddl-type-scriptobjectlocalvalue ObjectLocalValue = Serialization::Record.define( type: {fixed: 'object'}, - value: {wire_key: 'value', ref: 'Script::LocalValue', list: true} + value: {wire_key: 'value', ref: 'Script::LocalValue', list: true, scalar: 'string'} ) # @api private @@ -245,6 +247,7 @@ class PrimitiveProtocolValue < Serialization::Union boolean: 'Script::BooleanValue', bigint: 'Script::BigIntValue' ) + object_only end # @api private @@ -310,13 +313,14 @@ class RealmInfo < Serialization::Union audio_worklet: 'Script::AudioWorkletRealmInfo', worklet: 'Script::WorkletRealmInfo' ) + object_only end # @api private # @see https://www.selenium.dev/documentation/warnings/bidi-implementation/ # @see https://w3c.github.io/webdriver-bidi/#cddl-type-scriptbaserealminfo BaseRealmInfo = Serialization::Record.define( - realm: 'realm', + realm: {wire_key: 'realm', primitive: 'string'}, origin: {wire_key: 'origin', primitive: 'string'} ) @@ -325,10 +329,10 @@ class RealmInfo < Serialization::Union # @see https://w3c.github.io/webdriver-bidi/#cddl-type-scriptwindowrealminfo WindowRealmInfo = Serialization::Record.define( type: {fixed: 'window'}, - realm: 'realm', + realm: {wire_key: 'realm', primitive: 'string'}, origin: {wire_key: 'origin', primitive: 'string'}, - context: 'context', - user_context: {wire_key: 'userContext', required: false}, + context: {wire_key: 'context', primitive: 'string'}, + user_context: {wire_key: 'userContext', required: false, primitive: 'string'}, sandbox: {wire_key: 'sandbox', required: false, primitive: 'string'} ) @@ -337,7 +341,7 @@ class RealmInfo < Serialization::Union # @see https://w3c.github.io/webdriver-bidi/#cddl-type-scriptdedicatedworkerrealminfo DedicatedWorkerRealmInfo = Serialization::Record.define( type: {fixed: 'dedicated-worker'}, - realm: 'realm', + realm: {wire_key: 'realm', primitive: 'string'}, origin: {wire_key: 'origin', primitive: 'string'}, owners: {wire_key: 'owners', list: true} ) @@ -347,7 +351,7 @@ class RealmInfo < Serialization::Union # @see https://w3c.github.io/webdriver-bidi/#cddl-type-scriptsharedworkerrealminfo SharedWorkerRealmInfo = Serialization::Record.define( type: {fixed: 'shared-worker'}, - realm: 'realm', + realm: {wire_key: 'realm', primitive: 'string'}, origin: {wire_key: 'origin', primitive: 'string'} ) @@ -356,7 +360,7 @@ class RealmInfo < Serialization::Union # @see https://w3c.github.io/webdriver-bidi/#cddl-type-scriptserviceworkerrealminfo ServiceWorkerRealmInfo = Serialization::Record.define( type: {fixed: 'service-worker'}, - realm: 'realm', + realm: {wire_key: 'realm', primitive: 'string'}, origin: {wire_key: 'origin', primitive: 'string'} ) @@ -365,7 +369,7 @@ class RealmInfo < Serialization::Union # @see https://w3c.github.io/webdriver-bidi/#cddl-type-scriptworkerrealminfo WorkerRealmInfo = Serialization::Record.define( type: {fixed: 'worker'}, - realm: 'realm', + realm: {wire_key: 'realm', primitive: 'string'}, origin: {wire_key: 'origin', primitive: 'string'} ) @@ -374,7 +378,7 @@ class RealmInfo < Serialization::Union # @see https://w3c.github.io/webdriver-bidi/#cddl-type-scriptpaintworkletrealminfo PaintWorkletRealmInfo = Serialization::Record.define( type: {fixed: 'paint-worklet'}, - realm: 'realm', + realm: {wire_key: 'realm', primitive: 'string'}, origin: {wire_key: 'origin', primitive: 'string'} ) @@ -383,7 +387,7 @@ class RealmInfo < Serialization::Union # @see https://w3c.github.io/webdriver-bidi/#cddl-type-scriptaudioworkletrealminfo AudioWorkletRealmInfo = Serialization::Record.define( type: {fixed: 'audio-worklet'}, - realm: 'realm', + realm: {wire_key: 'realm', primitive: 'string'}, origin: {wire_key: 'origin', primitive: 'string'} ) @@ -392,7 +396,7 @@ class RealmInfo < Serialization::Union # @see https://w3c.github.io/webdriver-bidi/#cddl-type-scriptworkletrealminfo WorkletRealmInfo = Serialization::Record.define( type: {fixed: 'worklet'}, - realm: 'realm', + realm: {wire_key: 'realm', primitive: 'string'}, origin: {wire_key: 'origin', primitive: 'string'} ) @@ -404,14 +408,15 @@ class RemoteReference < Serialization::Union 'Script::SharedReference' => ['sharedId'], 'Script::RemoteObjectReference' => ['handle'] ) + object_only end # @api private # @see https://www.selenium.dev/documentation/warnings/bidi-implementation/ # @see https://w3c.github.io/webdriver-bidi/#cddl-type-scriptsharedreference SharedReference = Serialization::Record.define( - shared_id: 'sharedId', - handle: {wire_key: 'handle', required: false}, + shared_id: {wire_key: 'sharedId', primitive: 'string'}, + handle: {wire_key: 'handle', required: false, primitive: 'string'}, extensible: true ) @@ -419,8 +424,8 @@ class RemoteReference < Serialization::Union # @see https://www.selenium.dev/documentation/warnings/bidi-implementation/ # @see https://w3c.github.io/webdriver-bidi/#cddl-type-scriptremoteobjectreference RemoteObjectReference = Serialization::Record.define( - handle: 'handle', - shared_id: {wire_key: 'sharedId', required: false}, + handle: {wire_key: 'handle', primitive: 'string'}, + shared_id: {wire_key: 'sharedId', required: false, primitive: 'string'}, extensible: true ) @@ -484,6 +489,7 @@ class RemoteValue < Serialization::Union node: 'Script::NodeRemoteValue', window: 'Script::WindowProxyRemoteValue' ) + object_only end # @api private @@ -491,8 +497,8 @@ class RemoteValue < Serialization::Union # @see https://w3c.github.io/webdriver-bidi/#cddl-type-scriptsymbolremotevalue SymbolRemoteValue = Serialization::Record.define( type: {fixed: 'symbol'}, - handle: {wire_key: 'handle', required: false}, - internal_id: {wire_key: 'internalId', required: false} + handle: {wire_key: 'handle', required: false, primitive: 'string'}, + internal_id: {wire_key: 'internalId', required: false, primitive: 'string'} ) # @api private @@ -500,8 +506,8 @@ class RemoteValue < Serialization::Union # @see https://w3c.github.io/webdriver-bidi/#cddl-type-scriptarrayremotevalue ArrayRemoteValue = Serialization::Record.define( type: {fixed: 'array'}, - handle: {wire_key: 'handle', required: false}, - internal_id: {wire_key: 'internalId', required: false}, + handle: {wire_key: 'handle', required: false, primitive: 'string'}, + internal_id: {wire_key: 'internalId', required: false, primitive: 'string'}, value: {wire_key: 'value', required: false, ref: 'Script::RemoteValue', list: true} ) @@ -510,9 +516,9 @@ class RemoteValue < Serialization::Union # @see https://w3c.github.io/webdriver-bidi/#cddl-type-scriptobjectremotevalue ObjectRemoteValue = Serialization::Record.define( type: {fixed: 'object'}, - handle: {wire_key: 'handle', required: false}, - internal_id: {wire_key: 'internalId', required: false}, - value: {wire_key: 'value', required: false, ref: 'Script::RemoteValue', list: true} + handle: {wire_key: 'handle', required: false, primitive: 'string'}, + internal_id: {wire_key: 'internalId', required: false, primitive: 'string'}, + value: {wire_key: 'value', required: false, ref: 'Script::RemoteValue', list: true, scalar: 'string'} ) # @api private @@ -520,8 +526,8 @@ class RemoteValue < Serialization::Union # @see https://w3c.github.io/webdriver-bidi/#cddl-type-scriptfunctionremotevalue FunctionRemoteValue = Serialization::Record.define( type: {fixed: 'function'}, - handle: {wire_key: 'handle', required: false}, - internal_id: {wire_key: 'internalId', required: false} + handle: {wire_key: 'handle', required: false, primitive: 'string'}, + internal_id: {wire_key: 'internalId', required: false, primitive: 'string'} ) # @api private @@ -530,8 +536,8 @@ class RemoteValue < Serialization::Union RegExpRemoteValue = Serialization::Record.define( type: {fixed: 'regexp'}, value: {wire_key: 'value', ref: 'Script::RegExpValue'}, - handle: {wire_key: 'handle', required: false}, - internal_id: {wire_key: 'internalId', required: false} + handle: {wire_key: 'handle', required: false, primitive: 'string'}, + internal_id: {wire_key: 'internalId', required: false, primitive: 'string'} ) # @api private @@ -540,8 +546,8 @@ class RemoteValue < Serialization::Union DateRemoteValue = Serialization::Record.define( type: {fixed: 'date'}, value: {wire_key: 'value', primitive: 'string'}, - handle: {wire_key: 'handle', required: false}, - internal_id: {wire_key: 'internalId', required: false} + handle: {wire_key: 'handle', required: false, primitive: 'string'}, + internal_id: {wire_key: 'internalId', required: false, primitive: 'string'} ) # @api private @@ -549,9 +555,9 @@ class RemoteValue < Serialization::Union # @see https://w3c.github.io/webdriver-bidi/#cddl-type-scriptmapremotevalue MapRemoteValue = Serialization::Record.define( type: {fixed: 'map'}, - handle: {wire_key: 'handle', required: false}, - internal_id: {wire_key: 'internalId', required: false}, - value: {wire_key: 'value', required: false, ref: 'Script::RemoteValue', list: true} + handle: {wire_key: 'handle', required: false, primitive: 'string'}, + internal_id: {wire_key: 'internalId', required: false, primitive: 'string'}, + value: {wire_key: 'value', required: false, ref: 'Script::RemoteValue', list: true, scalar: 'string'} ) # @api private @@ -559,8 +565,8 @@ class RemoteValue < Serialization::Union # @see https://w3c.github.io/webdriver-bidi/#cddl-type-scriptsetremotevalue SetRemoteValue = Serialization::Record.define( type: {fixed: 'set'}, - handle: {wire_key: 'handle', required: false}, - internal_id: {wire_key: 'internalId', required: false}, + handle: {wire_key: 'handle', required: false, primitive: 'string'}, + internal_id: {wire_key: 'internalId', required: false, primitive: 'string'}, value: {wire_key: 'value', required: false, ref: 'Script::RemoteValue', list: true} ) @@ -569,8 +575,8 @@ class RemoteValue < Serialization::Union # @see https://w3c.github.io/webdriver-bidi/#cddl-type-scriptweakmapremotevalue WeakMapRemoteValue = Serialization::Record.define( type: {fixed: 'weakmap'}, - handle: {wire_key: 'handle', required: false}, - internal_id: {wire_key: 'internalId', required: false} + handle: {wire_key: 'handle', required: false, primitive: 'string'}, + internal_id: {wire_key: 'internalId', required: false, primitive: 'string'} ) # @api private @@ -578,8 +584,8 @@ class RemoteValue < Serialization::Union # @see https://w3c.github.io/webdriver-bidi/#cddl-type-scriptweaksetremotevalue WeakSetRemoteValue = Serialization::Record.define( type: {fixed: 'weakset'}, - handle: {wire_key: 'handle', required: false}, - internal_id: {wire_key: 'internalId', required: false} + handle: {wire_key: 'handle', required: false, primitive: 'string'}, + internal_id: {wire_key: 'internalId', required: false, primitive: 'string'} ) # @api private @@ -587,8 +593,8 @@ class RemoteValue < Serialization::Union # @see https://w3c.github.io/webdriver-bidi/#cddl-type-scriptgeneratorremotevalue GeneratorRemoteValue = Serialization::Record.define( type: {fixed: 'generator'}, - handle: {wire_key: 'handle', required: false}, - internal_id: {wire_key: 'internalId', required: false} + handle: {wire_key: 'handle', required: false, primitive: 'string'}, + internal_id: {wire_key: 'internalId', required: false, primitive: 'string'} ) # @api private @@ -596,8 +602,8 @@ class RemoteValue < Serialization::Union # @see https://w3c.github.io/webdriver-bidi/#cddl-type-scripterrorremotevalue ErrorRemoteValue = Serialization::Record.define( type: {fixed: 'error'}, - handle: {wire_key: 'handle', required: false}, - internal_id: {wire_key: 'internalId', required: false} + handle: {wire_key: 'handle', required: false, primitive: 'string'}, + internal_id: {wire_key: 'internalId', required: false, primitive: 'string'} ) # @api private @@ -605,8 +611,8 @@ class RemoteValue < Serialization::Union # @see https://w3c.github.io/webdriver-bidi/#cddl-type-scriptproxyremotevalue ProxyRemoteValue = Serialization::Record.define( type: {fixed: 'proxy'}, - handle: {wire_key: 'handle', required: false}, - internal_id: {wire_key: 'internalId', required: false} + handle: {wire_key: 'handle', required: false, primitive: 'string'}, + internal_id: {wire_key: 'internalId', required: false, primitive: 'string'} ) # @api private @@ -614,8 +620,8 @@ class RemoteValue < Serialization::Union # @see https://w3c.github.io/webdriver-bidi/#cddl-type-scriptpromiseremotevalue PromiseRemoteValue = Serialization::Record.define( type: {fixed: 'promise'}, - handle: {wire_key: 'handle', required: false}, - internal_id: {wire_key: 'internalId', required: false} + handle: {wire_key: 'handle', required: false, primitive: 'string'}, + internal_id: {wire_key: 'internalId', required: false, primitive: 'string'} ) # @api private @@ -623,8 +629,8 @@ class RemoteValue < Serialization::Union # @see https://w3c.github.io/webdriver-bidi/#cddl-type-scripttypedarrayremotevalue TypedArrayRemoteValue = Serialization::Record.define( type: {fixed: 'typedarray'}, - handle: {wire_key: 'handle', required: false}, - internal_id: {wire_key: 'internalId', required: false} + handle: {wire_key: 'handle', required: false, primitive: 'string'}, + internal_id: {wire_key: 'internalId', required: false, primitive: 'string'} ) # @api private @@ -632,8 +638,8 @@ class RemoteValue < Serialization::Union # @see https://w3c.github.io/webdriver-bidi/#cddl-type-scriptarraybufferremotevalue ArrayBufferRemoteValue = Serialization::Record.define( type: {fixed: 'arraybuffer'}, - handle: {wire_key: 'handle', required: false}, - internal_id: {wire_key: 'internalId', required: false} + handle: {wire_key: 'handle', required: false, primitive: 'string'}, + internal_id: {wire_key: 'internalId', required: false, primitive: 'string'} ) # @api private @@ -641,8 +647,8 @@ class RemoteValue < Serialization::Union # @see https://w3c.github.io/webdriver-bidi/#cddl-type-scriptnodelistremotevalue NodeListRemoteValue = Serialization::Record.define( type: {fixed: 'nodelist'}, - handle: {wire_key: 'handle', required: false}, - internal_id: {wire_key: 'internalId', required: false}, + handle: {wire_key: 'handle', required: false, primitive: 'string'}, + internal_id: {wire_key: 'internalId', required: false, primitive: 'string'}, value: {wire_key: 'value', required: false, ref: 'Script::RemoteValue', list: true} ) @@ -651,8 +657,8 @@ class RemoteValue < Serialization::Union # @see https://w3c.github.io/webdriver-bidi/#cddl-type-scripthtmlcollectionremotevalue HTMLCollectionRemoteValue = Serialization::Record.define( type: {fixed: 'htmlcollection'}, - handle: {wire_key: 'handle', required: false}, - internal_id: {wire_key: 'internalId', required: false}, + handle: {wire_key: 'handle', required: false, primitive: 'string'}, + internal_id: {wire_key: 'internalId', required: false, primitive: 'string'}, value: {wire_key: 'value', required: false, ref: 'Script::RemoteValue', list: true} ) @@ -661,9 +667,9 @@ class RemoteValue < Serialization::Union # @see https://w3c.github.io/webdriver-bidi/#cddl-type-scriptnoderemotevalue NodeRemoteValue = Serialization::Record.define( type: {fixed: 'node'}, - shared_id: {wire_key: 'sharedId', required: false}, - handle: {wire_key: 'handle', required: false}, - internal_id: {wire_key: 'internalId', required: false}, + shared_id: {wire_key: 'sharedId', required: false, primitive: 'string'}, + handle: {wire_key: 'handle', required: false, primitive: 'string'}, + internal_id: {wire_key: 'internalId', required: false, primitive: 'string'}, value: {wire_key: 'value', required: false, ref: 'Script::NodeProperties'} ) @@ -671,8 +677,8 @@ class RemoteValue < Serialization::Union # @see https://www.selenium.dev/documentation/warnings/bidi-implementation/ # @see https://w3c.github.io/webdriver-bidi/#cddl-type-scriptnodeproperties NodeProperties = Serialization::Record.define( - node_type: 'nodeType', - child_node_count: 'childNodeCount', + node_type: {wire_key: 'nodeType', primitive: 'integer'}, + child_node_count: {wire_key: 'childNodeCount', primitive: 'integer'}, attributes: {wire_key: 'attributes', required: false}, children: {wire_key: 'children', required: false, ref: 'Script::NodeRemoteValue', list: true}, local_name: {wire_key: 'localName', required: false, primitive: 'string'}, @@ -688,21 +694,21 @@ class RemoteValue < Serialization::Union WindowProxyRemoteValue = Serialization::Record.define( type: {fixed: 'window'}, value: {wire_key: 'value', ref: 'Script::WindowProxyProperties'}, - handle: {wire_key: 'handle', required: false}, - internal_id: {wire_key: 'internalId', required: false} + handle: {wire_key: 'handle', required: false, primitive: 'string'}, + internal_id: {wire_key: 'internalId', required: false, primitive: 'string'} ) # @api private # @see https://www.selenium.dev/documentation/warnings/bidi-implementation/ # @see https://w3c.github.io/webdriver-bidi/#cddl-type-scriptwindowproxyproperties - WindowProxyProperties = Serialization::Record.define(context: 'context') + WindowProxyProperties = Serialization::Record.define(context: {wire_key: 'context', primitive: 'string'}) # @api private # @see https://www.selenium.dev/documentation/warnings/bidi-implementation/ # @see https://w3c.github.io/webdriver-bidi/#type-script-SerializationOptions SerializationOptions = Serialization::Record.define( - max_dom_depth: {wire_key: 'maxDomDepth', required: false, nullable: true}, - max_object_depth: {wire_key: 'maxObjectDepth', required: false, nullable: true}, + max_dom_depth: {wire_key: 'maxDomDepth', required: false, nullable: true, primitive: 'integer'}, + max_object_depth: {wire_key: 'maxObjectDepth', required: false, nullable: true, primitive: 'integer'}, include_shadow_tree: { wire_key: 'includeShadowTree', required: false, @@ -714,9 +720,9 @@ class RemoteValue < Serialization::Union # @see https://www.selenium.dev/documentation/warnings/bidi-implementation/ # @see https://w3c.github.io/webdriver-bidi/#type-script-StackFrame StackFrame = Serialization::Record.define( - column_number: 'columnNumber', + column_number: {wire_key: 'columnNumber', primitive: 'integer'}, function_name: {wire_key: 'functionName', primitive: 'string'}, - line_number: 'lineNumber', + line_number: {wire_key: 'lineNumber', primitive: 'integer'}, url: {wire_key: 'url', primitive: 'string'} ) @@ -731,21 +737,21 @@ class RemoteValue < Serialization::Union # @see https://www.selenium.dev/documentation/warnings/bidi-implementation/ # @see https://w3c.github.io/webdriver-bidi/#type-script-Source Source = Serialization::Record.define( - realm: 'realm', - context: {wire_key: 'context', required: false}, - user_context: {wire_key: 'userContext', required: false} + realm: {wire_key: 'realm', primitive: 'string'}, + context: {wire_key: 'context', required: false, primitive: 'string'}, + user_context: {wire_key: 'userContext', required: false, primitive: 'string'} ) # @api private # @see https://www.selenium.dev/documentation/warnings/bidi-implementation/ # @see https://w3c.github.io/webdriver-bidi/#cddl-type-scriptrealmtarget - RealmTarget = Serialization::Record.define(realm: 'realm') + RealmTarget = Serialization::Record.define(realm: {wire_key: 'realm', primitive: 'string'}) # @api private # @see https://www.selenium.dev/documentation/warnings/bidi-implementation/ # @see https://w3c.github.io/webdriver-bidi/#cddl-type-scriptcontexttarget ContextTarget = Serialization::Record.define( - context: 'context', + context: {wire_key: 'context', primitive: 'string'}, sandbox: {wire_key: 'sandbox', required: false, primitive: 'string'} ) @@ -757,6 +763,7 @@ class Target < Serialization::Union 'Script::ContextTarget' => ['context'], 'Script::RealmTarget' => ['realm'] ) + object_only end # @api private @@ -773,7 +780,7 @@ class Target < Serialization::Union # @api private # @see https://www.selenium.dev/documentation/warnings/bidi-implementation/ # @see https://w3c.github.io/webdriver-bidi/#cddl-type-scriptaddpreloadscriptresult - AddPreloadScriptResult = Serialization::Record.define(script: 'script') + AddPreloadScriptResult = Serialization::Record.define(script: {wire_key: 'script', primitive: 'string'}) # @api private # @see https://www.selenium.dev/documentation/warnings/bidi-implementation/ @@ -821,7 +828,7 @@ class Target < Serialization::Union # @see https://www.selenium.dev/documentation/warnings/bidi-implementation/ # @see https://w3c.github.io/webdriver-bidi/#cddl-type-scriptgetrealmsparameters GetRealmsParameters = Serialization::Record.define( - context: {wire_key: 'context', required: false}, + context: {wire_key: 'context', required: false, primitive: 'string'}, type: {wire_key: 'type', required: false, enum: 'Script::REALM_TYPE'} ) @@ -835,13 +842,15 @@ class Target < Serialization::Union # @api private # @see https://www.selenium.dev/documentation/warnings/bidi-implementation/ # @see https://w3c.github.io/webdriver-bidi/#cddl-type-scriptremovepreloadscriptparameters - RemovePreloadScriptParameters = Serialization::Record.define(script: 'script') + RemovePreloadScriptParameters = Serialization::Record.define( + script: {wire_key: 'script', primitive: 'string'} + ) # @api private # @see https://www.selenium.dev/documentation/warnings/bidi-implementation/ # @see https://w3c.github.io/webdriver-bidi/#cddl-type-scriptmessageparameters MessageParameters = Serialization::Record.define( - channel: 'channel', + channel: {wire_key: 'channel', primitive: 'string'}, data: {wire_key: 'data', ref: 'Script::RemoteValue'}, source: {wire_key: 'source', ref: 'Script::Source'} ) @@ -849,7 +858,7 @@ class Target < Serialization::Union # @api private # @see https://www.selenium.dev/documentation/warnings/bidi-implementation/ # @see https://w3c.github.io/webdriver-bidi/#cddl-type-scriptrealmdestroyedparameters - RealmDestroyedParameters = Serialization::Record.define(realm: 'realm') + RealmDestroyedParameters = Serialization::Record.define(realm: {wire_key: 'realm', primitive: 'string'}) EVENT_TYPES = { 'script.message' => Script::MessageParameters, diff --git a/rb/lib/selenium/webdriver/bidi/protocol/session.rb b/rb/lib/selenium/webdriver/bidi/protocol/session.rb index fa394de87953c..f6080ff60094e 100644 --- a/rb/lib/selenium/webdriver/bidi/protocol/session.rb +++ b/rb/lib/selenium/webdriver/bidi/protocol/session.rb @@ -78,6 +78,7 @@ class ProxyConfiguration < Serialization::Union pac: 'Session::PacProxyConfiguration', system: 'Session::SystemProxyConfiguration' ) + object_only end # @api private @@ -203,14 +204,13 @@ class ProxyConfiguration < Serialization::Union required: false, ref: 'Session::UserPromptHandler' }, - web_socket_url: {wire_key: 'webSocketUrl', required: false, primitive: 'string'}, - extensible: true + web_socket_url: {wire_key: 'webSocketUrl', required: false, primitive: 'string'} ) # @api private # @see https://www.selenium.dev/documentation/warnings/bidi-implementation/ # @see https://w3c.github.io/webdriver-bidi/#cddl-type-sessionsubscriberesult - SubscribeResult = Serialization::Record.define(subscription: 'subscription') + SubscribeResult = Serialization::Record.define(subscription: {wire_key: 'subscription', primitive: 'string'}) # @api private # @see https://www.selenium.dev/documentation/warnings/bidi-implementation/ @@ -220,6 +220,7 @@ class UnsubscribeParameters < Serialization::Union 'Session::UnsubscribeByAttributesRequest' => ['events'], 'Session::UnsubscribeByIDRequest' => ['subscriptions'] ) + object_only end # @api private diff --git a/rb/lib/selenium/webdriver/bidi/protocol/storage.rb b/rb/lib/selenium/webdriver/bidi/protocol/storage.rb index 2cfaf4e54b2f3..6b50b696a83ce 100644 --- a/rb/lib/selenium/webdriver/bidi/protocol/storage.rb +++ b/rb/lib/selenium/webdriver/bidi/protocol/storage.rb @@ -33,8 +33,7 @@ class Storage < Domain # @see https://w3c.github.io/webdriver-bidi/#type-storage-PartitionKey PartitionKey = Serialization::Record.define( user_context: {wire_key: 'userContext', required: false, primitive: 'string'}, - source_origin: {wire_key: 'sourceOrigin', required: false, primitive: 'string'}, - extensible: true + source_origin: {wire_key: 'sourceOrigin', required: false, primitive: 'string'} ) # @api private @@ -45,11 +44,11 @@ class Storage < Domain value: {wire_key: 'value', required: false, ref: 'Network::BytesValue'}, domain: {wire_key: 'domain', required: false, primitive: 'string'}, path: {wire_key: 'path', required: false, primitive: 'string'}, - size: {wire_key: 'size', required: false}, + size: {wire_key: 'size', required: false, primitive: 'integer'}, http_only: {wire_key: 'httpOnly', required: false, primitive: 'boolean'}, secure: {wire_key: 'secure', required: false, primitive: 'boolean'}, same_site: {wire_key: 'sameSite', required: false, enum: 'Network::SAME_SITE'}, - expiry: {wire_key: 'expiry', required: false}, + expiry: {wire_key: 'expiry', required: false, primitive: 'integer'}, extensible: true ) @@ -58,7 +57,7 @@ class Storage < Domain # @see https://w3c.github.io/webdriver-bidi/#cddl-type-storagebrowsingcontextpartitiondescriptor BrowsingContextPartitionDescriptor = Serialization::Record.define( type: {fixed: 'context'}, - context: 'context' + context: {wire_key: 'context', primitive: 'string'} ) # @api private @@ -80,6 +79,7 @@ class PartitionDescriptor < Serialization::Union context: 'Storage::BrowsingContextPartitionDescriptor', storage_key: 'Storage::StorageKeyPartitionDescriptor' ) + object_only end # @api private @@ -109,7 +109,7 @@ class PartitionDescriptor < Serialization::Union http_only: {wire_key: 'httpOnly', required: false, primitive: 'boolean'}, secure: {wire_key: 'secure', required: false, primitive: 'boolean'}, same_site: {wire_key: 'sameSite', required: false, enum: 'Network::SAME_SITE'}, - expiry: {wire_key: 'expiry', required: false}, + expiry: {wire_key: 'expiry', required: false, primitive: 'integer'}, extensible: true ) diff --git a/rb/lib/selenium/webdriver/bidi/protocol/web_extension.rb b/rb/lib/selenium/webdriver/bidi/protocol/web_extension.rb index e131eff0f4e75..68c4751e92252 100644 --- a/rb/lib/selenium/webdriver/bidi/protocol/web_extension.rb +++ b/rb/lib/selenium/webdriver/bidi/protocol/web_extension.rb @@ -45,6 +45,7 @@ class ExtensionData < Serialization::Union base64: 'WebExtension::ExtensionBase64Encoded', path: 'WebExtension::ExtensionPath' ) + object_only end # @api private @@ -74,12 +75,12 @@ class ExtensionData < Serialization::Union # @api private # @see https://www.selenium.dev/documentation/warnings/bidi-implementation/ # @see https://w3c.github.io/webdriver-bidi/#cddl-type-webextensioninstallresult - InstallResult = Serialization::Record.define(extension: 'extension') + InstallResult = Serialization::Record.define(extension: {wire_key: 'extension', primitive: 'string'}) # @api private # @see https://www.selenium.dev/documentation/warnings/bidi-implementation/ # @see https://w3c.github.io/webdriver-bidi/#cddl-type-webextensionuninstallparameters - UninstallParameters = Serialization::Record.define(extension: 'extension') + UninstallParameters = Serialization::Record.define(extension: {wire_key: 'extension', primitive: 'string'}) # @api private # @see https://www.selenium.dev/documentation/warnings/bidi-implementation/ diff --git a/rb/lib/selenium/webdriver/bidi/serialization/record.rb b/rb/lib/selenium/webdriver/bidi/serialization/record.rb index ca5280e6f1990..a8364bc876e53 100644 --- a/rb/lib/selenium/webdriver/bidi/serialization/record.rb +++ b/rb/lib/selenium/webdriver/bidi/serialization/record.rb @@ -29,7 +29,7 @@ module Serialization # @api private class Record < ::Data # Named Field, not Member, to avoid colliding with +::Data#members+. - Field = ::Data.define(:name, :wire_key, :nullable, :ref, :list, :fixed, :enum, :required, :primitive) + Field = ::Data.define(:name, :wire_key, :nullable, :ref, :list, :fixed, :enum, :required, :primitive, :scalar) def self.define(**spec) extensible = spec.delete(:extensible) || false @@ -59,7 +59,8 @@ def self.field(name, meta) Field.new(name: name.to_sym, wire_key: meta.fetch(:wire_key, name.to_s), nullable: meta[:nullable] || false, ref: meta[:ref], list: meta[:list] || false, fixed: meta.fetch(:fixed, UNSET), enum: meta[:enum], - required: meta.fetch(:required, true), primitive: meta[:primitive]) + required: meta.fetch(:required, true), primitive: meta[:primitive], + scalar: meta[:scalar]) end private_class_method :field @@ -147,8 +148,18 @@ def read(field, raw) return raw end + read_ref(field, raw) + end + + # Reads a ref-typed value into its class. A `scalar` position is an inline union with + # a scalar arm collapsed onto its union ref (a map's string keys): a non-object leaf + # passes through instead of being handed to the object_only union, but only when it + # matches the arm's primitive (+scalar+ carries it). A list recurses per element. + def read_ref(field, raw) klass = (@refs ||= {})[field.name] ||= Protocol.const_get(field.ref) - field.list ? read_list(raw, klass) : klass.from_json(raw) + return read_list(field, raw, klass) if field.list + + field.scalar && !raw.is_a?(::Hash) ? scalar_value(field, raw) : klass.from_json(raw) end # A declared list must arrive as an array; a scalar-shaped field (enum or ref, not a @@ -181,10 +192,48 @@ def enum_hash(field) (@enums ||= {})[field.name] ||= Protocol.const_get(field.enum) end - # Parses each element, recursing into nested lists (e.g. a map's [key, value] pairs) - # so their entries become typed too. - def read_list(raw, klass) - raw.map { |element| element.is_a?(::Array) ? read_list(element, klass) : klass.from_json(element) } + # Parses each element. A `scalar` field is a map encoded as `[key, value]` pairs, so + # every element must be a 2-item pair — each is read as one, and a malformed entry is + # rejected. Non-scalar lists recurse into nested lists; other elements deserialize. + def read_list(field, raw, klass) + raw.map do |element| + if field.scalar + read_map_entry(field, element, klass) + elsif element.is_a?(::Array) + read_list(field, element, klass) + else + klass.from_json(element) + end + end + end + + # A map entry is a `[key, value]` pair. The key is `Ref / text` — an object key + # deserializes, a bare-string key passes through once validated against the arm's + # primitive. The value is the object-only Ref and always deserializes, so a bare scalar + # there is rejected (object_only holds at the value position). A non-pair element is a + # malformed entry and is rejected outright. + def read_map_entry(field, element, klass) + unless element.is_a?(::Array) && element.size == 2 + raise Error::WebDriverError, + "#{name}##{field.name} expected a [key, value] pair, got #{element.inspect}" + end + + key, value = element + key = key.is_a?(::Hash) ? klass.from_json(key) : scalar_value(field, key) + [key, klass.from_json(value)] + end + + # A bare scalar at a scalar-tolerant union position must match one of the union's + # scalar-arm primitives (+scalar+ is a primitive name or an array of them); a + # wrong-typed scalar (a number where a string is expected) is a wire error, not + # something to pass through. An unrecognized primitive (none in PRIMITIVE_TYPES) is + # left unchecked, matching the lenient default elsewhere. + def scalar_value(field, value) + expected = Array(field.scalar).flat_map { |primitive| PRIMITIVE_TYPES[primitive] || [] } + return value if expected.empty? || expected.any? { |type| value.is_a?(type) } + + raise Error::WebDriverError, + "#{name}##{field.name} expected #{Array(field.scalar).join(' or ')}, got #{value.inspect}" end def extra(json_payload) diff --git a/rb/lib/selenium/webdriver/bidi/serialization/union.rb b/rb/lib/selenium/webdriver/bidi/serialization/union.rb index c0ae135d6c755..b0e9ff29b3455 100644 --- a/rb/lib/selenium/webdriver/bidi/serialization/union.rb +++ b/rb/lib/selenium/webdriver/bidi/serialization/union.rb @@ -44,10 +44,19 @@ def variants(table) = @variants = table def presence(rules) = @presence = rules def fallback(path) = @fallback = path - # A non-Hash payload is a bare scalar arm (e.g. input.Origin's "viewport") with - # no object to dispatch on, so it is returned unchanged. + # Declared (via the schema's `objectOnly` signal) on a union whose every arm is an + # object, so a non-Hash payload is a schema violation rather than a scalar arm. + def object_only = @object_only = true + + # A non-Hash payload is a bare scalar arm (e.g. input.Origin's "viewport") with no + # object to dispatch on, so it is returned unchanged — unless every arm is an object + # (object_only), where a non-Hash cannot match any variant and is a wire error. def from_json(json_payload) - return json_payload unless json_payload.is_a?(::Hash) + unless json_payload.is_a?(::Hash) + return json_payload unless @object_only + + raise Error::WebDriverError, "#{name} expected an object on the wire, got #{json_payload.inspect}" + end variant = select(json_payload) unless variant diff --git a/rb/lib/selenium/webdriver/bidi/support/bidi_generate.rb b/rb/lib/selenium/webdriver/bidi/support/bidi_generate.rb index 677afd970823b..0e88f5b39451f 100644 --- a/rb/lib/selenium/webdriver/bidi/support/bidi_generate.rb +++ b/rb/lib/selenium/webdriver/bidi/support/bidi_generate.rb @@ -236,7 +236,7 @@ def type_entry = "'#{wire_name}' => #{payload_ref || 'nil'}" # ref is the Protocol-relative class path for a nested structured field (nil # for a scalar/opaque field); list wraps it in an array. wire_key is the exact # JSON payload key (the schema's `wire` name, baked verbatim). - FieldIR = Struct.new(:ruby_name, :wire_key, :required, :nullable, :ref, :list, :enum, :primitive, :rbs, + FieldIR = Struct.new(:ruby_name, :wire_key, :required, :nullable, :ref, :list, :enum, :primitive, :scalar, :rbs, keyword_init: true) do # A `Serialization::Record.define` spec entry: `name: 'jsonKey'` shorthand, or # `name: {wire_key:, …}` when the field carries JSON facts beyond its name. @@ -247,6 +247,7 @@ def spec_entry(indent = 0) meta << 'nullable: true' if nullable meta << "ref: '#{ref}'" if ref meta << 'list: true' if list + meta << "scalar: #{scalar_literal}" if scalar meta << "enum: '#{enum}'" if enum meta << "primitive: '#{primitive}'" if primitive return "#{ruby_name}: '#{wire_key}'" if meta.empty? @@ -255,6 +256,12 @@ def spec_entry(indent = 0) BiDiGenerate.wrap_call("#{ruby_name}: ", meta, indent, open: '{', close: '}') end + # The `scalar` primitive(s) a bare non-object wire value must match at a scalar-tolerant + # union position: a single primitive string, or an array when the union's scalar arms differ. + def scalar_literal + scalar.is_a?(::Array) ? "[#{scalar.map { |s| "'#{s}'" }.join(', ')}]" : "'#{scalar}'" + end + # The `self.new` keyword for this field — a user-supplied input carrying the field's # value type. The `?` prefix marks the field omittable; its value type already carries # the schema's nullability, so nil is admitted only for a nullable field. @@ -350,8 +357,10 @@ def discriminator_pair # A generated discriminated union (< Serialization::Union, resolved by lexical scope). # nested holds its synthetic variant records (see nest_synthetic). spec_href links to - # the union's definition in the live spec (nil when the schema has none). - UnionClass = Struct.new(:ruby_name, :discriminator_wire, :variants, :schema_name, :nested, :spec_href, + # the union's definition in the live spec (nil when the schema has none). object_only + # mirrors the schema's `objectOnly` signal: when true, a non-Hash payload is rejected + # rather than passed through (every arm is an object, so it can match no variant). + UnionClass = Struct.new(:ruby_name, :discriminator_wire, :variants, :schema_name, :nested, :spec_href, :object_only, keyword_init: true) do def union? = true def value_variants = variants.select { |v| v.mode == :value } @@ -533,29 +542,33 @@ def resolve(node) nullable = node['nullable'] ? true : false if node.key?('list') element = resolve(node['list']) - return {ref: element[:ref], list: true, nullable: nullable, rbs: nilable("Array[#{element[:rbs]}]", nullable)} + return {ref: element[:ref], list: true, nullable: nullable, scalar: element[:scalar], + rbs: nilable("Array[#{element[:rbs]}]", nullable)} end if node.key?('ref') named = resolve_named(node['ref']) - return {ref: named[:ref], list: named[:list], nullable: nullable, rbs: nilable(named[:rbs], nullable)} + return {ref: named[:ref], list: named[:list], nullable: nullable, scalar: named[:scalar], + rbs: nilable(named[:rbs], nullable)} end return resolve_union(node, nullable) if node.key?('union') - {ref: nil, list: false, nullable: nullable, primitive: checkable_primitive(node), - rbs: nilable(scalar_rbs(node), nullable)} + {ref: nil, list: false, nullable: nullable, rbs: nilable(scalar_rbs(node), nullable)} end # An inline union of one union-typed arm plus scalars (e.g. a MappingRemoteValue entry, - # RemoteValue / string) parses through that arm — its from_json returns a non-Hash value - # unchanged, so the scalar siblings pass through. Carry its ref so nested entries are typed; - # any other shape (a record arm, multiple structured arms, all scalars) stays opaque. + # RemoteValue / string) is carried as that union ref so nested entries are typed. Because + # the union is object_only, a bare-scalar sibling would raise there — so the projector's + # `scalar` signal (a bare-scalar arm is present) is forwarded, and the runtime passes a + # non-object leaf through instead (the map's string keys). Any other shape (a record arm, + # multiple structured arms, all scalars) stays opaque. def resolve_union(node, nullable) refs = node['union'].select { |arm| arm.key?('ref') } opaque = {ref: nil, list: false, nullable: nullable, rbs: nilable('untyped', nullable)} return opaque unless refs.one? && union_ref?(refs.first['ref']) named = resolve_named(refs.first['ref']) - {ref: named[:ref], list: named[:list], nullable: nullable, rbs: nilable('untyped', nullable)} + {ref: named[:ref], list: named[:list], nullable: nullable, scalar: node['scalar'], + rbs: nilable('untyped', nullable)} end # True when a ref (following aliases) is a union — the only arm whose from_json tolerates a @@ -602,7 +615,7 @@ def resolve_named_alias(name, inner, seen) if inner.key?('list') element = resolve(inner['list']) - return {ref: element[:ref], list: true, rbs: "Array[#{element[:rbs]}]"} + return {ref: element[:ref], list: true, scalar: element[:scalar], rbs: "Array[#{element[:rbs]}]"} end {ref: nil, list: false, rbs: scalar_rbs(inner)} @@ -618,8 +631,11 @@ def record_class(name, type) wire: const['wire'], value: const['type']['const'], rbs: rbs_const(const['type']['const'])} fields = type['fields'].reject { |f| baked_discriminator?(f) }.map { |f| field_ir(f) } + # Gate the extensions store on `preserveExtras` (extensible AND re-sendable), not raw + # `extensible`: only a type you receive and can hand back keeps unknown wire keys. A + # received-only extensible type gets no store, so its unknown keys are silently ignored. TypeClass.new(ruby_name: BiDiGenerate.type_class_name(name), fields: fields, - discriminator: discriminator, extensible: type['extensible'] ? true : false, + discriminator: discriminator, extensible: type['preserveExtras'] ? true : false, schema_name: name, synthetic: type['synthetic'] ? true : false, owner: type['owner'], label: type['label'], spec_href: type['specHref']) end @@ -638,7 +654,25 @@ def field_ir(field) FieldIR.new(ruby_name: ruby_name, wire_key: field['wire'], required: field['required'], nullable: resolved[:nullable], ref: resolved[:ref], list: resolved[:list], enum: enum_const(field['type']), - primitive: resolved[:primitive], rbs: resolved[:rbs]) + primitive: leaf_primitive(field['type']), scalar: resolved[:scalar], + rbs: resolved[:rbs]) + end + + # The runtime-checkable scalar primitive of a field, following alias chains so a + # scalar hidden behind a named alias (js-uint -> integer, browsingContext.BrowsingContext + # -> string) is typed rather than opaque. The projector carries the primitive on the + # alias node; this surfaces it onto the field. Nil for a list (its elements are not + # scalar-checked), a record/union ref, an enum, a const, or an opaque value. + def leaf_primitive(node, seen = {}) + return node['primitive'] if node.key?('primitive') && CHECKABLE_PRIMITIVES.include?(node['primitive']) + return nil unless node.key?('ref') + + name = node['ref'] + type = @types[name] + return nil if seen[name] || type.nil? || type['kind'] != 'alias' + + seen[name] = true + leaf_primitive(type['type'], seen) end def union_class(name) @@ -672,7 +706,7 @@ def union_from_selector(name, selector) UnionClass.new(ruby_name: BiDiGenerate.type_class_name(name), discriminator_wire: selector['by'], variants: variants, schema_name: name, - spec_href: @types[name]['specHref']) + spec_href: @types[name]['specHref'], object_only: @types[name]['objectOnly'] ? true : false) end def discriminated_variants(selector) @@ -704,9 +738,11 @@ def union_from_alias(name) variants = consts.map do |ref, const| VariantIR.new(mode: :value, value: const['type']['const'], ref: ruby_path(ref), requires: nil) end + # An alias-union carries bare-scalar arms (input.Origin's "viewport"/"pointer"), so it + # is never object_only — those arms must still pass a non-Hash payload through. UnionClass.new(ruby_name: BiDiGenerate.type_class_name(name), discriminator_wire: consts.values.first['wire'], variants: variants, schema_name: name, - spec_href: @types[name]['specHref']) + spec_href: @types[name]['specHref'], object_only: @types[name]['objectOnly'] ? true : false) end def record_params(fields) @@ -738,10 +774,6 @@ def rbs_type(node) # check fails open rather than a wrong strict default rejecting valid data. CHECKABLE_PRIMITIVES = %w[string number integer boolean].freeze - def checkable_primitive(node) - node['primitive'] if node.key?('primitive') && CHECKABLE_PRIMITIVES.include?(node['primitive']) - end - # The leaf of +resolve+: the bare scalar type, before any nullable wrap. An alias's # own nullable is intentionally left off — only the referencing node's is applied. def scalar_rbs(node) diff --git a/rb/lib/selenium/webdriver/bidi/support/templates/module.rb.erb b/rb/lib/selenium/webdriver/bidi/support/templates/module.rb.erb index 4eef796649883..8206f96ac084b 100644 --- a/rb/lib/selenium/webdriver/bidi/support/templates/module.rb.erb +++ b/rb/lib/selenium/webdriver/bidi/support/templates/module.rb.erb @@ -67,6 +67,9 @@ module Selenium <%- if type.fallback_variant -%> fallback '<%= type.fallback_variant.ref %>' <%- end -%> +<%- if type.object_only -%> + object_only +<%- end -%> <%- type.nested_types.each do |nested| -%> # @api private diff --git a/rb/sig/lib/selenium/webdriver/bidi/protocol/emulation.rbs b/rb/sig/lib/selenium/webdriver/bidi/protocol/emulation.rbs index cf0216b8c14cc..b34c6368e8ba1 100644 --- a/rb/sig/lib/selenium/webdriver/bidi/protocol/emulation.rbs +++ b/rb/sig/lib/selenium/webdriver/bidi/protocol/emulation.rbs @@ -127,10 +127,10 @@ module Selenium end class SetScrollbarTypeOverrideParameters < ::Selenium::WebDriver::BiDi::Serialization::Record - attr_reader scrollbar_type: untyped + attr_reader scrollbar_type: String? attr_reader contexts: untyped attr_reader user_contexts: untyped - def self.new: (scrollbar_type: untyped, ?contexts: Array[String], ?user_contexts: Array[String]) -> instance + def self.new: (scrollbar_type: String?, ?contexts: Array[String], ?user_contexts: Array[String]) -> instance end class SetTimezoneOverrideParameters < ::Selenium::WebDriver::BiDi::Serialization::Record @@ -154,7 +154,7 @@ module Selenium def set_screen_orientation_override: (screen_orientation: ::Selenium::WebDriver::BiDi::Protocol::Emulation::ScreenOrientation?, ?contexts: Array[String], ?user_contexts: Array[String]) -> untyped def set_screen_settings_override: (screen_area: ::Selenium::WebDriver::BiDi::Protocol::Emulation::ScreenArea?, ?contexts: Array[String], ?user_contexts: Array[String]) -> untyped def set_scripting_enabled: (enabled: bool?, ?contexts: Array[String], ?user_contexts: Array[String]) -> untyped - def set_scrollbar_type_override: (scrollbar_type: untyped, ?contexts: Array[String], ?user_contexts: Array[String]) -> untyped + def set_scrollbar_type_override: (scrollbar_type: String?, ?contexts: Array[String], ?user_contexts: Array[String]) -> untyped def set_timezone_override: (timezone: String?, ?contexts: Array[String], ?user_contexts: Array[String]) -> untyped def set_touch_override: (max_touch_points: Integer?, ?contexts: Array[String], ?user_contexts: Array[String]) -> untyped def set_user_agent_override: (user_agent: String?, ?contexts: Array[String], ?user_contexts: Array[String]) -> untyped diff --git a/rb/sig/lib/selenium/webdriver/bidi/protocol/network.rbs b/rb/sig/lib/selenium/webdriver/bidi/protocol/network.rbs index c10f1ba1a5c79..025217212748e 100644 --- a/rb/sig/lib/selenium/webdriver/bidi/protocol/network.rbs +++ b/rb/sig/lib/selenium/webdriver/bidi/protocol/network.rbs @@ -89,8 +89,7 @@ module Selenium attr_reader secure: bool attr_reader same_site: Symbol attr_reader expiry: untyped - attr_reader extensions: Hash[String, untyped] - def self.new: (name: String, value: ::Selenium::WebDriver::BiDi::Protocol::Network::BytesValue, domain: String, path: String, size: Integer, http_only: bool, secure: bool, same_site: Symbol, ?expiry: Integer, ?extensions: untyped) -> instance + def self.new: (name: String, value: ::Selenium::WebDriver::BiDi::Protocol::Network::BytesValue, domain: String, path: String, size: Integer, http_only: bool, secure: bool, same_site: Symbol, ?expiry: Integer) -> instance end class CookieHeader < ::Selenium::WebDriver::BiDi::Serialization::Record diff --git a/rb/sig/lib/selenium/webdriver/bidi/protocol/session.rbs b/rb/sig/lib/selenium/webdriver/bidi/protocol/session.rbs index 34b66a5127ba3..6a958e006dbc2 100644 --- a/rb/sig/lib/selenium/webdriver/bidi/protocol/session.rbs +++ b/rb/sig/lib/selenium/webdriver/bidi/protocol/session.rbs @@ -140,8 +140,7 @@ module Selenium attr_reader proxy: untyped attr_reader unhandled_prompt_behavior: untyped attr_reader web_socket_url: untyped - attr_reader extensions: Hash[String, untyped] - def self.new: (accept_insecure_certs: bool, browser_name: String, browser_version: String, platform_name: String, set_window_rect: bool, user_agent: String, ?proxy: ::Selenium::WebDriver::BiDi::Protocol::Session::ProxyConfiguration, ?unhandled_prompt_behavior: ::Selenium::WebDriver::BiDi::Protocol::Session::UserPromptHandler, ?web_socket_url: String, ?extensions: untyped) -> instance + def self.new: (accept_insecure_certs: bool, browser_name: String, browser_version: String, platform_name: String, set_window_rect: bool, user_agent: String, ?proxy: ::Selenium::WebDriver::BiDi::Protocol::Session::ProxyConfiguration, ?unhandled_prompt_behavior: ::Selenium::WebDriver::BiDi::Protocol::Session::UserPromptHandler, ?web_socket_url: String) -> instance end end diff --git a/rb/sig/lib/selenium/webdriver/bidi/protocol/storage.rbs b/rb/sig/lib/selenium/webdriver/bidi/protocol/storage.rbs index 366b3b2692bf3..055432d048148 100644 --- a/rb/sig/lib/selenium/webdriver/bidi/protocol/storage.rbs +++ b/rb/sig/lib/selenium/webdriver/bidi/protocol/storage.rbs @@ -26,8 +26,7 @@ module Selenium class PartitionKey < ::Selenium::WebDriver::BiDi::Serialization::Record attr_reader user_context: untyped attr_reader source_origin: untyped - attr_reader extensions: Hash[String, untyped] - def self.new: (?user_context: String, ?source_origin: String, ?extensions: untyped) -> instance + def self.new: (?user_context: String, ?source_origin: String) -> instance end class CookieFilter < ::Selenium::WebDriver::BiDi::Serialization::Record diff --git a/rb/sig/lib/selenium/webdriver/bidi/serialization.rbs b/rb/sig/lib/selenium/webdriver/bidi/serialization.rbs index 4079feb2faa24..ba4fbf6504b69 100644 --- a/rb/sig/lib/selenium/webdriver/bidi/serialization.rbs +++ b/rb/sig/lib/selenium/webdriver/bidi/serialization.rbs @@ -68,13 +68,19 @@ module Selenium def read: (untyped field, untyped raw) -> untyped + def read_ref: (untyped field, untyped raw) -> untyped + def check_shape: (untyped field, untyped raw) -> void def check_primitive: (untyped field, untyped raw) -> void def enum_hash: (untyped field) -> untyped - def read_list: (untyped raw, untyped klass) -> untyped + def read_list: (untyped field, untyped raw, untyped klass) -> untyped + + def read_map_entry: (untyped field, untyped element, untyped klass) -> untyped + + def scalar_value: (untyped field, untyped value) -> untyped def extra: (Hash[untyped, untyped] json_payload) -> Hash[untyped, untyped] end @@ -101,6 +107,8 @@ module Selenium def self.fallback: (String path) -> String + def self.object_only: () -> bool + def self.from_json: (untyped json_payload) -> untyped def self.build: (**untyped kwargs) -> untyped diff --git a/rb/spec/unit/selenium/webdriver/bidi/serialization_spec.rb b/rb/spec/unit/selenium/webdriver/bidi/serialization_spec.rb index 340726e74eb93..b0adce8300080 100644 --- a/rb/spec/unit/selenium/webdriver/bidi/serialization_spec.rb +++ b/rb/spec/unit/selenium/webdriver/bidi/serialization_spec.rb @@ -81,6 +81,25 @@ def valid_cookie_attrs expect { BrowsingContext::Locator.from_json(payload) } .to raise_error(Error::WebDriverError, /variant not in this Selenium's BiDi schema/) end + + it 'raises when an object-only union receives a bare scalar (no arm can match)' do + expect { Script::RemoteValue.from_json('not-an-object') } + .to raise_error(Error::WebDriverError, /RemoteValue expected an object/) + end + + it 'passes a bare scalar through a union that has a scalar arm (input.Origin)' do + expect(Input::Origin.from_json('viewport')).to eq('viewport') + end + + it 'keeps a map string key while typing its object value (object-only value union)' do + parsed = Script::ObjectRemoteValue.from_json( + 'type' => 'object', 'value' => [['k', {'type' => 'number', 'value' => 2}]] + ) + key, value = parsed.value.first + + expect(key).to eq('k') # a bare-string key survives, not rejected by the object-only union + expect(value).to be_a(Script::NumberValue) + end end describe 'nested structured fields' do @@ -124,6 +143,45 @@ def valid_cookie_attrs expect(value).to be_a(Script::NumberValue) expect(value.value).to eq(2) end + + # The outbound mirror of the map-key case: a bare-string key serializes through the + # scalar-tolerant union untouched while its object value is typed, and round-trips back. + it 'serializes and round-trips a map LocalValue whose key is a bare string' do + obj = Script::ObjectLocalValue.new(value: [['k', Script::StringValue.new(value: 'x')]]) + + expect(obj.as_json).to eq( + 'type' => 'object', + 'value' => [['k', {'type' => 'string', 'value' => 'x'}]] + ) + expect(Script::LocalValue.from_json(obj.as_json)).to eq(obj) + end + + # A scalar-tolerant position still validates the scalar arm's type: the map entry is + # `RemoteValue / text`, so a non-string bare value is a wire error, not passed through. + it 'rejects a wrong-typed scalar at a map key position instead of passing it through' do + wire = {'type' => 'object', 'value' => [[42, {'type' => 'number', 'value' => 2}]]} + + expect { Script::ObjectRemoteValue.from_json(wire) } + .to raise_error(Error::WebDriverError, /value expected string, got 42/) + end + + # Scalar tolerance is the key's alone: the value is the object-only RemoteValue union, + # so a bare-scalar value is rejected rather than passed through — object_only holds here. + it 'rejects a bare-scalar map value against the object-only value union' do + wire = {'type' => 'object', 'value' => [['k', 'bare string, not an object']]} + + expect { Script::ObjectRemoteValue.from_json(wire) } + .to raise_error(Error::WebDriverError, /expected an object on the wire/) + end + + # A map is `[key, value]` pairs; a malformed entry that is not a 2-item pair is a wire + # error, not something to pass through the scalar-tolerant path. + it 'rejects a malformed map entry that is not a [key, value] pair' do + wire = {'type' => 'object', 'value' => [['orphan-key']]} + + expect { Script::ObjectRemoteValue.from_json(wire) } + .to raise_error(Error::WebDriverError, /expected a \[key, value\] pair/) + end end describe 'optional + nullable fields' do @@ -151,6 +209,31 @@ def valid_cookie_attrs expect(parsed.extensions).to eq('webdriverValue' => 42) expect(parsed.as_json).to eq('sharedId' => 's1', 'webdriverValue' => 42) end + + # A re-sendable type (reachable from a command's params, e.g. a cookie filter) keeps + # unknown properties so a received-then-resent payload round-trips them. + it 'preserves an unknown key on a re-sendable type across a receive/re-send round trip' do + parsed = Storage::CookieFilter.from_json('name' => 'sid', 'x-vendor' => 'keep-me') + + expect(parsed.extensions).to eq('x-vendor' => 'keep-me') + expect(parsed.as_json).to eq('name' => 'sid', 'x-vendor' => 'keep-me') + end + + # network.Cookie is extensible but received-only (not reachable from any command's + # params), so preserveExtras is false: unknown keys are ignored, not stored/echoed. + it 'drops an unknown key on an extensible-but-received-only type on re-serialize' do + wire = Network::Cookie.new(**valid_cookie_attrs).as_json.merge('x-vendor' => 'drop-me') + parsed = Network::Cookie.from_json(wire) + + expect(parsed).not_to respond_to(:extensions) + expect(parsed.as_json).not_to include('x-vendor') + end + + it 'ignores an unknown key without raising on a non-extensible type' do + wire = {'type' => 'password', 'username' => 'u', 'password' => 'p', 'x-vendor' => 'v'} + + expect { Network::AuthCredentials.from_json(wire) }.not_to raise_error + end end describe 'outbound union command params' do @@ -316,6 +399,20 @@ def valid_cookie_attrs expect(parsed.key).to eq(5) end + + # Signal 3: an inline literal choice the projector now types as `string` + # (scrollbarType = "classic" / "overlay" / null), previously opaque. + it 'raises when an inline-enum scalar field arrives as the wrong primitive' do + expect { Emulation::SetScrollbarTypeOverrideParameters.from_json('scrollbarType' => 123) } + .to raise_error(Error::WebDriverError, /scrollbar_type expected string/) + end + + # Signal 3: a scalar hidden behind an alias (size -> js-uint -> integer) now carries + # its leaf primitive, so a wrong-typed value is rejected instead of passing opaque. + it 'raises when an alias-typed integer field (js-uint) arrives as a string' do + expect { Network::Cookie.from_json(cookie_wire.merge('size' => 'big')) } + .to raise_error(Error::WebDriverError, /size expected integer/) + end end end end # Protocol