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.



537
538
539
540
541
542
543
544
# File 'lib/selenium/webdriver/bidi/support/bidi_generate.rb', line 537

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.



636
637
638
639
640
641
642
643
644
645
646
647
648
# File 'lib/selenium/webdriver/bidi/support/bidi_generate.rb', line 636

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.



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

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.



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

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.



547
548
549
# File 'lib/selenium/webdriver/bidi/support/bidi_generate.rb', line 547

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.



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

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.



579
580
581
# File 'lib/selenium/webdriver/bidi/support/bidi_generate.rb', line 579

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.



692
693
694
695
696
697
698
699
700
701
# File 'lib/selenium/webdriver/bidi/support/bidi_generate.rb', line 692

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.to_s] }
    Enum.new(constant_name: BiDiGenerate.screaming_snake(name.sub("#{domain}.", '')), pairs: pairs,
             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)


742
743
744
745
746
747
# File 'lib/selenium/webdriver/bidi/support/bidi_generate.rb', line 742

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.



705
706
707
# File 'lib/selenium/webdriver/bidi/support/bidi_generate.rb', line 705

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.



671
672
673
# File 'lib/selenium/webdriver/bidi/support/bidi_generate.rb', line 671

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)


737
738
739
# File 'lib/selenium/webdriver/bidi/support/bidi_generate.rb', line 737

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.



679
680
681
682
683
684
685
686
687
688
689
# File 'lib/selenium/webdriver/bidi/support/bidi_generate.rb', line 679

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.



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

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.



559
560
561
562
563
564
565
566
567
# File 'lib/selenium/webdriver/bidi/support/bidi_generate.rb', line 559

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.



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

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.



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

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).



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

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)


730
731
732
# File 'lib/selenium/webdriver/bidi/support/bidi_generate.rb', line 730

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.



667
668
669
# File 'lib/selenium/webdriver/bidi/support/bidi_generate.rb', line 667

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.



714
715
716
717
718
719
720
721
722
723
724
725
# File 'lib/selenium/webdriver/bidi/support/bidi_generate.rb', line 714

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.



619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
# File 'lib/selenium/webdriver/bidi/support/bidi_generate.rb', line 619

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.



654
655
656
657
658
659
660
661
662
663
664
665
# File 'lib/selenium/webdriver/bidi/support/bidi_generate.rb', line 654

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