puppeteer-ruby 0.0.10
Sign up to get free protection for your applications and to get access to all the features.
- 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
|