puppeteer-ruby 0.0.10
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 +7 -0
- data/.circleci/config.yml +71 -0
- data/.github/stale.yml +16 -0
- data/.gitignore +19 -0
- data/.rspec +3 -0
- data/.rubocop.yml +302 -0
- data/.travis.yml +7 -0
- data/Dockerfile +6 -0
- data/Gemfile +6 -0
- data/README.md +54 -0
- data/Rakefile +1 -0
- data/bin/console +11 -0
- data/bin/setup +8 -0
- data/docker-compose.yml +15 -0
- data/docs/Puppeteer.html +2020 -0
- data/docs/Puppeteer/AsyncAwaitBehavior.html +105 -0
- data/docs/Puppeteer/Browser.html +2148 -0
- data/docs/Puppeteer/BrowserContext.html +809 -0
- data/docs/Puppeteer/BrowserFetcher.html +214 -0
- data/docs/Puppeteer/BrowserRunner.html +914 -0
- data/docs/Puppeteer/BrowserRunner/BrowserProcess.html +477 -0
- data/docs/Puppeteer/CDPSession.html +813 -0
- data/docs/Puppeteer/CDPSession/Error.html +124 -0
- data/docs/Puppeteer/ConcurrentRubyUtils.html +430 -0
- data/docs/Puppeteer/Connection.html +960 -0
- data/docs/Puppeteer/Connection/MessageCallback.html +434 -0
- data/docs/Puppeteer/Connection/ProtocolError.html +216 -0
- data/docs/Puppeteer/Connection/RequestDebugPrinter.html +217 -0
- data/docs/Puppeteer/Connection/ResponseDebugPrinter.html +244 -0
- data/docs/Puppeteer/ConsoleMessage.html +565 -0
- data/docs/Puppeteer/ConsoleMessage/Location.html +433 -0
- data/docs/Puppeteer/DOMWorld.html +2219 -0
- data/docs/Puppeteer/DOMWorld/DetachedError.html +124 -0
- data/docs/Puppeteer/DOMWorld/DocumentEvaluationError.html +124 -0
- data/docs/Puppeteer/DebugPrint.html +233 -0
- data/docs/Puppeteer/Device.html +470 -0
- data/docs/Puppeteer/Devices.html +139 -0
- data/docs/Puppeteer/ElementHandle.html +2542 -0
- data/docs/Puppeteer/ElementHandle/ElementNotFoundError.html +206 -0
- data/docs/Puppeteer/ElementHandle/ElementNotVisibleError.html +206 -0
- data/docs/Puppeteer/ElementHandle/Point.html +492 -0
- data/docs/Puppeteer/ElementHandle/ScrollIntoViewError.html +124 -0
- data/docs/Puppeteer/EmulationManager.html +454 -0
- data/docs/Puppeteer/EventCallbackable.html +433 -0
- data/docs/Puppeteer/EventCallbackable/EventListeners.html +435 -0
- data/docs/Puppeteer/ExecutionContext.html +998 -0
- data/docs/Puppeteer/ExecutionContext/EvaluationError.html +124 -0
- data/docs/Puppeteer/ExecutionContext/JavaScriptExpression.html +357 -0
- data/docs/Puppeteer/ExecutionContext/JavaScriptFunction.html +389 -0
- data/docs/Puppeteer/FileChooser.html +455 -0
- data/docs/Puppeteer/Frame.html +3677 -0
- data/docs/Puppeteer/FrameManager.html +2410 -0
- data/docs/Puppeteer/FrameManager/NavigationError.html +124 -0
- data/docs/Puppeteer/IfPresent.html +222 -0
- data/docs/Puppeteer/JSHandle.html +1352 -0
- data/docs/Puppeteer/Keyboard.html +1557 -0
- data/docs/Puppeteer/Keyboard/KeyDefinition.html +831 -0
- data/docs/Puppeteer/Keyboard/KeyDescription.html +603 -0
- data/docs/Puppeteer/Launcher.html +237 -0
- data/docs/Puppeteer/Launcher/Base.html +385 -0
- data/docs/Puppeteer/Launcher/Base/ExecutablePathNotFound.html +124 -0
- data/docs/Puppeteer/Launcher/BrowserOptions.html +441 -0
- data/docs/Puppeteer/Launcher/Chrome.html +669 -0
- data/docs/Puppeteer/Launcher/Chrome/DefaultArgs.html +382 -0
- data/docs/Puppeteer/Launcher/ChromeArgOptions.html +531 -0
- data/docs/Puppeteer/Launcher/LaunchOptions.html +893 -0
- data/docs/Puppeteer/LifecycleWatcher.html +834 -0
- data/docs/Puppeteer/LifecycleWatcher/ExpectedLifecycle.html +363 -0
- data/docs/Puppeteer/LifecycleWatcher/FrameDetachedError.html +206 -0
- data/docs/Puppeteer/LifecycleWatcher/TerminatedError.html +124 -0
- data/docs/Puppeteer/Mouse.html +1105 -0
- data/docs/Puppeteer/Mouse/Button.html +136 -0
- data/docs/Puppeteer/NetworkManager.html +901 -0
- data/docs/Puppeteer/NetworkManager/Credentials.html +385 -0
- data/docs/Puppeteer/Page.html +5970 -0
- data/docs/Puppeteer/Page/FileChooserTimeoutError.html +206 -0
- data/docs/Puppeteer/Page/ScreenshotOptions.html +845 -0
- data/docs/Puppeteer/Page/ScriptTag.html +555 -0
- data/docs/Puppeteer/Page/StyleTag.html +448 -0
- data/docs/Puppeteer/Page/TargetCrashedError.html +124 -0
- data/docs/Puppeteer/RemoteObject.html +1087 -0
- data/docs/Puppeteer/Target.html +1336 -0
- data/docs/Puppeteer/Target/InitializeFailure.html +124 -0
- data/docs/Puppeteer/Target/TargetInfo.html +729 -0
- data/docs/Puppeteer/TimeoutError.html +135 -0
- data/docs/Puppeteer/TimeoutSettings.html +496 -0
- data/docs/Puppeteer/TouchScreen.html +464 -0
- data/docs/Puppeteer/Viewport.html +837 -0
- data/docs/Puppeteer/WaitTask.html +637 -0
- data/docs/Puppeteer/WaitTask/TerminatedError.html +124 -0
- data/docs/Puppeteer/WaitTask/TimeoutError.html +206 -0
- data/docs/Puppeteer/WebSocket.html +673 -0
- data/docs/Puppeteer/WebSocket/DriverImpl.html +412 -0
- data/docs/Puppeteer/WebSocketTransport.html +600 -0
- data/docs/Puppeteer/WebSocktTransportError.html +124 -0
- data/docs/_index.html +823 -0
- data/docs/class_list.html +51 -0
- data/docs/css/common.css +1 -0
- data/docs/css/full_list.css +58 -0
- data/docs/css/style.css +496 -0
- data/docs/file.README.html +123 -0
- data/docs/file_list.html +56 -0
- data/docs/frames.html +17 -0
- data/docs/index.html +123 -0
- data/docs/js/app.js +314 -0
- data/docs/js/full_list.js +216 -0
- data/docs/js/jquery.js +4 -0
- data/docs/method_list.html +4075 -0
- data/docs/top-level-namespace.html +126 -0
- data/lib/puppeteer.rb +200 -0
- data/lib/puppeteer/async_await_behavior.rb +38 -0
- data/lib/puppeteer/browser.rb +259 -0
- data/lib/puppeteer/browser_context.rb +90 -0
- data/lib/puppeteer/browser_fetcher.rb +6 -0
- data/lib/puppeteer/browser_runner.rb +161 -0
- data/lib/puppeteer/cdp_session.rb +100 -0
- data/lib/puppeteer/concurrent_ruby_utils.rb +37 -0
- data/lib/puppeteer/connection.rb +254 -0
- data/lib/puppeteer/console_message.rb +24 -0
- data/lib/puppeteer/debug_print.rb +20 -0
- data/lib/puppeteer/device.rb +12 -0
- data/lib/puppeteer/devices.rb +885 -0
- data/lib/puppeteer/dom_world.rb +484 -0
- data/lib/puppeteer/element_handle.rb +433 -0
- data/lib/puppeteer/element_handle/bounding_box.rb +12 -0
- data/lib/puppeteer/element_handle/box_model.rb +19 -0
- data/lib/puppeteer/element_handle/point.rb +26 -0
- data/lib/puppeteer/emulation_manager.rb +46 -0
- data/lib/puppeteer/errors.rb +2 -0
- data/lib/puppeteer/event_callbackable.rb +88 -0
- data/lib/puppeteer/execution_context.rb +254 -0
- data/lib/puppeteer/file_chooser.rb +29 -0
- data/lib/puppeteer/frame.rb +286 -0
- data/lib/puppeteer/frame_manager.rb +378 -0
- data/lib/puppeteer/if_present.rb +18 -0
- data/lib/puppeteer/js_handle.rb +142 -0
- data/lib/puppeteer/keyboard.rb +183 -0
- data/lib/puppeteer/keyboard/key_description.rb +19 -0
- data/lib/puppeteer/keyboard/us_keyboard_layout.rb +283 -0
- data/lib/puppeteer/launcher.rb +25 -0
- data/lib/puppeteer/launcher/base.rb +48 -0
- data/lib/puppeteer/launcher/browser_options.rb +41 -0
- data/lib/puppeteer/launcher/chrome.rb +211 -0
- data/lib/puppeteer/launcher/chrome_arg_options.rb +49 -0
- data/lib/puppeteer/launcher/launch_options.rb +68 -0
- data/lib/puppeteer/lifecycle_watcher.rb +171 -0
- data/lib/puppeteer/mouse.rb +123 -0
- data/lib/puppeteer/network_manager.rb +122 -0
- data/lib/puppeteer/page.rb +1065 -0
- data/lib/puppeteer/page/screenshot_options.rb +78 -0
- data/lib/puppeteer/remote_object.rb +143 -0
- data/lib/puppeteer/target.rb +150 -0
- data/lib/puppeteer/timeout_settings.rb +15 -0
- data/lib/puppeteer/touch_screen.rb +43 -0
- data/lib/puppeteer/version.rb +3 -0
- data/lib/puppeteer/viewport.rb +54 -0
- data/lib/puppeteer/wait_task.rb +188 -0
- data/lib/puppeteer/web_socket.rb +122 -0
- data/lib/puppeteer/web_socket_transport.rb +49 -0
- data/puppeteer-ruby.gemspec +32 -0
- metadata +355 -0
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
class Puppeteer::ElementHandle < Puppeteer::JSHandle
|
|
2
|
+
# A class to represent (x, y)-coordinates
|
|
3
|
+
# supporting + and / operators.
|
|
4
|
+
class Point
|
|
5
|
+
def initialize(x:, y:)
|
|
6
|
+
@x = x
|
|
7
|
+
@y = y
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def +(other)
|
|
11
|
+
Point.new(
|
|
12
|
+
x: @x + other.x,
|
|
13
|
+
y: @y + other.y,
|
|
14
|
+
)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def /(num)
|
|
18
|
+
Point.new(
|
|
19
|
+
x: @x / num,
|
|
20
|
+
y: @y / num,
|
|
21
|
+
)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
attr_reader :x, :y
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
class Puppeteer::EmulationManager
|
|
2
|
+
using Puppeteer::AsyncAwaitBehavior
|
|
3
|
+
|
|
4
|
+
# @param {!Puppeteer.CDPSession} client
|
|
5
|
+
def initialize(client)
|
|
6
|
+
@client = client
|
|
7
|
+
@emulating_mobile = false
|
|
8
|
+
@has_touch = false
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
# @param viewport [Puppeteer::Viewport]
|
|
12
|
+
# @return [true|false]
|
|
13
|
+
def emulate_viewport(viewport)
|
|
14
|
+
mobile = viewport.mobile?
|
|
15
|
+
width = viewport.width
|
|
16
|
+
height = viewport.height
|
|
17
|
+
device_scale_factor = viewport.device_scale_factor
|
|
18
|
+
# /** @type {Protocol.Emulation.ScreenOrientation} */
|
|
19
|
+
# const screenOrientation = viewport.isLandscape ? { angle: 90, type: 'landscapePrimary' } : { angle: 0, type: 'portraitPrimary' };
|
|
20
|
+
has_touch = viewport.has_touch?
|
|
21
|
+
|
|
22
|
+
await_all(
|
|
23
|
+
@client.async_send_message('Emulation.setDeviceMetricsOverride',
|
|
24
|
+
mobile: mobile,
|
|
25
|
+
width: width,
|
|
26
|
+
height: height,
|
|
27
|
+
deviceScaleFactor: device_scale_factor,
|
|
28
|
+
# screenOrientation: screen_orientation,
|
|
29
|
+
),
|
|
30
|
+
@client.async_send_message('Emulation.setTouchEmulationEnabled',
|
|
31
|
+
enabled: has_touch,
|
|
32
|
+
),
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
reload_needed = @emulating_mobile != mobile || @hasTouch != has_touch
|
|
36
|
+
@emulating_mobile = mobile
|
|
37
|
+
@has_touch = has_touch
|
|
38
|
+
reload_needed
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# @param viewport [Puppeteer::Viewport]
|
|
42
|
+
# @return [Future<true|false>]
|
|
43
|
+
async def async_emulate_viewport(viewport)
|
|
44
|
+
emulate_viewport(viewport)
|
|
45
|
+
end
|
|
46
|
+
end
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
require 'securerandom'
|
|
2
|
+
|
|
3
|
+
module Puppeteer::EventCallbackable
|
|
4
|
+
class EventListeners
|
|
5
|
+
include Enumerable
|
|
6
|
+
|
|
7
|
+
def initialize
|
|
8
|
+
@listeners = {}
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
# @return [String] Listener ID
|
|
12
|
+
def add(&block)
|
|
13
|
+
id = SecureRandom.hex(8)
|
|
14
|
+
@listeners[id] = block
|
|
15
|
+
id
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# @param id [String] Listener ID returned on #add
|
|
19
|
+
def delete(id)
|
|
20
|
+
@listeners.delete(id)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# @implement Enumerable#each
|
|
24
|
+
def each(&block)
|
|
25
|
+
@listeners.values.each(&block)
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def add_event_listener(event_name, &block)
|
|
30
|
+
@event_listeners ||= {}
|
|
31
|
+
(@event_listeners[event_name] ||= EventListeners.new).add(&block)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def remove_event_listener(*id_args)
|
|
35
|
+
(@event_listeners ||= {}).each do |event_name, listeners|
|
|
36
|
+
id_args.each do |id|
|
|
37
|
+
listeners.delete(id)
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def on_event(event_name, &block)
|
|
43
|
+
@event_callbackable_handlers ||= {}
|
|
44
|
+
@event_callbackable_handlers[event_name] = block
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def emit_event(event_name, *args, **kwargs)
|
|
48
|
+
@event_callbackable_handlers ||= {}
|
|
49
|
+
@event_listeners ||= {}
|
|
50
|
+
|
|
51
|
+
if kwargs.empty?
|
|
52
|
+
# In Ruby's specification (version < 2.7),
|
|
53
|
+
# `method(:x).call(*args, **kwargs)` is equivalent to `x(*args, {})`
|
|
54
|
+
# It often causes unexpected ArgumentError.
|
|
55
|
+
#
|
|
56
|
+
# ----------------
|
|
57
|
+
# def greet
|
|
58
|
+
# puts 'Hello!'
|
|
59
|
+
# end
|
|
60
|
+
#
|
|
61
|
+
# def call_me(*args, **kwargs)
|
|
62
|
+
# greet(*args, **kwargs) # => 'Hello!'
|
|
63
|
+
#
|
|
64
|
+
# method(:greet).call(*args, **kwargs) # => `greet': wrong number of arguments (given 1, expected 0) (ArgumentError)
|
|
65
|
+
# end
|
|
66
|
+
#
|
|
67
|
+
# call_me
|
|
68
|
+
# ----------------
|
|
69
|
+
#
|
|
70
|
+
# This behavior is really annoying, and should be avoided, because we often want to set event handler as below:
|
|
71
|
+
#
|
|
72
|
+
# `on_event 'Some.Event.awesome', &method(:handle_awesome_event)`
|
|
73
|
+
#
|
|
74
|
+
# So Let's avoid it by checking kwargs.
|
|
75
|
+
@event_callbackable_handlers[event_name]&.call(*args)
|
|
76
|
+
@event_listeners[event_name]&.each do |proc|
|
|
77
|
+
proc.call(*args)
|
|
78
|
+
end
|
|
79
|
+
else
|
|
80
|
+
@event_callbackable_handlers[event_name]&.call(*args, **kwargs)
|
|
81
|
+
@event_listeners[event_name]&.each do |proc|
|
|
82
|
+
proc.call(*args, **kwargs)
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
event_name
|
|
87
|
+
end
|
|
88
|
+
end
|
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
class Puppeteer::ExecutionContext
|
|
2
|
+
include Puppeteer::IfPresent
|
|
3
|
+
using Puppeteer::AsyncAwaitBehavior
|
|
4
|
+
|
|
5
|
+
EVALUATION_SCRIPT_URL = '__puppeteer_evaluation_script__'
|
|
6
|
+
SOURCE_URL_REGEX = /^[\040\t]*\/\/[@#] sourceURL=\s*(\S*?)\s*$/m
|
|
7
|
+
|
|
8
|
+
# @param client [Puppeteer::CDPSession]
|
|
9
|
+
# @param context_payload [Hash]
|
|
10
|
+
# @param world [Puppeteer::DOMWorld?]
|
|
11
|
+
def initialize(client, context_payload, world)
|
|
12
|
+
@client = client
|
|
13
|
+
@world = world
|
|
14
|
+
@context_id = context_payload['id']
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
attr_reader :client, :world
|
|
18
|
+
|
|
19
|
+
# only used in DomWorld#delete_context
|
|
20
|
+
def _context_id
|
|
21
|
+
@context_id
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# @return [Puppeteer::Frame]
|
|
25
|
+
def frame
|
|
26
|
+
if_present(@world) do |world|
|
|
27
|
+
world.frame
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# @param page_function [String]
|
|
32
|
+
# @return [Object]
|
|
33
|
+
def evaluate(page_function, *args)
|
|
34
|
+
evaluate_internal(true, page_function, *args)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# @param page_function [String]
|
|
38
|
+
# @return [Puppeteer::JSHandle]
|
|
39
|
+
def evaluate_handle(page_function, *args)
|
|
40
|
+
evaluate_internal(false, page_function, *args)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
class JavaScriptExpression
|
|
44
|
+
def initialize(execution_context, expression, return_by_value)
|
|
45
|
+
@execution_context = execution_context
|
|
46
|
+
@expression = expression
|
|
47
|
+
@return_by_value = return_by_value
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# @param client [Puppeteer::CDPSession]
|
|
51
|
+
# @param context_id [String]
|
|
52
|
+
# @return [Object|JSHandle]
|
|
53
|
+
def evaluate_with(client:, context_id:)
|
|
54
|
+
result = client.send_message('Runtime.evaluate',
|
|
55
|
+
expression: expression_with_source_url,
|
|
56
|
+
contextId: context_id,
|
|
57
|
+
returnByValue: @return_by_value,
|
|
58
|
+
awaitPromise: true,
|
|
59
|
+
userGesture: true,
|
|
60
|
+
)
|
|
61
|
+
# }).catch(rewriteError);
|
|
62
|
+
|
|
63
|
+
exception_details = result['exceptionDetails']
|
|
64
|
+
if exception_details
|
|
65
|
+
raise EvaluationError.new("Evaluation failed: #{exception_details}")
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
remote_object = Puppeteer::RemoteObject.new(result['result'])
|
|
69
|
+
if @return_by_value
|
|
70
|
+
remote_object.value
|
|
71
|
+
else
|
|
72
|
+
Puppeteer::JSHandle.create(
|
|
73
|
+
context: @execution_context,
|
|
74
|
+
remote_object: remote_object,
|
|
75
|
+
)
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
private def suffix
|
|
80
|
+
"//# sourceURL=#{EVALUATION_SCRIPT_URL}"
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
private def expression_with_source_url
|
|
84
|
+
if SOURCE_URL_REGEX.match?(@expression)
|
|
85
|
+
@expression
|
|
86
|
+
else
|
|
87
|
+
"#{@expression}\n#{suffix}"
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
class JavaScriptFunction
|
|
93
|
+
include Puppeteer::IfPresent
|
|
94
|
+
|
|
95
|
+
def initialize(execution_context, expression, args, return_by_value)
|
|
96
|
+
@execution_context = execution_context
|
|
97
|
+
@expression = expression
|
|
98
|
+
@return_by_value = return_by_value
|
|
99
|
+
@args = args
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
# @param client [Puppeteer::CDPSession]
|
|
103
|
+
# @param context_id [String]
|
|
104
|
+
# @return [Object|JSHandle]
|
|
105
|
+
def evaluate_with(client:, context_id:)
|
|
106
|
+
# `function` can be omitted in JS after ES2015.
|
|
107
|
+
# https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/Object_initializer
|
|
108
|
+
#
|
|
109
|
+
# Original puppeteer implementation take it into consideration.
|
|
110
|
+
# But we don't support the syntax here.
|
|
111
|
+
|
|
112
|
+
result = client.send_message('Runtime.callFunctionOn',
|
|
113
|
+
functionDeclaration: "#{@expression}\n#{suffix}\n",
|
|
114
|
+
executionContextId: context_id,
|
|
115
|
+
arguments: converted_args,
|
|
116
|
+
returnByValue: @return_by_value,
|
|
117
|
+
awaitPromise: true,
|
|
118
|
+
userGesture: true,
|
|
119
|
+
) # .catch(rewriteError);
|
|
120
|
+
|
|
121
|
+
exception_details = result['exceptionDetails']
|
|
122
|
+
remote_object = Puppeteer::RemoteObject.new(result['result'])
|
|
123
|
+
|
|
124
|
+
if exception_details
|
|
125
|
+
raise EvaluationError.new("Evaluation failed: #{exception_details}")
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
if @return_by_value
|
|
129
|
+
remote_object.value
|
|
130
|
+
else
|
|
131
|
+
Puppeteer::JSHandle.create(
|
|
132
|
+
context: @execution_context,
|
|
133
|
+
remote_object: remote_object,
|
|
134
|
+
)
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
private def converted_args
|
|
139
|
+
# if (typeof arg === 'bigint') // eslint-disable-line valid-typeof
|
|
140
|
+
# return { unserializableValue: `${arg.toString()}n` };
|
|
141
|
+
# if (Object.is(arg, -0))
|
|
142
|
+
# return { unserializableValue: '-0' };
|
|
143
|
+
# if (Object.is(arg, Infinity))
|
|
144
|
+
# return { unserializableValue: 'Infinity' };
|
|
145
|
+
# if (Object.is(arg, -Infinity))
|
|
146
|
+
# return { unserializableValue: '-Infinity' };
|
|
147
|
+
# if (Object.is(arg, NaN))
|
|
148
|
+
# return { unserializableValue: 'NaN' };
|
|
149
|
+
@args.map do |arg|
|
|
150
|
+
if arg && arg.is_a?(Puppeteer::JSHandle)
|
|
151
|
+
if arg.context != @execution_context
|
|
152
|
+
raise EvaluationError.new('JSHandles can be evaluated only in the context they were created!')
|
|
153
|
+
elsif arg.disposed?
|
|
154
|
+
raise EvaluationError.new('JSHandles is disposed!')
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
arg.remote_object.converted_arg
|
|
158
|
+
else
|
|
159
|
+
{ value: arg }
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
# /**
|
|
165
|
+
# * @param {!Error} error
|
|
166
|
+
# * @return {!Protocol.Runtime.evaluateReturnValue}
|
|
167
|
+
# */
|
|
168
|
+
# function rewriteError(error) {
|
|
169
|
+
# if (error.message.includes('Object reference chain is too long'))
|
|
170
|
+
# return {result: {type: 'undefined'}};
|
|
171
|
+
# if (error.message.includes('Object couldn\'t be returned by value'))
|
|
172
|
+
# return {result: {type: 'undefined'}};
|
|
173
|
+
|
|
174
|
+
# if (error.message.endsWith('Cannot find context with specified id') || error.message.endsWith('Inspected target navigated or closed'))
|
|
175
|
+
# throw new Error('Execution context was destroyed, most likely because of a navigation.');
|
|
176
|
+
# throw error;
|
|
177
|
+
# }
|
|
178
|
+
|
|
179
|
+
private def suffix
|
|
180
|
+
"//# sourceURL=#{EVALUATION_SCRIPT_URL}"
|
|
181
|
+
end
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
class EvaluationError < StandardError; end
|
|
185
|
+
|
|
186
|
+
# @param return_by_value [Boolean]
|
|
187
|
+
# @param page_function [String]
|
|
188
|
+
# @return [Object|Puppeteer::JSHandle]
|
|
189
|
+
private def evaluate_internal(return_by_value, page_function, *args)
|
|
190
|
+
# `function` can be omitted in JS after ES2015.
|
|
191
|
+
# https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/Object_initializer
|
|
192
|
+
# But we don't support the syntax here.
|
|
193
|
+
js_object =
|
|
194
|
+
if ['=>', 'async', 'function'].any? { |keyword| page_function.include?(keyword) }
|
|
195
|
+
JavaScriptFunction.new(self, page_function, args, return_by_value)
|
|
196
|
+
else
|
|
197
|
+
JavaScriptExpression.new(self, page_function, return_by_value)
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
js_object.evaluate_with(
|
|
201
|
+
client: @client,
|
|
202
|
+
context_id: @context_id,
|
|
203
|
+
)
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
# /**
|
|
207
|
+
# * @param {!JSHandle} prototypeHandle
|
|
208
|
+
# * @return {!Promise<!JSHandle>}
|
|
209
|
+
# */
|
|
210
|
+
# async queryObjects(prototypeHandle) {
|
|
211
|
+
# assert(!prototypeHandle._disposed, 'Prototype JSHandle is disposed!');
|
|
212
|
+
# assert(prototypeHandle._remoteObject.objectId, 'Prototype JSHandle must not be referencing primitive value');
|
|
213
|
+
# const response = await this._client.send('Runtime.queryObjects', {
|
|
214
|
+
# prototypeObjectId: prototypeHandle._remoteObject.objectId
|
|
215
|
+
# });
|
|
216
|
+
# return createJSHandle(this, response.objects);
|
|
217
|
+
# }
|
|
218
|
+
|
|
219
|
+
# @param backend_node_id [Integer]
|
|
220
|
+
# @return [Puppeteer::ElementHandle]
|
|
221
|
+
def adopt_backend_node_id(backend_node_id)
|
|
222
|
+
response = @client.send_message('DOM.resolveNode',
|
|
223
|
+
backendNodeId: backend_node_id,
|
|
224
|
+
executionContextId: @context_id,
|
|
225
|
+
)
|
|
226
|
+
Puppeteer::JSHandle.create(
|
|
227
|
+
context: self,
|
|
228
|
+
remote_object: Puppeteer::RemoteObject.new(response["object"]),
|
|
229
|
+
)
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
# @param element_handle [Puppeteer::ElementHandle]
|
|
233
|
+
# @return [Puppeteer::ElementHandle]
|
|
234
|
+
def adopt_element_handle(element_handle)
|
|
235
|
+
if element_handle.execution_context == self
|
|
236
|
+
raise ArgumentError.new('Cannot adopt handle that already belongs to this execution context')
|
|
237
|
+
end
|
|
238
|
+
|
|
239
|
+
unless @world
|
|
240
|
+
raise 'Cannot adopt handle without DOMWorld'
|
|
241
|
+
end
|
|
242
|
+
|
|
243
|
+
node_info = element_handle.remote_object.node_info(@client)
|
|
244
|
+
response = @client.send_message('DOM.resolveNode',
|
|
245
|
+
backendNodeId: node_info["node"]["backendNodeId"],
|
|
246
|
+
executionContextId: @context_id,
|
|
247
|
+
)
|
|
248
|
+
|
|
249
|
+
Puppeteer::JSHandle.create(
|
|
250
|
+
context: self,
|
|
251
|
+
remote_object: Puppeteer::RemoteObject.new(response["object"]),
|
|
252
|
+
)
|
|
253
|
+
end
|
|
254
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
class Puppeteer::FileChooser
|
|
2
|
+
# @param element [Puppeteer::ElementHandle]
|
|
3
|
+
# @param event [Hash]
|
|
4
|
+
def initialize(element, event)
|
|
5
|
+
@element = element
|
|
6
|
+
@multiple = event['mode'] != 'selectSingle'
|
|
7
|
+
@handled = false
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def multiple?
|
|
11
|
+
@multiple
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
# @param file_paths [Array<String>]
|
|
15
|
+
def accept(file_paths)
|
|
16
|
+
if @handled
|
|
17
|
+
raise 'Cannot accept FileChooser which is already handled!'
|
|
18
|
+
end
|
|
19
|
+
@handled = true
|
|
20
|
+
@element.upload_file(*file_paths)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def cancel
|
|
24
|
+
if @handled
|
|
25
|
+
raise 'Cannot cancel FileChooser which is already handled!'
|
|
26
|
+
end
|
|
27
|
+
@handled = true
|
|
28
|
+
end
|
|
29
|
+
end
|