webkit_remote 0.3.2 → 0.4.0
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.
- data/.travis.yml +0 -2
- data/Gemfile +1 -0
- data/Gemfile.lock +10 -1
- data/README.md +36 -1
- data/VERSION +1 -1
- data/lib/webkit_remote.rb +2 -0
- data/lib/webkit_remote/client/console.rb +131 -0
- data/lib/webkit_remote/client/console_events.rb +24 -95
- data/lib/webkit_remote/client/dom.rb +297 -0
- data/lib/webkit_remote/client/dom_events.rb +18 -0
- data/lib/webkit_remote/client/network_events.rb +2 -2
- data/lib/webkit_remote/client/runtime.rb +66 -47
- data/lib/webkit_remote/process.rb +124 -6
- data/lib/webkit_remote/top_level.rb +5 -0
- data/test/fixtures/html/console.html +4 -0
- data/test/fixtures/html/dom.html +23 -0
- data/test/helper.rb +1 -0
- data/test/webkit_remote/browser_test.rb +1 -1
- data/test/webkit_remote/client/console_test.rb +63 -6
- data/test/webkit_remote/client/dom_test.rb +149 -0
- data/test/webkit_remote/client/{remote_object_group_test.rb → js_object_group_test.rb} +1 -1
- data/test/webkit_remote/client/{remote_object_test.rb → js_object_test.rb} +28 -21
- data/test/webkit_remote/client/runtime_test.rb +6 -6
- data/test/webkit_remote/client_test.rb +1 -1
- data/test/webkit_remote/process_test.rb +82 -30
- data/test/webkit_remote/rpc_test.rb +1 -1
- data/test/webkit_remote_test.rb +2 -2
- data/webkit_remote.gemspec +11 -4
- metadata +25 -5
@@ -0,0 +1,297 @@
|
|
1
|
+
module WebkitRemote
|
2
|
+
|
3
|
+
class Client
|
4
|
+
|
5
|
+
# API for the DOM domain.
|
6
|
+
module Dom
|
7
|
+
# @return [WebkitRemote::Client::DomNode] the root DOM node
|
8
|
+
def dom_root
|
9
|
+
@dom_root ||= dom_root!
|
10
|
+
end
|
11
|
+
|
12
|
+
# Obtains the root DOM node, bypassing the cache.
|
13
|
+
#
|
14
|
+
# @return [WebkitRemote::Client::DomNode] the root DOM node
|
15
|
+
def dom_root!
|
16
|
+
result = @rpc.call 'DOM.getDocument'
|
17
|
+
@dom_root = dom_update_node result['root']
|
18
|
+
end
|
19
|
+
|
20
|
+
# Removes all the cached DOM information.
|
21
|
+
#
|
22
|
+
# @return [WebkitRemote::Client] self
|
23
|
+
def clear_dom
|
24
|
+
@dom_root = nil
|
25
|
+
@dom_nodes.clear
|
26
|
+
self
|
27
|
+
end
|
28
|
+
|
29
|
+
# Looks up cached information about a DOM node.
|
30
|
+
#
|
31
|
+
# @private Use WebkitRemote::Client::Dom#querySelector or the other public
|
32
|
+
# APIs instead of calling this directly
|
33
|
+
#
|
34
|
+
# @param [String] remote_id value of the nodeId attribute in the JSON
|
35
|
+
# returned by a Webkit remote debugging server
|
36
|
+
# @return [WebkitRemote::Client::DomNode] cached information about the given
|
37
|
+
# DOM node
|
38
|
+
def dom_node(remote_id)
|
39
|
+
@dom_nodes[remote_id] ||= WebkitRemote::Client::DomNode.new remote_id, self
|
40
|
+
end
|
41
|
+
|
42
|
+
# @private Called by the Client constructor to set up Dom data.
|
43
|
+
def initialize_dom
|
44
|
+
@dom_nodes = {}
|
45
|
+
end
|
46
|
+
|
47
|
+
# Updates cached information about a DOM node.
|
48
|
+
#
|
49
|
+
# @param [Hash<String, Object>] raw_node a Node data structure in the DOM
|
50
|
+
# domain, as returned by a raw JSON RPC call to a Webkit remote debugging
|
51
|
+
# server
|
52
|
+
# @return [WebkitRemote::Client::DomNode] the updated cached information
|
53
|
+
def dom_update_node(raw_node)
|
54
|
+
remote_id = raw_node['nodeId']
|
55
|
+
dom_node(remote_id).update_all raw_node
|
56
|
+
end
|
57
|
+
end # module WebkitRemote::Client::Dom
|
58
|
+
|
59
|
+
initializer :initialize_dom
|
60
|
+
clearer :clear_dom
|
61
|
+
include WebkitRemote::Client::Dom
|
62
|
+
|
63
|
+
# Cached information about a DOM node.
|
64
|
+
class DomNode
|
65
|
+
# @return [Array<WebkitRemote::Client::DomNode>] children nodes
|
66
|
+
attr_reader :children
|
67
|
+
|
68
|
+
# @return [String] the node's local name
|
69
|
+
attr_reader :local_name
|
70
|
+
# @return [String] the node's name
|
71
|
+
attr_reader :name
|
72
|
+
# @return [String] the node's value
|
73
|
+
attr_reader :value
|
74
|
+
# @return [Symbol] the DOM node type (such as :element, :text, :attribute)
|
75
|
+
attr_reader :node_type
|
76
|
+
|
77
|
+
# @return [String] name, for attribute nodes
|
78
|
+
attr_reader :attr_name
|
79
|
+
# @return [String] value, for attribute nodes
|
80
|
+
attr_reader :attr_value
|
81
|
+
|
82
|
+
# @return [String] internal subset, for doctype nodes
|
83
|
+
attr_reader :internal_subset
|
84
|
+
# @return [String] public ID, for doctype nodes
|
85
|
+
attr_reader :public_id
|
86
|
+
# @return [String] system ID, for doctype nodes
|
87
|
+
attr_reader :system_id
|
88
|
+
|
89
|
+
# @return [WebkitRemote::Client::DomNode] content document, for frameowner
|
90
|
+
# nodes
|
91
|
+
# @return [String] the document URL, for document and frameowner nodes
|
92
|
+
attr_reader :document_url
|
93
|
+
# @return [String] the XML version, for document nodes
|
94
|
+
attr_reader :xml_version
|
95
|
+
|
96
|
+
# @return [Hash<String, Object>] the node's attributes
|
97
|
+
def attributes
|
98
|
+
@attributes ||= attributes!
|
99
|
+
end
|
100
|
+
|
101
|
+
# Retrieves this node's attributes, bypassing its cache.
|
102
|
+
#
|
103
|
+
# @return [Hash<String, Object>] the node's attributes
|
104
|
+
def attributes!
|
105
|
+
result = @client.rpc.call 'DOM.getAttributes', nodeId: @remote_id
|
106
|
+
@attributes = Hash[result['attributes'].each_slice(2).to_a]
|
107
|
+
end
|
108
|
+
|
109
|
+
# @return [WebkitRemote::Client::JsObject] this node's JavaScript object
|
110
|
+
def js_object
|
111
|
+
@js_object ||= js_object!
|
112
|
+
end
|
113
|
+
|
114
|
+
# Retrieves this node's JavaScript object, bypassing the node's cache.
|
115
|
+
#
|
116
|
+
# @param [String] group the name of an object group (think memory pools); the
|
117
|
+
# objects in a group can be released together by one call to
|
118
|
+
# WebkitRemote::Client::JsObjectGroup#release
|
119
|
+
# @return [WebkitRemote::Client::JsObject] this node's JavaScript object
|
120
|
+
def js_object!(group = nil)
|
121
|
+
group ||= @client.object_group_auto_name
|
122
|
+
result = @client.rpc.call 'DOM.resolveNode', nodeId: @remote_id,
|
123
|
+
groupName: group
|
124
|
+
WebkitRemote::Client::JsObject.for result['object'], @client, group
|
125
|
+
end
|
126
|
+
|
127
|
+
# @return [String] HTML markup for the node and all its contents
|
128
|
+
def outer_html
|
129
|
+
@outer_html ||= outer_html!
|
130
|
+
end
|
131
|
+
|
132
|
+
# @return [String] HTML markup for the node and all its contents
|
133
|
+
def outer_html!
|
134
|
+
result = @client.rpc.call 'DOM.getOuterHTML', nodeId: @remote_id
|
135
|
+
@outer_html = result['outerHTML']
|
136
|
+
end
|
137
|
+
|
138
|
+
# Retrieves the first descendant of this node that matches a CSS selector.
|
139
|
+
#
|
140
|
+
# @param [String] css_selector the CSS selector that must be matched by the
|
141
|
+
# returned node
|
142
|
+
# @return [WebkitRemote::Client::DomNode] DOM nodes in this node's subtree
|
143
|
+
# that match the given selector
|
144
|
+
def query_selector(css_selector)
|
145
|
+
result = @client.rpc.call 'DOM.querySelector', nodeId: @remote_id,
|
146
|
+
selector: css_selector
|
147
|
+
@client.dom_node result['nodeId']
|
148
|
+
end
|
149
|
+
|
150
|
+
# Retrieves all this node's descendants that match a CSS selector.
|
151
|
+
#
|
152
|
+
# @param [String] css_selector the CSS selector used to filter this node's
|
153
|
+
# subtree
|
154
|
+
# @return [Array<WebkitRemote::Client::DomNode>] DOM nodes in this node's
|
155
|
+
# subtree that match the given selector
|
156
|
+
def query_selector_all(css_selector)
|
157
|
+
result = @client.rpc.call 'DOM.querySelectorAll', nodeId: @remote_id,
|
158
|
+
selector: css_selector
|
159
|
+
result['nodeIds'].map { |remote_id| @client.dom_node remote_id }
|
160
|
+
end
|
161
|
+
|
162
|
+
# Deletes one of the node (element)'s attributes.
|
163
|
+
#
|
164
|
+
# @param [String] attr_name name of the attribute that will be deleted
|
165
|
+
# @return [WebkitRemote::Client::DomNode] self
|
166
|
+
def remove_attribute(attr_name)
|
167
|
+
@attributes.delete attr_name if @attributes
|
168
|
+
@client.rpc.call 'DOM.removeAttribute', nodeId: @remote_id, name: attr_name
|
169
|
+
self
|
170
|
+
end
|
171
|
+
|
172
|
+
# Removes this node from the document.
|
173
|
+
#
|
174
|
+
# @return [WebkitRemote::Client::DomNode] self
|
175
|
+
def remove
|
176
|
+
@client.rpc.call 'DOM.removeNode', nodeId: @remote_id
|
177
|
+
self
|
178
|
+
end
|
179
|
+
|
180
|
+
# Highlights this DOM node.
|
181
|
+
#
|
182
|
+
# @param [Hash<Symbol, Hash>] options colors to be used for highlighting
|
183
|
+
# @option options [Hash<Symbol, Number>] margin color used for highlighting
|
184
|
+
# the element's border
|
185
|
+
# @option options [Hash<Symbol, Number>] border color used for highlighting
|
186
|
+
# the element's border
|
187
|
+
# @option options [Hash<Symbol, Number>] padding color used for highlighting
|
188
|
+
# the element's padding
|
189
|
+
# @option options [Hash<Symbol, Number>] content color used for highlighting
|
190
|
+
# the element's content
|
191
|
+
# @option options [Boolean] tooltip if true, a tooltip containing node
|
192
|
+
# information is also shown
|
193
|
+
def highlight!(options)
|
194
|
+
config = {}
|
195
|
+
config[:marginColor] = options[:margin] if options[:margin]
|
196
|
+
config[:borderColor] = options[:border] if options[:border]
|
197
|
+
config[:paddingColor] = options[:padding] if options[:padding]
|
198
|
+
config[:contentColor] = options[:content] if options[:content]
|
199
|
+
config[:showInfo] = true if options[:tooltip]
|
200
|
+
@client.rpc.call 'DOM.highlightNode', nodeId: @remote_id,
|
201
|
+
highlightConfig: config
|
202
|
+
end
|
203
|
+
|
204
|
+
# @private Use WebkitRemote::Client::Dom#dom_node instead of calling this
|
205
|
+
def initialize(remote_id, client)
|
206
|
+
@remote_id = remote_id
|
207
|
+
@client = client
|
208
|
+
|
209
|
+
@attributes = nil
|
210
|
+
@attr_name = nil
|
211
|
+
@attr_value = nil
|
212
|
+
@children = nil
|
213
|
+
@content_document = nil
|
214
|
+
@document_url = nil
|
215
|
+
@internal_subset = nil
|
216
|
+
@js_object = nil
|
217
|
+
@local_name = nil
|
218
|
+
@name = nil
|
219
|
+
@node_type = nil
|
220
|
+
@outer_html = nil
|
221
|
+
@public_id = nil
|
222
|
+
@system_id = nil
|
223
|
+
@value = nil
|
224
|
+
@xml_version = nil
|
225
|
+
end
|
226
|
+
|
227
|
+
# Updates node state to reflect new data from the Webkit debugging server.
|
228
|
+
#
|
229
|
+
# @private Use WebkitRemote::Client::Dom#dom_node instead of calling this
|
230
|
+
#
|
231
|
+
# @param [Hash<String, Object>] raw_node a Node data structure in the DOM
|
232
|
+
# domain, as returned by a raw JSON RPC call to a Webkit remote debugging
|
233
|
+
# server
|
234
|
+
# @return [WebkitRemote::Client::DomNode] self
|
235
|
+
def update_all(raw_node)
|
236
|
+
if raw_node['attributes']
|
237
|
+
@attributes = Hash[raw_node['attributes'].each_slice(2).to_a]
|
238
|
+
end
|
239
|
+
if raw_node['children']
|
240
|
+
@children = raw_node['children'].map do |child_node|
|
241
|
+
@client.dom_update_node child_node
|
242
|
+
end
|
243
|
+
end
|
244
|
+
if raw_node['contentDocument']
|
245
|
+
@content_document = @client.dom_update_node raw_node['contentDocument']
|
246
|
+
end
|
247
|
+
@document_url = raw_node['documentURL'] if raw_node['documentURL']
|
248
|
+
@internal_subset = raw_node['internalSubset'] if raw_node['internalSubset']
|
249
|
+
@node_local_name = raw_node['localName'] if raw_node['localName']
|
250
|
+
@attr_name = raw_node['name'] if raw_node['name']
|
251
|
+
@name = raw_node['nodeName'] if raw_node['nodeName']
|
252
|
+
if raw_node['nodeType']
|
253
|
+
@node_type = NODE_TYPES[raw_node['nodeType'].to_i] || raw_node['nodeType']
|
254
|
+
end
|
255
|
+
@value = raw_node['nodeValue'] if raw_node['nodeValue']
|
256
|
+
@public_id = raw_node['publicId'] if raw_node['publicId']
|
257
|
+
@system_id = raw_node['systemId'] if raw_node['systemId']
|
258
|
+
@attr_value = raw_node['value'] if raw_node['value']
|
259
|
+
@xml_version = raw_node['xmlVersion'] if raw_node['xmlVersion']
|
260
|
+
|
261
|
+
self
|
262
|
+
end
|
263
|
+
|
264
|
+
# Maps numeric DOM types to their symbolic representation.
|
265
|
+
NODE_TYPES = {
|
266
|
+
1 => :element, 2 => :attribute, 3 => :text, 4 => :cdata_section,
|
267
|
+
5 => :entity_reference, 6 => :entity, 7 => :processing_instruction,
|
268
|
+
8 => :comment, 9 => :document, 10 => :document_type,
|
269
|
+
11 => :document_fragment, 12 => :notation
|
270
|
+
}.freeze
|
271
|
+
end # class WebkitRemote::Client::DomNode
|
272
|
+
|
273
|
+
class JsObject
|
274
|
+
# @return [WebkitRemote::Client::DomNode] the DOM node wrapped by this
|
275
|
+
# JavaScript object
|
276
|
+
def dom_node
|
277
|
+
@dom_node ||= dom_node!
|
278
|
+
end
|
279
|
+
|
280
|
+
# Fetches the wrapped DOM node, bypassing the object's cache.
|
281
|
+
#
|
282
|
+
# @return [WebkitRemote::Client::DomNode] the DOM domain object wrapped by
|
283
|
+
# this JavaScript object
|
284
|
+
def dom_node!
|
285
|
+
result = @client.rpc.call 'DOM.requestNode', objectId: @remote_id
|
286
|
+
@dom_node = if result['nodeId']
|
287
|
+
@client.dom_node result['nodeId']
|
288
|
+
else
|
289
|
+
nil
|
290
|
+
end
|
291
|
+
end
|
292
|
+
end # class WebkitRemote::Client::JsObject
|
293
|
+
|
294
|
+
end # namespace WebkitRemote::Client
|
295
|
+
|
296
|
+
end # namespace WebkitRemote
|
297
|
+
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module WebkitRemote
|
2
|
+
|
3
|
+
class Event
|
4
|
+
|
5
|
+
# Emitted when the entire document has changed, and all DOM structure is lost.
|
6
|
+
class DomReset < WebkitRemote::Event
|
7
|
+
register 'Dom.documentUpdated'
|
8
|
+
|
9
|
+
# @private Use Event#for instead of calling this constructor directly.
|
10
|
+
def initialize(rpc_event, client)
|
11
|
+
super
|
12
|
+
client.clear_dom
|
13
|
+
end
|
14
|
+
end # class WebkitRemote::Event::DomReset
|
15
|
+
|
16
|
+
end # namespace WebkitRemote::Event
|
17
|
+
|
18
|
+
end # namepspace WebkitRemote
|
@@ -200,7 +200,7 @@ class NetworkRequest < WebkitRemote::Event
|
|
200
200
|
raw_data['redirectResponse'])
|
201
201
|
end
|
202
202
|
if raw_data['stackTrace']
|
203
|
-
@stack_trace = WebkitRemote::
|
203
|
+
@stack_trace = WebkitRemote::Client::ConsoleMessage.parse_stack_trace(
|
204
204
|
raw_initiator['stackTrace'])
|
205
205
|
else
|
206
206
|
@stack_trace = nil
|
@@ -568,7 +568,7 @@ class NetworkRequestInitiator
|
|
568
568
|
else
|
569
569
|
@line = nil
|
570
570
|
end
|
571
|
-
@stack_trace = WebkitRemote::
|
571
|
+
@stack_trace = WebkitRemote::Client::ConsoleMessage.parse_stack_trace(
|
572
572
|
raw_initiator['stackTrace'])
|
573
573
|
@type = (raw_initiator['type'] || 'other').to_sym
|
574
574
|
@url = raw_initiator['url']
|
@@ -10,15 +10,15 @@ module Runtime
|
|
10
10
|
# @param [Hash] opts tweaks
|
11
11
|
# @option opts [String, Symbol] group the name of an object group (think
|
12
12
|
# memory pools); the objects in a group can be released together by one
|
13
|
-
# call to WebkitRemote::Client::
|
14
|
-
# @return [WebkitRemote::Client::
|
13
|
+
# call to WebkitRemote::Client::JsObjectGroup#release
|
14
|
+
# @return [WebkitRemote::Client::JsObject, Boolean, Number, String] the
|
15
15
|
# result of evaluating the expression
|
16
16
|
def remote_eval(expression, opts = {})
|
17
|
-
group_name = opts[:group] ||
|
17
|
+
group_name = opts[:group] || object_group_auto_name
|
18
18
|
# NOTE: returnByValue is always set to false to avoid some extra complexity
|
19
19
|
result = @rpc.call 'Runtime.evaluate', expression: expression,
|
20
20
|
objectGroup: group_name
|
21
|
-
object = WebkitRemote::Client::
|
21
|
+
object = WebkitRemote::Client::JsObject.for result['result'], self,
|
22
22
|
group_name
|
23
23
|
if result['wasThrown']
|
24
24
|
# TODO(pwnall): some wrapper for exceptions?
|
@@ -35,9 +35,9 @@ module Runtime
|
|
35
35
|
# un-grouped objects created by Console#MessageReceived
|
36
36
|
# @param [Boolean] create if true, fetching a group that does not exist will
|
37
37
|
# create the group; this parameter should only be used internally
|
38
|
-
# @return [WebkitRemote::Client::
|
38
|
+
# @return [WebkitRemote::Client::JsObject, Boolean, Number, String, nil]
|
39
39
|
# a Ruby wrapper for the evaluation result; primitives get wrapped by
|
40
|
-
# standard Ruby classes, and objects get wrapped by
|
40
|
+
# standard Ruby classes, and objects get wrapped by JsObject
|
41
41
|
# instances
|
42
42
|
def object_group(group_name, create = false)
|
43
43
|
group_name = group_name.nil? ? nil : group_name.to_s
|
@@ -45,15 +45,24 @@ module Runtime
|
|
45
45
|
return group if group
|
46
46
|
if create
|
47
47
|
@runtime_groups[group_name] =
|
48
|
-
WebkitRemote::Client::
|
48
|
+
WebkitRemote::Client::JsObjectGroup.new(group_name, self)
|
49
49
|
else
|
50
50
|
nil
|
51
51
|
end
|
52
52
|
end
|
53
53
|
|
54
|
+
# Generates a temporary group name for JavaScript objects.
|
55
|
+
#
|
56
|
+
# This is useful when the API user does not
|
57
|
+
#
|
58
|
+
# @return [String] an automatically-generated JS object name
|
59
|
+
def object_group_auto_name
|
60
|
+
'_'
|
61
|
+
end
|
62
|
+
|
54
63
|
# Removes a group from the list of tracked groups.
|
55
64
|
#
|
56
|
-
# @private Use WebkitRemote::Client::
|
65
|
+
# @private Use WebkitRemote::Client::JsObjectGroup#release instead of
|
57
66
|
# calling this directly.
|
58
67
|
# @return [WebkitRemote::Client] self
|
59
68
|
def object_group_remove(group)
|
@@ -122,8 +131,8 @@ end # class WebkitRemote::Client::UndefinedClass
|
|
122
131
|
|
123
132
|
Undefined = UndefinedClass.new
|
124
133
|
|
125
|
-
# Mirrors a
|
126
|
-
class
|
134
|
+
# Mirrors a JsObject, defined in the Runtime domain.
|
135
|
+
class JsObject
|
127
136
|
# @return [String] the class name computed by WebKit for this object
|
128
137
|
attr_reader :js_class_name
|
129
138
|
|
@@ -154,18 +163,18 @@ class RemoteObject
|
|
154
163
|
# that owns the objects in this group
|
155
164
|
attr_reader :client
|
156
165
|
|
157
|
-
# @return [WebkitRemote::Client::
|
166
|
+
# @return [WebkitRemote::Client::JsObjectGroup] the group that contains
|
158
167
|
# this object; the object can be released by calling release_all on the
|
159
168
|
# group
|
160
169
|
attr_reader :group
|
161
170
|
|
162
171
|
# @return [String] identifies this object in the remote debugger
|
163
|
-
# @private Use the
|
172
|
+
# @private Use the JsObject methods instead of calling this directly.
|
164
173
|
attr_reader :remote_id
|
165
174
|
|
166
175
|
# Releases this remote object on the browser side.
|
167
176
|
#
|
168
|
-
# @return [Webkit::Client::
|
177
|
+
# @return [Webkit::Client::JsObject] self
|
169
178
|
def release
|
170
179
|
return if @released
|
171
180
|
@client.rpc.call 'Runtime.releaseObject', objectId: @remote_id
|
@@ -178,7 +187,7 @@ class RemoteObject
|
|
178
187
|
# If the object's properties have not been retrieved, this method retrieves
|
179
188
|
# them via a RPC call.
|
180
189
|
#
|
181
|
-
# @return [Hash<
|
190
|
+
# @return [Hash<String, Webkit::Client::JsProperty>] frozen Hash containg
|
182
191
|
# the object's properties
|
183
192
|
def properties
|
184
193
|
@properties || properties!
|
@@ -188,13 +197,13 @@ class RemoteObject
|
|
188
197
|
#
|
189
198
|
# This method always reloads the object's properties via a RPC call.
|
190
199
|
#
|
191
|
-
# @return [Hash<Symbol, Webkit::Client::
|
200
|
+
# @return [Hash<Symbol, Webkit::Client::JsProperty>] frozen Hash containg
|
192
201
|
# the object's properties
|
193
202
|
def properties!
|
194
203
|
result = @client.rpc.call 'Runtime.getProperties', objectId: @remote_id
|
195
204
|
@properties = Hash[
|
196
205
|
result['result'].map do |raw_property|
|
197
|
-
property = WebkitRemote::Client::
|
206
|
+
property = WebkitRemote::Client::JsProperty.new raw_property, self
|
198
207
|
[property.name, property]
|
199
208
|
end
|
200
209
|
].freeze
|
@@ -206,13 +215,13 @@ class RemoteObject
|
|
206
215
|
# evaluate to a function
|
207
216
|
# @param [Array<WebkitRemote::Client::Object, String, Number, Boolean, nil>]
|
208
217
|
# args the arguments passed to the function
|
209
|
-
# @return [WebkitRemote::Client::
|
218
|
+
# @return [WebkitRemote::Client::JsObject, Boolean, Number, String, nil]
|
210
219
|
# a Ruby wrapper for the given raw object; primitives get wrapped by
|
211
|
-
# standard Ruby classes, and objects get wrapped by
|
220
|
+
# standard Ruby classes, and objects get wrapped by JsObject
|
212
221
|
# instances
|
213
222
|
def bound_call(function_expression, *args)
|
214
223
|
call_args = args.map do |arg|
|
215
|
-
if arg.kind_of? WebkitRemote::Client::
|
224
|
+
if arg.kind_of? WebkitRemote::Client::JsObject
|
216
225
|
{ objectId: arg.remote_id }
|
217
226
|
else
|
218
227
|
{ value: arg }
|
@@ -221,7 +230,7 @@ class RemoteObject
|
|
221
230
|
result = @client.rpc.call 'Runtime.callFunctionOn', objectId: @remote_id,
|
222
231
|
functionDeclaration: function_expression, arguments: call_args,
|
223
232
|
returnByValue: false
|
224
|
-
object = WebkitRemote::Client::
|
233
|
+
object = WebkitRemote::Client::JsObject.for result['result'], @client,
|
225
234
|
@group.name
|
226
235
|
if result['wasThrown']
|
227
236
|
# TODO(pwnall): some wrapper for exceptions?
|
@@ -236,22 +245,22 @@ class RemoteObject
|
|
236
245
|
# @private Use WebkitRemote::Client::Runtime#remote_eval instead of calling
|
237
246
|
# this directly.
|
238
247
|
#
|
239
|
-
# @param [Hash<String, Object>] raw_object a
|
248
|
+
# @param [Hash<String, Object>] raw_object a JsObject instance, according
|
240
249
|
# to the Webkit remote debugging protocol; this is the return value of a
|
241
250
|
# 'Runtime.evaluate' RPC call
|
242
251
|
# @param [WebkitRemote::Client::Runtime] client remote debugging client for
|
243
252
|
# the browser tab that owns this object
|
244
253
|
# @param [String] group_name name of the object group that will hold this
|
245
254
|
# object; object groups work like memory pools
|
246
|
-
# @return [WebkitRemote::Client::
|
255
|
+
# @return [WebkitRemote::Client::JsObject, Boolean, Number, String] a
|
247
256
|
# Ruby wrapper for the given raw object; primitives get wrapped by
|
248
|
-
# standard Ruby classes, and objects get wrapped by
|
257
|
+
# standard Ruby classes, and objects get wrapped by JsObject
|
249
258
|
# instances
|
250
259
|
def self.for(raw_object, client, group_name)
|
251
260
|
if remote_id = raw_object['objectId']
|
252
261
|
group = client.object_group group_name, true
|
253
262
|
return group.get(remote_id) ||
|
254
|
-
WebkitRemote::Client::
|
263
|
+
WebkitRemote::Client::JsObject.new(raw_object, group)
|
255
264
|
else
|
256
265
|
# primitive types
|
257
266
|
case raw_object['type'] ? raw_object['type'].to_sym : nil
|
@@ -272,7 +281,7 @@ class RemoteObject
|
|
272
281
|
|
273
282
|
# Wraps a remote JavaScript object
|
274
283
|
#
|
275
|
-
# @private
|
284
|
+
# @private JsObject#for should be used instead of this, as it handles
|
276
285
|
# some edge cases
|
277
286
|
def initialize(raw_object, group)
|
278
287
|
@group = group
|
@@ -290,21 +299,22 @@ class RemoteObject
|
|
290
299
|
@js_subtype = nil
|
291
300
|
end
|
292
301
|
@value = raw_object['value']
|
302
|
+
@dom_node = nil
|
293
303
|
|
294
304
|
group.add self
|
295
305
|
end
|
296
306
|
|
297
307
|
# Informs this object that it was released as part of a group release.
|
298
308
|
#
|
299
|
-
# @private Called by
|
309
|
+
# @private Called by JsObjectGroup#release_all.
|
300
310
|
def released!
|
301
311
|
@released = true
|
302
312
|
@group = nil
|
303
313
|
end
|
304
|
-
end # class WebkitRemote::Client::
|
314
|
+
end # class WebkitRemote::Client::JsObject
|
305
315
|
|
306
316
|
# Tracks the remote objects in a group (think memory pool).
|
307
|
-
class
|
317
|
+
class JsObjectGroup
|
308
318
|
# @return [String] the name of the group of remote objects
|
309
319
|
attr_reader :name
|
310
320
|
|
@@ -318,7 +328,7 @@ class RemoteObjectGroup
|
|
318
328
|
|
319
329
|
# Releases all the remote objects in this group.
|
320
330
|
#
|
321
|
-
# @return [Webkit::Client::
|
331
|
+
# @return [Webkit::Client::JsObjectGroup] self
|
322
332
|
def release_all
|
323
333
|
return if @objects.empty?
|
324
334
|
|
@@ -368,9 +378,9 @@ class RemoteObjectGroup
|
|
368
378
|
# @private Use WebkitRemote::Client::Runtime#remote_eval instead of calling
|
369
379
|
# this directly.
|
370
380
|
#
|
371
|
-
# @param [WebkitRemote::Client::
|
381
|
+
# @param [WebkitRemote::Client::JsObject] object the object to be added
|
372
382
|
# to this group
|
373
|
-
# @return [WebkitRemote::Client::
|
383
|
+
# @return [WebkitRemote::Client::JsObjectGroup] self
|
374
384
|
def add(object)
|
375
385
|
if @released
|
376
386
|
raise RuntimeError, 'Remote object group already released'
|
@@ -381,12 +391,12 @@ class RemoteObjectGroup
|
|
381
391
|
|
382
392
|
# Removes a remote object that was individually released.
|
383
393
|
#
|
384
|
-
# @private Use WebkitRemote::Client::
|
394
|
+
# @private Use WebkitRemote::Client::JsObject#release instead of calling
|
385
395
|
# this directly
|
386
396
|
#
|
387
|
-
# @param [WebkitRemote::Client::
|
397
|
+
# @param [WebkitRemote::Client::JsObject] object the object that will be
|
388
398
|
# removed from the group
|
389
|
-
# @return [WebkitRemote::Client::
|
399
|
+
# @return [WebkitRemote::Client::JsObjectGroup] self
|
390
400
|
def remove(object)
|
391
401
|
@objects.delete object.remote_id
|
392
402
|
if @objects.empty?
|
@@ -401,21 +411,21 @@ class RemoteObjectGroup
|
|
401
411
|
# This helps avoid creating multiple wrappers for the same object.
|
402
412
|
#
|
403
413
|
# @param [String] remote_id the id to look for
|
404
|
-
# @return [WebkitRemote::Client::
|
414
|
+
# @return [WebkitRemote::Client::JsObject, nil] nil if there is no object
|
405
415
|
# whose remote_id matches the method's parameter
|
406
416
|
def get(remote_id)
|
407
417
|
@objects.fetch remote_id, nil
|
408
418
|
end
|
409
|
-
end # class WebkitRemote::Client::
|
419
|
+
end # class WebkitRemote::Client::JsObjectGroup
|
410
420
|
|
411
421
|
# A property of a remote JavaScript object.
|
412
|
-
class
|
413
|
-
# @return [
|
422
|
+
class JsProperty
|
423
|
+
# @return [String] the property's name
|
414
424
|
attr_reader :name
|
415
425
|
|
416
|
-
# @return [WebkitRemote::Client::
|
426
|
+
# @return [WebkitRemote::Client::JsObject, Boolean, Number, String, nil]
|
417
427
|
# a Ruby wrapper for the property's value; primitives get wrapped by
|
418
|
-
# standard Ruby classes, and objects get wrapped by
|
428
|
+
# standard Ruby classes, and objects get wrapped by JsObject
|
419
429
|
# instances
|
420
430
|
attr_reader :value
|
421
431
|
|
@@ -431,14 +441,14 @@ class RemoteProperty
|
|
431
441
|
attr_reader :writable
|
432
442
|
alias_method :writable?, :writable
|
433
443
|
|
434
|
-
# @return [WebkitRemote::
|
444
|
+
# @return [WebkitRemote::JsObject] the object that this property belongs
|
435
445
|
# to
|
436
446
|
attr_reader :owner
|
437
447
|
|
438
448
|
# @param [Hash<String, Object>] raw_property a PropertyDescriptor instance,
|
439
449
|
# according to the Webkit remote debugging protocol; this is an item in
|
440
450
|
# the array returned by the 'Runtime.getProperties' RPC call
|
441
|
-
# @param [WebkitRemote::Client::
|
451
|
+
# @param [WebkitRemote::Client::JsObject] owner the object that this
|
442
452
|
# property belongs to
|
443
453
|
def initialize(raw_property, owner)
|
444
454
|
# NOTE: these are only used at construction time
|
@@ -446,18 +456,27 @@ class RemoteProperty
|
|
446
456
|
group_name = owner.group.name
|
447
457
|
|
448
458
|
@owner = owner
|
449
|
-
@name = raw_property['name']
|
459
|
+
@name = raw_property['name']
|
450
460
|
@configurable = !!raw_property['configurable']
|
451
461
|
@enumerable = !!raw_property['enumerable']
|
452
462
|
@writable = !!raw_property['writable']
|
453
|
-
@js_getter = raw_property['get'] && WebkitRemote::Client::
|
463
|
+
@js_getter = raw_property['get'] && WebkitRemote::Client::JsObject.for(
|
454
464
|
raw_property['get'], client, group_name)
|
455
|
-
@js_setter = raw_property['set'] && WebkitRemote::Client::
|
465
|
+
@js_setter = raw_property['set'] && WebkitRemote::Client::JsObject.for(
|
456
466
|
raw_property['set'], client, group_name)
|
457
|
-
@value = raw_property['value'] && WebkitRemote::Client::
|
467
|
+
@value = raw_property['value'] && WebkitRemote::Client::JsObject.for(
|
458
468
|
raw_property['value'], client, group_name)
|
459
469
|
end
|
460
|
-
|
470
|
+
|
471
|
+
# Debugging output.
|
472
|
+
def inspect
|
473
|
+
result = self.to_s
|
474
|
+
result[-1, 0] =
|
475
|
+
" name=#{@name.inspect} configurable=#{@configurable} " +
|
476
|
+
"enumerable=#{@enumerable} writable=#{@writable}"
|
477
|
+
result
|
478
|
+
end
|
479
|
+
end # class WebkitRemote::Client::JsProperty
|
461
480
|
|
462
481
|
end # namespace WebkitRemote::Client
|
463
482
|
|