puppeteer-ruby 0.45.6 → 0.50.0.alpha5
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.
- checksums.yaml +4 -4
- data/.rubocop.yml +1 -3
- data/AGENTS.md +169 -0
- data/CLAUDE/README.md +41 -0
- data/CLAUDE/architecture.md +253 -0
- data/CLAUDE/cdp_protocol.md +230 -0
- data/CLAUDE/concurrency.md +216 -0
- data/CLAUDE/porting_puppeteer.md +575 -0
- data/CLAUDE/rbs_type_checking.md +101 -0
- data/CLAUDE/spec_migration_plans.md +1041 -0
- data/CLAUDE/testing.md +278 -0
- data/CLAUDE.md +242 -0
- data/README.md +8 -0
- data/Rakefile +7 -0
- data/Steepfile +28 -0
- data/docs/api_coverage.md +105 -56
- data/lib/puppeteer/aria_query_handler.rb +3 -2
- data/lib/puppeteer/async_utils.rb +214 -0
- data/lib/puppeteer/browser.rb +98 -56
- data/lib/puppeteer/browser_connector.rb +18 -3
- data/lib/puppeteer/browser_context.rb +196 -3
- data/lib/puppeteer/browser_runner.rb +18 -10
- data/lib/puppeteer/cdp_session.rb +67 -23
- data/lib/puppeteer/chrome_target_manager.rb +65 -40
- data/lib/puppeteer/connection.rb +55 -36
- data/lib/puppeteer/console_message.rb +9 -1
- data/lib/puppeteer/console_patch.rb +47 -0
- data/lib/puppeteer/css_coverage.rb +5 -3
- data/lib/puppeteer/custom_query_handler.rb +80 -33
- data/lib/puppeteer/define_async_method.rb +31 -37
- data/lib/puppeteer/dialog.rb +47 -14
- data/lib/puppeteer/element_handle.rb +231 -62
- data/lib/puppeteer/emulation_manager.rb +1 -1
- data/lib/puppeteer/env.rb +1 -1
- data/lib/puppeteer/errors.rb +25 -2
- data/lib/puppeteer/event_callbackable.rb +15 -0
- data/lib/puppeteer/events.rb +4 -0
- data/lib/puppeteer/execution_context.rb +148 -3
- data/lib/puppeteer/file_chooser.rb +6 -0
- data/lib/puppeteer/frame.rb +162 -91
- data/lib/puppeteer/frame_manager.rb +69 -48
- data/lib/puppeteer/http_request.rb +114 -38
- data/lib/puppeteer/http_response.rb +24 -7
- data/lib/puppeteer/isolated_world.rb +64 -41
- data/lib/puppeteer/js_coverage.rb +5 -3
- data/lib/puppeteer/js_handle.rb +58 -16
- data/lib/puppeteer/keyboard.rb +30 -17
- data/lib/puppeteer/launcher/browser_options.rb +3 -1
- data/lib/puppeteer/launcher/chrome.rb +8 -5
- data/lib/puppeteer/launcher/launch_options.rb +7 -2
- data/lib/puppeteer/launcher.rb +4 -8
- data/lib/puppeteer/lifecycle_watcher.rb +38 -22
- data/lib/puppeteer/mouse.rb +273 -64
- data/lib/puppeteer/network_event_manager.rb +7 -0
- data/lib/puppeteer/network_manager.rb +393 -112
- data/lib/puppeteer/page/screenshot_task_queue.rb +14 -4
- data/lib/puppeteer/page.rb +568 -226
- data/lib/puppeteer/puppeteer.rb +171 -64
- data/lib/puppeteer/query_handler_manager.rb +112 -16
- data/lib/puppeteer/reactor_runner.rb +247 -0
- data/lib/puppeteer/remote_object.rb +127 -47
- data/lib/puppeteer/target.rb +74 -27
- data/lib/puppeteer/task_manager.rb +3 -1
- data/lib/puppeteer/timeout_helper.rb +6 -10
- data/lib/puppeteer/touch_handle.rb +39 -0
- data/lib/puppeteer/touch_screen.rb +72 -22
- data/lib/puppeteer/tracing.rb +3 -3
- data/lib/puppeteer/version.rb +1 -1
- data/lib/puppeteer/wait_task.rb +264 -101
- data/lib/puppeteer/web_socket.rb +2 -2
- data/lib/puppeteer/web_socket_transport.rb +91 -27
- data/lib/puppeteer/web_worker.rb +175 -0
- data/lib/puppeteer.rb +20 -4
- data/puppeteer-ruby.gemspec +15 -11
- data/sig/_external.rbs +8 -0
- data/sig/_supplementary.rbs +314 -0
- data/sig/puppeteer/browser.rbs +166 -0
- data/sig/puppeteer/cdp_session.rbs +64 -0
- data/sig/puppeteer/dialog.rbs +41 -0
- data/sig/puppeteer/element_handle.rbs +305 -0
- data/sig/puppeteer/execution_context.rbs +87 -0
- data/sig/puppeteer/frame.rbs +226 -0
- data/sig/puppeteer/http_request.rbs +214 -0
- data/sig/puppeteer/http_response.rbs +89 -0
- data/sig/puppeteer/js_handle.rbs +64 -0
- data/sig/puppeteer/keyboard.rbs +40 -0
- data/sig/puppeteer/mouse.rbs +113 -0
- data/sig/puppeteer/page.rbs +515 -0
- data/sig/puppeteer/puppeteer.rbs +98 -0
- data/sig/puppeteer/remote_object.rbs +78 -0
- data/sig/puppeteer/touch_handle.rbs +21 -0
- data/sig/puppeteer/touch_screen.rbs +35 -0
- data/sig/puppeteer/web_worker.rbs +83 -0
- metadata +116 -45
- data/CHANGELOG.md +0 -397
- data/lib/puppeteer/concurrent_ruby_utils.rb +0 -81
- data/lib/puppeteer/firefox_target_manager.rb +0 -157
- data/lib/puppeteer/launcher/firefox.rb +0 -453
data/docs/api_coverage.md
CHANGED
|
@@ -1,22 +1,14 @@
|
|
|
1
1
|
# API coverages
|
|
2
|
-
- Puppeteer version:
|
|
3
|
-
- puppeteer-ruby version: 0.
|
|
2
|
+
- Puppeteer version: v24.35.0
|
|
3
|
+
- puppeteer-ruby version: 0.50.0.alpha5
|
|
4
4
|
|
|
5
5
|
## Puppeteer
|
|
6
6
|
|
|
7
|
-
* ~~clearCustomQueryHandlers~~
|
|
8
7
|
* connect
|
|
9
|
-
* ~~createBrowserFetcher~~
|
|
10
|
-
* ~~customQueryHandlerNames~~
|
|
11
8
|
* defaultArgs => `#default_args`
|
|
12
|
-
* devices
|
|
13
|
-
* ~~errors~~
|
|
14
9
|
* executablePath => `#executable_path`
|
|
15
10
|
* launch
|
|
16
|
-
* networkConditions => `#network_conditions`
|
|
17
11
|
* ~~puppeteer~~
|
|
18
|
-
* registerCustomQueryHandler => `#register_custom_query_handler`
|
|
19
|
-
* ~~unregisterCustomQueryHandler~~
|
|
20
12
|
|
|
21
13
|
## ~~Accessibility~~
|
|
22
14
|
|
|
@@ -24,17 +16,28 @@
|
|
|
24
16
|
|
|
25
17
|
## Browser
|
|
26
18
|
|
|
19
|
+
* ~~addScreen~~
|
|
27
20
|
* browserContexts => `#browser_contexts`
|
|
28
21
|
* close
|
|
29
|
-
*
|
|
22
|
+
* ~~cookies~~
|
|
23
|
+
* createBrowserContext => `#create_browser_context`
|
|
30
24
|
* defaultBrowserContext => `#default_browser_context`
|
|
25
|
+
* ~~deleteCookie~~
|
|
26
|
+
* ~~deleteMatchingCookies~~
|
|
31
27
|
* disconnect
|
|
28
|
+
* ~~getWindowBounds~~
|
|
29
|
+
* ~~installExtension~~
|
|
32
30
|
* isConnected => `#connected?`
|
|
33
31
|
* newPage => `#new_page`
|
|
34
32
|
* pages
|
|
35
33
|
* process
|
|
34
|
+
* ~~removeScreen~~
|
|
35
|
+
* ~~screens~~
|
|
36
|
+
* ~~setCookie~~
|
|
37
|
+
* ~~setWindowBounds~~
|
|
36
38
|
* target
|
|
37
39
|
* targets
|
|
40
|
+
* ~~uninstallExtension~~
|
|
38
41
|
* userAgent => `#user_agent`
|
|
39
42
|
* version
|
|
40
43
|
* waitForTarget => `#wait_for_target`
|
|
@@ -45,23 +48,21 @@
|
|
|
45
48
|
* browser
|
|
46
49
|
* clearPermissionOverrides => `#clear_permission_overrides`
|
|
47
50
|
* close
|
|
48
|
-
*
|
|
51
|
+
* cookies
|
|
52
|
+
* deleteCookie => `#delete_cookie`
|
|
53
|
+
* deleteMatchingCookies => `#delete_matching_cookies`
|
|
49
54
|
* newPage => `#new_page`
|
|
50
55
|
* overridePermissions => `#override_permissions`
|
|
51
56
|
* pages
|
|
57
|
+
* setCookie => `#set_cookie`
|
|
52
58
|
* targets
|
|
53
59
|
* waitForTarget => `#wait_for_target`
|
|
54
60
|
|
|
55
|
-
## ~~
|
|
61
|
+
## ~~BrowserLauncher~~
|
|
56
62
|
|
|
57
|
-
* ~~
|
|
58
|
-
* ~~
|
|
59
|
-
* ~~
|
|
60
|
-
* ~~localRevisions~~
|
|
61
|
-
* ~~platform~~
|
|
62
|
-
* ~~product~~
|
|
63
|
-
* ~~remove~~
|
|
64
|
-
* ~~revisionInfo~~
|
|
63
|
+
* ~~defaultArgs~~
|
|
64
|
+
* ~~executablePath~~
|
|
65
|
+
* ~~launch~~
|
|
65
66
|
|
|
66
67
|
## CDPSession
|
|
67
68
|
|
|
@@ -79,6 +80,9 @@
|
|
|
79
80
|
* session
|
|
80
81
|
* url
|
|
81
82
|
|
|
83
|
+
## ~~ConnectionClosedError~~
|
|
84
|
+
|
|
85
|
+
|
|
82
86
|
## ConsoleMessage
|
|
83
87
|
|
|
84
88
|
* args
|
|
@@ -99,8 +103,11 @@
|
|
|
99
103
|
* start
|
|
100
104
|
* stop
|
|
101
105
|
|
|
102
|
-
## ~~
|
|
106
|
+
## ~~DeviceRequestPrompt~~
|
|
103
107
|
|
|
108
|
+
* ~~cancel~~
|
|
109
|
+
* ~~select~~
|
|
110
|
+
* ~~waitForDevice~~
|
|
104
111
|
|
|
105
112
|
## Dialog
|
|
106
113
|
|
|
@@ -116,8 +123,9 @@
|
|
|
116
123
|
* $$ => `#query_selector_all`
|
|
117
124
|
* $$eval => `#eval_on_selector_all`
|
|
118
125
|
* $eval => `#eval_on_selector`
|
|
119
|
-
*
|
|
120
|
-
*
|
|
126
|
+
* ~~asLocator~~
|
|
127
|
+
* ~~autofill~~
|
|
128
|
+
* ~~backendNodeId~~
|
|
121
129
|
* boundingBox => `#bounding_box`
|
|
122
130
|
* boxModel => `#box_model`
|
|
123
131
|
* click
|
|
@@ -130,27 +138,36 @@
|
|
|
130
138
|
* drop
|
|
131
139
|
* focus
|
|
132
140
|
* hover
|
|
141
|
+
* isHidden => `#hidden?`
|
|
133
142
|
* isIntersectingViewport => `#intersecting_viewport?`
|
|
143
|
+
* isVisible => `#visible?`
|
|
134
144
|
* press
|
|
135
145
|
* screenshot
|
|
146
|
+
* ~~scrollIntoView~~
|
|
136
147
|
* select
|
|
137
148
|
* tap
|
|
138
149
|
* toElement => `#to_element`
|
|
150
|
+
* touchEnd => `#touch_end`
|
|
151
|
+
* touchMove => `#touch_move`
|
|
152
|
+
* touchStart => `#touch_start`
|
|
139
153
|
* type => `#type_text`
|
|
140
154
|
* uploadFile => `#upload_file`
|
|
141
155
|
* waitForSelector => `#wait_for_selector`
|
|
142
|
-
* waitForXPath => `#wait_for_xpath`
|
|
143
156
|
|
|
144
157
|
## ~~EventEmitter~~
|
|
145
158
|
|
|
146
|
-
* ~~addListener~~
|
|
147
159
|
* ~~emit~~
|
|
148
160
|
* ~~listenerCount~~
|
|
149
161
|
* ~~off~~
|
|
150
162
|
* ~~on~~
|
|
151
163
|
* ~~once~~
|
|
152
164
|
* ~~removeAllListeners~~
|
|
153
|
-
|
|
165
|
+
|
|
166
|
+
## ~~ExtensionTransport~~
|
|
167
|
+
|
|
168
|
+
* ~~close~~
|
|
169
|
+
* ~~connectTab~~
|
|
170
|
+
* ~~send~~
|
|
154
171
|
|
|
155
172
|
## FileChooser
|
|
156
173
|
|
|
@@ -164,20 +181,19 @@
|
|
|
164
181
|
* $$ => `#query_selector_all`
|
|
165
182
|
* $$eval => `#eval_on_selector_all`
|
|
166
183
|
* $eval => `#eval_on_selector`
|
|
167
|
-
* $x => `#Sx`
|
|
168
184
|
* addScriptTag => `#add_script_tag`
|
|
169
185
|
* addStyleTag => `#add_style_tag`
|
|
170
|
-
* addStyleTag => `#add_style_tag`
|
|
171
186
|
* childFrames => `#child_frames`
|
|
172
187
|
* click
|
|
173
188
|
* content
|
|
174
189
|
* evaluate
|
|
175
190
|
* evaluateHandle => `#evaluate_handle`
|
|
176
191
|
* focus
|
|
192
|
+
* frameElement => `#frame_element`
|
|
177
193
|
* goto
|
|
178
194
|
* hover
|
|
179
195
|
* isDetached => `#detached?`
|
|
180
|
-
*
|
|
196
|
+
* ~~locator~~
|
|
181
197
|
* name
|
|
182
198
|
* page
|
|
183
199
|
* parentFrame => `#parent_frame`
|
|
@@ -190,8 +206,6 @@
|
|
|
190
206
|
* waitForFunction => `#wait_for_function`
|
|
191
207
|
* waitForNavigation => `#wait_for_navigation`
|
|
192
208
|
* waitForSelector => `#wait_for_selector`
|
|
193
|
-
* waitForTimeout => `#wait_for_timeout`
|
|
194
|
-
* waitForXPath => `#wait_for_xpath`
|
|
195
209
|
|
|
196
210
|
## HTTPRequest
|
|
197
211
|
|
|
@@ -201,8 +215,10 @@
|
|
|
201
215
|
* continueRequestOverrides => `#continue_request_overrides`
|
|
202
216
|
* enqueueInterceptAction => `#enqueue_intercept_action`
|
|
203
217
|
* failure
|
|
218
|
+
* fetchPostData => `#fetch_post_data`
|
|
204
219
|
* finalizeInterceptions => `#finalize_interceptions`
|
|
205
220
|
* frame
|
|
221
|
+
* ~~hasPostData~~
|
|
206
222
|
* headers
|
|
207
223
|
* initiator
|
|
208
224
|
* interceptResolutionState => `#intercept_resolution_state`
|
|
@@ -220,6 +236,7 @@
|
|
|
220
236
|
## HTTPResponse
|
|
221
237
|
|
|
222
238
|
* buffer
|
|
239
|
+
* ~~content~~
|
|
223
240
|
* frame
|
|
224
241
|
* ~~fromCache~~
|
|
225
242
|
* ~~fromServiceWorker~~
|
|
@@ -232,7 +249,7 @@
|
|
|
232
249
|
* status
|
|
233
250
|
* statusText => `#status_text`
|
|
234
251
|
* text
|
|
235
|
-
*
|
|
252
|
+
* timing
|
|
236
253
|
* url
|
|
237
254
|
|
|
238
255
|
## JSCoverage
|
|
@@ -248,10 +265,9 @@
|
|
|
248
265
|
* evaluateHandle => `#evaluate_handle`
|
|
249
266
|
* getProperties => `#properties`
|
|
250
267
|
* getProperty => `#[]`
|
|
251
|
-
* getProperty => `#[]`
|
|
252
268
|
* jsonValue => `#json_value`
|
|
253
269
|
* remoteObject => `#remote_object`
|
|
254
|
-
*
|
|
270
|
+
* toString => `#to_s`
|
|
255
271
|
|
|
256
272
|
## Keyboard
|
|
257
273
|
|
|
@@ -261,6 +277,24 @@
|
|
|
261
277
|
* type => `#type_text`
|
|
262
278
|
* up
|
|
263
279
|
|
|
280
|
+
## ~~Locator~~
|
|
281
|
+
|
|
282
|
+
* ~~click~~
|
|
283
|
+
* ~~clone~~
|
|
284
|
+
* ~~fill~~
|
|
285
|
+
* ~~filter~~
|
|
286
|
+
* ~~hover~~
|
|
287
|
+
* ~~map~~
|
|
288
|
+
* ~~race~~
|
|
289
|
+
* ~~scroll~~
|
|
290
|
+
* ~~setEnsureElementIsInTheViewport~~
|
|
291
|
+
* ~~setTimeout~~
|
|
292
|
+
* ~~setVisibility~~
|
|
293
|
+
* ~~setWaitForEnabled~~
|
|
294
|
+
* ~~setWaitForStableBoundingBox~~
|
|
295
|
+
* ~~wait~~
|
|
296
|
+
* ~~waitHandle~~
|
|
297
|
+
|
|
264
298
|
## Mouse
|
|
265
299
|
|
|
266
300
|
* click
|
|
@@ -271,6 +305,7 @@
|
|
|
271
305
|
* dragOver => `#drag_over`
|
|
272
306
|
* drop
|
|
273
307
|
* move
|
|
308
|
+
* reset
|
|
274
309
|
* up
|
|
275
310
|
* wheel
|
|
276
311
|
|
|
@@ -280,11 +315,8 @@
|
|
|
280
315
|
* $$ => `#query_selector_all`
|
|
281
316
|
* $$eval => `#eval_on_selector_all`
|
|
282
317
|
* $eval => `#eval_on_selector`
|
|
283
|
-
* $x => `#Sx`
|
|
284
318
|
* addScriptTag => `#add_script_tag`
|
|
285
319
|
* addStyleTag => `#add_style_tag`
|
|
286
|
-
* addStyleTag => `#add_style_tag`
|
|
287
|
-
* addStyleTag => `#add_style_tag`
|
|
288
320
|
* authenticate
|
|
289
321
|
* bringToFront => `#bring_to_front`
|
|
290
322
|
* browser
|
|
@@ -293,10 +325,12 @@
|
|
|
293
325
|
* close
|
|
294
326
|
* content
|
|
295
327
|
* cookies
|
|
328
|
+
* ~~createCDPSession~~
|
|
296
329
|
* createPDFStream => `#create_pdf_stream`
|
|
297
330
|
* deleteCookie => `#delete_cookie`
|
|
298
331
|
* emulate
|
|
299
332
|
* emulateCPUThrottling => `#emulate_cpu_throttling`
|
|
333
|
+
* ~~emulateFocusedPage~~
|
|
300
334
|
* emulateIdleState => `#emulate_idle_state`
|
|
301
335
|
* emulateMediaFeatures => `#emulate_media_features`
|
|
302
336
|
* emulateMediaType => `#emulate_media_type`
|
|
@@ -309,6 +343,7 @@
|
|
|
309
343
|
* exposeFunction => `#expose_function`
|
|
310
344
|
* focus
|
|
311
345
|
* frames
|
|
346
|
+
* ~~getDefaultNavigationTimeout~~
|
|
312
347
|
* ~~getDefaultTimeout~~
|
|
313
348
|
* goBack => `#go_back`
|
|
314
349
|
* goForward => `#go_forward`
|
|
@@ -317,17 +352,22 @@
|
|
|
317
352
|
* isClosed => `#closed?`
|
|
318
353
|
* isDragInterceptionEnabled => `#drag_interception_enabled?`
|
|
319
354
|
* isJavaScriptEnabled => `#javascript_enabled?`
|
|
355
|
+
* isServiceWorkerBypassed => `#service_worker_bypassed?`
|
|
356
|
+
* ~~locator~~
|
|
320
357
|
* mainFrame => `#main_frame`
|
|
321
358
|
* metrics
|
|
322
|
-
* ~~
|
|
323
|
-
* on
|
|
324
|
-
* once
|
|
359
|
+
* ~~openDevTools~~
|
|
325
360
|
* pdf
|
|
326
361
|
* queryObjects => `#query_objects`
|
|
327
362
|
* reload
|
|
363
|
+
* removeExposedFunction => `#remove_exposed_function`
|
|
364
|
+
* removeScriptToEvaluateOnNewDocument => `#remove_script_to_evaluate_on_new_document`
|
|
365
|
+
* ~~resize~~
|
|
366
|
+
* ~~screencast~~
|
|
328
367
|
* screenshot
|
|
329
368
|
* select
|
|
330
369
|
* setBypassCSP => `#bypass_csp=`
|
|
370
|
+
* ~~setBypassServiceWorker~~
|
|
331
371
|
* setCacheEnabled => `#cache_enabled=`
|
|
332
372
|
* setContent => `#content=`
|
|
333
373
|
* setCookie => `#set_cookie`
|
|
@@ -347,26 +387,24 @@
|
|
|
347
387
|
* type => `#type_text`
|
|
348
388
|
* url
|
|
349
389
|
* viewport
|
|
390
|
+
* ~~waitForDevicePrompt~~
|
|
350
391
|
* waitForFileChooser => `#wait_for_file_chooser`
|
|
351
392
|
* waitForFrame => `#wait_for_frame`
|
|
352
393
|
* waitForFunction => `#wait_for_function`
|
|
353
394
|
* waitForNavigation => `#wait_for_navigation`
|
|
354
|
-
*
|
|
395
|
+
* waitForNetworkIdle => `#wait_for_network_idle`
|
|
355
396
|
* waitForRequest => `#wait_for_request`
|
|
356
397
|
* waitForResponse => `#wait_for_response`
|
|
357
398
|
* waitForSelector => `#wait_for_selector`
|
|
358
|
-
*
|
|
359
|
-
* waitForXPath => `#wait_for_xpath`
|
|
399
|
+
* ~~windowId~~
|
|
360
400
|
* workers
|
|
361
401
|
|
|
362
|
-
## ~~
|
|
402
|
+
## ~~ProtocolError~~
|
|
363
403
|
|
|
364
|
-
* ~~defaultArgs~~
|
|
365
|
-
* ~~executablePath~~
|
|
366
|
-
* ~~launch~~
|
|
367
404
|
|
|
368
|
-
## ~~
|
|
405
|
+
## ~~ScreenRecorder~~
|
|
369
406
|
|
|
407
|
+
* ~~stop~~
|
|
370
408
|
|
|
371
409
|
## ~~SecurityDetails~~
|
|
372
410
|
|
|
@@ -379,6 +417,7 @@
|
|
|
379
417
|
|
|
380
418
|
## Target
|
|
381
419
|
|
|
420
|
+
* ~~asPage~~
|
|
382
421
|
* browser
|
|
383
422
|
* browserContext => `#browser_context`
|
|
384
423
|
* createCDPSession => `#create_cdp_session`
|
|
@@ -386,22 +425,32 @@
|
|
|
386
425
|
* page
|
|
387
426
|
* type
|
|
388
427
|
* url
|
|
389
|
-
*
|
|
428
|
+
* worker
|
|
390
429
|
|
|
391
430
|
## TimeoutError
|
|
392
431
|
|
|
393
432
|
|
|
394
|
-
##
|
|
433
|
+
## TouchError
|
|
395
434
|
|
|
396
|
-
|
|
435
|
+
|
|
436
|
+
## Touchscreen
|
|
437
|
+
|
|
438
|
+
* tap
|
|
439
|
+
* touchEnd => `#touch_end`
|
|
440
|
+
* touchMove => `#touch_move`
|
|
441
|
+
* touchStart => `#touch_start`
|
|
397
442
|
|
|
398
443
|
## Tracing
|
|
399
444
|
|
|
400
445
|
* start
|
|
401
446
|
* stop
|
|
402
447
|
|
|
403
|
-
## ~~
|
|
448
|
+
## ~~UnsupportedOperation~~
|
|
449
|
+
|
|
404
450
|
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
*
|
|
451
|
+
## WebWorker
|
|
452
|
+
|
|
453
|
+
* close
|
|
454
|
+
* evaluate
|
|
455
|
+
* evaluateHandle => `#evaluate_handle`
|
|
456
|
+
* url
|
|
@@ -48,7 +48,7 @@ class Puppeteer::AriaQueryHandler
|
|
|
48
48
|
end
|
|
49
49
|
end
|
|
50
50
|
|
|
51
|
-
def wait_for(element_or_frame, selector, visible: nil, hidden: nil, timeout: nil)
|
|
51
|
+
def wait_for(element_or_frame, selector, visible: nil, hidden: nil, timeout: nil, polling: nil)
|
|
52
52
|
case element_or_frame
|
|
53
53
|
when Puppeteer::Frame
|
|
54
54
|
frame = element_or_frame
|
|
@@ -80,6 +80,7 @@ class Puppeteer::AriaQueryHandler
|
|
|
80
80
|
visible: visible,
|
|
81
81
|
hidden: hidden,
|
|
82
82
|
timeout: timeout,
|
|
83
|
+
polling: polling,
|
|
83
84
|
binding_function: binding_function,
|
|
84
85
|
)
|
|
85
86
|
|
|
@@ -103,7 +104,7 @@ class Puppeteer::AriaQueryHandler
|
|
|
103
104
|
promises = res.map do |ax_node|
|
|
104
105
|
world.send(:async_adopt_backend_node, ax_node['backendDOMNodeId'])
|
|
105
106
|
end
|
|
106
|
-
|
|
107
|
+
Puppeteer::AsyncUtils.await_promise_all(*promises)
|
|
107
108
|
end
|
|
108
109
|
end
|
|
109
110
|
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "async"
|
|
4
|
+
require "async/barrier"
|
|
5
|
+
require "async/promise"
|
|
6
|
+
|
|
7
|
+
module Puppeteer
|
|
8
|
+
# Async helpers for Promise-style coordination using socketry/async.
|
|
9
|
+
module AsyncUtils
|
|
10
|
+
extend self
|
|
11
|
+
|
|
12
|
+
def await(task)
|
|
13
|
+
if task.is_a?(Proc)
|
|
14
|
+
task.call
|
|
15
|
+
elsif task.is_a?(Async::Promise)
|
|
16
|
+
current_task = Async::Task.current?
|
|
17
|
+
if current_task
|
|
18
|
+
until task.resolved?
|
|
19
|
+
current_task.sleep(0.001)
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
task.wait
|
|
23
|
+
elsif task.respond_to?(:wait)
|
|
24
|
+
task.wait
|
|
25
|
+
else
|
|
26
|
+
task
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# Execute a task with a timeout using Async::Task#with_timeout.
|
|
31
|
+
# @param timeout_ms [Numeric] Timeout duration in milliseconds (0 means no timeout)
|
|
32
|
+
# @param task [Proc, Async::Promise, nil] Task to execute; falls back to block
|
|
33
|
+
# @yield [async_task] Execute a task within the timeout, optionally receiving Async::Task
|
|
34
|
+
# @return [Async::Task] Async task that resolves/rejects once the operation completes
|
|
35
|
+
def async_timeout(timeout_ms, task = nil, &block)
|
|
36
|
+
if task
|
|
37
|
+
runner = lambda do |async_task|
|
|
38
|
+
if timeout_ms == 0
|
|
39
|
+
if task.is_a?(Proc)
|
|
40
|
+
args = task.arity.positive? ? [async_task] : []
|
|
41
|
+
task.call(*args)
|
|
42
|
+
else
|
|
43
|
+
await(task)
|
|
44
|
+
end
|
|
45
|
+
else
|
|
46
|
+
timeout_seconds = timeout_ms / 1000.0
|
|
47
|
+
async_task.with_timeout(timeout_seconds) do
|
|
48
|
+
if task.is_a?(Proc)
|
|
49
|
+
args = task.arity.positive? ? [async_task] : []
|
|
50
|
+
task.call(*args)
|
|
51
|
+
else
|
|
52
|
+
await(task)
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
elsif block
|
|
58
|
+
runner = lambda do |async_task|
|
|
59
|
+
if timeout_ms == 0
|
|
60
|
+
args = block.arity.positive? ? [async_task] : []
|
|
61
|
+
await(block.call(*args))
|
|
62
|
+
else
|
|
63
|
+
timeout_seconds = timeout_ms / 1000.0
|
|
64
|
+
async_task.with_timeout(timeout_seconds) do
|
|
65
|
+
args = block.arity.positive? ? [async_task] : []
|
|
66
|
+
await(block.call(*args))
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
else
|
|
71
|
+
raise ArgumentError.new("AsyncUtils.async_timeout requires a task or block")
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
current_task = Async::Task.current?
|
|
75
|
+
if current_task
|
|
76
|
+
return current_task.async do |async_task|
|
|
77
|
+
runner.call(async_task)
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
result = nil
|
|
82
|
+
error = nil
|
|
83
|
+
Async do |async_task|
|
|
84
|
+
result = runner.call(async_task)
|
|
85
|
+
rescue => err
|
|
86
|
+
error = err
|
|
87
|
+
end.wait
|
|
88
|
+
|
|
89
|
+
ImmediateTask.new(result, error)
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
# Wait for all async tasks to complete and return results.
|
|
93
|
+
def await_promise_all(*tasks)
|
|
94
|
+
Sync { zip(*tasks) }
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
# Race multiple async tasks and return the result of the first one to complete.
|
|
98
|
+
def await_promise_race(*tasks)
|
|
99
|
+
Sync { first(*tasks) }
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def future_with_logging(&block)
|
|
103
|
+
proc do |*block_args|
|
|
104
|
+
block.call(*block_args)
|
|
105
|
+
rescue ::Puppeteer::TimeoutError
|
|
106
|
+
raise
|
|
107
|
+
rescue => err
|
|
108
|
+
warn("#{err.message} (#{err.class})")
|
|
109
|
+
raise err
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def sleep_seconds(duration)
|
|
114
|
+
task = Async::Task.current
|
|
115
|
+
if task
|
|
116
|
+
task.sleep(duration)
|
|
117
|
+
else
|
|
118
|
+
Kernel.sleep(duration)
|
|
119
|
+
end
|
|
120
|
+
rescue RuntimeError, NoMethodError
|
|
121
|
+
Kernel.sleep(duration)
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
class ImmediateTask
|
|
125
|
+
def initialize(result, error)
|
|
126
|
+
@result = result
|
|
127
|
+
@error = error
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
def wait
|
|
131
|
+
raise @error if @error
|
|
132
|
+
|
|
133
|
+
@result
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
private def zip(*tasks)
|
|
138
|
+
barrier = Async::Barrier.new
|
|
139
|
+
results = Array.new(tasks.size)
|
|
140
|
+
|
|
141
|
+
begin
|
|
142
|
+
tasks.each_with_index do |task, index|
|
|
143
|
+
barrier.async do
|
|
144
|
+
results[index] = await(task)
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
barrier.wait
|
|
149
|
+
results
|
|
150
|
+
rescue Exception
|
|
151
|
+
drain_barrier_tasks(barrier)
|
|
152
|
+
raise
|
|
153
|
+
end
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
private def first(*tasks)
|
|
157
|
+
barrier = Async::Barrier.new
|
|
158
|
+
result = nil
|
|
159
|
+
|
|
160
|
+
begin
|
|
161
|
+
tasks.each do |task|
|
|
162
|
+
barrier.async(finished: false) do
|
|
163
|
+
await(task)
|
|
164
|
+
end
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
barrier.wait do |completed_task|
|
|
168
|
+
result = completed_task.wait
|
|
169
|
+
break
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
result
|
|
173
|
+
ensure
|
|
174
|
+
drain_barrier_tasks(barrier)
|
|
175
|
+
end
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
private def drain_barrier_tasks(barrier)
|
|
179
|
+
pending = barrier.tasks.to_a
|
|
180
|
+
return if pending.empty?
|
|
181
|
+
|
|
182
|
+
barrier.stop
|
|
183
|
+
pending.each do |waiting|
|
|
184
|
+
task = waiting.task
|
|
185
|
+
next unless task.completed? || task.failed? || task.stopped?
|
|
186
|
+
|
|
187
|
+
begin
|
|
188
|
+
task.wait
|
|
189
|
+
rescue StandardError
|
|
190
|
+
# The race winner is already decided; ignore losers' errors.
|
|
191
|
+
end
|
|
192
|
+
end
|
|
193
|
+
end
|
|
194
|
+
end
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
module AsyncPromiseWaitRetry
|
|
198
|
+
def wait(...)
|
|
199
|
+
loop do
|
|
200
|
+
begin
|
|
201
|
+
return super
|
|
202
|
+
rescue ThreadError => e
|
|
203
|
+
raise unless e.message == 'Attempt to unlock a mutex which is not locked'
|
|
204
|
+
next unless resolved?
|
|
205
|
+
|
|
206
|
+
value = self.value
|
|
207
|
+
raise value if value.is_a?(Exception)
|
|
208
|
+
return value
|
|
209
|
+
end
|
|
210
|
+
end
|
|
211
|
+
end
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
Async::Promise.prepend(AsyncPromiseWaitRetry)
|