Skip to content

[js] Add serialization and domain layer - #17927

Open
pujagani wants to merge 1 commit into
SeleniumHQ:trunkfrom
pujagani:bidi-domain-js
Open

[js] Add serialization and domain layer#17927
pujagani wants to merge 1 commit into
SeleniumHQ:trunkfrom
pujagani:bidi-domain-js

Conversation

@pujagani

Copy link
Copy Markdown
Contributor

🔗 Related Issues

Add Domain and Serialization class, foundation for CDDL generation.

💥 What does this PR do?

Introduces Domain base class (modules will be built on top of this for generator) and bunch of serialization base classes (
defineRecord/defineEnum/defineUnion etc) in alignment with low-level behavioral ADR.

🔧 Implementation Notes

🤖 AI assistance

  • No substantial AI assistance used
  • AI assisted (complete below)
    • Tool(s):
    • What was generated:
    • I reviewed all AI output and can explain the change

💡 Additional Considerations

🔄 Types of changes

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

@selenium-ci selenium-ci added C-nodejs JavaScript Bindings B-build Includes scripting, bazel and CI integrations B-devtools Includes everything BiDi or Chrome DevTools related labels Aug 18, 2026
@qodo-code-review

Copy link
Copy Markdown
Contributor

PR Summary by Qodo

Add JavaScript BiDi domain and serialization foundation

✨ Enhancement 🧪 Tests 🕐 40+ Minutes

Grey Divider

AI Description

• Adds a guarded base class for generated WebDriver BiDi domains.
• Introduces schema-driven records, enums, aliases, unions, and runtime wire validation.
• Defines inbound/outbound contracts with comprehensive serialization and security tests.
Diagram

graph TD
  G["Generated Domains"] --> D["Domain Base"] --> B["BiDi Connection"]
  G --> S["Serialization Types"] --> R["Type Registry"] --> V["Wire Validation"] --> B
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Generate standalone serializers per domain
  • ➕ Eliminates the global runtime registry
  • ➕ Allows generated code to inline domain-specific validation
  • ➖ Duplicates validation logic across generated modules
  • ➖ Increases generated output and generator complexity
  • ➖ Makes consistent inbound and outbound behavior harder to maintain
2. Use JSON Schema with Ajv
  • ➕ Uses a mature validation engine
  • ➕ Provides broad schema validation capabilities
  • ➖ Requires translating BiDi CDDL semantics into JSON Schema
  • ➖ Adds a runtime dependency and bundle overhead
  • ➖ Does not naturally model directional extras or typed union instances

Recommendation: Retain the shared schema-aware runtime introduced by this PR. It centralizes wire-contract behavior while keeping generated domain modules small, and deferred registry resolution directly supports cross-domain, forward, and circular references. Standalone generation or Ajv would add duplication or impedance without clear benefit for the BiDi-specific semantics.

Files changed (14) +1309 / -0

Enhancement (9) +631 / -0
domain.d.tsDeclare the generated BiDi domain API +37/-0

Declare the generated BiDi domain API

• Defines typed event descriptors, the guarded domain construction token, command dispatch, and callback subscription methods.

javascript/selenium-webdriver/bidi/domain.d.ts

domain.jsImplement the shared BiDi domain runtime +76/-0

Implement the shared BiDi domain runtime

• Adds guarded domain construction, shared connection acquisition, remote-error handling, and typed event payload parsing before callback delivery.

javascript/selenium-webdriver/bidi/domain.js

enum.d.tsDeclare schema enum definitions +23/-0

Declare schema enum definitions

• Adds the typed enum entry contract and defineEnum factory declaration.

javascript/selenium-webdriver/bidi/serialization/enum.d.ts

enum.jsImplement registered schema enums +31/-0

Implement registered schema enums

• Creates set-backed enum membership checks and registers enum definitions for reference validation.

javascript/selenium-webdriver/bidi/serialization/enum.js

record.d.tsDeclare record schemas and validation types +58/-0

Declare record schemas and validation types

• Defines schema type nodes, field metadata, extensibility options, immutable record classes, aliases, and validation errors.

javascript/selenium-webdriver/bidi/serialization/record.d.ts

record.jsImplement directional record validation +258/-0

Implement directional record validation

• Adds immutable schema records with strict outbound validation and tolerant inbound handling of undeclared fields. Supports primitives, constants, enums, collections, references, aliases, unions, nullable values, and prototype-safe extensible fields.

javascript/selenium-webdriver/bidi/serialization/record.js

registry.jsAdd deferred schema type resolution +34/-0

Add deferred schema type resolution

• Introduces a shared name-based type registry so generated types can resolve forward, circular, and cross-domain references during validation.

javascript/selenium-webdriver/bidi/serialization/registry.js

union.d.tsDeclare schema union definitions +27/-0

Declare schema union definitions

• Defines union options and typed outbound build and inbound parsing operations.

javascript/selenium-webdriver/bidi/serialization/union.d.ts

union.jsImplement discriminated and structural unions +87/-0

Implement discriminated and structural unions

• Selects union variants by discriminator or ordered required-key matching, then delegates to the selected record's directional validation path.

javascript/selenium-webdriver/bidi/serialization/union.js

Tests (4) +673 / -0
domain_test.jsTest domain callbacks and construction safeguards +98/-0

Test domain callbacks and construction safeguards

• Verifies typed and untyped event dispatch, callback removal, token enforcement, and private transport encapsulation.

javascript/selenium-webdriver/test/bidi/domain_test.js

record_test.jsTest record validation and extensibility +191/-0

Test record validation and extensibility

• Covers required fields, enum and integer validation, nullability, immutability, inbound warnings, extensible extras, and prototype-pollution protection.

javascript/selenium-webdriver/test/bidi/serialization/record_test.js

union_test.jsTest union variant selection +117/-0

Test union variant selection

• Exercises outbound and inbound dispatch for discriminated and structural unions, including unknown variants and extensible records.

javascript/selenium-webdriver/test/bidi/serialization/union_test.js

wire_contract_test.jsCodify BiDi wire-contract guarantees +267/-0

Codify BiDi wire-contract guarantees

• Tests typed representation, field-name mapping, numeric fidelity, directional validation, extensibility behavior, undeclared-field handling, and remote error precedence.

javascript/selenium-webdriver/test/bidi/serialization/wire_contract_test.js

Other (1) +5 / -0
BUILD.bazelPackage serialization modules and register their tests +5/-0

Package serialization modules and register their tests

• Includes the new BiDi serialization directory in the JavaScript library and adds domain, record, union, and wire-contract suites to the small-test target.

javascript/selenium-webdriver/BUILD.bazel

@qodo-code-review

Copy link
Copy Markdown
Contributor

Code Review by Qodo

🐞 Bugs (7) 📘 Rule violations (6) 📜 Skill insights (0)

Grey Divider


Action required

1. Callback transport methods missing 🐞 Bug ≡ Correctness
Description
Domain.addCallback() and removeCallback() invoke methods that the real BiDi connection does not
implement, so every generated event registration or removal fails with a TypeError. The connection
is an EventEmitter exposing protocol events through on/off, while its subscription methods are
named subscribe and unsubscribe.
Code

javascript/selenium-webdriver/bidi/domain.js[R66-72]

+  async addCallback(descriptor, handler) {
+    const dispatch = descriptor.type === undefined ? handler : (params) => handler(descriptor.type.fromWire(params))
+    return this.#bidi.addCallback(descriptor.method, dispatch)
+  }
+
+  async removeCallback(subscriptionId) {
+    return this.#bidi.removeCallback(subscriptionId)
Evidence
The domain obtains the Index transport through getBidiConnection; that class emits incoming
event methods but defines no callback registration or removal methods matching these calls.

javascript/selenium-webdriver/bidi/domain.js[54-68]
javascript/selenium-webdriver/lib/bidi_connection.js[39-56]
javascript/selenium-webdriver/bidi/index.js[82-105]
javascript/selenium-webdriver/bidi/index.js[231-312]

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

## Issue description
`Domain.addCallback()` and `removeCallback()` delegate to nonexistent methods on the real BiDi connection, causing event APIs to fail at runtime.

## Issue Context
`getBidiConnection()` returns `bidi/index.js`, which emits events by protocol method name and implements `subscribe()`/`unsubscribe()`, but not `addCallback()`/`removeCallback()`.

## Fix Focus Areas
- javascript/selenium-webdriver/bidi/domain.js[66-72]
- javascript/selenium-webdriver/bidi/index.js[82-105]
- javascript/selenium-webdriver/bidi/index.js[231-312]

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


2. Inline enums bypass validation 🐞 Bug ≡ Correctness
Description
validateValue() returns after checking an inline enum's primitive, so it never checks the same
node's enum values. Projected inline enums therefore accept any value of the correct primitive
type rather than only their declared literals.
Code

javascript/selenium-webdriver/bidi/serialization/record.js[R34-44]

+  if (typeNode.primitive !== undefined) {
+    const expected = { string: 'string', integer: 'number', number: 'number', boolean: 'boolean' }[typeNode.primitive]
+    if (expected && typeof value !== expected) {
+      throw new ValidationError(`${path}: expected ${typeNode.primitive}, got ${typeof value}`)
+    }
+    // `number` admits any JSON number; `integer` rejects a fractional value
+    // (5.7) while still accepting one written 5.0 (Number.isInteger(5.0) is true).
+    if (typeNode.primitive === 'integer' && !Number.isInteger(value)) {
+      throw new ValidationError(`${path}: expected an integer, got ${value}`)
+    }
+    return
Evidence
The projector creates {enum: values, primitive: ...} nodes, while the validator's earlier
primitive branch returns before reaching its enum branch.

javascript/selenium-webdriver/project_bidi_schema.mjs[132-140]
javascript/selenium-webdriver/bidi/serialization/record.js[34-63]

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

## Issue description
Inline enum nodes contain both `primitive` and `enum`, but primitive validation returns before validating the allowed literals.

## Issue Context
`project_bidi_schema.mjs` deliberately emits both properties so bindings can enforce the primitive and closed vocabulary.

## Fix Focus Areas
- javascript/selenium-webdriver/bidi/serialization/record.js[34-63]
- javascript/selenium-webdriver/project_bidi_schema.mjs[132-140]

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


3. Inline records skip validation 🐞 Bug ≡ Correctness
Description
The schema projector emits inline field types as {record: [...]}, but validateValue() has no
record branch and silently accepts them. Missing required members, invalid member types, and
undeclared members in inline records consequently pass both inbound and outbound validation.
Code

javascript/selenium-webdriver/bidi/serialization/record.js[R128-140]

+  if (typeNode.union !== undefined) {
+    const errors = []
+    for (const variant of typeNode.union) {
+      try {
+        validateValue(variant, value, path, direction)
+        return
+      } catch (err) {
+        errors.push(err.message)
+      }
+    }
+    throw new ValidationError(`${path}: value did not match any variant (${errors.join('; ')})`)
+  }
+}
Evidence
projectEntry() explicitly returns a record node for an inline named group, but the new TypeNode
declaration and runtime validator recognize no such property.

javascript/selenium-webdriver/project_bidi_schema.mjs[195-204]
javascript/selenium-webdriver/bidi/serialization/record.d.ts[19-36]
javascript/selenium-webdriver/bidi/serialization/record.js[128-140]

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

## Issue description
Inline record TypeNodes emitted by the schema projector fall through `validateValue()` without any validation.

## Issue Context
Inline records contain projected `FieldSpec` entries and need the same directional required-field, extra-field, and nested-value handling as named records. Add the missing TypeScript representation as well.

## Fix Focus Areas
- javascript/selenium-webdriver/bidi/serialization/record.js[28-140]
- javascript/selenium-webdriver/bidi/serialization/record.d.ts[19-36]
- javascript/selenium-webdriver/project_bidi_schema.mjs[195-204]

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


View high (2)
4. Nested parsing result discarded 🐞 Bug ≡ Correctness
Description
Nested record and union references are parsed only for validation, after which fromWire() assigns
the original raw object to the parent. Nested fields therefore remain plain mutable objects and
retain undeclared properties that their nested fromWire() call had dropped.
Code

javascript/selenium-webdriver/bidi/serialization/record.js[R103-106]

+      if (direction === 'inbound') {
+        referenced.RecordClass.fromWire(value)
+      } else {
+        new referenced.RecordClass(value)
Evidence
The referenced fromWire() methods return typed sanitized instances, but their return values are
ignored and line 213 stores the original payload value instead.

javascript/selenium-webdriver/bidi/serialization/record.js[96-117]
javascript/selenium-webdriver/bidi/serialization/record.js[203-214]
javascript/selenium-webdriver/bidi/serialization/union.js[70-80]

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

## Issue description
Nested record and union parsing results are discarded, leaving raw wire objects in otherwise typed parent records.

## Issue Context
`validateValue()` currently returns no transformed value. Refactor validation/parsing so inbound nested refs return and assign the `fromWire()` result, while preserving outbound behavior.

## Fix Focus Areas
- javascript/selenium-webdriver/bidi/serialization/record.js[96-117]
- javascript/selenium-webdriver/bidi/serialization/record.js[203-214]

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


5. Validated collections remain mutable 🐞 Bug ☼ Reliability
Description
Record construction stores caller-owned arrays and objects directly and only freezes the outer
instance. A caller can mutate a validated list or map afterward, including inserting schema-invalid
values that are then serialized to the wire.
Code

javascript/selenium-webdriver/bidi/serialization/record.js[R165-168]

+        const value = data[field.wire]
+        validateValue(field.type, value, `${name}.${field.wire}`, 'outbound')
+        this[field.name] = value
+      }
Evidence
List and map validation only iterates their contents, and both constructors retain the original
value reference before freezing only the record object.

javascript/selenium-webdriver/bidi/serialization/record.js[65-80]
javascript/selenium-webdriver/bidi/serialization/record.js[165-187]
javascript/selenium-webdriver/test/bidi/serialization/record_test.js[76-81]

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

## Issue description
Validated arrays, maps, and nested objects remain mutable after a record is frozen, allowing post-validation corruption.

## Issue Context
The outer `Object.freeze()` does not freeze or copy values assigned from input data. Store immutable validated copies or deeply freeze the supported value graph.

## Fix Focus Areas
- javascript/selenium-webdriver/bidi/serialization/record.js[65-80]
- javascript/selenium-webdriver/bidi/serialization/record.js[158-187]
- javascript/selenium-webdriver/bidi/serialization/record.js[203-237]

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



Remediation recommended

6. event JSDoc lacks description 📘 Rule violation ✧ Quality
Description
The exported event function's JSDoc contains no free-text summary, and its @returns tag has no
description. This leaves the public API documentation incomplete.
Code

javascript/selenium-webdriver/bidi/domain.js[R37-39]

+ * @returns {{method: string, type: ({fromWire(payload: unknown): unknown}|undefined)}}
+ */
+function event(method, type) {
Evidence
The checklist requires a free-text description and a return type with descriptive text. The added
block begins directly with @param, while its @returns tag provides only a type.

Rule 389257: Document public API functions with complete JSDoc blocks
javascript/selenium-webdriver/bidi/domain.js[29-39]

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

## Issue description
Complete the JSDoc for the exported `event` function with a summary and a descriptive `@returns` tag.

## Issue Context
PR Compliance 389257 requires every exported function to have a complete JSDoc block immediately before its declaration.

## Fix Focus Areas
- javascript/selenium-webdriver/bidi/domain.js[29-39]
- javascript/selenium-webdriver/bidi/domain.d.ts[23-23]

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


7. Domain callbacks lack JSDoc 📘 Rule violation ✧ Quality
Description
The exported Domain class adds public addCallback and removeCallback methods without
immediately preceding JSDoc blocks. Their parameters and non-void promise return values are
therefore undocumented.
Code

javascript/selenium-webdriver/bidi/domain.js[66]

+  async addCallback(descriptor, handler) {
Evidence
The checklist requires complete JSDoc for methods of exported classes. These public methods are
declared with no JSDoc blocks in either the implementation or public declaration surface.

Rule 389257: Document public API functions with complete JSDoc blocks
javascript/selenium-webdriver/bidi/domain.js[66-73]
javascript/selenium-webdriver/bidi/domain.d.ts[32-36]

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

## Issue description
Add complete JSDoc blocks for `Domain.addCallback` and `Domain.removeCallback`, including summaries, typed parameters, and described return values.

## Issue Context
`Domain` is exported through `module.exports`, and both methods are public in its TypeScript declaration.

## Fix Focus Areas
- javascript/selenium-webdriver/bidi/domain.js[66-73]
- javascript/selenium-webdriver/bidi/domain.d.ts[32-36]

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


8. defineEnum JSDoc incomplete 📘 Rule violation ✧ Quality
Description
The exported defineEnum function's JSDoc has no free-text description and omits documentation for
its non-void return value. Consumers are not told that the function returns the registered enum
entry.
Code

javascript/selenium-webdriver/bidi/serialization/enum.js[R20-24]

+/**
+ * @param {string} name Schema type name, e.g. 'network.InterceptPhase'.
+ * @param {string[]} values
+ */
+function defineEnum(name, values) {
Evidence
The block contains only two @param tags, while the implementation returns entry and the
declaration exposes EnumEntry<T>. This violates the required summary and return documentation
criteria.

Rule 389257: Document public API functions with complete JSDoc blocks
javascript/selenium-webdriver/bidi/serialization/enum.js[20-29]

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

## Issue description
Add a summary and a descriptive typed `@returns` tag to the `defineEnum` JSDoc block.

## Issue Context
The function is exported from the module and returns `entry`, so complete return documentation is required.

## Fix Focus Areas
- javascript/selenium-webdriver/bidi/serialization/enum.js[20-24]
- javascript/selenium-webdriver/bidi/serialization/enum.d.ts[23-23]

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


View medium (5)
9. defineRecord JSDoc incomplete 📘 Rule violation ✧ Quality
Description
The exported defineRecord function's JSDoc lacks a free-text description and a typed, described
@returns tag. The generated record class returned by this public factory is undocumented.
Code

javascript/selenium-webdriver/bidi/serialization/record.js[R142-147]

+/**
+ * @param {string} name Schema type name, e.g. 'network.AddInterceptParameters'.
+ * @param {Array<{name: string, wire: string, required: boolean, type: object}>} fields
+ * @param {{extensible?: boolean}} [options]
+ */
+function defineRecord(name, fields, options = {}) {
Evidence
The added JSDoc begins with parameter tags and has no return tag, although the implementation
returns Record and the declaration specifies RecordClass<T>.

Rule 389257: Document public API functions with complete JSDoc blocks
javascript/selenium-webdriver/bidi/serialization/record.js[142-147]
javascript/selenium-webdriver/bidi/serialization/record.js[242-245]

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

## Issue description
Add a concise summary and a typed, descriptive `@returns` tag to `defineRecord`'s JSDoc.

## Issue Context
`defineRecord` is exported and returns the generated `Record` class at the end of the function.

## Fix Focus Areas
- javascript/selenium-webdriver/bidi/serialization/record.js[142-147]
- javascript/selenium-webdriver/bidi/serialization/record.d.ts[56-56]

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


10. defineUnion JSDoc incomplete 📘 Rule violation ✧ Quality
Description
The exported defineUnion function's JSDoc lacks a free-text description and documentation for its
non-void return value. The returned union API is therefore not completely documented.
Code

javascript/selenium-webdriver/bidi/serialization/union.js[R42-47]

+/**
+ * @param {string} name Schema type name, e.g. 'session.ProxyConfiguration'.
+ * @param {object} selector The schema's `selector` node for this union.
+ * @param {{objectOnly?: boolean}} [options]
+ */
+function defineUnion(name, selector, options = {}) {
Evidence
The JSDoc contains only parameter tags despite the implementation returning union. It consequently
fails both the description and return documentation requirements.

Rule 389257: Document public API functions with complete JSDoc blocks
javascript/selenium-webdriver/bidi/serialization/union.js[42-47]
javascript/selenium-webdriver/bidi/serialization/union.js[83-85]

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

## Issue description
Add a concise summary and a typed, descriptive `@returns` tag to the `defineUnion` JSDoc block.

## Issue Context
The exported factory returns `union`, whose public declaration is `UnionClass<T>`.

## Fix Focus Areas
- javascript/selenium-webdriver/bidi/serialization/union.js[42-47]
- javascript/selenium-webdriver/bidi/serialization/union.d.ts[27-27]

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


11. defineAlias lacks tests 📘 Rule violation ▣ Testability
Description
The new exported defineAlias behavior is not exercised by any added or existing test under the
JavaScript test tree. A regression in alias registration or alias-based validation could therefore
pass unnoticed.
Code

javascript/selenium-webdriver/bidi/serialization/record.js[R254-256]

+function defineAlias(name, type) {
+  register(name, { kind: 'alias', type })
+}
Evidence
The checklist requires tests that import and exercise every new public function with assertions that
fail if the behavior is reverted. The PR exports defineAlias, while the added serialization tests
exercise records, enums, and unions but never call this function.

Rule 389273: Require tests for all new functionality and bug fixes
javascript/selenium-webdriver/bidi/serialization/record.js[247-258]
javascript/selenium-webdriver/bidi/serialization/record.d.ts[58-58]

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

## Issue description
Add automated tests that invoke `defineAlias` and assert that records containing references to the alias accept valid values and reject invalid values.

## Issue Context
`defineAlias` is newly exported from both the JavaScript module and its TypeScript declaration, but the test tree contains no invocation of it.

## Fix Focus Areas
- javascript/selenium-webdriver/bidi/serialization/record.js[247-258]
- javascript/selenium-webdriver/test/bidi/serialization/record_test.js[45-191]

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


12. Wire names serialize incorrectly 🐞 Bug ≡ Correctness
Description
The constructor reads each value using field.wire but stores it under field.name, and no
wire-key conversion occurs before the transport calls JSON.stringify(). Whenever name !== wire,
the command sends the JS-facing name instead of the protocol key.
Code

javascript/selenium-webdriver/bidi/serialization/record.js[R165-167]

+        const value = data[field.wire]
+        validateValue(field.type, value, `${name}.${field.wire}`, 'outbound')
+        this[field.name] = value
Evidence
The record stores an enumerable field.name property, Domain forwards it unchanged, and the
transport JSON-stringifies that object; the test fixture demonstrates that the API intentionally
permits different name and wire values.

javascript/selenium-webdriver/bidi/serialization/record.js[158-187]
javascript/selenium-webdriver/bidi/domain.js[58-63]
javascript/selenium-webdriver/bidi/index.js[217-227]
javascript/selenium-webdriver/test/bidi/serialization/wire_contract_test.js[100-114]

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

## Issue description
Outbound records expose JS property names directly to JSON serialization instead of mapping them back to their declared wire names.

## Issue Context
The wire contract test already defines a record where `name` and `wire` differ, but only checks inbound parsing. Add an explicit outbound representation method and cover this fixture through JSON serialization.

## Fix Focus Areas
- javascript/selenium-webdriver/bidi/serialization/record.js[147-188]
- javascript/selenium-webdriver/bidi/domain.js[58-63]
- javascript/selenium-webdriver/test/bidi/serialization/wire_contract_test.js[100-114]

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


13. Nonfinite numbers pass validation 🐞 Bug ≡ Correctness
Description
A number node accepts NaN and both infinities because validation only checks `typeof value ===
'number'. When the transport JSON-stringifies these values they become null`, silently sending a
value different from the validated record.
Code

javascript/selenium-webdriver/bidi/serialization/record.js[R34-42]

+  if (typeNode.primitive !== undefined) {
+    const expected = { string: 'string', integer: 'number', number: 'number', boolean: 'boolean' }[typeNode.primitive]
+    if (expected && typeof value !== expected) {
+      throw new ValidationError(`${path}: expected ${typeNode.primitive}, got ${typeof value}`)
+    }
+    // `number` admits any JSON number; `integer` rejects a fractional value
+    // (5.7) while still accepting one written 5.0 (Number.isInteger(5.0) is true).
+    if (typeNode.primitive === 'integer' && !Number.isInteger(value)) {
+      throw new ValidationError(`${path}: expected an integer, got ${value}`)
Evidence
The schema maps float/number types to the number primitive, but the validator accepts every
JavaScript value whose typeof is number; the transport subsequently serializes the value with
JSON.stringify.

javascript/selenium-webdriver/project_bidi_schema.mjs[89-107]
javascript/selenium-webdriver/bidi/serialization/record.js[34-44]
javascript/selenium-webdriver/bidi/index.js[217-220]

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

## Issue description
Primitive number validation accepts nonfinite JavaScript numbers that cannot be represented as BiDi JSON numbers.

## Issue Context
Require `Number.isFinite()` for numeric primitives in addition to the existing integer-specific check, and test both inbound and outbound paths.

## Fix Focus Areas
- javascript/selenium-webdriver/bidi/serialization/record.js[34-44]
- javascript/selenium-webdriver/test/bidi/serialization/record_test.js[127-146]

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


Grey Divider

Context
✅ Compliance rules (platform): 14 rules

Grey Divider

Tip of the day
💡 Did you know, you can keep summaries lean with Finding overflow, which tucks the rest behind 'View more'

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

Comment on lines +37 to +39
* @returns {{method: string, type: ({fromWire(payload: unknown): unknown}|undefined)}}
*/
function event(method, type) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remediation recommended

1. event jsdoc lacks description 📘 Rule violation ✧ Quality

The exported event function's JSDoc contains no free-text summary, and its @returns tag has no
description. This leaves the public API documentation incomplete.
Agent Prompt
## Issue description
Complete the JSDoc for the exported `event` function with a summary and a descriptive `@returns` tag.

## Issue Context
PR Compliance 389257 requires every exported function to have a complete JSDoc block immediately before its declaration.

## Fix Focus Areas
- javascript/selenium-webdriver/bidi/domain.js[29-39]
- javascript/selenium-webdriver/bidi/domain.d.ts[23-23]

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

return response?.result
}

async addCallback(descriptor, handler) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remediation recommended

2. domain callbacks lack jsdoc 📘 Rule violation ✧ Quality

The exported Domain class adds public addCallback and removeCallback methods without
immediately preceding JSDoc blocks. Their parameters and non-void promise return values are
therefore undocumented.
Agent Prompt
## Issue description
Add complete JSDoc blocks for `Domain.addCallback` and `Domain.removeCallback`, including summaries, typed parameters, and described return values.

## Issue Context
`Domain` is exported through `module.exports`, and both methods are public in its TypeScript declaration.

## Fix Focus Areas
- javascript/selenium-webdriver/bidi/domain.js[66-73]
- javascript/selenium-webdriver/bidi/domain.d.ts[32-36]

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

Comment on lines +20 to +24
/**
* @param {string} name Schema type name, e.g. 'network.InterceptPhase'.
* @param {string[]} values
*/
function defineEnum(name, values) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remediation recommended

3. defineenum jsdoc incomplete 📘 Rule violation ✧ Quality

The exported defineEnum function's JSDoc has no free-text description and omits documentation for
its non-void return value. Consumers are not told that the function returns the registered enum
entry.
Agent Prompt
## Issue description
Add a summary and a descriptive typed `@returns` tag to the `defineEnum` JSDoc block.

## Issue Context
The function is exported from the module and returns `entry`, so complete return documentation is required.

## Fix Focus Areas
- javascript/selenium-webdriver/bidi/serialization/enum.js[20-24]
- javascript/selenium-webdriver/bidi/serialization/enum.d.ts[23-23]

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

Comment on lines +142 to +147
/**
* @param {string} name Schema type name, e.g. 'network.AddInterceptParameters'.
* @param {Array<{name: string, wire: string, required: boolean, type: object}>} fields
* @param {{extensible?: boolean}} [options]
*/
function defineRecord(name, fields, options = {}) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remediation recommended

4. definerecord jsdoc incomplete 📘 Rule violation ✧ Quality

The exported defineRecord function's JSDoc lacks a free-text description and a typed, described
@returns tag. The generated record class returned by this public factory is undocumented.
Agent Prompt
## Issue description
Add a concise summary and a typed, descriptive `@returns` tag to `defineRecord`'s JSDoc.

## Issue Context
`defineRecord` is exported and returns the generated `Record` class at the end of the function.

## Fix Focus Areas
- javascript/selenium-webdriver/bidi/serialization/record.js[142-147]
- javascript/selenium-webdriver/bidi/serialization/record.d.ts[56-56]

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

Comment on lines +42 to +47
/**
* @param {string} name Schema type name, e.g. 'session.ProxyConfiguration'.
* @param {object} selector The schema's `selector` node for this union.
* @param {{objectOnly?: boolean}} [options]
*/
function defineUnion(name, selector, options = {}) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remediation recommended

5. defineunion jsdoc incomplete 📘 Rule violation ✧ Quality

The exported defineUnion function's JSDoc lacks a free-text description and documentation for its
non-void return value. The returned union API is therefore not completely documented.
Agent Prompt
## Issue description
Add a concise summary and a typed, descriptive `@returns` tag to the `defineUnion` JSDoc block.

## Issue Context
The exported factory returns `union`, whose public declaration is `UnionClass<T>`.

## Fix Focus Areas
- javascript/selenium-webdriver/bidi/serialization/union.js[42-47]
- javascript/selenium-webdriver/bidi/serialization/union.d.ts[27-27]

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

Comment on lines +128 to +140
if (typeNode.union !== undefined) {
const errors = []
for (const variant of typeNode.union) {
try {
validateValue(variant, value, path, direction)
return
} catch (err) {
errors.push(err.message)
}
}
throw new ValidationError(`${path}: value did not match any variant (${errors.join('; ')})`)
}
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

9. Inline records skip validation 🐞 Bug ≡ Correctness

The schema projector emits inline field types as {record: [...]}, but validateValue() has no
record branch and silently accepts them. Missing required members, invalid member types, and
undeclared members in inline records consequently pass both inbound and outbound validation.
Agent Prompt
## Issue description
Inline record TypeNodes emitted by the schema projector fall through `validateValue()` without any validation.

## Issue Context
Inline records contain projected `FieldSpec` entries and need the same directional required-field, extra-field, and nested-value handling as named records. Add the missing TypeScript representation as well.

## Fix Focus Areas
- javascript/selenium-webdriver/bidi/serialization/record.js[28-140]
- javascript/selenium-webdriver/bidi/serialization/record.d.ts[19-36]
- javascript/selenium-webdriver/project_bidi_schema.mjs[195-204]

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

Comment on lines +103 to +106
if (direction === 'inbound') {
referenced.RecordClass.fromWire(value)
} else {
new referenced.RecordClass(value)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

10. Nested parsing result discarded 🐞 Bug ≡ Correctness

Nested record and union references are parsed only for validation, after which fromWire() assigns
the original raw object to the parent. Nested fields therefore remain plain mutable objects and
retain undeclared properties that their nested fromWire() call had dropped.
Agent Prompt
## Issue description
Nested record and union parsing results are discarded, leaving raw wire objects in otherwise typed parent records.

## Issue Context
`validateValue()` currently returns no transformed value. Refactor validation/parsing so inbound nested refs return and assign the `fromWire()` result, while preserving outbound behavior.

## Fix Focus Areas
- javascript/selenium-webdriver/bidi/serialization/record.js[96-117]
- javascript/selenium-webdriver/bidi/serialization/record.js[203-214]

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

Comment on lines +165 to +168
const value = data[field.wire]
validateValue(field.type, value, `${name}.${field.wire}`, 'outbound')
this[field.name] = value
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

11. Validated collections remain mutable 🐞 Bug ☼ Reliability

Record construction stores caller-owned arrays and objects directly and only freezes the outer
instance. A caller can mutate a validated list or map afterward, including inserting schema-invalid
values that are then serialized to the wire.
Agent Prompt
## Issue description
Validated arrays, maps, and nested objects remain mutable after a record is frozen, allowing post-validation corruption.

## Issue Context
The outer `Object.freeze()` does not freeze or copy values assigned from input data. Store immutable validated copies or deeply freeze the supported value graph.

## Fix Focus Areas
- javascript/selenium-webdriver/bidi/serialization/record.js[65-80]
- javascript/selenium-webdriver/bidi/serialization/record.js[158-187]
- javascript/selenium-webdriver/bidi/serialization/record.js[203-237]

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

Comment on lines +165 to +167
const value = data[field.wire]
validateValue(field.type, value, `${name}.${field.wire}`, 'outbound')
this[field.name] = value

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remediation recommended

12. Wire names serialize incorrectly 🐞 Bug ≡ Correctness

The constructor reads each value using field.wire but stores it under field.name, and no
wire-key conversion occurs before the transport calls JSON.stringify(). Whenever name !== wire,
the command sends the JS-facing name instead of the protocol key.
Agent Prompt
## Issue description
Outbound records expose JS property names directly to JSON serialization instead of mapping them back to their declared wire names.

## Issue Context
The wire contract test already defines a record where `name` and `wire` differ, but only checks inbound parsing. Add an explicit outbound representation method and cover this fixture through JSON serialization.

## Fix Focus Areas
- javascript/selenium-webdriver/bidi/serialization/record.js[147-188]
- javascript/selenium-webdriver/bidi/domain.js[58-63]
- javascript/selenium-webdriver/test/bidi/serialization/wire_contract_test.js[100-114]

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

Comment on lines +34 to +42
if (typeNode.primitive !== undefined) {
const expected = { string: 'string', integer: 'number', number: 'number', boolean: 'boolean' }[typeNode.primitive]
if (expected && typeof value !== expected) {
throw new ValidationError(`${path}: expected ${typeNode.primitive}, got ${typeof value}`)
}
// `number` admits any JSON number; `integer` rejects a fractional value
// (5.7) while still accepting one written 5.0 (Number.isInteger(5.0) is true).
if (typeNode.primitive === 'integer' && !Number.isInteger(value)) {
throw new ValidationError(`${path}: expected an integer, got ${value}`)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remediation recommended

13. Nonfinite numbers pass validation 🐞 Bug ≡ Correctness

A number node accepts NaN and both infinities because validation only checks `typeof value ===
'number'. When the transport JSON-stringifies these values they become null`, silently sending a
value different from the validated record.
Agent Prompt
## Issue description
Primitive number validation accepts nonfinite JavaScript numbers that cannot be represented as BiDi JSON numbers.

## Issue Context
Require `Number.isFinite()` for numeric primitives in addition to the existing integer-specific check, and test both inbound and outbound paths.

## Fix Focus Areas
- javascript/selenium-webdriver/bidi/serialization/record.js[34-44]
- javascript/selenium-webdriver/test/bidi/serialization/record_test.js[127-146]

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

B-build Includes scripting, bazel and CI integrations B-devtools Includes everything BiDi or Chrome DevTools related C-nodejs JavaScript Bindings

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants