Class: BiDiGenerate::Schema Private

Inherits:
Object
  • Object
show all
Defined in:
lib/selenium/webdriver/bidi/support/bidi_generate.rb

This class is part of a private API. You should avoid using this class if possible, as it may be removed or be changed in the future.

Instance Method Summary collapse

Constructor Details

#initialize(schema) ⇒ Schema

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns a new instance of Schema.



546
547
548
549
550
551
552
553
# File 'lib/selenium/webdriver/bidi/support/bidi_generate.rb', line 546

def initialize(schema)
  @types = schema['types']
  @commands = schema['commands']
  @events = schema['events']
  @domains = schema['domains'] || {}
  @vendor = schema['vendor'] || {}
  promote_command_params_records!
end

Instance Method Details

#build_vendor_command(cmd, type_name, entry, namespace) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



645
646
647
648
649
650
651
652
653
654
655
656
657
# File 'lib/selenium/webdriver/bidi/support/bidi_generate.rb', line 645

def build_vendor_command(cmd, type_name, entry, namespace)
  shared = record_params(@types[type_name]['fields'])
  taken = shared.map(&:ruby_name)
  VendorCommand.new(
    method_name: BiDiGenerate.safe_method_name(BiDiGenerate.camel_to_snake(cmd['name'])),
    wire_name: cmd['method'],
    result_ref: cmd['result'] && structured_ref(cmd['result']['ref']),
    params_class: BiDiGenerate.type_class_name(type_name),
    shared_params: shared,
    vendor_params: entry['fields'].map { |field| vendor_param(field, namespace, taken) },
    spec_href: cmd['specHref']
  )
end

#command_wrapper_refs(domain) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

The domain's command param/result wrapper type names — the classes a command constructs (params) or parses its result into. They are reachable (so tagged outbound/inbound) but are the message wrappers a command method already builds, not data a caller composes, so they are excluded from the type accessors.



600
601
602
# File 'lib/selenium/webdriver/bidi/support/bidi_generate.rb', line 600

def command_wrapper_refs(domain)
  commands_for(domain).flat_map { |c| [c.dig('params', 'ref'), c.dig('result', 'ref')] }.compact.to_set
end

#commands_for(domain) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



592
593
594
# File 'lib/selenium/webdriver/bidi/support/bidi_generate.rb', line 592

def commands_for(domain)
  @commands.select { |c| c['domain'] == domain }
end

#domain_href(domain) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

The domain's #module-<domain> spec link, or nil when the schema has none.



556
557
558
# File 'lib/selenium/webdriver/bidi/support/bidi_generate.rb', line 556

def domain_href(domain)
  @domains.dig(domain, 'specHref')
end

#domain_relative_path(name) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

The class path to a type relative to its domain class (an accessor body resolves in the Domain subclass scope): "ExtensionData", or "AccessibilityLocator::Value" for a synthetic nested under its owner.



618
619
620
621
# File 'lib/selenium/webdriver/bidi/support/bidi_generate.rb', line 618

def domain_relative_path(name)
  prefix = "#{BiDiGenerate.snake_to_class_name(BiDiGenerate.camel_to_snake(name.split('.', 2).first))}::"
  ruby_path(name).sub(/\A#{Regexp.escape(prefix)}/, '')
end

#domainsObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Domains that carry a command or event each become one generated module.



588
589
590
# File 'lib/selenium/webdriver/bidi/support/bidi_generate.rb', line 588

def domains
  (@commands + @events).map { |entry| entry['domain'] }.uniq
end

#enums_for(domain) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Enum types declared under "." become nested constant modules.



701
702
703
704
705
706
707
708
709
710
# File 'lib/selenium/webdriver/bidi/support/bidi_generate.rb', line 701

def enums_for(domain)
  @types.filter_map do |name, type|
    next unless type['kind'] == 'enum'
    next unless name.start_with?("#{domain}.")

    pairs = type['values'].map { |v| [BiDiGenerate.enum_key(v), v] }
    Enum.new(constant_name: BiDiGenerate.screaming_snake(name.sub("#{domain}.", '')), pairs: pairs,
             primitive: type['primitive'], spec_href: type['specHref'])
  end
end

#envelope_synthetic?(type) ⇒ Boolean

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

A synthetic record lifted out as an envelope's params (its owner is an envelope).

Returns:

  • (Boolean)


751
752
753
754
755
756
# File 'lib/selenium/webdriver/bidi/support/bidi_generate.rb', line 751

def envelope_synthetic?(type)
  return false unless type['synthetic']

  owner = @types[type['owner']]
  owner && owner['kind'] == 'record' && message_envelope?(owner)
end

#error_codesObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

The protocol-root ErrorCode enum's wire values (e.g. "no such frame"), in schema order. Used to generate the BiDi-specific Error subclasses. [] when the schema has no ErrorCode.



714
715
716
# File 'lib/selenium/webdriver/bidi/support/bidi_generate.rb', line 714

def error_codes
  @types.dig('ErrorCode', 'values') || []
end

#events_for(domain) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



680
681
682
# File 'lib/selenium/webdriver/bidi/support/bidi_generate.rb', line 680

def events_for(domain)
  @events.select { |e| e['domain'] == domain }
end

#message_envelope?(type) ⇒ Boolean

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

A protocol message envelope is a record with a baked method discriminator ({method: <const>, params: …}) — the wire shape of a command/event message. No value type carries a const method field, so this is unambiguous.

Returns:

  • (Boolean)


746
747
748
# File 'lib/selenium/webdriver/bidi/support/bidi_generate.rb', line 746

def message_envelope?(type)
  type['fields'].any? { |f| f['wire'] == 'method' && f['type'].key?('const') }
end

#params_for(params_ref) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Flat params for a command: the record's fields, or — for a union of records — the merged superset of variant fields. Returns [] for commands with no params, or nil when params can't be flattened (alias, or a union whose variants aren't all records) so the caller forwards verbatim.



688
689
690
691
692
693
694
695
696
697
698
# File 'lib/selenium/webdriver/bidi/support/bidi_generate.rb', line 688

def params_for(params_ref)
  return [] unless params_ref

  type = @types[params_ref['ref']]
  return nil unless type

  case type['kind']
  when 'record' then record_params(type['fields'])
  when 'union' then union_params(type, params_ref['ref'])
  end
end

#plainly_reached_typesObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Type names reached by at least one non-union-arm reference: used as a record field, list element, map value, or alias target somewhere — not solely as a named union's variant. A type reached only as a union arm is built through its union (a variant factory or the command's flattened dispatch), so a nested one needs no accessor; one reached as a plain field ref (browsingContext.AccessibilityLocator's value) does.



609
610
611
612
613
# File 'lib/selenium/webdriver/bidi/support/bidi_generate.rb', line 609

def plainly_reached_types
  @plainly_reached_types ||= @types.each_value.with_object(Set.new) do |node, reached|
    plain_refs(node).each { |ref| reached << ref }
  end
end

#promote_command_params_records!Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

A command written in CDDL map form carries its params as an inline object (rather than the usual group form referencing a named params type). The projector links the command to those params, but hoists them into a synthetic record owned by the command's message envelope. That envelope is suppressed (Transport forms it), so the synthetic params record would never be emitted even though the command's params ref points straight at it. Promote it to a top-level domain record so the generator emits and references it like any other params type. Today this is exactly userAgentClientHints.setClientHintsOverride.



568
569
570
571
572
573
574
575
576
# File 'lib/selenium/webdriver/bidi/support/bidi_generate.rb', line 568

def promote_command_params_records!
  @commands.each do |cmd|
    ref = cmd.dig('params', 'ref')
    next unless ref

    type = @types[ref]
    promote_to_domain_type!(ref) if type && envelope_synthetic?(type)
  end
end

#promote_to_domain_type!(name) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Strip the synthetic/owner/label tags so a lifted-out type emits as a top-level domain record instead of nesting under its (suppressed) envelope.



580
581
582
583
584
585
# File 'lib/selenium/webdriver/bidi/support/bidi_generate.rb', line 580

def promote_to_domain_type!(name)
  type = @types[name]
  type&.delete('synthetic')
  type&.delete('owner')
  type&.delete('label')
end

#ruby_path_for(name) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Public ruby-path resolver (Owner::Label for a synthetic), matching how a variant's ref is emitted — so a caller can map a variant ref back to its emitted record.



767
# File 'lib/selenium/webdriver/bidi/support/bidi_generate.rb', line 767

def ruby_path_for(name) = ruby_path(name)

#structured_ref(name) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

The Protocol-relative class path a command result parses into, or nil when it is non-structured (or a bare list, returned raw).



760
761
762
763
# File 'lib/selenium/webdriver/bidi/support/bidi_generate.rb', line 760

def structured_ref(name)
  resolved = resolve_named(name)
  resolved[:list] ? nil : resolved[:ref]
end

#suppressed_record?(type) ⇒ Boolean

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Records the generator deliberately does not emit: a message envelope, or a synthetic params record lifted out of one. Both are reachable only through the envelope, which Transport replaces — so nothing else references them.

Returns:

  • (Boolean)


739
740
741
# File 'lib/selenium/webdriver/bidi/support/bidi_generate.rb', line 739

def suppressed_record?(type)
  message_envelope?(type) || envelope_synthetic?(type)
end

#type_kind(ref) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



676
677
678
# File 'lib/selenium/webdriver/bidi/support/bidi_generate.rb', line 676

def type_kind(ref)
  @types[ref]&.fetch('kind', nil)
end

#types_for(domain) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Structured value classes (records + discriminated unions) declared under "." Empty records are projector artifacts with nothing to carry, so they stay opaque hashes; only non-empty records and unions become classes. Command/event message envelopes (the {method, params} wire wrapper) are skipped — Transport forms that envelope, so nothing references them.



723
724
725
726
727
728
729
730
731
732
733
734
# File 'lib/selenium/webdriver/bidi/support/bidi_generate.rb', line 723

def types_for(domain)
  prefix = "#{domain}."
  @types.filter_map do |name, type|
    next unless name.start_with?(prefix)

    case type['kind']
    when 'record' then record_class(name, type) unless type['fields'].empty? || suppressed_record?(type)
    when 'union' then union_class(name)
    when 'alias' then union_class(name) if type['type'].key?('union')
    end
  end
end

#vendor_modules_for(domain) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

The vendor modules a domain carries, one per namespace (moz → module Moz). The schema's vendor section names, per namespace, which shared type each vendor extends; we map that type back to the command that sends it, so the vendor method mirrors the base command's wire method and result while adding the typed vendor fields. Empty for any domain (or schema) with no vendor extensions, so non-vendor output is unaffected.



628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
# File 'lib/selenium/webdriver/bidi/support/bidi_generate.rb', line 628

def vendor_modules_for(domain)
  parent = BiDiGenerate.snake_to_class_name(BiDiGenerate.camel_to_snake(domain))
  groups = Hash.new { |h, k| h[k] = [] }
  @vendor.each do |namespace, spec|
    (spec['extends'] || {}).each do |type_name, entry|
      cmd = @commands.find { |c| c.dig('params', 'ref') == type_name }
      next unless cmd && cmd['domain'] == domain

      groups[namespace] << build_vendor_command(cmd, type_name, entry, namespace)
    end
  end
  groups.map do |namespace, commands|
    VendorModule.new(name: BiDiGenerate.snake_to_class_name(namespace), namespace: namespace, parent: parent,
                     commands: commands)
  end
end

#vendor_param(field, namespace, taken) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

A vendor field's ruby name drops its namespace prefix (moz:permanent → permanent): the module already scopes it, so re-encoding the namespace in every identifier is redundant. The wire key is untouched. Falls back to the prefixed name only if stripping would collide with a shared param on the same command.



663
664
665
666
667
668
669
670
671
672
673
674
# File 'lib/selenium/webdriver/bidi/support/bidi_generate.rb', line 663

def vendor_param(field, namespace, taken)
  stripped = field['name'].sub(/\A#{Regexp.escape(namespace)}:/, '')
  ruby_name = BiDiGenerate.safe_field_name(BiDiGenerate.camel_to_snake(stripped))
  ruby_name = BiDiGenerate.safe_field_name(BiDiGenerate.camel_to_snake(field['name'])) if taken.include?(ruby_name)
  Param.new(
    ruby_name: ruby_name,
    wire_name: field['wire'],
    required: field['required'],
    enum: enum_const(field['type']),
    rbs: rbs_type(field['type'])
  )
end