puppeteer-ruby 0.37.2 → 0.39.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -50,19 +50,26 @@ class Puppeteer::Page
50
50
  @workers = {}
51
51
  @user_drag_interception_enabled = false
52
52
 
53
- @client.on_event('Target.attachedToTarget') do |event|
54
- if event['targetInfo']['type'] != 'worker'
53
+ @client.add_event_listener('Target.attachedToTarget') do |event|
54
+ if event['targetInfo']['type'] != 'worker' && event['targetInfo']['type'] != 'iframe'
55
55
  # If we don't detach from service workers, they will never die.
56
+ # We still want to attach to workers for emitting events.
57
+ # We still want to attach to iframes so sessions may interact with them.
58
+ # We detach from all other types out of an abundance of caution.
59
+ # See https://source.chromium.org/chromium/chromium/src/+/main:content/browser/devtools/devtools_agent_host_impl.cc?ss=chromium&q=f:devtools%20-f:out%20%22::kTypePage%5B%5D%22
60
+ # for the complete list of available types.
56
61
  @client.async_send_message('Target.detachFromTarget', sessionId: event['sessionId'])
57
62
  next
58
63
  end
59
64
 
60
- session = Puppeteer::Connection.from_session(@client).session(event['sessionId']) # rubocop:disable Lint/UselessAssignment
61
- # const worker = new Worker(session, event.targetInfo.url, this._addConsoleMessage.bind(this), this._handleException.bind(this));
62
- # this._workers.set(event.sessionId, worker);
63
- # this.emit(PageEmittedEvents::WorkerCreated, worker);
65
+ if event['targetInfo']['type'] == 'worker'
66
+ session = Puppeteer::Connection.from_session(@client).session(event['sessionId']) # rubocop:disable Lint/UselessAssignment
67
+ # const worker = new Worker(session, event.targetInfo.url, this._addConsoleMessage.bind(this), this._handleException.bind(this));
68
+ # this._workers.set(event.sessionId, worker);
69
+ # this.emit(PageEmittedEvents::WorkerCreated, worker);
70
+ end
64
71
  end
65
- @client.on_event('Target.detachedFromTarget') do |event|
72
+ @client.add_event_listener('Target.detachedFromTarget') do |event|
66
73
  session_id = event['sessionId']
67
74
  worker = @workers[session_id]
68
75
  next unless worker
@@ -103,10 +110,10 @@ class Puppeteer::Page
103
110
  @client.on_event('Page.loadEventFired') do |event|
104
111
  emit_event(PageEmittedEvents::Load)
105
112
  end
106
- @client.on('Runtime.consoleAPICalled') do |event|
113
+ @client.add_event_listener('Runtime.consoleAPICalled') do |event|
107
114
  handle_console_api(event)
108
115
  end
109
- @client.on('Runtime.bindingCalled') do |event|
116
+ @client.add_event_listener('Runtime.bindingCalled') do |event|
110
117
  handle_binding_called(event)
111
118
  end
112
119
  @client.on_event('Page.javascriptDialogOpening') do |event|
@@ -518,7 +525,7 @@ class Puppeteer::Page
518
525
  return
519
526
  end
520
527
 
521
- context = @frame_manager.execution_context_by_id(event['executionContextId'])
528
+ context = @frame_manager.execution_context_by_id(event['executionContextId'], @client)
522
529
  values = event['args'].map do |arg|
523
530
  remote_object = Puppeteer::RemoteObject.new(arg)
524
531
  Puppeteer::JSHandle.create(context: context, remote_object: remote_object)
@@ -664,19 +671,38 @@ class Puppeteer::Page
664
671
  private def wait_for_network_manager_event(event_name, predicate:, timeout:)
665
672
  option_timeout = timeout || @timeout_settings.timeout
666
673
 
667
- @wait_for_network_manager_event_listener_ids ||= {}
668
- if_present(@wait_for_network_manager_event_listener_ids[event_name]) do |listener_id|
674
+ promise = resolvable_future
675
+
676
+ listener_id = @frame_manager.network_manager.add_event_listener(event_name) do |event_target|
677
+ if predicate.call(event_target)
678
+ promise.fulfill(event_target)
679
+ end
680
+ end
681
+
682
+ begin
683
+ # Timeout.timeout(0) means "no limit" for timeout.
684
+ Timeout.timeout(option_timeout / 1000.0) do
685
+ await_any(promise, session_close_promise)
686
+ end
687
+ rescue Timeout::Error
688
+ raise Puppeteer::TimeoutError.new("waiting for #{event_name} failed: timeout #{option_timeout}ms exceeded")
689
+ ensure
669
690
  @frame_manager.network_manager.remove_event_listener(listener_id)
670
691
  end
692
+ end
693
+
694
+ private def wait_for_frame_manager_event(*event_names, predicate:, timeout:)
695
+ option_timeout = timeout || @timeout_settings.timeout
671
696
 
672
697
  promise = resolvable_future
673
698
 
674
- @wait_for_network_manager_event_listener_ids[event_name] =
675
- @frame_manager.network_manager.add_event_listener(event_name) do |event_target|
699
+ listener_ids = event_names.map do |event_name|
700
+ @frame_manager.add_event_listener(event_name) do |event_target|
676
701
  if predicate.call(event_target)
677
- promise.fulfill(event_target)
702
+ promise.fulfill(event_target) unless promise.resolved?
678
703
  end
679
704
  end
705
+ end
680
706
 
681
707
  begin
682
708
  # Timeout.timeout(0) means "no limit" for timeout.
@@ -684,9 +710,11 @@ class Puppeteer::Page
684
710
  await_any(promise, session_close_promise)
685
711
  end
686
712
  rescue Timeout::Error
687
- raise Puppeteer::TimeoutError.new("waiting for #{event_name} failed: timeout #{timeout}ms exceeded")
713
+ raise Puppeteer::TimeoutError.new("waiting for #{event_names.join(" or ")} failed: timeout #{option_timeout}ms exceeded")
688
714
  ensure
689
- @frame_manager.network_manager.remove_event_listener(@wait_for_network_manager_event_listener_ids[event_name])
715
+ listener_ids.each do |listener_id|
716
+ @frame_manager.remove_event_listener(listener_id)
717
+ end
690
718
  end
691
719
  end
692
720
 
@@ -709,7 +737,7 @@ class Puppeteer::Page
709
737
  if url
710
738
  -> (request) { request.url == url }
711
739
  else
712
- -> (request) { predicate.call(request) }
740
+ predicate
713
741
  end
714
742
 
715
743
  wait_for_network_manager_event(NetworkManagerEmittedEvents::Request,
@@ -743,7 +771,7 @@ class Puppeteer::Page
743
771
  if url
744
772
  -> (response) { response.url == url }
745
773
  else
746
- -> (response) { predicate.call(response) }
774
+ predicate
747
775
  end
748
776
 
749
777
  wait_for_network_manager_event(NetworkManagerEmittedEvents::Response,
@@ -758,6 +786,34 @@ class Puppeteer::Page
758
786
  # @param predicate [Proc(Puppeteer::HTTPRequest -> Boolean)]
759
787
  define_async_method :async_wait_for_response
760
788
 
789
+ def wait_for_frame(url: nil, predicate: nil, timeout: nil)
790
+ if !url && !predicate
791
+ raise ArgumentError.new('url or predicate must be specified')
792
+ end
793
+ if predicate && !predicate.is_a?(Proc)
794
+ raise ArgumentError.new('predicate must be a proc.')
795
+ end
796
+ frame_predicate =
797
+ if url
798
+ -> (frame) { frame.url == url }
799
+ else
800
+ predicate
801
+ end
802
+
803
+ wait_for_frame_manager_event(
804
+ FrameManagerEmittedEvents::FrameAttached,
805
+ FrameManagerEmittedEvents::FrameNavigated,
806
+ predicate: frame_predicate,
807
+ timeout: timeout,
808
+ )
809
+ end
810
+
811
+ # @!method async_wait_for_frame(url: nil, predicate: nil, timeout: nil)
812
+ #
813
+ # @param url [String]
814
+ # @param predicate [Proc(Puppeteer::Frame -> Boolean)]
815
+ define_async_method :async_wait_for_frame
816
+
761
817
  # @param timeout [number|nil]
762
818
  # @param wait_until [string|nil] 'load' | 'domcontentloaded' | 'networkidle0' | 'networkidle2'
763
819
  def go_back(timeout: nil, wait_until: nil)
@@ -44,6 +44,7 @@ class Puppeteer::Puppeteer
44
44
  args: nil,
45
45
  user_data_dir: nil,
46
46
  devtools: nil,
47
+ debugging_port: nil,
47
48
  headless: nil,
48
49
  ignore_https_errors: nil,
49
50
  default_viewport: NoViewport.new,
@@ -63,6 +64,7 @@ class Puppeteer::Puppeteer
63
64
  args: args,
64
65
  user_data_dir: user_data_dir,
65
66
  devtools: devtools,
67
+ debugging_port: debugging_port,
66
68
  headless: headless,
67
69
  ignore_https_errors: ignore_https_errors,
68
70
  default_viewport: default_viewport,
@@ -119,6 +119,11 @@ class Puppeteer::Target
119
119
  end
120
120
  end
121
121
 
122
+ # @internal
123
+ def raw_type
124
+ @target_info.type
125
+ end
126
+
122
127
  # @return {!Puppeteer.Browser}
123
128
  def browser
124
129
  @browser_context.browser
@@ -1,3 +1,3 @@
1
1
  module Puppeteer
2
- VERSION = '0.37.2'
2
+ VERSION = '0.39.0'
3
3
  end
data/lib/puppeteer.rb CHANGED
@@ -33,6 +33,7 @@ require 'puppeteer/dialog'
33
33
  require 'puppeteer/dom_world'
34
34
  require 'puppeteer/emulation_manager'
35
35
  require 'puppeteer/exception_details'
36
+ require 'puppeteer/executable_path_finder'
36
37
  require 'puppeteer/execution_context'
37
38
  require 'puppeteer/file_chooser'
38
39
  require 'puppeteer/frame'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: puppeteer-ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.37.2
4
+ version: 0.39.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - YusukeIwaki
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-11-21 00:00:00.000000000 Z
11
+ date: 2021-12-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: concurrent-ruby
@@ -282,6 +282,7 @@ files:
282
282
  - lib/puppeteer/event_callbackable.rb
283
283
  - lib/puppeteer/events.rb
284
284
  - lib/puppeteer/exception_details.rb
285
+ - lib/puppeteer/executable_path_finder.rb
285
286
  - lib/puppeteer/execution_context.rb
286
287
  - lib/puppeteer/file_chooser.rb
287
288
  - lib/puppeteer/frame.rb