class Playwright::Connection

def async_send_message_to_server(guid, method, params, metadata: nil)

def async_send_message_to_server(guid, method, params, metadata: nil)
  return if @closed_error
  callback = Concurrent::Promises.resolvable_future
  with_generated_id do |id|
    # register callback promise object first.
    # @see https://github.com/YusukeIwaki/puppeteer-ruby/pull/34
    @callbacks[id] = callback
    _metadata = {}
    frames = []
    if metadata
      frames = metadata[:stack]
      _metadata[:wallTime] = metadata[:wallTime]
      _metadata[:apiName] = metadata[:apiName]
      _metadata[:location] = metadata[:stack].first
      _metadata[:internal] = !metadata[:apiName]
    end
    _metadata.compact!
    message = {
      id: id,
      guid: guid,
      method: method,
      params: replace_channels_with_guids(params),
      metadata: _metadata,
    }
    begin
      @transport.send_message(message)
    rescue => err
      @callbacks.delete(id)
      callback.reject(err)
      raise unless err.is_a?(Transport::AlreadyDisconnectedError)
    end
    if @tracing_count > 0 && !frames.empty? && guid != 'localUtils'
      @local_utils.add_stack_to_tracing_no_reply(id, frames)
    end
  end
  callback
end