puppeteer-ruby 0.50.0.alpha9 → 0.50.0.alpha10
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/docs/api_coverage.md +1 -1
- data/lib/puppeteer/connection.rb +43 -2
- data/lib/puppeteer/frame_manager.rb +74 -48
- data/lib/puppeteer/version.rb +1 -1
- data/sig/_supplementary.rbs +5 -3
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 6ad92e4a471db943a70ea1f6e928ba29e611cba0fc4b62b001bafb0cf444c797
|
|
4
|
+
data.tar.gz: 226103f1934651f038099e58a7b94414e248db9290f928c4fc2d4b262df59807
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 1ba290b15ba557824715b8aa82ad8695cdc9d08200381c7e004cb3c3fe63e041bc732e5e27f904e6bf75ff4eef51e6fdb905972d4225cfa495bbde9637a5f2ac
|
|
7
|
+
data.tar.gz: c7a208b38765265b77cef6f81dc1945daa6b4f4c09957c0b9b8e20484630a20a0359bbd3bbde26d5d88c1b55ea5c17cb02d522e358e294aa3db814685559a736
|
data/docs/api_coverage.md
CHANGED
data/lib/puppeteer/connection.rb
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
require 'json'
|
|
2
|
+
require 'async/queue'
|
|
2
3
|
|
|
3
4
|
class Puppeteer::Connection
|
|
4
5
|
include Puppeteer::DebugPrint
|
|
@@ -44,11 +45,16 @@ class Puppeteer::Connection
|
|
|
44
45
|
@delay = delay
|
|
45
46
|
@protocol_timeout = protocol_timeout
|
|
46
47
|
|
|
48
|
+
@network_message_queue = Async::Queue.new
|
|
49
|
+
@network_message_task = nil
|
|
50
|
+
|
|
47
51
|
@transport = transport
|
|
48
52
|
@transport.on_message do |data|
|
|
49
53
|
message = JSON.parse(data)
|
|
50
54
|
sleep_before_handling_message(message)
|
|
51
|
-
if
|
|
55
|
+
if network_event_message?(message)
|
|
56
|
+
enqueue_network_message(message)
|
|
57
|
+
elsif should_handle_synchronously?(message)
|
|
52
58
|
handle_message(message)
|
|
53
59
|
else
|
|
54
60
|
async_handle_message(message)
|
|
@@ -87,7 +93,8 @@ class Puppeteer::Connection
|
|
|
87
93
|
when nil
|
|
88
94
|
false
|
|
89
95
|
when /^Network\./
|
|
90
|
-
|
|
96
|
+
# Network events are queued for ordered async processing.
|
|
97
|
+
false
|
|
91
98
|
when /^Page\.frame/
|
|
92
99
|
# Page.frameAttached
|
|
93
100
|
# Page.frameNavigated
|
|
@@ -112,6 +119,34 @@ class Puppeteer::Connection
|
|
|
112
119
|
end
|
|
113
120
|
end
|
|
114
121
|
|
|
122
|
+
private def network_event_message?(message)
|
|
123
|
+
message['method']&.start_with?('Network.')
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
private def ensure_network_message_task
|
|
127
|
+
return if @network_message_task&.alive?
|
|
128
|
+
return unless Async::Task.current?
|
|
129
|
+
|
|
130
|
+
@network_message_task = Async do
|
|
131
|
+
while (queued = @network_message_queue.dequeue)
|
|
132
|
+
handle_message(queued)
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
private def enqueue_network_message(message)
|
|
138
|
+
if Async::Task.current?
|
|
139
|
+
ensure_network_message_task
|
|
140
|
+
begin
|
|
141
|
+
@network_message_queue.enqueue(message)
|
|
142
|
+
rescue Async::Queue::ClosedError
|
|
143
|
+
# Connection is closing; ignore late network events.
|
|
144
|
+
end
|
|
145
|
+
else
|
|
146
|
+
handle_message(message)
|
|
147
|
+
end
|
|
148
|
+
end
|
|
149
|
+
|
|
115
150
|
def self.from_session(session)
|
|
116
151
|
session.connection
|
|
117
152
|
end
|
|
@@ -310,6 +345,12 @@ class Puppeteer::Connection
|
|
|
310
345
|
@closed = true
|
|
311
346
|
@transport.on_message
|
|
312
347
|
@transport.on_close
|
|
348
|
+
@network_message_queue.close
|
|
349
|
+
begin
|
|
350
|
+
@network_message_task&.stop
|
|
351
|
+
rescue Async::Stop
|
|
352
|
+
# Task already stopping; ignore.
|
|
353
|
+
end
|
|
313
354
|
callbacks = @callbacks_mutex.synchronize do
|
|
314
355
|
@callbacks.values.tap { @callbacks.clear }
|
|
315
356
|
end
|
|
@@ -35,33 +35,48 @@ class Puppeteer::FrameManager
|
|
|
35
35
|
# Keeps track of frames that are in the process of being attached in #onFrameAttached.
|
|
36
36
|
@frames_pending_attachment = {}
|
|
37
37
|
@frame_tree_handled_promise = nil
|
|
38
|
-
@
|
|
38
|
+
@queued_frame_events = []
|
|
39
|
+
@frame_tree_mutex = Mutex.new
|
|
39
40
|
|
|
40
41
|
setup_listeners(@client)
|
|
41
42
|
end
|
|
42
43
|
|
|
43
44
|
private def setup_listeners(client)
|
|
44
45
|
client.on_event('Page.frameAttached') do |event|
|
|
45
|
-
|
|
46
|
+
with_frame_tree_handled do
|
|
47
|
+
handle_frame_attached(client, event['frameId'], event['parentFrameId'])
|
|
48
|
+
end
|
|
46
49
|
end
|
|
47
50
|
client.on_event('Page.frameNavigated') do |event|
|
|
48
|
-
|
|
49
|
-
|
|
51
|
+
with_frame_tree_handled do
|
|
52
|
+
@frame_naviigated_received << event['frame']['id']
|
|
53
|
+
handle_frame_navigated(event['frame'])
|
|
54
|
+
end
|
|
50
55
|
end
|
|
51
56
|
client.on_event('Page.navigatedWithinDocument') do |event|
|
|
52
|
-
|
|
57
|
+
with_frame_tree_handled do
|
|
58
|
+
handle_frame_navigated_within_document(event['frameId'], event['url'])
|
|
59
|
+
end
|
|
53
60
|
end
|
|
54
61
|
client.on_event('Page.frameDetached') do |event|
|
|
55
|
-
|
|
62
|
+
with_frame_tree_handled do
|
|
63
|
+
handle_frame_detached(event['frameId'], event['reason'])
|
|
64
|
+
end
|
|
56
65
|
end
|
|
57
66
|
client.on_event('Page.frameStartedLoading') do |event|
|
|
58
|
-
|
|
67
|
+
with_frame_tree_handled do
|
|
68
|
+
handle_frame_started_loading(event['frameId'])
|
|
69
|
+
end
|
|
59
70
|
end
|
|
60
71
|
client.on_event('Page.frameStoppedLoading') do |event|
|
|
61
|
-
|
|
72
|
+
with_frame_tree_handled do
|
|
73
|
+
handle_frame_stopped_loading(event['frameId'])
|
|
74
|
+
end
|
|
62
75
|
end
|
|
63
76
|
client.on_event('Runtime.executionContextCreated') do |event|
|
|
64
|
-
|
|
77
|
+
with_frame_tree_handled do
|
|
78
|
+
handle_execution_context_created(event['context'], client)
|
|
79
|
+
end
|
|
65
80
|
end
|
|
66
81
|
client.on_event('Runtime.executionContextDestroyed') do |event|
|
|
67
82
|
handle_execution_context_destroyed(event['executionContextId'], client)
|
|
@@ -70,7 +85,9 @@ class Puppeteer::FrameManager
|
|
|
70
85
|
handle_execution_contexts_cleared(client)
|
|
71
86
|
end
|
|
72
87
|
client.on_event('Page.lifecycleEvent') do |event|
|
|
73
|
-
|
|
88
|
+
with_frame_tree_handled do
|
|
89
|
+
handle_lifecycle_event(event)
|
|
90
|
+
end
|
|
74
91
|
end
|
|
75
92
|
end
|
|
76
93
|
|
|
@@ -98,15 +115,13 @@ class Puppeteer::FrameManager
|
|
|
98
115
|
rescue => err
|
|
99
116
|
# The target might have been closed before the initialization finished.
|
|
100
117
|
if err.message.include?('Target closed') || err.message.include?('Session closed')
|
|
101
|
-
finish_frame_tree_handling
|
|
118
|
+
finish_frame_tree_handling
|
|
102
119
|
return
|
|
103
120
|
end
|
|
104
121
|
|
|
105
122
|
raise
|
|
106
123
|
ensure
|
|
107
|
-
if @frame_tree_handled_promise && !@frame_tree_handled_promise.resolved?
|
|
108
|
-
finish_frame_tree_handling(process_queue: false)
|
|
109
|
-
end
|
|
124
|
+
finish_frame_tree_handling if @frame_tree_handled_promise && !@frame_tree_handled_promise.resolved?
|
|
110
125
|
@frames_pending_target_init.delete(target_id)&.resolve(nil)
|
|
111
126
|
end
|
|
112
127
|
|
|
@@ -224,21 +239,52 @@ class Puppeteer::FrameManager
|
|
|
224
239
|
|
|
225
240
|
# @param event [Hash]
|
|
226
241
|
def handle_lifecycle_event(event)
|
|
227
|
-
if @frame_tree_handled_promise && !@frame_tree_handled_promise.resolved?
|
|
228
|
-
@queued_lifecycle_events << event
|
|
229
|
-
return
|
|
230
|
-
end
|
|
231
|
-
|
|
232
|
-
handle_lifecycle_event_impl(event)
|
|
233
|
-
end
|
|
234
|
-
|
|
235
|
-
private def handle_lifecycle_event_impl(event)
|
|
236
242
|
frame = @frames[event['frameId']]
|
|
237
243
|
return if !frame
|
|
238
244
|
frame.handle_lifecycle_event(event['loaderId'], event['name'])
|
|
239
245
|
emit_event(FrameManagerEmittedEvents::LifecycleEvent, frame)
|
|
240
246
|
end
|
|
241
247
|
|
|
248
|
+
private def with_frame_tree_handled(&block)
|
|
249
|
+
promise = @frame_tree_handled_promise
|
|
250
|
+
if promise && !promise.resolved?
|
|
251
|
+
queued = false
|
|
252
|
+
@frame_tree_mutex.synchronize do
|
|
253
|
+
promise = @frame_tree_handled_promise
|
|
254
|
+
if promise && !promise.resolved?
|
|
255
|
+
@queued_frame_events << block
|
|
256
|
+
queued = true
|
|
257
|
+
end
|
|
258
|
+
end
|
|
259
|
+
return if queued
|
|
260
|
+
end
|
|
261
|
+
block.call
|
|
262
|
+
end
|
|
263
|
+
|
|
264
|
+
private def prepare_frame_tree_handling
|
|
265
|
+
queued = nil
|
|
266
|
+
@frame_tree_mutex.synchronize do
|
|
267
|
+
if @frame_tree_handled_promise && !@frame_tree_handled_promise.resolved?
|
|
268
|
+
@frame_tree_handled_promise.resolve(nil)
|
|
269
|
+
queued = @queued_frame_events
|
|
270
|
+
end
|
|
271
|
+
@queued_frame_events = []
|
|
272
|
+
@frame_tree_handled_promise = Async::Promise.new
|
|
273
|
+
end
|
|
274
|
+
queued&.each(&:call)
|
|
275
|
+
end
|
|
276
|
+
|
|
277
|
+
private def finish_frame_tree_handling
|
|
278
|
+
queued = nil
|
|
279
|
+
@frame_tree_mutex.synchronize do
|
|
280
|
+
return unless @frame_tree_handled_promise
|
|
281
|
+
@frame_tree_handled_promise.resolve(nil) unless @frame_tree_handled_promise.resolved?
|
|
282
|
+
queued = @queued_frame_events
|
|
283
|
+
@queued_frame_events = []
|
|
284
|
+
end
|
|
285
|
+
queued&.each(&:call)
|
|
286
|
+
end
|
|
287
|
+
|
|
242
288
|
# @param frame_id [String]
|
|
243
289
|
def handle_frame_started_loading(frame_id)
|
|
244
290
|
frame = @frames[frame_id]
|
|
@@ -270,29 +316,6 @@ class Puppeteer::FrameManager
|
|
|
270
316
|
end
|
|
271
317
|
end
|
|
272
318
|
|
|
273
|
-
private def prepare_frame_tree_handling
|
|
274
|
-
if @frame_tree_handled_promise && !@frame_tree_handled_promise.resolved?
|
|
275
|
-
@frame_tree_handled_promise.resolve(nil)
|
|
276
|
-
end
|
|
277
|
-
@frame_tree_handled_promise = Async::Promise.new
|
|
278
|
-
@queued_lifecycle_events = []
|
|
279
|
-
end
|
|
280
|
-
|
|
281
|
-
private def finish_frame_tree_handling(process_queue: true)
|
|
282
|
-
return unless @frame_tree_handled_promise
|
|
283
|
-
|
|
284
|
-
@frame_tree_handled_promise.resolve(nil) unless @frame_tree_handled_promise.resolved?
|
|
285
|
-
flush_queued_lifecycle_events if process_queue
|
|
286
|
-
end
|
|
287
|
-
|
|
288
|
-
private def flush_queued_lifecycle_events
|
|
289
|
-
return if @queued_lifecycle_events.empty?
|
|
290
|
-
|
|
291
|
-
queued = @queued_lifecycle_events
|
|
292
|
-
@queued_lifecycle_events = []
|
|
293
|
-
queued.each { |event| handle_lifecycle_event_impl(event) }
|
|
294
|
-
end
|
|
295
|
-
|
|
296
319
|
# @return {!Puppeteer.Page}
|
|
297
320
|
def page
|
|
298
321
|
@page
|
|
@@ -394,8 +417,11 @@ class Puppeteer::FrameManager
|
|
|
394
417
|
if is_main_frame
|
|
395
418
|
if frame
|
|
396
419
|
# Update frame id to retain frame identity on cross-process navigation.
|
|
397
|
-
|
|
398
|
-
|
|
420
|
+
if frame.id != frame_id
|
|
421
|
+
old_frame_id = frame.id
|
|
422
|
+
@frames.delete(old_frame_id)
|
|
423
|
+
frame.id = frame_id
|
|
424
|
+
end
|
|
399
425
|
else
|
|
400
426
|
# Initial main frame navigation.
|
|
401
427
|
frame = Puppeteer::Frame.new(self, nil, frame_id, @client)
|
data/lib/puppeteer/version.rb
CHANGED
data/sig/_supplementary.rbs
CHANGED
|
@@ -178,10 +178,9 @@ class Puppeteer::FrameManager
|
|
|
178
178
|
|
|
179
179
|
def setup_listeners: (Puppeteer::CDPSession client) -> void
|
|
180
180
|
def init: (String target_id, ?Puppeteer::CDPSession cdp_session) -> void
|
|
181
|
-
def
|
|
181
|
+
def with_frame_tree_handled: () { () -> void } -> void
|
|
182
182
|
def prepare_frame_tree_handling: () -> void
|
|
183
|
-
def finish_frame_tree_handling: (
|
|
184
|
-
def flush_queued_lifecycle_events: () -> void
|
|
183
|
+
def finish_frame_tree_handling: () -> void
|
|
185
184
|
def attach_child_frame: (Puppeteer::Frame parent_frame, String parent_frame_id, String frame_id, Puppeteer::CDPSession? session) -> void
|
|
186
185
|
def reattach_frame: (Puppeteer::Frame frame, String frame_id, bool is_main_frame, Hash[String, untyped] frame_payload) -> void
|
|
187
186
|
def ensure_isolated_world: (Puppeteer::CDPSession session, String name) -> void
|
|
@@ -290,6 +289,9 @@ class Puppeteer::Connection
|
|
|
290
289
|
|
|
291
290
|
def sleep_before_handling_message: (Hash[String, untyped] message) -> void
|
|
292
291
|
def should_handle_synchronously?: (Hash[String, untyped] message) -> bool
|
|
292
|
+
def network_event_message?: (Hash[String, untyped] message) -> bool
|
|
293
|
+
def ensure_network_message_task: () -> void
|
|
294
|
+
def enqueue_network_message: (Hash[String, untyped] message) -> void
|
|
293
295
|
def request_debug_printer: () -> untyped
|
|
294
296
|
def response_debug_printer: () -> untyped
|
|
295
297
|
def handle_message: (Hash[String, untyped] message) -> void
|
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.50.0.
|
|
4
|
+
version: 0.50.0.alpha10
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- YusukeIwaki
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-01-
|
|
11
|
+
date: 2026-01-25 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: async
|