Class: Puppeteer::Bidi::Connection

Inherits:
Object
  • Object
show all
Defined in:
lib/puppeteer/bidi/connection.rb,
sig/puppeteer/bidi/connection.rbs

Overview

Connection manages BiDi protocol communication Handles command sending, response waiting, and event dispatching

Defined Under Namespace

Classes: ProtocolError, TimeoutError

Constant Summary collapse

DEFAULT_TIMEOUT =

: Integer -- 30 seconds in milliseconds

Returns:

  • (Integer)
30_000

Instance Method Summary collapse

Constructor Details

#initialize(transport) ⇒ Connection

Returns a new instance of Connection.

Parameters:



19
20
21
22
23
24
25
26
27
# File 'lib/puppeteer/bidi/connection.rb', line 19

def initialize(transport)
  @transport = transport
  @next_id = 1
  @pending_commands = {} #: Hash[Integer, Hash[Symbol, untyped]]
  @event_listeners = {} #: Hash[String, Array[^(untyped) -> void]]
  @closed = false

  setup_transport_handlers
end

Instance Method Details

#async_send_command(method, params = {}, timeout: DEFAULT_TIMEOUT) ⇒ Async::Task[Hash[String, untyped]]

Send a BiDi command and wait for response

Parameters:

  • method (String)
  • params (Hash[String | Symbol, untyped]) (defaults to: {})
  • timeout: (Integer) (defaults to: DEFAULT_TIMEOUT)

Returns:



34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/puppeteer/bidi/connection.rb', line 34

def async_send_command(method, params = {}, timeout: DEFAULT_TIMEOUT)
  raise ProtocolError, 'Connection is closed' if @closed

  id = next_id
  command = {
    id: id,
    method: method,
    params: params
  }

  # Create promise for this command
  promise = Async::Promise.new

  @pending_commands[id] = {
    promise: promise,
    method: method,
    sent_at: Time.now
  }

  # Debug output
  if ENV['DEBUG_BIDI_COMMAND']
    puts "[BiDi] Request #{method}: #{command.inspect}"
  end

  Async do
    # Send command through transport
    @transport.async_send_message(command).wait

    # Wait for response with timeout
    begin
      result = AsyncUtils.async_timeout(timeout, promise).wait

      # Debug output
      if ENV['DEBUG_BIDI_COMMAND']
        puts "[BiDi] Response for #{method}: #{result.inspect}"
      end

      unless result.is_a?(Hash) && result.key?('type')
        raise ProtocolError, "Protocol Error. Message is not in BiDi protocol format: #{result.inspect}"
      end

      case result['type']
      when 'success'
        result['result']
      when 'error'
        # BiDi error format: { "type": "error", "error": "...", "message": "...", ... }
        error_type = result['error'] || 'unknown error'
        error_message = result['message'] || error_type
        raise ProtocolError, "BiDi error (#{method}): #{error_message}"
      else
        raise ProtocolError, "Protocol Error. Unexpected BiDi message type: #{result['type'].inspect}"
      end
    rescue Async::TimeoutError
      @pending_commands.delete(id)
      raise TimeoutError, "Timeout waiting for #{method} (#{timeout}ms)"
    end
  end
end

#closevoid

This method returns an undefined value.

Close the connection



118
119
120
121
122
123
124
125
126
127
128
129
130
# File 'lib/puppeteer/bidi/connection.rb', line 118

def close
  return if @closed

  @closed = true

  # Reject all pending commands
  @pending_commands.each_value do |pending|
    pending[:promise].reject(ProtocolError.new('Connection closed'))
  end
  @pending_commands.clear

  @transport.close
end

#closed?Boolean

Returns:

  • (Boolean)


133
134
135
# File 'lib/puppeteer/bidi/connection.rb', line 133

def closed?
  @closed
end

#handle_event(message) ⇒ void

This method returns an undefined value.

Parameters:

  • message (Hash[String, untyped])


188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
# File 'lib/puppeteer/bidi/connection.rb', line 188

def handle_event(message)
  method = message['method']
  params = message['params'] || {}

  if ENV['DEBUG_BIDI_COMMAND']
    puts "[BiDi] Event #{method}: #{params.inspect}"
  end

  listeners = @event_listeners[method]
  return unless listeners

  # Call all registered listeners for this event
  listeners.each do |listener|
    begin
      listener.call(params)
    rescue => e
      warn "Error in event listener for #{method}: #{e.message}"
    end
  end
end

#handle_message(message) ⇒ void

This method returns an undefined value.

Parameters:

  • message (Hash[String, untyped])


159
160
161
162
163
164
165
166
167
168
169
# File 'lib/puppeteer/bidi/connection.rb', line 159

def handle_message(message)
  # Response to a command (has 'id' field)
  if message['id']
    handle_response(message)
  # Event (has 'method' but no 'id')
  elsif message['method']
    handle_event(message)
  else
    warn "Unknown BiDi message format: #{message}"
  end
end

#handle_response(message) ⇒ void

This method returns an undefined value.

Parameters:

  • message (Hash[String, untyped])


173
174
175
176
177
178
179
180
181
182
183
184
# File 'lib/puppeteer/bidi/connection.rb', line 173

def handle_response(message)
  id = message['id']
  pending = @pending_commands.delete(id)

  unless pending
    warn "Received response for unknown command id: #{id}"
    return
  end

  # Resolve the promise with the response
  pending[:promise].resolve(message)
end

#next_idInteger

Returns:

  • (Integer)


140
141
142
143
144
# File 'lib/puppeteer/bidi/connection.rb', line 140

def next_id
  id = @next_id
  @next_id += 1
  id
end

#off(event, &block) ⇒ void

This method returns an undefined value.

Unsubscribe from BiDi events

Parameters:

  • event (String)


106
107
108
109
110
111
112
113
114
# File 'lib/puppeteer/bidi/connection.rb', line 106

def off(event, &block)
  return unless @event_listeners[event]

  if block
    @event_listeners[event].delete(block)
  else
    @event_listeners.delete(event)
  end
end

#on(event) {|arg0| ... } ⇒ void

This method returns an undefined value.

Subscribe to BiDi events

Parameters:

  • event (String)

Yields:

Yield Parameters:

  • arg0 (Object)

Yield Returns:

  • (void)


97
98
99
100
# File 'lib/puppeteer/bidi/connection.rb', line 97

def on(event, &block)
  @event_listeners[event] ||= []
  @event_listeners[event] << block
end

#setup_transport_handlersvoid

This method returns an undefined value.



147
148
149
150
151
152
153
154
155
# File 'lib/puppeteer/bidi/connection.rb', line 147

def setup_transport_handlers
  @transport.on_message do |message|
    handle_message(message)
  end

  @transport.on_close do
    close
  end
end