puppeteer-ruby 0.0.13 → 0.0.14

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.
Files changed (126) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +0 -12
  3. data/.github/workflows/docs.yml +45 -0
  4. data/.github/workflows/reviewdog.yml +15 -0
  5. data/README.md +52 -1
  6. data/lib/puppeteer.rb +1 -1
  7. data/lib/puppeteer/browser.rb +17 -25
  8. data/lib/puppeteer/cdp_session.rb +3 -19
  9. data/lib/puppeteer/concurrent_ruby_utils.rb +6 -0
  10. data/lib/puppeteer/connection.rb +3 -15
  11. data/lib/puppeteer/define_async_method.rb +23 -0
  12. data/lib/puppeteer/dom_world.rb +6 -21
  13. data/lib/puppeteer/element_handle.rb +15 -44
  14. data/lib/puppeteer/emulation_manager.rb +2 -6
  15. data/lib/puppeteer/execution_context.rb +1 -6
  16. data/lib/puppeteer/frame.rb +30 -16
  17. data/lib/puppeteer/frame_manager.rb +7 -25
  18. data/lib/puppeteer/js_handle.rb +3 -12
  19. data/lib/puppeteer/keyboard.rb +6 -27
  20. data/lib/puppeteer/mouse.rb +5 -25
  21. data/lib/puppeteer/page.rb +39 -63
  22. data/lib/puppeteer/remote_object.rb +2 -5
  23. data/lib/puppeteer/touch_screen.rb +2 -7
  24. data/lib/puppeteer/version.rb +1 -1
  25. data/lib/puppeteer/wait_task.rb +2 -4
  26. data/puppeteer-ruby.gemspec +1 -1
  27. metadata +7 -103
  28. data/docs/Puppeteer.html +0 -2338
  29. data/docs/Puppeteer/AsyncAwaitBehavior.html +0 -105
  30. data/docs/Puppeteer/Browser.html +0 -2258
  31. data/docs/Puppeteer/BrowserContext.html +0 -809
  32. data/docs/Puppeteer/BrowserFetcher.html +0 -214
  33. data/docs/Puppeteer/BrowserRunner.html +0 -914
  34. data/docs/Puppeteer/BrowserRunner/BrowserProcess.html +0 -477
  35. data/docs/Puppeteer/CDPSession.html +0 -813
  36. data/docs/Puppeteer/CDPSession/Error.html +0 -124
  37. data/docs/Puppeteer/ConcurrentRubyUtils.html +0 -438
  38. data/docs/Puppeteer/Connection.html +0 -964
  39. data/docs/Puppeteer/Connection/MessageCallback.html +0 -434
  40. data/docs/Puppeteer/Connection/ProtocolError.html +0 -216
  41. data/docs/Puppeteer/Connection/RequestDebugPrinter.html +0 -217
  42. data/docs/Puppeteer/Connection/ResponseDebugPrinter.html +0 -244
  43. data/docs/Puppeteer/ConsoleMessage.html +0 -565
  44. data/docs/Puppeteer/ConsoleMessage/Location.html +0 -433
  45. data/docs/Puppeteer/DOMWorld.html +0 -2293
  46. data/docs/Puppeteer/DOMWorld/DetachedError.html +0 -124
  47. data/docs/Puppeteer/DOMWorld/DocumentEvaluationError.html +0 -124
  48. data/docs/Puppeteer/DebugPrint.html +0 -233
  49. data/docs/Puppeteer/Device.html +0 -470
  50. data/docs/Puppeteer/Devices.html +0 -139
  51. data/docs/Puppeteer/ElementHandle.html +0 -2542
  52. data/docs/Puppeteer/ElementHandle/BoundingBox.html +0 -507
  53. data/docs/Puppeteer/ElementHandle/BoxModel.html +0 -404
  54. data/docs/Puppeteer/ElementHandle/ElementNotFoundError.html +0 -206
  55. data/docs/Puppeteer/ElementHandle/ElementNotVisibleError.html +0 -206
  56. data/docs/Puppeteer/ElementHandle/Point.html +0 -492
  57. data/docs/Puppeteer/ElementHandle/ScrollIntoViewError.html +0 -124
  58. data/docs/Puppeteer/EmulationManager.html +0 -454
  59. data/docs/Puppeteer/EventCallbackable.html +0 -499
  60. data/docs/Puppeteer/EventCallbackable/EventListeners.html +0 -435
  61. data/docs/Puppeteer/ExecutionContext.html +0 -998
  62. data/docs/Puppeteer/ExecutionContext/EvaluationError.html +0 -124
  63. data/docs/Puppeteer/ExecutionContext/JavaScriptExpression.html +0 -357
  64. data/docs/Puppeteer/ExecutionContext/JavaScriptFunction.html +0 -389
  65. data/docs/Puppeteer/FileChooser.html +0 -455
  66. data/docs/Puppeteer/Frame.html +0 -3835
  67. data/docs/Puppeteer/FrameManager.html +0 -2410
  68. data/docs/Puppeteer/FrameManager/NavigationError.html +0 -124
  69. data/docs/Puppeteer/IfPresent.html +0 -222
  70. data/docs/Puppeteer/JSHandle.html +0 -1352
  71. data/docs/Puppeteer/Keyboard.html +0 -1557
  72. data/docs/Puppeteer/Keyboard/KeyDefinition.html +0 -831
  73. data/docs/Puppeteer/Keyboard/KeyDescription.html +0 -603
  74. data/docs/Puppeteer/Launcher.html +0 -237
  75. data/docs/Puppeteer/Launcher/Base.html +0 -385
  76. data/docs/Puppeteer/Launcher/Base/ExecutablePathNotFound.html +0 -124
  77. data/docs/Puppeteer/Launcher/BrowserOptions.html +0 -441
  78. data/docs/Puppeteer/Launcher/Chrome.html +0 -674
  79. data/docs/Puppeteer/Launcher/Chrome/DefaultArgs.html +0 -382
  80. data/docs/Puppeteer/Launcher/ChromeArgOptions.html +0 -531
  81. data/docs/Puppeteer/Launcher/LaunchOptions.html +0 -893
  82. data/docs/Puppeteer/LifecycleWatcher.html +0 -834
  83. data/docs/Puppeteer/LifecycleWatcher/ExpectedLifecycle.html +0 -363
  84. data/docs/Puppeteer/LifecycleWatcher/FrameDetachedError.html +0 -206
  85. data/docs/Puppeteer/LifecycleWatcher/TerminatedError.html +0 -124
  86. data/docs/Puppeteer/Mouse.html +0 -1095
  87. data/docs/Puppeteer/Mouse/Button.html +0 -136
  88. data/docs/Puppeteer/NetworkManager.html +0 -901
  89. data/docs/Puppeteer/NetworkManager/Credentials.html +0 -385
  90. data/docs/Puppeteer/Page.html +0 -6173
  91. data/docs/Puppeteer/Page/FileChooserTimeoutError.html +0 -206
  92. data/docs/Puppeteer/Page/ScreenshotOptions.html +0 -845
  93. data/docs/Puppeteer/Page/ScriptTag.html +0 -555
  94. data/docs/Puppeteer/Page/StyleTag.html +0 -448
  95. data/docs/Puppeteer/Page/TargetCrashedError.html +0 -124
  96. data/docs/Puppeteer/RemoteObject.html +0 -1087
  97. data/docs/Puppeteer/Target.html +0 -1336
  98. data/docs/Puppeteer/Target/InitializeFailure.html +0 -124
  99. data/docs/Puppeteer/Target/TargetInfo.html +0 -729
  100. data/docs/Puppeteer/TimeoutError.html +0 -135
  101. data/docs/Puppeteer/TimeoutSettings.html +0 -496
  102. data/docs/Puppeteer/TouchScreen.html +0 -464
  103. data/docs/Puppeteer/Viewport.html +0 -837
  104. data/docs/Puppeteer/WaitTask.html +0 -637
  105. data/docs/Puppeteer/WaitTask/TerminatedError.html +0 -124
  106. data/docs/Puppeteer/WaitTask/TimeoutError.html +0 -206
  107. data/docs/Puppeteer/WebSocket.html +0 -673
  108. data/docs/Puppeteer/WebSocket/DriverImpl.html +0 -412
  109. data/docs/Puppeteer/WebSocket/TransportError.html +0 -124
  110. data/docs/Puppeteer/WebSocketTransport.html +0 -600
  111. data/docs/Puppeteer/WebSocktTransportError.html +0 -124
  112. data/docs/_index.html +0 -816
  113. data/docs/class_list.html +0 -51
  114. data/docs/css/common.css +0 -1
  115. data/docs/css/full_list.css +0 -58
  116. data/docs/css/style.css +0 -496
  117. data/docs/file.README.html +0 -125
  118. data/docs/file_list.html +0 -56
  119. data/docs/frames.html +0 -17
  120. data/docs/index.html +0 -125
  121. data/docs/js/app.js +0 -314
  122. data/docs/js/full_list.js +0 -216
  123. data/docs/js/jquery.js +0 -4
  124. data/docs/method_list.html +0 -4123
  125. data/docs/top-level-namespace.html +0 -126
  126. data/lib/puppeteer/async_await_behavior.rb +0 -38
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0c440ee3ee2c46ab3b4639855bb08497063338c8cc4458fa4e1d4eeba8fd7c65
4
- data.tar.gz: 0d380b3fc666f05402676ba85f278f42cce9b271bd713cffd938d0fefd39be71
3
+ metadata.gz: 0a500508a5a1d88ed4694c5614c7c70bdae06d4d5cb10f81c1237ebd25a6623f
4
+ data.tar.gz: 338b902e3c64d9f96e7b7822353a7b664ab112cd3993e7a7ec06cda41752521e
5
5
  SHA512:
6
- metadata.gz: a6018e2425cc73f5d3a850169041906d9f6eb50f0398690df3f4bef871960834c4aaf07ae14f439e854f7069e33691575e29c1153b379ed22dbab6120c34731c
7
- data.tar.gz: 6ba30ed2dddb60113bb6e8f1341b7e326901a4c4ebcf8c61734a93c114dcd667954ce442bcbc4d44d5f951537ff65458ac34dcedf23747182b45a86920f67245
6
+ metadata.gz: 51ea52a62c04917d5ec62c4224ffe91cacf3ccd3cfc796d94d975c309971dc0e789fdec7f4fabcc37f51619d833f070e7d6136f18cdb7113721382392456dd88
7
+ data.tar.gz: ef643098e96d3d1794470f38befb55039916c13b35d7d133596acf42d7217c302d1de4865c62c178e758aa619063ee9469bbbfcda1665c3e19fcca26aaee12ce
@@ -18,17 +18,6 @@ jobs:
18
18
  --out test_results/rspec.xml \
19
19
  --format progress
20
20
 
21
- rubocop:
22
- docker:
23
- - image: circleci/ruby:2.6.3-stretch-node
24
- executor: ruby/default
25
- steps:
26
- - checkout
27
- - ruby/bundle-install
28
- - run:
29
- name: rubocop
30
- command: bundle exec rubocop
31
-
32
21
  deploy:
33
22
  docker:
34
23
  - image: circleci/ruby:2.6.3-stretch-node
@@ -60,7 +49,6 @@ workflows:
60
49
  ci:
61
50
  jobs:
62
51
  - rspec
63
- - rubocop
64
52
  rubygems-deploy:
65
53
  jobs:
66
54
  - deploy:
@@ -0,0 +1,45 @@
1
+ name: update docs
2
+ on:
3
+ push:
4
+ branches:
5
+ - master
6
+
7
+ jobs:
8
+ update-docs:
9
+ name: update docs
10
+ runs-on: ubuntu-latest
11
+
12
+ steps:
13
+ - name: Checkout
14
+ uses: actions/checkout@v2
15
+
16
+ - name: Set up Ruby
17
+ uses: ruby/setup-ruby@v1
18
+ with:
19
+ ruby-version: 2.6
20
+
21
+ - name: Install dependencies
22
+ run: |
23
+ gem uninstall bundler
24
+ gem install bundler -v 1.17
25
+ bundle install
26
+
27
+ - name: Deploy Configuration
28
+ run: |
29
+ mkdir ~/.ssh
30
+ ssh-keyscan -t rsa github.com >> ~/.ssh/known_hosts
31
+ echo "${{ secrets.DOCS_DEPLOY_SSH_RSA }}" | base64 -d > ~/.ssh/id_rsa
32
+ chmod 400 ~/.ssh/id_rsa
33
+
34
+ - name: Build and Push
35
+ run: |
36
+ git clone git@github.com:YusukeIwaki/puppeteer-ruby-docs.git docs
37
+ rm -rf docs/*
38
+ bundle exec yardoc -o docs
39
+ cp puppeteer-ruby.png docs/
40
+ cd docs/
41
+ git add -A
42
+ git config user.name github
43
+ git config user.email github@example.com
44
+ git commit -m ${{ github.sha }}
45
+ git push origin master
@@ -0,0 +1,15 @@
1
+ name: reviewdog
2
+ on: [pull_request]
3
+ jobs:
4
+ rubocop:
5
+ name: runner / rubocop
6
+ runs-on: ubuntu-latest
7
+ steps:
8
+ - name: Check out code
9
+ uses: actions/checkout@v2
10
+ - name: rubocop
11
+ uses: reviewdog/action-rubocop@v1
12
+ with:
13
+ github_token: ${{ secrets.github_token }}
14
+ reporter: github-pr-review
15
+ rubocop_version: 0.86.0
data/README.md CHANGED
@@ -47,9 +47,60 @@ end
47
47
 
48
48
  More usage examples can be found [here](https://github.com/YusukeIwaki/puppeteer-ruby-example)
49
49
 
50
+ ## Collaboration with Selenium or Capybara
51
+
52
+ It is really remarkable that we can use puppeteer functions in existing Selenium or Capybara codes, with a few configuration in advance.
53
+
54
+ ```ruby
55
+ require 'spec_helper'
56
+
57
+ RSpec.describe 'hotel.testplanisphere.dev', type: :feature do
58
+ before {
59
+ visit 'https://hotel.testplanisphere.dev/'
60
+
61
+ # acquire Puppeteer::Browser instance, by connecting Chrome with DevTools Protocol.
62
+ @browser = Puppeteer.connect(
63
+ browser_url: 'http://localhost:9222',
64
+ default_viewport: Puppeteer::Viewport.new(width: 1280, height: 800))
65
+ }
66
+
67
+ after {
68
+ # release Puppeteer::Browser reesource.
69
+ @browser.disconnect
70
+ }
71
+
72
+ it 'can be handled with puppeteer and assert with Capybara' do
73
+ # automation with puppeteer
74
+ puppeteer_page = @browser.pages.first
75
+ puppeteer_page.wait_for_selector('li.nav-item')
76
+
77
+ reservation_link = puppeteer_page.SS('li.nav-item')[1]
78
+
79
+ await_all(
80
+ puppeteer_page.async_wait_for_navigation,
81
+ reservation_link.async_click,
82
+ )
83
+
84
+ # expectation with Capybara DSL
85
+ expect(page).to have_text('宿泊プラン一覧')
86
+ end
87
+
88
+ it 'can be handled with Capybara and assert with puppeteer' do
89
+ # automation with Capybara
90
+ page.all('li.nav-item')[1].click
91
+
92
+ # expectation with puppeteer
93
+ puppeteer_page = @browser.pages.first
94
+ body_text = puppeteer_page.Seval('body', '(el) => el.textContent')
95
+ expect(body_text).to include('宿泊プラン一覧')
96
+ end
97
+ ```
98
+
99
+ The detailed step of configuration can be found [here](https://github.com/YusukeIwaki/puppeteer-ruby-example/tree/master/_with_capybara-rspec).
100
+
50
101
  ## API
51
102
 
52
- https://yusukeiwaki.github.io/puppeteer-ruby/
103
+ https://yusukeiwaki.github.io/puppeteer-ruby-docs/
53
104
 
54
105
  ## Contributing
55
106
 
@@ -8,8 +8,8 @@ require 'puppeteer/errors'
8
8
  require 'puppeteer/viewport'
9
9
 
10
10
  # Modules
11
- require 'puppeteer/async_await_behavior'
12
11
  require 'puppeteer/concurrent_ruby_utils'
12
+ require 'puppeteer/define_async_method'
13
13
  require 'puppeteer/debug_print'
14
14
  require 'puppeteer/event_callbackable'
15
15
  require 'puppeteer/if_present'
@@ -5,7 +5,7 @@ class Puppeteer::Browser
5
5
  include Puppeteer::DebugPrint
6
6
  include Puppeteer::EventCallbackable
7
7
  include Puppeteer::IfPresent
8
- using Puppeteer::AsyncAwaitBehavior
8
+ using Puppeteer::DefineAsyncMethod
9
9
 
10
10
  # @param {!Puppeteer.Connection} connection
11
11
  # @param {!Array<string>} contextIds
@@ -97,6 +97,12 @@ class Puppeteer::Browser
97
97
  @contexts.remove(context_id)
98
98
  end
99
99
 
100
+ class TargetAlreadyExistError < StandardError
101
+ def initialize
102
+ super('Target should not exist before targetCreated')
103
+ end
104
+ end
105
+
100
106
  # @param {!Protocol.Target.targetCreatedPayload} event
101
107
  def handle_target_created(event)
102
108
  target_info = Puppeteer::Target::TargetInfo.new(event['targetInfo'])
@@ -108,6 +114,9 @@ class Puppeteer::Browser
108
114
  @default_context
109
115
  end
110
116
 
117
+ if @targets[target_info.target_id]
118
+ raise TargetAlreadyExistError.new
119
+ end
111
120
  target = Puppeteer::Target.new(
112
121
  target_info: target_info,
113
122
  browser_context: context,
@@ -122,13 +131,8 @@ class Puppeteer::Browser
122
131
  emit_event 'Events.Browser.TargetCreated', target
123
132
  context.emit_event 'Events.BrowserContext.TargetCreated', target
124
133
  end
125
-
126
- if_present(pending_target_info_changed_event.delete(target_info.target_id)) do |pending_event|
127
- handle_target_info_changed(pending_event)
128
- end
129
134
  end
130
135
 
131
-
132
136
  # @param {{targetId: string}} event
133
137
  def handle_target_destroyed(event)
134
138
  target_id = event['targetId']
@@ -142,24 +146,16 @@ class Puppeteer::Browser
142
146
  end
143
147
  end
144
148
 
149
+ class TargetNotExistError < StandardError
150
+ def initialize
151
+ super('target should exist before targetInfoChanged')
152
+ end
153
+ end
154
+
145
155
  # @param {!Protocol.Target.targetInfoChangedPayload} event
146
156
  def handle_target_info_changed(event)
147
157
  target_info = Puppeteer::Target::TargetInfo.new(event['targetInfo'])
148
- target = @targets[target_info.target_id]
149
- if !target
150
- # targetCreated is sometimes notified after targetInfoChanged.
151
- # We don't raise error. Instead, keep the event as a pending change,
152
- # and handle it on handle_target_created.
153
- #
154
- # D, [2020-04-22T00:22:26.630328 #79646] DEBUG -- : RECV << {"method"=>"Target.targetInfoChanged", "params"=>{"targetInfo"=>{"targetId"=>"8068CED48357B9557EEC85AA62165A8E", "type"=>"iframe", "title"=>"", "url"=>"", "attached"=>true, "browserContextId"=>"7895BFB24BF22CE40584808713D96E8D"}}}
155
- # E, [2020-04-22T00:22:26.630448 #79646] ERROR -- : target should exist before targetInfoChanged (StandardError)
156
- # D, [2020-04-22T00:22:26.630648 #79646] DEBUG -- : RECV << {"method"=>"Target.targetCreated", "params"=>{"targetInfo"=>{"targetId"=>"8068CED48357B9557EEC85AA62165A8E", "type"=>"iframe", "title"=>"", "url"=>"", "attached"=>false, "browserContextId"=>"7895BFB24BF22CE40584808713D96E8D"}}}
157
- pending_target_info_changed_event[target_info.target_id] = event
158
- return
159
- # original implementation is:
160
- #
161
- # raise StandardError.new('target should exist before targetInfoChanged')
162
- end
158
+ target = @targets[target_info.target_id] or raise TargetNotExistError.new
163
159
  previous_url = target.url
164
160
  was_initialized = target.initialized?
165
161
  target.handle_target_info_changed(target_info)
@@ -169,10 +165,6 @@ class Puppeteer::Browser
169
165
  end
170
166
  end
171
167
 
172
- private def pending_target_info_changed_event
173
- @pending_target_info_changed_event ||= {}
174
- end
175
-
176
168
  # @return [String]
177
169
  def websocket_endpoint
178
170
  @connection.url
@@ -1,7 +1,7 @@
1
1
  class Puppeteer::CDPSession
2
2
  include Puppeteer::DebugPrint
3
3
  include Puppeteer::EventCallbackable
4
- using Puppeteer::AsyncAwaitBehavior
4
+ using Puppeteer::DefineAsyncMethod
5
5
 
6
6
  class Error < StandardError; end
7
7
 
@@ -13,7 +13,6 @@ class Puppeteer::CDPSession
13
13
  @connection = connection
14
14
  @target_type = target_type
15
15
  @session_id = session_id
16
- @pending_messages = {}
17
16
  end
18
17
 
19
18
  attr_reader :connection
@@ -35,12 +34,7 @@ class Puppeteer::CDPSession
35
34
  id = @connection.raw_send(message: { sessionId: @session_id, method: method, params: params })
36
35
  promise = resolvable_future
37
36
  callback = Puppeteer::Connection::MessageCallback.new(method: method, promise: promise)
38
- if pending_message = @pending_messages.delete(id)
39
- debug_puts "Pending message (id: #{id}) is handled"
40
- callback_with_message(callback, pending_message)
41
- else
42
- @callbacks[id] = callback
43
- end
37
+ @callbacks[id] = callback
44
38
  promise
45
39
  end
46
40
 
@@ -50,17 +44,7 @@ class Puppeteer::CDPSession
50
44
  if callback = @callbacks.delete(message['id'])
51
45
  callback_with_message(callback, message)
52
46
  else
53
- debug_puts "unknown id: #{id}. Store it into pending message"
54
-
55
- # RECV is often notified before SEND.
56
- # Wait about 10 frames before throwing an error.
57
- message_id = message['id']
58
- @pending_messages[message_id] = message
59
- Concurrent::Promises.schedule(0.16, message_id) do |id|
60
- if @pending_messages.delete(id)
61
- raise Error.new("unknown id: #{id}")
62
- end
63
- end
47
+ raise Error.new("unknown id: #{id}")
64
48
  end
65
49
  else
66
50
  emit_event message['method'], message['params']
@@ -1,5 +1,8 @@
1
1
  # utility methods for Concurrent::Promises.
2
2
  module Puppeteer::ConcurrentRubyUtils
3
+ # wait for all promises.
4
+ # REMARK: This method doesn't assure the order of calling.
5
+ # for example, await_all(async1, async2) calls calls2 -> calls1 often.
3
6
  def await_all(*args)
4
7
  if args.length == 1 && args[0].is_a?(Enumerable)
5
8
  Concurrent::Promises.zip(*(args[0])).value!
@@ -8,6 +11,9 @@ module Puppeteer::ConcurrentRubyUtils
8
11
  end
9
12
  end
10
13
 
14
+ # wait for first promises.
15
+ # REMARK: This method doesn't assure the order of calling.
16
+ # for example, await_all(async1, async2) calls calls2 -> calls1 often.
11
17
  def await_any(*args)
12
18
  if args.length == 1 && args[0].is_a?(Enumerable)
13
19
  Concurrent::Promises.any(*(args[0])).value!
@@ -3,7 +3,7 @@ require 'json'
3
3
  class Puppeteer::Connection
4
4
  include Puppeteer::DebugPrint
5
5
  include Puppeteer::EventCallbackable
6
- using Puppeteer::AsyncAwaitBehavior
6
+ using Puppeteer::DefineAsyncMethod
7
7
 
8
8
  class ProtocolError < StandardError
9
9
  def initialize(method:, error_message:, error_data: nil)
@@ -210,9 +210,7 @@ class Puppeteer::Connection
210
210
  end
211
211
  end
212
212
 
213
- private async def async_handle_message(message)
214
- handle_message(message)
215
- end
213
+ private define_async_method :async_handle_message
216
214
 
217
215
  private def handle_close
218
216
  return if @closed
@@ -251,16 +249,6 @@ class Puppeteer::Connection
251
249
  def create_session(target_info)
252
250
  result = send_message('Target.attachToTarget', targetId: target_info.target_id, flatten: true)
253
251
  session_id = result['sessionId']
254
-
255
- # Target.attachedToTarget is often notified after the result of Target.attachToTarget.
256
- # D, [2020-04-04T23:04:30.736311 #91875] DEBUG -- : RECV << {"id"=>2, "result"=>{"sessionId"=>"DA002F8A95B04710502CB40D8430B95A"}}
257
- # D, [2020-04-04T23:04:30.736649 #91875] DEBUG -- : RECV << {"method"=>"Target.attachedToTarget", "params"=>{"sessionId"=>"DA002F8A95B04710502CB40D8430B95A", "targetInfo"=>{"targetId"=>"EBAB949A7DE63F12CB94268AD3A9976B", "type"=>"page", "title"=>"about:blank", "url"=>"about:blank", "attached"=>true, "browserContextId"=>"46D23767E9B79DD9E589101121F6DADD"}, "waitingForDebugger"=>false}}
258
- # So we have to wait for "Target.attachedToTarget" a bit.
259
- 20.times do
260
- if @sessions[session_id]
261
- return @sessions[session_id]
262
- end
263
- sleep 0.1
264
- end
252
+ @sessions[session_id]
265
253
  end
266
254
  end
@@ -0,0 +1,23 @@
1
+ module Puppeteer::DefineAsyncMethod
2
+ refine Class do
3
+ def define_async_method(async_method_name)
4
+ unless async_method_name.to_s.start_with?('async_')
5
+ raise ArgumentError.new('async method name should start with "async_"')
6
+ end
7
+
8
+ if method_defined?(async_method_name) || private_method_defined?(async_method_name)
9
+ raise ArgumentError.new("#{async_method_name} is already defined")
10
+ end
11
+
12
+ original_method = instance_method(async_method_name[6..-1])
13
+ define_method(async_method_name) do |*args|
14
+ Concurrent::Promises.future do
15
+ original_method.bind(self).call(*args)
16
+ rescue => err
17
+ Logger.new(STDERR).warn(err)
18
+ raise err
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -2,7 +2,7 @@ require 'thread'
2
2
 
3
3
  # https://github.com/puppeteer/puppeteer/blob/master/src/DOMWorld.js
4
4
  class Puppeteer::DOMWorld
5
- using Puppeteer::AsyncAwaitBehavior
5
+ using Puppeteer::DefineAsyncMethod
6
6
 
7
7
  # @param {!Puppeteer.FrameManager} frameManager
8
8
  # @param {!Puppeteer.Frame} frame
@@ -12,7 +12,6 @@ class Puppeteer::DOMWorld
12
12
  @frame = frame
13
13
  @timeout_settings = timeout_settings
14
14
  @context_promise = resolvable_future
15
- @pending_destroy = []
16
15
  @wait_tasks = Set.new
17
16
  @detached = false
18
17
  end
@@ -24,22 +23,12 @@ class Puppeteer::DOMWorld
24
23
  @wait_tasks
25
24
  end
26
25
 
27
- # @param {?Puppeteer.ExecutionContext} context
26
+ # @param context [Puppeteer::ExecutionContext]
28
27
  def context=(context)
29
- # D, [2020-04-12T22:45:03.938754 #46154] DEBUG -- : RECV << {"method"=>"Runtime.executionContextCreated", "params"=>{"context"=>{"id"=>3, "origin"=>"https://github.com", "name"=>"", "auxData"=>{"isDefault"=>true, "type"=>"default", "frameId"=>"3AD7F1E82BCBA88BFE31D03BC49FF6CB"}}}, "sessionId"=>"636CEF0C4FEAFC4FE815E9E7B5F7BA68"}
30
- # D, [2020-04-12T22:45:03.938856 #46154] DEBUG -- : RECV << {"method"=>"Runtime.executionContextCreated", "params"=>{"context"=>{"id"=>4, "origin"=>"://", "name"=>"__puppeteer_utility_world__", "auxData"=>{"isDefault"=>false, "type"=>"isolated", "frameId"=>"3AD7F1E82BCBA88BFE31D03BC49FF6CB"}}}, "sessionId"=>"636CEF0C4FEAFC4FE815E9E7B5F7BA68"}
31
- # D, [2020-04-12T22:45:03.938960 #46154] DEBUG -- : RECV << {"method"=>"Runtime.executionContextDestroyed", "params"=>{"executionContextId"=>1}, "sessionId"=>"636CEF0C4FEAFC4FE815E9E7B5F7BA68"}
32
- # D, [2020-04-12T22:45:03.939110 #46154] DEBUG -- : RECV << {"method"=>"Page.frameNavigated", "params"=>{"frame"=>{"id"=>"3AD7F1E82BCBA88BFE31D03BC49FF6CB", "loaderId"=>"301B349884E582986C502CBE020966DF", "url"=>"https://github.com/", "securityOrigin"=>"https://github.com", "mimeType"=>"text/html"}}, "sessionId"=>"636CEF0C4FEAFC4FE815E9E7B5F7BA68"}
33
- # D, [2020-04-12T22:45:03.939793 #46154] DEBUG -- : RECV << {"method"=>"Runtime.executionContextDestroyed", "params"=>{"executionContextId"=>2}, "sessionId"=>"636CEF0C4FEAFC4FE815E9E7B5F7BA68"}
34
- # executionContextDestroyed is often notified after executionContextCreated.
35
-
36
28
  if context
37
- if @context_promise.fulfilled?
38
- @pending_destroy << context._context_id
39
- @document = nil
40
- @context_promise = resolvable_future
29
+ unless @context_promise.resolved?
30
+ @context_promise.fulfill(context)
41
31
  end
42
- @context_promise.fulfill(context)
43
32
  @wait_tasks.each(&:async_rerun)
44
33
  else
45
34
  raise ArgumentError.new("context should now be nil. Use #delete_context for clearing document.")
@@ -47,12 +36,8 @@ class Puppeteer::DOMWorld
47
36
  end
48
37
 
49
38
  def delete_context(execution_context_id)
50
- if @pending_destroy.include?(execution_context_id)
51
- @pending_destroy.delete(execution_context_id)
52
- else
53
- @document = nil
54
- @context_promise = resolvable_future
55
- end
39
+ @document = nil
40
+ @context_promise = resolvable_future
56
41
  end
57
42
 
58
43
  def has_context?