cuprite 0.6.0 → 0.7.1
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/README.md +100 -67
- data/lib/capybara/cuprite/browser.rb +66 -224
- data/lib/capybara/cuprite/driver.rb +101 -48
- data/lib/capybara/cuprite/errors.rb +1 -64
- data/lib/capybara/cuprite/{browser/javascripts → javascripts}/index.js +26 -20
- data/lib/capybara/cuprite/node.rb +37 -31
- data/lib/capybara/cuprite/page.rb +166 -0
- data/lib/capybara/cuprite/version.rb +1 -1
- data/lib/capybara/cuprite.rb +8 -21
- metadata +8 -42
- data/lib/capybara/cuprite/browser/client.rb +0 -74
- data/lib/capybara/cuprite/browser/dom.rb +0 -50
- data/lib/capybara/cuprite/browser/frame.rb +0 -115
- data/lib/capybara/cuprite/browser/input.json +0 -1341
- data/lib/capybara/cuprite/browser/input.rb +0 -200
- data/lib/capybara/cuprite/browser/net.rb +0 -90
- data/lib/capybara/cuprite/browser/page.rb +0 -378
- data/lib/capybara/cuprite/browser/process.rb +0 -223
- data/lib/capybara/cuprite/browser/runtime.rb +0 -182
- data/lib/capybara/cuprite/browser/targets.rb +0 -129
- data/lib/capybara/cuprite/browser/web_socket.rb +0 -69
- data/lib/capybara/cuprite/network/error.rb +0 -25
- data/lib/capybara/cuprite/network/request.rb +0 -33
- data/lib/capybara/cuprite/network/response.rb +0 -44
@@ -0,0 +1,166 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Capybara::Cuprite
|
4
|
+
module Page
|
5
|
+
MODAL_WAIT = ENV.fetch("CUPRITE_MODAL_WAIT", 0.05).to_f
|
6
|
+
|
7
|
+
def initialize(*args)
|
8
|
+
super
|
9
|
+
@accept_modal = []
|
10
|
+
@modal_messages = []
|
11
|
+
end
|
12
|
+
|
13
|
+
def set(node, value)
|
14
|
+
object_id = command("DOM.resolveNode", nodeId: node.node_id).dig("object", "objectId")
|
15
|
+
evaluate("_cuprite.set(arguments[0], arguments[1])", { "objectId" => object_id }, value)
|
16
|
+
end
|
17
|
+
|
18
|
+
def select(node, value)
|
19
|
+
evaluate_on(node: node, expression: "_cuprite.select(this, #{value})")
|
20
|
+
end
|
21
|
+
|
22
|
+
def trigger(node, event)
|
23
|
+
options = {}
|
24
|
+
options.merge!(wait: Ferrum::Mouse::CLICK_WAIT) if event.to_s == "click"
|
25
|
+
evaluate_on(node: node, expression: %(_cuprite.trigger(this, "#{event}")), **options)
|
26
|
+
end
|
27
|
+
|
28
|
+
def hover(node)
|
29
|
+
evaluate_on(node: node, expression: "_cuprite.scrollIntoViewport(this)")
|
30
|
+
x, y = find_position(node)
|
31
|
+
command("Input.dispatchMouseEvent", type: "mouseMoved", x: x, y: y)
|
32
|
+
end
|
33
|
+
|
34
|
+
def send_keys(node, keys)
|
35
|
+
if !evaluate_on(node: node, expression: %(_cuprite.containsSelection(this)))
|
36
|
+
before_click(node, "click")
|
37
|
+
node.click(mode: :left, keys: keys)
|
38
|
+
end
|
39
|
+
|
40
|
+
keyboard.type(keys)
|
41
|
+
end
|
42
|
+
|
43
|
+
def accept_confirm
|
44
|
+
@accept_modal << true
|
45
|
+
end
|
46
|
+
|
47
|
+
def dismiss_confirm
|
48
|
+
@accept_modal << false
|
49
|
+
end
|
50
|
+
|
51
|
+
def accept_prompt(modal_response)
|
52
|
+
@accept_modal << true
|
53
|
+
@modal_response = modal_response
|
54
|
+
end
|
55
|
+
|
56
|
+
def dismiss_prompt
|
57
|
+
@accept_modal << false
|
58
|
+
end
|
59
|
+
|
60
|
+
def find_modal(options)
|
61
|
+
start = Ferrum.monotonic_time
|
62
|
+
timeout = options.fetch(:wait) { session_wait_time }
|
63
|
+
expect_text = options[:text]
|
64
|
+
expect_regexp = expect_text.is_a?(Regexp) ? expect_text : Regexp.escape(expect_text.to_s)
|
65
|
+
not_found_msg = "Unable to find modal dialog"
|
66
|
+
not_found_msg += " with #{expect_text}" if expect_text
|
67
|
+
|
68
|
+
begin
|
69
|
+
modal_text = @modal_messages.shift
|
70
|
+
raise Capybara::ModalNotFound if modal_text.nil? || (expect_text && !modal_text.match(expect_regexp))
|
71
|
+
rescue Capybara::ModalNotFound => e
|
72
|
+
raise e, not_found_msg if Ferrum.timeout?(start, timeout)
|
73
|
+
sleep(MODAL_WAIT)
|
74
|
+
retry
|
75
|
+
end
|
76
|
+
|
77
|
+
modal_text
|
78
|
+
end
|
79
|
+
|
80
|
+
def reset_modals
|
81
|
+
@accept_modal = []
|
82
|
+
@modal_response = nil
|
83
|
+
@modal_messages = []
|
84
|
+
end
|
85
|
+
|
86
|
+
def before_click(node, name, keys = [], offset = {})
|
87
|
+
evaluate_on(node: node, expression: "_cuprite.scrollIntoViewport(this)")
|
88
|
+
x, y = find_position(node, offset[:x], offset[:y])
|
89
|
+
evaluate_on(node: node, expression: "_cuprite.mouseEventTest(this, '#{name}', #{x}, #{y})")
|
90
|
+
true
|
91
|
+
rescue Ferrum::JavaScriptError => e
|
92
|
+
raise MouseEventFailed.new(e.message) if e.class_name == "MouseEventFailed"
|
93
|
+
end
|
94
|
+
|
95
|
+
def switch_to_frame(handle)
|
96
|
+
case handle
|
97
|
+
when :parent
|
98
|
+
@frame_stack.pop
|
99
|
+
when :top
|
100
|
+
@frame_stack = []
|
101
|
+
else
|
102
|
+
@frame_stack << handle
|
103
|
+
inject_extensions
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
private
|
108
|
+
|
109
|
+
def prepare_page
|
110
|
+
super
|
111
|
+
|
112
|
+
network.intercept if !Array(@browser.url_whitelist).empty? ||
|
113
|
+
!Array(@browser.url_blacklist).empty?
|
114
|
+
|
115
|
+
on(:request) do |request, index, total|
|
116
|
+
if @browser.url_blacklist && !@browser.url_blacklist.empty?
|
117
|
+
if @browser.url_blacklist.any? { |r| request.match?(r) }
|
118
|
+
request.abort and return
|
119
|
+
else
|
120
|
+
request.continue and return
|
121
|
+
end
|
122
|
+
elsif @browser.url_whitelist && !@browser.url_whitelist.empty?
|
123
|
+
if @browser.url_whitelist.any? { |r| request.match?(r) }
|
124
|
+
request.continue and return
|
125
|
+
else
|
126
|
+
request.abort and return
|
127
|
+
end
|
128
|
+
elsif index + 1 < total
|
129
|
+
# There are other callbacks that may handle this request
|
130
|
+
next
|
131
|
+
else
|
132
|
+
# If there are no callbacks then just continue
|
133
|
+
request.continue
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
on("Page.javascriptDialogOpening") do |params|
|
138
|
+
accept_modal = @accept_modal.last
|
139
|
+
if accept_modal == true || accept_modal == false
|
140
|
+
@accept_modal.pop
|
141
|
+
@modal_messages << params["message"]
|
142
|
+
options = { accept: accept_modal }
|
143
|
+
response = @modal_response || params["defaultPrompt"]
|
144
|
+
options.merge!(promptText: response) if response
|
145
|
+
command("Page.handleJavaScriptDialog", **options)
|
146
|
+
else
|
147
|
+
warn "Modal window has been opened, but you didn't wrap your code into (`accept_prompt` | `dismiss_prompt` | `accept_confirm` | `dismiss_confirm` | `accept_alert`), accepting by default"
|
148
|
+
options = { accept: true }
|
149
|
+
response = params["defaultPrompt"]
|
150
|
+
options.merge!(promptText: response) if response
|
151
|
+
command("Page.handleJavaScriptDialog", **options)
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
def find_position(node, *args)
|
157
|
+
x, y = node.find_position(*args)
|
158
|
+
rescue Ferrum::BrowserError => e
|
159
|
+
if e.message == "Could not compute content quads."
|
160
|
+
raise MouseEventFailed.new("MouseEventFailed: click, none, 0, 0")
|
161
|
+
else
|
162
|
+
raise
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
data/lib/capybara/cuprite.rb
CHANGED
@@ -1,31 +1,18 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "ferrum"
|
3
4
|
require "capybara"
|
4
5
|
|
5
|
-
Thread.abort_on_exception = true
|
6
|
-
Thread.report_on_exception = true if Thread.respond_to?(:report_on_exception=)
|
7
|
-
|
8
6
|
module Capybara::Cuprite
|
9
|
-
|
10
|
-
require "capybara/cuprite/browser"
|
11
|
-
require "capybara/cuprite/node"
|
12
|
-
require "capybara/cuprite/errors"
|
13
|
-
require "capybara/cuprite/cookie"
|
14
|
-
|
15
|
-
class << self
|
16
|
-
def windows?
|
17
|
-
RbConfig::CONFIG["host_os"] =~ /mingw|mswin|cygwin/
|
18
|
-
end
|
7
|
+
end
|
19
8
|
|
20
|
-
|
21
|
-
|
22
|
-
|
9
|
+
require "capybara/cuprite/driver"
|
10
|
+
require "capybara/cuprite/browser"
|
11
|
+
require "capybara/cuprite/page"
|
12
|
+
require "capybara/cuprite/node"
|
13
|
+
require "capybara/cuprite/errors"
|
23
14
|
|
24
|
-
|
25
|
-
defined?(RUBY_ENGINE) && RUBY_ENGINE == "ruby"
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
15
|
+
Ferrum::Page.prepend(Capybara::Cuprite::Page)
|
29
16
|
|
30
17
|
Capybara.register_driver(:cuprite) do |app|
|
31
18
|
Capybara::Cuprite::Driver.new(app)
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cuprite
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.7.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dmitry Vorotilin
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-
|
11
|
+
date: 2019-09-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: capybara
|
@@ -31,39 +31,19 @@ dependencies:
|
|
31
31
|
- !ruby/object:Gem::Version
|
32
32
|
version: '4'
|
33
33
|
- !ruby/object:Gem::Dependency
|
34
|
-
name:
|
34
|
+
name: ferrum
|
35
35
|
requirement: !ruby/object:Gem::Requirement
|
36
36
|
requirements:
|
37
37
|
- - ">="
|
38
38
|
- !ruby/object:Gem::Version
|
39
|
-
version:
|
40
|
-
- - "<"
|
41
|
-
- !ruby/object:Gem::Version
|
42
|
-
version: '0.8'
|
39
|
+
version: 0.2.1
|
43
40
|
type: :runtime
|
44
41
|
prerelease: false
|
45
42
|
version_requirements: !ruby/object:Gem::Requirement
|
46
43
|
requirements:
|
47
44
|
- - ">="
|
48
45
|
- !ruby/object:Gem::Version
|
49
|
-
version:
|
50
|
-
- - "<"
|
51
|
-
- !ruby/object:Gem::Version
|
52
|
-
version: '0.8'
|
53
|
-
- !ruby/object:Gem::Dependency
|
54
|
-
name: cliver
|
55
|
-
requirement: !ruby/object:Gem::Requirement
|
56
|
-
requirements:
|
57
|
-
- - "~>"
|
58
|
-
- !ruby/object:Gem::Version
|
59
|
-
version: '0.3'
|
60
|
-
type: :runtime
|
61
|
-
prerelease: false
|
62
|
-
version_requirements: !ruby/object:Gem::Requirement
|
63
|
-
requirements:
|
64
|
-
- - "~>"
|
65
|
-
- !ruby/object:Gem::Version
|
66
|
-
version: '0.3'
|
46
|
+
version: 0.2.1
|
67
47
|
- !ruby/object:Gem::Dependency
|
68
48
|
name: image_size
|
69
49
|
requirement: !ruby/object:Gem::Requirement
|
@@ -202,25 +182,12 @@ files:
|
|
202
182
|
- README.md
|
203
183
|
- lib/capybara/cuprite.rb
|
204
184
|
- lib/capybara/cuprite/browser.rb
|
205
|
-
- lib/capybara/cuprite/browser/client.rb
|
206
|
-
- lib/capybara/cuprite/browser/dom.rb
|
207
|
-
- lib/capybara/cuprite/browser/frame.rb
|
208
|
-
- lib/capybara/cuprite/browser/input.json
|
209
|
-
- lib/capybara/cuprite/browser/input.rb
|
210
|
-
- lib/capybara/cuprite/browser/javascripts/index.js
|
211
|
-
- lib/capybara/cuprite/browser/net.rb
|
212
|
-
- lib/capybara/cuprite/browser/page.rb
|
213
|
-
- lib/capybara/cuprite/browser/process.rb
|
214
|
-
- lib/capybara/cuprite/browser/runtime.rb
|
215
|
-
- lib/capybara/cuprite/browser/targets.rb
|
216
|
-
- lib/capybara/cuprite/browser/web_socket.rb
|
217
185
|
- lib/capybara/cuprite/cookie.rb
|
218
186
|
- lib/capybara/cuprite/driver.rb
|
219
187
|
- lib/capybara/cuprite/errors.rb
|
220
|
-
- lib/capybara/cuprite/
|
221
|
-
- lib/capybara/cuprite/network/request.rb
|
222
|
-
- lib/capybara/cuprite/network/response.rb
|
188
|
+
- lib/capybara/cuprite/javascripts/index.js
|
223
189
|
- lib/capybara/cuprite/node.rb
|
190
|
+
- lib/capybara/cuprite/page.rb
|
224
191
|
- lib/capybara/cuprite/version.rb
|
225
192
|
homepage: https://github.com/machinio/cuprite
|
226
193
|
licenses:
|
@@ -241,8 +208,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
241
208
|
- !ruby/object:Gem::Version
|
242
209
|
version: '0'
|
243
210
|
requirements: []
|
244
|
-
|
245
|
-
rubygems_version: 2.7.6
|
211
|
+
rubygems_version: 3.0.3
|
246
212
|
signing_key:
|
247
213
|
specification_version: 4
|
248
214
|
summary: Headless Chrome driver for Capybara
|
@@ -1,74 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "timeout"
|
4
|
-
require "capybara/cuprite/browser/web_socket"
|
5
|
-
|
6
|
-
module Capybara::Cuprite
|
7
|
-
class Browser
|
8
|
-
class Client
|
9
|
-
class IdError < RuntimeError; end
|
10
|
-
|
11
|
-
def initialize(browser, ws_url, allow_slowmo = true)
|
12
|
-
@command_id = 0
|
13
|
-
@subscribed = Hash.new { |h, k| h[k] = [] }
|
14
|
-
@browser, @allow_slowmo = browser, allow_slowmo
|
15
|
-
@commands = Queue.new
|
16
|
-
@ws = WebSocket.new(ws_url, @browser.logger)
|
17
|
-
|
18
|
-
@thread = Thread.new do
|
19
|
-
while message = @ws.messages.pop
|
20
|
-
method, params = message.values_at("method", "params")
|
21
|
-
if method
|
22
|
-
@subscribed[method].each { |b| b.call(params) }
|
23
|
-
else
|
24
|
-
@commands.push(message)
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
@commands.close
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
def command(method, params = {})
|
33
|
-
message = build_message(method, params)
|
34
|
-
sleep(@browser.slowmo) if !@browser.slowmo.nil? && @allow_slowmo
|
35
|
-
@ws.send_message(message)
|
36
|
-
message[:id]
|
37
|
-
end
|
38
|
-
|
39
|
-
def wait(id:)
|
40
|
-
message = Timeout.timeout(@browser.timeout, TimeoutError) { @commands.pop }
|
41
|
-
raise DeadBrowser unless message
|
42
|
-
raise IdError if message["id"] != id
|
43
|
-
error, response = message.values_at("error", "result")
|
44
|
-
raise BrowserError.new(error) if error
|
45
|
-
response
|
46
|
-
rescue IdError
|
47
|
-
retry
|
48
|
-
end
|
49
|
-
|
50
|
-
def subscribe(event, &block)
|
51
|
-
@subscribed[event] << block
|
52
|
-
true
|
53
|
-
end
|
54
|
-
|
55
|
-
def close
|
56
|
-
@ws.close
|
57
|
-
# Give a thread some time to handle a tail of messages
|
58
|
-
Timeout.timeout(1) { @thread.join }
|
59
|
-
rescue Timeout::Error
|
60
|
-
@thread.kill
|
61
|
-
end
|
62
|
-
|
63
|
-
private
|
64
|
-
|
65
|
-
def build_message(method, params)
|
66
|
-
{ method: method, params: params }.merge(id: next_command_id)
|
67
|
-
end
|
68
|
-
|
69
|
-
def next_command_id
|
70
|
-
@command_id += 1
|
71
|
-
end
|
72
|
-
end
|
73
|
-
end
|
74
|
-
end
|
@@ -1,50 +0,0 @@
|
|
1
|
-
module Capybara::Cuprite
|
2
|
-
class Browser
|
3
|
-
module DOM
|
4
|
-
def current_url
|
5
|
-
evaluate_in(execution_context_id, "window.top.location.href")
|
6
|
-
end
|
7
|
-
|
8
|
-
def title
|
9
|
-
evaluate_in(execution_context_id, "window.top.document.title")
|
10
|
-
end
|
11
|
-
|
12
|
-
def body
|
13
|
-
evaluate("document.documentElement.outerHTML")
|
14
|
-
end
|
15
|
-
|
16
|
-
def all_text(node)
|
17
|
-
evaluate_on(node: node, expr: "this.textContent")
|
18
|
-
end
|
19
|
-
|
20
|
-
def property(node, name)
|
21
|
-
evaluate_on(node: node, expr: %Q(this["#{name}"]))
|
22
|
-
end
|
23
|
-
|
24
|
-
def attributes(node)
|
25
|
-
value = evaluate_on(node: node, expr: "_cuprite.getAttributes(this)")
|
26
|
-
JSON.parse(value)
|
27
|
-
end
|
28
|
-
|
29
|
-
def attribute(node, name)
|
30
|
-
evaluate_on(node: node, expr: %Q(_cuprite.getAttribute(this, "#{name}")))
|
31
|
-
end
|
32
|
-
|
33
|
-
def value(node)
|
34
|
-
evaluate_on(node: node, expr: "_cuprite.value(this)")
|
35
|
-
end
|
36
|
-
|
37
|
-
def visible?(node)
|
38
|
-
evaluate_on(node: node, expr: "_cuprite.isVisible(this)")
|
39
|
-
end
|
40
|
-
|
41
|
-
def disabled?(node)
|
42
|
-
evaluate_on(node: node, expr: "_cuprite.isDisabled(this)")
|
43
|
-
end
|
44
|
-
|
45
|
-
def path(node)
|
46
|
-
evaluate_on(node: node, expr: "_cuprite.path(this)")
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|
50
|
-
end
|
@@ -1,115 +0,0 @@
|
|
1
|
-
module Capybara::Cuprite
|
2
|
-
class Browser
|
3
|
-
module Frame
|
4
|
-
def execution_context_id
|
5
|
-
@mutex.synchronize do
|
6
|
-
if !@frame_stack.empty?
|
7
|
-
@frames[@frame_stack.last]["execution_context_id"]
|
8
|
-
else
|
9
|
-
@execution_context_id
|
10
|
-
end
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
|
-
def frame_name
|
15
|
-
evaluate("window.name")
|
16
|
-
end
|
17
|
-
|
18
|
-
def frame_url
|
19
|
-
evaluate("window.location.href")
|
20
|
-
end
|
21
|
-
|
22
|
-
def frame_title
|
23
|
-
evaluate("document.title")
|
24
|
-
end
|
25
|
-
|
26
|
-
def switch_to_frame(handle)
|
27
|
-
case handle
|
28
|
-
when Capybara::Node::Base
|
29
|
-
@frame_stack << handle.native.node["frameId"]
|
30
|
-
inject_extensions
|
31
|
-
when :parent
|
32
|
-
@frame_stack.pop
|
33
|
-
when :top
|
34
|
-
@frame_stack = []
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
private
|
39
|
-
|
40
|
-
def subscribe_events
|
41
|
-
super if defined?(super)
|
42
|
-
|
43
|
-
@client.subscribe("Page.frameAttached") do |params|
|
44
|
-
@frames[params["frameId"]] = { "parent_id" => params["parentFrameId"] }
|
45
|
-
end
|
46
|
-
|
47
|
-
@client.subscribe("Page.frameStartedLoading") do |params|
|
48
|
-
@waiting_frames << params["frameId"]
|
49
|
-
@mutex.try_lock
|
50
|
-
end
|
51
|
-
|
52
|
-
@client.subscribe("Page.frameNavigated") do |params|
|
53
|
-
id = params["frame"]["id"]
|
54
|
-
if frame = @frames[id]
|
55
|
-
frame.merge!(params["frame"].select { |k, v| k == "name" || k == "url" })
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
@client.subscribe("Page.frameScheduledNavigation") do |params|
|
60
|
-
# Trying to lock mutex if frame is the main frame
|
61
|
-
@waiting_frames << params["frameId"]
|
62
|
-
@mutex.try_lock
|
63
|
-
end
|
64
|
-
|
65
|
-
@client.subscribe("Page.frameStoppedLoading") do |params|
|
66
|
-
# `DOM.performSearch` doesn't work without getting #document node first.
|
67
|
-
# It returns node with nodeId 1 and nodeType 9 from which descend the
|
68
|
-
# tree and we save it in a variable because if we call that again root
|
69
|
-
# node will change the id and all subsequent nodes have to change id too.
|
70
|
-
# `command` is not allowed in the block as it will deadlock the process.
|
71
|
-
if params["frameId"] == @frame_id
|
72
|
-
signal if @waiting_frames.empty?
|
73
|
-
@client.command("DOM.getDocument", depth: 0)
|
74
|
-
end
|
75
|
-
|
76
|
-
if @waiting_frames.include?(params["frameId"])
|
77
|
-
@waiting_frames.delete(params["frameId"])
|
78
|
-
signal if @waiting_frames.empty?
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
|
-
@client.subscribe("Runtime.executionContextCreated") do |params|
|
83
|
-
frame_id = params.dig("context", "auxData", "frameId")
|
84
|
-
execution_context_id = params.dig("context", "id")
|
85
|
-
|
86
|
-
# Remember the very first frame since it's the main one
|
87
|
-
@frame_id ||= frame_id
|
88
|
-
@execution_context_id ||= execution_context_id
|
89
|
-
|
90
|
-
if @frames[frame_id]
|
91
|
-
@frames[frame_id].merge!("execution_context_id" => execution_context_id)
|
92
|
-
else
|
93
|
-
@frames[frame_id] = { "execution_context_id" => execution_context_id }
|
94
|
-
end
|
95
|
-
end
|
96
|
-
|
97
|
-
@client.subscribe("Runtime.executionContextDestroyed") do |params|
|
98
|
-
execution_context_id = params["executionContextId"]
|
99
|
-
id, frame = @frames.find { |_, p| p["execution_context_id"] == execution_context_id }
|
100
|
-
frame["execution_context_id"] = nil if frame
|
101
|
-
|
102
|
-
if @execution_context_id == execution_context_id
|
103
|
-
@execution_context_id = nil
|
104
|
-
end
|
105
|
-
end
|
106
|
-
|
107
|
-
@client.subscribe("Runtime.executionContextsCleared") do
|
108
|
-
# If we didn't have time to set context id at the beginning we have
|
109
|
-
# to set lock and release it when we set something.
|
110
|
-
@execution_context_id = nil
|
111
|
-
end
|
112
|
-
end
|
113
|
-
end
|
114
|
-
end
|
115
|
-
end
|