Class: BiDiGenerate::Schema Private
- Inherits:
-
Object
- Object
- BiDiGenerate::Schema
- Defined in:
- rb/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
-
#build_added_command(cmd, namespace, domain) ⇒ Object
private
The vendor variant already scopes the command, so its name drops the namespace (
moz:listExtensions→ list_extensions); a name that would silently override a spec command fails generation instead. - #build_vendor_command(cmd, type_name, entry, namespace) ⇒ Object private
-
#command_wrapper_refs(domain) ⇒ Object
private
The domain's command param/result wrapper type names — the classes a command constructs (
params) or parses its result into. - #commands_for(domain) ⇒ Object private
-
#domain_href(domain) ⇒ Object
private
The domain's
#module-<domain>spec link, or nil when the schema has none. -
#domain_relative_path(name) ⇒ Object
private
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.
-
#domains ⇒ Object
private
Domains that carry a command or event each become one generated module.
-
#enums_for(domain) ⇒ Object
private
Enum types declared under "
." become nested constant modules. -
#envelope_synthetic?(type) ⇒ Boolean
private
A synthetic record lifted out as an envelope's params (its owner is an envelope).
-
#error_codes ⇒ Object
private
The protocol-root ErrorCode enum's wire values (e.g. "no such frame"), in schema order.
- #events_for(domain) ⇒ Object private
-
#initialize(schema) ⇒ Schema
constructor
private
Vendor content (schema
vendor.<namespace>) is folded in beside the spec's: a vendor module's commands and events become a domain of their own, and its types resolve like spec types and are emitted in that module (see owned_types). -
#message_envelope?(type) ⇒ Boolean
private
A protocol message envelope is a record with a baked
methoddiscriminator ({method: <const>, params: …}) — the wire shape of a command/event message. -
#owned_types(domain) ⇒ Object
private
The types a domain's module declares.
-
#params_for(params_ref) ⇒ Object
private
Flat params for a command: the record's fields, or — for a union of records — the merged superset of variant fields.
-
#plainly_reached_types ⇒ Object
private
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.
-
#promote_command_params_records! ⇒ Object
private
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).
-
#promote_to_domain_type!(name) ⇒ Object
private
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.
-
#ruby_path_for(name) ⇒ Object
private
Public ruby-path resolver (
Owner::Labelfor a synthetic), matching how a variant's ref is emitted — so a caller can map a variant ref back to its emitted record. -
#structured_ref(name) ⇒ Object
private
The Protocol-relative class path a command result parses into, or nil when it is non-structured (or a bare list, returned raw).
-
#suppressed_record?(type) ⇒ Boolean
private
Records the generator deliberately does not emit: a message envelope, or a synthetic params record lifted out of one.
- #type_kind(ref) ⇒ Object private
- #type_prefixes(domain) ⇒ Object private
-
#types_for(domain) ⇒ Object
private
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. -
#vendor_added_commands(domain, namespace) ⇒ Object
private
The commands a vendor defines in a spec domain (
webExtension.moz:listExtensions). -
#vendor_domain?(domain) ⇒ Boolean
private
A vendor module's domain keeps its wire prefix (
moz:debugging); a spec domain has none. -
#vendor_events ⇒ Object
private
A vendor event in a spec domain would need the same vendor-variant routing as a command; none exists yet, so fail generation rather than leak it into the shared class.
- #vendor_messages(kind) ⇒ Object private
-
#vendor_modules_for(domain) ⇒ Object
private
The vendor modules a domain carries, one per namespace (
moz→ moduleMoz). -
#vendor_param(field, namespace, taken) ⇒ Object
private
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. -
#vendor_types_reached(domain) ⇒ Object
private
The vendor types a vendor-added command in this spec domain reaches through its params and result, so they are emitted in the domain's module beside the command that returns them.
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.
Vendor content (schema vendor.<namespace>) is folded in beside the spec's: a vendor
module's commands and events become a domain of their own, and its types resolve like
spec types and are emitted in that module (see owned_types).
581 582 583 584 585 586 587 588 589 |
# File 'rb/lib/selenium/webdriver/bidi/support/bidi_generate.rb', line 581 def initialize(schema) @vendor = schema['vendor'] || {} @vendor_types = @vendor.values.map { |section| section['types'] || {} }.reduce({}, :merge) @types = schema['types'].merge(@vendor_types) @commands = schema['commands'] + ('commands').select { |c| vendor_domain?(c['domain']) } @events = schema['events'] + vendor_events @domains = schema['domains'] || {} promote_command_params_records! end |
Instance Method Details
#build_added_command(cmd, namespace, 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 variant already scopes the command, so its name drops the namespace (moz:listExtensions
→ list_extensions); a name that would silently override a spec command fails generation instead.
707 708 709 710 711 712 713 714 715 716 717 |
# File 'rb/lib/selenium/webdriver/bidi/support/bidi_generate.rb', line 707 def build_added_command(cmd, namespace, domain) command = BiDiGenerate.build_command(self, cmd.merge('name' => cmd['name'].delete_prefix("#{namespace}:"))) spec_names = commands_for(domain).map do |c| BiDiGenerate.safe_method_name(BiDiGenerate.camel_to_snake(c['name'])) end if spec_names.include?(command.method_name) raise "vendor command #{cmd['method']} would override spec command #{domain}.#{command.method_name}" end command end |
#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.
719 720 721 722 723 724 725 726 727 728 729 730 731 |
# File 'rb/lib/selenium/webdriver/bidi/support/bidi_generate.rb', line 719 def build_vendor_command(cmd, type_name, entry, namespace) shared = record_params(@types[type_name]['fields'], extensible_record?(type_name)) 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.
661 662 663 |
# File 'rb/lib/selenium/webdriver/bidi/support/bidi_generate.rb', line 661 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.
653 654 655 |
# File 'rb/lib/selenium/webdriver/bidi/support/bidi_generate.rb', line 653 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.
617 618 619 |
# File 'rb/lib/selenium/webdriver/bidi/support/bidi_generate.rb', line 617 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.
679 680 681 682 |
# File 'rb/lib/selenium/webdriver/bidi/support/bidi_generate.rb', line 679 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 |
#domains ⇒ 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.
Domains that carry a command or event each become one generated module.
649 650 651 |
# File 'rb/lib/selenium/webdriver/bidi/support/bidi_generate.rb', line 649 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 "
775 776 777 778 779 780 781 782 783 |
# File 'rb/lib/selenium/webdriver/bidi/support/bidi_generate.rb', line 775 def enums_for(domain) owned_types(domain).filter_map do |name, type| next unless type['kind'] == 'enum' pairs = type['values'].map { |v| [BiDiGenerate.enum_key(v), v] } Enum.new(constant_name: BiDiGenerate.screaming_snake(name.split('.', 2).last), 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).
860 861 862 863 864 865 |
# File 'rb/lib/selenium/webdriver/bidi/support/bidi_generate.rb', line 860 def envelope_synthetic?(type) return false unless type['synthetic'] owner = @types[type['owner']] owner && owner['kind'] == 'record' && (owner) end |
#error_codes ⇒ 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-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.
826 827 828 |
# File 'rb/lib/selenium/webdriver/bidi/support/bidi_generate.rb', line 826 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.
754 755 756 |
# File 'rb/lib/selenium/webdriver/bidi/support/bidi_generate.rb', line 754 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.
855 856 857 |
# File 'rb/lib/selenium/webdriver/bidi/support/bidi_generate.rb', line 855 def (type) type['fields'].any? { |f| f['wire'] == 'method' && f['type'].key?('const') } end |
#owned_types(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 types a domain's module declares. A spec domain's are the "moz:debugging) owns the vendor types its commands
and events name (Mozilla prefixes them mozDebugging.), read off their params and result refs.
789 790 791 792 793 794 795 796 797 798 |
# File 'rb/lib/selenium/webdriver/bidi/support/bidi_generate.rb', line 789 def owned_types(domain) vendor = vendor_domain?(domain) prefixes = type_prefixes(domain).map { |prefix| "#{prefix}." } added = vendor ? Set.new : vendor_types_reached(domain) @types.select do |name, _| next false unless prefixes.any? { |p| name.start_with?(p) } @vendor_types.key?(name) ? vendor || added.include?(name) : !vendor end 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.
762 763 764 765 766 767 768 769 770 771 772 |
# File 'rb/lib/selenium/webdriver/bidi/support/bidi_generate.rb', line 762 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'], extensible_record?(params_ref['ref'])) when 'union' then union_params(type, params_ref['ref']) end end |
#plainly_reached_types ⇒ 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.
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.
670 671 672 673 674 |
# File 'rb/lib/selenium/webdriver/bidi/support/bidi_generate.rb', line 670 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.
629 630 631 632 633 634 635 636 637 |
# File 'rb/lib/selenium/webdriver/bidi/support/bidi_generate.rb', line 629 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.
641 642 643 644 645 646 |
# File 'rb/lib/selenium/webdriver/bidi/support/bidi_generate.rb', line 641 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.
876 |
# File 'rb/lib/selenium/webdriver/bidi/support/bidi_generate.rb', line 876 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).
869 870 871 872 |
# File 'rb/lib/selenium/webdriver/bidi/support/bidi_generate.rb', line 869 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.
848 849 850 |
# File 'rb/lib/selenium/webdriver/bidi/support/bidi_generate.rb', line 848 def suppressed_record?(type) (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.
750 751 752 |
# File 'rb/lib/selenium/webdriver/bidi/support/bidi_generate.rb', line 750 def type_kind(ref) @types[ref]&.fetch('kind', nil) end |
#type_prefixes(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.
816 817 818 819 820 821 822 |
# File 'rb/lib/selenium/webdriver/bidi/support/bidi_generate.rb', line 816 def type_prefixes(domain) return [domain] unless vendor_domain?(domain) = commands_for(domain) + events_for(domain) refs = .flat_map { |m| [m.dig('params', 'ref'), m.dig('result', 'ref')] } refs.compact.select { |ref| ref.include?('.') }.map { |ref| ref.split('.', 2).first }.uniq 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
"{method, params} wire wrapper) are
skipped — Transport forms that envelope, so nothing references them.
835 836 837 838 839 840 841 842 843 |
# File 'rb/lib/selenium/webdriver/bidi/support/bidi_generate.rb', line 835 def types_for(domain) owned_types(domain).filter_map do |name, type| 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_added_commands(domain, 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.
The commands a vendor defines in a spec domain (webExtension.moz:listExtensions). They are
emitted on that domain's vendor variant, never on the shared class (see vendor_modules_for).
610 611 612 613 614 |
# File 'rb/lib/selenium/webdriver/bidi/support/bidi_generate.rb', line 610 def vendor_added_commands(domain, namespace) return [] if vendor_domain?(domain) (@vendor.dig(namespace, 'commands') || []).select { |c| c['domain'] == domain } end |
#vendor_domain?(domain) ⇒ 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 vendor module's domain keeps its wire prefix (moz:debugging); a spec domain has none.
592 |
# File 'rb/lib/selenium/webdriver/bidi/support/bidi_generate.rb', line 592 def vendor_domain?(domain) = domain.include?(':') |
#vendor_events ⇒ 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 event in a spec domain would need the same vendor-variant routing as a command; none exists yet, so fail generation rather than leak it into the shared class.
600 601 602 603 604 605 606 |
# File 'rb/lib/selenium/webdriver/bidi/support/bidi_generate.rb', line 600 def vendor_events events = ('events') stray = events.reject { |e| vendor_domain?(e['domain']) } raise "vendor event #{stray.first['method']} in spec domain #{stray.first['domain']} is unsupported" if stray.any? events end |
#vendor_messages(kind) ⇒ 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.
594 595 596 |
# File 'rb/lib/selenium/webdriver/bidi/support/bidi_generate.rb', line 594 def (kind) @vendor.values.flat_map { |section| section[kind] || [] } 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.
689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 |
# File 'rb/lib/selenium/webdriver/bidi/support/bidi_generate.rb', line 689 def vendor_modules_for(domain) parent = BiDiGenerate.snake_to_class_name(BiDiGenerate.camel_to_snake(domain)) @vendor.filter_map do |namespace, spec| overrides = (spec['extends'] || {}).filter_map do |type_name, entry| cmd = @commands.find { |c| c.dig('params', 'ref') == type_name } build_vendor_command(cmd, type_name, entry, namespace) if cmd && cmd['domain'] == domain end added = vendor_added_commands(domain, namespace).map { |cmd| build_added_command(cmd, namespace, domain) } commands = overrides + added next if commands.empty? 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.
737 738 739 740 741 742 743 744 745 746 747 748 |
# File 'rb/lib/selenium/webdriver/bidi/support/bidi_generate.rb', line 737 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 |
#vendor_types_reached(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 types a vendor-added command in this spec domain reaches through its params and result, so they are emitted in the domain's module beside the command that returns them.
802 803 804 805 806 807 808 809 810 811 812 813 814 |
# File 'rb/lib/selenium/webdriver/bidi/support/bidi_generate.rb', line 802 def vendor_types_reached(domain) commands = @vendor.keys.flat_map { |namespace| vendor_added_commands(domain, namespace) } pending = commands.flat_map { |c| [c.dig('params', 'ref'), c.dig('result', 'ref')] }.compact reached = Set.new until pending.empty? name = pending.pop next if reached.include?(name) || !@vendor_types.key?(name) reached << name pending.concat(plain_refs(@types[name]) + (@types[name]['variants'] || [])) end reached end |