puppeteer-ruby 0.43.1 → 0.44.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e723d5efd8074f8c70f1b94de1399f35ec39eca88fd86d1991b036db32d783a8
4
- data.tar.gz: 463781ad3737b5db0f09b2ba9ec2ed8f62863991c011291437230c512671e0ba
3
+ metadata.gz: 6ade25ba8f8e99240ed29fdad9300af7b65cc12ddf09e45c43f7b672c6324ed4
4
+ data.tar.gz: 97d3bfc48b3a2e3729dd8857c2bb6deca7babd4d0b055195f2dbe7c01c941e97
5
5
  SHA512:
6
- metadata.gz: 46462c2894970d02792d5021088252fce262f41f81531449a73d9d40745ede1742fe187cde65cae64222ba817366500d347ca310aa658147040e4fbfa5d1b5db
7
- data.tar.gz: d5b6e7ae1e0efc6c1e69e7bb136f90dfdc1c2370c29ec4bf9a6877c22bbe38cd6a81f698f086dce3157800bdfc7bfcb06f7eb35b518434870fd95456dc1fbe3c
6
+ metadata.gz: 891d8c29ac63d25cdb34178024d7a9202675d77b121a903e24a51e9465e46a9b7a0a9b70a2d893d9b274724b5547d5bb90e133aa2c217052f3f523f952e1a0a3
7
+ data.tar.gz: eea1fb6ff2f179208932a3bb84ca96841b1b08ff588d914e88ace6ad9e31f71c567c21321e3376b019a265122e51a4352b3f0039dd6bea770dba2a383efe82e5
data/CHANGELOG.md CHANGED
@@ -1,7 +1,13 @@
1
- ### main [[diff](https://github.com/YusukeIwaki/puppeteer-ruby/compare/0.43.1...main)]
1
+ ### main [[diff](https://github.com/YusukeIwaki/puppeteer-ruby/compare/0.44.0...main)]
2
2
 
3
3
  - xxx
4
4
 
5
+ ### 0.44.0 [[diff](https://github.com/YusukeIwaki/puppeteer-ruby/compare/0.43.1...0.44.0)]
6
+
7
+ - Port Puppeteer v17.0-v17.1 features.
8
+ - `wait_for_selector` no longer accept `root` parameter.
9
+
10
+
5
11
  ### 0.43.1 [[diff](https://github.com/YusukeIwaki/puppeteer-ruby/compare/0.43.0...0.43.1)]
6
12
 
7
13
  - Port Puppeteer v16.1 features, including bugfix and XPath query handler.
data/docs/api_coverage.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # API coverages
2
- - Puppeteer version: v16.2.0
3
- - puppeteer-ruby version: 0.43.1
2
+ - Puppeteer version: v17.1.3
3
+ - puppeteer-ruby version: 0.44.0
4
4
 
5
5
  ## Puppeteer
6
6
 
@@ -150,13 +150,6 @@
150
150
  * ~~removeAllListeners~~
151
151
  * ~~removeListener~~
152
152
 
153
- ## ExecutionContext
154
-
155
- * evaluate
156
- * evaluateHandle => `#evaluate_handle`
157
- * frame
158
- * ~~queryObjects~~
159
-
160
153
  ## FileChooser
161
154
 
162
155
  * accept
@@ -172,12 +165,12 @@
172
165
  * $x => `#Sx`
173
166
  * addScriptTag => `#add_script_tag`
174
167
  * addStyleTag => `#add_style_tag`
168
+ * addStyleTag => `#add_style_tag`
175
169
  * childFrames => `#child_frames`
176
170
  * click
177
171
  * content
178
172
  * evaluate
179
173
  * evaluateHandle => `#evaluate_handle`
180
- * executionContext => `#execution_context`
181
174
  * focus
182
175
  * goto
183
176
  * hover
@@ -251,7 +244,6 @@
251
244
  * dispose
252
245
  * evaluate
253
246
  * evaluateHandle => `#evaluate_handle`
254
- * executionContext => `#execution_context`
255
247
  * getProperties => `#properties`
256
248
  * getProperty => `#[]`
257
249
  * getProperty => `#[]`
@@ -289,6 +281,7 @@
289
281
  * $x => `#Sx`
290
282
  * addScriptTag => `#add_script_tag`
291
283
  * addStyleTag => `#add_style_tag`
284
+ * addStyleTag => `#add_style_tag`
292
285
  * authenticate
293
286
  * bringToFront => `#bring_to_front`
294
287
  * browser
@@ -313,6 +306,7 @@
313
306
  * exposeFunction => `#expose_function`
314
307
  * focus
315
308
  * frames
309
+ * ~~getDefaultTimeout~~
316
310
  * goBack => `#go_back`
317
311
  * goForward => `#go_forward`
318
312
  * goto
@@ -401,5 +395,4 @@
401
395
 
402
396
  * ~~evaluate~~
403
397
  * ~~evaluateHandle~~
404
- * ~~executionContext~~
405
398
  * ~~url~~
@@ -25,43 +25,83 @@ class Puppeteer::AriaQueryHandler
25
25
  query_options
26
26
  end
27
27
 
28
- def query_one(element, selector)
29
- context = element.execution_context
28
+ # @param element [Puppeteer::ElementHandle]
29
+ # @param selector [String]
30
+ private def query_one_id(element, selector)
30
31
  parse_result = parse_aria_selector(selector)
31
32
  res = element.query_ax_tree(accessible_name: parse_result[:name], role: parse_result[:role])
32
- if res.empty?
33
+
34
+ if res.first.is_a?(Hash)
35
+ res.first['backendDOMNodeId']
36
+ else
33
37
  nil
38
+ end
39
+ end
40
+
41
+ def query_one(element, selector)
42
+ id = query_one_id(element, selector)
43
+
44
+ if id
45
+ element.frame.main_world.adopt_backend_node(id)
34
46
  else
35
- context.adopt_backend_node_id(res.first['backendDOMNodeId'])
47
+ nil
36
48
  end
37
49
  end
38
50
 
39
- def wait_for(dom_world, selector, visible: nil, hidden: nil, timeout: nil, root: nil)
51
+ def wait_for(element_or_frame, selector, visible: nil, hidden: nil, timeout: nil)
52
+ case element_or_frame
53
+ when Puppeteer::Frame
54
+ frame = element_or_frame
55
+ element = nil
56
+ when Puppeteer::ElementHandle
57
+ frame = element_or_frame.frame
58
+ element = frame.puppeteer_world.adopt_handle(element_or_frame)
59
+ else
60
+ raise ArgumentError.new("element_or_frame must be a Frame or ElementHandle. #{element_or_frame.inspect}")
61
+ end
62
+
40
63
  # addHandlerToWorld
41
- binding_function = Puppeteer::DOMWorld::BindingFunction.new(
64
+ binding_function = Puppeteer::IsolaatedWorld::BindingFunction.new(
42
65
  name: 'ariaQuerySelector',
43
- proc: -> (sel) { query_one(root || dom_world.send(:document), sel) },
66
+ proc: -> (sel) {
67
+ id = query_one_id(element || frame.puppeteer_world.document, sel)
68
+
69
+ if id
70
+ frame.puppeteer_world.adopt_backend_node(id)
71
+ else
72
+ nil
73
+ end
74
+ },
44
75
  )
45
- dom_world.send(:wait_for_selector_in_page,
76
+ result = frame.puppeteer_world.send(:wait_for_selector_in_page,
46
77
  '(_, selector) => globalThis.ariaQuerySelector(selector)',
78
+ element,
47
79
  selector,
48
80
  visible: visible,
49
81
  hidden: hidden,
50
82
  timeout: timeout,
51
83
  binding_function: binding_function,
52
- root: root,
53
84
  )
85
+
86
+ element&.dispose
87
+
88
+ if result.is_a?(Puppeteer::ElementHandle)
89
+ result.frame.main_world.transfer_handle(result)
90
+ else
91
+ result&.dispose
92
+ nil
93
+ end
54
94
  end
55
95
 
56
96
  def query_all(element, selector)
57
- context = element.execution_context
97
+ world = element.frame.main_world
58
98
  parse_result = parse_aria_selector(selector)
59
99
  res = element.query_ax_tree(accessible_name: parse_result[:name], role: parse_result[:role])
60
100
  if res.empty?
61
101
  nil
62
102
  else
63
103
  promises = res.map do |ax_node|
64
- context.send(:async_adopt_backend_node_id, ax_node['backendDOMNodeId'])
104
+ world.send(:async_adopt_backend_node, ax_node['backendDOMNodeId'])
65
105
  end
66
106
  await_all(*promises)
67
107
  end
@@ -108,7 +108,7 @@ class Puppeteer::Coverage
108
108
 
109
109
  # Filter out empty ranges.
110
110
  results.select do |range|
111
- range[:end] - range[:start] > 1
111
+ range[:end] - range[:start] > 0
112
112
  end
113
113
  end
114
114
  end
@@ -21,12 +21,39 @@ class Puppeteer::CustomQueryHandler
21
21
  nil
22
22
  end
23
23
 
24
- def wait_for(dom_world, selector, visible: nil, hidden: nil, timeout: nil, root: nil)
24
+ def wait_for(element_or_frame, selector, visible: nil, hidden: nil, timeout: nil)
25
+ case element_or_frame
26
+ when Puppeteer::Frame
27
+ frame = element_or_frame
28
+ element = nil
29
+ when Puppeteer::ElementHandle
30
+ frame = element_or_frame.frame
31
+ element = frame.puppeteer_world.adopt_handle(element_or_frame)
32
+ else
33
+ raise ArgumentError.new("element_or_frame must be a Frame or ElementHandle. #{element_or_frame.inspect}")
34
+ end
35
+
25
36
  unless @query_one
26
37
  raise NotImplementedError.new("#{self.class}##{__method__} is not implemented.")
27
38
  end
28
39
 
29
- dom_world.send(:wait_for_selector_in_page, @query_one, selector, visible: visible, hidden: hidden, timeout: timeout, root: root)
40
+ result = frame.puppeteer_world.send(:wait_for_selector_in_page,
41
+ @query_one,
42
+ element,
43
+ selector,
44
+ visible: visible,
45
+ hidden: hidden,
46
+ timeout: timeout,
47
+ )
48
+
49
+ element&.dispose
50
+
51
+ if result.is_a?(Puppeteer::ElementHandle)
52
+ result.frame.main_world.transfer_handle(result)
53
+ else
54
+ result&.dispose
55
+ nil
56
+ end
30
57
  end
31
58
 
32
59
  def query_all(element, selector)
@@ -12,16 +12,16 @@ class Puppeteer::ElementHandle < Puppeteer::JSHandle
12
12
  # @param client [Puppeteer::CDPSession]
13
13
  # @param remote_object [Puppeteer::RemoteObject]
14
14
  # @param frame [Puppeteer::Frame]
15
- # @param page [Puppeteer::Page]
16
- # @param frame_manager [Puppeteer::FrameManager]
17
- def initialize(context:, client:, remote_object:, frame:, page:, frame_manager:)
15
+ def initialize(context:, client:, remote_object:, frame:)
18
16
  super(context: context, client: client, remote_object: remote_object)
19
17
  @frame = frame
20
- @page = page
21
- @frame_manager = frame_manager
18
+ @page = frame.page
19
+ @frame_manager = frame.frame_manager
22
20
  @disposed = false
23
21
  end
24
22
 
23
+ attr_reader :page, :frame, :frame_manager
24
+
25
25
  def inspect
26
26
  values = %i[context remote_object page disposed].map do |sym|
27
27
  value = instance_variable_get(:"@#{sym}")
@@ -60,18 +60,7 @@ class Puppeteer::ElementHandle < Puppeteer::JSHandle
60
60
  # (30 seconds). Pass `0` to disable timeout. The default value can be changed
61
61
  # by using the {@link Page.setDefaultTimeout} method.
62
62
  def wait_for_selector(selector, visible: nil, hidden: nil, timeout: nil)
63
- frame = @context.frame
64
-
65
- secondary_world = frame.secondary_world
66
- adopted_root = secondary_world.execution_context.adopt_element_handle(self)
67
- handle = secondary_world.wait_for_selector(selector, visible: visible, hidden: hidden, timeout: timeout, root: adopted_root)
68
- adopted_root.dispose
69
- return nil unless handle
70
-
71
- main_world = frame.main_world
72
- result = main_world.execution_context.adopt_element_handle(handle)
73
- handle.dispose
74
- result
63
+ query_handler_manager.detect_query_handler(selector).wait_for(self, visible: visible, hidden: hidden, timeout: timeout)
75
64
  end
76
65
 
77
66
  define_async_method :async_wait_for_selector
@@ -653,6 +642,6 @@ class Puppeteer::ElementHandle < Puppeteer::JSHandle
653
642
  # used in AriaQueryHandler
654
643
  def query_ax_tree(accessible_name: nil, role: nil)
655
644
  @remote_object.query_ax_tree(@client,
656
- accessible_name: accessible_name, role: role)
645
+ accessible_name: accessible_name, role: role)
657
646
  end
658
647
  end
@@ -7,7 +7,7 @@ class Puppeteer::ExecutionContext
7
7
 
8
8
  # @param client [Puppeteer::CDPSession]
9
9
  # @param context_payload [Hash]
10
- # @param world [Puppeteer::DOMWorld?]
10
+ # @param world [Puppeteer::IsolaatedWorld?]
11
11
  def initialize(client, context_payload, world)
12
12
  @client = client
13
13
  @world = world
@@ -17,23 +17,16 @@ class Puppeteer::ExecutionContext
17
17
 
18
18
  attr_reader :client, :world
19
19
 
20
- # only used in DOMWorld
20
+ # only used in IsolaatedWorld
21
21
  private def _context_id
22
22
  @context_id
23
23
  end
24
24
 
25
- # only used in DOMWorld::BindingFunction#add_binding_to_context
25
+ # only used in IsolaatedWorld::BindingFunction#add_binding_to_context
26
26
  private def _context_name
27
27
  @context_name
28
28
  end
29
29
 
30
- # @return [Puppeteer::Frame]
31
- def frame
32
- if_present(@world) do |world|
33
- world.frame
34
- end
35
- end
36
-
37
30
  # @param page_function [String]
38
31
  # @return [Object]
39
32
  def evaluate(page_function, *args)
@@ -208,54 +201,4 @@ class Puppeteer::ExecutionContext
208
201
  context_id: @context_id,
209
202
  )
210
203
  end
211
-
212
- # /**
213
- # * @param {!JSHandle} prototypeHandle
214
- # * @return {!Promise<!JSHandle>}
215
- # */
216
- # async queryObjects(prototypeHandle) {
217
- # assert(!prototypeHandle._disposed, 'Prototype JSHandle is disposed!');
218
- # assert(prototypeHandle._remoteObject.objectId, 'Prototype JSHandle must not be referencing primitive value');
219
- # const response = await this._client.send('Runtime.queryObjects', {
220
- # prototypeObjectId: prototypeHandle._remoteObject.objectId
221
- # });
222
- # return createJSHandle(this, response.objects);
223
- # }
224
-
225
- # @param backend_node_id [Integer]
226
- # @return [Puppeteer::ElementHandle]
227
- def adopt_backend_node_id(backend_node_id)
228
- response = @client.send_message('DOM.resolveNode',
229
- backendNodeId: backend_node_id,
230
- executionContextId: @context_id,
231
- )
232
- Puppeteer::JSHandle.create(
233
- context: self,
234
- remote_object: Puppeteer::RemoteObject.new(response["object"]),
235
- )
236
- end
237
- private define_async_method :async_adopt_backend_node_id
238
-
239
- # @param element_handle [Puppeteer::ElementHandle]
240
- # @return [Puppeteer::ElementHandle]
241
- def adopt_element_handle(element_handle)
242
- if element_handle.execution_context == self
243
- raise ArgumentError.new('Cannot adopt handle that already belongs to this execution context')
244
- end
245
-
246
- unless @world
247
- raise 'Cannot adopt handle without DOMWorld'
248
- end
249
-
250
- node_info = element_handle.remote_object.node_info(@client)
251
- response = @client.send_message('DOM.resolveNode',
252
- backendNodeId: node_info["node"]["backendNodeId"],
253
- executionContextId: @context_id,
254
- )
255
-
256
- Puppeteer::JSHandle.create(
257
- context: self,
258
- remote_object: Puppeteer::RemoteObject.new(response["object"]),
259
- )
260
- end
261
204
  end
@@ -37,8 +37,8 @@ class Puppeteer::Frame
37
37
  # @param client [Puppeteer::CDPSession]
38
38
  private def update_client(client)
39
39
  @client = client
40
- @main_world = Puppeteer::DOMWorld.new(@client, @frame_manager, self, @frame_manager.timeout_settings)
41
- @secondary_world = Puppeteer::DOMWorld.new(@client, @frame_manager, self, @frame_manager.timeout_settings)
40
+ @main_world = Puppeteer::IsolaatedWorld.new(@client, @frame_manager, self, @frame_manager.timeout_settings)
41
+ @puppeteer_world = Puppeteer::IsolaatedWorld.new(@client, @frame_manager, self, @frame_manager.timeout_settings)
42
42
  end
43
43
 
44
44
  def page
@@ -49,7 +49,7 @@ class Puppeteer::Frame
49
49
  @client != @frame_manager.client
50
50
  end
51
51
 
52
- attr_accessor :frame_manager, :id, :loader_id, :lifecycle_events, :main_world, :secondary_world
52
+ attr_accessor :frame_manager, :id, :loader_id, :lifecycle_events, :main_world, :puppeteer_world
53
53
 
54
54
  def has_started_loading?
55
55
  @has_started_loading
@@ -154,14 +154,14 @@ class Puppeteer::Frame
154
154
 
155
155
  # @return [String]
156
156
  def content
157
- @secondary_world.content
157
+ @puppeteer_world.content
158
158
  end
159
159
 
160
160
  # @param html [String]
161
161
  # @param timeout [Integer]
162
162
  # @param wait_until [String|Array<String>]
163
163
  def set_content(html, timeout: nil, wait_until: nil)
164
- @secondary_world.set_content(html, timeout: timeout, wait_until: wait_until)
164
+ @puppeteer_world.set_content(html, timeout: timeout, wait_until: wait_until)
165
165
  end
166
166
 
167
167
  # @return [String]
@@ -212,35 +212,35 @@ class Puppeteer::Frame
212
212
  # @param button [String] "left"|"right"|"middle"
213
213
  # @param click_count [Number]
214
214
  def click(selector, delay: nil, button: nil, click_count: nil)
215
- @secondary_world.click(selector, delay: delay, button: button, click_count: click_count)
215
+ @puppeteer_world.click(selector, delay: delay, button: button, click_count: click_count)
216
216
  end
217
217
 
218
218
  define_async_method :async_click
219
219
 
220
220
  # @param {string} selector
221
221
  def focus(selector)
222
- @secondary_world.focus(selector)
222
+ @puppeteer_world.focus(selector)
223
223
  end
224
224
 
225
225
  define_async_method :async_focus
226
226
 
227
227
  # @param {string} selector
228
228
  def hover(selector)
229
- @secondary_world.hover(selector)
229
+ @puppeteer_world.hover(selector)
230
230
  end
231
231
 
232
232
  # @param {string} selector
233
233
  # @param {!Array<string>} values
234
234
  # @return {!Promise<!Array<string>>}
235
235
  def select(selector, *values)
236
- @secondary_world.select(selector, *values)
236
+ @puppeteer_world.select(selector, *values)
237
237
  end
238
238
 
239
239
  define_async_method :async_select
240
240
 
241
241
  # @param {string} selector
242
242
  def tap(selector)
243
- @secondary_world.tap(selector)
243
+ @puppeteer_world.tap(selector)
244
244
  end
245
245
 
246
246
  define_async_method :async_tap
@@ -259,14 +259,8 @@ class Puppeteer::Frame
259
259
  # @param hidden [Boolean] Wait for element invisible ('display: none' nor 'visibility: hidden') on true. default to false.
260
260
  # @param timeout [Integer]
261
261
  def wait_for_selector(selector, visible: nil, hidden: nil, timeout: nil)
262
- handle = @secondary_world.wait_for_selector(selector, visible: visible, hidden: hidden, timeout: timeout)
263
- if !handle
264
- return nil
265
- end
266
- main_execution_context = @main_world.execution_context
267
- result = main_execution_context.adopt_element_handle(handle)
268
- handle.dispose
269
- result
262
+ query_handler_manager = Puppeteer::QueryHandlerManager.instance
263
+ query_handler_manager.detect_query_handler(selector).wait_for(self, visible: visible, hidden: hidden, timeout: timeout)
270
264
  end
271
265
 
272
266
  define_async_method :async_wait_for_selector
@@ -306,7 +300,7 @@ class Puppeteer::Frame
306
300
 
307
301
  # @return [String]
308
302
  def title
309
- @secondary_world.title
303
+ @puppeteer_world.title
310
304
  end
311
305
 
312
306
  # @param frame_payload [Hash]
@@ -344,7 +338,7 @@ class Puppeteer::Frame
344
338
  def detach
345
339
  @detached = true
346
340
  @main_world.detach
347
- @secondary_world.detach
341
+ @puppeteer_world.detach
348
342
  if @parent_frame
349
343
  @parent_frame._child_frames.delete(self)
350
344
  end
@@ -413,11 +413,11 @@ class Puppeteer::FrameManager
413
413
 
414
414
  if context_payload.dig('auxData', 'isDefault')
415
415
  world = frame.main_world
416
- elsif context_payload['name'] == UTILITY_WORLD_NAME && !frame.secondary_world.has_context?
416
+ elsif context_payload['name'] == UTILITY_WORLD_NAME && !frame.puppeteer_world.has_context?
417
417
  # In case of multiple sessions to the same target, there's a race between
418
418
  # connections so we might end up creating multiple isolated worlds.
419
419
  # We can use either.
420
- world = frame.secondary_world
420
+ world = frame.puppeteer_world
421
421
  end
422
422
  end
423
423
 
@@ -1,7 +1,7 @@
1
1
  require 'thread'
2
2
 
3
- # https://github.com/puppeteer/puppeteer/blob/master/src/DOMWorld.js
4
- class Puppeteer::DOMWorld
3
+ # https://github.com/puppeteer/puppeteer/blob/master/src/IsolaatedWorld.js
4
+ class Puppeteer::IsolaatedWorld
5
5
  using Puppeteer::DefineAsyncMethod
6
6
 
7
7
  class BindingFunction
@@ -152,7 +152,7 @@ class Puppeteer::DOMWorld
152
152
  raise 'Bug of puppeteer-ruby...'
153
153
  end
154
154
 
155
- private def document
155
+ def document
156
156
  @document ||= evaluate_document.as_element
157
157
  end
158
158
 
@@ -416,16 +416,6 @@ class Puppeteer::DOMWorld
416
416
  handle.dispose
417
417
  end
418
418
 
419
- # @param selector [String]
420
- # @param visible [Boolean] Wait for element visible (not 'display: none' nor 'visibility: hidden') on true. default to false.
421
- # @param hidden [Boolean] Wait for element invisible ('display: none' nor 'visibility: hidden') on true. default to false.
422
- # @param timeout [Integer]
423
- def wait_for_selector(selector, visible: nil, hidden: nil, timeout: nil, root: nil)
424
- # call wait_for_selector_in_page with custom query selector.
425
- query_selector_manager = Puppeteer::QueryHandlerManager.instance
426
- query_selector_manager.detect_query_handler(selector).wait_for(self, visible: visible, hidden: hidden, timeout: timeout, root: root)
427
- end
428
-
429
419
  private def binding_identifier(name, context)
430
420
  "#{name}_#{context.send(:_context_id)}"
431
421
  end
@@ -497,7 +487,7 @@ class Puppeteer::DOMWorld
497
487
  # @param visible [Boolean] Wait for element visible (not 'display: none' nor 'visibility: hidden') on true. default to false.
498
488
  # @param hidden [Boolean] Wait for element invisible ('display: none' nor 'visibility: hidden') on true. default to false.
499
489
  # @param timeout [Integer]
500
- private def wait_for_selector_in_page(query_one, selector, visible: nil, hidden: nil, timeout: nil, root: nil, binding_function: nil)
490
+ private def wait_for_selector_in_page(query_one, root, selector, visible: nil, hidden: nil, timeout: nil, binding_function: nil)
501
491
  option_wait_for_visible = visible || false
502
492
  option_wait_for_hidden = hidden || false
503
493
  option_timeout = timeout || @timeout_settings.timeout
@@ -531,12 +521,7 @@ class Puppeteer::DOMWorld
531
521
  root: option_root,
532
522
  binding_function: binding_function,
533
523
  )
534
- handle = wait_task.await_promise
535
- unless handle.as_element
536
- handle.dispose
537
- return nil
538
- end
539
- handle.as_element
524
+ wait_task.await_promise
540
525
  end
541
526
 
542
527
  # @param page_function [String]
@@ -601,4 +586,35 @@ class Puppeteer::DOMWorld
601
586
  }
602
587
  JAVASCRIPT
603
588
  end
589
+
590
+ # @param backend_node_id [Integer]
591
+ # @return [Puppeteer::ElementHandle]
592
+ def adopt_backend_node(backend_node_id)
593
+ response = @client.send_message('DOM.resolveNode',
594
+ backendNodeId: backend_node_id,
595
+ executionContextId: execution_context.send(:_context_id),
596
+ )
597
+ Puppeteer::JSHandle.create(
598
+ context: execution_context,
599
+ remote_object: Puppeteer::RemoteObject.new(response["object"]),
600
+ )
601
+ end
602
+ private define_async_method :async_adopt_backend_node
603
+
604
+ # @param element_handle [Puppeteer::ElementHandle]
605
+ # @return [Puppeteer::ElementHandle]
606
+ def adopt_handle(element_handle)
607
+ if element_handle.execution_context == execution_context
608
+ raise ArgumentError.new('Cannot adopt handle that already belongs to this execution context')
609
+ end
610
+
611
+ node_info = element_handle.remote_object.node_info(@client)
612
+ adopt_backend_node(node_info["node"]["backendNodeId"])
613
+ end
614
+
615
+ def transfer_handle(element_handle)
616
+ result = adopt_handle(element_handle)
617
+ element_handle.dispose
618
+ result
619
+ end
604
620
  end
@@ -5,16 +5,12 @@ class Puppeteer::JSHandle
5
5
  # @param context [Puppeteer::ExecutionContext]
6
6
  # @param remote_object [Puppeteer::RemoteObject]
7
7
  def self.create(context:, remote_object:)
8
- frame = context.frame
9
- if remote_object.sub_type == 'node' && frame
10
- frame_manager = frame.frame_manager
8
+ if remote_object.sub_type == 'node' && context.world
11
9
  Puppeteer::ElementHandle.new(
12
10
  context: context,
13
11
  client: context.client,
14
12
  remote_object: remote_object,
15
- frame: frame,
16
- page: frame_manager.page,
17
- frame_manager: frame_manager,
13
+ frame: context.world.frame,
18
14
  )
19
15
  else
20
16
  Puppeteer::JSHandle.new(
@@ -93,13 +93,14 @@ class Puppeteer::LifecycleWatcher
93
93
  check_lifecycle_complete
94
94
  end
95
95
 
96
- class AnotherRequestReceivedError < StandardError ; end
97
-
98
96
  # @param [Puppeteer::HTTPRequest] request
99
97
  def handle_request(request)
100
98
  return if request.frame != @frame || !request.navigation_request?
101
99
  @navigation_request = request
102
- @navigation_response_received&.reject(AnotherRequestReceivedError.new('New navigation request was received'))
100
+ # Resolve previous navigation response in case there are multiple
101
+ # navigation requests reported by the backend. This generally should not
102
+ # happen by it looks like it's possible.
103
+ @navigation_response_received&.fulfill(nil)
103
104
  @navigation_response_received = resolvable_future
104
105
  if request.response && !@navigation_response_received.resolved?
105
106
  @navigation_response_received.fulfill(nil)
@@ -191,8 +191,7 @@ class Puppeteer::Page
191
191
  return if @file_chooser_interceptors.empty?
192
192
 
193
193
  frame = @frame_manager.frame(event['frameId'])
194
- context = frame.execution_context
195
- element = context.adopt_backend_node_id(event['backendNodeId'])
194
+ element = frame.main_world.adopt_backend_node(event['backendNodeId'])
196
195
  interceptors = @file_chooser_interceptors.to_a
197
196
  @file_chooser_interceptors.clear
198
197
  file_chooser = Puppeteer::FileChooser.new(element, event)
@@ -1070,7 +1069,8 @@ class Puppeteer::Page
1070
1069
  clip = if_present(screenshot_options.clip) do |rect|
1071
1070
  x = rect[:x].round
1072
1071
  y = rect[:y].round
1073
- { x: x, y: y, width: rect[:width] + rect[:x] - x, height: rect[:height] + rect[:y] - y, scale: 1 }
1072
+ scale = rect[:scale] || 1
1073
+ { x: x, y: y, width: rect[:width] + rect[:x] - x, height: rect[:height] + rect[:y] - y, scale: scale }
1074
1074
  end
1075
1075
 
1076
1076
  if screenshot_options.full_page?
@@ -61,8 +61,8 @@ class Puppeteer::QueryHandlerManager
61
61
  @query_handler.query_one(element_handle, @selector)
62
62
  end
63
63
 
64
- def wait_for(dom_world, visible:, hidden:, timeout:, root:)
65
- @query_handler.wait_for(dom_world, @selector, visible: visible, hidden: hidden, timeout: timeout, root: root)
64
+ def wait_for(element_or_frame, visible:, hidden:, timeout:)
65
+ @query_handler.wait_for(element_or_frame, @selector, visible: visible, hidden: hidden, timeout: timeout)
66
66
  end
67
67
 
68
68
  def query_all(element_handle)
@@ -105,8 +105,8 @@ class Puppeteer::RemoteObject
105
105
  role: role,
106
106
  }.compact)
107
107
 
108
- result['nodes'].reject do |node|
109
- node['role']['value'] == 'text'
108
+ result['nodes'].select do |node|
109
+ node['role'] && node['role']['value'] != 'StaticText'
110
110
  end
111
111
  end
112
112
 
@@ -1,3 +1,3 @@
1
1
  module Puppeteer
2
- VERSION = '0.43.1'
2
+ VERSION = '0.44.0'
3
3
  end
data/lib/puppeteer.rb CHANGED
@@ -32,7 +32,6 @@ require 'puppeteer/css_coverage'
32
32
  require 'puppeteer/custom_query_handler'
33
33
  require 'puppeteer/devices'
34
34
  require 'puppeteer/dialog'
35
- require 'puppeteer/dom_world'
36
35
  require 'puppeteer/emulation_manager'
37
36
  require 'puppeteer/exception_details'
38
37
  require 'puppeteer/executable_path_finder'
@@ -43,6 +42,7 @@ require 'puppeteer/frame'
43
42
  require 'puppeteer/frame_manager'
44
43
  require 'puppeteer/http_request'
45
44
  require 'puppeteer/http_response'
45
+ require 'puppeteer/isolated_world'
46
46
  require 'puppeteer/js_coverage'
47
47
  require 'puppeteer/js_handle'
48
48
  require 'puppeteer/keyboard'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: puppeteer-ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.43.1
4
+ version: 0.44.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - YusukeIwaki
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-09-18 00:00:00.000000000 Z
11
+ date: 2022-09-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: concurrent-ruby
@@ -272,7 +272,6 @@ files:
272
272
  - lib/puppeteer/device.rb
273
273
  - lib/puppeteer/devices.rb
274
274
  - lib/puppeteer/dialog.rb
275
- - lib/puppeteer/dom_world.rb
276
275
  - lib/puppeteer/element_handle.rb
277
276
  - lib/puppeteer/element_handle/bounding_box.rb
278
277
  - lib/puppeteer/element_handle/box_model.rb
@@ -294,6 +293,7 @@ files:
294
293
  - lib/puppeteer/http_request.rb
295
294
  - lib/puppeteer/http_response.rb
296
295
  - lib/puppeteer/if_present.rb
296
+ - lib/puppeteer/isolated_world.rb
297
297
  - lib/puppeteer/js_coverage.rb
298
298
  - lib/puppeteer/js_handle.rb
299
299
  - lib/puppeteer/keyboard.rb