puppeteer-ruby 0.38.0 → 0.40.2
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 +2 -0
- data/CHANGELOG.md +29 -1
- data/docs/api_coverage.md +5 -2
- data/lib/puppeteer/aria_query_handler.rb +8 -5
- data/lib/puppeteer/browser_runner.rb +21 -10
- data/lib/puppeteer/custom_query_handler.rb +2 -2
- data/lib/puppeteer/dom_world.rb +12 -8
- data/lib/puppeteer/element_handle.rb +54 -0
- data/lib/puppeteer/events.rb +1 -0
- data/lib/puppeteer/frame_manager.rb +1 -1
- data/lib/puppeteer/http_response.rb +25 -4
- data/lib/puppeteer/js_handle.rb +8 -0
- data/lib/puppeteer/launcher/chrome.rb +48 -32
- data/lib/puppeteer/launcher/firefox.rb +256 -226
- data/lib/puppeteer/launcher/launch_options.rb +2 -1
- data/lib/puppeteer/network_event_manager.rb +122 -0
- data/lib/puppeteer/network_manager.rb +180 -40
- data/lib/puppeteer/query_handler_manager.rb +2 -2
- data/lib/puppeteer/version.rb +1 -1
- data/lib/puppeteer/wait_task.rb +10 -7
- data/lib/puppeteer.rb +1 -0
- data/puppeteer-ruby.gemspec +2 -2
- metadata +8 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e88033f07007a1841f99535a96497bef2aa35b58e0599d51886ec760ef8f8201
|
4
|
+
data.tar.gz: 3b4b69f023861cc24a4ecf402e2b6eff0cba0d57fbef37991996964a1b57007b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6e63bd3b526e4cc09f309fc206f9395618393ab104438e93eebc190e3efa36a7e12e3037388480b9dd735121f752cbbd0bd5dc1152ae39a57be6f855dc41b41f
|
7
|
+
data.tar.gz: fe6dff5b5b82813c003e67725868a467e2e9b43e16c4bf4bca1eb48c588daa2efd782d4c1c6b351117a3cfbf7daea4feb37b36fde3637abacea33cd2e3244cb4
|
data/.rubocop.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,7 +1,35 @@
|
|
1
|
-
### main [[diff](https://github.com/YusukeIwaki/puppeteer-ruby/compare/0.
|
1
|
+
### main [[diff](https://github.com/YusukeIwaki/puppeteer-ruby/compare/0.40.2...main)]
|
2
2
|
|
3
3
|
- xxx
|
4
4
|
|
5
|
+
### 0.40.2 [[diff](https://github.com/YusukeIwaki/puppeteer-ruby/compare/0.40.1...0.40.2)]
|
6
|
+
|
7
|
+
Bugfix:
|
8
|
+
|
9
|
+
- Fix crash on setting response listener [#195](https://github.com/YusukeIwaki/puppeteer-ruby/pull/195)
|
10
|
+
|
11
|
+
### 0.40.1 [[diff](https://github.com/YusukeIwaki/puppeteer-ruby/compare/0.40.0...0.40.1)]
|
12
|
+
|
13
|
+
Bugfix:
|
14
|
+
|
15
|
+
- Fix error on reload [#190](https://github.com/YusukeIwaki/puppeteer-ruby/pull/190)
|
16
|
+
- Fix error message on failing to find Chrome executable.
|
17
|
+
- Fix apidoc
|
18
|
+
|
19
|
+
### 0.40.0 [[diff](https://github.com/YusukeIwaki/puppeteer-ruby/compare/0.39.0...0.40.0)]
|
20
|
+
|
21
|
+
New features:
|
22
|
+
|
23
|
+
- Puppeteer 13.0, 13.1 functionalities
|
24
|
+
- Support Ruby 3.1
|
25
|
+
|
26
|
+
|
27
|
+
### 0.39.0 [[diff](https://github.com/YusukeIwaki/puppeteer-ruby/compare/0.38.0...0.39.0)]
|
28
|
+
|
29
|
+
New features:
|
30
|
+
|
31
|
+
- Puppeteer 12.0 functionalities
|
32
|
+
|
5
33
|
### 0.38.0 [[diff](https://github.com/YusukeIwaki/puppeteer-ruby/compare/0.37.4...0.38.0)]
|
6
34
|
|
7
35
|
New features:
|
data/docs/api_coverage.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# API coverages
|
2
|
-
- Puppeteer version:
|
3
|
-
- puppeteer-ruby version: 0.
|
2
|
+
- Puppeteer version: v13.0.1
|
3
|
+
- puppeteer-ruby version: 0.40.2
|
4
4
|
|
5
5
|
## Puppeteer
|
6
6
|
|
@@ -296,6 +296,7 @@
|
|
296
296
|
* ~~toString~~
|
297
297
|
* type => `#type_text`
|
298
298
|
* uploadFile => `#upload_file`
|
299
|
+
* waitForSelector => `#wait_for_selector`
|
299
300
|
|
300
301
|
## HTTPRequest
|
301
302
|
|
@@ -309,6 +310,8 @@
|
|
309
310
|
* frame
|
310
311
|
* headers
|
311
312
|
* initiator
|
313
|
+
* ~~interceptResolutionState~~
|
314
|
+
* ~~isInterceptResolutionHandled~~
|
312
315
|
* isNavigationRequest => `#navigation_request?`
|
313
316
|
* method
|
314
317
|
* postData => `#post_data`
|
@@ -7,10 +7,10 @@ class Puppeteer::AriaQueryHandler
|
|
7
7
|
private def parse_aria_selector(selector)
|
8
8
|
known_attributes = %w(name role)
|
9
9
|
query_options = {}
|
10
|
-
attribute_regexp = /\[\s*(?<attribute>\w+)\s*=\s*"(?<value
|
10
|
+
attribute_regexp = /\[\s*(?<attribute>\w+)\s*=\s*(?<quote>"|')(?<value>\\.|.*?(?=\k<quote>))\k<quote>\s*\]/
|
11
11
|
default_name = selector.gsub(attribute_regexp) do
|
12
12
|
attribute = $1.strip
|
13
|
-
value = $
|
13
|
+
value = $3
|
14
14
|
unless known_attributes.include?(attribute)
|
15
15
|
raise ArgumentError.new("Unkown aria attribute \"#{attribute}\" in selector")
|
16
16
|
end
|
@@ -36,10 +36,11 @@ class Puppeteer::AriaQueryHandler
|
|
36
36
|
end
|
37
37
|
end
|
38
38
|
|
39
|
-
def wait_for(dom_world, selector, visible: nil, hidden: nil, timeout: nil)
|
39
|
+
def wait_for(dom_world, selector, visible: nil, hidden: nil, timeout: nil, root: nil)
|
40
|
+
# addHandlerToWorld
|
40
41
|
binding_function = Puppeteer::DOMWorld::BindingFunction.new(
|
41
42
|
name: 'ariaQuerySelector',
|
42
|
-
proc: -> (
|
43
|
+
proc: -> (sel) { query_one(root || dom_world.send(:document), sel) },
|
43
44
|
)
|
44
45
|
dom_world.send(:wait_for_selector_in_page,
|
45
46
|
'(_, selector) => globalThis.ariaQuerySelector(selector)',
|
@@ -47,7 +48,9 @@ class Puppeteer::AriaQueryHandler
|
|
47
48
|
visible: visible,
|
48
49
|
hidden: hidden,
|
49
50
|
timeout: timeout,
|
50
|
-
binding_function: binding_function
|
51
|
+
binding_function: binding_function,
|
52
|
+
root: root,
|
53
|
+
)
|
51
54
|
end
|
52
55
|
|
53
56
|
def query_all(element, selector)
|
@@ -4,13 +4,17 @@ require 'timeout'
|
|
4
4
|
|
5
5
|
# https://github.com/puppeteer/puppeteer/blob/master/lib/Launcher.js
|
6
6
|
class Puppeteer::BrowserRunner
|
7
|
+
include Puppeteer::DebugPrint
|
8
|
+
|
7
9
|
# @param {string} executablePath
|
8
10
|
# @param {!Array<string>} processArguments
|
9
11
|
# @param {string=} tempDirectory
|
10
|
-
def initialize(executable_path, process_arguments,
|
12
|
+
def initialize(for_firefox, executable_path, process_arguments, user_data_dir, using_temp_user_data_dir)
|
13
|
+
@for_firefox = for_firefox
|
11
14
|
@executable_path = executable_path
|
12
15
|
@process_arguments = process_arguments
|
13
|
-
@
|
16
|
+
@user_data_dir = user_data_dir
|
17
|
+
@using_temp_user_data_dir = using_temp_user_data_dir
|
14
18
|
@proc = nil
|
15
19
|
@connection = nil
|
16
20
|
@closed = true
|
@@ -90,8 +94,8 @@ class Puppeteer::BrowserRunner
|
|
90
94
|
@process_closing = -> {
|
91
95
|
@proc.dispose
|
92
96
|
@closed = true
|
93
|
-
if @
|
94
|
-
FileUtils.rm_rf(@
|
97
|
+
if @using_temp_user_data_dir
|
98
|
+
FileUtils.rm_rf(@user_data_dir)
|
95
99
|
end
|
96
100
|
}
|
97
101
|
at_exit do
|
@@ -122,7 +126,7 @@ class Puppeteer::BrowserRunner
|
|
122
126
|
def close
|
123
127
|
return if @closed
|
124
128
|
|
125
|
-
if @
|
129
|
+
if @using_temp_user_data_dir && !@for_firefox
|
126
130
|
kill
|
127
131
|
elsif @connection
|
128
132
|
begin
|
@@ -137,11 +141,18 @@ class Puppeteer::BrowserRunner
|
|
137
141
|
|
138
142
|
# @return {Promise}
|
139
143
|
def kill
|
140
|
-
if
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
144
|
+
# If the process failed to launch (for example if the browser executable path
|
145
|
+
# is invalid), then the process does not get a pid assigned. A call to
|
146
|
+
# `proc.kill` would error, as the `pid` to-be-killed can not be found.
|
147
|
+
@proc&.kill
|
148
|
+
|
149
|
+
# Attempt to remove temporary profile directory to avoid littering.
|
150
|
+
begin
|
151
|
+
if @using_temp_user_data_dir
|
152
|
+
FileUtils.rm_rf(@user_data_dir)
|
153
|
+
end
|
154
|
+
rescue => err
|
155
|
+
debug_puts(err)
|
145
156
|
end
|
146
157
|
end
|
147
158
|
|
@@ -21,12 +21,12 @@ class Puppeteer::CustomQueryHandler
|
|
21
21
|
nil
|
22
22
|
end
|
23
23
|
|
24
|
-
def wait_for(dom_world, selector, visible: nil, hidden: nil, timeout: nil)
|
24
|
+
def wait_for(dom_world, selector, visible: nil, hidden: nil, timeout: nil, root: nil)
|
25
25
|
unless @query_one
|
26
26
|
raise NotImplementedError.new("#{self.class}##{__method__} is not implemented.")
|
27
27
|
end
|
28
28
|
|
29
|
-
dom_world.send(:wait_for_selector_in_page, @query_one, selector, visible: visible, hidden: hidden, timeout: timeout)
|
29
|
+
dom_world.send(:wait_for_selector_in_page, @query_one, selector, visible: visible, hidden: hidden, timeout: timeout, root: root)
|
30
30
|
end
|
31
31
|
|
32
32
|
def query_all(element, selector)
|
data/lib/puppeteer/dom_world.rb
CHANGED
@@ -420,10 +420,10 @@ class Puppeteer::DOMWorld
|
|
420
420
|
# @param visible [Boolean] Wait for element visible (not 'display: none' nor 'visibility: hidden') on true. default to false.
|
421
421
|
# @param hidden [Boolean] Wait for element invisible ('display: none' nor 'visibility: hidden') on true. default to false.
|
422
422
|
# @param timeout [Integer]
|
423
|
-
def wait_for_selector(selector, visible: nil, hidden: nil, timeout: nil)
|
423
|
+
def wait_for_selector(selector, visible: nil, hidden: nil, timeout: nil, root: nil)
|
424
424
|
# call wait_for_selector_in_page with custom query selector.
|
425
425
|
query_selector_manager = Puppeteer::QueryHandlerManager.instance
|
426
|
-
query_selector_manager.detect_query_handler(selector).wait_for(self, visible: visible, hidden: hidden, timeout: timeout)
|
426
|
+
query_selector_manager.detect_query_handler(selector).wait_for(self, visible: visible, hidden: hidden, timeout: timeout, root: root)
|
427
427
|
end
|
428
428
|
|
429
429
|
private def binding_identifier(name, context)
|
@@ -497,10 +497,11 @@ class Puppeteer::DOMWorld
|
|
497
497
|
# @param visible [Boolean] Wait for element visible (not 'display: none' nor 'visibility: hidden') on true. default to false.
|
498
498
|
# @param hidden [Boolean] Wait for element invisible ('display: none' nor 'visibility: hidden') on true. default to false.
|
499
499
|
# @param timeout [Integer]
|
500
|
-
private def wait_for_selector_in_page(query_one, selector, visible: nil, hidden: nil, timeout: nil, binding_function: nil)
|
500
|
+
private def wait_for_selector_in_page(query_one, selector, visible: nil, hidden: nil, timeout: nil, root: nil, binding_function: nil)
|
501
501
|
option_wait_for_visible = visible || false
|
502
502
|
option_wait_for_hidden = hidden || false
|
503
503
|
option_timeout = timeout || @timeout_settings.timeout
|
504
|
+
option_root = root
|
504
505
|
|
505
506
|
polling =
|
506
507
|
if option_wait_for_visible || option_wait_for_hidden
|
@@ -511,11 +512,11 @@ class Puppeteer::DOMWorld
|
|
511
512
|
title = "selector #{selector}#{option_wait_for_hidden ? 'to be hidden' : ''}"
|
512
513
|
|
513
514
|
selector_predicate = make_predicate_string(
|
514
|
-
predicate_arg_def: '(selector, waitForVisible, waitForHidden)',
|
515
|
+
predicate_arg_def: '(root, selector, waitForVisible, waitForHidden)',
|
515
516
|
predicate_query_handler: query_one,
|
516
517
|
async: true,
|
517
518
|
predicate_body: <<~JAVASCRIPT
|
518
|
-
const node = await predicateQueryHandler(
|
519
|
+
const node = await predicateQueryHandler(root, selector)
|
519
520
|
return checkWaitForOptions(node, waitForVisible, waitForHidden);
|
520
521
|
JAVASCRIPT
|
521
522
|
)
|
@@ -527,6 +528,7 @@ class Puppeteer::DOMWorld
|
|
527
528
|
polling: polling,
|
528
529
|
timeout: option_timeout,
|
529
530
|
args: [selector, option_wait_for_visible, option_wait_for_hidden],
|
531
|
+
root: option_root,
|
530
532
|
binding_function: binding_function,
|
531
533
|
)
|
532
534
|
handle = wait_task.await_promise
|
@@ -541,10 +543,11 @@ class Puppeteer::DOMWorld
|
|
541
543
|
# @param visible [Boolean] Wait for element visible (not 'display: none' nor 'visibility: hidden') on true. default to false.
|
542
544
|
# @param hidden [Boolean] Wait for element invisible ('display: none' nor 'visibility: hidden') on true. default to false.
|
543
545
|
# @param timeout [Integer]
|
544
|
-
def wait_for_xpath(xpath, visible: nil, hidden: nil, timeout: nil)
|
546
|
+
def wait_for_xpath(xpath, visible: nil, hidden: nil, timeout: nil, root: nil)
|
545
547
|
option_wait_for_visible = visible || false
|
546
548
|
option_wait_for_hidden = hidden || false
|
547
549
|
option_timeout = timeout || @timeout_settings.timeout
|
550
|
+
option_root = root
|
548
551
|
|
549
552
|
polling =
|
550
553
|
if option_wait_for_visible || option_wait_for_hidden
|
@@ -555,9 +558,9 @@ class Puppeteer::DOMWorld
|
|
555
558
|
title = "XPath #{xpath}#{option_wait_for_hidden ? 'to be hidden' : ''}"
|
556
559
|
|
557
560
|
xpath_predicate = make_predicate_string(
|
558
|
-
predicate_arg_def: '(selector, waitForVisible, waitForHidden)',
|
561
|
+
predicate_arg_def: '(root, selector, waitForVisible, waitForHidden)',
|
559
562
|
predicate_body: <<~JAVASCRIPT
|
560
|
-
const node = document.evaluate(selector,
|
563
|
+
const node = document.evaluate(selector, root, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
|
561
564
|
return checkWaitForOptions(node, waitForVisible, waitForHidden);
|
562
565
|
JAVASCRIPT
|
563
566
|
)
|
@@ -569,6 +572,7 @@ class Puppeteer::DOMWorld
|
|
569
572
|
polling: polling,
|
570
573
|
timeout: option_timeout,
|
571
574
|
args: [xpath, option_wait_for_visible, option_wait_for_hidden],
|
575
|
+
root: option_root,
|
572
576
|
)
|
573
577
|
handle = wait_task.await_promise
|
574
578
|
unless handle.as_element
|
@@ -20,6 +20,60 @@ class Puppeteer::ElementHandle < Puppeteer::JSHandle
|
|
20
20
|
@disposed = false
|
21
21
|
end
|
22
22
|
|
23
|
+
def inspect
|
24
|
+
values = %i[context remote_object page disposed].map do |sym|
|
25
|
+
value = instance_variable_get(:"@#{sym}")
|
26
|
+
"@#{sym}=#{value}"
|
27
|
+
end
|
28
|
+
"#<Puppeteer::ElementHandle #{values.join(' ')}>"
|
29
|
+
end
|
30
|
+
|
31
|
+
#
|
32
|
+
# Wait for the `selector` to appear within the element. If at the moment of calling the
|
33
|
+
# method the `selector` already exists, the method will return immediately. If
|
34
|
+
# the `selector` doesn't appear after the `timeout` milliseconds of waiting, the
|
35
|
+
# function will throw.
|
36
|
+
#
|
37
|
+
# This method does not work across navigations or if the element is detached from DOM.
|
38
|
+
#
|
39
|
+
# @param selector - A
|
40
|
+
# {@link https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors | selector}
|
41
|
+
# of an element to wait for
|
42
|
+
# @param options - Optional waiting parameters
|
43
|
+
# @returns Promise which resolves when element specified by selector string
|
44
|
+
# is added to DOM. Resolves to `null` if waiting for hidden: `true` and
|
45
|
+
# selector is not found in DOM.
|
46
|
+
# @remarks
|
47
|
+
# The optional parameters in `options` are:
|
48
|
+
#
|
49
|
+
# - `visible`: wait for the selected element to be present in DOM and to be
|
50
|
+
# visible, i.e. to not have `display: none` or `visibility: hidden` CSS
|
51
|
+
# properties. Defaults to `false`.
|
52
|
+
#
|
53
|
+
# - `hidden`: wait for the selected element to not be found in the DOM or to be hidden,
|
54
|
+
# i.e. have `display: none` or `visibility: hidden` CSS properties. Defaults to
|
55
|
+
# `false`.
|
56
|
+
#
|
57
|
+
# - `timeout`: maximum time to wait in milliseconds. Defaults to `30000`
|
58
|
+
# (30 seconds). Pass `0` to disable timeout. The default value can be changed
|
59
|
+
# by using the {@link Page.setDefaultTimeout} method.
|
60
|
+
def wait_for_selector(selector, visible: nil, hidden: nil, timeout: nil)
|
61
|
+
frame = @context.frame
|
62
|
+
|
63
|
+
secondary_world = frame.secondary_world
|
64
|
+
adopted_root = secondary_world.execution_context.adopt_element_handle(self)
|
65
|
+
handle = secondary_world.wait_for_selector(selector, visible: visible, hidden: hidden, timeout: timeout, root: adopted_root)
|
66
|
+
adopted_root.dispose
|
67
|
+
return nil unless handle
|
68
|
+
|
69
|
+
main_world = frame.main_world
|
70
|
+
result = main_world.execution_context.adopt_element_handle(handle)
|
71
|
+
handle.dispose
|
72
|
+
result
|
73
|
+
end
|
74
|
+
|
75
|
+
define_async_method :async_wait_for_selector
|
76
|
+
|
23
77
|
def as_element
|
24
78
|
self
|
25
79
|
end
|
data/lib/puppeteer/events.rb
CHANGED
@@ -81,6 +81,7 @@ module NetworkManagerEmittedEvents ; end
|
|
81
81
|
|
82
82
|
{
|
83
83
|
Request: EventsDefinitionUtils.symbol('NetworkManager.Request'),
|
84
|
+
RequestServedFromCache: EventsDefinitionUtils.symbol('NetworkManager.RequestServedFromCache'),
|
84
85
|
Response: EventsDefinitionUtils.symbol('NetworkManager.Response'),
|
85
86
|
RequestFailed: EventsDefinitionUtils.symbol('NetworkManager.RequestFailed'),
|
86
87
|
RequestFinished: EventsDefinitionUtils.symbol('NetworkManager.RequestFinished'),
|
@@ -382,7 +382,7 @@ class Puppeteer::FrameManager
|
|
382
382
|
@isolated_worlds << context_payload['name']
|
383
383
|
end
|
384
384
|
|
385
|
-
context = Puppeteer::ExecutionContext.new(frame
|
385
|
+
context = Puppeteer::ExecutionContext.new(frame&._client || @client, context_payload, world)
|
386
386
|
if world
|
387
387
|
world.context = context
|
388
388
|
end
|
@@ -31,7 +31,8 @@ class Puppeteer::HTTPResponse
|
|
31
31
|
# @param client [Puppeteer::CDPSession]
|
32
32
|
# @param request [Puppeteer::HTTPRequest]
|
33
33
|
# @param response_payload [Hash]
|
34
|
-
|
34
|
+
# @param extra_info [Hash|nil]
|
35
|
+
def initialize(client, request, response_payload, extra_info)
|
35
36
|
@client = client
|
36
37
|
@request = request
|
37
38
|
|
@@ -41,14 +42,15 @@ class Puppeteer::HTTPResponse
|
|
41
42
|
port: response_payload['remotePort'],
|
42
43
|
)
|
43
44
|
|
44
|
-
@
|
45
|
-
@status_text = response_payload['statusText']
|
45
|
+
@status_text = parse_štatus_text_from_extra_info(extra_info) || response_payload['statusText']
|
46
46
|
@url = request.url
|
47
47
|
@from_disk_cache = !!response_payload['fromDiskCache']
|
48
48
|
@from_service_worker = !!response_payload['fromServiceWorker']
|
49
49
|
|
50
|
+
@status = extra_info ? extra_info['statusCode'] : response_payload['status']
|
50
51
|
@headers = {}
|
51
|
-
|
52
|
+
headers = extra_info ? extra_info['headers'] : response_payload['headers']
|
53
|
+
headers.each do |key, value|
|
52
54
|
@headers[key.downcase] = value
|
53
55
|
end
|
54
56
|
@security_details = if_present(response_payload['securityDetails']) do |security_payload|
|
@@ -62,6 +64,25 @@ class Puppeteer::HTTPResponse
|
|
62
64
|
|
63
65
|
attr_reader :remote_address, :url, :status, :status_text, :headers, :security_details, :request
|
64
66
|
|
67
|
+
def inspect
|
68
|
+
values = %i[remote_address url status status_text headers security_details request].map do |sym|
|
69
|
+
value = instance_variable_get(:"@#{sym}")
|
70
|
+
"@#{sym}=#{value}"
|
71
|
+
end
|
72
|
+
"#<Puppeteer::HTTPRequest #{values.join(' ')}>"
|
73
|
+
end
|
74
|
+
|
75
|
+
private def parse_štatus_text_from_extra_info(extra_info)
|
76
|
+
return nil if !extra_info || !extra_info['headersText']
|
77
|
+
first_line = extra_info['headersText'].split("\r").first
|
78
|
+
return nil unless first_line
|
79
|
+
/[^ ]* [^ ]* (.*)/.match(first_line) do |m|
|
80
|
+
return m[1]
|
81
|
+
end
|
82
|
+
|
83
|
+
nil
|
84
|
+
end
|
85
|
+
|
65
86
|
# @return [Boolean]
|
66
87
|
def ok?
|
67
88
|
@status == 0 || (@status >= 200 && @status <= 299)
|
data/lib/puppeteer/js_handle.rb
CHANGED
@@ -36,6 +36,14 @@ class Puppeteer::JSHandle
|
|
36
36
|
|
37
37
|
attr_reader :context, :remote_object
|
38
38
|
|
39
|
+
def inspect
|
40
|
+
values = %i[context remote_object disposed].map do |sym|
|
41
|
+
value = instance_variable_get(:"@#{sym}")
|
42
|
+
"@#{sym}=#{value}"
|
43
|
+
end
|
44
|
+
"#<Puppeteer::JSHandle #{values.join(' ')}>"
|
45
|
+
end
|
46
|
+
|
39
47
|
# @return [Puppeteer::ExecutionContext]
|
40
48
|
def execution_context
|
41
49
|
@context
|
@@ -27,9 +27,6 @@ module Puppeteer::Launcher
|
|
27
27
|
@chrome_arg_options.args.dup
|
28
28
|
end
|
29
29
|
|
30
|
-
#
|
31
|
-
# let temporaryUserDataDir = null;
|
32
|
-
|
33
30
|
if chrome_arguments.none? { |arg| arg.start_with?('--remote-debugging-') }
|
34
31
|
if @launch_options.pipe?
|
35
32
|
chrome_arguments << '--remote-debugging-pipe'
|
@@ -38,10 +35,17 @@ module Puppeteer::Launcher
|
|
38
35
|
end
|
39
36
|
end
|
40
37
|
|
41
|
-
|
42
|
-
if
|
43
|
-
|
44
|
-
|
38
|
+
user_data_dir = chrome_arguments.find { |arg| arg.start_with?('--user-data-dir') }
|
39
|
+
if user_data_dir
|
40
|
+
user_data_dir = user_data_dir.split('=').last
|
41
|
+
unless File.exist?(user_data_dir)
|
42
|
+
raise ArgumentError.new("Chrome user data dir not found at '#{user_data_dir}'")
|
43
|
+
end
|
44
|
+
using_temp_user_data_dir = false
|
45
|
+
else
|
46
|
+
user_data_dir = Dir.mktmpdir('puppeteer_dev_chrome_profile-', ENV['PUPPETEER_TMP_DIR'])
|
47
|
+
chrome_arguments << "--user-data-dir=#{user_data_dir}"
|
48
|
+
using_temp_user_data_dir = true
|
45
49
|
end
|
46
50
|
|
47
51
|
chrome_executable =
|
@@ -51,7 +55,13 @@ module Puppeteer::Launcher
|
|
51
55
|
@launch_options.executable_path || fallback_executable_path
|
52
56
|
end
|
53
57
|
use_pipe = chrome_arguments.include?('--remote-debugging-pipe')
|
54
|
-
runner = Puppeteer::BrowserRunner.new(
|
58
|
+
runner = Puppeteer::BrowserRunner.new(
|
59
|
+
false,
|
60
|
+
chrome_executable,
|
61
|
+
chrome_arguments,
|
62
|
+
user_data_dir,
|
63
|
+
using_temp_user_data_dir,
|
64
|
+
)
|
55
65
|
runner.start(
|
56
66
|
handle_SIGHUP: @launch_options.handle_SIGHUP?,
|
57
67
|
handle_SIGTERM: @launch_options.handle_SIGTERM?,
|
@@ -61,33 +71,39 @@ module Puppeteer::Launcher
|
|
61
71
|
pipe: use_pipe,
|
62
72
|
)
|
63
73
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
74
|
+
browser =
|
75
|
+
begin
|
76
|
+
connection = runner.setup_connection(
|
77
|
+
use_pipe: use_pipe,
|
78
|
+
timeout: @launch_options.timeout,
|
79
|
+
slow_mo: @browser_options.slow_mo,
|
80
|
+
preferred_revision: @preferred_revision,
|
81
|
+
)
|
82
|
+
|
83
|
+
Puppeteer::Browser.create(
|
84
|
+
connection: connection,
|
85
|
+
context_ids: [],
|
86
|
+
ignore_https_errors: @browser_options.ignore_https_errors?,
|
87
|
+
default_viewport: @browser_options.default_viewport,
|
88
|
+
process: runner.proc,
|
89
|
+
close_callback: -> { runner.close },
|
90
|
+
)
|
91
|
+
rescue
|
92
|
+
runner.kill
|
93
|
+
raise
|
94
|
+
end
|
80
95
|
|
96
|
+
begin
|
81
97
|
browser.wait_for_target(
|
82
98
|
predicate: ->(target) { target.type == 'page' },
|
83
99
|
timeout: @launch_options.timeout,
|
84
100
|
)
|
85
|
-
|
86
|
-
browser
|
87
101
|
rescue
|
88
|
-
|
102
|
+
browser.close
|
89
103
|
raise
|
90
104
|
end
|
105
|
+
|
106
|
+
browser
|
91
107
|
end
|
92
108
|
|
93
109
|
class DefaultArgs
|
@@ -270,15 +286,15 @@ module Puppeteer::Launcher
|
|
270
286
|
end
|
271
287
|
|
272
288
|
chrome_path = chrome_path_map[channel]
|
273
|
-
if chrome_path.is_a?(Proc)
|
274
|
-
chrome_path = chrome_path.call
|
275
|
-
end
|
276
|
-
|
277
289
|
unless chrome_path
|
278
290
|
raise ArgumentError.new("Invalid channel: '#{channel}'. Allowed channel is #{chrome_path_map.keys}")
|
279
291
|
end
|
280
292
|
|
281
|
-
|
293
|
+
if chrome_path.is_a?(Proc)
|
294
|
+
chrome_path = chrome_path.call
|
295
|
+
end
|
296
|
+
|
297
|
+
if !chrome_path || !File.exist?(chrome_path)
|
282
298
|
raise "#{channel} is not installed on this system.\nExpected path: #{chrome_path}"
|
283
299
|
end
|
284
300
|
|